| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_wg.c,v 1.42 2020/08/31 20:26:21 riastradh Exp $ */ | | 1 | /* $NetBSD: if_wg.c,v 1.43 2020/08/31 20:26:46 riastradh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (C) Ryota Ozaki <ozaki.ryota@gmail.com> | | 4 | * Copyright (C) Ryota Ozaki <ozaki.ryota@gmail.com> |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -31,27 +31,27 @@ | | | @@ -31,27 +31,27 @@ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * This network interface aims to implement the WireGuard protocol. | | 33 | * This network interface aims to implement the WireGuard protocol. |
34 | * The implementation is based on the paper of WireGuard as of | | 34 | * The implementation is based on the paper of WireGuard as of |
35 | * 2018-06-30 [1]. The paper is referred in the source code with label | | 35 | * 2018-06-30 [1]. The paper is referred in the source code with label |
36 | * [W]. Also the specification of the Noise protocol framework as of | | 36 | * [W]. Also the specification of the Noise protocol framework as of |
37 | * 2018-07-11 [2] is referred with label [N]. | | 37 | * 2018-07-11 [2] is referred with label [N]. |
38 | * | | 38 | * |
39 | * [1] https://www.wireguard.com/papers/wireguard.pdf | | 39 | * [1] https://www.wireguard.com/papers/wireguard.pdf |
40 | * [2] http://noiseprotocol.org/noise.pdf | | 40 | * [2] http://noiseprotocol.org/noise.pdf |
41 | */ | | 41 | */ |
42 | | | 42 | |
43 | #include <sys/cdefs.h> | | 43 | #include <sys/cdefs.h> |
44 | __KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.42 2020/08/31 20:26:21 riastradh Exp $"); | | 44 | __KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.43 2020/08/31 20:26:46 riastradh Exp $"); |
45 | | | 45 | |
46 | #ifdef _KERNEL_OPT | | 46 | #ifdef _KERNEL_OPT |
47 | #include "opt_inet.h" | | 47 | #include "opt_inet.h" |
48 | #endif | | 48 | #endif |
49 | | | 49 | |
50 | #include <sys/param.h> | | 50 | #include <sys/param.h> |
51 | #include <sys/types.h> | | 51 | #include <sys/types.h> |
52 | | | 52 | |
53 | #include <sys/atomic.h> | | 53 | #include <sys/atomic.h> |
54 | #include <sys/callout.h> | | 54 | #include <sys/callout.h> |
55 | #include <sys/cprng.h> | | 55 | #include <sys/cprng.h> |
56 | #include <sys/cpu.h> | | 56 | #include <sys/cpu.h> |
57 | #include <sys/device.h> | | 57 | #include <sys/device.h> |
| @@ -1319,27 +1319,26 @@ wg_fill_msg_init(struct wg_softc *wg, st | | | @@ -1319,27 +1319,26 @@ wg_fill_msg_init(struct wg_softc *wg, st |
1319 | WG_DLOG("%s: sender=%x\n", __func__, wgs->wgs_sender_index); | | 1319 | WG_DLOG("%s: sender=%x\n", __func__, wgs->wgs_sender_index); |
1320 | } | | 1320 | } |
1321 | | | 1321 | |
1322 | static void | | 1322 | static void |
1323 | wg_handle_msg_init(struct wg_softc *wg, const struct wg_msg_init *wgmi, | | 1323 | wg_handle_msg_init(struct wg_softc *wg, const struct wg_msg_init *wgmi, |
1324 | const struct sockaddr *src) | | 1324 | const struct sockaddr *src) |
1325 | { | | 1325 | { |
1326 | uint8_t ckey[WG_CHAINING_KEY_LEN]; /* [W] 5.4.2: Ci */ | | 1326 | uint8_t ckey[WG_CHAINING_KEY_LEN]; /* [W] 5.4.2: Ci */ |
1327 | uint8_t hash[WG_HASH_LEN]; /* [W] 5.4.2: Hi */ | | 1327 | uint8_t hash[WG_HASH_LEN]; /* [W] 5.4.2: Hi */ |
1328 | uint8_t cipher_key[WG_CIPHER_KEY_LEN]; | | 1328 | uint8_t cipher_key[WG_CIPHER_KEY_LEN]; |
1329 | uint8_t peer_pubkey[WG_STATIC_KEY_LEN]; | | 1329 | uint8_t peer_pubkey[WG_STATIC_KEY_LEN]; |
1330 | struct wg_peer *wgp; | | 1330 | struct wg_peer *wgp; |
1331 | struct wg_session *wgs; | | 1331 | struct wg_session *wgs; |
1332 | bool reset_state_on_error = false; | | | |
1333 | int error, ret; | | 1332 | int error, ret; |
1334 | struct psref psref_peer; | | 1333 | struct psref psref_peer; |
1335 | struct psref psref_session; | | 1334 | struct psref psref_session; |
1336 | uint8_t mac1[WG_MAC_LEN]; | | 1335 | uint8_t mac1[WG_MAC_LEN]; |
1337 | | | 1336 | |
1338 | WG_TRACE("init msg received"); | | 1337 | WG_TRACE("init msg received"); |
1339 | | | 1338 | |
1340 | /* | | 1339 | /* |
1341 | * [W] 5.4.2: First Message: Initiator to Responder | | 1340 | * [W] 5.4.2: First Message: Initiator to Responder |
1342 | * "When the responder receives this message, it does the same | | 1341 | * "When the responder receives this message, it does the same |
1343 | * operations so that its final state variables are identical, | | 1342 | * operations so that its final state variables are identical, |
1344 | * replacing the operands of the DH function to produce equivalent | | 1343 | * replacing the operands of the DH function to produce equivalent |
1345 | * values." | | 1344 | * values." |
| @@ -1399,27 +1398,26 @@ wg_handle_msg_init(struct wg_softc *wg, | | | @@ -1399,27 +1398,26 @@ wg_handle_msg_init(struct wg_softc *wg, |
1399 | wg_clear_states(wgs); | | 1398 | wg_clear_states(wgs); |
1400 | wgs->wgs_state = WGS_STATE_UNKNOWN; | | 1399 | wgs->wgs_state = WGS_STATE_UNKNOWN; |
1401 | } | | 1400 | } |
1402 | if (wgs->wgs_state == WGS_STATE_INIT_ACTIVE) { | | 1401 | if (wgs->wgs_state == WGS_STATE_INIT_ACTIVE) { |
1403 | WG_TRACE("Sesssion already initializing, ignoring the message"); | | 1402 | WG_TRACE("Sesssion already initializing, ignoring the message"); |
1404 | mutex_exit(wgs->wgs_lock); | | 1403 | mutex_exit(wgs->wgs_lock); |
1405 | goto out_wgp; | | 1404 | goto out_wgp; |
1406 | } | | 1405 | } |
1407 | if (wgs->wgs_state == WGS_STATE_INIT_PASSIVE) { | | 1406 | if (wgs->wgs_state == WGS_STATE_INIT_PASSIVE) { |
1408 | WG_TRACE("Sesssion already initializing, destroying old states"); | | 1407 | WG_TRACE("Sesssion already initializing, destroying old states"); |
1409 | wg_clear_states(wgs); | | 1408 | wg_clear_states(wgs); |
1410 | } | | 1409 | } |
1411 | wgs->wgs_state = WGS_STATE_INIT_PASSIVE; | | 1410 | wgs->wgs_state = WGS_STATE_INIT_PASSIVE; |
1412 | reset_state_on_error = true; | | | |
1413 | wg_get_session(wgs, &psref_session); | | 1411 | wg_get_session(wgs, &psref_session); |
1414 | mutex_exit(wgs->wgs_lock); | | 1412 | mutex_exit(wgs->wgs_lock); |
1415 | | | 1413 | |
1416 | wg_algo_mac_mac1(mac1, sizeof(mac1), | | 1414 | wg_algo_mac_mac1(mac1, sizeof(mac1), |
1417 | wg->wg_pubkey, sizeof(wg->wg_pubkey), | | 1415 | wg->wg_pubkey, sizeof(wg->wg_pubkey), |
1418 | (const uint8_t *)wgmi, offsetof(struct wg_msg_init, wgmi_mac1)); | | 1416 | (const uint8_t *)wgmi, offsetof(struct wg_msg_init, wgmi_mac1)); |
1419 | | | 1417 | |
1420 | /* | | 1418 | /* |
1421 | * [W] 5.3: Denial of Service Mitigation & Cookies | | 1419 | * [W] 5.3: Denial of Service Mitigation & Cookies |
1422 | * "the responder, ..., must always reject messages with an invalid | | 1420 | * "the responder, ..., must always reject messages with an invalid |
1423 | * msg.mac1" | | 1421 | * msg.mac1" |
1424 | */ | | 1422 | */ |
1425 | if (!consttime_memequal(mac1, wgmi->wgmi_mac1, sizeof(mac1))) { | | 1423 | if (!consttime_memequal(mac1, wgmi->wgmi_mac1, sizeof(mac1))) { |
| @@ -1499,32 +1497,30 @@ wg_handle_msg_init(struct wg_softc *wg, | | | @@ -1499,32 +1497,30 @@ wg_handle_msg_init(struct wg_softc *wg, |
1499 | | | 1497 | |
1500 | wg_update_endpoint_if_necessary(wgp, src); | | 1498 | wg_update_endpoint_if_necessary(wgp, src); |
1501 | | | 1499 | |
1502 | (void)wg_send_handshake_msg_resp(wg, wgp, wgmi); | | 1500 | (void)wg_send_handshake_msg_resp(wg, wgp, wgmi); |
1503 | | | 1501 | |
1504 | wg_calculate_keys(wgs, false); | | 1502 | wg_calculate_keys(wgs, false); |
1505 | wg_clear_states(wgs); | | 1503 | wg_clear_states(wgs); |
1506 | | | 1504 | |
1507 | wg_put_session(wgs, &psref_session); | | 1505 | wg_put_session(wgs, &psref_session); |
1508 | wg_put_peer(wgp, &psref_peer); | | 1506 | wg_put_peer(wgp, &psref_peer); |
1509 | return; | | 1507 | return; |
1510 | | | 1508 | |
1511 | out: | | 1509 | out: |
1512 | if (reset_state_on_error) { | | 1510 | mutex_enter(wgs->wgs_lock); |
1513 | mutex_enter(wgs->wgs_lock); | | 1511 | KASSERT(wgs->wgs_state == WGS_STATE_INIT_PASSIVE); |
1514 | KASSERT(wgs->wgs_state == WGS_STATE_INIT_PASSIVE); | | 1512 | wgs->wgs_state = WGS_STATE_UNKNOWN; |
1515 | wgs->wgs_state = WGS_STATE_UNKNOWN; | | 1513 | mutex_exit(wgs->wgs_lock); |
1516 | mutex_exit(wgs->wgs_lock); | | | |
1517 | } | | | |
1518 | wg_put_session(wgs, &psref_session); | | 1514 | wg_put_session(wgs, &psref_session); |
1519 | out_wgp: | | 1515 | out_wgp: |
1520 | wg_put_peer(wgp, &psref_peer); | | 1516 | wg_put_peer(wgp, &psref_peer); |
1521 | } | | 1517 | } |
1522 | | | 1518 | |
1523 | static void | | 1519 | static void |
1524 | wg_schedule_handshake_timeout_timer(struct wg_peer *wgp) | | 1520 | wg_schedule_handshake_timeout_timer(struct wg_peer *wgp) |
1525 | { | | 1521 | { |
1526 | | | 1522 | |
1527 | mutex_enter(wgp->wgp_lock); | | 1523 | mutex_enter(wgp->wgp_lock); |
1528 | if (__predict_true(wgp->wgp_state != WGP_STATE_DESTROYING)) { | | 1524 | if (__predict_true(wgp->wgp_state != WGP_STATE_DESTROYING)) { |
1529 | callout_schedule(&wgp->wgp_handshake_timeout_timer, | | 1525 | callout_schedule(&wgp->wgp_handshake_timeout_timer, |
1530 | MIN(wg_rekey_timeout, INT_MAX/hz) * hz); | | 1526 | MIN(wg_rekey_timeout, INT_MAX/hz) * hz); |