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(¤t->kp_can_send); 865744bfb21SJohn Baldwin if (!keep_key_fresh) 866744bfb21SJohn Baldwin goto out; 867744bfb21SJohn Baldwin #ifdef __LP64__ 868e32e1a16SJohn Baldwin nonce = atomic_load_64(¤t->kp_nonce_send); 869744bfb21SJohn Baldwin #else 870744bfb21SJohn Baldwin rw_rlock(¤t->kp_nonce_lock); 871744bfb21SJohn Baldwin nonce = current->kp_nonce_send; 872744bfb21SJohn Baldwin rw_runlock(¤t->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(¤t->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