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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <openssl/hmac.h>
19 #include <wireguard/wireguard.h>
21 /* This implements Noise_IKpsk2:
25 * -> e, es, s, ss, {t}
26 * <- e, ee, se, psk, {}
29 noise_local_t *noise_local_pool;
31 /* Private functions */
32 static noise_keypair_t *noise_remote_keypair_allocate (noise_remote_t *);
33 static void noise_remote_keypair_free (vlib_main_t * vm, noise_remote_t *,
35 static uint32_t noise_remote_handshake_index_get (noise_remote_t *);
36 static void noise_remote_handshake_index_drop (noise_remote_t *);
38 static uint64_t noise_counter_send (noise_counter_t *);
39 bool noise_counter_recv (noise_counter_t *, uint64_t);
41 static void noise_kdf (uint8_t *, uint8_t *, uint8_t *, const uint8_t *,
42 size_t, size_t, size_t, size_t,
43 const uint8_t[NOISE_HASH_LEN]);
44 static bool noise_mix_dh (uint8_t[NOISE_HASH_LEN],
45 uint8_t[NOISE_SYMMETRIC_KEY_LEN],
46 const uint8_t[NOISE_PUBLIC_KEY_LEN],
47 const uint8_t[NOISE_PUBLIC_KEY_LEN]);
48 static bool noise_mix_ss (uint8_t ck[NOISE_HASH_LEN],
49 uint8_t key[NOISE_SYMMETRIC_KEY_LEN],
50 const uint8_t ss[NOISE_PUBLIC_KEY_LEN]);
51 static void noise_mix_hash (uint8_t[NOISE_HASH_LEN], const uint8_t *, size_t);
52 static void noise_mix_psk (uint8_t[NOISE_HASH_LEN],
53 uint8_t[NOISE_HASH_LEN],
54 uint8_t[NOISE_SYMMETRIC_KEY_LEN],
55 const uint8_t[NOISE_SYMMETRIC_KEY_LEN]);
56 static void noise_param_init (uint8_t[NOISE_HASH_LEN],
57 uint8_t[NOISE_HASH_LEN],
58 const uint8_t[NOISE_PUBLIC_KEY_LEN]);
60 static void noise_msg_encrypt (vlib_main_t * vm, uint8_t *, uint8_t *, size_t,
61 uint32_t key_idx, uint8_t[NOISE_HASH_LEN]);
62 static bool noise_msg_decrypt (vlib_main_t * vm, uint8_t *, uint8_t *, size_t,
63 uint32_t key_idx, uint8_t[NOISE_HASH_LEN]);
64 static void noise_msg_ephemeral (uint8_t[NOISE_HASH_LEN],
65 uint8_t[NOISE_HASH_LEN],
66 const uint8_t src[NOISE_PUBLIC_KEY_LEN]);
68 static void noise_tai64n_now (uint8_t[NOISE_TIMESTAMP_LEN]);
70 static void secure_zero_memory (void *v, size_t n);
72 /* Set/Get noise parameters */
74 noise_local_init (noise_local_t * l, struct noise_upcall *upcall)
76 clib_memset (l, 0, sizeof (*l));
77 l->l_upcall = *upcall;
81 noise_local_set_private (noise_local_t * l,
82 const uint8_t private[NOISE_PUBLIC_KEY_LEN])
84 clib_memcpy (l->l_private, private, NOISE_PUBLIC_KEY_LEN);
86 return curve25519_gen_public (l->l_public, private);
90 noise_remote_init (noise_remote_t * r, uint32_t peer_pool_idx,
91 const uint8_t public[NOISE_PUBLIC_KEY_LEN],
94 clib_memset (r, 0, sizeof (*r));
95 clib_memcpy (r->r_public, public, NOISE_PUBLIC_KEY_LEN);
96 clib_rwlock_init (&r->r_keypair_lock);
97 r->r_peer_idx = peer_pool_idx;
98 r->r_local_idx = noise_local_idx;
99 r->r_handshake.hs_state = HS_ZEROED;
101 noise_remote_precompute (r);
105 noise_remote_precompute (noise_remote_t * r)
107 noise_local_t *l = noise_local_get (r->r_local_idx);
109 if (!curve25519_gen_shared (r->r_ss, l->l_private, r->r_public))
110 clib_memset (r->r_ss, 0, NOISE_PUBLIC_KEY_LEN);
112 noise_remote_handshake_index_drop (r);
113 secure_zero_memory (&r->r_handshake, sizeof (r->r_handshake));
116 /* Handshake functions */
118 noise_create_initiation (vlib_main_t * vm, noise_remote_t * r,
119 uint32_t * s_idx, uint8_t ue[NOISE_PUBLIC_KEY_LEN],
120 uint8_t es[NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN],
121 uint8_t ets[NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN])
123 noise_handshake_t *hs = &r->r_handshake;
124 noise_local_t *l = noise_local_get (r->r_local_idx);
125 uint8_t _key[NOISE_SYMMETRIC_KEY_LEN];
131 vnet_crypto_key_add (vm, VNET_CRYPTO_ALG_CHACHA20_POLY1305, _key,
132 NOISE_SYMMETRIC_KEY_LEN);
133 key = vnet_crypto_get_key (key_idx)->data;
135 noise_param_init (hs->hs_ck, hs->hs_hash, r->r_public);
138 curve25519_gen_secret (hs->hs_e);
139 if (!curve25519_gen_public (ue, hs->hs_e))
141 noise_msg_ephemeral (hs->hs_ck, hs->hs_hash, ue);
144 if (!noise_mix_dh (hs->hs_ck, key, hs->hs_e, r->r_public))
148 noise_msg_encrypt (vm, es, l->l_public, NOISE_PUBLIC_KEY_LEN, key_idx,
152 if (!noise_mix_ss (hs->hs_ck, key, r->r_ss))
156 noise_tai64n_now (ets);
157 noise_msg_encrypt (vm, ets, ets, NOISE_TIMESTAMP_LEN, key_idx, hs->hs_hash);
158 noise_remote_handshake_index_drop (r);
159 hs->hs_state = CREATED_INITIATION;
160 hs->hs_local_index = noise_remote_handshake_index_get (r);
161 *s_idx = hs->hs_local_index;
164 secure_zero_memory (key, NOISE_SYMMETRIC_KEY_LEN);
165 vnet_crypto_key_del (vm, key_idx);
170 noise_consume_initiation (vlib_main_t * vm, noise_local_t * l,
171 noise_remote_t ** rp, uint32_t s_idx,
172 uint8_t ue[NOISE_PUBLIC_KEY_LEN],
173 uint8_t es[NOISE_PUBLIC_KEY_LEN +
175 uint8_t ets[NOISE_TIMESTAMP_LEN +
179 noise_handshake_t hs;
180 uint8_t _key[NOISE_SYMMETRIC_KEY_LEN];
181 uint8_t r_public[NOISE_PUBLIC_KEY_LEN];
182 uint8_t timestamp[NOISE_TIMESTAMP_LEN];
188 vnet_crypto_key_add (vm, VNET_CRYPTO_ALG_CHACHA20_POLY1305, _key,
189 NOISE_SYMMETRIC_KEY_LEN);
190 key = vnet_crypto_get_key (key_idx)->data;
192 noise_param_init (hs.hs_ck, hs.hs_hash, l->l_public);
195 noise_msg_ephemeral (hs.hs_ck, hs.hs_hash, ue);
198 if (!noise_mix_dh (hs.hs_ck, key, l->l_private, ue))
203 if (!noise_msg_decrypt (vm, r_public, es,
204 NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN, key_idx,
208 /* Lookup the remote we received from */
209 if ((r = l->l_upcall.u_remote_get (r_public)) == NULL)
213 if (!noise_mix_ss (hs.hs_ck, key, r->r_ss))
217 if (!noise_msg_decrypt (vm, timestamp, ets,
218 NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN, key_idx,
223 hs.hs_state = CONSUMED_INITIATION;
224 hs.hs_local_index = 0;
225 hs.hs_remote_index = s_idx;
226 clib_memcpy (hs.hs_e, ue, NOISE_PUBLIC_KEY_LEN);
229 if (clib_memcmp (timestamp, r->r_timestamp, NOISE_TIMESTAMP_LEN) > 0)
230 clib_memcpy (r->r_timestamp, timestamp, NOISE_TIMESTAMP_LEN);
235 if (wg_birthdate_has_expired (r->r_last_init, REJECT_INTERVAL))
236 r->r_last_init = vlib_time_now (vm);
240 /* Ok, we're happy to accept this initiation now */
241 noise_remote_handshake_index_drop (r);
247 secure_zero_memory (key, NOISE_SYMMETRIC_KEY_LEN);
248 vnet_crypto_key_del (vm, key_idx);
249 secure_zero_memory (&hs, sizeof (hs));
254 noise_create_response (vlib_main_t * vm, noise_remote_t * r, uint32_t * s_idx,
255 uint32_t * r_idx, uint8_t ue[NOISE_PUBLIC_KEY_LEN],
256 uint8_t en[0 + NOISE_AUTHTAG_LEN])
258 noise_handshake_t *hs = &r->r_handshake;
259 uint8_t _key[NOISE_SYMMETRIC_KEY_LEN];
260 uint8_t e[NOISE_PUBLIC_KEY_LEN];
266 vnet_crypto_key_add (vm, VNET_CRYPTO_ALG_CHACHA20_POLY1305, _key,
267 NOISE_SYMMETRIC_KEY_LEN);
268 key = vnet_crypto_get_key (key_idx)->data;
270 if (hs->hs_state != CONSUMED_INITIATION)
274 curve25519_gen_secret (e);
275 if (!curve25519_gen_public (ue, e))
277 noise_msg_ephemeral (hs->hs_ck, hs->hs_hash, ue);
280 if (!noise_mix_dh (hs->hs_ck, NULL, e, hs->hs_e))
284 if (!noise_mix_dh (hs->hs_ck, NULL, e, r->r_public))
288 noise_mix_psk (hs->hs_ck, hs->hs_hash, key, r->r_psk);
291 noise_msg_encrypt (vm, en, NULL, 0, key_idx, hs->hs_hash);
294 hs->hs_state = CREATED_RESPONSE;
295 hs->hs_local_index = noise_remote_handshake_index_get (r);
296 *r_idx = hs->hs_remote_index;
297 *s_idx = hs->hs_local_index;
300 secure_zero_memory (key, NOISE_SYMMETRIC_KEY_LEN);
301 vnet_crypto_key_del (vm, key_idx);
302 secure_zero_memory (e, NOISE_PUBLIC_KEY_LEN);
307 noise_consume_response (vlib_main_t * vm, noise_remote_t * r, uint32_t s_idx,
308 uint32_t r_idx, uint8_t ue[NOISE_PUBLIC_KEY_LEN],
309 uint8_t en[0 + NOISE_AUTHTAG_LEN])
311 noise_local_t *l = noise_local_get (r->r_local_idx);
312 noise_handshake_t hs;
313 uint8_t _key[NOISE_SYMMETRIC_KEY_LEN];
314 uint8_t preshared_key[NOISE_PUBLIC_KEY_LEN];
320 vnet_crypto_key_add (vm, VNET_CRYPTO_ALG_CHACHA20_POLY1305, _key,
321 NOISE_SYMMETRIC_KEY_LEN);
322 key = vnet_crypto_get_key (key_idx)->data;
325 clib_memcpy (preshared_key, r->r_psk, NOISE_SYMMETRIC_KEY_LEN);
327 if (hs.hs_state != CREATED_INITIATION || hs.hs_local_index != r_idx)
331 noise_msg_ephemeral (hs.hs_ck, hs.hs_hash, ue);
334 if (!noise_mix_dh (hs.hs_ck, NULL, hs.hs_e, ue))
338 if (!noise_mix_dh (hs.hs_ck, NULL, l->l_private, ue))
342 noise_mix_psk (hs.hs_ck, hs.hs_hash, key, preshared_key);
346 if (!noise_msg_decrypt
347 (vm, NULL, en, 0 + NOISE_AUTHTAG_LEN, key_idx, hs.hs_hash))
351 hs.hs_remote_index = s_idx;
353 if (r->r_handshake.hs_state == hs.hs_state &&
354 r->r_handshake.hs_local_index == hs.hs_local_index)
357 r->r_handshake.hs_state = CONSUMED_RESPONSE;
361 secure_zero_memory (&hs, sizeof (hs));
362 secure_zero_memory (key, NOISE_SYMMETRIC_KEY_LEN);
363 vnet_crypto_key_del (vm, key_idx);
368 noise_remote_begin_session (vlib_main_t * vm, noise_remote_t * r)
370 noise_handshake_t *hs = &r->r_handshake;
371 noise_keypair_t kp, *next, *current, *previous;
373 uint8_t key_send[NOISE_SYMMETRIC_KEY_LEN];
374 uint8_t key_recv[NOISE_SYMMETRIC_KEY_LEN];
376 /* We now derive the keypair from the handshake */
377 if (hs->hs_state == CONSUMED_RESPONSE)
379 kp.kp_is_initiator = 1;
380 noise_kdf (key_send, key_recv, NULL, NULL,
381 NOISE_SYMMETRIC_KEY_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, 0,
384 else if (hs->hs_state == CREATED_RESPONSE)
386 kp.kp_is_initiator = 0;
387 noise_kdf (key_recv, key_send, NULL, NULL,
388 NOISE_SYMMETRIC_KEY_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, 0,
397 kp.kp_send_index = vnet_crypto_key_add (vm,
398 VNET_CRYPTO_ALG_CHACHA20_POLY1305,
399 key_send, NOISE_SYMMETRIC_KEY_LEN);
400 kp.kp_recv_index = vnet_crypto_key_add (vm,
401 VNET_CRYPTO_ALG_CHACHA20_POLY1305,
402 key_recv, NOISE_SYMMETRIC_KEY_LEN);
403 kp.kp_local_index = hs->hs_local_index;
404 kp.kp_remote_index = hs->hs_remote_index;
405 kp.kp_birthdate = vlib_time_now (vm);
406 clib_memset (&kp.kp_ctr, 0, sizeof (kp.kp_ctr));
408 /* Now we need to add_new_keypair */
409 clib_rwlock_writer_lock (&r->r_keypair_lock);
410 /* Activate barrier to synchronization keys between threads */
411 vlib_worker_thread_barrier_sync (vm);
413 current = r->r_current;
414 previous = r->r_previous;
416 if (kp.kp_is_initiator)
421 r->r_previous = next;
422 noise_remote_keypair_free (vm, r, ¤t);
426 r->r_previous = current;
429 noise_remote_keypair_free (vm, r, &previous);
431 r->r_current = noise_remote_keypair_allocate (r);
436 noise_remote_keypair_free (vm, r, &next);
437 r->r_previous = NULL;
438 noise_remote_keypair_free (vm, r, &previous);
440 r->r_next = noise_remote_keypair_allocate (r);
443 vlib_worker_thread_barrier_release (vm);
444 clib_rwlock_writer_unlock (&r->r_keypair_lock);
446 secure_zero_memory (&r->r_handshake, sizeof (r->r_handshake));
448 secure_zero_memory (&kp, sizeof (kp));
453 noise_remote_clear (vlib_main_t * vm, noise_remote_t * r)
455 noise_remote_handshake_index_drop (r);
456 secure_zero_memory (&r->r_handshake, sizeof (r->r_handshake));
458 clib_rwlock_writer_lock (&r->r_keypair_lock);
459 noise_remote_keypair_free (vm, r, &r->r_next);
460 noise_remote_keypair_free (vm, r, &r->r_current);
461 noise_remote_keypair_free (vm, r, &r->r_previous);
464 r->r_previous = NULL;
465 clib_rwlock_writer_unlock (&r->r_keypair_lock);
469 noise_remote_expire_current (noise_remote_t * r)
471 clib_rwlock_writer_lock (&r->r_keypair_lock);
472 if (r->r_next != NULL)
473 r->r_next->kp_valid = 0;
474 if (r->r_current != NULL)
475 r->r_current->kp_valid = 0;
476 clib_rwlock_writer_unlock (&r->r_keypair_lock);
480 noise_remote_ready (noise_remote_t * r)
485 clib_rwlock_reader_lock (&r->r_keypair_lock);
486 if ((kp = r->r_current) == NULL ||
488 wg_birthdate_has_expired (kp->kp_birthdate, REJECT_AFTER_TIME) ||
489 kp->kp_ctr.c_recv >= REJECT_AFTER_MESSAGES ||
490 kp->kp_ctr.c_send >= REJECT_AFTER_MESSAGES)
494 clib_rwlock_reader_unlock (&r->r_keypair_lock);
499 chacha20poly1305_calc (vlib_main_t * vm,
506 vnet_crypto_op_id_t op_id,
507 vnet_crypto_key_index_t key_index)
509 vnet_crypto_op_t _op, *op = &_op;
511 u8 tag_[NOISE_AUTHTAG_LEN] = { };
514 clib_memset (iv, 0, 12);
515 clib_memcpy (iv + 4, &nonce, sizeof (nonce));
517 vnet_crypto_op_init (op, op_id);
519 op->tag_len = NOISE_AUTHTAG_LEN;
520 if (op_id == VNET_CRYPTO_OP_CHACHA20_POLY1305_DEC)
522 op->tag = src + src_len - NOISE_AUTHTAG_LEN;
523 src_len -= NOISE_AUTHTAG_LEN;
524 op->flags |= VNET_CRYPTO_OP_FLAG_HMAC_CHECK;
529 op->src = !src ? src_ : src;
533 op->key_index = key_index;
535 op->aad_len = aad_len;
538 vnet_crypto_process_ops (vm, op, 1);
539 if (op_id == VNET_CRYPTO_OP_CHACHA20_POLY1305_ENC)
541 clib_memcpy (dst + src_len, op->tag, NOISE_AUTHTAG_LEN);
544 return (op->status == VNET_CRYPTO_OP_STATUS_COMPLETED);
548 wg_prepare_sync_op (vlib_main_t *vm, vnet_crypto_op_t **crypto_ops, u8 *src,
549 u32 src_len, u8 *dst, u8 *aad, u32 aad_len, u64 nonce,
550 vnet_crypto_op_id_t op_id,
551 vnet_crypto_key_index_t key_index, u32 bi, u8 *iv)
553 vnet_crypto_op_t _op, *op = &_op;
556 clib_memset (iv, 0, 4);
557 clib_memcpy (iv + 4, &nonce, sizeof (nonce));
559 vec_add2_aligned (crypto_ops[0], op, 1, CLIB_CACHE_LINE_BYTES);
560 vnet_crypto_op_init (op, op_id);
562 op->tag_len = NOISE_AUTHTAG_LEN;
563 if (op_id == VNET_CRYPTO_OP_CHACHA20_POLY1305_DEC)
565 op->tag = src + src_len;
566 op->flags |= VNET_CRYPTO_OP_FLAG_HMAC_CHECK;
569 op->tag = dst + src_len;
571 op->src = !src ? src_ : src;
575 op->key_index = key_index;
577 op->aad_len = aad_len;
582 enum noise_state_crypt
583 noise_remote_encrypt (vlib_main_t * vm, noise_remote_t * r, uint32_t * r_idx,
584 uint64_t * nonce, uint8_t * src, size_t srclen,
588 enum noise_state_crypt ret = SC_FAILED;
590 if ((kp = r->r_current) == NULL)
593 /* We confirm that our values are within our tolerances. We want:
595 * - our keypair to be less than REJECT_AFTER_TIME seconds old
596 * - our receive counter to be less than REJECT_AFTER_MESSAGES
597 * - our send counter to be less than REJECT_AFTER_MESSAGES
600 wg_birthdate_has_expired (kp->kp_birthdate, REJECT_AFTER_TIME) ||
601 kp->kp_ctr.c_recv >= REJECT_AFTER_MESSAGES ||
602 ((*nonce = noise_counter_send (&kp->kp_ctr)) > REJECT_AFTER_MESSAGES))
605 /* We encrypt into the same buffer, so the caller must ensure that buf
606 * has NOISE_AUTHTAG_LEN bytes to store the MAC. The nonce and index
607 * are passed back out to the caller through the provided data pointer. */
608 *r_idx = kp->kp_remote_index;
610 chacha20poly1305_calc (vm, src, srclen, dst, NULL, 0, *nonce,
611 VNET_CRYPTO_OP_CHACHA20_POLY1305_ENC,
614 /* If our values are still within tolerances, but we are approaching
615 * the tolerances, we notify the caller with ESTALE that they should
616 * establish a new keypair. The current keypair can continue to be used
617 * until the tolerances are hit. We notify if:
618 * - our send counter is valid and not less than REKEY_AFTER_MESSAGES
619 * - we're the initiator and our keypair is older than
620 * REKEY_AFTER_TIME seconds */
621 ret = SC_KEEP_KEY_FRESH;
622 if ((kp->kp_valid && *nonce >= REKEY_AFTER_MESSAGES) ||
623 (kp->kp_is_initiator &&
624 wg_birthdate_has_expired (kp->kp_birthdate, REKEY_AFTER_TIME)))
632 enum noise_state_crypt
633 noise_sync_remote_decrypt (vlib_main_t *vm, vnet_crypto_op_t **crypto_ops,
634 noise_remote_t *r, uint32_t r_idx, uint64_t nonce,
635 uint8_t *src, size_t srclen, uint8_t *dst, u32 bi,
639 enum noise_state_crypt ret = SC_FAILED;
641 if ((kp = wg_get_active_keypair (r, r_idx)) == NULL)
646 /* We confirm that our values are within our tolerances. These values
647 * are the same as the encrypt routine.
649 * kp_ctr isn't locked here, we're happy to accept a racy read. */
650 if (wg_birthdate_has_expired_opt (kp->kp_birthdate, REJECT_AFTER_TIME,
652 kp->kp_ctr.c_recv >= REJECT_AFTER_MESSAGES)
655 /* Decrypt, then validate the counter. We don't want to validate the
656 * counter before decrypting as we do not know the message is authentic
657 * prior to decryption. */
658 wg_prepare_sync_op (vm, crypto_ops, src, srclen, dst, NULL, 0, nonce,
659 VNET_CRYPTO_OP_CHACHA20_POLY1305_DEC, kp->kp_recv_index,
662 /* If we've received the handshake confirming data packet then move the
663 * next keypair into current. If we do slide the next keypair in, then
664 * we skip the REKEY_AFTER_TIME_RECV check. This is safe to do as a
665 * data packet can't confirm a session that we are an INITIATOR of. */
668 clib_rwlock_writer_lock (&r->r_keypair_lock);
669 if (kp == r->r_next && kp->kp_local_index == r_idx)
671 noise_remote_keypair_free (vm, r, &r->r_previous);
672 r->r_previous = r->r_current;
673 r->r_current = r->r_next;
677 clib_rwlock_writer_unlock (&r->r_keypair_lock);
680 clib_rwlock_writer_unlock (&r->r_keypair_lock);
683 /* Similar to when we encrypt, we want to notify the caller when we
684 * are approaching our tolerances. We notify if:
685 * - we're the initiator and the current keypair is older than
686 * REKEY_AFTER_TIME_RECV seconds. */
687 ret = SC_KEEP_KEY_FRESH;
689 if (kp != NULL && kp->kp_valid && kp->kp_is_initiator &&
690 wg_birthdate_has_expired_opt (kp->kp_birthdate, REKEY_AFTER_TIME_RECV,
699 /* Private functions - these should not be called outside this file under any
701 static noise_keypair_t *
702 noise_remote_keypair_allocate (noise_remote_t * r)
705 kp = clib_mem_alloc (sizeof (*kp));
710 noise_remote_keypair_free (vlib_main_t * vm, noise_remote_t * r,
711 noise_keypair_t ** kp)
713 noise_local_t *local = noise_local_get (r->r_local_idx);
714 struct noise_upcall *u = &local->l_upcall;
717 u->u_index_drop ((*kp)->kp_local_index);
718 vnet_crypto_key_del (vm, (*kp)->kp_send_index);
719 vnet_crypto_key_del (vm, (*kp)->kp_recv_index);
725 noise_remote_handshake_index_get (noise_remote_t * r)
727 noise_local_t *local = noise_local_get (r->r_local_idx);
728 struct noise_upcall *u = &local->l_upcall;
729 return u->u_index_set (r);
733 noise_remote_handshake_index_drop (noise_remote_t * r)
735 noise_handshake_t *hs = &r->r_handshake;
736 noise_local_t *local = noise_local_get (r->r_local_idx);
737 struct noise_upcall *u = &local->l_upcall;
738 if (hs->hs_state != HS_ZEROED)
739 u->u_index_drop (hs->hs_local_index);
743 noise_kdf (uint8_t * a, uint8_t * b, uint8_t * c, const uint8_t * x,
744 size_t a_len, size_t b_len, size_t c_len, size_t x_len,
745 const uint8_t ck[NOISE_HASH_LEN])
747 uint8_t out[BLAKE2S_HASH_SIZE + 1];
748 uint8_t sec[BLAKE2S_HASH_SIZE];
750 /* Extract entropy from "x" into sec */
752 HMAC (EVP_blake2s256 (), ck, NOISE_HASH_LEN, x, x_len, sec, &l);
753 ASSERT (l == BLAKE2S_HASH_SIZE);
754 if (a == NULL || a_len == 0)
757 /* Expand first key: key = sec, data = 0x1 */
759 HMAC (EVP_blake2s256 (), sec, BLAKE2S_HASH_SIZE, out, 1, out, &l);
760 ASSERT (l == BLAKE2S_HASH_SIZE);
761 clib_memcpy (a, out, a_len);
763 if (b == NULL || b_len == 0)
766 /* Expand second key: key = sec, data = "a" || 0x2 */
767 out[BLAKE2S_HASH_SIZE] = 2;
768 HMAC (EVP_blake2s256 (), sec, BLAKE2S_HASH_SIZE, out, BLAKE2S_HASH_SIZE + 1,
770 ASSERT (l == BLAKE2S_HASH_SIZE);
771 clib_memcpy (b, out, b_len);
773 if (c == NULL || c_len == 0)
776 /* Expand third key: key = sec, data = "b" || 0x3 */
777 out[BLAKE2S_HASH_SIZE] = 3;
778 HMAC (EVP_blake2s256 (), sec, BLAKE2S_HASH_SIZE, out, BLAKE2S_HASH_SIZE + 1,
780 ASSERT (l == BLAKE2S_HASH_SIZE);
782 clib_memcpy (c, out, c_len);
785 /* Clear sensitive data from stack */
786 secure_zero_memory (sec, BLAKE2S_HASH_SIZE);
787 secure_zero_memory (out, BLAKE2S_HASH_SIZE + 1);
791 noise_mix_dh (uint8_t ck[NOISE_HASH_LEN],
792 uint8_t key[NOISE_SYMMETRIC_KEY_LEN],
793 const uint8_t private[NOISE_PUBLIC_KEY_LEN],
794 const uint8_t public[NOISE_PUBLIC_KEY_LEN])
796 uint8_t dh[NOISE_PUBLIC_KEY_LEN];
797 if (!curve25519_gen_shared (dh, private, public))
799 noise_kdf (ck, key, NULL, dh,
800 NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, NOISE_PUBLIC_KEY_LEN,
802 secure_zero_memory (dh, NOISE_PUBLIC_KEY_LEN);
807 noise_mix_ss (uint8_t ck[NOISE_HASH_LEN],
808 uint8_t key[NOISE_SYMMETRIC_KEY_LEN],
809 const uint8_t ss[NOISE_PUBLIC_KEY_LEN])
811 static uint8_t null_point[NOISE_PUBLIC_KEY_LEN];
812 if (clib_memcmp (ss, null_point, NOISE_PUBLIC_KEY_LEN) == 0)
814 noise_kdf (ck, key, NULL, ss,
815 NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, NOISE_PUBLIC_KEY_LEN,
821 noise_mix_hash (uint8_t hash[NOISE_HASH_LEN], const uint8_t * src,
824 blake2s_state_t blake;
826 blake2s_init (&blake, NOISE_HASH_LEN);
827 blake2s_update (&blake, hash, NOISE_HASH_LEN);
828 blake2s_update (&blake, src, src_len);
829 blake2s_final (&blake, hash, NOISE_HASH_LEN);
833 noise_mix_psk (uint8_t ck[NOISE_HASH_LEN], uint8_t hash[NOISE_HASH_LEN],
834 uint8_t key[NOISE_SYMMETRIC_KEY_LEN],
835 const uint8_t psk[NOISE_SYMMETRIC_KEY_LEN])
837 uint8_t tmp[NOISE_HASH_LEN];
839 noise_kdf (ck, tmp, key, psk,
840 NOISE_HASH_LEN, NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN,
841 NOISE_SYMMETRIC_KEY_LEN, ck);
842 noise_mix_hash (hash, tmp, NOISE_HASH_LEN);
843 secure_zero_memory (tmp, NOISE_HASH_LEN);
847 noise_param_init (uint8_t ck[NOISE_HASH_LEN], uint8_t hash[NOISE_HASH_LEN],
848 const uint8_t s[NOISE_PUBLIC_KEY_LEN])
850 blake2s_state_t blake;
852 blake2s (ck, NOISE_HASH_LEN, (uint8_t *) NOISE_HANDSHAKE_NAME,
853 strlen (NOISE_HANDSHAKE_NAME), NULL, 0);
855 blake2s_init (&blake, NOISE_HASH_LEN);
856 blake2s_update (&blake, ck, NOISE_HASH_LEN);
857 blake2s_update (&blake, (uint8_t *) NOISE_IDENTIFIER_NAME,
858 strlen (NOISE_IDENTIFIER_NAME));
859 blake2s_final (&blake, hash, NOISE_HASH_LEN);
861 noise_mix_hash (hash, s, NOISE_PUBLIC_KEY_LEN);
865 noise_msg_encrypt (vlib_main_t * vm, uint8_t * dst, uint8_t * src,
866 size_t src_len, uint32_t key_idx,
867 uint8_t hash[NOISE_HASH_LEN])
869 /* Nonce always zero for Noise_IK */
870 chacha20poly1305_calc (vm, src, src_len, dst, hash, NOISE_HASH_LEN, 0,
871 VNET_CRYPTO_OP_CHACHA20_POLY1305_ENC, key_idx);
872 noise_mix_hash (hash, dst, src_len + NOISE_AUTHTAG_LEN);
876 noise_msg_decrypt (vlib_main_t * vm, uint8_t * dst, uint8_t * src,
877 size_t src_len, uint32_t key_idx,
878 uint8_t hash[NOISE_HASH_LEN])
880 /* Nonce always zero for Noise_IK */
881 if (!chacha20poly1305_calc (vm, src, src_len, dst, hash, NOISE_HASH_LEN, 0,
882 VNET_CRYPTO_OP_CHACHA20_POLY1305_DEC, key_idx))
884 noise_mix_hash (hash, src, src_len);
889 noise_msg_ephemeral (uint8_t ck[NOISE_HASH_LEN], uint8_t hash[NOISE_HASH_LEN],
890 const uint8_t src[NOISE_PUBLIC_KEY_LEN])
892 noise_mix_hash (hash, src, NOISE_PUBLIC_KEY_LEN);
893 noise_kdf (ck, NULL, NULL, src, NOISE_HASH_LEN, 0, 0,
894 NOISE_PUBLIC_KEY_LEN, ck);
898 noise_tai64n_now (uint8_t output[NOISE_TIMESTAMP_LEN])
901 uint32_t unix_nanosec;
906 unix_time_now_nsec_fraction (&unix_sec, &unix_nanosec);
908 /* Round down the nsec counter to limit precise timing leak. */
909 unix_nanosec &= REJECT_INTERVAL_MASK;
911 /* https://cr.yp.to/libtai/tai64.html */
912 sec = htobe64 (0x400000000000000aULL + unix_sec);
913 nsec = htobe32 (unix_nanosec);
915 /* memcpy to output buffer, assuming output could be unaligned. */
916 clib_memcpy (output, &sec, sizeof (sec));
917 clib_memcpy (output + sizeof (sec), &nsec, sizeof (nsec));
921 secure_zero_memory (void *v, size_t n)
923 static void *(*const volatile memset_v) (void *, int, size_t) = &memset;
928 * fd.io coding-style-patch-verification: ON
931 * eval: (c-set-style "gnu")