xref: /freebsd/sys/dev/wg/wg_noise.c (revision dcf581bb49bedcf9c18d6cccc80a9fbd68516d23)
1744bfb21SJohn Baldwin /* SPDX-License-Identifier: ISC
2744bfb21SJohn Baldwin  *
3744bfb21SJohn Baldwin  * Copyright (C) 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
4744bfb21SJohn Baldwin  * Copyright (C) 2019-2021 Matt Dunwoodie <ncon@noconroy.net>
5744bfb21SJohn Baldwin  * Copyright (c) 2022 The FreeBSD Foundation
6744bfb21SJohn Baldwin  */
7744bfb21SJohn Baldwin 
8744bfb21SJohn Baldwin #include <sys/param.h>
9744bfb21SJohn Baldwin #include <sys/systm.h>
10744bfb21SJohn Baldwin #include <sys/ck.h>
11744bfb21SJohn Baldwin #include <sys/endian.h>
12744bfb21SJohn Baldwin #include <sys/epoch.h>
13744bfb21SJohn Baldwin #include <sys/kernel.h>
14744bfb21SJohn Baldwin #include <sys/lock.h>
15744bfb21SJohn Baldwin #include <sys/malloc.h>
16744bfb21SJohn Baldwin #include <sys/mutex.h>
17744bfb21SJohn Baldwin #include <sys/refcount.h>
18744bfb21SJohn Baldwin #include <sys/rwlock.h>
19744bfb21SJohn Baldwin #include <crypto/siphash/siphash.h>
20744bfb21SJohn Baldwin 
21744bfb21SJohn Baldwin #include "crypto.h"
22744bfb21SJohn Baldwin #include "wg_noise.h"
23744bfb21SJohn Baldwin #include "support.h"
24744bfb21SJohn Baldwin 
25744bfb21SJohn Baldwin /* Protocol string constants */
26744bfb21SJohn Baldwin #define NOISE_HANDSHAKE_NAME	"Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"
27744bfb21SJohn Baldwin #define NOISE_IDENTIFIER_NAME	"WireGuard v1 zx2c4 Jason@zx2c4.com"
28744bfb21SJohn Baldwin 
29744bfb21SJohn Baldwin /* Constants for the counter */
30744bfb21SJohn Baldwin #define COUNTER_BITS_TOTAL	8192
31744bfb21SJohn Baldwin #ifdef __LP64__
32744bfb21SJohn Baldwin #define COUNTER_ORDER		6
33744bfb21SJohn Baldwin #define COUNTER_BITS		64
34744bfb21SJohn Baldwin #else
35744bfb21SJohn Baldwin #define COUNTER_ORDER		5
36744bfb21SJohn Baldwin #define COUNTER_BITS		32
37744bfb21SJohn Baldwin #endif
38744bfb21SJohn Baldwin #define COUNTER_REDUNDANT_BITS	COUNTER_BITS
39744bfb21SJohn Baldwin #define COUNTER_WINDOW_SIZE	(COUNTER_BITS_TOTAL - COUNTER_REDUNDANT_BITS)
40744bfb21SJohn Baldwin 
41744bfb21SJohn Baldwin /* Constants for the keypair */
42744bfb21SJohn Baldwin #define REKEY_AFTER_MESSAGES	(1ull << 60)
43744bfb21SJohn Baldwin #define REJECT_AFTER_MESSAGES	(UINT64_MAX - COUNTER_WINDOW_SIZE - 1)
44744bfb21SJohn Baldwin #define REKEY_AFTER_TIME	120
45744bfb21SJohn Baldwin #define REKEY_AFTER_TIME_RECV	165
46744bfb21SJohn Baldwin #define REJECT_INTERVAL		(1000000000 / 50) /* fifty times per sec */
47744bfb21SJohn Baldwin /* 24 = floor(log2(REJECT_INTERVAL)) */
48744bfb21SJohn Baldwin #define REJECT_INTERVAL_MASK	(~((1ull<<24)-1))
49744bfb21SJohn Baldwin #define TIMER_RESET		(SBT_1S * -(REKEY_TIMEOUT+1))
50744bfb21SJohn Baldwin 
51744bfb21SJohn Baldwin #define HT_INDEX_SIZE		(1 << 13)
52744bfb21SJohn Baldwin #define HT_INDEX_MASK		(HT_INDEX_SIZE - 1)
53744bfb21SJohn Baldwin #define HT_REMOTE_SIZE		(1 << 11)
54744bfb21SJohn Baldwin #define HT_REMOTE_MASK		(HT_REMOTE_SIZE - 1)
55744bfb21SJohn Baldwin #define MAX_REMOTE_PER_LOCAL	(1 << 20)
56744bfb21SJohn Baldwin 
57744bfb21SJohn Baldwin struct noise_index {
58744bfb21SJohn Baldwin 	CK_LIST_ENTRY(noise_index)	 i_entry;
59744bfb21SJohn Baldwin 	uint32_t			 i_local_index;
60744bfb21SJohn Baldwin 	uint32_t			 i_remote_index;
61744bfb21SJohn Baldwin 	int				 i_is_keypair;
62744bfb21SJohn Baldwin };
63744bfb21SJohn Baldwin 
64744bfb21SJohn Baldwin struct noise_keypair {
65744bfb21SJohn Baldwin 	struct noise_index		 kp_index;
66744bfb21SJohn Baldwin 	u_int				 kp_refcnt;
67744bfb21SJohn Baldwin 	bool				 kp_can_send;
68744bfb21SJohn Baldwin 	bool				 kp_is_initiator;
69744bfb21SJohn Baldwin 	sbintime_t			 kp_birthdate; /* sbinuptime */
70744bfb21SJohn Baldwin 	struct noise_remote		*kp_remote;
71744bfb21SJohn Baldwin 
72744bfb21SJohn Baldwin 	uint8_t				 kp_send[NOISE_SYMMETRIC_KEY_LEN];
73744bfb21SJohn Baldwin 	uint8_t				 kp_recv[NOISE_SYMMETRIC_KEY_LEN];
74744bfb21SJohn Baldwin 
75744bfb21SJohn Baldwin 	/* Counter elements */
76744bfb21SJohn Baldwin 	struct rwlock			 kp_nonce_lock;
77744bfb21SJohn Baldwin 	uint64_t			 kp_nonce_send;
78744bfb21SJohn Baldwin 	uint64_t			 kp_nonce_recv;
79744bfb21SJohn Baldwin 	unsigned long			 kp_backtrack[COUNTER_BITS_TOTAL / COUNTER_BITS];
80744bfb21SJohn Baldwin 
81744bfb21SJohn Baldwin 	struct epoch_context		 kp_smr;
82744bfb21SJohn Baldwin };
83744bfb21SJohn Baldwin 
84744bfb21SJohn Baldwin struct noise_handshake {
85744bfb21SJohn Baldwin 	uint8_t	 			 hs_e[NOISE_PUBLIC_KEY_LEN];
86744bfb21SJohn Baldwin 	uint8_t	 			 hs_hash[NOISE_HASH_LEN];
87744bfb21SJohn Baldwin 	uint8_t	 			 hs_ck[NOISE_HASH_LEN];
88744bfb21SJohn Baldwin };
89744bfb21SJohn Baldwin 
90744bfb21SJohn Baldwin enum noise_handshake_state {
91744bfb21SJohn Baldwin 	HANDSHAKE_DEAD,
92744bfb21SJohn Baldwin 	HANDSHAKE_INITIATOR,
93744bfb21SJohn Baldwin 	HANDSHAKE_RESPONDER,
94744bfb21SJohn Baldwin };
95744bfb21SJohn Baldwin 
96744bfb21SJohn Baldwin struct noise_remote {
97744bfb21SJohn Baldwin 	struct noise_index		 r_index;
98744bfb21SJohn Baldwin 
99744bfb21SJohn Baldwin 	CK_LIST_ENTRY(noise_remote) 	 r_entry;
100744bfb21SJohn Baldwin 	bool				 r_entry_inserted;
101744bfb21SJohn Baldwin 	uint8_t				 r_public[NOISE_PUBLIC_KEY_LEN];
102744bfb21SJohn Baldwin 
103744bfb21SJohn Baldwin 	struct rwlock			 r_handshake_lock;
104744bfb21SJohn Baldwin 	struct noise_handshake		 r_handshake;
105744bfb21SJohn Baldwin 	enum noise_handshake_state	 r_handshake_state;
106744bfb21SJohn Baldwin 	sbintime_t			 r_last_sent; /* sbinuptime */
107744bfb21SJohn Baldwin 	sbintime_t			 r_last_init_recv; /* sbinuptime */
108744bfb21SJohn Baldwin 	uint8_t				 r_timestamp[NOISE_TIMESTAMP_LEN];
109744bfb21SJohn Baldwin 	uint8_t				 r_psk[NOISE_SYMMETRIC_KEY_LEN];
110744bfb21SJohn Baldwin 	uint8_t		 		 r_ss[NOISE_PUBLIC_KEY_LEN];
111744bfb21SJohn Baldwin 
112744bfb21SJohn Baldwin 	u_int				 r_refcnt;
113744bfb21SJohn Baldwin 	struct noise_local		*r_local;
114744bfb21SJohn Baldwin 	void				*r_arg;
115744bfb21SJohn Baldwin 
116744bfb21SJohn Baldwin 	struct mtx			 r_keypair_mtx;
117744bfb21SJohn Baldwin 	struct noise_keypair		*r_next, *r_current, *r_previous;
118744bfb21SJohn Baldwin 
119744bfb21SJohn Baldwin 	struct epoch_context		 r_smr;
120744bfb21SJohn Baldwin 	void				(*r_cleanup)(struct noise_remote *);
121744bfb21SJohn Baldwin };
122744bfb21SJohn Baldwin 
123744bfb21SJohn Baldwin struct noise_local {
124744bfb21SJohn Baldwin 	struct rwlock			 l_identity_lock;
125744bfb21SJohn Baldwin 	bool				 l_has_identity;
126744bfb21SJohn Baldwin 	uint8_t				 l_public[NOISE_PUBLIC_KEY_LEN];
127744bfb21SJohn Baldwin 	uint8_t				 l_private[NOISE_PUBLIC_KEY_LEN];
128744bfb21SJohn Baldwin 
129744bfb21SJohn Baldwin 	u_int				 l_refcnt;
130744bfb21SJohn Baldwin 	uint8_t				 l_hash_key[SIPHASH_KEY_LENGTH];
131744bfb21SJohn Baldwin 	void				*l_arg;
132744bfb21SJohn Baldwin 	void				(*l_cleanup)(struct noise_local *);
133744bfb21SJohn Baldwin 
134744bfb21SJohn Baldwin 	struct mtx			 l_remote_mtx;
135744bfb21SJohn Baldwin 	size_t				 l_remote_num;
136744bfb21SJohn Baldwin 	CK_LIST_HEAD(,noise_remote)	 l_remote_hash[HT_REMOTE_SIZE];
137744bfb21SJohn Baldwin 
138744bfb21SJohn Baldwin 	struct mtx			 l_index_mtx;
139744bfb21SJohn Baldwin 	CK_LIST_HEAD(,noise_index)	 l_index_hash[HT_INDEX_SIZE];
140744bfb21SJohn Baldwin };
141744bfb21SJohn Baldwin 
142744bfb21SJohn Baldwin static void	noise_precompute_ss(struct noise_local *, struct noise_remote *);
143744bfb21SJohn Baldwin 
144744bfb21SJohn Baldwin static void	noise_remote_index_insert(struct noise_local *, struct noise_remote *);
145744bfb21SJohn Baldwin static struct noise_remote *
146744bfb21SJohn Baldwin 		noise_remote_index_lookup(struct noise_local *, uint32_t, bool);
147744bfb21SJohn Baldwin static int	noise_remote_index_remove(struct noise_local *, struct noise_remote *);
148744bfb21SJohn Baldwin static void	noise_remote_expire_current(struct noise_remote *);
149744bfb21SJohn Baldwin 
150744bfb21SJohn Baldwin static void	noise_add_new_keypair(struct noise_local *, struct noise_remote *, struct noise_keypair *);
151744bfb21SJohn Baldwin static int	noise_begin_session(struct noise_remote *);
152744bfb21SJohn Baldwin static void	noise_keypair_drop(struct noise_keypair *);
153744bfb21SJohn Baldwin 
154744bfb21SJohn Baldwin static void	noise_kdf(uint8_t *, uint8_t *, uint8_t *, const uint8_t *,
155744bfb21SJohn Baldwin 		    size_t, size_t, size_t, size_t,
156744bfb21SJohn Baldwin 		    const uint8_t [NOISE_HASH_LEN]);
157744bfb21SJohn Baldwin static int	noise_mix_dh(uint8_t [NOISE_HASH_LEN], uint8_t [NOISE_SYMMETRIC_KEY_LEN],
158744bfb21SJohn Baldwin 		    const uint8_t [NOISE_PUBLIC_KEY_LEN],
159744bfb21SJohn Baldwin 		    const uint8_t [NOISE_PUBLIC_KEY_LEN]);
160744bfb21SJohn Baldwin static int	noise_mix_ss(uint8_t ck[NOISE_HASH_LEN], uint8_t [NOISE_SYMMETRIC_KEY_LEN],
161744bfb21SJohn Baldwin 		    const uint8_t [NOISE_PUBLIC_KEY_LEN]);
162744bfb21SJohn Baldwin static void	noise_mix_hash(uint8_t [NOISE_HASH_LEN], const uint8_t *, size_t);
163744bfb21SJohn Baldwin static void	noise_mix_psk(uint8_t [NOISE_HASH_LEN], uint8_t [NOISE_HASH_LEN],
164744bfb21SJohn Baldwin 		    uint8_t [NOISE_SYMMETRIC_KEY_LEN], const uint8_t [NOISE_SYMMETRIC_KEY_LEN]);
165744bfb21SJohn Baldwin static void	noise_param_init(uint8_t [NOISE_HASH_LEN], uint8_t [NOISE_HASH_LEN],
166744bfb21SJohn Baldwin 		    const uint8_t [NOISE_PUBLIC_KEY_LEN]);
167744bfb21SJohn Baldwin static void	noise_msg_encrypt(uint8_t *, const uint8_t *, size_t,
168744bfb21SJohn Baldwin 		    uint8_t [NOISE_SYMMETRIC_KEY_LEN], uint8_t [NOISE_HASH_LEN]);
169744bfb21SJohn Baldwin static int	noise_msg_decrypt(uint8_t *, const uint8_t *, size_t,
170744bfb21SJohn Baldwin 		    uint8_t [NOISE_SYMMETRIC_KEY_LEN], uint8_t [NOISE_HASH_LEN]);
171744bfb21SJohn Baldwin static void	noise_msg_ephemeral(uint8_t [NOISE_HASH_LEN], uint8_t [NOISE_HASH_LEN],
172744bfb21SJohn Baldwin 		    const uint8_t [NOISE_PUBLIC_KEY_LEN]);
173744bfb21SJohn Baldwin static void	noise_tai64n_now(uint8_t [NOISE_TIMESTAMP_LEN]);
174744bfb21SJohn Baldwin static int	noise_timer_expired(sbintime_t, uint32_t, uint32_t);
175744bfb21SJohn Baldwin static uint64_t siphash24(const uint8_t [SIPHASH_KEY_LENGTH], const void *, size_t);
176744bfb21SJohn Baldwin 
177744bfb21SJohn Baldwin MALLOC_DEFINE(M_NOISE, "NOISE", "wgnoise");
178744bfb21SJohn Baldwin 
179744bfb21SJohn Baldwin /* Local configuration */
180744bfb21SJohn Baldwin struct noise_local *
181744bfb21SJohn Baldwin noise_local_alloc(void *arg)
182744bfb21SJohn Baldwin {
183744bfb21SJohn Baldwin 	struct noise_local *l;
184744bfb21SJohn Baldwin 	size_t i;
185744bfb21SJohn Baldwin 
186744bfb21SJohn Baldwin 	l = malloc(sizeof(*l), M_NOISE, M_WAITOK | M_ZERO);
187744bfb21SJohn Baldwin 
188744bfb21SJohn Baldwin 	rw_init(&l->l_identity_lock, "noise_identity");
189744bfb21SJohn Baldwin 	l->l_has_identity = false;
190744bfb21SJohn Baldwin 	bzero(l->l_public, NOISE_PUBLIC_KEY_LEN);
191744bfb21SJohn Baldwin 	bzero(l->l_private, NOISE_PUBLIC_KEY_LEN);
192744bfb21SJohn Baldwin 
193744bfb21SJohn Baldwin 	refcount_init(&l->l_refcnt, 1);
194744bfb21SJohn Baldwin 	arc4random_buf(l->l_hash_key, sizeof(l->l_hash_key));
195744bfb21SJohn Baldwin 	l->l_arg = arg;
196744bfb21SJohn Baldwin 	l->l_cleanup = NULL;
197744bfb21SJohn Baldwin 
198744bfb21SJohn Baldwin 	mtx_init(&l->l_remote_mtx, "noise_remote", NULL, MTX_DEF);
199744bfb21SJohn Baldwin 	l->l_remote_num = 0;
200744bfb21SJohn Baldwin 	for (i = 0; i < HT_REMOTE_SIZE; i++)
201744bfb21SJohn Baldwin 		CK_LIST_INIT(&l->l_remote_hash[i]);
202744bfb21SJohn Baldwin 
203744bfb21SJohn Baldwin 	mtx_init(&l->l_index_mtx, "noise_index", NULL, MTX_DEF);
204744bfb21SJohn Baldwin 	for (i = 0; i < HT_INDEX_SIZE; i++)
205744bfb21SJohn Baldwin 		CK_LIST_INIT(&l->l_index_hash[i]);
206744bfb21SJohn Baldwin 
207744bfb21SJohn Baldwin 	return (l);
208744bfb21SJohn Baldwin }
209744bfb21SJohn Baldwin 
210744bfb21SJohn Baldwin struct noise_local *
211744bfb21SJohn Baldwin noise_local_ref(struct noise_local *l)
212744bfb21SJohn Baldwin {
213744bfb21SJohn Baldwin 	refcount_acquire(&l->l_refcnt);
214744bfb21SJohn Baldwin 	return (l);
215744bfb21SJohn Baldwin }
216744bfb21SJohn Baldwin 
217744bfb21SJohn Baldwin void
218744bfb21SJohn Baldwin noise_local_put(struct noise_local *l)
219744bfb21SJohn Baldwin {
220744bfb21SJohn Baldwin 	if (refcount_release(&l->l_refcnt)) {
221744bfb21SJohn Baldwin 		if (l->l_cleanup != NULL)
222744bfb21SJohn Baldwin 			l->l_cleanup(l);
223744bfb21SJohn Baldwin 		rw_destroy(&l->l_identity_lock);
224744bfb21SJohn Baldwin 		mtx_destroy(&l->l_remote_mtx);
225744bfb21SJohn Baldwin 		mtx_destroy(&l->l_index_mtx);
226*dcf581bbSJohn Baldwin 		zfree(l, M_NOISE);
227744bfb21SJohn Baldwin 	}
228744bfb21SJohn Baldwin }
229744bfb21SJohn Baldwin 
230744bfb21SJohn Baldwin void
231744bfb21SJohn Baldwin noise_local_free(struct noise_local *l, void (*cleanup)(struct noise_local *))
232744bfb21SJohn Baldwin {
233744bfb21SJohn Baldwin 	l->l_cleanup = cleanup;
234744bfb21SJohn Baldwin 	noise_local_put(l);
235744bfb21SJohn Baldwin }
236744bfb21SJohn Baldwin 
237744bfb21SJohn Baldwin void *
238744bfb21SJohn Baldwin noise_local_arg(struct noise_local *l)
239744bfb21SJohn Baldwin {
240744bfb21SJohn Baldwin 	return (l->l_arg);
241744bfb21SJohn Baldwin }
242744bfb21SJohn Baldwin 
243744bfb21SJohn Baldwin void
244744bfb21SJohn Baldwin noise_local_private(struct noise_local *l, const uint8_t private[NOISE_PUBLIC_KEY_LEN])
245744bfb21SJohn Baldwin {
246744bfb21SJohn Baldwin 	struct epoch_tracker et;
247744bfb21SJohn Baldwin 	struct noise_remote *r;
248744bfb21SJohn Baldwin 	size_t i;
249744bfb21SJohn Baldwin 
250744bfb21SJohn Baldwin 	rw_wlock(&l->l_identity_lock);
251744bfb21SJohn Baldwin 	memcpy(l->l_private, private, NOISE_PUBLIC_KEY_LEN);
252744bfb21SJohn Baldwin 	curve25519_clamp_secret(l->l_private);
253744bfb21SJohn Baldwin 	l->l_has_identity = curve25519_generate_public(l->l_public, l->l_private);
254744bfb21SJohn Baldwin 
255744bfb21SJohn Baldwin 	NET_EPOCH_ENTER(et);
256744bfb21SJohn Baldwin 	for (i = 0; i < HT_REMOTE_SIZE; i++) {
257744bfb21SJohn Baldwin 		CK_LIST_FOREACH(r, &l->l_remote_hash[i], r_entry) {
258744bfb21SJohn Baldwin 			noise_precompute_ss(l, r);
259744bfb21SJohn Baldwin 			noise_remote_expire_current(r);
260744bfb21SJohn Baldwin 		}
261744bfb21SJohn Baldwin 	}
262744bfb21SJohn Baldwin 	NET_EPOCH_EXIT(et);
263744bfb21SJohn Baldwin 	rw_wunlock(&l->l_identity_lock);
264744bfb21SJohn Baldwin }
265744bfb21SJohn Baldwin 
266744bfb21SJohn Baldwin int
267744bfb21SJohn Baldwin noise_local_keys(struct noise_local *l, uint8_t public[NOISE_PUBLIC_KEY_LEN],
268744bfb21SJohn Baldwin     uint8_t private[NOISE_PUBLIC_KEY_LEN])
269744bfb21SJohn Baldwin {
270744bfb21SJohn Baldwin 	int has_identity;
271744bfb21SJohn Baldwin 	rw_rlock(&l->l_identity_lock);
272744bfb21SJohn Baldwin 	if ((has_identity = l->l_has_identity)) {
273744bfb21SJohn Baldwin 		if (public != NULL)
274744bfb21SJohn Baldwin 			memcpy(public, l->l_public, NOISE_PUBLIC_KEY_LEN);
275744bfb21SJohn Baldwin 		if (private != NULL)
276744bfb21SJohn Baldwin 			memcpy(private, l->l_private, NOISE_PUBLIC_KEY_LEN);
277744bfb21SJohn Baldwin 	}
278744bfb21SJohn Baldwin 	rw_runlock(&l->l_identity_lock);
279744bfb21SJohn Baldwin 	return (has_identity ? 0 : ENXIO);
280744bfb21SJohn Baldwin }
281744bfb21SJohn Baldwin 
282744bfb21SJohn Baldwin static void
283744bfb21SJohn Baldwin noise_precompute_ss(struct noise_local *l, struct noise_remote *r)
284744bfb21SJohn Baldwin {
285744bfb21SJohn Baldwin 	rw_wlock(&r->r_handshake_lock);
286744bfb21SJohn Baldwin 	if (!l->l_has_identity ||
287744bfb21SJohn Baldwin 	    !curve25519(r->r_ss, l->l_private, r->r_public))
288744bfb21SJohn Baldwin 		bzero(r->r_ss, NOISE_PUBLIC_KEY_LEN);
289744bfb21SJohn Baldwin 	rw_wunlock(&r->r_handshake_lock);
290744bfb21SJohn Baldwin }
291744bfb21SJohn Baldwin 
292744bfb21SJohn Baldwin /* Remote configuration */
293744bfb21SJohn Baldwin struct noise_remote *
294744bfb21SJohn Baldwin noise_remote_alloc(struct noise_local *l, void *arg,
295744bfb21SJohn Baldwin     const uint8_t public[NOISE_PUBLIC_KEY_LEN])
296744bfb21SJohn Baldwin {
297744bfb21SJohn Baldwin 	struct noise_remote *r;
298744bfb21SJohn Baldwin 
299744bfb21SJohn Baldwin 	r = malloc(sizeof(*r), M_NOISE, M_WAITOK | M_ZERO);
300744bfb21SJohn Baldwin 	memcpy(r->r_public, public, NOISE_PUBLIC_KEY_LEN);
301744bfb21SJohn Baldwin 
302744bfb21SJohn Baldwin 	rw_init(&r->r_handshake_lock, "noise_handshake");
303744bfb21SJohn Baldwin 	r->r_handshake_state = HANDSHAKE_DEAD;
304744bfb21SJohn Baldwin 	r->r_last_sent = TIMER_RESET;
305744bfb21SJohn Baldwin 	r->r_last_init_recv = TIMER_RESET;
306744bfb21SJohn Baldwin 	noise_precompute_ss(l, r);
307744bfb21SJohn Baldwin 
308744bfb21SJohn Baldwin 	refcount_init(&r->r_refcnt, 1);
309744bfb21SJohn Baldwin 	r->r_local = noise_local_ref(l);
310744bfb21SJohn Baldwin 	r->r_arg = arg;
311744bfb21SJohn Baldwin 
312744bfb21SJohn Baldwin 	mtx_init(&r->r_keypair_mtx, "noise_keypair", NULL, MTX_DEF);
313744bfb21SJohn Baldwin 
314744bfb21SJohn Baldwin 	return (r);
315744bfb21SJohn Baldwin }
316744bfb21SJohn Baldwin 
317744bfb21SJohn Baldwin int
318744bfb21SJohn Baldwin noise_remote_enable(struct noise_remote *r)
319744bfb21SJohn Baldwin {
320744bfb21SJohn Baldwin 	struct noise_local *l = r->r_local;
321744bfb21SJohn Baldwin 	uint64_t idx;
322744bfb21SJohn Baldwin 	int ret = 0;
323744bfb21SJohn Baldwin 
324744bfb21SJohn Baldwin 	/* Insert to hashtable */
325744bfb21SJohn Baldwin 	idx = siphash24(l->l_hash_key, r->r_public, NOISE_PUBLIC_KEY_LEN) & HT_REMOTE_MASK;
326744bfb21SJohn Baldwin 
327744bfb21SJohn Baldwin 	mtx_lock(&l->l_remote_mtx);
328744bfb21SJohn Baldwin 	if (!r->r_entry_inserted) {
329744bfb21SJohn Baldwin 		if (l->l_remote_num < MAX_REMOTE_PER_LOCAL) {
330744bfb21SJohn Baldwin 			r->r_entry_inserted = true;
331744bfb21SJohn Baldwin 			l->l_remote_num++;
332744bfb21SJohn Baldwin 			CK_LIST_INSERT_HEAD(&l->l_remote_hash[idx], r, r_entry);
333744bfb21SJohn Baldwin 		} else {
334744bfb21SJohn Baldwin 			ret = ENOSPC;
335744bfb21SJohn Baldwin 		}
336744bfb21SJohn Baldwin 	}
337744bfb21SJohn Baldwin 	mtx_unlock(&l->l_remote_mtx);
338744bfb21SJohn Baldwin 
339744bfb21SJohn Baldwin 	return ret;
340744bfb21SJohn Baldwin }
341744bfb21SJohn Baldwin 
342744bfb21SJohn Baldwin void
343744bfb21SJohn Baldwin noise_remote_disable(struct noise_remote *r)
344744bfb21SJohn Baldwin {
345744bfb21SJohn Baldwin 	struct noise_local *l = r->r_local;
346744bfb21SJohn Baldwin 	/* remove from hashtable */
347744bfb21SJohn Baldwin 	mtx_lock(&l->l_remote_mtx);
348744bfb21SJohn Baldwin 	if (r->r_entry_inserted) {
349744bfb21SJohn Baldwin 		r->r_entry_inserted = false;
350744bfb21SJohn Baldwin 		CK_LIST_REMOVE(r, r_entry);
351744bfb21SJohn Baldwin 		l->l_remote_num--;
352744bfb21SJohn Baldwin 	};
353744bfb21SJohn Baldwin 	mtx_unlock(&l->l_remote_mtx);
354744bfb21SJohn Baldwin }
355744bfb21SJohn Baldwin 
356744bfb21SJohn Baldwin struct noise_remote *
357744bfb21SJohn Baldwin noise_remote_lookup(struct noise_local *l, const uint8_t public[NOISE_PUBLIC_KEY_LEN])
358744bfb21SJohn Baldwin {
359744bfb21SJohn Baldwin 	struct epoch_tracker et;
360744bfb21SJohn Baldwin 	struct noise_remote *r, *ret = NULL;
361744bfb21SJohn Baldwin 	uint64_t idx;
362744bfb21SJohn Baldwin 
363744bfb21SJohn Baldwin 	idx = siphash24(l->l_hash_key, public, NOISE_PUBLIC_KEY_LEN) & HT_REMOTE_MASK;
364744bfb21SJohn Baldwin 
365744bfb21SJohn Baldwin 	NET_EPOCH_ENTER(et);
366744bfb21SJohn Baldwin 	CK_LIST_FOREACH(r, &l->l_remote_hash[idx], r_entry) {
367744bfb21SJohn Baldwin 		if (timingsafe_bcmp(r->r_public, public, NOISE_PUBLIC_KEY_LEN) == 0) {
368744bfb21SJohn Baldwin 			if (refcount_acquire_if_not_zero(&r->r_refcnt))
369744bfb21SJohn Baldwin 				ret = r;
370744bfb21SJohn Baldwin 			break;
371744bfb21SJohn Baldwin 		}
372744bfb21SJohn Baldwin 	}
373744bfb21SJohn Baldwin 	NET_EPOCH_EXIT(et);
374744bfb21SJohn Baldwin 	return (ret);
375744bfb21SJohn Baldwin }
376744bfb21SJohn Baldwin 
377744bfb21SJohn Baldwin static void
378744bfb21SJohn Baldwin noise_remote_index_insert(struct noise_local *l, struct noise_remote *r)
379744bfb21SJohn Baldwin {
380744bfb21SJohn Baldwin 	struct noise_index *i, *r_i = &r->r_index;
381744bfb21SJohn Baldwin 	struct epoch_tracker et;
382744bfb21SJohn Baldwin 	uint32_t idx;
383744bfb21SJohn Baldwin 
384744bfb21SJohn Baldwin 	noise_remote_index_remove(l, r);
385744bfb21SJohn Baldwin 
386744bfb21SJohn Baldwin 	NET_EPOCH_ENTER(et);
387744bfb21SJohn Baldwin assign_id:
388744bfb21SJohn Baldwin 	r_i->i_local_index = arc4random();
389744bfb21SJohn Baldwin 	idx = r_i->i_local_index & HT_INDEX_MASK;
390744bfb21SJohn Baldwin 	CK_LIST_FOREACH(i, &l->l_index_hash[idx], i_entry) {
391744bfb21SJohn Baldwin 		if (i->i_local_index == r_i->i_local_index)
392744bfb21SJohn Baldwin 			goto assign_id;
393744bfb21SJohn Baldwin 	}
394744bfb21SJohn Baldwin 
395744bfb21SJohn Baldwin 	mtx_lock(&l->l_index_mtx);
396744bfb21SJohn Baldwin 	CK_LIST_FOREACH(i, &l->l_index_hash[idx], i_entry) {
397744bfb21SJohn Baldwin 		if (i->i_local_index == r_i->i_local_index) {
398744bfb21SJohn Baldwin 			mtx_unlock(&l->l_index_mtx);
399744bfb21SJohn Baldwin 			goto assign_id;
400744bfb21SJohn Baldwin 		}
401744bfb21SJohn Baldwin 	}
402744bfb21SJohn Baldwin 	CK_LIST_INSERT_HEAD(&l->l_index_hash[idx], r_i, i_entry);
403744bfb21SJohn Baldwin 	mtx_unlock(&l->l_index_mtx);
404744bfb21SJohn Baldwin 
405744bfb21SJohn Baldwin 	NET_EPOCH_EXIT(et);
406744bfb21SJohn Baldwin }
407744bfb21SJohn Baldwin 
408744bfb21SJohn Baldwin static struct noise_remote *
409744bfb21SJohn Baldwin noise_remote_index_lookup(struct noise_local *l, uint32_t idx0, bool lookup_keypair)
410744bfb21SJohn Baldwin {
411744bfb21SJohn Baldwin 	struct epoch_tracker et;
412744bfb21SJohn Baldwin 	struct noise_index *i;
413744bfb21SJohn Baldwin 	struct noise_keypair *kp;
414744bfb21SJohn Baldwin 	struct noise_remote *r, *ret = NULL;
415744bfb21SJohn Baldwin 	uint32_t idx = idx0 & HT_INDEX_MASK;
416744bfb21SJohn Baldwin 
417744bfb21SJohn Baldwin 	NET_EPOCH_ENTER(et);
418744bfb21SJohn Baldwin 	CK_LIST_FOREACH(i, &l->l_index_hash[idx], i_entry) {
419744bfb21SJohn Baldwin 		if (i->i_local_index == idx0) {
420744bfb21SJohn Baldwin 			if (!i->i_is_keypair) {
421744bfb21SJohn Baldwin 				r = (struct noise_remote *) i;
422744bfb21SJohn Baldwin 			} else if (lookup_keypair) {
423744bfb21SJohn Baldwin 				kp = (struct noise_keypair *) i;
424744bfb21SJohn Baldwin 				r = kp->kp_remote;
425744bfb21SJohn Baldwin 			} else {
426744bfb21SJohn Baldwin 				break;
427744bfb21SJohn Baldwin 			}
428744bfb21SJohn Baldwin 			if (refcount_acquire_if_not_zero(&r->r_refcnt))
429744bfb21SJohn Baldwin 				ret = r;
430744bfb21SJohn Baldwin 			break;
431744bfb21SJohn Baldwin 		}
432744bfb21SJohn Baldwin 	}
433744bfb21SJohn Baldwin 	NET_EPOCH_EXIT(et);
434744bfb21SJohn Baldwin 	return (ret);
435744bfb21SJohn Baldwin }
436744bfb21SJohn Baldwin 
437744bfb21SJohn Baldwin struct noise_remote *
438744bfb21SJohn Baldwin noise_remote_index(struct noise_local *l, uint32_t idx)
439744bfb21SJohn Baldwin {
440744bfb21SJohn Baldwin 	return noise_remote_index_lookup(l, idx, true);
441744bfb21SJohn Baldwin }
442744bfb21SJohn Baldwin 
443744bfb21SJohn Baldwin static int
444744bfb21SJohn Baldwin noise_remote_index_remove(struct noise_local *l, struct noise_remote *r)
445744bfb21SJohn Baldwin {
446744bfb21SJohn Baldwin 	rw_assert(&r->r_handshake_lock, RA_WLOCKED);
447744bfb21SJohn Baldwin 	if (r->r_handshake_state != HANDSHAKE_DEAD) {
448744bfb21SJohn Baldwin 		mtx_lock(&l->l_index_mtx);
449744bfb21SJohn Baldwin 		r->r_handshake_state = HANDSHAKE_DEAD;
450744bfb21SJohn Baldwin 		CK_LIST_REMOVE(&r->r_index, i_entry);
451744bfb21SJohn Baldwin 		mtx_unlock(&l->l_index_mtx);
452744bfb21SJohn Baldwin 		return (1);
453744bfb21SJohn Baldwin 	}
454744bfb21SJohn Baldwin 	return (0);
455744bfb21SJohn Baldwin }
456744bfb21SJohn Baldwin 
457744bfb21SJohn Baldwin struct noise_remote *
458744bfb21SJohn Baldwin noise_remote_ref(struct noise_remote *r)
459744bfb21SJohn Baldwin {
460744bfb21SJohn Baldwin 	refcount_acquire(&r->r_refcnt);
461744bfb21SJohn Baldwin 	return (r);
462744bfb21SJohn Baldwin }
463744bfb21SJohn Baldwin 
464744bfb21SJohn Baldwin static void
465744bfb21SJohn Baldwin noise_remote_smr_free(struct epoch_context *smr)
466744bfb21SJohn Baldwin {
467744bfb21SJohn Baldwin 	struct noise_remote *r;
468744bfb21SJohn Baldwin 	r = __containerof(smr, struct noise_remote, r_smr);
469744bfb21SJohn Baldwin 	if (r->r_cleanup != NULL)
470744bfb21SJohn Baldwin 		r->r_cleanup(r);
471744bfb21SJohn Baldwin 	noise_local_put(r->r_local);
472744bfb21SJohn Baldwin 	rw_destroy(&r->r_handshake_lock);
473744bfb21SJohn Baldwin 	mtx_destroy(&r->r_keypair_mtx);
474*dcf581bbSJohn Baldwin 	zfree(r, M_NOISE);
475744bfb21SJohn Baldwin }
476744bfb21SJohn Baldwin 
477744bfb21SJohn Baldwin void
478744bfb21SJohn Baldwin noise_remote_put(struct noise_remote *r)
479744bfb21SJohn Baldwin {
480744bfb21SJohn Baldwin 	if (refcount_release(&r->r_refcnt))
481744bfb21SJohn Baldwin 		NET_EPOCH_CALL(noise_remote_smr_free, &r->r_smr);
482744bfb21SJohn Baldwin }
483744bfb21SJohn Baldwin 
484744bfb21SJohn Baldwin void
485744bfb21SJohn Baldwin noise_remote_free(struct noise_remote *r, void (*cleanup)(struct noise_remote *))
486744bfb21SJohn Baldwin {
487744bfb21SJohn Baldwin 	r->r_cleanup = cleanup;
488744bfb21SJohn Baldwin 	noise_remote_disable(r);
489744bfb21SJohn Baldwin 
490744bfb21SJohn Baldwin 	/* now clear all keypairs and handshakes, then put this reference */
491744bfb21SJohn Baldwin 	noise_remote_handshake_clear(r);
492744bfb21SJohn Baldwin 	noise_remote_keypairs_clear(r);
493744bfb21SJohn Baldwin 	noise_remote_put(r);
494744bfb21SJohn Baldwin }
495744bfb21SJohn Baldwin 
496744bfb21SJohn Baldwin struct noise_local *
497744bfb21SJohn Baldwin noise_remote_local(struct noise_remote *r)
498744bfb21SJohn Baldwin {
499744bfb21SJohn Baldwin 	return (noise_local_ref(r->r_local));
500744bfb21SJohn Baldwin }
501744bfb21SJohn Baldwin 
502744bfb21SJohn Baldwin void *
503744bfb21SJohn Baldwin noise_remote_arg(struct noise_remote *r)
504744bfb21SJohn Baldwin {
505744bfb21SJohn Baldwin 	return (r->r_arg);
506744bfb21SJohn Baldwin }
507744bfb21SJohn Baldwin 
508744bfb21SJohn Baldwin void
509744bfb21SJohn Baldwin noise_remote_set_psk(struct noise_remote *r,
510744bfb21SJohn Baldwin     const uint8_t psk[NOISE_SYMMETRIC_KEY_LEN])
511744bfb21SJohn Baldwin {
512744bfb21SJohn Baldwin 	rw_wlock(&r->r_handshake_lock);
513744bfb21SJohn Baldwin 	if (psk == NULL)
514744bfb21SJohn Baldwin 		bzero(r->r_psk, NOISE_SYMMETRIC_KEY_LEN);
515744bfb21SJohn Baldwin 	else
516744bfb21SJohn Baldwin 		memcpy(r->r_psk, psk, NOISE_SYMMETRIC_KEY_LEN);
517744bfb21SJohn Baldwin 	rw_wunlock(&r->r_handshake_lock);
518744bfb21SJohn Baldwin }
519744bfb21SJohn Baldwin 
520744bfb21SJohn Baldwin int
521744bfb21SJohn Baldwin noise_remote_keys(struct noise_remote *r, uint8_t public[NOISE_PUBLIC_KEY_LEN],
522744bfb21SJohn Baldwin     uint8_t psk[NOISE_SYMMETRIC_KEY_LEN])
523744bfb21SJohn Baldwin {
524744bfb21SJohn Baldwin 	static uint8_t null_psk[NOISE_SYMMETRIC_KEY_LEN];
525744bfb21SJohn Baldwin 	int ret;
526744bfb21SJohn Baldwin 
527744bfb21SJohn Baldwin 	if (public != NULL)
528744bfb21SJohn Baldwin 		memcpy(public, r->r_public, NOISE_PUBLIC_KEY_LEN);
529744bfb21SJohn Baldwin 
530744bfb21SJohn Baldwin 	rw_rlock(&r->r_handshake_lock);
531744bfb21SJohn Baldwin 	if (psk != NULL)
532744bfb21SJohn Baldwin 		memcpy(psk, r->r_psk, NOISE_SYMMETRIC_KEY_LEN);
533744bfb21SJohn Baldwin 	ret = timingsafe_bcmp(r->r_psk, null_psk, NOISE_SYMMETRIC_KEY_LEN);
534744bfb21SJohn Baldwin 	rw_runlock(&r->r_handshake_lock);
535744bfb21SJohn Baldwin 
536744bfb21SJohn Baldwin 	return (ret ? 0 : ENOENT);
537744bfb21SJohn Baldwin }
538744bfb21SJohn Baldwin 
539744bfb21SJohn Baldwin int
540744bfb21SJohn Baldwin noise_remote_initiation_expired(struct noise_remote *r)
541744bfb21SJohn Baldwin {
542744bfb21SJohn Baldwin 	int expired;
543744bfb21SJohn Baldwin 	rw_rlock(&r->r_handshake_lock);
544744bfb21SJohn Baldwin 	expired = noise_timer_expired(r->r_last_sent, REKEY_TIMEOUT, 0);
545744bfb21SJohn Baldwin 	rw_runlock(&r->r_handshake_lock);
546744bfb21SJohn Baldwin 	return (expired);
547744bfb21SJohn Baldwin }
548744bfb21SJohn Baldwin 
549744bfb21SJohn Baldwin void
550744bfb21SJohn Baldwin noise_remote_handshake_clear(struct noise_remote *r)
551744bfb21SJohn Baldwin {
552744bfb21SJohn Baldwin 	rw_wlock(&r->r_handshake_lock);
553744bfb21SJohn Baldwin 	if (noise_remote_index_remove(r->r_local, r))
554744bfb21SJohn Baldwin 		bzero(&r->r_handshake, sizeof(r->r_handshake));
555744bfb21SJohn Baldwin 	r->r_last_sent = TIMER_RESET;
556744bfb21SJohn Baldwin 	rw_wunlock(&r->r_handshake_lock);
557744bfb21SJohn Baldwin }
558744bfb21SJohn Baldwin 
559744bfb21SJohn Baldwin void
560744bfb21SJohn Baldwin noise_remote_keypairs_clear(struct noise_remote *r)
561744bfb21SJohn Baldwin {
562744bfb21SJohn Baldwin 	struct noise_keypair *kp;
563744bfb21SJohn Baldwin 
564744bfb21SJohn Baldwin 	mtx_lock(&r->r_keypair_mtx);
565e32e1a16SJohn Baldwin 	kp = atomic_load_ptr(&r->r_next);
566e32e1a16SJohn Baldwin 	atomic_store_ptr(&r->r_next, NULL);
567744bfb21SJohn Baldwin 	noise_keypair_drop(kp);
568744bfb21SJohn Baldwin 
569e32e1a16SJohn Baldwin 	kp = atomic_load_ptr(&r->r_current);
570e32e1a16SJohn Baldwin 	atomic_store_ptr(&r->r_current, NULL);
571744bfb21SJohn Baldwin 	noise_keypair_drop(kp);
572744bfb21SJohn Baldwin 
573e32e1a16SJohn Baldwin 	kp = atomic_load_ptr(&r->r_previous);
574e32e1a16SJohn Baldwin 	atomic_store_ptr(&r->r_previous, NULL);
575744bfb21SJohn Baldwin 	noise_keypair_drop(kp);
576744bfb21SJohn Baldwin 	mtx_unlock(&r->r_keypair_mtx);
577744bfb21SJohn Baldwin }
578744bfb21SJohn Baldwin 
579744bfb21SJohn Baldwin static void
580744bfb21SJohn Baldwin noise_remote_expire_current(struct noise_remote *r)
581744bfb21SJohn Baldwin {
582744bfb21SJohn Baldwin 	struct epoch_tracker et;
583744bfb21SJohn Baldwin 	struct noise_keypair *kp;
584744bfb21SJohn Baldwin 
585744bfb21SJohn Baldwin 	noise_remote_handshake_clear(r);
586744bfb21SJohn Baldwin 
587744bfb21SJohn Baldwin 	NET_EPOCH_ENTER(et);
588e32e1a16SJohn Baldwin 	kp = atomic_load_ptr(&r->r_next);
589744bfb21SJohn Baldwin 	if (kp != NULL)
590e32e1a16SJohn Baldwin 		atomic_store_bool(&kp->kp_can_send, false);
591e32e1a16SJohn Baldwin 	kp = atomic_load_ptr(&r->r_current);
592744bfb21SJohn Baldwin 	if (kp != NULL)
593e32e1a16SJohn Baldwin 		atomic_store_bool(&kp->kp_can_send, false);
594744bfb21SJohn Baldwin 	NET_EPOCH_EXIT(et);
595744bfb21SJohn Baldwin }
596744bfb21SJohn Baldwin 
597744bfb21SJohn Baldwin /* Keypair functions */
598744bfb21SJohn Baldwin static void
599744bfb21SJohn Baldwin noise_add_new_keypair(struct noise_local *l, struct noise_remote *r,
600744bfb21SJohn Baldwin     struct noise_keypair *kp)
601744bfb21SJohn Baldwin {
602744bfb21SJohn Baldwin 	struct noise_keypair *next, *current, *previous;
603744bfb21SJohn Baldwin 	struct noise_index *r_i = &r->r_index;
604744bfb21SJohn Baldwin 
605744bfb21SJohn Baldwin 	/* Insert into the keypair table */
606744bfb21SJohn Baldwin 	mtx_lock(&r->r_keypair_mtx);
607e32e1a16SJohn Baldwin 	next = atomic_load_ptr(&r->r_next);
608e32e1a16SJohn Baldwin 	current = atomic_load_ptr(&r->r_current);
609e32e1a16SJohn Baldwin 	previous = atomic_load_ptr(&r->r_previous);
610744bfb21SJohn Baldwin 
611744bfb21SJohn Baldwin 	if (kp->kp_is_initiator) {
612744bfb21SJohn Baldwin 		if (next != NULL) {
613e32e1a16SJohn Baldwin 			atomic_store_ptr(&r->r_next, NULL);
614e32e1a16SJohn Baldwin 			atomic_store_ptr(&r->r_previous, next);
615744bfb21SJohn Baldwin 			noise_keypair_drop(current);
616744bfb21SJohn Baldwin 		} else {
617e32e1a16SJohn Baldwin 			atomic_store_ptr(&r->r_previous, current);
618744bfb21SJohn Baldwin 		}
619744bfb21SJohn Baldwin 		noise_keypair_drop(previous);
620e32e1a16SJohn Baldwin 		atomic_store_ptr(&r->r_current, kp);
621744bfb21SJohn Baldwin 	} else {
622e32e1a16SJohn Baldwin 		atomic_store_ptr(&r->r_next, kp);
623744bfb21SJohn Baldwin 		noise_keypair_drop(next);
624e32e1a16SJohn Baldwin 		atomic_store_ptr(&r->r_previous, NULL);
625744bfb21SJohn Baldwin 		noise_keypair_drop(previous);
626744bfb21SJohn Baldwin 
627744bfb21SJohn Baldwin 	}
628744bfb21SJohn Baldwin 	mtx_unlock(&r->r_keypair_mtx);
629744bfb21SJohn Baldwin 
630744bfb21SJohn Baldwin 	/* Insert into index table */
631744bfb21SJohn Baldwin 	rw_assert(&r->r_handshake_lock, RA_WLOCKED);
632744bfb21SJohn Baldwin 
633744bfb21SJohn Baldwin 	kp->kp_index.i_is_keypair = true;
634744bfb21SJohn Baldwin 	kp->kp_index.i_local_index = r_i->i_local_index;
635744bfb21SJohn Baldwin 	kp->kp_index.i_remote_index = r_i->i_remote_index;
636744bfb21SJohn Baldwin 
637744bfb21SJohn Baldwin 	mtx_lock(&l->l_index_mtx);
638744bfb21SJohn Baldwin 	CK_LIST_INSERT_BEFORE(r_i, &kp->kp_index, i_entry);
639744bfb21SJohn Baldwin 	r->r_handshake_state = HANDSHAKE_DEAD;
640744bfb21SJohn Baldwin 	CK_LIST_REMOVE(r_i, i_entry);
641744bfb21SJohn Baldwin 	mtx_unlock(&l->l_index_mtx);
642744bfb21SJohn Baldwin 
643744bfb21SJohn Baldwin 	explicit_bzero(&r->r_handshake, sizeof(r->r_handshake));
644744bfb21SJohn Baldwin }
645744bfb21SJohn Baldwin 
646744bfb21SJohn Baldwin static int
647744bfb21SJohn Baldwin noise_begin_session(struct noise_remote *r)
648744bfb21SJohn Baldwin {
649744bfb21SJohn Baldwin 	struct noise_keypair *kp;
650744bfb21SJohn Baldwin 
651744bfb21SJohn Baldwin 	rw_assert(&r->r_handshake_lock, RA_WLOCKED);
652744bfb21SJohn Baldwin 
653744bfb21SJohn Baldwin 	if ((kp = malloc(sizeof(*kp), M_NOISE, M_NOWAIT | M_ZERO)) == NULL)
654744bfb21SJohn Baldwin 		return (ENOSPC);
655744bfb21SJohn Baldwin 
656744bfb21SJohn Baldwin 	refcount_init(&kp->kp_refcnt, 1);
657744bfb21SJohn Baldwin 	kp->kp_can_send = true;
658744bfb21SJohn Baldwin 	kp->kp_is_initiator = r->r_handshake_state == HANDSHAKE_INITIATOR;
659744bfb21SJohn Baldwin 	kp->kp_birthdate = getsbinuptime();
660744bfb21SJohn Baldwin 	kp->kp_remote = noise_remote_ref(r);
661744bfb21SJohn Baldwin 
662744bfb21SJohn Baldwin 	if (kp->kp_is_initiator)
663744bfb21SJohn Baldwin 		noise_kdf(kp->kp_send, kp->kp_recv, NULL, NULL,
664744bfb21SJohn Baldwin 		    NOISE_SYMMETRIC_KEY_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, 0,
665744bfb21SJohn Baldwin 		    r->r_handshake.hs_ck);
666744bfb21SJohn Baldwin 	else
667744bfb21SJohn Baldwin 		noise_kdf(kp->kp_recv, kp->kp_send, NULL, NULL,
668744bfb21SJohn Baldwin 		    NOISE_SYMMETRIC_KEY_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, 0,
669744bfb21SJohn Baldwin 		    r->r_handshake.hs_ck);
670744bfb21SJohn Baldwin 
671744bfb21SJohn Baldwin 	rw_init(&kp->kp_nonce_lock, "noise_nonce");
672744bfb21SJohn Baldwin 
673744bfb21SJohn Baldwin 	noise_add_new_keypair(r->r_local, r, kp);
674744bfb21SJohn Baldwin 	return (0);
675744bfb21SJohn Baldwin }
676744bfb21SJohn Baldwin 
677744bfb21SJohn Baldwin struct noise_keypair *
678744bfb21SJohn Baldwin noise_keypair_lookup(struct noise_local *l, uint32_t idx0)
679744bfb21SJohn Baldwin {
680744bfb21SJohn Baldwin 	struct epoch_tracker et;
681744bfb21SJohn Baldwin 	struct noise_index *i;
682744bfb21SJohn Baldwin 	struct noise_keypair *kp, *ret = NULL;
683744bfb21SJohn Baldwin 	uint32_t idx = idx0 & HT_INDEX_MASK;
684744bfb21SJohn Baldwin 
685744bfb21SJohn Baldwin 	NET_EPOCH_ENTER(et);
686744bfb21SJohn Baldwin 	CK_LIST_FOREACH(i, &l->l_index_hash[idx], i_entry) {
687744bfb21SJohn Baldwin 		if (i->i_local_index == idx0 && i->i_is_keypair) {
688744bfb21SJohn Baldwin 			kp = (struct noise_keypair *) i;
689744bfb21SJohn Baldwin 			if (refcount_acquire_if_not_zero(&kp->kp_refcnt))
690744bfb21SJohn Baldwin 				ret = kp;
691744bfb21SJohn Baldwin 			break;
692744bfb21SJohn Baldwin 		}
693744bfb21SJohn Baldwin 	}
694744bfb21SJohn Baldwin 	NET_EPOCH_EXIT(et);
695744bfb21SJohn Baldwin 	return (ret);
696744bfb21SJohn Baldwin }
697744bfb21SJohn Baldwin 
698744bfb21SJohn Baldwin struct noise_keypair *
699744bfb21SJohn Baldwin noise_keypair_current(struct noise_remote *r)
700744bfb21SJohn Baldwin {
701744bfb21SJohn Baldwin 	struct epoch_tracker et;
702744bfb21SJohn Baldwin 	struct noise_keypair *kp, *ret = NULL;
703744bfb21SJohn Baldwin 
704744bfb21SJohn Baldwin 	NET_EPOCH_ENTER(et);
705e32e1a16SJohn Baldwin 	kp = atomic_load_ptr(&r->r_current);
706e32e1a16SJohn Baldwin 	if (kp != NULL && atomic_load_bool(&kp->kp_can_send)) {
707744bfb21SJohn Baldwin 		if (noise_timer_expired(kp->kp_birthdate, REJECT_AFTER_TIME, 0))
708e32e1a16SJohn Baldwin 			atomic_store_bool(&kp->kp_can_send, false);
709744bfb21SJohn Baldwin 		else if (refcount_acquire_if_not_zero(&kp->kp_refcnt))
710744bfb21SJohn Baldwin 			ret = kp;
711744bfb21SJohn Baldwin 	}
712744bfb21SJohn Baldwin 	NET_EPOCH_EXIT(et);
713744bfb21SJohn Baldwin 	return (ret);
714744bfb21SJohn Baldwin }
715744bfb21SJohn Baldwin 
716744bfb21SJohn Baldwin struct noise_keypair *
717744bfb21SJohn Baldwin noise_keypair_ref(struct noise_keypair *kp)
718744bfb21SJohn Baldwin {
719744bfb21SJohn Baldwin 	refcount_acquire(&kp->kp_refcnt);
720744bfb21SJohn Baldwin 	return (kp);
721744bfb21SJohn Baldwin }
722744bfb21SJohn Baldwin 
723744bfb21SJohn Baldwin int
724744bfb21SJohn Baldwin noise_keypair_received_with(struct noise_keypair *kp)
725744bfb21SJohn Baldwin {
726744bfb21SJohn Baldwin 	struct noise_keypair *old;
727744bfb21SJohn Baldwin 	struct noise_remote *r = kp->kp_remote;
728744bfb21SJohn Baldwin 
729e32e1a16SJohn Baldwin 	if (kp != atomic_load_ptr(&r->r_next))
730744bfb21SJohn Baldwin 		return (0);
731744bfb21SJohn Baldwin 
732744bfb21SJohn Baldwin 	mtx_lock(&r->r_keypair_mtx);
733e32e1a16SJohn Baldwin 	if (kp != atomic_load_ptr(&r->r_next)) {
734744bfb21SJohn Baldwin 		mtx_unlock(&r->r_keypair_mtx);
735744bfb21SJohn Baldwin 		return (0);
736744bfb21SJohn Baldwin 	}
737744bfb21SJohn Baldwin 
738e32e1a16SJohn Baldwin 	old = atomic_load_ptr(&r->r_previous);
739e32e1a16SJohn Baldwin 	atomic_store_ptr(&r->r_previous, atomic_load_ptr(&r->r_current));
740744bfb21SJohn Baldwin 	noise_keypair_drop(old);
741e32e1a16SJohn Baldwin 	atomic_store_ptr(&r->r_current, kp);
742e32e1a16SJohn Baldwin 	atomic_store_ptr(&r->r_next, NULL);
743744bfb21SJohn Baldwin 	mtx_unlock(&r->r_keypair_mtx);
744744bfb21SJohn Baldwin 
745744bfb21SJohn Baldwin 	return (ECONNRESET);
746744bfb21SJohn Baldwin }
747744bfb21SJohn Baldwin 
748744bfb21SJohn Baldwin static void
749744bfb21SJohn Baldwin noise_keypair_smr_free(struct epoch_context *smr)
750744bfb21SJohn Baldwin {
751744bfb21SJohn Baldwin 	struct noise_keypair *kp;
752744bfb21SJohn Baldwin 	kp = __containerof(smr, struct noise_keypair, kp_smr);
753744bfb21SJohn Baldwin 	noise_remote_put(kp->kp_remote);
754744bfb21SJohn Baldwin 	rw_destroy(&kp->kp_nonce_lock);
755*dcf581bbSJohn Baldwin 	zfree(kp, M_NOISE);
756744bfb21SJohn Baldwin }
757744bfb21SJohn Baldwin 
758744bfb21SJohn Baldwin void
759744bfb21SJohn Baldwin noise_keypair_put(struct noise_keypair *kp)
760744bfb21SJohn Baldwin {
761744bfb21SJohn Baldwin 	if (refcount_release(&kp->kp_refcnt))
762744bfb21SJohn Baldwin 		NET_EPOCH_CALL(noise_keypair_smr_free, &kp->kp_smr);
763744bfb21SJohn Baldwin }
764744bfb21SJohn Baldwin 
765744bfb21SJohn Baldwin static void
766744bfb21SJohn Baldwin noise_keypair_drop(struct noise_keypair *kp)
767744bfb21SJohn Baldwin {
768744bfb21SJohn Baldwin 	struct noise_remote *r;
769744bfb21SJohn Baldwin 	struct noise_local *l;
770744bfb21SJohn Baldwin 
771744bfb21SJohn Baldwin 	if (kp == NULL)
772744bfb21SJohn Baldwin 		return;
773744bfb21SJohn Baldwin 
774744bfb21SJohn Baldwin 	r = kp->kp_remote;
775744bfb21SJohn Baldwin 	l = r->r_local;
776744bfb21SJohn Baldwin 
777744bfb21SJohn Baldwin 	mtx_lock(&l->l_index_mtx);
778744bfb21SJohn Baldwin 	CK_LIST_REMOVE(&kp->kp_index, i_entry);
779744bfb21SJohn Baldwin 	mtx_unlock(&l->l_index_mtx);
780744bfb21SJohn Baldwin 
781744bfb21SJohn Baldwin 	noise_keypair_put(kp);
782744bfb21SJohn Baldwin }
783744bfb21SJohn Baldwin 
784744bfb21SJohn Baldwin struct noise_remote *
785744bfb21SJohn Baldwin noise_keypair_remote(struct noise_keypair *kp)
786744bfb21SJohn Baldwin {
787744bfb21SJohn Baldwin 	return (noise_remote_ref(kp->kp_remote));
788744bfb21SJohn Baldwin }
789744bfb21SJohn Baldwin 
790744bfb21SJohn Baldwin int
791744bfb21SJohn Baldwin noise_keypair_nonce_next(struct noise_keypair *kp, uint64_t *send)
792744bfb21SJohn Baldwin {
793e32e1a16SJohn Baldwin 	if (!atomic_load_bool(&kp->kp_can_send))
794744bfb21SJohn Baldwin 		return (EINVAL);
795744bfb21SJohn Baldwin 
796744bfb21SJohn Baldwin #ifdef __LP64__
797e32e1a16SJohn Baldwin 	*send = atomic_fetchadd_64(&kp->kp_nonce_send, 1);
798744bfb21SJohn Baldwin #else
799744bfb21SJohn Baldwin 	rw_wlock(&kp->kp_nonce_lock);
800744bfb21SJohn Baldwin 	*send = kp->kp_nonce_send++;
801744bfb21SJohn Baldwin 	rw_wunlock(&kp->kp_nonce_lock);
802744bfb21SJohn Baldwin #endif
803744bfb21SJohn Baldwin 	if (*send < REJECT_AFTER_MESSAGES)
804744bfb21SJohn Baldwin 		return (0);
805e32e1a16SJohn Baldwin 	atomic_store_bool(&kp->kp_can_send, false);
806744bfb21SJohn Baldwin 	return (EINVAL);
807744bfb21SJohn Baldwin }
808744bfb21SJohn Baldwin 
809744bfb21SJohn Baldwin int
810744bfb21SJohn Baldwin noise_keypair_nonce_check(struct noise_keypair *kp, uint64_t recv)
811744bfb21SJohn Baldwin {
812744bfb21SJohn Baldwin 	unsigned long index, index_current, top, i, bit;
813744bfb21SJohn Baldwin 	int ret = EEXIST;
814744bfb21SJohn Baldwin 
815744bfb21SJohn Baldwin 	rw_wlock(&kp->kp_nonce_lock);
816744bfb21SJohn Baldwin 
817744bfb21SJohn Baldwin 	if (__predict_false(kp->kp_nonce_recv >= REJECT_AFTER_MESSAGES + 1 ||
818744bfb21SJohn Baldwin 			    recv >= REJECT_AFTER_MESSAGES))
819744bfb21SJohn Baldwin 		goto error;
820744bfb21SJohn Baldwin 
821744bfb21SJohn Baldwin 	++recv;
822744bfb21SJohn Baldwin 
823744bfb21SJohn Baldwin 	if (__predict_false(recv + COUNTER_WINDOW_SIZE < kp->kp_nonce_recv))
824744bfb21SJohn Baldwin 		goto error;
825744bfb21SJohn Baldwin 
826744bfb21SJohn Baldwin 	index = recv >> COUNTER_ORDER;
827744bfb21SJohn Baldwin 
828744bfb21SJohn Baldwin 	if (__predict_true(recv > kp->kp_nonce_recv)) {
829744bfb21SJohn Baldwin 		index_current = kp->kp_nonce_recv >> COUNTER_ORDER;
830744bfb21SJohn Baldwin 		top = MIN(index - index_current, COUNTER_BITS_TOTAL / COUNTER_BITS);
831744bfb21SJohn Baldwin 		for (i = 1; i <= top; i++)
832744bfb21SJohn Baldwin 			kp->kp_backtrack[
833744bfb21SJohn Baldwin 			    (i + index_current) &
834744bfb21SJohn Baldwin 				((COUNTER_BITS_TOTAL / COUNTER_BITS) - 1)] = 0;
835744bfb21SJohn Baldwin #ifdef __LP64__
836e32e1a16SJohn Baldwin 		atomic_store_64(&kp->kp_nonce_recv, recv);
837744bfb21SJohn Baldwin #else
838744bfb21SJohn Baldwin 		kp->kp_nonce_recv = recv;
839744bfb21SJohn Baldwin #endif
840744bfb21SJohn Baldwin 	}
841744bfb21SJohn Baldwin 
842744bfb21SJohn Baldwin 	index &= (COUNTER_BITS_TOTAL / COUNTER_BITS) - 1;
843744bfb21SJohn Baldwin 	bit = 1ul << (recv & (COUNTER_BITS - 1));
844744bfb21SJohn Baldwin 	if (kp->kp_backtrack[index] & bit)
845744bfb21SJohn Baldwin 		goto error;
846744bfb21SJohn Baldwin 
847744bfb21SJohn Baldwin 	kp->kp_backtrack[index] |= bit;
848744bfb21SJohn Baldwin 	ret = 0;
849744bfb21SJohn Baldwin error:
850744bfb21SJohn Baldwin 	rw_wunlock(&kp->kp_nonce_lock);
851744bfb21SJohn Baldwin 	return (ret);
852744bfb21SJohn Baldwin }
853744bfb21SJohn Baldwin 
854744bfb21SJohn Baldwin int
855744bfb21SJohn Baldwin noise_keep_key_fresh_send(struct noise_remote *r)
856744bfb21SJohn Baldwin {
857744bfb21SJohn Baldwin 	struct epoch_tracker et;
858744bfb21SJohn Baldwin 	struct noise_keypair *current;
859744bfb21SJohn Baldwin 	int keep_key_fresh;
860744bfb21SJohn Baldwin 	uint64_t nonce;
861744bfb21SJohn Baldwin 
862744bfb21SJohn Baldwin 	NET_EPOCH_ENTER(et);
863e32e1a16SJohn Baldwin 	current = atomic_load_ptr(&r->r_current);
864e32e1a16SJohn Baldwin 	keep_key_fresh = current != NULL && atomic_load_bool(&current->kp_can_send);
865744bfb21SJohn Baldwin 	if (!keep_key_fresh)
866744bfb21SJohn Baldwin 		goto out;
867744bfb21SJohn Baldwin #ifdef __LP64__
868e32e1a16SJohn Baldwin 	nonce = atomic_load_64(&current->kp_nonce_send);
869744bfb21SJohn Baldwin #else
870744bfb21SJohn Baldwin 	rw_rlock(&current->kp_nonce_lock);
871744bfb21SJohn Baldwin 	nonce = current->kp_nonce_send;
872744bfb21SJohn Baldwin 	rw_runlock(&current->kp_nonce_lock);
873744bfb21SJohn Baldwin #endif
874744bfb21SJohn Baldwin 	keep_key_fresh = nonce > REKEY_AFTER_MESSAGES;
875744bfb21SJohn Baldwin 	if (keep_key_fresh)
876744bfb21SJohn Baldwin 		goto out;
877744bfb21SJohn Baldwin 	keep_key_fresh = current->kp_is_initiator && noise_timer_expired(current->kp_birthdate, REKEY_AFTER_TIME, 0);
878744bfb21SJohn Baldwin 
879744bfb21SJohn Baldwin out:
880744bfb21SJohn Baldwin 	NET_EPOCH_EXIT(et);
881744bfb21SJohn Baldwin 	return (keep_key_fresh ? ESTALE : 0);
882744bfb21SJohn Baldwin }
883744bfb21SJohn Baldwin 
884744bfb21SJohn Baldwin int
885744bfb21SJohn Baldwin noise_keep_key_fresh_recv(struct noise_remote *r)
886744bfb21SJohn Baldwin {
887744bfb21SJohn Baldwin 	struct epoch_tracker et;
888744bfb21SJohn Baldwin 	struct noise_keypair *current;
889744bfb21SJohn Baldwin 	int keep_key_fresh;
890744bfb21SJohn Baldwin 
891744bfb21SJohn Baldwin 	NET_EPOCH_ENTER(et);
892e32e1a16SJohn Baldwin 	current = atomic_load_ptr(&r->r_current);
893e32e1a16SJohn Baldwin 	keep_key_fresh = current != NULL && atomic_load_bool(&current->kp_can_send) &&
894744bfb21SJohn Baldwin 	    current->kp_is_initiator && noise_timer_expired(current->kp_birthdate,
895744bfb21SJohn Baldwin 	    REJECT_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT, 0);
896744bfb21SJohn Baldwin 	NET_EPOCH_EXIT(et);
897744bfb21SJohn Baldwin 
898744bfb21SJohn Baldwin 	return (keep_key_fresh ? ESTALE : 0);
899744bfb21SJohn Baldwin }
900744bfb21SJohn Baldwin 
901744bfb21SJohn Baldwin int
902744bfb21SJohn Baldwin noise_keypair_encrypt(struct noise_keypair *kp, uint32_t *r_idx, uint64_t nonce, struct mbuf *m)
903744bfb21SJohn Baldwin {
904744bfb21SJohn Baldwin 	int ret;
905744bfb21SJohn Baldwin 
906744bfb21SJohn Baldwin 	ret = chacha20poly1305_encrypt_mbuf(m, nonce, kp->kp_send);
907744bfb21SJohn Baldwin 	if (ret)
908744bfb21SJohn Baldwin 		return (ret);
909744bfb21SJohn Baldwin 
910744bfb21SJohn Baldwin 	*r_idx = kp->kp_index.i_remote_index;
911744bfb21SJohn Baldwin 	return (0);
912744bfb21SJohn Baldwin }
913744bfb21SJohn Baldwin 
914744bfb21SJohn Baldwin int
915744bfb21SJohn Baldwin noise_keypair_decrypt(struct noise_keypair *kp, uint64_t nonce, struct mbuf *m)
916744bfb21SJohn Baldwin {
917744bfb21SJohn Baldwin 	uint64_t cur_nonce;
918744bfb21SJohn Baldwin 	int ret;
919744bfb21SJohn Baldwin 
920744bfb21SJohn Baldwin #ifdef __LP64__
921e32e1a16SJohn Baldwin 	cur_nonce = atomic_load_64(&kp->kp_nonce_recv);
922744bfb21SJohn Baldwin #else
923744bfb21SJohn Baldwin 	rw_rlock(&kp->kp_nonce_lock);
924744bfb21SJohn Baldwin 	cur_nonce = kp->kp_nonce_recv;
925744bfb21SJohn Baldwin 	rw_runlock(&kp->kp_nonce_lock);
926744bfb21SJohn Baldwin #endif
927744bfb21SJohn Baldwin 
928744bfb21SJohn Baldwin 	if (cur_nonce >= REJECT_AFTER_MESSAGES ||
929744bfb21SJohn Baldwin 	    noise_timer_expired(kp->kp_birthdate, REJECT_AFTER_TIME, 0))
930744bfb21SJohn Baldwin 		return (EINVAL);
931744bfb21SJohn Baldwin 
932744bfb21SJohn Baldwin 	ret = chacha20poly1305_decrypt_mbuf(m, nonce, kp->kp_recv);
933744bfb21SJohn Baldwin 	if (ret)
934744bfb21SJohn Baldwin 		return (ret);
935744bfb21SJohn Baldwin 
936744bfb21SJohn Baldwin 	return (0);
937744bfb21SJohn Baldwin }
938744bfb21SJohn Baldwin 
939744bfb21SJohn Baldwin /* Handshake functions */
940744bfb21SJohn Baldwin int
941744bfb21SJohn Baldwin noise_create_initiation(struct noise_remote *r,
942744bfb21SJohn Baldwin     uint32_t *s_idx,
943744bfb21SJohn Baldwin     uint8_t ue[NOISE_PUBLIC_KEY_LEN],
944744bfb21SJohn Baldwin     uint8_t es[NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN],
945744bfb21SJohn Baldwin     uint8_t ets[NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN])
946744bfb21SJohn Baldwin {
947744bfb21SJohn Baldwin 	struct noise_handshake *hs = &r->r_handshake;
948744bfb21SJohn Baldwin 	struct noise_local *l = r->r_local;
949744bfb21SJohn Baldwin 	uint8_t key[NOISE_SYMMETRIC_KEY_LEN];
950744bfb21SJohn Baldwin 	int ret = EINVAL;
951744bfb21SJohn Baldwin 
952744bfb21SJohn Baldwin 	rw_rlock(&l->l_identity_lock);
953744bfb21SJohn Baldwin 	rw_wlock(&r->r_handshake_lock);
954744bfb21SJohn Baldwin 	if (!l->l_has_identity)
955744bfb21SJohn Baldwin 		goto error;
956744bfb21SJohn Baldwin 	if (!noise_timer_expired(r->r_last_sent, REKEY_TIMEOUT, 0))
957744bfb21SJohn Baldwin 		goto error;
958744bfb21SJohn Baldwin 	noise_param_init(hs->hs_ck, hs->hs_hash, r->r_public);
959744bfb21SJohn Baldwin 
960744bfb21SJohn Baldwin 	/* e */
961744bfb21SJohn Baldwin 	curve25519_generate_secret(hs->hs_e);
962744bfb21SJohn Baldwin 	if (curve25519_generate_public(ue, hs->hs_e) == 0)
963744bfb21SJohn Baldwin 		goto error;
964744bfb21SJohn Baldwin 	noise_msg_ephemeral(hs->hs_ck, hs->hs_hash, ue);
965744bfb21SJohn Baldwin 
966744bfb21SJohn Baldwin 	/* es */
967744bfb21SJohn Baldwin 	if (noise_mix_dh(hs->hs_ck, key, hs->hs_e, r->r_public) != 0)
968744bfb21SJohn Baldwin 		goto error;
969744bfb21SJohn Baldwin 
970744bfb21SJohn Baldwin 	/* s */
971744bfb21SJohn Baldwin 	noise_msg_encrypt(es, l->l_public,
972744bfb21SJohn Baldwin 	    NOISE_PUBLIC_KEY_LEN, key, hs->hs_hash);
973744bfb21SJohn Baldwin 
974744bfb21SJohn Baldwin 	/* ss */
975744bfb21SJohn Baldwin 	if (noise_mix_ss(hs->hs_ck, key, r->r_ss) != 0)
976744bfb21SJohn Baldwin 		goto error;
977744bfb21SJohn Baldwin 
978744bfb21SJohn Baldwin 	/* {t} */
979744bfb21SJohn Baldwin 	noise_tai64n_now(ets);
980744bfb21SJohn Baldwin 	noise_msg_encrypt(ets, ets,
981744bfb21SJohn Baldwin 	    NOISE_TIMESTAMP_LEN, key, hs->hs_hash);
982744bfb21SJohn Baldwin 
983744bfb21SJohn Baldwin 	noise_remote_index_insert(l, r);
984744bfb21SJohn Baldwin 	r->r_handshake_state = HANDSHAKE_INITIATOR;
985744bfb21SJohn Baldwin 	r->r_last_sent = getsbinuptime();
986744bfb21SJohn Baldwin 	*s_idx = r->r_index.i_local_index;
987744bfb21SJohn Baldwin 	ret = 0;
988744bfb21SJohn Baldwin error:
989744bfb21SJohn Baldwin 	rw_wunlock(&r->r_handshake_lock);
990744bfb21SJohn Baldwin 	rw_runlock(&l->l_identity_lock);
991744bfb21SJohn Baldwin 	explicit_bzero(key, NOISE_SYMMETRIC_KEY_LEN);
992744bfb21SJohn Baldwin 	return (ret);
993744bfb21SJohn Baldwin }
994744bfb21SJohn Baldwin 
995744bfb21SJohn Baldwin int
996744bfb21SJohn Baldwin noise_consume_initiation(struct noise_local *l, struct noise_remote **rp,
997744bfb21SJohn Baldwin     uint32_t s_idx,
998744bfb21SJohn Baldwin     uint8_t ue[NOISE_PUBLIC_KEY_LEN],
999744bfb21SJohn Baldwin     uint8_t es[NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN],
1000744bfb21SJohn Baldwin     uint8_t ets[NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN])
1001744bfb21SJohn Baldwin {
1002744bfb21SJohn Baldwin 	struct noise_remote *r;
1003744bfb21SJohn Baldwin 	struct noise_handshake hs;
1004744bfb21SJohn Baldwin 	uint8_t key[NOISE_SYMMETRIC_KEY_LEN];
1005744bfb21SJohn Baldwin 	uint8_t r_public[NOISE_PUBLIC_KEY_LEN];
1006744bfb21SJohn Baldwin 	uint8_t	timestamp[NOISE_TIMESTAMP_LEN];
1007744bfb21SJohn Baldwin 	int ret = EINVAL;
1008744bfb21SJohn Baldwin 
1009744bfb21SJohn Baldwin 	rw_rlock(&l->l_identity_lock);
1010744bfb21SJohn Baldwin 	if (!l->l_has_identity)
1011744bfb21SJohn Baldwin 		goto error;
1012744bfb21SJohn Baldwin 	noise_param_init(hs.hs_ck, hs.hs_hash, l->l_public);
1013744bfb21SJohn Baldwin 
1014744bfb21SJohn Baldwin 	/* e */
1015744bfb21SJohn Baldwin 	noise_msg_ephemeral(hs.hs_ck, hs.hs_hash, ue);
1016744bfb21SJohn Baldwin 
1017744bfb21SJohn Baldwin 	/* es */
1018744bfb21SJohn Baldwin 	if (noise_mix_dh(hs.hs_ck, key, l->l_private, ue) != 0)
1019744bfb21SJohn Baldwin 		goto error;
1020744bfb21SJohn Baldwin 
1021744bfb21SJohn Baldwin 	/* s */
1022744bfb21SJohn Baldwin 	if (noise_msg_decrypt(r_public, es,
1023744bfb21SJohn Baldwin 	    NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN, key, hs.hs_hash) != 0)
1024744bfb21SJohn Baldwin 		goto error;
1025744bfb21SJohn Baldwin 
1026744bfb21SJohn Baldwin 	/* Lookup the remote we received from */
1027744bfb21SJohn Baldwin 	if ((r = noise_remote_lookup(l, r_public)) == NULL)
1028744bfb21SJohn Baldwin 		goto error;
1029744bfb21SJohn Baldwin 
1030744bfb21SJohn Baldwin 	/* ss */
1031744bfb21SJohn Baldwin 	if (noise_mix_ss(hs.hs_ck, key, r->r_ss) != 0)
1032744bfb21SJohn Baldwin 		goto error_put;
1033744bfb21SJohn Baldwin 
1034744bfb21SJohn Baldwin 	/* {t} */
1035744bfb21SJohn Baldwin 	if (noise_msg_decrypt(timestamp, ets,
1036744bfb21SJohn Baldwin 	    NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN, key, hs.hs_hash) != 0)
1037744bfb21SJohn Baldwin 		goto error_put;
1038744bfb21SJohn Baldwin 
1039744bfb21SJohn Baldwin 	memcpy(hs.hs_e, ue, NOISE_PUBLIC_KEY_LEN);
1040744bfb21SJohn Baldwin 
1041744bfb21SJohn Baldwin 	/* We have successfully computed the same results, now we ensure that
1042744bfb21SJohn Baldwin 	 * this is not an initiation replay, or a flood attack */
1043744bfb21SJohn Baldwin 	rw_wlock(&r->r_handshake_lock);
1044744bfb21SJohn Baldwin 
1045744bfb21SJohn Baldwin 	/* Replay */
1046744bfb21SJohn Baldwin 	if (memcmp(timestamp, r->r_timestamp, NOISE_TIMESTAMP_LEN) > 0)
1047744bfb21SJohn Baldwin 		memcpy(r->r_timestamp, timestamp, NOISE_TIMESTAMP_LEN);
1048744bfb21SJohn Baldwin 	else
1049744bfb21SJohn Baldwin 		goto error_set;
1050744bfb21SJohn Baldwin 	/* Flood attack */
1051744bfb21SJohn Baldwin 	if (noise_timer_expired(r->r_last_init_recv, 0, REJECT_INTERVAL))
1052744bfb21SJohn Baldwin 		r->r_last_init_recv = getsbinuptime();
1053744bfb21SJohn Baldwin 	else
1054744bfb21SJohn Baldwin 		goto error_set;
1055744bfb21SJohn Baldwin 
1056744bfb21SJohn Baldwin 	/* Ok, we're happy to accept this initiation now */
1057744bfb21SJohn Baldwin 	noise_remote_index_insert(l, r);
1058744bfb21SJohn Baldwin 	r->r_index.i_remote_index = s_idx;
1059744bfb21SJohn Baldwin 	r->r_handshake_state = HANDSHAKE_RESPONDER;
1060744bfb21SJohn Baldwin 	r->r_handshake = hs;
1061744bfb21SJohn Baldwin 	*rp = noise_remote_ref(r);
1062744bfb21SJohn Baldwin 	ret = 0;
1063744bfb21SJohn Baldwin error_set:
1064744bfb21SJohn Baldwin 	rw_wunlock(&r->r_handshake_lock);
1065744bfb21SJohn Baldwin error_put:
1066744bfb21SJohn Baldwin 	noise_remote_put(r);
1067744bfb21SJohn Baldwin error:
1068744bfb21SJohn Baldwin 	rw_runlock(&l->l_identity_lock);
1069744bfb21SJohn Baldwin 	explicit_bzero(key, NOISE_SYMMETRIC_KEY_LEN);
1070744bfb21SJohn Baldwin 	explicit_bzero(&hs, sizeof(hs));
1071744bfb21SJohn Baldwin 	return (ret);
1072744bfb21SJohn Baldwin }
1073744bfb21SJohn Baldwin 
1074744bfb21SJohn Baldwin int
1075744bfb21SJohn Baldwin noise_create_response(struct noise_remote *r,
1076744bfb21SJohn Baldwin     uint32_t *s_idx, uint32_t *r_idx,
1077744bfb21SJohn Baldwin     uint8_t ue[NOISE_PUBLIC_KEY_LEN],
1078744bfb21SJohn Baldwin     uint8_t en[0 + NOISE_AUTHTAG_LEN])
1079744bfb21SJohn Baldwin {
1080744bfb21SJohn Baldwin 	struct noise_handshake *hs = &r->r_handshake;
1081744bfb21SJohn Baldwin 	struct noise_local *l = r->r_local;
1082744bfb21SJohn Baldwin 	uint8_t key[NOISE_SYMMETRIC_KEY_LEN];
1083744bfb21SJohn Baldwin 	uint8_t e[NOISE_PUBLIC_KEY_LEN];
1084744bfb21SJohn Baldwin 	int ret = EINVAL;
1085744bfb21SJohn Baldwin 
1086744bfb21SJohn Baldwin 	rw_rlock(&l->l_identity_lock);
1087744bfb21SJohn Baldwin 	rw_wlock(&r->r_handshake_lock);
1088744bfb21SJohn Baldwin 
1089744bfb21SJohn Baldwin 	if (r->r_handshake_state != HANDSHAKE_RESPONDER)
1090744bfb21SJohn Baldwin 		goto error;
1091744bfb21SJohn Baldwin 
1092744bfb21SJohn Baldwin 	/* e */
1093744bfb21SJohn Baldwin 	curve25519_generate_secret(e);
1094744bfb21SJohn Baldwin 	if (curve25519_generate_public(ue, e) == 0)
1095744bfb21SJohn Baldwin 		goto error;
1096744bfb21SJohn Baldwin 	noise_msg_ephemeral(hs->hs_ck, hs->hs_hash, ue);
1097744bfb21SJohn Baldwin 
1098744bfb21SJohn Baldwin 	/* ee */
1099744bfb21SJohn Baldwin 	if (noise_mix_dh(hs->hs_ck, NULL, e, hs->hs_e) != 0)
1100744bfb21SJohn Baldwin 		goto error;
1101744bfb21SJohn Baldwin 
1102744bfb21SJohn Baldwin 	/* se */
1103744bfb21SJohn Baldwin 	if (noise_mix_dh(hs->hs_ck, NULL, e, r->r_public) != 0)
1104744bfb21SJohn Baldwin 		goto error;
1105744bfb21SJohn Baldwin 
1106744bfb21SJohn Baldwin 	/* psk */
1107744bfb21SJohn Baldwin 	noise_mix_psk(hs->hs_ck, hs->hs_hash, key, r->r_psk);
1108744bfb21SJohn Baldwin 
1109744bfb21SJohn Baldwin 	/* {} */
1110744bfb21SJohn Baldwin 	noise_msg_encrypt(en, NULL, 0, key, hs->hs_hash);
1111744bfb21SJohn Baldwin 
1112744bfb21SJohn Baldwin 	if ((ret = noise_begin_session(r)) == 0) {
1113744bfb21SJohn Baldwin 		r->r_last_sent = getsbinuptime();
1114744bfb21SJohn Baldwin 		*s_idx = r->r_index.i_local_index;
1115744bfb21SJohn Baldwin 		*r_idx = r->r_index.i_remote_index;
1116744bfb21SJohn Baldwin 	}
1117744bfb21SJohn Baldwin error:
1118744bfb21SJohn Baldwin 	rw_wunlock(&r->r_handshake_lock);
1119744bfb21SJohn Baldwin 	rw_runlock(&l->l_identity_lock);
1120744bfb21SJohn Baldwin 	explicit_bzero(key, NOISE_SYMMETRIC_KEY_LEN);
1121744bfb21SJohn Baldwin 	explicit_bzero(e, NOISE_PUBLIC_KEY_LEN);
1122744bfb21SJohn Baldwin 	return (ret);
1123744bfb21SJohn Baldwin }
1124744bfb21SJohn Baldwin 
1125744bfb21SJohn Baldwin int
1126744bfb21SJohn Baldwin noise_consume_response(struct noise_local *l, struct noise_remote **rp,
1127744bfb21SJohn Baldwin     uint32_t s_idx, uint32_t r_idx,
1128744bfb21SJohn Baldwin     uint8_t ue[NOISE_PUBLIC_KEY_LEN],
1129744bfb21SJohn Baldwin     uint8_t en[0 + NOISE_AUTHTAG_LEN])
1130744bfb21SJohn Baldwin {
1131744bfb21SJohn Baldwin 	uint8_t preshared_key[NOISE_SYMMETRIC_KEY_LEN];
1132744bfb21SJohn Baldwin 	uint8_t key[NOISE_SYMMETRIC_KEY_LEN];
1133744bfb21SJohn Baldwin 	struct noise_handshake hs;
1134744bfb21SJohn Baldwin 	struct noise_remote *r = NULL;
1135744bfb21SJohn Baldwin 	int ret = EINVAL;
1136744bfb21SJohn Baldwin 
1137744bfb21SJohn Baldwin 	if ((r = noise_remote_index_lookup(l, r_idx, false)) == NULL)
1138744bfb21SJohn Baldwin 		return (ret);
1139744bfb21SJohn Baldwin 
1140744bfb21SJohn Baldwin 	rw_rlock(&l->l_identity_lock);
1141744bfb21SJohn Baldwin 	if (!l->l_has_identity)
1142744bfb21SJohn Baldwin 		goto error;
1143744bfb21SJohn Baldwin 
1144744bfb21SJohn Baldwin 	rw_rlock(&r->r_handshake_lock);
1145744bfb21SJohn Baldwin 	if (r->r_handshake_state != HANDSHAKE_INITIATOR) {
1146744bfb21SJohn Baldwin 		rw_runlock(&r->r_handshake_lock);
1147744bfb21SJohn Baldwin 		goto error;
1148744bfb21SJohn Baldwin 	}
1149744bfb21SJohn Baldwin 	memcpy(preshared_key, r->r_psk, NOISE_SYMMETRIC_KEY_LEN);
1150744bfb21SJohn Baldwin 	hs = r->r_handshake;
1151744bfb21SJohn Baldwin 	rw_runlock(&r->r_handshake_lock);
1152744bfb21SJohn Baldwin 
1153744bfb21SJohn Baldwin 	/* e */
1154744bfb21SJohn Baldwin 	noise_msg_ephemeral(hs.hs_ck, hs.hs_hash, ue);
1155744bfb21SJohn Baldwin 
1156744bfb21SJohn Baldwin 	/* ee */
1157744bfb21SJohn Baldwin 	if (noise_mix_dh(hs.hs_ck, NULL, hs.hs_e, ue) != 0)
1158744bfb21SJohn Baldwin 		goto error_zero;
1159744bfb21SJohn Baldwin 
1160744bfb21SJohn Baldwin 	/* se */
1161744bfb21SJohn Baldwin 	if (noise_mix_dh(hs.hs_ck, NULL, l->l_private, ue) != 0)
1162744bfb21SJohn Baldwin 		goto error_zero;
1163744bfb21SJohn Baldwin 
1164744bfb21SJohn Baldwin 	/* psk */
1165744bfb21SJohn Baldwin 	noise_mix_psk(hs.hs_ck, hs.hs_hash, key, preshared_key);
1166744bfb21SJohn Baldwin 
1167744bfb21SJohn Baldwin 	/* {} */
1168744bfb21SJohn Baldwin 	if (noise_msg_decrypt(NULL, en,
1169744bfb21SJohn Baldwin 	    0 + NOISE_AUTHTAG_LEN, key, hs.hs_hash) != 0)
1170744bfb21SJohn Baldwin 		goto error_zero;
1171744bfb21SJohn Baldwin 
1172744bfb21SJohn Baldwin 	rw_wlock(&r->r_handshake_lock);
1173744bfb21SJohn Baldwin 	if (r->r_handshake_state == HANDSHAKE_INITIATOR &&
1174744bfb21SJohn Baldwin 	    r->r_index.i_local_index == r_idx) {
1175744bfb21SJohn Baldwin 		r->r_handshake = hs;
1176744bfb21SJohn Baldwin 		r->r_index.i_remote_index = s_idx;
1177744bfb21SJohn Baldwin 		if ((ret = noise_begin_session(r)) == 0)
1178744bfb21SJohn Baldwin 			*rp = noise_remote_ref(r);
1179744bfb21SJohn Baldwin 	}
1180744bfb21SJohn Baldwin 	rw_wunlock(&r->r_handshake_lock);
1181744bfb21SJohn Baldwin error_zero:
1182744bfb21SJohn Baldwin 	explicit_bzero(preshared_key, NOISE_SYMMETRIC_KEY_LEN);
1183744bfb21SJohn Baldwin 	explicit_bzero(key, NOISE_SYMMETRIC_KEY_LEN);
1184744bfb21SJohn Baldwin 	explicit_bzero(&hs, sizeof(hs));
1185744bfb21SJohn Baldwin error:
1186744bfb21SJohn Baldwin 	rw_runlock(&l->l_identity_lock);
1187744bfb21SJohn Baldwin 	noise_remote_put(r);
1188744bfb21SJohn Baldwin 	return (ret);
1189744bfb21SJohn Baldwin }
1190744bfb21SJohn Baldwin 
1191744bfb21SJohn Baldwin static void
1192744bfb21SJohn Baldwin hmac(uint8_t *out, const uint8_t *in, const uint8_t *key, const size_t outlen,
1193744bfb21SJohn Baldwin      const size_t inlen, const size_t keylen)
1194744bfb21SJohn Baldwin {
1195744bfb21SJohn Baldwin 	struct blake2s_state state;
1196744bfb21SJohn Baldwin 	uint8_t x_key[BLAKE2S_BLOCK_SIZE] __aligned(sizeof(uint32_t)) = { 0 };
1197744bfb21SJohn Baldwin 	uint8_t i_hash[BLAKE2S_HASH_SIZE] __aligned(sizeof(uint32_t));
1198744bfb21SJohn Baldwin 	int i;
1199744bfb21SJohn Baldwin 
1200744bfb21SJohn Baldwin 	if (keylen > BLAKE2S_BLOCK_SIZE) {
1201744bfb21SJohn Baldwin 		blake2s_init(&state, BLAKE2S_HASH_SIZE);
1202744bfb21SJohn Baldwin 		blake2s_update(&state, key, keylen);
1203744bfb21SJohn Baldwin 		blake2s_final(&state, x_key);
1204744bfb21SJohn Baldwin 	} else
1205744bfb21SJohn Baldwin 		memcpy(x_key, key, keylen);
1206744bfb21SJohn Baldwin 
1207744bfb21SJohn Baldwin 	for (i = 0; i < BLAKE2S_BLOCK_SIZE; ++i)
1208744bfb21SJohn Baldwin 		x_key[i] ^= 0x36;
1209744bfb21SJohn Baldwin 
1210744bfb21SJohn Baldwin 	blake2s_init(&state, BLAKE2S_HASH_SIZE);
1211744bfb21SJohn Baldwin 	blake2s_update(&state, x_key, BLAKE2S_BLOCK_SIZE);
1212744bfb21SJohn Baldwin 	blake2s_update(&state, in, inlen);
1213744bfb21SJohn Baldwin 	blake2s_final(&state, i_hash);
1214744bfb21SJohn Baldwin 
1215744bfb21SJohn Baldwin 	for (i = 0; i < BLAKE2S_BLOCK_SIZE; ++i)
1216744bfb21SJohn Baldwin 		x_key[i] ^= 0x5c ^ 0x36;
1217744bfb21SJohn Baldwin 
1218744bfb21SJohn Baldwin 	blake2s_init(&state, BLAKE2S_HASH_SIZE);
1219744bfb21SJohn Baldwin 	blake2s_update(&state, x_key, BLAKE2S_BLOCK_SIZE);
1220744bfb21SJohn Baldwin 	blake2s_update(&state, i_hash, BLAKE2S_HASH_SIZE);
1221744bfb21SJohn Baldwin 	blake2s_final(&state, i_hash);
1222744bfb21SJohn Baldwin 
1223744bfb21SJohn Baldwin 	memcpy(out, i_hash, outlen);
1224744bfb21SJohn Baldwin 	explicit_bzero(x_key, BLAKE2S_BLOCK_SIZE);
1225744bfb21SJohn Baldwin 	explicit_bzero(i_hash, BLAKE2S_HASH_SIZE);
1226744bfb21SJohn Baldwin }
1227744bfb21SJohn Baldwin 
1228744bfb21SJohn Baldwin /* Handshake helper functions */
1229744bfb21SJohn Baldwin static void
1230744bfb21SJohn Baldwin noise_kdf(uint8_t *a, uint8_t *b, uint8_t *c, const uint8_t *x,
1231744bfb21SJohn Baldwin     size_t a_len, size_t b_len, size_t c_len, size_t x_len,
1232744bfb21SJohn Baldwin     const uint8_t ck[NOISE_HASH_LEN])
1233744bfb21SJohn Baldwin {
1234744bfb21SJohn Baldwin 	uint8_t out[BLAKE2S_HASH_SIZE + 1];
1235744bfb21SJohn Baldwin 	uint8_t sec[BLAKE2S_HASH_SIZE];
1236744bfb21SJohn Baldwin 
1237744bfb21SJohn Baldwin 	/* Extract entropy from "x" into sec */
1238744bfb21SJohn Baldwin 	hmac(sec, x, ck, BLAKE2S_HASH_SIZE, x_len, NOISE_HASH_LEN);
1239744bfb21SJohn Baldwin 
1240744bfb21SJohn Baldwin 	if (a == NULL || a_len == 0)
1241744bfb21SJohn Baldwin 		goto out;
1242744bfb21SJohn Baldwin 
1243744bfb21SJohn Baldwin 	/* Expand first key: key = sec, data = 0x1 */
1244744bfb21SJohn Baldwin 	out[0] = 1;
1245744bfb21SJohn Baldwin 	hmac(out, out, sec, BLAKE2S_HASH_SIZE, 1, BLAKE2S_HASH_SIZE);
1246744bfb21SJohn Baldwin 	memcpy(a, out, a_len);
1247744bfb21SJohn Baldwin 
1248744bfb21SJohn Baldwin 	if (b == NULL || b_len == 0)
1249744bfb21SJohn Baldwin 		goto out;
1250744bfb21SJohn Baldwin 
1251744bfb21SJohn Baldwin 	/* Expand second key: key = sec, data = "a" || 0x2 */
1252744bfb21SJohn Baldwin 	out[BLAKE2S_HASH_SIZE] = 2;
1253744bfb21SJohn Baldwin 	hmac(out, out, sec, BLAKE2S_HASH_SIZE, BLAKE2S_HASH_SIZE + 1, BLAKE2S_HASH_SIZE);
1254744bfb21SJohn Baldwin 	memcpy(b, out, b_len);
1255744bfb21SJohn Baldwin 
1256744bfb21SJohn Baldwin 	if (c == NULL || c_len == 0)
1257744bfb21SJohn Baldwin 		goto out;
1258744bfb21SJohn Baldwin 
1259744bfb21SJohn Baldwin 	/* Expand third key: key = sec, data = "b" || 0x3 */
1260744bfb21SJohn Baldwin 	out[BLAKE2S_HASH_SIZE] = 3;
1261744bfb21SJohn Baldwin 	hmac(out, out, sec, BLAKE2S_HASH_SIZE, BLAKE2S_HASH_SIZE + 1, BLAKE2S_HASH_SIZE);
1262744bfb21SJohn Baldwin 	memcpy(c, out, c_len);
1263744bfb21SJohn Baldwin 
1264744bfb21SJohn Baldwin out:
1265744bfb21SJohn Baldwin 	/* Clear sensitive data from stack */
1266744bfb21SJohn Baldwin 	explicit_bzero(sec, BLAKE2S_HASH_SIZE);
1267744bfb21SJohn Baldwin 	explicit_bzero(out, BLAKE2S_HASH_SIZE + 1);
1268744bfb21SJohn Baldwin }
1269744bfb21SJohn Baldwin 
1270744bfb21SJohn Baldwin static int
1271744bfb21SJohn Baldwin noise_mix_dh(uint8_t ck[NOISE_HASH_LEN], uint8_t key[NOISE_SYMMETRIC_KEY_LEN],
1272744bfb21SJohn Baldwin     const uint8_t private[NOISE_PUBLIC_KEY_LEN],
1273744bfb21SJohn Baldwin     const uint8_t public[NOISE_PUBLIC_KEY_LEN])
1274744bfb21SJohn Baldwin {
1275744bfb21SJohn Baldwin 	uint8_t dh[NOISE_PUBLIC_KEY_LEN];
1276744bfb21SJohn Baldwin 
1277744bfb21SJohn Baldwin 	if (!curve25519(dh, private, public))
1278744bfb21SJohn Baldwin 		return (EINVAL);
1279744bfb21SJohn Baldwin 	noise_kdf(ck, key, NULL, dh,
1280744bfb21SJohn Baldwin 	    NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, NOISE_PUBLIC_KEY_LEN, ck);
1281744bfb21SJohn Baldwin 	explicit_bzero(dh, NOISE_PUBLIC_KEY_LEN);
1282744bfb21SJohn Baldwin 	return (0);
1283744bfb21SJohn Baldwin }
1284744bfb21SJohn Baldwin 
1285744bfb21SJohn Baldwin static int
1286744bfb21SJohn Baldwin noise_mix_ss(uint8_t ck[NOISE_HASH_LEN], uint8_t key[NOISE_SYMMETRIC_KEY_LEN],
1287744bfb21SJohn Baldwin     const uint8_t ss[NOISE_PUBLIC_KEY_LEN])
1288744bfb21SJohn Baldwin {
1289744bfb21SJohn Baldwin 	static uint8_t null_point[NOISE_PUBLIC_KEY_LEN];
1290744bfb21SJohn Baldwin 	if (timingsafe_bcmp(ss, null_point, NOISE_PUBLIC_KEY_LEN) == 0)
1291744bfb21SJohn Baldwin 		return (ENOENT);
1292744bfb21SJohn Baldwin 	noise_kdf(ck, key, NULL, ss,
1293744bfb21SJohn Baldwin 	    NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, NOISE_PUBLIC_KEY_LEN, ck);
1294744bfb21SJohn Baldwin 	return (0);
1295744bfb21SJohn Baldwin }
1296744bfb21SJohn Baldwin 
1297744bfb21SJohn Baldwin static void
1298744bfb21SJohn Baldwin noise_mix_hash(uint8_t hash[NOISE_HASH_LEN], const uint8_t *src,
1299744bfb21SJohn Baldwin     size_t src_len)
1300744bfb21SJohn Baldwin {
1301744bfb21SJohn Baldwin 	struct blake2s_state blake;
1302744bfb21SJohn Baldwin 
1303744bfb21SJohn Baldwin 	blake2s_init(&blake, NOISE_HASH_LEN);
1304744bfb21SJohn Baldwin 	blake2s_update(&blake, hash, NOISE_HASH_LEN);
1305744bfb21SJohn Baldwin 	blake2s_update(&blake, src, src_len);
1306744bfb21SJohn Baldwin 	blake2s_final(&blake, hash);
1307744bfb21SJohn Baldwin }
1308744bfb21SJohn Baldwin 
1309744bfb21SJohn Baldwin static void
1310744bfb21SJohn Baldwin noise_mix_psk(uint8_t ck[NOISE_HASH_LEN], uint8_t hash[NOISE_HASH_LEN],
1311744bfb21SJohn Baldwin     uint8_t key[NOISE_SYMMETRIC_KEY_LEN],
1312744bfb21SJohn Baldwin     const uint8_t psk[NOISE_SYMMETRIC_KEY_LEN])
1313744bfb21SJohn Baldwin {
1314744bfb21SJohn Baldwin 	uint8_t tmp[NOISE_HASH_LEN];
1315744bfb21SJohn Baldwin 
1316744bfb21SJohn Baldwin 	noise_kdf(ck, tmp, key, psk,
1317744bfb21SJohn Baldwin 	    NOISE_HASH_LEN, NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN,
1318744bfb21SJohn Baldwin 	    NOISE_SYMMETRIC_KEY_LEN, ck);
1319744bfb21SJohn Baldwin 	noise_mix_hash(hash, tmp, NOISE_HASH_LEN);
1320744bfb21SJohn Baldwin 	explicit_bzero(tmp, NOISE_HASH_LEN);
1321744bfb21SJohn Baldwin }
1322744bfb21SJohn Baldwin 
1323744bfb21SJohn Baldwin static void
1324744bfb21SJohn Baldwin noise_param_init(uint8_t ck[NOISE_HASH_LEN], uint8_t hash[NOISE_HASH_LEN],
1325744bfb21SJohn Baldwin     const uint8_t s[NOISE_PUBLIC_KEY_LEN])
1326744bfb21SJohn Baldwin {
1327744bfb21SJohn Baldwin 	struct blake2s_state blake;
1328744bfb21SJohn Baldwin 
1329744bfb21SJohn Baldwin 	blake2s(ck, (uint8_t *)NOISE_HANDSHAKE_NAME, NULL,
1330744bfb21SJohn Baldwin 	    NOISE_HASH_LEN, strlen(NOISE_HANDSHAKE_NAME), 0);
1331744bfb21SJohn Baldwin 	blake2s_init(&blake, NOISE_HASH_LEN);
1332744bfb21SJohn Baldwin 	blake2s_update(&blake, ck, NOISE_HASH_LEN);
1333744bfb21SJohn Baldwin 	blake2s_update(&blake, (uint8_t *)NOISE_IDENTIFIER_NAME,
1334744bfb21SJohn Baldwin 	    strlen(NOISE_IDENTIFIER_NAME));
1335744bfb21SJohn Baldwin 	blake2s_final(&blake, hash);
1336744bfb21SJohn Baldwin 
1337744bfb21SJohn Baldwin 	noise_mix_hash(hash, s, NOISE_PUBLIC_KEY_LEN);
1338744bfb21SJohn Baldwin }
1339744bfb21SJohn Baldwin 
1340744bfb21SJohn Baldwin static void
1341744bfb21SJohn Baldwin noise_msg_encrypt(uint8_t *dst, const uint8_t *src, size_t src_len,
1342744bfb21SJohn Baldwin     uint8_t key[NOISE_SYMMETRIC_KEY_LEN], uint8_t hash[NOISE_HASH_LEN])
1343744bfb21SJohn Baldwin {
1344744bfb21SJohn Baldwin 	/* Nonce always zero for Noise_IK */
1345744bfb21SJohn Baldwin 	chacha20poly1305_encrypt(dst, src, src_len,
1346744bfb21SJohn Baldwin 	    hash, NOISE_HASH_LEN, 0, key);
1347744bfb21SJohn Baldwin 	noise_mix_hash(hash, dst, src_len + NOISE_AUTHTAG_LEN);
1348744bfb21SJohn Baldwin }
1349744bfb21SJohn Baldwin 
1350744bfb21SJohn Baldwin static int
1351744bfb21SJohn Baldwin noise_msg_decrypt(uint8_t *dst, const uint8_t *src, size_t src_len,
1352744bfb21SJohn Baldwin     uint8_t key[NOISE_SYMMETRIC_KEY_LEN], uint8_t hash[NOISE_HASH_LEN])
1353744bfb21SJohn Baldwin {
1354744bfb21SJohn Baldwin 	/* Nonce always zero for Noise_IK */
1355744bfb21SJohn Baldwin 	if (!chacha20poly1305_decrypt(dst, src, src_len,
1356744bfb21SJohn Baldwin 	    hash, NOISE_HASH_LEN, 0, key))
1357744bfb21SJohn Baldwin 		return (EINVAL);
1358744bfb21SJohn Baldwin 	noise_mix_hash(hash, src, src_len);
1359744bfb21SJohn Baldwin 	return (0);
1360744bfb21SJohn Baldwin }
1361744bfb21SJohn Baldwin 
1362744bfb21SJohn Baldwin static void
1363744bfb21SJohn Baldwin noise_msg_ephemeral(uint8_t ck[NOISE_HASH_LEN], uint8_t hash[NOISE_HASH_LEN],
1364744bfb21SJohn Baldwin     const uint8_t src[NOISE_PUBLIC_KEY_LEN])
1365744bfb21SJohn Baldwin {
1366744bfb21SJohn Baldwin 	noise_mix_hash(hash, src, NOISE_PUBLIC_KEY_LEN);
1367744bfb21SJohn Baldwin 	noise_kdf(ck, NULL, NULL, src, NOISE_HASH_LEN, 0, 0,
1368744bfb21SJohn Baldwin 		  NOISE_PUBLIC_KEY_LEN, ck);
1369744bfb21SJohn Baldwin }
1370744bfb21SJohn Baldwin 
1371744bfb21SJohn Baldwin static void
1372744bfb21SJohn Baldwin noise_tai64n_now(uint8_t output[NOISE_TIMESTAMP_LEN])
1373744bfb21SJohn Baldwin {
1374744bfb21SJohn Baldwin 	struct timespec time;
1375744bfb21SJohn Baldwin 	uint64_t sec;
1376744bfb21SJohn Baldwin 	uint32_t nsec;
1377744bfb21SJohn Baldwin 
1378744bfb21SJohn Baldwin 	getnanotime(&time);
1379744bfb21SJohn Baldwin 
1380744bfb21SJohn Baldwin 	/* Round down the nsec counter to limit precise timing leak. */
1381744bfb21SJohn Baldwin 	time.tv_nsec &= REJECT_INTERVAL_MASK;
1382744bfb21SJohn Baldwin 
1383744bfb21SJohn Baldwin 	/* https://cr.yp.to/libtai/tai64.html */
1384744bfb21SJohn Baldwin 	sec = htobe64(0x400000000000000aULL + time.tv_sec);
1385744bfb21SJohn Baldwin 	nsec = htobe32(time.tv_nsec);
1386744bfb21SJohn Baldwin 
1387744bfb21SJohn Baldwin 	/* memcpy to output buffer, assuming output could be unaligned. */
1388744bfb21SJohn Baldwin 	memcpy(output, &sec, sizeof(sec));
1389744bfb21SJohn Baldwin 	memcpy(output + sizeof(sec), &nsec, sizeof(nsec));
1390744bfb21SJohn Baldwin }
1391744bfb21SJohn Baldwin 
1392744bfb21SJohn Baldwin static inline int
1393744bfb21SJohn Baldwin noise_timer_expired(sbintime_t timer, uint32_t sec, uint32_t nsec)
1394744bfb21SJohn Baldwin {
1395744bfb21SJohn Baldwin 	sbintime_t now = getsbinuptime();
1396744bfb21SJohn Baldwin 	return (now > (timer + sec * SBT_1S + nstosbt(nsec))) ? ETIMEDOUT : 0;
1397744bfb21SJohn Baldwin }
1398744bfb21SJohn Baldwin 
1399744bfb21SJohn Baldwin static uint64_t siphash24(const uint8_t key[SIPHASH_KEY_LENGTH], const void *src, size_t len)
1400744bfb21SJohn Baldwin {
1401744bfb21SJohn Baldwin 	SIPHASH_CTX ctx;
1402744bfb21SJohn Baldwin 	return (SipHashX(&ctx, 2, 4, key, src, len));
1403744bfb21SJohn Baldwin }
1404744bfb21SJohn Baldwin 
1405744bfb21SJohn Baldwin #ifdef SELFTESTS
1406744bfb21SJohn Baldwin #include "selftest/counter.c"
1407744bfb21SJohn Baldwin #endif /* SELFTESTS */
1408