xref: /openbsd-src/sys/net/wg_noise.h (revision efbb2e09ffebb712903070c7f89c2796597a6043)
1*efbb2e09Smvs /*	$OpenBSD: wg_noise.h,v 1.3 2024/03/05 17:48:01 mvs Exp $ */
258360b13Sdlg /*
358360b13Sdlg  * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
458360b13Sdlg  * Copyright (C) 2019-2020 Matt Dunwoodie <ncon@noconroy.net>
558360b13Sdlg  *
658360b13Sdlg  * Permission to use, copy, modify, and distribute this software for any
758360b13Sdlg  * purpose with or without fee is hereby granted, provided that the above
858360b13Sdlg  * copyright notice and this permission notice appear in all copies.
958360b13Sdlg  *
1058360b13Sdlg  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1158360b13Sdlg  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1258360b13Sdlg  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1358360b13Sdlg  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1458360b13Sdlg  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1558360b13Sdlg  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1658360b13Sdlg  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1758360b13Sdlg  */
1858360b13Sdlg 
1958360b13Sdlg #ifndef __NOISE_H__
2058360b13Sdlg #define __NOISE_H__
2158360b13Sdlg 
2258360b13Sdlg #include <sys/types.h>
2358360b13Sdlg #include <sys/time.h>
24*efbb2e09Smvs #include <sys/mutex.h>
2558360b13Sdlg #include <sys/rwlock.h>
2658360b13Sdlg 
2758360b13Sdlg #include <crypto/blake2s.h>
2858360b13Sdlg #include <crypto/chachapoly.h>
2958360b13Sdlg #include <crypto/curve25519.h>
3058360b13Sdlg 
3158360b13Sdlg #define NOISE_PUBLIC_KEY_LEN	CURVE25519_KEY_SIZE
3258360b13Sdlg #define NOISE_SYMMETRIC_KEY_LEN	CHACHA20POLY1305_KEY_SIZE
3358360b13Sdlg #define NOISE_TIMESTAMP_LEN	(sizeof(uint64_t) + sizeof(uint32_t))
3458360b13Sdlg #define NOISE_AUTHTAG_LEN	CHACHA20POLY1305_AUTHTAG_SIZE
3558360b13Sdlg #define NOISE_HASH_LEN		BLAKE2S_HASH_SIZE
3658360b13Sdlg 
3758360b13Sdlg /* Protocol string constants */
3858360b13Sdlg #define NOISE_HANDSHAKE_NAME	"Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"
3958360b13Sdlg #define NOISE_IDENTIFIER_NAME	"WireGuard v1 zx2c4 Jason@zx2c4.com"
4058360b13Sdlg 
4158360b13Sdlg /* Constants for the counter */
4258360b13Sdlg #define COUNTER_BITS_TOTAL	8192
4358360b13Sdlg #define COUNTER_BITS		(sizeof(unsigned long) * 8)
4458360b13Sdlg #define COUNTER_NUM		(COUNTER_BITS_TOTAL / COUNTER_BITS)
4558360b13Sdlg #define COUNTER_WINDOW_SIZE	(COUNTER_BITS_TOTAL - COUNTER_BITS)
4658360b13Sdlg 
4758360b13Sdlg /* Constants for the keypair */
4858360b13Sdlg #define REKEY_AFTER_MESSAGES	(1ull << 60)
4958360b13Sdlg #define REJECT_AFTER_MESSAGES	(UINT64_MAX - COUNTER_WINDOW_SIZE - 1)
5058360b13Sdlg #define REKEY_AFTER_TIME	120
5158360b13Sdlg #define REKEY_AFTER_TIME_RECV	165
5258360b13Sdlg #define REJECT_AFTER_TIME	180
5358360b13Sdlg #define REJECT_INTERVAL		(1000000000 / 50) /* fifty times per sec */
5458360b13Sdlg /* 24 = floor(log2(REJECT_INTERVAL)) */
5558360b13Sdlg #define REJECT_INTERVAL_MASK	(~((1ull<<24)-1))
5658360b13Sdlg 
5758360b13Sdlg enum noise_state_hs {
5858360b13Sdlg 	HS_ZEROED = 0,
5958360b13Sdlg 	CREATED_INITIATION,
6058360b13Sdlg 	CONSUMED_INITIATION,
6158360b13Sdlg 	CREATED_RESPONSE,
6258360b13Sdlg 	CONSUMED_RESPONSE,
6358360b13Sdlg };
6458360b13Sdlg 
6558360b13Sdlg struct noise_handshake {
6658360b13Sdlg 	enum noise_state_hs	 hs_state;
6758360b13Sdlg 	uint32_t		 hs_local_index;
6858360b13Sdlg 	uint32_t		 hs_remote_index;
6958360b13Sdlg 	uint8_t		 	 hs_e[NOISE_PUBLIC_KEY_LEN];
7058360b13Sdlg 	uint8_t		 	 hs_hash[NOISE_HASH_LEN];
7158360b13Sdlg 	uint8_t		 	 hs_ck[NOISE_HASH_LEN];
7258360b13Sdlg };
7358360b13Sdlg 
7458360b13Sdlg struct noise_counter {
75*efbb2e09Smvs 	struct mutex		 c_mtx;
7658360b13Sdlg 	uint64_t		 c_send;
7758360b13Sdlg 	uint64_t		 c_recv;
7858360b13Sdlg 	unsigned long		 c_backtrack[COUNTER_NUM];
7958360b13Sdlg };
8058360b13Sdlg 
8158360b13Sdlg struct noise_keypair {
8258360b13Sdlg 	SLIST_ENTRY(noise_keypair)	kp_entry;
8358360b13Sdlg 	int				kp_valid;
8458360b13Sdlg 	int				kp_is_initiator;
8558360b13Sdlg 	uint32_t			kp_local_index;
8658360b13Sdlg 	uint32_t			kp_remote_index;
8758360b13Sdlg 	uint8_t				kp_send[NOISE_SYMMETRIC_KEY_LEN];
8858360b13Sdlg 	uint8_t				kp_recv[NOISE_SYMMETRIC_KEY_LEN];
8958360b13Sdlg 	struct timespec			kp_birthdate; /* nanouptime */
9058360b13Sdlg 	struct noise_counter		kp_ctr;
9158360b13Sdlg };
9258360b13Sdlg 
9358360b13Sdlg struct noise_remote {
9458360b13Sdlg 	uint8_t				 r_public[NOISE_PUBLIC_KEY_LEN];
9558360b13Sdlg 	struct noise_local		*r_local;
9658360b13Sdlg 	uint8_t		 		 r_ss[NOISE_PUBLIC_KEY_LEN];
9758360b13Sdlg 
9858360b13Sdlg 	struct rwlock			 r_handshake_lock;
9958360b13Sdlg 	struct noise_handshake		 r_handshake;
10058360b13Sdlg 	uint8_t				 r_psk[NOISE_SYMMETRIC_KEY_LEN];
10158360b13Sdlg 	uint8_t				 r_timestamp[NOISE_TIMESTAMP_LEN];
10258360b13Sdlg 	struct timespec			 r_last_init; /* nanouptime */
10358360b13Sdlg 
104*efbb2e09Smvs 	struct mutex			 r_keypair_mtx;
10558360b13Sdlg 	SLIST_HEAD(,noise_keypair)	 r_unused_keypairs;
10658360b13Sdlg 	struct noise_keypair		*r_next, *r_current, *r_previous;
10758360b13Sdlg 	struct noise_keypair		 r_keypair[3]; /* 3: next, current, previous. */
10858360b13Sdlg 
10958360b13Sdlg };
11058360b13Sdlg 
11158360b13Sdlg struct noise_local {
11258360b13Sdlg 	struct rwlock		l_identity_lock;
11358360b13Sdlg 	int			l_has_identity;
11458360b13Sdlg 	uint8_t			l_public[NOISE_PUBLIC_KEY_LEN];
11558360b13Sdlg 	uint8_t			l_private[NOISE_PUBLIC_KEY_LEN];
11658360b13Sdlg 
11758360b13Sdlg 	struct noise_upcall {
11858360b13Sdlg 		void	 *u_arg;
11958360b13Sdlg 		struct noise_remote *
12058360b13Sdlg 			(*u_remote_get)(void *, uint8_t[NOISE_PUBLIC_KEY_LEN]);
12158360b13Sdlg 		uint32_t
12258360b13Sdlg 			(*u_index_set)(void *, struct noise_remote *);
12358360b13Sdlg 		void	(*u_index_drop)(void *, uint32_t);
12458360b13Sdlg 	}			l_upcall;
12558360b13Sdlg };
12658360b13Sdlg 
12758360b13Sdlg /* Set/Get noise parameters */
12858360b13Sdlg void	noise_local_init(struct noise_local *, struct noise_upcall *);
12958360b13Sdlg void	noise_local_lock_identity(struct noise_local *);
13058360b13Sdlg void	noise_local_unlock_identity(struct noise_local *);
13158360b13Sdlg int	noise_local_set_private(struct noise_local *, uint8_t[NOISE_PUBLIC_KEY_LEN]);
13258360b13Sdlg int	noise_local_keys(struct noise_local *, uint8_t[NOISE_PUBLIC_KEY_LEN],
13358360b13Sdlg 	    uint8_t[NOISE_PUBLIC_KEY_LEN]);
13458360b13Sdlg 
13558360b13Sdlg void	noise_remote_init(struct noise_remote *, uint8_t[NOISE_PUBLIC_KEY_LEN],
13658360b13Sdlg 	    struct noise_local *);
13758360b13Sdlg int	noise_remote_set_psk(struct noise_remote *, uint8_t[NOISE_SYMMETRIC_KEY_LEN]);
13858360b13Sdlg int	noise_remote_keys(struct noise_remote *, uint8_t[NOISE_PUBLIC_KEY_LEN],
13958360b13Sdlg 	    uint8_t[NOISE_SYMMETRIC_KEY_LEN]);
14058360b13Sdlg 
14158360b13Sdlg /* Should be called anytime noise_local_set_private is called */
14258360b13Sdlg void	noise_remote_precompute(struct noise_remote *);
14358360b13Sdlg 
14458360b13Sdlg /* Cryptographic functions */
14558360b13Sdlg int	noise_create_initiation(
14658360b13Sdlg 	    struct noise_remote *,
14758360b13Sdlg 	    uint32_t *s_idx,
14858360b13Sdlg 	    uint8_t ue[NOISE_PUBLIC_KEY_LEN],
14958360b13Sdlg 	    uint8_t es[NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN],
15058360b13Sdlg 	    uint8_t ets[NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN]);
15158360b13Sdlg 
15258360b13Sdlg int	noise_consume_initiation(
15358360b13Sdlg 	    struct noise_local *,
15458360b13Sdlg 	    struct noise_remote **,
15558360b13Sdlg 	    uint32_t s_idx,
15658360b13Sdlg 	    uint8_t ue[NOISE_PUBLIC_KEY_LEN],
15758360b13Sdlg 	    uint8_t es[NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN],
15858360b13Sdlg 	    uint8_t ets[NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN]);
15958360b13Sdlg 
16058360b13Sdlg int	noise_create_response(
16158360b13Sdlg 	    struct noise_remote *,
16258360b13Sdlg 	    uint32_t *s_idx,
16358360b13Sdlg 	    uint32_t *r_idx,
16458360b13Sdlg 	    uint8_t ue[NOISE_PUBLIC_KEY_LEN],
16558360b13Sdlg 	    uint8_t en[0 + NOISE_AUTHTAG_LEN]);
16658360b13Sdlg 
16758360b13Sdlg int	noise_consume_response(
16858360b13Sdlg 	    struct noise_remote *,
16958360b13Sdlg 	    uint32_t s_idx,
17058360b13Sdlg 	    uint32_t r_idx,
17158360b13Sdlg 	    uint8_t ue[NOISE_PUBLIC_KEY_LEN],
17258360b13Sdlg 	    uint8_t en[0 + NOISE_AUTHTAG_LEN]);
17358360b13Sdlg 
17458360b13Sdlg int	noise_remote_begin_session(struct noise_remote *);
17558360b13Sdlg void	noise_remote_clear(struct noise_remote *);
17658360b13Sdlg void	noise_remote_expire_current(struct noise_remote *);
17758360b13Sdlg 
17858360b13Sdlg int	noise_remote_ready(struct noise_remote *);
17958360b13Sdlg 
18058360b13Sdlg int	noise_remote_encrypt(
18158360b13Sdlg 	    struct noise_remote *,
18258360b13Sdlg 	    uint32_t *r_idx,
18358360b13Sdlg 	    uint64_t *nonce,
18458360b13Sdlg 	    uint8_t *buf,
18558360b13Sdlg 	    size_t buflen);
18658360b13Sdlg int	noise_remote_decrypt(
18758360b13Sdlg 	    struct noise_remote *,
18858360b13Sdlg 	    uint32_t r_idx,
18958360b13Sdlg 	    uint64_t nonce,
19058360b13Sdlg 	    uint8_t *buf,
19158360b13Sdlg 	    size_t buflen);
19258360b13Sdlg 
19358360b13Sdlg #ifdef WGTEST
19458360b13Sdlg void	noise_test();
19558360b13Sdlg #endif /* WGTEST */
19658360b13Sdlg 
19758360b13Sdlg #endif /* __NOISE_H__ */
198