Line data Source code
1 : /*
2 : * Copyright (c) 2020 Doc.ai and/or its affiliates.
3 : * Copyright (c) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>.
4 : * Copyright (c) 2019-2020 Matt Dunwoodie <ncon@noconroy.net>.
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at:
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #include <openssl/hmac.h>
19 : #include <wireguard/wireguard.h>
20 : #include <wireguard/wireguard_chachapoly.h>
21 :
22 : /* This implements Noise_IKpsk2:
23 : *
24 : * <- s
25 : * ******
26 : * -> e, es, s, ss, {t}
27 : * <- e, ee, se, psk, {}
28 : */
29 :
30 : noise_local_t *noise_local_pool;
31 :
32 : /* Private functions */
33 : static noise_keypair_t *noise_remote_keypair_allocate (noise_remote_t *);
34 : static void noise_remote_keypair_free (vlib_main_t * vm, noise_remote_t *,
35 : noise_keypair_t **);
36 : static uint32_t noise_remote_handshake_index_get (vlib_main_t *vm,
37 : noise_remote_t *);
38 : static void noise_remote_handshake_index_drop (vlib_main_t *vm,
39 : noise_remote_t *);
40 :
41 : static uint64_t noise_counter_send (noise_counter_t *);
42 : bool noise_counter_recv (noise_counter_t *, uint64_t);
43 :
44 : static void noise_kdf (uint8_t *, uint8_t *, uint8_t *, const uint8_t *,
45 : size_t, size_t, size_t, size_t,
46 : const uint8_t[NOISE_HASH_LEN]);
47 : static bool noise_mix_dh (uint8_t[NOISE_HASH_LEN],
48 : uint8_t[NOISE_SYMMETRIC_KEY_LEN],
49 : const uint8_t[NOISE_PUBLIC_KEY_LEN],
50 : const uint8_t[NOISE_PUBLIC_KEY_LEN]);
51 : static bool noise_mix_ss (uint8_t ck[NOISE_HASH_LEN],
52 : uint8_t key[NOISE_SYMMETRIC_KEY_LEN],
53 : const uint8_t ss[NOISE_PUBLIC_KEY_LEN]);
54 : static void noise_mix_hash (uint8_t[NOISE_HASH_LEN], const uint8_t *, size_t);
55 : static void noise_mix_psk (uint8_t[NOISE_HASH_LEN],
56 : uint8_t[NOISE_HASH_LEN],
57 : uint8_t[NOISE_SYMMETRIC_KEY_LEN],
58 : const uint8_t[NOISE_SYMMETRIC_KEY_LEN]);
59 : static void noise_param_init (uint8_t[NOISE_HASH_LEN],
60 : uint8_t[NOISE_HASH_LEN],
61 : const uint8_t[NOISE_PUBLIC_KEY_LEN]);
62 :
63 : static void noise_msg_encrypt (vlib_main_t * vm, uint8_t *, uint8_t *, size_t,
64 : uint32_t key_idx, uint8_t[NOISE_HASH_LEN]);
65 : static bool noise_msg_decrypt (vlib_main_t * vm, uint8_t *, uint8_t *, size_t,
66 : uint32_t key_idx, uint8_t[NOISE_HASH_LEN]);
67 : static void noise_msg_ephemeral (uint8_t[NOISE_HASH_LEN],
68 : uint8_t[NOISE_HASH_LEN],
69 : const uint8_t src[NOISE_PUBLIC_KEY_LEN]);
70 :
71 : static void noise_tai64n_now (uint8_t[NOISE_TIMESTAMP_LEN]);
72 :
73 : /* Set/Get noise parameters */
74 : void
75 82 : noise_local_init (noise_local_t * l, struct noise_upcall *upcall)
76 : {
77 82 : clib_memset (l, 0, sizeof (*l));
78 82 : l->l_upcall = *upcall;
79 82 : }
80 :
81 : bool
82 82 : noise_local_set_private (noise_local_t * l,
83 : const uint8_t private[NOISE_PUBLIC_KEY_LEN])
84 : {
85 82 : clib_memcpy (l->l_private, private, NOISE_PUBLIC_KEY_LEN);
86 :
87 82 : return curve25519_gen_public (l->l_public, private);
88 : }
89 :
90 : void
91 150 : noise_remote_init (vlib_main_t *vm, noise_remote_t *r, uint32_t peer_pool_idx,
92 : const uint8_t public[NOISE_PUBLIC_KEY_LEN],
93 : u32 noise_local_idx)
94 : {
95 150 : clib_memset (r, 0, sizeof (*r));
96 150 : clib_memcpy (r->r_public, public, NOISE_PUBLIC_KEY_LEN);
97 150 : clib_rwlock_init (&r->r_keypair_lock);
98 150 : r->r_peer_idx = peer_pool_idx;
99 150 : r->r_local_idx = noise_local_idx;
100 150 : r->r_handshake.hs_state = HS_ZEROED;
101 :
102 150 : noise_remote_precompute (vm, r);
103 150 : }
104 :
105 : void
106 150 : noise_remote_precompute (vlib_main_t *vm, noise_remote_t *r)
107 : {
108 150 : noise_local_t *l = noise_local_get (r->r_local_idx);
109 :
110 150 : if (!curve25519_gen_shared (r->r_ss, l->l_private, r->r_public))
111 0 : clib_memset (r->r_ss, 0, NOISE_PUBLIC_KEY_LEN);
112 :
113 150 : noise_remote_handshake_index_drop (vm, r);
114 150 : wg_secure_zero_memory (&r->r_handshake, sizeof (r->r_handshake));
115 150 : }
116 :
117 : /* Handshake functions */
118 : bool
119 155 : noise_create_initiation (vlib_main_t * vm, noise_remote_t * r,
120 : uint32_t * s_idx, uint8_t ue[NOISE_PUBLIC_KEY_LEN],
121 : uint8_t es[NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN],
122 : uint8_t ets[NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN])
123 : {
124 155 : noise_handshake_t *hs = &r->r_handshake;
125 155 : noise_local_t *l = noise_local_get (r->r_local_idx);
126 155 : uint8_t _key[NOISE_SYMMETRIC_KEY_LEN] = { 0 };
127 : uint32_t key_idx;
128 : uint8_t *key;
129 155 : int ret = false;
130 :
131 : key_idx =
132 155 : vnet_crypto_key_add (vm, VNET_CRYPTO_ALG_CHACHA20_POLY1305, _key,
133 : NOISE_SYMMETRIC_KEY_LEN);
134 155 : key = vnet_crypto_get_key (key_idx)->data;
135 :
136 155 : noise_param_init (hs->hs_ck, hs->hs_hash, r->r_public);
137 :
138 : /* e */
139 155 : curve25519_gen_secret (hs->hs_e);
140 155 : if (!curve25519_gen_public (ue, hs->hs_e))
141 0 : goto error;
142 155 : noise_msg_ephemeral (hs->hs_ck, hs->hs_hash, ue);
143 :
144 : /* es */
145 155 : if (!noise_mix_dh (hs->hs_ck, key, hs->hs_e, r->r_public))
146 0 : goto error;
147 :
148 : /* s */
149 155 : noise_msg_encrypt (vm, es, l->l_public, NOISE_PUBLIC_KEY_LEN, key_idx,
150 155 : hs->hs_hash);
151 :
152 : /* ss */
153 155 : if (!noise_mix_ss (hs->hs_ck, key, r->r_ss))
154 0 : goto error;
155 :
156 : /* {t} */
157 155 : noise_tai64n_now (ets);
158 155 : noise_msg_encrypt (vm, ets, ets, NOISE_TIMESTAMP_LEN, key_idx, hs->hs_hash);
159 155 : noise_remote_handshake_index_drop (vm, r);
160 155 : hs->hs_state = CREATED_INITIATION;
161 155 : hs->hs_local_index = noise_remote_handshake_index_get (vm, r);
162 155 : *s_idx = hs->hs_local_index;
163 155 : ret = true;
164 155 : error:
165 155 : wg_secure_zero_memory (key, NOISE_SYMMETRIC_KEY_LEN);
166 155 : vnet_crypto_key_del (vm, key_idx);
167 155 : return ret;
168 : }
169 :
170 : bool
171 635 : noise_consume_initiation (vlib_main_t * vm, noise_local_t * l,
172 : noise_remote_t ** rp, uint32_t s_idx,
173 : uint8_t ue[NOISE_PUBLIC_KEY_LEN],
174 : uint8_t es[NOISE_PUBLIC_KEY_LEN +
175 : NOISE_AUTHTAG_LEN],
176 : uint8_t ets[NOISE_TIMESTAMP_LEN +
177 : NOISE_AUTHTAG_LEN])
178 : {
179 : noise_remote_t *r;
180 : noise_handshake_t hs;
181 635 : uint8_t _key[NOISE_SYMMETRIC_KEY_LEN] = { 0 };
182 635 : uint8_t r_public[NOISE_PUBLIC_KEY_LEN] = { 0 };
183 635 : uint8_t timestamp[NOISE_TIMESTAMP_LEN] = { 0 };
184 : u32 key_idx;
185 : uint8_t *key;
186 635 : int ret = false;
187 :
188 : key_idx =
189 635 : vnet_crypto_key_add (vm, VNET_CRYPTO_ALG_CHACHA20_POLY1305, _key,
190 : NOISE_SYMMETRIC_KEY_LEN);
191 635 : key = vnet_crypto_get_key (key_idx)->data;
192 :
193 635 : noise_param_init (hs.hs_ck, hs.hs_hash, l->l_public);
194 :
195 : /* e */
196 635 : noise_msg_ephemeral (hs.hs_ck, hs.hs_hash, ue);
197 :
198 : /* es */
199 635 : if (!noise_mix_dh (hs.hs_ck, key, l->l_private, ue))
200 0 : goto error;
201 :
202 : /* s */
203 :
204 635 : if (!noise_msg_decrypt (vm, r_public, es,
205 : NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN, key_idx,
206 : hs.hs_hash))
207 8 : goto error;
208 :
209 : /* Lookup the remote we received from */
210 627 : if ((r = l->l_upcall.u_remote_get (r_public)) == NULL)
211 0 : goto error;
212 :
213 : /* ss */
214 627 : if (!noise_mix_ss (hs.hs_ck, key, r->r_ss))
215 0 : goto error;
216 :
217 : /* {t} */
218 627 : if (!noise_msg_decrypt (vm, timestamp, ets,
219 : NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN, key_idx,
220 : hs.hs_hash))
221 0 : goto error;
222 : ;
223 :
224 627 : hs.hs_state = CONSUMED_INITIATION;
225 627 : hs.hs_local_index = 0;
226 627 : hs.hs_remote_index = s_idx;
227 627 : clib_memcpy (hs.hs_e, ue, NOISE_PUBLIC_KEY_LEN);
228 :
229 : /* Replay */
230 627 : if (clib_memcmp (timestamp, r->r_timestamp, NOISE_TIMESTAMP_LEN) > 0)
231 59 : clib_memcpy (r->r_timestamp, timestamp, NOISE_TIMESTAMP_LEN);
232 : else
233 568 : goto error;
234 :
235 : /* Flood attack */
236 59 : if (wg_birthdate_has_expired (r->r_last_init, REJECT_INTERVAL))
237 59 : r->r_last_init = vlib_time_now (vm);
238 : else
239 0 : goto error;
240 :
241 : /* Ok, we're happy to accept this initiation now */
242 59 : noise_remote_handshake_index_drop (vm, r);
243 59 : r->r_handshake = hs;
244 59 : *rp = r;
245 59 : ret = true;
246 :
247 635 : error:
248 635 : wg_secure_zero_memory (key, NOISE_SYMMETRIC_KEY_LEN);
249 635 : vnet_crypto_key_del (vm, key_idx);
250 635 : wg_secure_zero_memory (&hs, sizeof (hs));
251 635 : return ret;
252 : }
253 :
254 : bool
255 59 : noise_create_response (vlib_main_t * vm, noise_remote_t * r, uint32_t * s_idx,
256 : uint32_t * r_idx, uint8_t ue[NOISE_PUBLIC_KEY_LEN],
257 : uint8_t en[0 + NOISE_AUTHTAG_LEN])
258 : {
259 59 : noise_handshake_t *hs = &r->r_handshake;
260 59 : uint8_t _key[NOISE_SYMMETRIC_KEY_LEN] = { 0 };
261 59 : uint8_t e[NOISE_PUBLIC_KEY_LEN] = { 0 };
262 : uint32_t key_idx;
263 : uint8_t *key;
264 59 : int ret = false;
265 :
266 : key_idx =
267 59 : vnet_crypto_key_add (vm, VNET_CRYPTO_ALG_CHACHA20_POLY1305, _key,
268 : NOISE_SYMMETRIC_KEY_LEN);
269 59 : key = vnet_crypto_get_key (key_idx)->data;
270 :
271 59 : if (hs->hs_state != CONSUMED_INITIATION)
272 0 : goto error;
273 :
274 : /* e */
275 59 : curve25519_gen_secret (e);
276 59 : if (!curve25519_gen_public (ue, e))
277 0 : goto error;
278 59 : noise_msg_ephemeral (hs->hs_ck, hs->hs_hash, ue);
279 :
280 : /* ee */
281 59 : if (!noise_mix_dh (hs->hs_ck, NULL, e, hs->hs_e))
282 0 : goto error;
283 :
284 : /* se */
285 59 : if (!noise_mix_dh (hs->hs_ck, NULL, e, r->r_public))
286 0 : goto error;
287 :
288 : /* psk */
289 59 : noise_mix_psk (hs->hs_ck, hs->hs_hash, key, r->r_psk);
290 :
291 : /* {} */
292 59 : noise_msg_encrypt (vm, en, NULL, 0, key_idx, hs->hs_hash);
293 :
294 :
295 59 : hs->hs_state = CREATED_RESPONSE;
296 59 : hs->hs_local_index = noise_remote_handshake_index_get (vm, r);
297 59 : *r_idx = hs->hs_remote_index;
298 59 : *s_idx = hs->hs_local_index;
299 59 : ret = true;
300 59 : error:
301 59 : wg_secure_zero_memory (key, NOISE_SYMMETRIC_KEY_LEN);
302 59 : vnet_crypto_key_del (vm, key_idx);
303 59 : wg_secure_zero_memory (e, NOISE_PUBLIC_KEY_LEN);
304 59 : return ret;
305 : }
306 :
307 : bool
308 187 : noise_consume_response (vlib_main_t * vm, noise_remote_t * r, uint32_t s_idx,
309 : uint32_t r_idx, uint8_t ue[NOISE_PUBLIC_KEY_LEN],
310 : uint8_t en[0 + NOISE_AUTHTAG_LEN])
311 : {
312 187 : noise_local_t *l = noise_local_get (r->r_local_idx);
313 : noise_handshake_t hs;
314 187 : uint8_t _key[NOISE_SYMMETRIC_KEY_LEN] = { 0 };
315 187 : uint8_t preshared_key[NOISE_PUBLIC_KEY_LEN] = { 0 };
316 : uint32_t key_idx;
317 : uint8_t *key;
318 187 : int ret = false;
319 :
320 : key_idx =
321 187 : vnet_crypto_key_add (vm, VNET_CRYPTO_ALG_CHACHA20_POLY1305, _key,
322 : NOISE_SYMMETRIC_KEY_LEN);
323 187 : key = vnet_crypto_get_key (key_idx)->data;
324 :
325 187 : hs = r->r_handshake;
326 187 : clib_memcpy (preshared_key, r->r_psk, NOISE_SYMMETRIC_KEY_LEN);
327 :
328 187 : if (hs.hs_state != CREATED_INITIATION || hs.hs_local_index != r_idx)
329 152 : goto error;
330 :
331 : /* e */
332 35 : noise_msg_ephemeral (hs.hs_ck, hs.hs_hash, ue);
333 :
334 : /* ee */
335 35 : if (!noise_mix_dh (hs.hs_ck, NULL, hs.hs_e, ue))
336 0 : goto error;
337 :
338 : /* se */
339 35 : if (!noise_mix_dh (hs.hs_ck, NULL, l->l_private, ue))
340 0 : goto error;
341 :
342 : /* psk */
343 35 : noise_mix_psk (hs.hs_ck, hs.hs_hash, key, preshared_key);
344 :
345 : /* {} */
346 :
347 35 : if (!noise_msg_decrypt
348 : (vm, NULL, en, 0 + NOISE_AUTHTAG_LEN, key_idx, hs.hs_hash))
349 0 : goto error;
350 :
351 :
352 35 : hs.hs_remote_index = s_idx;
353 :
354 35 : if (r->r_handshake.hs_state == hs.hs_state &&
355 35 : r->r_handshake.hs_local_index == hs.hs_local_index)
356 : {
357 35 : r->r_handshake = hs;
358 35 : r->r_handshake.hs_state = CONSUMED_RESPONSE;
359 35 : ret = true;
360 : }
361 0 : error:
362 187 : wg_secure_zero_memory (&hs, sizeof (hs));
363 187 : wg_secure_zero_memory (key, NOISE_SYMMETRIC_KEY_LEN);
364 187 : vnet_crypto_key_del (vm, key_idx);
365 187 : return ret;
366 : }
367 :
368 : bool
369 94 : noise_remote_begin_session (vlib_main_t * vm, noise_remote_t * r)
370 : {
371 94 : noise_handshake_t *hs = &r->r_handshake;
372 : noise_keypair_t kp, *next, *current, *previous;
373 :
374 : uint8_t key_send[NOISE_SYMMETRIC_KEY_LEN];
375 : uint8_t key_recv[NOISE_SYMMETRIC_KEY_LEN];
376 :
377 : /* We now derive the keypair from the handshake */
378 94 : if (hs->hs_state == CONSUMED_RESPONSE)
379 : {
380 35 : kp.kp_is_initiator = 1;
381 35 : noise_kdf (key_send, key_recv, NULL, NULL,
382 : NOISE_SYMMETRIC_KEY_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, 0,
383 35 : hs->hs_ck);
384 : }
385 59 : else if (hs->hs_state == CREATED_RESPONSE)
386 : {
387 59 : kp.kp_is_initiator = 0;
388 59 : noise_kdf (key_recv, key_send, NULL, NULL,
389 : NOISE_SYMMETRIC_KEY_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, 0,
390 59 : hs->hs_ck);
391 : }
392 : else
393 : {
394 0 : return false;
395 : }
396 :
397 94 : kp.kp_valid = 1;
398 94 : kp.kp_send_index = vnet_crypto_key_add (vm,
399 : VNET_CRYPTO_ALG_CHACHA20_POLY1305,
400 : key_send, NOISE_SYMMETRIC_KEY_LEN);
401 94 : kp.kp_recv_index = vnet_crypto_key_add (vm,
402 : VNET_CRYPTO_ALG_CHACHA20_POLY1305,
403 : key_recv, NOISE_SYMMETRIC_KEY_LEN);
404 94 : kp.kp_local_index = hs->hs_local_index;
405 94 : kp.kp_remote_index = hs->hs_remote_index;
406 94 : kp.kp_birthdate = vlib_time_now (vm);
407 94 : clib_memset (&kp.kp_ctr, 0, sizeof (kp.kp_ctr));
408 :
409 : /* Now we need to add_new_keypair */
410 94 : clib_rwlock_writer_lock (&r->r_keypair_lock);
411 : /* Activate barrier to synchronization keys between threads */
412 94 : vlib_worker_thread_barrier_sync (vm);
413 94 : next = r->r_next;
414 94 : current = r->r_current;
415 94 : previous = r->r_previous;
416 :
417 94 : if (kp.kp_is_initiator)
418 : {
419 35 : if (next != NULL)
420 : {
421 0 : r->r_next = NULL;
422 0 : r->r_previous = next;
423 0 : noise_remote_keypair_free (vm, r, ¤t);
424 : }
425 : else
426 : {
427 35 : r->r_previous = current;
428 : }
429 :
430 35 : noise_remote_keypair_free (vm, r, &previous);
431 :
432 35 : r->r_current = noise_remote_keypair_allocate (r);
433 35 : *r->r_current = kp;
434 : }
435 : else
436 : {
437 59 : noise_remote_keypair_free (vm, r, &next);
438 59 : r->r_previous = NULL;
439 59 : noise_remote_keypair_free (vm, r, &previous);
440 :
441 59 : r->r_next = noise_remote_keypair_allocate (r);
442 59 : *r->r_next = kp;
443 : }
444 94 : vlib_worker_thread_barrier_release (vm);
445 94 : clib_rwlock_writer_unlock (&r->r_keypair_lock);
446 :
447 94 : wg_secure_zero_memory (&r->r_handshake, sizeof (r->r_handshake));
448 :
449 94 : wg_secure_zero_memory (&kp, sizeof (kp));
450 94 : return true;
451 : }
452 :
453 : void
454 150 : noise_remote_clear (vlib_main_t * vm, noise_remote_t * r)
455 : {
456 150 : noise_remote_handshake_index_drop (vm, r);
457 150 : wg_secure_zero_memory (&r->r_handshake, sizeof (r->r_handshake));
458 :
459 150 : clib_rwlock_writer_lock (&r->r_keypair_lock);
460 150 : noise_remote_keypair_free (vm, r, &r->r_next);
461 150 : noise_remote_keypair_free (vm, r, &r->r_current);
462 150 : noise_remote_keypair_free (vm, r, &r->r_previous);
463 150 : r->r_next = NULL;
464 150 : r->r_current = NULL;
465 150 : r->r_previous = NULL;
466 150 : clib_rwlock_writer_unlock (&r->r_keypair_lock);
467 150 : }
468 :
469 : void
470 0 : noise_remote_expire_current (noise_remote_t * r)
471 : {
472 0 : clib_rwlock_writer_lock (&r->r_keypair_lock);
473 0 : if (r->r_next != NULL)
474 0 : r->r_next->kp_valid = 0;
475 0 : if (r->r_current != NULL)
476 0 : r->r_current->kp_valid = 0;
477 0 : clib_rwlock_writer_unlock (&r->r_keypair_lock);
478 0 : }
479 :
480 : bool
481 0 : noise_remote_ready (noise_remote_t * r)
482 : {
483 : noise_keypair_t *kp;
484 : int ret;
485 :
486 0 : clib_rwlock_reader_lock (&r->r_keypair_lock);
487 0 : if ((kp = r->r_current) == NULL ||
488 0 : !kp->kp_valid ||
489 0 : wg_birthdate_has_expired (kp->kp_birthdate, REJECT_AFTER_TIME) ||
490 0 : kp->kp_ctr.c_recv >= REJECT_AFTER_MESSAGES ||
491 0 : kp->kp_ctr.c_send >= REJECT_AFTER_MESSAGES)
492 0 : ret = false;
493 : else
494 0 : ret = true;
495 0 : clib_rwlock_reader_unlock (&r->r_keypair_lock);
496 0 : return ret;
497 : }
498 :
499 : enum noise_state_crypt
500 35 : noise_remote_encrypt (vlib_main_t * vm, noise_remote_t * r, uint32_t * r_idx,
501 : uint64_t * nonce, uint8_t * src, size_t srclen,
502 : uint8_t * dst)
503 : {
504 : noise_keypair_t *kp;
505 35 : enum noise_state_crypt ret = SC_FAILED;
506 :
507 35 : if ((kp = r->r_current) == NULL)
508 0 : goto error;
509 :
510 : /* We confirm that our values are within our tolerances. We want:
511 : * - a valid keypair
512 : * - our keypair to be less than REJECT_AFTER_TIME seconds old
513 : * - our receive counter to be less than REJECT_AFTER_MESSAGES
514 : * - our send counter to be less than REJECT_AFTER_MESSAGES
515 : */
516 70 : if (!kp->kp_valid ||
517 35 : wg_birthdate_has_expired (kp->kp_birthdate, REJECT_AFTER_TIME) ||
518 35 : kp->kp_ctr.c_recv >= REJECT_AFTER_MESSAGES ||
519 35 : ((*nonce = noise_counter_send (&kp->kp_ctr)) > REJECT_AFTER_MESSAGES))
520 0 : goto error;
521 :
522 : /* We encrypt into the same buffer, so the caller must ensure that buf
523 : * has NOISE_AUTHTAG_LEN bytes to store the MAC. The nonce and index
524 : * are passed back out to the caller through the provided data pointer. */
525 35 : *r_idx = kp->kp_remote_index;
526 :
527 35 : wg_chacha20poly1305_calc (vm, src, srclen, dst, NULL, 0, *nonce,
528 : VNET_CRYPTO_OP_CHACHA20_POLY1305_ENC,
529 : kp->kp_send_index);
530 :
531 : /* If our values are still within tolerances, but we are approaching
532 : * the tolerances, we notify the caller with ESTALE that they should
533 : * establish a new keypair. The current keypair can continue to be used
534 : * until the tolerances are hit. We notify if:
535 : * - our send counter is valid and not less than REKEY_AFTER_MESSAGES
536 : * - we're the initiator and our keypair is older than
537 : * REKEY_AFTER_TIME seconds */
538 35 : ret = SC_KEEP_KEY_FRESH;
539 35 : if ((kp->kp_valid && *nonce >= REKEY_AFTER_MESSAGES) ||
540 70 : (kp->kp_is_initiator &&
541 35 : wg_birthdate_has_expired (kp->kp_birthdate, REKEY_AFTER_TIME)))
542 0 : goto error;
543 :
544 35 : ret = SC_OK;
545 35 : error:
546 35 : return ret;
547 : }
548 :
549 : /* Private functions - these should not be called outside this file under any
550 : * circumstances. */
551 : static noise_keypair_t *
552 94 : noise_remote_keypair_allocate (noise_remote_t * r)
553 : {
554 : noise_keypair_t *kp;
555 94 : kp = clib_mem_alloc (sizeof (*kp));
556 94 : return kp;
557 : }
558 :
559 : static uint32_t
560 214 : noise_remote_handshake_index_get (vlib_main_t *vm, noise_remote_t *r)
561 : {
562 214 : noise_local_t *local = noise_local_get (r->r_local_idx);
563 214 : struct noise_upcall *u = &local->l_upcall;
564 214 : return u->u_index_set (vm, r);
565 : }
566 :
567 : static void
568 514 : noise_remote_handshake_index_drop (vlib_main_t *vm, noise_remote_t *r)
569 : {
570 514 : noise_handshake_t *hs = &r->r_handshake;
571 514 : noise_local_t *local = noise_local_get (r->r_local_idx);
572 514 : struct noise_upcall *u = &local->l_upcall;
573 514 : if (hs->hs_state != HS_ZEROED)
574 120 : u->u_index_drop (vm, hs->hs_local_index);
575 514 : }
576 :
577 : static void
578 2832 : noise_kdf (uint8_t * a, uint8_t * b, uint8_t * c, const uint8_t * x,
579 : size_t a_len, size_t b_len, size_t c_len, size_t x_len,
580 : const uint8_t ck[NOISE_HASH_LEN])
581 : {
582 : uint8_t out[BLAKE2S_HASH_SIZE + 1];
583 : uint8_t sec[BLAKE2S_HASH_SIZE];
584 :
585 : /* Extract entropy from "x" into sec */
586 2832 : u32 l = 0;
587 2832 : HMAC (EVP_blake2s256 (), ck, NOISE_HASH_LEN, x, x_len, sec, &l);
588 2832 : ASSERT (l == BLAKE2S_HASH_SIZE);
589 2832 : if (a == NULL || a_len == 0)
590 0 : goto out;
591 :
592 : /* Expand first key: key = sec, data = 0x1 */
593 2832 : out[0] = 1;
594 2832 : HMAC (EVP_blake2s256 (), sec, BLAKE2S_HASH_SIZE, out, 1, out, &l);
595 2832 : ASSERT (l == BLAKE2S_HASH_SIZE);
596 2832 : clib_memcpy (a, out, a_len);
597 :
598 2832 : if (b == NULL || b_len == 0)
599 1072 : goto out;
600 :
601 : /* Expand second key: key = sec, data = "a" || 0x2 */
602 1760 : out[BLAKE2S_HASH_SIZE] = 2;
603 1760 : HMAC (EVP_blake2s256 (), sec, BLAKE2S_HASH_SIZE, out, BLAKE2S_HASH_SIZE + 1,
604 : out, &l);
605 1760 : ASSERT (l == BLAKE2S_HASH_SIZE);
606 1760 : clib_memcpy (b, out, b_len);
607 :
608 1760 : if (c == NULL || c_len == 0)
609 1666 : goto out;
610 :
611 : /* Expand third key: key = sec, data = "b" || 0x3 */
612 94 : out[BLAKE2S_HASH_SIZE] = 3;
613 94 : HMAC (EVP_blake2s256 (), sec, BLAKE2S_HASH_SIZE, out, BLAKE2S_HASH_SIZE + 1,
614 : out, &l);
615 94 : ASSERT (l == BLAKE2S_HASH_SIZE);
616 :
617 94 : clib_memcpy (c, out, c_len);
618 :
619 2832 : out:
620 : /* Clear sensitive data from stack */
621 2832 : wg_secure_zero_memory (sec, BLAKE2S_HASH_SIZE);
622 2832 : wg_secure_zero_memory (out, BLAKE2S_HASH_SIZE + 1);
623 2832 : }
624 :
625 : static bool
626 978 : noise_mix_dh (uint8_t ck[NOISE_HASH_LEN],
627 : uint8_t key[NOISE_SYMMETRIC_KEY_LEN],
628 : const uint8_t private[NOISE_PUBLIC_KEY_LEN],
629 : const uint8_t public[NOISE_PUBLIC_KEY_LEN])
630 : {
631 : uint8_t dh[NOISE_PUBLIC_KEY_LEN];
632 978 : if (!curve25519_gen_shared (dh, private, public))
633 0 : return false;
634 978 : noise_kdf (ck, key, NULL, dh,
635 : NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, NOISE_PUBLIC_KEY_LEN,
636 : ck);
637 978 : wg_secure_zero_memory (dh, NOISE_PUBLIC_KEY_LEN);
638 978 : return true;
639 : }
640 :
641 : static bool
642 782 : noise_mix_ss (uint8_t ck[NOISE_HASH_LEN],
643 : uint8_t key[NOISE_SYMMETRIC_KEY_LEN],
644 : const uint8_t ss[NOISE_PUBLIC_KEY_LEN])
645 : {
646 : static uint8_t null_point[NOISE_PUBLIC_KEY_LEN];
647 782 : if (clib_memcmp (ss, null_point, NOISE_PUBLIC_KEY_LEN) == 0)
648 0 : return false;
649 782 : noise_kdf (ck, key, NULL, ss,
650 : NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, NOISE_PUBLIC_KEY_LEN,
651 : ck);
652 782 : return true;
653 : }
654 :
655 : static void
656 3426 : noise_mix_hash (uint8_t hash[NOISE_HASH_LEN], const uint8_t * src,
657 : size_t src_len)
658 : {
659 : blake2s_state_t blake;
660 :
661 3426 : blake2s_init (&blake, NOISE_HASH_LEN);
662 3426 : blake2s_update (&blake, hash, NOISE_HASH_LEN);
663 3426 : blake2s_update (&blake, src, src_len);
664 3426 : blake2s_final (&blake, hash, NOISE_HASH_LEN);
665 3426 : }
666 :
667 : static void
668 94 : noise_mix_psk (uint8_t ck[NOISE_HASH_LEN], uint8_t hash[NOISE_HASH_LEN],
669 : uint8_t key[NOISE_SYMMETRIC_KEY_LEN],
670 : const uint8_t psk[NOISE_SYMMETRIC_KEY_LEN])
671 : {
672 : uint8_t tmp[NOISE_HASH_LEN];
673 :
674 94 : noise_kdf (ck, tmp, key, psk,
675 : NOISE_HASH_LEN, NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN,
676 : NOISE_SYMMETRIC_KEY_LEN, ck);
677 94 : noise_mix_hash (hash, tmp, NOISE_HASH_LEN);
678 94 : wg_secure_zero_memory (tmp, NOISE_HASH_LEN);
679 94 : }
680 :
681 : static void
682 790 : noise_param_init (uint8_t ck[NOISE_HASH_LEN], uint8_t hash[NOISE_HASH_LEN],
683 : const uint8_t s[NOISE_PUBLIC_KEY_LEN])
684 : {
685 : blake2s_state_t blake;
686 :
687 790 : blake2s (ck, NOISE_HASH_LEN, (uint8_t *) NOISE_HANDSHAKE_NAME,
688 : strlen (NOISE_HANDSHAKE_NAME), NULL, 0);
689 :
690 790 : blake2s_init (&blake, NOISE_HASH_LEN);
691 790 : blake2s_update (&blake, ck, NOISE_HASH_LEN);
692 790 : blake2s_update (&blake, (uint8_t *) NOISE_IDENTIFIER_NAME,
693 : strlen (NOISE_IDENTIFIER_NAME));
694 790 : blake2s_final (&blake, hash, NOISE_HASH_LEN);
695 :
696 790 : noise_mix_hash (hash, s, NOISE_PUBLIC_KEY_LEN);
697 790 : }
698 :
699 : static void
700 369 : noise_msg_encrypt (vlib_main_t * vm, uint8_t * dst, uint8_t * src,
701 : size_t src_len, uint32_t key_idx,
702 : uint8_t hash[NOISE_HASH_LEN])
703 : {
704 : /* Nonce always zero for Noise_IK */
705 369 : wg_chacha20poly1305_calc (vm, src, src_len, dst, hash, NOISE_HASH_LEN, 0,
706 : VNET_CRYPTO_OP_CHACHA20_POLY1305_ENC, key_idx);
707 369 : noise_mix_hash (hash, dst, src_len + NOISE_AUTHTAG_LEN);
708 369 : }
709 :
710 : static bool
711 1297 : noise_msg_decrypt (vlib_main_t * vm, uint8_t * dst, uint8_t * src,
712 : size_t src_len, uint32_t key_idx,
713 : uint8_t hash[NOISE_HASH_LEN])
714 : {
715 : /* Nonce always zero for Noise_IK */
716 1297 : if (!wg_chacha20poly1305_calc (vm, src, src_len, dst, hash, NOISE_HASH_LEN,
717 : 0, VNET_CRYPTO_OP_CHACHA20_POLY1305_DEC,
718 : key_idx))
719 8 : return false;
720 1289 : noise_mix_hash (hash, src, src_len);
721 1289 : return true;
722 : }
723 :
724 : static void
725 884 : noise_msg_ephemeral (uint8_t ck[NOISE_HASH_LEN], uint8_t hash[NOISE_HASH_LEN],
726 : const uint8_t src[NOISE_PUBLIC_KEY_LEN])
727 : {
728 884 : noise_mix_hash (hash, src, NOISE_PUBLIC_KEY_LEN);
729 884 : noise_kdf (ck, NULL, NULL, src, NOISE_HASH_LEN, 0, 0,
730 : NOISE_PUBLIC_KEY_LEN, ck);
731 884 : }
732 :
733 : static void
734 155 : noise_tai64n_now (uint8_t output[NOISE_TIMESTAMP_LEN])
735 : {
736 : uint32_t unix_sec;
737 : uint32_t unix_nanosec;
738 :
739 : uint64_t sec;
740 : uint32_t nsec;
741 :
742 155 : unix_time_now_nsec_fraction (&unix_sec, &unix_nanosec);
743 :
744 : /* Round down the nsec counter to limit precise timing leak. */
745 155 : unix_nanosec &= REJECT_INTERVAL_MASK;
746 :
747 : /* https://cr.yp.to/libtai/tai64.html */
748 155 : sec = htobe64 (0x400000000000000aULL + unix_sec);
749 155 : nsec = htobe32 (unix_nanosec);
750 :
751 : /* memcpy to output buffer, assuming output could be unaligned. */
752 155 : clib_memcpy (output, &sec, sizeof (sec));
753 155 : clib_memcpy (output + sizeof (sec), &nsec, sizeof (nsec));
754 155 : }
755 :
756 : /*
757 : * fd.io coding-style-patch-verification: ON
758 : *
759 : * Local Variables:
760 : * eval: (c-set-style "gnu")
761 : * End:
762 : */
|