diff options
author | Kyle Evans <kevans@FreeBSD.org> | 2021-03-15 02:25:40 +0000 |
---|---|---|
committer | Kyle Evans <kevans@FreeBSD.org> | 2021-03-15 04:52:04 +0000 |
commit | 74ae3f3e33b810248da19004c58b3581cd367843 (patch) | |
tree | b17ce98b77a3a1a86e8255dad7861d9c160222a9 /sys/dev/if_wg/crypto.h | |
parent | 3e5e9939cda3b24df37c37da5f195415a894d9fd (diff) | |
download | src-74ae3f3e33b810248da19004c58b3581cd367843.tar.gz src-74ae3f3e33b810248da19004c58b3581cd367843.zip |
if_wg: import latest fixup work from the wireguard-freebsd project
This is the culmination of about a week of work from three developers to
fix a number of functional and security issues. This patch consists of
work done by the following folks:
- Jason A. Donenfeld <Jason@zx2c4.com>
- Matt Dunwoodie <ncon@noconroy.net>
- Kyle Evans <kevans@FreeBSD.org>
Notable changes include:
- Packets are now correctly staged for processing once the handshake has
completed, resulting in less packet loss in the interim.
- Various race conditions have been resolved, particularly w.r.t. socket
and packet lifetime (panics)
- Various tests have been added to assure correct functionality and
tooling conformance
- Many security issues have been addressed
- if_wg now maintains jail-friendly semantics: sockets are created in
the interface's home vnet so that it can act as the sole network
connection for a jail
- if_wg no longer fails to remove peer allowed-ips of 0.0.0.0/0
- if_wg now exports via ioctl a format that is future proof and
complete. It is additionally supported by the upstream
wireguard-tools (which we plan to merge in to base soon)
- if_wg now conforms to the WireGuard protocol and is more closely
aligned with security auditing guidelines
Note that the driver has been rebased away from using iflib. iflib
poses a number of challenges for a cloned device trying to operate in a
vnet that are non-trivial to solve and adds complexity to the
implementation for little gain.
The crypto implementation that was previously added to the tree was a
super complex integration of what previously appeared in an old out of
tree Linux module, which has been reduced to crypto.c containing simple
boring reference implementations. This is part of a near-to-mid term
goal to work with FreeBSD kernel crypto folks and take advantage of or
improve accelerated crypto already offered elsewhere.
There's additional test suite effort underway out-of-tree taking
advantage of the aforementioned jail-friendly semantics to test a number
of real-world topologies, based on netns.sh.
Also note that this is still a work in progress; work going further will
be much smaller in nature.
MFC after: 1 month (maybe)
Diffstat (limited to 'sys/dev/if_wg/crypto.h')
-rw-r--r-- | sys/dev/if_wg/crypto.h | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/sys/dev/if_wg/crypto.h b/sys/dev/if_wg/crypto.h new file mode 100644 index 000000000000..6e045c2fe0bf --- /dev/null +++ b/sys/dev/if_wg/crypto.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _WG_CRYPTO +#define _WG_CRYPTO + +#include <sys/types.h> + +enum chacha20poly1305_lengths { + XCHACHA20POLY1305_NONCE_SIZE = 24, + CHACHA20POLY1305_KEY_SIZE = 32, + CHACHA20POLY1305_AUTHTAG_SIZE = 16 +}; + +void +chacha20poly1305_encrypt(uint8_t *dst, const uint8_t *src, const size_t src_len, + const uint8_t *ad, const size_t ad_len, + const uint64_t nonce, + const uint8_t key[CHACHA20POLY1305_KEY_SIZE]); + +bool +chacha20poly1305_decrypt(uint8_t *dst, const uint8_t *src, const size_t src_len, + const uint8_t *ad, const size_t ad_len, + const uint64_t nonce, + const uint8_t key[CHACHA20POLY1305_KEY_SIZE]); + +void +xchacha20poly1305_encrypt(uint8_t *dst, const uint8_t *src, + const size_t src_len, const uint8_t *ad, + const size_t ad_len, + const uint8_t nonce[XCHACHA20POLY1305_NONCE_SIZE], + const uint8_t key[CHACHA20POLY1305_KEY_SIZE]); + +bool +xchacha20poly1305_decrypt(uint8_t *dst, const uint8_t *src, + const size_t src_len, const uint8_t *ad, + const size_t ad_len, + const uint8_t nonce[XCHACHA20POLY1305_NONCE_SIZE], + const uint8_t key[CHACHA20POLY1305_KEY_SIZE]); + + +enum blake2s_lengths { + BLAKE2S_BLOCK_SIZE = 64, + BLAKE2S_HASH_SIZE = 32, + BLAKE2S_KEY_SIZE = 32 +}; + +struct blake2s_state { + uint32_t h[8]; + uint32_t t[2]; + uint32_t f[2]; + uint8_t buf[BLAKE2S_BLOCK_SIZE]; + unsigned int buflen; + unsigned int outlen; +}; + +void blake2s_init(struct blake2s_state *state, const size_t outlen); + +void blake2s_init_key(struct blake2s_state *state, const size_t outlen, + const uint8_t *key, const size_t keylen); + +void blake2s_update(struct blake2s_state *state, const uint8_t *in, size_t inlen); + +void blake2s_final(struct blake2s_state *state, uint8_t *out); + +void blake2s(uint8_t *out, const uint8_t *in, const uint8_t *key, + const size_t outlen, const size_t inlen, const size_t keylen); + +void blake2s_hmac(uint8_t *out, const uint8_t *in, const uint8_t *key, + const size_t outlen, const size_t inlen, const size_t keylen); + +enum curve25519_lengths { + CURVE25519_KEY_SIZE = 32 +}; + +bool curve25519(uint8_t mypublic[static CURVE25519_KEY_SIZE], + const uint8_t secret[static CURVE25519_KEY_SIZE], + const uint8_t basepoint[static CURVE25519_KEY_SIZE]); + +static inline bool +curve25519_generate_public(uint8_t pub[static CURVE25519_KEY_SIZE], + const uint8_t secret[static CURVE25519_KEY_SIZE]) +{ + static const uint8_t basepoint[CURVE25519_KEY_SIZE] = { 9 }; + + return curve25519(pub, secret, basepoint); +} + +static inline void curve25519_clamp_secret(uint8_t secret[static CURVE25519_KEY_SIZE]) +{ + secret[0] &= 248; + secret[31] = (secret[31] & 127) | 64; +} + +static inline void curve25519_generate_secret(uint8_t secret[CURVE25519_KEY_SIZE]) +{ + arc4random_buf(secret, CURVE25519_KEY_SIZE); + curve25519_clamp_secret(secret); +} + +#endif |