Lines Matching +full:noise +full:- +full:sensitive
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
6 #include "noise.h"
22 * <- s
24 * -> e, es, s, ss, {t}
25 * <- e, ee, se, psk, {}
46 /* Must hold peer->handshake.static_identity->lock */
49 down_write(&peer->handshake.lock); in wg_noise_precompute_static_static()
50 if (!peer->handshake.static_identity->has_identity || in wg_noise_precompute_static_static()
51 !curve25519(peer->handshake.precomputed_static_static, in wg_noise_precompute_static_static()
52 peer->handshake.static_identity->static_private, in wg_noise_precompute_static_static()
53 peer->handshake.remote_static)) in wg_noise_precompute_static_static()
54 memset(peer->handshake.precomputed_static_static, 0, in wg_noise_precompute_static_static()
56 up_write(&peer->handshake.lock); in wg_noise_precompute_static_static()
66 init_rwsem(&handshake->lock); in wg_noise_handshake_init()
67 handshake->entry.type = INDEX_HASHTABLE_HANDSHAKE; in wg_noise_handshake_init()
68 handshake->entry.peer = peer; in wg_noise_handshake_init()
69 memcpy(handshake->remote_static, peer_public_key, NOISE_PUBLIC_KEY_LEN); in wg_noise_handshake_init()
71 memcpy(handshake->preshared_key, peer_preshared_key, in wg_noise_handshake_init()
73 handshake->static_identity = static_identity; in wg_noise_handshake_init()
74 handshake->state = HANDSHAKE_ZEROED; in wg_noise_handshake_init()
80 memset(&handshake->ephemeral_private, 0, NOISE_PUBLIC_KEY_LEN); in handshake_zero()
81 memset(&handshake->remote_ephemeral, 0, NOISE_PUBLIC_KEY_LEN); in handshake_zero()
82 memset(&handshake->hash, 0, NOISE_HASH_LEN); in handshake_zero()
83 memset(&handshake->chaining_key, 0, NOISE_HASH_LEN); in handshake_zero()
84 handshake->remote_index = 0; in handshake_zero()
85 handshake->state = HANDSHAKE_ZEROED; in handshake_zero()
90 down_write(&handshake->lock); in wg_noise_handshake_clear()
92 handshake->entry.peer->device->index_hashtable, in wg_noise_handshake_clear()
93 &handshake->entry); in wg_noise_handshake_clear()
95 up_write(&handshake->lock); in wg_noise_handshake_clear()
104 spin_lock_init(&keypair->receiving_counter.lock); in keypair_create()
105 keypair->internal_id = atomic64_inc_return(&keypair_counter); in keypair_create()
106 keypair->entry.type = INDEX_HASHTABLE_KEYPAIR; in keypair_create()
107 keypair->entry.peer = peer; in keypair_create()
108 kref_init(&keypair->refcount); in keypair_create()
123 keypair->entry.peer->device->dev->name, in keypair_free_kref()
124 keypair->internal_id, in keypair_free_kref()
125 keypair->entry.peer->internal_id); in keypair_free_kref()
126 wg_index_hashtable_remove(keypair->entry.peer->device->index_hashtable, in keypair_free_kref()
127 &keypair->entry); in keypair_free_kref()
128 call_rcu(&keypair->rcu, keypair_free_rcu); in keypair_free_kref()
137 keypair->entry.peer->device->index_hashtable, in wg_noise_keypair_put()
138 &keypair->entry); in wg_noise_keypair_put()
139 kref_put(&keypair->refcount, keypair_free_kref); in wg_noise_keypair_put()
145 "Taking noise keypair reference without holding the RCU BH read lock"); in wg_noise_keypair_get()
146 if (unlikely(!keypair || !kref_get_unless_zero(&keypair->refcount))) in wg_noise_keypair_get()
155 spin_lock_bh(&keypairs->keypair_update_lock); in wg_noise_keypairs_clear()
161 old = rcu_dereference_protected(keypairs->next_keypair, in wg_noise_keypairs_clear()
162 lockdep_is_held(&keypairs->keypair_update_lock)); in wg_noise_keypairs_clear()
163 RCU_INIT_POINTER(keypairs->next_keypair, NULL); in wg_noise_keypairs_clear()
166 old = rcu_dereference_protected(keypairs->previous_keypair, in wg_noise_keypairs_clear()
167 lockdep_is_held(&keypairs->keypair_update_lock)); in wg_noise_keypairs_clear()
168 RCU_INIT_POINTER(keypairs->previous_keypair, NULL); in wg_noise_keypairs_clear()
171 old = rcu_dereference_protected(keypairs->current_keypair, in wg_noise_keypairs_clear()
172 lockdep_is_held(&keypairs->keypair_update_lock)); in wg_noise_keypairs_clear()
173 RCU_INIT_POINTER(keypairs->current_keypair, NULL); in wg_noise_keypairs_clear()
176 spin_unlock_bh(&keypairs->keypair_update_lock); in wg_noise_keypairs_clear()
183 wg_noise_handshake_clear(&peer->handshake); in wg_noise_expire_current_peer_keypairs()
184 wg_noise_reset_last_sent_handshake(&peer->last_sent_handshake); in wg_noise_expire_current_peer_keypairs()
186 spin_lock_bh(&peer->keypairs.keypair_update_lock); in wg_noise_expire_current_peer_keypairs()
187 keypair = rcu_dereference_protected(peer->keypairs.next_keypair, in wg_noise_expire_current_peer_keypairs()
188 lockdep_is_held(&peer->keypairs.keypair_update_lock)); in wg_noise_expire_current_peer_keypairs()
190 keypair->sending.is_valid = false; in wg_noise_expire_current_peer_keypairs()
191 keypair = rcu_dereference_protected(peer->keypairs.current_keypair, in wg_noise_expire_current_peer_keypairs()
192 lockdep_is_held(&peer->keypairs.keypair_update_lock)); in wg_noise_expire_current_peer_keypairs()
194 keypair->sending.is_valid = false; in wg_noise_expire_current_peer_keypairs()
195 spin_unlock_bh(&peer->keypairs.keypair_update_lock); in wg_noise_expire_current_peer_keypairs()
203 spin_lock_bh(&keypairs->keypair_update_lock); in add_new_keypair()
204 previous_keypair = rcu_dereference_protected(keypairs->previous_keypair, in add_new_keypair()
205 lockdep_is_held(&keypairs->keypair_update_lock)); in add_new_keypair()
206 next_keypair = rcu_dereference_protected(keypairs->next_keypair, in add_new_keypair()
207 lockdep_is_held(&keypairs->keypair_update_lock)); in add_new_keypair()
208 current_keypair = rcu_dereference_protected(keypairs->current_keypair, in add_new_keypair()
209 lockdep_is_held(&keypairs->keypair_update_lock)); in add_new_keypair()
210 if (new_keypair->i_am_the_initiator) { in add_new_keypair()
225 RCU_INIT_POINTER(keypairs->next_keypair, NULL); in add_new_keypair()
226 rcu_assign_pointer(keypairs->previous_keypair, in add_new_keypair()
232 rcu_assign_pointer(keypairs->previous_keypair, in add_new_keypair()
238 rcu_assign_pointer(keypairs->current_keypair, new_keypair); in add_new_keypair()
245 rcu_assign_pointer(keypairs->next_keypair, new_keypair); in add_new_keypair()
247 RCU_INIT_POINTER(keypairs->previous_keypair, NULL); in add_new_keypair()
250 spin_unlock_bh(&keypairs->keypair_update_lock); in add_new_keypair()
261 rcu_access_pointer(keypairs->next_keypair); in wg_noise_received_with_keypair()
265 spin_lock_bh(&keypairs->keypair_update_lock); in wg_noise_received_with_keypair()
270 rcu_dereference_protected(keypairs->next_keypair, in wg_noise_received_with_keypair()
271 lockdep_is_held(&keypairs->keypair_update_lock)))) { in wg_noise_received_with_keypair()
272 spin_unlock_bh(&keypairs->keypair_update_lock); in wg_noise_received_with_keypair()
280 old_keypair = rcu_dereference_protected(keypairs->previous_keypair, in wg_noise_received_with_keypair()
281 lockdep_is_held(&keypairs->keypair_update_lock)); in wg_noise_received_with_keypair()
282 rcu_assign_pointer(keypairs->previous_keypair, in wg_noise_received_with_keypair()
283 rcu_dereference_protected(keypairs->current_keypair, in wg_noise_received_with_keypair()
284 lockdep_is_held(&keypairs->keypair_update_lock))); in wg_noise_received_with_keypair()
286 rcu_assign_pointer(keypairs->current_keypair, received_keypair); in wg_noise_received_with_keypair()
287 RCU_INIT_POINTER(keypairs->next_keypair, NULL); in wg_noise_received_with_keypair()
289 spin_unlock_bh(&keypairs->keypair_update_lock); in wg_noise_received_with_keypair()
293 /* Must hold static_identity->lock */
298 memcpy(static_identity->static_private, private_key, in wg_noise_set_static_identity_private_key()
300 curve25519_clamp_secret(static_identity->static_private); in wg_noise_set_static_identity_private_key()
301 static_identity->has_identity = curve25519_generate_public( in wg_noise_set_static_identity_private_key()
302 static_identity->static_public, private_key); in wg_noise_set_static_identity_private_key()
341 * - https://eprint.iacr.org/2010/264.pdf
342 * - https://tools.ietf.org/html/rfc5869
373 /* Expand second key: key = secret, data = first-key || 0x2 */ in kdf()
381 /* Expand third key: key = secret, data = second-key || 0x3 */ in kdf()
387 /* Clear sensitive data from stack */ in kdf()
397 kdf(first_dst->key, second_dst->key, NULL, NULL, in derive_keys()
400 first_dst->birthdate = second_dst->birthdate = birthdate; in derive_keys()
401 first_dst->is_valid = second_dst->is_valid = true; in derive_keys()
504 * round down the nanoseconds part to the closest rounded-down power of in tai64n_now()
529 down_read(&handshake->static_identity->lock); in wg_noise_handshake_create_initiation()
530 down_write(&handshake->lock); in wg_noise_handshake_create_initiation()
532 if (unlikely(!handshake->static_identity->has_identity)) in wg_noise_handshake_create_initiation()
535 dst->header.type = cpu_to_le32(MESSAGE_HANDSHAKE_INITIATION); in wg_noise_handshake_create_initiation()
537 handshake_init(handshake->chaining_key, handshake->hash, in wg_noise_handshake_create_initiation()
538 handshake->remote_static); in wg_noise_handshake_create_initiation()
541 curve25519_generate_secret(handshake->ephemeral_private); in wg_noise_handshake_create_initiation()
542 if (!curve25519_generate_public(dst->unencrypted_ephemeral, in wg_noise_handshake_create_initiation()
543 handshake->ephemeral_private)) in wg_noise_handshake_create_initiation()
545 message_ephemeral(dst->unencrypted_ephemeral, in wg_noise_handshake_create_initiation()
546 dst->unencrypted_ephemeral, handshake->chaining_key, in wg_noise_handshake_create_initiation()
547 handshake->hash); in wg_noise_handshake_create_initiation()
550 if (!mix_dh(handshake->chaining_key, key, handshake->ephemeral_private, in wg_noise_handshake_create_initiation()
551 handshake->remote_static)) in wg_noise_handshake_create_initiation()
555 message_encrypt(dst->encrypted_static, in wg_noise_handshake_create_initiation()
556 handshake->static_identity->static_public, in wg_noise_handshake_create_initiation()
557 NOISE_PUBLIC_KEY_LEN, key, handshake->hash); in wg_noise_handshake_create_initiation()
560 if (!mix_precomputed_dh(handshake->chaining_key, key, in wg_noise_handshake_create_initiation()
561 handshake->precomputed_static_static)) in wg_noise_handshake_create_initiation()
566 message_encrypt(dst->encrypted_timestamp, timestamp, in wg_noise_handshake_create_initiation()
567 NOISE_TIMESTAMP_LEN, key, handshake->hash); in wg_noise_handshake_create_initiation()
569 dst->sender_index = wg_index_hashtable_insert( in wg_noise_handshake_create_initiation()
570 handshake->entry.peer->device->index_hashtable, in wg_noise_handshake_create_initiation()
571 &handshake->entry); in wg_noise_handshake_create_initiation()
573 handshake->state = HANDSHAKE_CREATED_INITIATION; in wg_noise_handshake_create_initiation()
577 up_write(&handshake->lock); in wg_noise_handshake_create_initiation()
578 up_read(&handshake->static_identity->lock); in wg_noise_handshake_create_initiation()
598 down_read(&wg->static_identity.lock); in wg_noise_handshake_consume_initiation()
599 if (unlikely(!wg->static_identity.has_identity)) in wg_noise_handshake_consume_initiation()
602 handshake_init(chaining_key, hash, wg->static_identity.static_public); in wg_noise_handshake_consume_initiation()
605 message_ephemeral(e, src->unencrypted_ephemeral, chaining_key, hash); in wg_noise_handshake_consume_initiation()
608 if (!mix_dh(chaining_key, key, wg->static_identity.static_private, e)) in wg_noise_handshake_consume_initiation()
612 if (!message_decrypt(s, src->encrypted_static, in wg_noise_handshake_consume_initiation()
613 sizeof(src->encrypted_static), key, hash)) in wg_noise_handshake_consume_initiation()
617 peer = wg_pubkey_hashtable_lookup(wg->peer_hashtable, s); in wg_noise_handshake_consume_initiation()
620 handshake = &peer->handshake; in wg_noise_handshake_consume_initiation()
624 handshake->precomputed_static_static)) in wg_noise_handshake_consume_initiation()
628 if (!message_decrypt(t, src->encrypted_timestamp, in wg_noise_handshake_consume_initiation()
629 sizeof(src->encrypted_timestamp), key, hash)) in wg_noise_handshake_consume_initiation()
632 down_read(&handshake->lock); in wg_noise_handshake_consume_initiation()
633 replay_attack = memcmp(t, handshake->latest_timestamp, in wg_noise_handshake_consume_initiation()
635 flood_attack = (s64)handshake->last_initiation_consumption + in wg_noise_handshake_consume_initiation()
638 up_read(&handshake->lock); in wg_noise_handshake_consume_initiation()
643 down_write(&handshake->lock); in wg_noise_handshake_consume_initiation()
644 memcpy(handshake->remote_ephemeral, e, NOISE_PUBLIC_KEY_LEN); in wg_noise_handshake_consume_initiation()
645 if (memcmp(t, handshake->latest_timestamp, NOISE_TIMESTAMP_LEN) > 0) in wg_noise_handshake_consume_initiation()
646 memcpy(handshake->latest_timestamp, t, NOISE_TIMESTAMP_LEN); in wg_noise_handshake_consume_initiation()
647 memcpy(handshake->hash, hash, NOISE_HASH_LEN); in wg_noise_handshake_consume_initiation()
648 memcpy(handshake->chaining_key, chaining_key, NOISE_HASH_LEN); in wg_noise_handshake_consume_initiation()
649 handshake->remote_index = src->sender_index; in wg_noise_handshake_consume_initiation()
651 if ((s64)(handshake->last_initiation_consumption - initiation_consumption) < 0) in wg_noise_handshake_consume_initiation()
652 handshake->last_initiation_consumption = initiation_consumption; in wg_noise_handshake_consume_initiation()
653 handshake->state = HANDSHAKE_CONSUMED_INITIATION; in wg_noise_handshake_consume_initiation()
654 up_write(&handshake->lock); in wg_noise_handshake_consume_initiation()
661 up_read(&wg->static_identity.lock); in wg_noise_handshake_consume_initiation()
678 down_read(&handshake->static_identity->lock); in wg_noise_handshake_create_response()
679 down_write(&handshake->lock); in wg_noise_handshake_create_response()
681 if (handshake->state != HANDSHAKE_CONSUMED_INITIATION) in wg_noise_handshake_create_response()
684 dst->header.type = cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE); in wg_noise_handshake_create_response()
685 dst->receiver_index = handshake->remote_index; in wg_noise_handshake_create_response()
688 curve25519_generate_secret(handshake->ephemeral_private); in wg_noise_handshake_create_response()
689 if (!curve25519_generate_public(dst->unencrypted_ephemeral, in wg_noise_handshake_create_response()
690 handshake->ephemeral_private)) in wg_noise_handshake_create_response()
692 message_ephemeral(dst->unencrypted_ephemeral, in wg_noise_handshake_create_response()
693 dst->unencrypted_ephemeral, handshake->chaining_key, in wg_noise_handshake_create_response()
694 handshake->hash); in wg_noise_handshake_create_response()
697 if (!mix_dh(handshake->chaining_key, NULL, handshake->ephemeral_private, in wg_noise_handshake_create_response()
698 handshake->remote_ephemeral)) in wg_noise_handshake_create_response()
702 if (!mix_dh(handshake->chaining_key, NULL, handshake->ephemeral_private, in wg_noise_handshake_create_response()
703 handshake->remote_static)) in wg_noise_handshake_create_response()
707 mix_psk(handshake->chaining_key, handshake->hash, key, in wg_noise_handshake_create_response()
708 handshake->preshared_key); in wg_noise_handshake_create_response()
711 message_encrypt(dst->encrypted_nothing, NULL, 0, key, handshake->hash); in wg_noise_handshake_create_response()
713 dst->sender_index = wg_index_hashtable_insert( in wg_noise_handshake_create_response()
714 handshake->entry.peer->device->index_hashtable, in wg_noise_handshake_create_response()
715 &handshake->entry); in wg_noise_handshake_create_response()
717 handshake->state = HANDSHAKE_CREATED_RESPONSE; in wg_noise_handshake_create_response()
721 up_write(&handshake->lock); in wg_noise_handshake_create_response()
722 up_read(&handshake->static_identity->lock); in wg_noise_handshake_create_response()
742 down_read(&wg->static_identity.lock); in wg_noise_handshake_consume_response()
744 if (unlikely(!wg->static_identity.has_identity)) in wg_noise_handshake_consume_response()
748 wg->index_hashtable, INDEX_HASHTABLE_HANDSHAKE, in wg_noise_handshake_consume_response()
749 src->receiver_index, &peer); in wg_noise_handshake_consume_response()
753 down_read(&handshake->lock); in wg_noise_handshake_consume_response()
754 state = handshake->state; in wg_noise_handshake_consume_response()
755 memcpy(hash, handshake->hash, NOISE_HASH_LEN); in wg_noise_handshake_consume_response()
756 memcpy(chaining_key, handshake->chaining_key, NOISE_HASH_LEN); in wg_noise_handshake_consume_response()
757 memcpy(ephemeral_private, handshake->ephemeral_private, in wg_noise_handshake_consume_response()
759 memcpy(preshared_key, handshake->preshared_key, in wg_noise_handshake_consume_response()
761 up_read(&handshake->lock); in wg_noise_handshake_consume_response()
767 message_ephemeral(e, src->unencrypted_ephemeral, chaining_key, hash); in wg_noise_handshake_consume_response()
774 if (!mix_dh(chaining_key, NULL, wg->static_identity.static_private, e)) in wg_noise_handshake_consume_response()
781 if (!message_decrypt(NULL, src->encrypted_nothing, in wg_noise_handshake_consume_response()
782 sizeof(src->encrypted_nothing), key, hash)) in wg_noise_handshake_consume_response()
786 down_write(&handshake->lock); in wg_noise_handshake_consume_response()
790 if (handshake->state != state) { in wg_noise_handshake_consume_response()
791 up_write(&handshake->lock); in wg_noise_handshake_consume_response()
794 memcpy(handshake->remote_ephemeral, e, NOISE_PUBLIC_KEY_LEN); in wg_noise_handshake_consume_response()
795 memcpy(handshake->hash, hash, NOISE_HASH_LEN); in wg_noise_handshake_consume_response()
796 memcpy(handshake->chaining_key, chaining_key, NOISE_HASH_LEN); in wg_noise_handshake_consume_response()
797 handshake->remote_index = src->sender_index; in wg_noise_handshake_consume_response()
798 handshake->state = HANDSHAKE_CONSUMED_RESPONSE; in wg_noise_handshake_consume_response()
799 up_write(&handshake->lock); in wg_noise_handshake_consume_response()
812 up_read(&wg->static_identity.lock); in wg_noise_handshake_consume_response()
822 down_write(&handshake->lock); in wg_noise_handshake_begin_session()
823 if (handshake->state != HANDSHAKE_CREATED_RESPONSE && in wg_noise_handshake_begin_session()
824 handshake->state != HANDSHAKE_CONSUMED_RESPONSE) in wg_noise_handshake_begin_session()
827 new_keypair = keypair_create(handshake->entry.peer); in wg_noise_handshake_begin_session()
830 new_keypair->i_am_the_initiator = handshake->state == in wg_noise_handshake_begin_session()
832 new_keypair->remote_index = handshake->remote_index; in wg_noise_handshake_begin_session()
834 if (new_keypair->i_am_the_initiator) in wg_noise_handshake_begin_session()
835 derive_keys(&new_keypair->sending, &new_keypair->receiving, in wg_noise_handshake_begin_session()
836 handshake->chaining_key); in wg_noise_handshake_begin_session()
838 derive_keys(&new_keypair->receiving, &new_keypair->sending, in wg_noise_handshake_begin_session()
839 handshake->chaining_key); in wg_noise_handshake_begin_session()
844 handshake)->is_dead))) { in wg_noise_handshake_begin_session()
847 handshake->entry.peer->device->dev->name, in wg_noise_handshake_begin_session()
848 new_keypair->internal_id, in wg_noise_handshake_begin_session()
849 handshake->entry.peer->internal_id); in wg_noise_handshake_begin_session()
851 handshake->entry.peer->device->index_hashtable, in wg_noise_handshake_begin_session()
852 &handshake->entry, &new_keypair->entry); in wg_noise_handshake_begin_session()
859 up_write(&handshake->lock); in wg_noise_handshake_begin_session()