| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_wg.c,v 1.25 2020/08/27 02:52:33 riastradh Exp $ */ | | 1 | /* $NetBSD: if_wg.c,v 1.26 2020/08/27 02:53:47 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.25 2020/08/27 02:52:33 riastradh Exp $"); | | 44 | __KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.26 2020/08/27 02:53:47 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/systm.h> | | 51 | #include <sys/systm.h> |
52 | #include <sys/kernel.h> | | 52 | #include <sys/kernel.h> |
53 | #include <sys/mbuf.h> | | 53 | #include <sys/mbuf.h> |
54 | #include <sys/socket.h> | | 54 | #include <sys/socket.h> |
55 | #include <sys/sockio.h> | | 55 | #include <sys/sockio.h> |
56 | #include <sys/errno.h> | | 56 | #include <sys/errno.h> |
57 | #include <sys/ioctl.h> | | 57 | #include <sys/ioctl.h> |
| @@ -2333,31 +2333,27 @@ wg_handle_msg_data(struct wg_softc *wg, | | | @@ -2333,31 +2333,27 @@ wg_handle_msg_data(struct wg_softc *wg, |
2333 | const struct sockaddr *src) | | 2333 | const struct sockaddr *src) |
2334 | { | | 2334 | { |
2335 | struct wg_msg_data *wgmd; | | 2335 | struct wg_msg_data *wgmd; |
2336 | char *encrypted_buf = NULL, *decrypted_buf; | | 2336 | char *encrypted_buf = NULL, *decrypted_buf; |
2337 | size_t encrypted_len, decrypted_len; | | 2337 | size_t encrypted_len, decrypted_len; |
2338 | struct wg_session *wgs; | | 2338 | struct wg_session *wgs; |
2339 | struct wg_peer *wgp; | | 2339 | struct wg_peer *wgp; |
2340 | size_t mlen; | | 2340 | size_t mlen; |
2341 | struct psref psref; | | 2341 | struct psref psref; |
2342 | int error, af; | | 2342 | int error, af; |
2343 | bool success, free_encrypted_buf = false, ok; | | 2343 | bool success, free_encrypted_buf = false, ok; |
2344 | struct mbuf *n; | | 2344 | struct mbuf *n; |
2345 | | | 2345 | |
2346 | if (m->m_len < sizeof(struct wg_msg_data)) { | | 2346 | KASSERT(m->m_len >= sizeof(struct wg_msg_data)); |
2347 | m = m_pullup(m, sizeof(struct wg_msg_data)); | | | |
2348 | if (m == NULL) | | | |
2349 | return; | | | |
2350 | } | | | |
2351 | wgmd = mtod(m, struct wg_msg_data *); | | 2347 | wgmd = mtod(m, struct wg_msg_data *); |
2352 | | | 2348 | |
2353 | KASSERT(wgmd->wgmd_type == WG_MSG_TYPE_DATA); | | 2349 | KASSERT(wgmd->wgmd_type == WG_MSG_TYPE_DATA); |
2354 | WG_TRACE("data"); | | 2350 | WG_TRACE("data"); |
2355 | | | 2351 | |
2356 | wgs = wg_lookup_session_by_index(wg, wgmd->wgmd_receiver, &psref); | | 2352 | wgs = wg_lookup_session_by_index(wg, wgmd->wgmd_receiver, &psref); |
2357 | if (wgs == NULL) { | | 2353 | if (wgs == NULL) { |
2358 | WG_TRACE("No session found"); | | 2354 | WG_TRACE("No session found"); |
2359 | m_freem(m); | | 2355 | m_freem(m); |
2360 | return; | | 2356 | return; |
2361 | } | | 2357 | } |
2362 | wgp = wgs->wgs_peer; | | 2358 | wgp = wgs->wgs_peer; |
2363 | | | 2359 | |
| @@ -2563,93 +2559,112 @@ wg_handle_msg_cookie(struct wg_softc *wg | | | @@ -2563,93 +2559,112 @@ wg_handle_msg_cookie(struct wg_softc *wg |
2563 | } | | 2559 | } |
2564 | /* | | 2560 | /* |
2565 | * [W] 6.6: Interaction with Cookie Reply System | | 2561 | * [W] 6.6: Interaction with Cookie Reply System |
2566 | * "it should simply store the decrypted cookie value from the cookie | | 2562 | * "it should simply store the decrypted cookie value from the cookie |
2567 | * reply message, and wait for the expiration of the REKEY-TIMEOUT | | 2563 | * reply message, and wait for the expiration of the REKEY-TIMEOUT |
2568 | * timer for retrying a handshake initiation message." | | 2564 | * timer for retrying a handshake initiation message." |
2569 | */ | | 2565 | */ |
2570 | wgp->wgp_latest_cookie_time = time_uptime; | | 2566 | wgp->wgp_latest_cookie_time = time_uptime; |
2571 | memcpy(wgp->wgp_latest_cookie, cookie, sizeof(wgp->wgp_latest_cookie)); | | 2567 | memcpy(wgp->wgp_latest_cookie, cookie, sizeof(wgp->wgp_latest_cookie)); |
2572 | out: | | 2568 | out: |
2573 | wg_put_session(wgs, &psref); | | 2569 | wg_put_session(wgs, &psref); |
2574 | } | | 2570 | } |
2575 | | | 2571 | |
2576 | static bool | | 2572 | static struct mbuf * |
2577 | wg_validate_msg_length(struct wg_softc *wg, const struct mbuf *m) | | 2573 | wg_validate_msg_header(struct wg_softc *wg, struct mbuf *m) |
2578 | { | | 2574 | { |
2579 | struct wg_msg *wgm; | | 2575 | struct wg_msg wgm; |
2580 | size_t mlen; | | 2576 | size_t mbuflen; |
| | | 2577 | size_t msglen; |
2581 | | | 2578 | |
2582 | mlen = m_length(m); | | 2579 | /* |
2583 | if (__predict_false(mlen < sizeof(struct wg_msg))) | | 2580 | * Get the mbuf chain length. It is already guaranteed, by |
2584 | return false; | | 2581 | * wg_overudp_cb, to be large enough for a struct wg_msg. |
| | | 2582 | */ |
| | | 2583 | mbuflen = m_length(m); |
| | | 2584 | KASSERT(mbuflen >= sizeof(struct wg_msg)); |
2585 | | | 2585 | |
2586 | wgm = mtod(m, struct wg_msg *); | | 2586 | /* |
2587 | switch (wgm->wgm_type) { | | 2587 | * Copy the message header (32-bit message type) out -- we'll |
| | | 2588 | * worry about contiguity and alignment later. |
| | | 2589 | */ |
| | | 2590 | m_copydata(m, 0, sizeof(wgm), &wgm); |
| | | 2591 | switch (wgm.wgm_type) { |
2588 | case WG_MSG_TYPE_INIT: | | 2592 | case WG_MSG_TYPE_INIT: |
2589 | if (__predict_true(mlen >= sizeof(struct wg_msg_init))) | | 2593 | msglen = sizeof(struct wg_msg_init); |
2590 | return true; | | | |
2591 | break; | | 2594 | break; |
2592 | case WG_MSG_TYPE_RESP: | | 2595 | case WG_MSG_TYPE_RESP: |
2593 | if (__predict_true(mlen >= sizeof(struct wg_msg_resp))) | | 2596 | msglen = sizeof(struct wg_msg_resp); |
2594 | return true; | | | |
2595 | break; | | 2597 | break; |
2596 | case WG_MSG_TYPE_COOKIE: | | 2598 | case WG_MSG_TYPE_COOKIE: |
2597 | if (__predict_true(mlen >= sizeof(struct wg_msg_cookie))) | | 2599 | msglen = sizeof(struct wg_msg_cookie); |
2598 | return true; | | | |
2599 | break; | | 2600 | break; |
2600 | case WG_MSG_TYPE_DATA: | | 2601 | case WG_MSG_TYPE_DATA: |
2601 | if (__predict_true(mlen >= sizeof(struct wg_msg_data))) | | 2602 | msglen = sizeof(struct wg_msg_data); |
2602 | return true; | | | |
2603 | break; | | 2603 | break; |
2604 | default: | | 2604 | default: |
2605 | WG_LOG_RATECHECK(&wg->wg_ppsratecheck, LOG_DEBUG, | | 2605 | WG_LOG_RATECHECK(&wg->wg_ppsratecheck, LOG_DEBUG, |
2606 | "Unexpected msg type: %u\n", wgm->wgm_type); | | 2606 | "Unexpected msg type: %u\n", wgm.wgm_type); |
2607 | return false; | | 2607 | goto error; |
2608 | } | | 2608 | } |
2609 | WG_DLOG("Invalid msg size: mlen=%lu type=%u\n", mlen, wgm->wgm_type); | | | |
2610 | | | 2609 | |
2611 | return false; | | 2610 | /* Verify the mbuf chain is long enough for this type of message. */ |
| | | 2611 | if (__predict_false(mbuflen < msglen)) { |
| | | 2612 | WG_DLOG("Invalid msg size: mbuflen=%lu type=%u\n", mbuflen, |
| | | 2613 | wgm.wgm_type); |
| | | 2614 | goto error; |
| | | 2615 | } |
| | | 2616 | |
| | | 2617 | /* Make the message header contiguous if necessary. */ |
| | | 2618 | if (__predict_false(m->m_len < msglen)) { |
| | | 2619 | m = m_pullup(m, msglen); |
| | | 2620 | if (m == NULL) |
| | | 2621 | return NULL; |
| | | 2622 | } |
| | | 2623 | |
| | | 2624 | return m; |
| | | 2625 | |
| | | 2626 | error: |
| | | 2627 | m_freem(m); |
| | | 2628 | return NULL; |
2612 | } | | 2629 | } |
2613 | | | 2630 | |
2614 | static void | | 2631 | static void |
2615 | wg_handle_packet(struct wg_softc *wg, struct mbuf *m, | | 2632 | wg_handle_packet(struct wg_softc *wg, struct mbuf *m, |
2616 | const struct sockaddr *src) | | 2633 | const struct sockaddr *src) |
2617 | { | | 2634 | { |
2618 | struct wg_msg *wgm; | | 2635 | struct wg_msg *wgm; |
2619 | bool valid; | | | |
2620 | | | 2636 | |
2621 | valid = wg_validate_msg_length(wg, m); | | 2637 | m = wg_validate_msg_header(wg, m); |
2622 | if (!valid) { | | 2638 | if (__predict_false(m == NULL)) |
2623 | m_freem(m); | | | |
2624 | return; | | 2639 | return; |
2625 | } | | | |
2626 | | | 2640 | |
| | | 2641 | KASSERT(m->m_len >= sizeof(struct wg_msg)); |
2627 | wgm = mtod(m, struct wg_msg *); | | 2642 | wgm = mtod(m, struct wg_msg *); |
2628 | switch (wgm->wgm_type) { | | 2643 | switch (wgm->wgm_type) { |
2629 | case WG_MSG_TYPE_INIT: | | 2644 | case WG_MSG_TYPE_INIT: |
2630 | wg_handle_msg_init(wg, (struct wg_msg_init *)wgm, src); | | 2645 | wg_handle_msg_init(wg, (struct wg_msg_init *)wgm, src); |
2631 | break; | | 2646 | break; |
2632 | case WG_MSG_TYPE_RESP: | | 2647 | case WG_MSG_TYPE_RESP: |
2633 | wg_handle_msg_resp(wg, (struct wg_msg_resp *)wgm, src); | | 2648 | wg_handle_msg_resp(wg, (struct wg_msg_resp *)wgm, src); |
2634 | break; | | 2649 | break; |
2635 | case WG_MSG_TYPE_COOKIE: | | 2650 | case WG_MSG_TYPE_COOKIE: |
2636 | wg_handle_msg_cookie(wg, (struct wg_msg_cookie *)wgm); | | 2651 | wg_handle_msg_cookie(wg, (struct wg_msg_cookie *)wgm); |
2637 | break; | | 2652 | break; |
2638 | case WG_MSG_TYPE_DATA: | | 2653 | case WG_MSG_TYPE_DATA: |
2639 | wg_handle_msg_data(wg, m, src); | | 2654 | wg_handle_msg_data(wg, m, src); |
2640 | break; | | 2655 | break; |
2641 | default: | | 2656 | default: |
2642 | /* wg_validate_msg_length should already reject this case */ | | 2657 | /* wg_validate_msg_header should already reject this case */ |
2643 | break; | | 2658 | break; |
2644 | } | | 2659 | } |
2645 | } | | 2660 | } |
2646 | | | 2661 | |
2647 | static void | | 2662 | static void |
2648 | wg_receive_packets(struct wg_softc *wg, const int af) | | 2663 | wg_receive_packets(struct wg_softc *wg, const int af) |
2649 | { | | 2664 | { |
2650 | | | 2665 | |
2651 | for (;;) { | | 2666 | for (;;) { |
2652 | int error, flags; | | 2667 | int error, flags; |
2653 | struct socket *so; | | 2668 | struct socket *so; |
2654 | struct mbuf *m = NULL; | | 2669 | struct mbuf *m = NULL; |
2655 | struct uio dummy_uio; | | 2670 | struct uio dummy_uio; |