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); 226744bfb21SJohn Baldwin explicit_bzero(l, sizeof(*l)); 227744bfb21SJohn Baldwin free(l, M_NOISE); 228744bfb21SJohn Baldwin } 229744bfb21SJohn Baldwin } 230744bfb21SJohn Baldwin 231744bfb21SJohn Baldwin void 232744bfb21SJohn Baldwin noise_local_free(struct noise_local *l, void (*cleanup)(struct noise_local *)) 233744bfb21SJohn Baldwin { 234744bfb21SJohn Baldwin l->l_cleanup = cleanup; 235744bfb21SJohn Baldwin noise_local_put(l); 236744bfb21SJohn Baldwin } 237744bfb21SJohn Baldwin 238744bfb21SJohn Baldwin void * 239744bfb21SJohn Baldwin noise_local_arg(struct noise_local *l) 240744bfb21SJohn Baldwin { 241744bfb21SJohn Baldwin return (l->l_arg); 242744bfb21SJohn Baldwin } 243744bfb21SJohn Baldwin 244744bfb21SJohn Baldwin void 245744bfb21SJohn Baldwin noise_local_private(struct noise_local *l, const uint8_t private[NOISE_PUBLIC_KEY_LEN]) 246744bfb21SJohn Baldwin { 247744bfb21SJohn Baldwin struct epoch_tracker et; 248744bfb21SJohn Baldwin struct noise_remote *r; 249744bfb21SJohn Baldwin size_t i; 250744bfb21SJohn Baldwin 251744bfb21SJohn Baldwin rw_wlock(&l->l_identity_lock); 252744bfb21SJohn Baldwin memcpy(l->l_private, private, NOISE_PUBLIC_KEY_LEN); 253744bfb21SJohn Baldwin curve25519_clamp_secret(l->l_private); 254744bfb21SJohn Baldwin l->l_has_identity = curve25519_generate_public(l->l_public, l->l_private); 255744bfb21SJohn Baldwin 256744bfb21SJohn Baldwin NET_EPOCH_ENTER(et); 257744bfb21SJohn Baldwin for (i = 0; i < HT_REMOTE_SIZE; i++) { 258744bfb21SJohn Baldwin CK_LIST_FOREACH(r, &l->l_remote_hash[i], r_entry) { 259744bfb21SJohn Baldwin noise_precompute_ss(l, r); 260744bfb21SJohn Baldwin noise_remote_expire_current(r); 261744bfb21SJohn Baldwin } 262744bfb21SJohn Baldwin } 263744bfb21SJohn Baldwin NET_EPOCH_EXIT(et); 264744bfb21SJohn Baldwin rw_wunlock(&l->l_identity_lock); 265744bfb21SJohn Baldwin } 266744bfb21SJohn Baldwin 267744bfb21SJohn Baldwin int 268744bfb21SJohn Baldwin noise_local_keys(struct noise_local *l, uint8_t public[NOISE_PUBLIC_KEY_LEN], 269744bfb21SJohn Baldwin uint8_t private[NOISE_PUBLIC_KEY_LEN]) 270744bfb21SJohn Baldwin { 271744bfb21SJohn Baldwin int has_identity; 272744bfb21SJohn Baldwin rw_rlock(&l->l_identity_lock); 273744bfb21SJohn Baldwin if ((has_identity = l->l_has_identity)) { 274744bfb21SJohn Baldwin if (public != NULL) 275744bfb21SJohn Baldwin memcpy(public, l->l_public, NOISE_PUBLIC_KEY_LEN); 276744bfb21SJohn Baldwin if (private != NULL) 277744bfb21SJohn Baldwin memcpy(private, l->l_private, NOISE_PUBLIC_KEY_LEN); 278744bfb21SJohn Baldwin } 279744bfb21SJohn Baldwin rw_runlock(&l->l_identity_lock); 280744bfb21SJohn Baldwin return (has_identity ? 0 : ENXIO); 281744bfb21SJohn Baldwin } 282744bfb21SJohn Baldwin 283744bfb21SJohn Baldwin static void 284744bfb21SJohn Baldwin noise_precompute_ss(struct noise_local *l, struct noise_remote *r) 285744bfb21SJohn Baldwin { 286744bfb21SJohn Baldwin rw_wlock(&r->r_handshake_lock); 287744bfb21SJohn Baldwin if (!l->l_has_identity || 288744bfb21SJohn Baldwin !curve25519(r->r_ss, l->l_private, r->r_public)) 289744bfb21SJohn Baldwin bzero(r->r_ss, NOISE_PUBLIC_KEY_LEN); 290744bfb21SJohn Baldwin rw_wunlock(&r->r_handshake_lock); 291744bfb21SJohn Baldwin } 292744bfb21SJohn Baldwin 293744bfb21SJohn Baldwin /* Remote configuration */ 294744bfb21SJohn Baldwin struct noise_remote * 295744bfb21SJohn Baldwin noise_remote_alloc(struct noise_local *l, void *arg, 296744bfb21SJohn Baldwin const uint8_t public[NOISE_PUBLIC_KEY_LEN]) 297744bfb21SJohn Baldwin { 298744bfb21SJohn Baldwin struct noise_remote *r; 299744bfb21SJohn Baldwin 300744bfb21SJohn Baldwin r = malloc(sizeof(*r), M_NOISE, M_WAITOK | M_ZERO); 301744bfb21SJohn Baldwin memcpy(r->r_public, public, NOISE_PUBLIC_KEY_LEN); 302744bfb21SJohn Baldwin 303744bfb21SJohn Baldwin rw_init(&r->r_handshake_lock, "noise_handshake"); 304744bfb21SJohn Baldwin r->r_handshake_state = HANDSHAKE_DEAD; 305744bfb21SJohn Baldwin r->r_last_sent = TIMER_RESET; 306744bfb21SJohn Baldwin r->r_last_init_recv = TIMER_RESET; 307744bfb21SJohn Baldwin noise_precompute_ss(l, r); 308744bfb21SJohn Baldwin 309744bfb21SJohn Baldwin refcount_init(&r->r_refcnt, 1); 310744bfb21SJohn Baldwin r->r_local = noise_local_ref(l); 311744bfb21SJohn Baldwin r->r_arg = arg; 312744bfb21SJohn Baldwin 313744bfb21SJohn Baldwin mtx_init(&r->r_keypair_mtx, "noise_keypair", NULL, MTX_DEF); 314744bfb21SJohn Baldwin 315744bfb21SJohn Baldwin return (r); 316744bfb21SJohn Baldwin } 317744bfb21SJohn Baldwin 318744bfb21SJohn Baldwin int 319744bfb21SJohn Baldwin noise_remote_enable(struct noise_remote *r) 320744bfb21SJohn Baldwin { 321744bfb21SJohn Baldwin struct noise_local *l = r->r_local; 322744bfb21SJohn Baldwin uint64_t idx; 323744bfb21SJohn Baldwin int ret = 0; 324744bfb21SJohn Baldwin 325744bfb21SJohn Baldwin /* Insert to hashtable */ 326744bfb21SJohn Baldwin idx = siphash24(l->l_hash_key, r->r_public, NOISE_PUBLIC_KEY_LEN) & HT_REMOTE_MASK; 327744bfb21SJohn Baldwin 328744bfb21SJohn Baldwin mtx_lock(&l->l_remote_mtx); 329744bfb21SJohn Baldwin if (!r->r_entry_inserted) { 330744bfb21SJohn Baldwin if (l->l_remote_num < MAX_REMOTE_PER_LOCAL) { 331744bfb21SJohn Baldwin r->r_entry_inserted = true; 332744bfb21SJohn Baldwin l->l_remote_num++; 333744bfb21SJohn Baldwin CK_LIST_INSERT_HEAD(&l->l_remote_hash[idx], r, r_entry); 334744bfb21SJohn Baldwin } else { 335744bfb21SJohn Baldwin ret = ENOSPC; 336744bfb21SJohn Baldwin } 337744bfb21SJohn Baldwin } 338744bfb21SJohn Baldwin mtx_unlock(&l->l_remote_mtx); 339744bfb21SJohn Baldwin 340744bfb21SJohn Baldwin return ret; 341744bfb21SJohn Baldwin } 342744bfb21SJohn Baldwin 343744bfb21SJohn Baldwin void 344744bfb21SJohn Baldwin noise_remote_disable(struct noise_remote *r) 345744bfb21SJohn Baldwin { 346744bfb21SJohn Baldwin struct noise_local *l = r->r_local; 347744bfb21SJohn Baldwin /* remove from hashtable */ 348744bfb21SJohn Baldwin mtx_lock(&l->l_remote_mtx); 349744bfb21SJohn Baldwin if (r->r_entry_inserted) { 350744bfb21SJohn Baldwin r->r_entry_inserted = false; 351744bfb21SJohn Baldwin CK_LIST_REMOVE(r, r_entry); 352744bfb21SJohn Baldwin l->l_remote_num--; 353744bfb21SJohn Baldwin }; 354744bfb21SJohn Baldwin mtx_unlock(&l->l_remote_mtx); 355744bfb21SJohn Baldwin } 356744bfb21SJohn Baldwin 357744bfb21SJohn Baldwin struct noise_remote * 358744bfb21SJohn Baldwin noise_remote_lookup(struct noise_local *l, const uint8_t public[NOISE_PUBLIC_KEY_LEN]) 359744bfb21SJohn Baldwin { 360744bfb21SJohn Baldwin struct epoch_tracker et; 361744bfb21SJohn Baldwin struct noise_remote *r, *ret = NULL; 362744bfb21SJohn Baldwin uint64_t idx; 363744bfb21SJohn Baldwin 364744bfb21SJohn Baldwin idx = siphash24(l->l_hash_key, public, NOISE_PUBLIC_KEY_LEN) & HT_REMOTE_MASK; 365744bfb21SJohn Baldwin 366744bfb21SJohn Baldwin NET_EPOCH_ENTER(et); 367744bfb21SJohn Baldwin CK_LIST_FOREACH(r, &l->l_remote_hash[idx], r_entry) { 368744bfb21SJohn Baldwin if (timingsafe_bcmp(r->r_public, public, NOISE_PUBLIC_KEY_LEN) == 0) { 369744bfb21SJohn Baldwin if (refcount_acquire_if_not_zero(&r->r_refcnt)) 370744bfb21SJohn Baldwin ret = r; 371744bfb21SJohn Baldwin break; 372744bfb21SJohn Baldwin } 373744bfb21SJohn Baldwin } 374744bfb21SJohn Baldwin NET_EPOCH_EXIT(et); 375744bfb21SJohn Baldwin return (ret); 376744bfb21SJohn Baldwin } 377744bfb21SJohn Baldwin 378744bfb21SJohn Baldwin static void 379744bfb21SJohn Baldwin noise_remote_index_insert(struct noise_local *l, struct noise_remote *r) 380744bfb21SJohn Baldwin { 381744bfb21SJohn Baldwin struct noise_index *i, *r_i = &r->r_index; 382744bfb21SJohn Baldwin struct epoch_tracker et; 383744bfb21SJohn Baldwin uint32_t idx; 384744bfb21SJohn Baldwin 385744bfb21SJohn Baldwin noise_remote_index_remove(l, r); 386744bfb21SJohn Baldwin 387744bfb21SJohn Baldwin NET_EPOCH_ENTER(et); 388744bfb21SJohn Baldwin assign_id: 389744bfb21SJohn Baldwin r_i->i_local_index = arc4random(); 390744bfb21SJohn Baldwin idx = r_i->i_local_index & HT_INDEX_MASK; 391744bfb21SJohn Baldwin CK_LIST_FOREACH(i, &l->l_index_hash[idx], i_entry) { 392744bfb21SJohn Baldwin if (i->i_local_index == r_i->i_local_index) 393744bfb21SJohn Baldwin goto assign_id; 394744bfb21SJohn Baldwin } 395744bfb21SJohn Baldwin 396744bfb21SJohn Baldwin mtx_lock(&l->l_index_mtx); 397744bfb21SJohn Baldwin CK_LIST_FOREACH(i, &l->l_index_hash[idx], i_entry) { 398744bfb21SJohn Baldwin if (i->i_local_index == r_i->i_local_index) { 399744bfb21SJohn Baldwin mtx_unlock(&l->l_index_mtx); 400744bfb21SJohn Baldwin goto assign_id; 401744bfb21SJohn Baldwin } 402744bfb21SJohn Baldwin } 403744bfb21SJohn Baldwin CK_LIST_INSERT_HEAD(&l->l_index_hash[idx], r_i, i_entry); 404744bfb21SJohn Baldwin mtx_unlock(&l->l_index_mtx); 405744bfb21SJohn Baldwin 406744bfb21SJohn Baldwin NET_EPOCH_EXIT(et); 407744bfb21SJohn Baldwin } 408744bfb21SJohn Baldwin 409744bfb21SJohn Baldwin static struct noise_remote * 410744bfb21SJohn Baldwin noise_remote_index_lookup(struct noise_local *l, uint32_t idx0, bool lookup_keypair) 411744bfb21SJohn Baldwin { 412744bfb21SJohn Baldwin struct epoch_tracker et; 413744bfb21SJohn Baldwin struct noise_index *i; 414744bfb21SJohn Baldwin struct noise_keypair *kp; 415744bfb21SJohn Baldwin struct noise_remote *r, *ret = NULL; 416744bfb21SJohn Baldwin uint32_t idx = idx0 & HT_INDEX_MASK; 417744bfb21SJohn Baldwin 418744bfb21SJohn Baldwin NET_EPOCH_ENTER(et); 419744bfb21SJohn Baldwin CK_LIST_FOREACH(i, &l->l_index_hash[idx], i_entry) { 420744bfb21SJohn Baldwin if (i->i_local_index == idx0) { 421744bfb21SJohn Baldwin if (!i->i_is_keypair) { 422744bfb21SJohn Baldwin r = (struct noise_remote *) i; 423744bfb21SJohn Baldwin } else if (lookup_keypair) { 424744bfb21SJohn Baldwin kp = (struct noise_keypair *) i; 425744bfb21SJohn Baldwin r = kp->kp_remote; 426744bfb21SJohn Baldwin } else { 427744bfb21SJohn Baldwin break; 428744bfb21SJohn Baldwin } 429744bfb21SJohn Baldwin if (refcount_acquire_if_not_zero(&r->r_refcnt)) 430744bfb21SJohn Baldwin ret = r; 431744bfb21SJohn Baldwin break; 432744bfb21SJohn Baldwin } 433744bfb21SJohn Baldwin } 434744bfb21SJohn Baldwin NET_EPOCH_EXIT(et); 435744bfb21SJohn Baldwin return (ret); 436744bfb21SJohn Baldwin } 437744bfb21SJohn Baldwin 438744bfb21SJohn Baldwin struct noise_remote * 439744bfb21SJohn Baldwin noise_remote_index(struct noise_local *l, uint32_t idx) 440744bfb21SJohn Baldwin { 441744bfb21SJohn Baldwin return noise_remote_index_lookup(l, idx, true); 442744bfb21SJohn Baldwin } 443744bfb21SJohn Baldwin 444744bfb21SJohn Baldwin static int 445744bfb21SJohn Baldwin noise_remote_index_remove(struct noise_local *l, struct noise_remote *r) 446744bfb21SJohn Baldwin { 447744bfb21SJohn Baldwin rw_assert(&r->r_handshake_lock, RA_WLOCKED); 448744bfb21SJohn Baldwin if (r->r_handshake_state != HANDSHAKE_DEAD) { 449744bfb21SJohn Baldwin mtx_lock(&l->l_index_mtx); 450744bfb21SJohn Baldwin r->r_handshake_state = HANDSHAKE_DEAD; 451744bfb21SJohn Baldwin CK_LIST_REMOVE(&r->r_index, i_entry); 452744bfb21SJohn Baldwin mtx_unlock(&l->l_index_mtx); 453744bfb21SJohn Baldwin return (1); 454744bfb21SJohn Baldwin } 455744bfb21SJohn Baldwin return (0); 456744bfb21SJohn Baldwin } 457744bfb21SJohn Baldwin 458744bfb21SJohn Baldwin struct noise_remote * 459744bfb21SJohn Baldwin noise_remote_ref(struct noise_remote *r) 460744bfb21SJohn Baldwin { 461744bfb21SJohn Baldwin refcount_acquire(&r->r_refcnt); 462744bfb21SJohn Baldwin return (r); 463744bfb21SJohn Baldwin } 464744bfb21SJohn Baldwin 465744bfb21SJohn Baldwin static void 466744bfb21SJohn Baldwin noise_remote_smr_free(struct epoch_context *smr) 467744bfb21SJohn Baldwin { 468744bfb21SJohn Baldwin struct noise_remote *r; 469744bfb21SJohn Baldwin r = __containerof(smr, struct noise_remote, r_smr); 470744bfb21SJohn Baldwin if (r->r_cleanup != NULL) 471744bfb21SJohn Baldwin r->r_cleanup(r); 472744bfb21SJohn Baldwin noise_local_put(r->r_local); 473744bfb21SJohn Baldwin rw_destroy(&r->r_handshake_lock); 474744bfb21SJohn Baldwin mtx_destroy(&r->r_keypair_mtx); 475744bfb21SJohn Baldwin explicit_bzero(r, sizeof(*r)); 476744bfb21SJohn Baldwin free(r, M_NOISE); 477744bfb21SJohn Baldwin } 478744bfb21SJohn Baldwin 479744bfb21SJohn Baldwin void 480744bfb21SJohn Baldwin noise_remote_put(struct noise_remote *r) 481744bfb21SJohn Baldwin { 482744bfb21SJohn Baldwin if (refcount_release(&r->r_refcnt)) 483744bfb21SJohn Baldwin NET_EPOCH_CALL(noise_remote_smr_free, &r->r_smr); 484744bfb21SJohn Baldwin } 485744bfb21SJohn Baldwin 486744bfb21SJohn Baldwin void 487744bfb21SJohn Baldwin noise_remote_free(struct noise_remote *r, void (*cleanup)(struct noise_remote *)) 488744bfb21SJohn Baldwin { 489744bfb21SJohn Baldwin r->r_cleanup = cleanup; 490744bfb21SJohn Baldwin noise_remote_disable(r); 491744bfb21SJohn Baldwin 492744bfb21SJohn Baldwin /* now clear all keypairs and handshakes, then put this reference */ 493744bfb21SJohn Baldwin noise_remote_handshake_clear(r); 494744bfb21SJohn Baldwin noise_remote_keypairs_clear(r); 495744bfb21SJohn Baldwin noise_remote_put(r); 496744bfb21SJohn Baldwin } 497744bfb21SJohn Baldwin 498744bfb21SJohn Baldwin struct noise_local * 499744bfb21SJohn Baldwin noise_remote_local(struct noise_remote *r) 500744bfb21SJohn Baldwin { 501744bfb21SJohn Baldwin return (noise_local_ref(r->r_local)); 502744bfb21SJohn Baldwin } 503744bfb21SJohn Baldwin 504744bfb21SJohn Baldwin void * 505744bfb21SJohn Baldwin noise_remote_arg(struct noise_remote *r) 506744bfb21SJohn Baldwin { 507744bfb21SJohn Baldwin return (r->r_arg); 508744bfb21SJohn Baldwin } 509744bfb21SJohn Baldwin 510744bfb21SJohn Baldwin void 511744bfb21SJohn Baldwin noise_remote_set_psk(struct noise_remote *r, 512744bfb21SJohn Baldwin const uint8_t psk[NOISE_SYMMETRIC_KEY_LEN]) 513744bfb21SJohn Baldwin { 514744bfb21SJohn Baldwin rw_wlock(&r->r_handshake_lock); 515744bfb21SJohn Baldwin if (psk == NULL) 516744bfb21SJohn Baldwin bzero(r->r_psk, NOISE_SYMMETRIC_KEY_LEN); 517744bfb21SJohn Baldwin else 518744bfb21SJohn Baldwin memcpy(r->r_psk, psk, NOISE_SYMMETRIC_KEY_LEN); 519744bfb21SJohn Baldwin rw_wunlock(&r->r_handshake_lock); 520744bfb21SJohn Baldwin } 521744bfb21SJohn Baldwin 522744bfb21SJohn Baldwin int 523744bfb21SJohn Baldwin noise_remote_keys(struct noise_remote *r, uint8_t public[NOISE_PUBLIC_KEY_LEN], 524744bfb21SJohn Baldwin uint8_t psk[NOISE_SYMMETRIC_KEY_LEN]) 525744bfb21SJohn Baldwin { 526744bfb21SJohn Baldwin static uint8_t null_psk[NOISE_SYMMETRIC_KEY_LEN]; 527744bfb21SJohn Baldwin int ret; 528744bfb21SJohn Baldwin 529744bfb21SJohn Baldwin if (public != NULL) 530744bfb21SJohn Baldwin memcpy(public, r->r_public, NOISE_PUBLIC_KEY_LEN); 531744bfb21SJohn Baldwin 532744bfb21SJohn Baldwin rw_rlock(&r->r_handshake_lock); 533744bfb21SJohn Baldwin if (psk != NULL) 534744bfb21SJohn Baldwin memcpy(psk, r->r_psk, NOISE_SYMMETRIC_KEY_LEN); 535744bfb21SJohn Baldwin ret = timingsafe_bcmp(r->r_psk, null_psk, NOISE_SYMMETRIC_KEY_LEN); 536744bfb21SJohn Baldwin rw_runlock(&r->r_handshake_lock); 537744bfb21SJohn Baldwin 538744bfb21SJohn Baldwin return (ret ? 0 : ENOENT); 539744bfb21SJohn Baldwin } 540744bfb21SJohn Baldwin 541744bfb21SJohn Baldwin int 542744bfb21SJohn Baldwin noise_remote_initiation_expired(struct noise_remote *r) 543744bfb21SJohn Baldwin { 544744bfb21SJohn Baldwin int expired; 545744bfb21SJohn Baldwin rw_rlock(&r->r_handshake_lock); 546744bfb21SJohn Baldwin expired = noise_timer_expired(r->r_last_sent, REKEY_TIMEOUT, 0); 547744bfb21SJohn Baldwin rw_runlock(&r->r_handshake_lock); 548744bfb21SJohn Baldwin return (expired); 549744bfb21SJohn Baldwin } 550744bfb21SJohn Baldwin 551744bfb21SJohn Baldwin void 552744bfb21SJohn Baldwin noise_remote_handshake_clear(struct noise_remote *r) 553744bfb21SJohn Baldwin { 554744bfb21SJohn Baldwin rw_wlock(&r->r_handshake_lock); 555744bfb21SJohn Baldwin if (noise_remote_index_remove(r->r_local, r)) 556744bfb21SJohn Baldwin bzero(&r->r_handshake, sizeof(r->r_handshake)); 557744bfb21SJohn Baldwin r->r_last_sent = TIMER_RESET; 558744bfb21SJohn Baldwin rw_wunlock(&r->r_handshake_lock); 559744bfb21SJohn Baldwin } 560744bfb21SJohn Baldwin 561744bfb21SJohn Baldwin void 562744bfb21SJohn Baldwin noise_remote_keypairs_clear(struct noise_remote *r) 563744bfb21SJohn Baldwin { 564744bfb21SJohn Baldwin struct noise_keypair *kp; 565744bfb21SJohn Baldwin 566744bfb21SJohn Baldwin mtx_lock(&r->r_keypair_mtx); 567*e32e1a16SJohn Baldwin kp = atomic_load_ptr(&r->r_next); 568*e32e1a16SJohn Baldwin atomic_store_ptr(&r->r_next, NULL); 569744bfb21SJohn Baldwin noise_keypair_drop(kp); 570744bfb21SJohn Baldwin 571*e32e1a16SJohn Baldwin kp = atomic_load_ptr(&r->r_current); 572*e32e1a16SJohn Baldwin atomic_store_ptr(&r->r_current, NULL); 573744bfb21SJohn Baldwin noise_keypair_drop(kp); 574744bfb21SJohn Baldwin 575*e32e1a16SJohn Baldwin kp = atomic_load_ptr(&r->r_previous); 576*e32e1a16SJohn Baldwin atomic_store_ptr(&r->r_previous, NULL); 577744bfb21SJohn Baldwin noise_keypair_drop(kp); 578744bfb21SJohn Baldwin mtx_unlock(&r->r_keypair_mtx); 579744bfb21SJohn Baldwin } 580744bfb21SJohn Baldwin 581744bfb21SJohn Baldwin static void 582744bfb21SJohn Baldwin noise_remote_expire_current(struct noise_remote *r) 583744bfb21SJohn Baldwin { 584744bfb21SJohn Baldwin struct epoch_tracker et; 585744bfb21SJohn Baldwin struct noise_keypair *kp; 586744bfb21SJohn Baldwin 587744bfb21SJohn Baldwin noise_remote_handshake_clear(r); 588744bfb21SJohn Baldwin 589744bfb21SJohn Baldwin NET_EPOCH_ENTER(et); 590*e32e1a16SJohn Baldwin kp = atomic_load_ptr(&r->r_next); 591744bfb21SJohn Baldwin if (kp != NULL) 592*e32e1a16SJohn Baldwin atomic_store_bool(&kp->kp_can_send, false); 593*e32e1a16SJohn Baldwin kp = atomic_load_ptr(&r->r_current); 594744bfb21SJohn Baldwin if (kp != NULL) 595*e32e1a16SJohn Baldwin atomic_store_bool(&kp->kp_can_send, false); 596744bfb21SJohn Baldwin NET_EPOCH_EXIT(et); 597744bfb21SJohn Baldwin } 598744bfb21SJohn Baldwin 599744bfb21SJohn Baldwin /* Keypair functions */ 600744bfb21SJohn Baldwin static void 601744bfb21SJohn Baldwin noise_add_new_keypair(struct noise_local *l, struct noise_remote *r, 602744bfb21SJohn Baldwin struct noise_keypair *kp) 603744bfb21SJohn Baldwin { 604744bfb21SJohn Baldwin struct noise_keypair *next, *current, *previous; 605744bfb21SJohn Baldwin struct noise_index *r_i = &r->r_index; 606744bfb21SJohn Baldwin 607744bfb21SJohn Baldwin /* Insert into the keypair table */ 608744bfb21SJohn Baldwin mtx_lock(&r->r_keypair_mtx); 609*e32e1a16SJohn Baldwin next = atomic_load_ptr(&r->r_next); 610*e32e1a16SJohn Baldwin current = atomic_load_ptr(&r->r_current); 611*e32e1a16SJohn Baldwin previous = atomic_load_ptr(&r->r_previous); 612744bfb21SJohn Baldwin 613744bfb21SJohn Baldwin if (kp->kp_is_initiator) { 614744bfb21SJohn Baldwin if (next != NULL) { 615*e32e1a16SJohn Baldwin atomic_store_ptr(&r->r_next, NULL); 616*e32e1a16SJohn Baldwin atomic_store_ptr(&r->r_previous, next); 617744bfb21SJohn Baldwin noise_keypair_drop(current); 618744bfb21SJohn Baldwin } else { 619*e32e1a16SJohn Baldwin atomic_store_ptr(&r->r_previous, current); 620744bfb21SJohn Baldwin } 621744bfb21SJohn Baldwin noise_keypair_drop(previous); 622*e32e1a16SJohn Baldwin atomic_store_ptr(&r->r_current, kp); 623744bfb21SJohn Baldwin } else { 624*e32e1a16SJohn Baldwin atomic_store_ptr(&r->r_next, kp); 625744bfb21SJohn Baldwin noise_keypair_drop(next); 626*e32e1a16SJohn Baldwin atomic_store_ptr(&r->r_previous, NULL); 627744bfb21SJohn Baldwin noise_keypair_drop(previous); 628744bfb21SJohn Baldwin 629744bfb21SJohn Baldwin } 630744bfb21SJohn Baldwin mtx_unlock(&r->r_keypair_mtx); 631744bfb21SJohn Baldwin 632744bfb21SJohn Baldwin /* Insert into index table */ 633744bfb21SJohn Baldwin rw_assert(&r->r_handshake_lock, RA_WLOCKED); 634744bfb21SJohn Baldwin 635744bfb21SJohn Baldwin kp->kp_index.i_is_keypair = true; 636744bfb21SJohn Baldwin kp->kp_index.i_local_index = r_i->i_local_index; 637744bfb21SJohn Baldwin kp->kp_index.i_remote_index = r_i->i_remote_index; 638744bfb21SJohn Baldwin 639744bfb21SJohn Baldwin mtx_lock(&l->l_index_mtx); 640744bfb21SJohn Baldwin CK_LIST_INSERT_BEFORE(r_i, &kp->kp_index, i_entry); 641744bfb21SJohn Baldwin r->r_handshake_state = HANDSHAKE_DEAD; 642744bfb21SJohn Baldwin CK_LIST_REMOVE(r_i, i_entry); 643744bfb21SJohn Baldwin mtx_unlock(&l->l_index_mtx); 644744bfb21SJohn Baldwin 645744bfb21SJohn Baldwin explicit_bzero(&r->r_handshake, sizeof(r->r_handshake)); 646744bfb21SJohn Baldwin } 647744bfb21SJohn Baldwin 648744bfb21SJohn Baldwin static int 649744bfb21SJohn Baldwin noise_begin_session(struct noise_remote *r) 650744bfb21SJohn Baldwin { 651744bfb21SJohn Baldwin struct noise_keypair *kp; 652744bfb21SJohn Baldwin 653744bfb21SJohn Baldwin rw_assert(&r->r_handshake_lock, RA_WLOCKED); 654744bfb21SJohn Baldwin 655744bfb21SJohn Baldwin if ((kp = malloc(sizeof(*kp), M_NOISE, M_NOWAIT | M_ZERO)) == NULL) 656744bfb21SJohn Baldwin return (ENOSPC); 657744bfb21SJohn Baldwin 658744bfb21SJohn Baldwin refcount_init(&kp->kp_refcnt, 1); 659744bfb21SJohn Baldwin kp->kp_can_send = true; 660744bfb21SJohn Baldwin kp->kp_is_initiator = r->r_handshake_state == HANDSHAKE_INITIATOR; 661744bfb21SJohn Baldwin kp->kp_birthdate = getsbinuptime(); 662744bfb21SJohn Baldwin kp->kp_remote = noise_remote_ref(r); 663744bfb21SJohn Baldwin 664744bfb21SJohn Baldwin if (kp->kp_is_initiator) 665744bfb21SJohn Baldwin noise_kdf(kp->kp_send, kp->kp_recv, NULL, NULL, 666744bfb21SJohn Baldwin NOISE_SYMMETRIC_KEY_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, 0, 667744bfb21SJohn Baldwin r->r_handshake.hs_ck); 668744bfb21SJohn Baldwin else 669744bfb21SJohn Baldwin noise_kdf(kp->kp_recv, kp->kp_send, NULL, NULL, 670744bfb21SJohn Baldwin NOISE_SYMMETRIC_KEY_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, 0, 671744bfb21SJohn Baldwin r->r_handshake.hs_ck); 672744bfb21SJohn Baldwin 673744bfb21SJohn Baldwin rw_init(&kp->kp_nonce_lock, "noise_nonce"); 674744bfb21SJohn Baldwin 675744bfb21SJohn Baldwin noise_add_new_keypair(r->r_local, r, kp); 676744bfb21SJohn Baldwin return (0); 677744bfb21SJohn Baldwin } 678744bfb21SJohn Baldwin 679744bfb21SJohn Baldwin struct noise_keypair * 680744bfb21SJohn Baldwin noise_keypair_lookup(struct noise_local *l, uint32_t idx0) 681744bfb21SJohn Baldwin { 682744bfb21SJohn Baldwin struct epoch_tracker et; 683744bfb21SJohn Baldwin struct noise_index *i; 684744bfb21SJohn Baldwin struct noise_keypair *kp, *ret = NULL; 685744bfb21SJohn Baldwin uint32_t idx = idx0 & HT_INDEX_MASK; 686744bfb21SJohn Baldwin 687744bfb21SJohn Baldwin NET_EPOCH_ENTER(et); 688744bfb21SJohn Baldwin CK_LIST_FOREACH(i, &l->l_index_hash[idx], i_entry) { 689744bfb21SJohn Baldwin if (i->i_local_index == idx0 && i->i_is_keypair) { 690744bfb21SJohn Baldwin kp = (struct noise_keypair *) i; 691744bfb21SJohn Baldwin if (refcount_acquire_if_not_zero(&kp->kp_refcnt)) 692744bfb21SJohn Baldwin ret = kp; 693744bfb21SJohn Baldwin break; 694744bfb21SJohn Baldwin } 695744bfb21SJohn Baldwin } 696744bfb21SJohn Baldwin NET_EPOCH_EXIT(et); 697744bfb21SJohn Baldwin return (ret); 698744bfb21SJohn Baldwin } 699744bfb21SJohn Baldwin 700744bfb21SJohn Baldwin struct noise_keypair * 701744bfb21SJohn Baldwin noise_keypair_current(struct noise_remote *r) 702744bfb21SJohn Baldwin { 703744bfb21SJohn Baldwin struct epoch_tracker et; 704744bfb21SJohn Baldwin struct noise_keypair *kp, *ret = NULL; 705744bfb21SJohn Baldwin 706744bfb21SJohn Baldwin NET_EPOCH_ENTER(et); 707*e32e1a16SJohn Baldwin kp = atomic_load_ptr(&r->r_current); 708*e32e1a16SJohn Baldwin if (kp != NULL && atomic_load_bool(&kp->kp_can_send)) { 709744bfb21SJohn Baldwin if (noise_timer_expired(kp->kp_birthdate, REJECT_AFTER_TIME, 0)) 710*e32e1a16SJohn Baldwin atomic_store_bool(&kp->kp_can_send, false); 711744bfb21SJohn Baldwin else if (refcount_acquire_if_not_zero(&kp->kp_refcnt)) 712744bfb21SJohn Baldwin ret = kp; 713744bfb21SJohn Baldwin } 714744bfb21SJohn Baldwin NET_EPOCH_EXIT(et); 715744bfb21SJohn Baldwin return (ret); 716744bfb21SJohn Baldwin } 717744bfb21SJohn Baldwin 718744bfb21SJohn Baldwin struct noise_keypair * 719744bfb21SJohn Baldwin noise_keypair_ref(struct noise_keypair *kp) 720744bfb21SJohn Baldwin { 721744bfb21SJohn Baldwin refcount_acquire(&kp->kp_refcnt); 722744bfb21SJohn Baldwin return (kp); 723744bfb21SJohn Baldwin } 724744bfb21SJohn Baldwin 725744bfb21SJohn Baldwin int 726744bfb21SJohn Baldwin noise_keypair_received_with(struct noise_keypair *kp) 727744bfb21SJohn Baldwin { 728744bfb21SJohn Baldwin struct noise_keypair *old; 729744bfb21SJohn Baldwin struct noise_remote *r = kp->kp_remote; 730744bfb21SJohn Baldwin 731*e32e1a16SJohn Baldwin if (kp != atomic_load_ptr(&r->r_next)) 732744bfb21SJohn Baldwin return (0); 733744bfb21SJohn Baldwin 734744bfb21SJohn Baldwin mtx_lock(&r->r_keypair_mtx); 735*e32e1a16SJohn Baldwin if (kp != atomic_load_ptr(&r->r_next)) { 736744bfb21SJohn Baldwin mtx_unlock(&r->r_keypair_mtx); 737744bfb21SJohn Baldwin return (0); 738744bfb21SJohn Baldwin } 739744bfb21SJohn Baldwin 740*e32e1a16SJohn Baldwin old = atomic_load_ptr(&r->r_previous); 741*e32e1a16SJohn Baldwin atomic_store_ptr(&r->r_previous, atomic_load_ptr(&r->r_current)); 742744bfb21SJohn Baldwin noise_keypair_drop(old); 743*e32e1a16SJohn Baldwin atomic_store_ptr(&r->r_current, kp); 744*e32e1a16SJohn Baldwin atomic_store_ptr(&r->r_next, NULL); 745744bfb21SJohn Baldwin mtx_unlock(&r->r_keypair_mtx); 746744bfb21SJohn Baldwin 747744bfb21SJohn Baldwin return (ECONNRESET); 748744bfb21SJohn Baldwin } 749744bfb21SJohn Baldwin 750744bfb21SJohn Baldwin static void 751744bfb21SJohn Baldwin noise_keypair_smr_free(struct epoch_context *smr) 752744bfb21SJohn Baldwin { 753744bfb21SJohn Baldwin struct noise_keypair *kp; 754744bfb21SJohn Baldwin kp = __containerof(smr, struct noise_keypair, kp_smr); 755744bfb21SJohn Baldwin noise_remote_put(kp->kp_remote); 756744bfb21SJohn Baldwin rw_destroy(&kp->kp_nonce_lock); 757744bfb21SJohn Baldwin explicit_bzero(kp, sizeof(*kp)); 758744bfb21SJohn Baldwin free(kp, M_NOISE); 759744bfb21SJohn Baldwin } 760744bfb21SJohn Baldwin 761744bfb21SJohn Baldwin void 762744bfb21SJohn Baldwin noise_keypair_put(struct noise_keypair *kp) 763744bfb21SJohn Baldwin { 764744bfb21SJohn Baldwin if (refcount_release(&kp->kp_refcnt)) 765744bfb21SJohn Baldwin NET_EPOCH_CALL(noise_keypair_smr_free, &kp->kp_smr); 766744bfb21SJohn Baldwin } 767744bfb21SJohn Baldwin 768744bfb21SJohn Baldwin static void 769744bfb21SJohn Baldwin noise_keypair_drop(struct noise_keypair *kp) 770744bfb21SJohn Baldwin { 771744bfb21SJohn Baldwin struct noise_remote *r; 772744bfb21SJohn Baldwin struct noise_local *l; 773744bfb21SJohn Baldwin 774744bfb21SJohn Baldwin if (kp == NULL) 775744bfb21SJohn Baldwin return; 776744bfb21SJohn Baldwin 777744bfb21SJohn Baldwin r = kp->kp_remote; 778744bfb21SJohn Baldwin l = r->r_local; 779744bfb21SJohn Baldwin 780744bfb21SJohn Baldwin mtx_lock(&l->l_index_mtx); 781744bfb21SJohn Baldwin CK_LIST_REMOVE(&kp->kp_index, i_entry); 782744bfb21SJohn Baldwin mtx_unlock(&l->l_index_mtx); 783744bfb21SJohn Baldwin 784744bfb21SJohn Baldwin noise_keypair_put(kp); 785744bfb21SJohn Baldwin } 786744bfb21SJohn Baldwin 787744bfb21SJohn Baldwin struct noise_remote * 788744bfb21SJohn Baldwin noise_keypair_remote(struct noise_keypair *kp) 789744bfb21SJohn Baldwin { 790744bfb21SJohn Baldwin return (noise_remote_ref(kp->kp_remote)); 791744bfb21SJohn Baldwin } 792744bfb21SJohn Baldwin 793744bfb21SJohn Baldwin int 794744bfb21SJohn Baldwin noise_keypair_nonce_next(struct noise_keypair *kp, uint64_t *send) 795744bfb21SJohn Baldwin { 796*e32e1a16SJohn Baldwin if (!atomic_load_bool(&kp->kp_can_send)) 797744bfb21SJohn Baldwin return (EINVAL); 798744bfb21SJohn Baldwin 799744bfb21SJohn Baldwin #ifdef __LP64__ 800*e32e1a16SJohn Baldwin *send = atomic_fetchadd_64(&kp->kp_nonce_send, 1); 801744bfb21SJohn Baldwin #else 802744bfb21SJohn Baldwin rw_wlock(&kp->kp_nonce_lock); 803744bfb21SJohn Baldwin *send = kp->kp_nonce_send++; 804744bfb21SJohn Baldwin rw_wunlock(&kp->kp_nonce_lock); 805744bfb21SJohn Baldwin #endif 806744bfb21SJohn Baldwin if (*send < REJECT_AFTER_MESSAGES) 807744bfb21SJohn Baldwin return (0); 808*e32e1a16SJohn Baldwin atomic_store_bool(&kp->kp_can_send, false); 809744bfb21SJohn Baldwin return (EINVAL); 810744bfb21SJohn Baldwin } 811744bfb21SJohn Baldwin 812744bfb21SJohn Baldwin int 813744bfb21SJohn Baldwin noise_keypair_nonce_check(struct noise_keypair *kp, uint64_t recv) 814744bfb21SJohn Baldwin { 815744bfb21SJohn Baldwin unsigned long index, index_current, top, i, bit; 816744bfb21SJohn Baldwin int ret = EEXIST; 817744bfb21SJohn Baldwin 818744bfb21SJohn Baldwin rw_wlock(&kp->kp_nonce_lock); 819744bfb21SJohn Baldwin 820744bfb21SJohn Baldwin if (__predict_false(kp->kp_nonce_recv >= REJECT_AFTER_MESSAGES + 1 || 821744bfb21SJohn Baldwin recv >= REJECT_AFTER_MESSAGES)) 822744bfb21SJohn Baldwin goto error; 823744bfb21SJohn Baldwin 824744bfb21SJohn Baldwin ++recv; 825744bfb21SJohn Baldwin 826744bfb21SJohn Baldwin if (__predict_false(recv + COUNTER_WINDOW_SIZE < kp->kp_nonce_recv)) 827744bfb21SJohn Baldwin goto error; 828744bfb21SJohn Baldwin 829744bfb21SJohn Baldwin index = recv >> COUNTER_ORDER; 830744bfb21SJohn Baldwin 831744bfb21SJohn Baldwin if (__predict_true(recv > kp->kp_nonce_recv)) { 832744bfb21SJohn Baldwin index_current = kp->kp_nonce_recv >> COUNTER_ORDER; 833744bfb21SJohn Baldwin top = MIN(index - index_current, COUNTER_BITS_TOTAL / COUNTER_BITS); 834744bfb21SJohn Baldwin for (i = 1; i <= top; i++) 835744bfb21SJohn Baldwin kp->kp_backtrack[ 836744bfb21SJohn Baldwin (i + index_current) & 837744bfb21SJohn Baldwin ((COUNTER_BITS_TOTAL / COUNTER_BITS) - 1)] = 0; 838744bfb21SJohn Baldwin #ifdef __LP64__ 839*e32e1a16SJohn Baldwin atomic_store_64(&kp->kp_nonce_recv, recv); 840744bfb21SJohn Baldwin #else 841744bfb21SJohn Baldwin kp->kp_nonce_recv = recv; 842744bfb21SJohn Baldwin #endif 843744bfb21SJohn Baldwin } 844744bfb21SJohn Baldwin 845744bfb21SJohn Baldwin index &= (COUNTER_BITS_TOTAL / COUNTER_BITS) - 1; 846744bfb21SJohn Baldwin bit = 1ul << (recv & (COUNTER_BITS - 1)); 847744bfb21SJohn Baldwin if (kp->kp_backtrack[index] & bit) 848744bfb21SJohn Baldwin goto error; 849744bfb21SJohn Baldwin 850744bfb21SJohn Baldwin kp->kp_backtrack[index] |= bit; 851744bfb21SJohn Baldwin ret = 0; 852744bfb21SJohn Baldwin error: 853744bfb21SJohn Baldwin rw_wunlock(&kp->kp_nonce_lock); 854744bfb21SJohn Baldwin return (ret); 855744bfb21SJohn Baldwin } 856744bfb21SJohn Baldwin 857744bfb21SJohn Baldwin int 858744bfb21SJohn Baldwin noise_keep_key_fresh_send(struct noise_remote *r) 859744bfb21SJohn Baldwin { 860744bfb21SJohn Baldwin struct epoch_tracker et; 861744bfb21SJohn Baldwin struct noise_keypair *current; 862744bfb21SJohn Baldwin int keep_key_fresh; 863744bfb21SJohn Baldwin uint64_t nonce; 864744bfb21SJohn Baldwin 865744bfb21SJohn Baldwin NET_EPOCH_ENTER(et); 866*e32e1a16SJohn Baldwin current = atomic_load_ptr(&r->r_current); 867*e32e1a16SJohn Baldwin keep_key_fresh = current != NULL && atomic_load_bool(¤t->kp_can_send); 868744bfb21SJohn Baldwin if (!keep_key_fresh) 869744bfb21SJohn Baldwin goto out; 870744bfb21SJohn Baldwin #ifdef __LP64__ 871*e32e1a16SJohn Baldwin nonce = atomic_load_64(¤t->kp_nonce_send); 872744bfb21SJohn Baldwin #else 873744bfb21SJohn Baldwin rw_rlock(¤t->kp_nonce_lock); 874744bfb21SJohn Baldwin nonce = current->kp_nonce_send; 875744bfb21SJohn Baldwin rw_runlock(¤t->kp_nonce_lock); 876744bfb21SJohn Baldwin #endif 877744bfb21SJohn Baldwin keep_key_fresh = nonce > REKEY_AFTER_MESSAGES; 878744bfb21SJohn Baldwin if (keep_key_fresh) 879744bfb21SJohn Baldwin goto out; 880744bfb21SJohn Baldwin keep_key_fresh = current->kp_is_initiator && noise_timer_expired(current->kp_birthdate, REKEY_AFTER_TIME, 0); 881744bfb21SJohn Baldwin 882744bfb21SJohn Baldwin out: 883744bfb21SJohn Baldwin NET_EPOCH_EXIT(et); 884744bfb21SJohn Baldwin return (keep_key_fresh ? ESTALE : 0); 885744bfb21SJohn Baldwin } 886744bfb21SJohn Baldwin 887744bfb21SJohn Baldwin int 888744bfb21SJohn Baldwin noise_keep_key_fresh_recv(struct noise_remote *r) 889744bfb21SJohn Baldwin { 890744bfb21SJohn Baldwin struct epoch_tracker et; 891744bfb21SJohn Baldwin struct noise_keypair *current; 892744bfb21SJohn Baldwin int keep_key_fresh; 893744bfb21SJohn Baldwin 894744bfb21SJohn Baldwin NET_EPOCH_ENTER(et); 895*e32e1a16SJohn Baldwin current = atomic_load_ptr(&r->r_current); 896*e32e1a16SJohn Baldwin keep_key_fresh = current != NULL && atomic_load_bool(¤t->kp_can_send) && 897744bfb21SJohn Baldwin current->kp_is_initiator && noise_timer_expired(current->kp_birthdate, 898744bfb21SJohn Baldwin REJECT_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT, 0); 899744bfb21SJohn Baldwin NET_EPOCH_EXIT(et); 900744bfb21SJohn Baldwin 901744bfb21SJohn Baldwin return (keep_key_fresh ? ESTALE : 0); 902744bfb21SJohn Baldwin } 903744bfb21SJohn Baldwin 904744bfb21SJohn Baldwin int 905744bfb21SJohn Baldwin noise_keypair_encrypt(struct noise_keypair *kp, uint32_t *r_idx, uint64_t nonce, struct mbuf *m) 906744bfb21SJohn Baldwin { 907744bfb21SJohn Baldwin int ret; 908744bfb21SJohn Baldwin 909744bfb21SJohn Baldwin ret = chacha20poly1305_encrypt_mbuf(m, nonce, kp->kp_send); 910744bfb21SJohn Baldwin if (ret) 911744bfb21SJohn Baldwin return (ret); 912744bfb21SJohn Baldwin 913744bfb21SJohn Baldwin *r_idx = kp->kp_index.i_remote_index; 914744bfb21SJohn Baldwin return (0); 915744bfb21SJohn Baldwin } 916744bfb21SJohn Baldwin 917744bfb21SJohn Baldwin int 918744bfb21SJohn Baldwin noise_keypair_decrypt(struct noise_keypair *kp, uint64_t nonce, struct mbuf *m) 919744bfb21SJohn Baldwin { 920744bfb21SJohn Baldwin uint64_t cur_nonce; 921744bfb21SJohn Baldwin int ret; 922744bfb21SJohn Baldwin 923744bfb21SJohn Baldwin #ifdef __LP64__ 924*e32e1a16SJohn Baldwin cur_nonce = atomic_load_64(&kp->kp_nonce_recv); 925744bfb21SJohn Baldwin #else 926744bfb21SJohn Baldwin rw_rlock(&kp->kp_nonce_lock); 927744bfb21SJohn Baldwin cur_nonce = kp->kp_nonce_recv; 928744bfb21SJohn Baldwin rw_runlock(&kp->kp_nonce_lock); 929744bfb21SJohn Baldwin #endif 930744bfb21SJohn Baldwin 931744bfb21SJohn Baldwin if (cur_nonce >= REJECT_AFTER_MESSAGES || 932744bfb21SJohn Baldwin noise_timer_expired(kp->kp_birthdate, REJECT_AFTER_TIME, 0)) 933744bfb21SJohn Baldwin return (EINVAL); 934744bfb21SJohn Baldwin 935744bfb21SJohn Baldwin ret = chacha20poly1305_decrypt_mbuf(m, nonce, kp->kp_recv); 936744bfb21SJohn Baldwin if (ret) 937744bfb21SJohn Baldwin return (ret); 938744bfb21SJohn Baldwin 939744bfb21SJohn Baldwin return (0); 940744bfb21SJohn Baldwin } 941744bfb21SJohn Baldwin 942744bfb21SJohn Baldwin /* Handshake functions */ 943744bfb21SJohn Baldwin int 944744bfb21SJohn Baldwin noise_create_initiation(struct noise_remote *r, 945744bfb21SJohn Baldwin uint32_t *s_idx, 946744bfb21SJohn Baldwin uint8_t ue[NOISE_PUBLIC_KEY_LEN], 947744bfb21SJohn Baldwin uint8_t es[NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN], 948744bfb21SJohn Baldwin uint8_t ets[NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN]) 949744bfb21SJohn Baldwin { 950744bfb21SJohn Baldwin struct noise_handshake *hs = &r->r_handshake; 951744bfb21SJohn Baldwin struct noise_local *l = r->r_local; 952744bfb21SJohn Baldwin uint8_t key[NOISE_SYMMETRIC_KEY_LEN]; 953744bfb21SJohn Baldwin int ret = EINVAL; 954744bfb21SJohn Baldwin 955744bfb21SJohn Baldwin rw_rlock(&l->l_identity_lock); 956744bfb21SJohn Baldwin rw_wlock(&r->r_handshake_lock); 957744bfb21SJohn Baldwin if (!l->l_has_identity) 958744bfb21SJohn Baldwin goto error; 959744bfb21SJohn Baldwin if (!noise_timer_expired(r->r_last_sent, REKEY_TIMEOUT, 0)) 960744bfb21SJohn Baldwin goto error; 961744bfb21SJohn Baldwin noise_param_init(hs->hs_ck, hs->hs_hash, r->r_public); 962744bfb21SJohn Baldwin 963744bfb21SJohn Baldwin /* e */ 964744bfb21SJohn Baldwin curve25519_generate_secret(hs->hs_e); 965744bfb21SJohn Baldwin if (curve25519_generate_public(ue, hs->hs_e) == 0) 966744bfb21SJohn Baldwin goto error; 967744bfb21SJohn Baldwin noise_msg_ephemeral(hs->hs_ck, hs->hs_hash, ue); 968744bfb21SJohn Baldwin 969744bfb21SJohn Baldwin /* es */ 970744bfb21SJohn Baldwin if (noise_mix_dh(hs->hs_ck, key, hs->hs_e, r->r_public) != 0) 971744bfb21SJohn Baldwin goto error; 972744bfb21SJohn Baldwin 973744bfb21SJohn Baldwin /* s */ 974744bfb21SJohn Baldwin noise_msg_encrypt(es, l->l_public, 975744bfb21SJohn Baldwin NOISE_PUBLIC_KEY_LEN, key, hs->hs_hash); 976744bfb21SJohn Baldwin 977744bfb21SJohn Baldwin /* ss */ 978744bfb21SJohn Baldwin if (noise_mix_ss(hs->hs_ck, key, r->r_ss) != 0) 979744bfb21SJohn Baldwin goto error; 980744bfb21SJohn Baldwin 981744bfb21SJohn Baldwin /* {t} */ 982744bfb21SJohn Baldwin noise_tai64n_now(ets); 983744bfb21SJohn Baldwin noise_msg_encrypt(ets, ets, 984744bfb21SJohn Baldwin NOISE_TIMESTAMP_LEN, key, hs->hs_hash); 985744bfb21SJohn Baldwin 986744bfb21SJohn Baldwin noise_remote_index_insert(l, r); 987744bfb21SJohn Baldwin r->r_handshake_state = HANDSHAKE_INITIATOR; 988744bfb21SJohn Baldwin r->r_last_sent = getsbinuptime(); 989744bfb21SJohn Baldwin *s_idx = r->r_index.i_local_index; 990744bfb21SJohn Baldwin ret = 0; 991744bfb21SJohn Baldwin error: 992744bfb21SJohn Baldwin rw_wunlock(&r->r_handshake_lock); 993744bfb21SJohn Baldwin rw_runlock(&l->l_identity_lock); 994744bfb21SJohn Baldwin explicit_bzero(key, NOISE_SYMMETRIC_KEY_LEN); 995744bfb21SJohn Baldwin return (ret); 996744bfb21SJohn Baldwin } 997744bfb21SJohn Baldwin 998744bfb21SJohn Baldwin int 999744bfb21SJohn Baldwin noise_consume_initiation(struct noise_local *l, struct noise_remote **rp, 1000744bfb21SJohn Baldwin uint32_t s_idx, 1001744bfb21SJohn Baldwin uint8_t ue[NOISE_PUBLIC_KEY_LEN], 1002744bfb21SJohn Baldwin uint8_t es[NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN], 1003744bfb21SJohn Baldwin uint8_t ets[NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN]) 1004744bfb21SJohn Baldwin { 1005744bfb21SJohn Baldwin struct noise_remote *r; 1006744bfb21SJohn Baldwin struct noise_handshake hs; 1007744bfb21SJohn Baldwin uint8_t key[NOISE_SYMMETRIC_KEY_LEN]; 1008744bfb21SJohn Baldwin uint8_t r_public[NOISE_PUBLIC_KEY_LEN]; 1009744bfb21SJohn Baldwin uint8_t timestamp[NOISE_TIMESTAMP_LEN]; 1010744bfb21SJohn Baldwin int ret = EINVAL; 1011744bfb21SJohn Baldwin 1012744bfb21SJohn Baldwin rw_rlock(&l->l_identity_lock); 1013744bfb21SJohn Baldwin if (!l->l_has_identity) 1014744bfb21SJohn Baldwin goto error; 1015744bfb21SJohn Baldwin noise_param_init(hs.hs_ck, hs.hs_hash, l->l_public); 1016744bfb21SJohn Baldwin 1017744bfb21SJohn Baldwin /* e */ 1018744bfb21SJohn Baldwin noise_msg_ephemeral(hs.hs_ck, hs.hs_hash, ue); 1019744bfb21SJohn Baldwin 1020744bfb21SJohn Baldwin /* es */ 1021744bfb21SJohn Baldwin if (noise_mix_dh(hs.hs_ck, key, l->l_private, ue) != 0) 1022744bfb21SJohn Baldwin goto error; 1023744bfb21SJohn Baldwin 1024744bfb21SJohn Baldwin /* s */ 1025744bfb21SJohn Baldwin if (noise_msg_decrypt(r_public, es, 1026744bfb21SJohn Baldwin NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN, key, hs.hs_hash) != 0) 1027744bfb21SJohn Baldwin goto error; 1028744bfb21SJohn Baldwin 1029744bfb21SJohn Baldwin /* Lookup the remote we received from */ 1030744bfb21SJohn Baldwin if ((r = noise_remote_lookup(l, r_public)) == NULL) 1031744bfb21SJohn Baldwin goto error; 1032744bfb21SJohn Baldwin 1033744bfb21SJohn Baldwin /* ss */ 1034744bfb21SJohn Baldwin if (noise_mix_ss(hs.hs_ck, key, r->r_ss) != 0) 1035744bfb21SJohn Baldwin goto error_put; 1036744bfb21SJohn Baldwin 1037744bfb21SJohn Baldwin /* {t} */ 1038744bfb21SJohn Baldwin if (noise_msg_decrypt(timestamp, ets, 1039744bfb21SJohn Baldwin NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN, key, hs.hs_hash) != 0) 1040744bfb21SJohn Baldwin goto error_put; 1041744bfb21SJohn Baldwin 1042744bfb21SJohn Baldwin memcpy(hs.hs_e, ue, NOISE_PUBLIC_KEY_LEN); 1043744bfb21SJohn Baldwin 1044744bfb21SJohn Baldwin /* We have successfully computed the same results, now we ensure that 1045744bfb21SJohn Baldwin * this is not an initiation replay, or a flood attack */ 1046744bfb21SJohn Baldwin rw_wlock(&r->r_handshake_lock); 1047744bfb21SJohn Baldwin 1048744bfb21SJohn Baldwin /* Replay */ 1049744bfb21SJohn Baldwin if (memcmp(timestamp, r->r_timestamp, NOISE_TIMESTAMP_LEN) > 0) 1050744bfb21SJohn Baldwin memcpy(r->r_timestamp, timestamp, NOISE_TIMESTAMP_LEN); 1051744bfb21SJohn Baldwin else 1052744bfb21SJohn Baldwin goto error_set; 1053744bfb21SJohn Baldwin /* Flood attack */ 1054744bfb21SJohn Baldwin if (noise_timer_expired(r->r_last_init_recv, 0, REJECT_INTERVAL)) 1055744bfb21SJohn Baldwin r->r_last_init_recv = getsbinuptime(); 1056744bfb21SJohn Baldwin else 1057744bfb21SJohn Baldwin goto error_set; 1058744bfb21SJohn Baldwin 1059744bfb21SJohn Baldwin /* Ok, we're happy to accept this initiation now */ 1060744bfb21SJohn Baldwin noise_remote_index_insert(l, r); 1061744bfb21SJohn Baldwin r->r_index.i_remote_index = s_idx; 1062744bfb21SJohn Baldwin r->r_handshake_state = HANDSHAKE_RESPONDER; 1063744bfb21SJohn Baldwin r->r_handshake = hs; 1064744bfb21SJohn Baldwin *rp = noise_remote_ref(r); 1065744bfb21SJohn Baldwin ret = 0; 1066744bfb21SJohn Baldwin error_set: 1067744bfb21SJohn Baldwin rw_wunlock(&r->r_handshake_lock); 1068744bfb21SJohn Baldwin error_put: 1069744bfb21SJohn Baldwin noise_remote_put(r); 1070744bfb21SJohn Baldwin error: 1071744bfb21SJohn Baldwin rw_runlock(&l->l_identity_lock); 1072744bfb21SJohn Baldwin explicit_bzero(key, NOISE_SYMMETRIC_KEY_LEN); 1073744bfb21SJohn Baldwin explicit_bzero(&hs, sizeof(hs)); 1074744bfb21SJohn Baldwin return (ret); 1075744bfb21SJohn Baldwin } 1076744bfb21SJohn Baldwin 1077744bfb21SJohn Baldwin int 1078744bfb21SJohn Baldwin noise_create_response(struct noise_remote *r, 1079744bfb21SJohn Baldwin uint32_t *s_idx, uint32_t *r_idx, 1080744bfb21SJohn Baldwin uint8_t ue[NOISE_PUBLIC_KEY_LEN], 1081744bfb21SJohn Baldwin uint8_t en[0 + NOISE_AUTHTAG_LEN]) 1082744bfb21SJohn Baldwin { 1083744bfb21SJohn Baldwin struct noise_handshake *hs = &r->r_handshake; 1084744bfb21SJohn Baldwin struct noise_local *l = r->r_local; 1085744bfb21SJohn Baldwin uint8_t key[NOISE_SYMMETRIC_KEY_LEN]; 1086744bfb21SJohn Baldwin uint8_t e[NOISE_PUBLIC_KEY_LEN]; 1087744bfb21SJohn Baldwin int ret = EINVAL; 1088744bfb21SJohn Baldwin 1089744bfb21SJohn Baldwin rw_rlock(&l->l_identity_lock); 1090744bfb21SJohn Baldwin rw_wlock(&r->r_handshake_lock); 1091744bfb21SJohn Baldwin 1092744bfb21SJohn Baldwin if (r->r_handshake_state != HANDSHAKE_RESPONDER) 1093744bfb21SJohn Baldwin goto error; 1094744bfb21SJohn Baldwin 1095744bfb21SJohn Baldwin /* e */ 1096744bfb21SJohn Baldwin curve25519_generate_secret(e); 1097744bfb21SJohn Baldwin if (curve25519_generate_public(ue, e) == 0) 1098744bfb21SJohn Baldwin goto error; 1099744bfb21SJohn Baldwin noise_msg_ephemeral(hs->hs_ck, hs->hs_hash, ue); 1100744bfb21SJohn Baldwin 1101744bfb21SJohn Baldwin /* ee */ 1102744bfb21SJohn Baldwin if (noise_mix_dh(hs->hs_ck, NULL, e, hs->hs_e) != 0) 1103744bfb21SJohn Baldwin goto error; 1104744bfb21SJohn Baldwin 1105744bfb21SJohn Baldwin /* se */ 1106744bfb21SJohn Baldwin if (noise_mix_dh(hs->hs_ck, NULL, e, r->r_public) != 0) 1107744bfb21SJohn Baldwin goto error; 1108744bfb21SJohn Baldwin 1109744bfb21SJohn Baldwin /* psk */ 1110744bfb21SJohn Baldwin noise_mix_psk(hs->hs_ck, hs->hs_hash, key, r->r_psk); 1111744bfb21SJohn Baldwin 1112744bfb21SJohn Baldwin /* {} */ 1113744bfb21SJohn Baldwin noise_msg_encrypt(en, NULL, 0, key, hs->hs_hash); 1114744bfb21SJohn Baldwin 1115744bfb21SJohn Baldwin if ((ret = noise_begin_session(r)) == 0) { 1116744bfb21SJohn Baldwin r->r_last_sent = getsbinuptime(); 1117744bfb21SJohn Baldwin *s_idx = r->r_index.i_local_index; 1118744bfb21SJohn Baldwin *r_idx = r->r_index.i_remote_index; 1119744bfb21SJohn Baldwin } 1120744bfb21SJohn Baldwin error: 1121744bfb21SJohn Baldwin rw_wunlock(&r->r_handshake_lock); 1122744bfb21SJohn Baldwin rw_runlock(&l->l_identity_lock); 1123744bfb21SJohn Baldwin explicit_bzero(key, NOISE_SYMMETRIC_KEY_LEN); 1124744bfb21SJohn Baldwin explicit_bzero(e, NOISE_PUBLIC_KEY_LEN); 1125744bfb21SJohn Baldwin return (ret); 1126744bfb21SJohn Baldwin } 1127744bfb21SJohn Baldwin 1128744bfb21SJohn Baldwin int 1129744bfb21SJohn Baldwin noise_consume_response(struct noise_local *l, struct noise_remote **rp, 1130744bfb21SJohn Baldwin uint32_t s_idx, uint32_t r_idx, 1131744bfb21SJohn Baldwin uint8_t ue[NOISE_PUBLIC_KEY_LEN], 1132744bfb21SJohn Baldwin uint8_t en[0 + NOISE_AUTHTAG_LEN]) 1133744bfb21SJohn Baldwin { 1134744bfb21SJohn Baldwin uint8_t preshared_key[NOISE_SYMMETRIC_KEY_LEN]; 1135744bfb21SJohn Baldwin uint8_t key[NOISE_SYMMETRIC_KEY_LEN]; 1136744bfb21SJohn Baldwin struct noise_handshake hs; 1137744bfb21SJohn Baldwin struct noise_remote *r = NULL; 1138744bfb21SJohn Baldwin int ret = EINVAL; 1139744bfb21SJohn Baldwin 1140744bfb21SJohn Baldwin if ((r = noise_remote_index_lookup(l, r_idx, false)) == NULL) 1141744bfb21SJohn Baldwin return (ret); 1142744bfb21SJohn Baldwin 1143744bfb21SJohn Baldwin rw_rlock(&l->l_identity_lock); 1144744bfb21SJohn Baldwin if (!l->l_has_identity) 1145744bfb21SJohn Baldwin goto error; 1146744bfb21SJohn Baldwin 1147744bfb21SJohn Baldwin rw_rlock(&r->r_handshake_lock); 1148744bfb21SJohn Baldwin if (r->r_handshake_state != HANDSHAKE_INITIATOR) { 1149744bfb21SJohn Baldwin rw_runlock(&r->r_handshake_lock); 1150744bfb21SJohn Baldwin goto error; 1151744bfb21SJohn Baldwin } 1152744bfb21SJohn Baldwin memcpy(preshared_key, r->r_psk, NOISE_SYMMETRIC_KEY_LEN); 1153744bfb21SJohn Baldwin hs = r->r_handshake; 1154744bfb21SJohn Baldwin rw_runlock(&r->r_handshake_lock); 1155744bfb21SJohn Baldwin 1156744bfb21SJohn Baldwin /* e */ 1157744bfb21SJohn Baldwin noise_msg_ephemeral(hs.hs_ck, hs.hs_hash, ue); 1158744bfb21SJohn Baldwin 1159744bfb21SJohn Baldwin /* ee */ 1160744bfb21SJohn Baldwin if (noise_mix_dh(hs.hs_ck, NULL, hs.hs_e, ue) != 0) 1161744bfb21SJohn Baldwin goto error_zero; 1162744bfb21SJohn Baldwin 1163744bfb21SJohn Baldwin /* se */ 1164744bfb21SJohn Baldwin if (noise_mix_dh(hs.hs_ck, NULL, l->l_private, ue) != 0) 1165744bfb21SJohn Baldwin goto error_zero; 1166744bfb21SJohn Baldwin 1167744bfb21SJohn Baldwin /* psk */ 1168744bfb21SJohn Baldwin noise_mix_psk(hs.hs_ck, hs.hs_hash, key, preshared_key); 1169744bfb21SJohn Baldwin 1170744bfb21SJohn Baldwin /* {} */ 1171744bfb21SJohn Baldwin if (noise_msg_decrypt(NULL, en, 1172744bfb21SJohn Baldwin 0 + NOISE_AUTHTAG_LEN, key, hs.hs_hash) != 0) 1173744bfb21SJohn Baldwin goto error_zero; 1174744bfb21SJohn Baldwin 1175744bfb21SJohn Baldwin rw_wlock(&r->r_handshake_lock); 1176744bfb21SJohn Baldwin if (r->r_handshake_state == HANDSHAKE_INITIATOR && 1177744bfb21SJohn Baldwin r->r_index.i_local_index == r_idx) { 1178744bfb21SJohn Baldwin r->r_handshake = hs; 1179744bfb21SJohn Baldwin r->r_index.i_remote_index = s_idx; 1180744bfb21SJohn Baldwin if ((ret = noise_begin_session(r)) == 0) 1181744bfb21SJohn Baldwin *rp = noise_remote_ref(r); 1182744bfb21SJohn Baldwin } 1183744bfb21SJohn Baldwin rw_wunlock(&r->r_handshake_lock); 1184744bfb21SJohn Baldwin error_zero: 1185744bfb21SJohn Baldwin explicit_bzero(preshared_key, NOISE_SYMMETRIC_KEY_LEN); 1186744bfb21SJohn Baldwin explicit_bzero(key, NOISE_SYMMETRIC_KEY_LEN); 1187744bfb21SJohn Baldwin explicit_bzero(&hs, sizeof(hs)); 1188744bfb21SJohn Baldwin error: 1189744bfb21SJohn Baldwin rw_runlock(&l->l_identity_lock); 1190744bfb21SJohn Baldwin noise_remote_put(r); 1191744bfb21SJohn Baldwin return (ret); 1192744bfb21SJohn Baldwin } 1193744bfb21SJohn Baldwin 1194744bfb21SJohn Baldwin static void 1195744bfb21SJohn Baldwin hmac(uint8_t *out, const uint8_t *in, const uint8_t *key, const size_t outlen, 1196744bfb21SJohn Baldwin const size_t inlen, const size_t keylen) 1197744bfb21SJohn Baldwin { 1198744bfb21SJohn Baldwin struct blake2s_state state; 1199744bfb21SJohn Baldwin uint8_t x_key[BLAKE2S_BLOCK_SIZE] __aligned(sizeof(uint32_t)) = { 0 }; 1200744bfb21SJohn Baldwin uint8_t i_hash[BLAKE2S_HASH_SIZE] __aligned(sizeof(uint32_t)); 1201744bfb21SJohn Baldwin int i; 1202744bfb21SJohn Baldwin 1203744bfb21SJohn Baldwin if (keylen > BLAKE2S_BLOCK_SIZE) { 1204744bfb21SJohn Baldwin blake2s_init(&state, BLAKE2S_HASH_SIZE); 1205744bfb21SJohn Baldwin blake2s_update(&state, key, keylen); 1206744bfb21SJohn Baldwin blake2s_final(&state, x_key); 1207744bfb21SJohn Baldwin } else 1208744bfb21SJohn Baldwin memcpy(x_key, key, keylen); 1209744bfb21SJohn Baldwin 1210744bfb21SJohn Baldwin for (i = 0; i < BLAKE2S_BLOCK_SIZE; ++i) 1211744bfb21SJohn Baldwin x_key[i] ^= 0x36; 1212744bfb21SJohn Baldwin 1213744bfb21SJohn Baldwin blake2s_init(&state, BLAKE2S_HASH_SIZE); 1214744bfb21SJohn Baldwin blake2s_update(&state, x_key, BLAKE2S_BLOCK_SIZE); 1215744bfb21SJohn Baldwin blake2s_update(&state, in, inlen); 1216744bfb21SJohn Baldwin blake2s_final(&state, i_hash); 1217744bfb21SJohn Baldwin 1218744bfb21SJohn Baldwin for (i = 0; i < BLAKE2S_BLOCK_SIZE; ++i) 1219744bfb21SJohn Baldwin x_key[i] ^= 0x5c ^ 0x36; 1220744bfb21SJohn Baldwin 1221744bfb21SJohn Baldwin blake2s_init(&state, BLAKE2S_HASH_SIZE); 1222744bfb21SJohn Baldwin blake2s_update(&state, x_key, BLAKE2S_BLOCK_SIZE); 1223744bfb21SJohn Baldwin blake2s_update(&state, i_hash, BLAKE2S_HASH_SIZE); 1224744bfb21SJohn Baldwin blake2s_final(&state, i_hash); 1225744bfb21SJohn Baldwin 1226744bfb21SJohn Baldwin memcpy(out, i_hash, outlen); 1227744bfb21SJohn Baldwin explicit_bzero(x_key, BLAKE2S_BLOCK_SIZE); 1228744bfb21SJohn Baldwin explicit_bzero(i_hash, BLAKE2S_HASH_SIZE); 1229744bfb21SJohn Baldwin } 1230744bfb21SJohn Baldwin 1231744bfb21SJohn Baldwin /* Handshake helper functions */ 1232744bfb21SJohn Baldwin static void 1233744bfb21SJohn Baldwin noise_kdf(uint8_t *a, uint8_t *b, uint8_t *c, const uint8_t *x, 1234744bfb21SJohn Baldwin size_t a_len, size_t b_len, size_t c_len, size_t x_len, 1235744bfb21SJohn Baldwin const uint8_t ck[NOISE_HASH_LEN]) 1236744bfb21SJohn Baldwin { 1237744bfb21SJohn Baldwin uint8_t out[BLAKE2S_HASH_SIZE + 1]; 1238744bfb21SJohn Baldwin uint8_t sec[BLAKE2S_HASH_SIZE]; 1239744bfb21SJohn Baldwin 1240744bfb21SJohn Baldwin /* Extract entropy from "x" into sec */ 1241744bfb21SJohn Baldwin hmac(sec, x, ck, BLAKE2S_HASH_SIZE, x_len, NOISE_HASH_LEN); 1242744bfb21SJohn Baldwin 1243744bfb21SJohn Baldwin if (a == NULL || a_len == 0) 1244744bfb21SJohn Baldwin goto out; 1245744bfb21SJohn Baldwin 1246744bfb21SJohn Baldwin /* Expand first key: key = sec, data = 0x1 */ 1247744bfb21SJohn Baldwin out[0] = 1; 1248744bfb21SJohn Baldwin hmac(out, out, sec, BLAKE2S_HASH_SIZE, 1, BLAKE2S_HASH_SIZE); 1249744bfb21SJohn Baldwin memcpy(a, out, a_len); 1250744bfb21SJohn Baldwin 1251744bfb21SJohn Baldwin if (b == NULL || b_len == 0) 1252744bfb21SJohn Baldwin goto out; 1253744bfb21SJohn Baldwin 1254744bfb21SJohn Baldwin /* Expand second key: key = sec, data = "a" || 0x2 */ 1255744bfb21SJohn Baldwin out[BLAKE2S_HASH_SIZE] = 2; 1256744bfb21SJohn Baldwin hmac(out, out, sec, BLAKE2S_HASH_SIZE, BLAKE2S_HASH_SIZE + 1, BLAKE2S_HASH_SIZE); 1257744bfb21SJohn Baldwin memcpy(b, out, b_len); 1258744bfb21SJohn Baldwin 1259744bfb21SJohn Baldwin if (c == NULL || c_len == 0) 1260744bfb21SJohn Baldwin goto out; 1261744bfb21SJohn Baldwin 1262744bfb21SJohn Baldwin /* Expand third key: key = sec, data = "b" || 0x3 */ 1263744bfb21SJohn Baldwin out[BLAKE2S_HASH_SIZE] = 3; 1264744bfb21SJohn Baldwin hmac(out, out, sec, BLAKE2S_HASH_SIZE, BLAKE2S_HASH_SIZE + 1, BLAKE2S_HASH_SIZE); 1265744bfb21SJohn Baldwin memcpy(c, out, c_len); 1266744bfb21SJohn Baldwin 1267744bfb21SJohn Baldwin out: 1268744bfb21SJohn Baldwin /* Clear sensitive data from stack */ 1269744bfb21SJohn Baldwin explicit_bzero(sec, BLAKE2S_HASH_SIZE); 1270744bfb21SJohn Baldwin explicit_bzero(out, BLAKE2S_HASH_SIZE + 1); 1271744bfb21SJohn Baldwin } 1272744bfb21SJohn Baldwin 1273744bfb21SJohn Baldwin static int 1274744bfb21SJohn Baldwin noise_mix_dh(uint8_t ck[NOISE_HASH_LEN], uint8_t key[NOISE_SYMMETRIC_KEY_LEN], 1275744bfb21SJohn Baldwin const uint8_t private[NOISE_PUBLIC_KEY_LEN], 1276744bfb21SJohn Baldwin const uint8_t public[NOISE_PUBLIC_KEY_LEN]) 1277744bfb21SJohn Baldwin { 1278744bfb21SJohn Baldwin uint8_t dh[NOISE_PUBLIC_KEY_LEN]; 1279744bfb21SJohn Baldwin 1280744bfb21SJohn Baldwin if (!curve25519(dh, private, public)) 1281744bfb21SJohn Baldwin return (EINVAL); 1282744bfb21SJohn Baldwin noise_kdf(ck, key, NULL, dh, 1283744bfb21SJohn Baldwin NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, NOISE_PUBLIC_KEY_LEN, ck); 1284744bfb21SJohn Baldwin explicit_bzero(dh, NOISE_PUBLIC_KEY_LEN); 1285744bfb21SJohn Baldwin return (0); 1286744bfb21SJohn Baldwin } 1287744bfb21SJohn Baldwin 1288744bfb21SJohn Baldwin static int 1289744bfb21SJohn Baldwin noise_mix_ss(uint8_t ck[NOISE_HASH_LEN], uint8_t key[NOISE_SYMMETRIC_KEY_LEN], 1290744bfb21SJohn Baldwin const uint8_t ss[NOISE_PUBLIC_KEY_LEN]) 1291744bfb21SJohn Baldwin { 1292744bfb21SJohn Baldwin static uint8_t null_point[NOISE_PUBLIC_KEY_LEN]; 1293744bfb21SJohn Baldwin if (timingsafe_bcmp(ss, null_point, NOISE_PUBLIC_KEY_LEN) == 0) 1294744bfb21SJohn Baldwin return (ENOENT); 1295744bfb21SJohn Baldwin noise_kdf(ck, key, NULL, ss, 1296744bfb21SJohn Baldwin NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, NOISE_PUBLIC_KEY_LEN, ck); 1297744bfb21SJohn Baldwin return (0); 1298744bfb21SJohn Baldwin } 1299744bfb21SJohn Baldwin 1300744bfb21SJohn Baldwin static void 1301744bfb21SJohn Baldwin noise_mix_hash(uint8_t hash[NOISE_HASH_LEN], const uint8_t *src, 1302744bfb21SJohn Baldwin size_t src_len) 1303744bfb21SJohn Baldwin { 1304744bfb21SJohn Baldwin struct blake2s_state blake; 1305744bfb21SJohn Baldwin 1306744bfb21SJohn Baldwin blake2s_init(&blake, NOISE_HASH_LEN); 1307744bfb21SJohn Baldwin blake2s_update(&blake, hash, NOISE_HASH_LEN); 1308744bfb21SJohn Baldwin blake2s_update(&blake, src, src_len); 1309744bfb21SJohn Baldwin blake2s_final(&blake, hash); 1310744bfb21SJohn Baldwin } 1311744bfb21SJohn Baldwin 1312744bfb21SJohn Baldwin static void 1313744bfb21SJohn Baldwin noise_mix_psk(uint8_t ck[NOISE_HASH_LEN], uint8_t hash[NOISE_HASH_LEN], 1314744bfb21SJohn Baldwin uint8_t key[NOISE_SYMMETRIC_KEY_LEN], 1315744bfb21SJohn Baldwin const uint8_t psk[NOISE_SYMMETRIC_KEY_LEN]) 1316744bfb21SJohn Baldwin { 1317744bfb21SJohn Baldwin uint8_t tmp[NOISE_HASH_LEN]; 1318744bfb21SJohn Baldwin 1319744bfb21SJohn Baldwin noise_kdf(ck, tmp, key, psk, 1320744bfb21SJohn Baldwin NOISE_HASH_LEN, NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN, 1321744bfb21SJohn Baldwin NOISE_SYMMETRIC_KEY_LEN, ck); 1322744bfb21SJohn Baldwin noise_mix_hash(hash, tmp, NOISE_HASH_LEN); 1323744bfb21SJohn Baldwin explicit_bzero(tmp, NOISE_HASH_LEN); 1324744bfb21SJohn Baldwin } 1325744bfb21SJohn Baldwin 1326744bfb21SJohn Baldwin static void 1327744bfb21SJohn Baldwin noise_param_init(uint8_t ck[NOISE_HASH_LEN], uint8_t hash[NOISE_HASH_LEN], 1328744bfb21SJohn Baldwin const uint8_t s[NOISE_PUBLIC_KEY_LEN]) 1329744bfb21SJohn Baldwin { 1330744bfb21SJohn Baldwin struct blake2s_state blake; 1331744bfb21SJohn Baldwin 1332744bfb21SJohn Baldwin blake2s(ck, (uint8_t *)NOISE_HANDSHAKE_NAME, NULL, 1333744bfb21SJohn Baldwin NOISE_HASH_LEN, strlen(NOISE_HANDSHAKE_NAME), 0); 1334744bfb21SJohn Baldwin blake2s_init(&blake, NOISE_HASH_LEN); 1335744bfb21SJohn Baldwin blake2s_update(&blake, ck, NOISE_HASH_LEN); 1336744bfb21SJohn Baldwin blake2s_update(&blake, (uint8_t *)NOISE_IDENTIFIER_NAME, 1337744bfb21SJohn Baldwin strlen(NOISE_IDENTIFIER_NAME)); 1338744bfb21SJohn Baldwin blake2s_final(&blake, hash); 1339744bfb21SJohn Baldwin 1340744bfb21SJohn Baldwin noise_mix_hash(hash, s, NOISE_PUBLIC_KEY_LEN); 1341744bfb21SJohn Baldwin } 1342744bfb21SJohn Baldwin 1343744bfb21SJohn Baldwin static void 1344744bfb21SJohn Baldwin noise_msg_encrypt(uint8_t *dst, const uint8_t *src, size_t src_len, 1345744bfb21SJohn Baldwin uint8_t key[NOISE_SYMMETRIC_KEY_LEN], uint8_t hash[NOISE_HASH_LEN]) 1346744bfb21SJohn Baldwin { 1347744bfb21SJohn Baldwin /* Nonce always zero for Noise_IK */ 1348744bfb21SJohn Baldwin chacha20poly1305_encrypt(dst, src, src_len, 1349744bfb21SJohn Baldwin hash, NOISE_HASH_LEN, 0, key); 1350744bfb21SJohn Baldwin noise_mix_hash(hash, dst, src_len + NOISE_AUTHTAG_LEN); 1351744bfb21SJohn Baldwin } 1352744bfb21SJohn Baldwin 1353744bfb21SJohn Baldwin static int 1354744bfb21SJohn Baldwin noise_msg_decrypt(uint8_t *dst, const uint8_t *src, size_t src_len, 1355744bfb21SJohn Baldwin uint8_t key[NOISE_SYMMETRIC_KEY_LEN], uint8_t hash[NOISE_HASH_LEN]) 1356744bfb21SJohn Baldwin { 1357744bfb21SJohn Baldwin /* Nonce always zero for Noise_IK */ 1358744bfb21SJohn Baldwin if (!chacha20poly1305_decrypt(dst, src, src_len, 1359744bfb21SJohn Baldwin hash, NOISE_HASH_LEN, 0, key)) 1360744bfb21SJohn Baldwin return (EINVAL); 1361744bfb21SJohn Baldwin noise_mix_hash(hash, src, src_len); 1362744bfb21SJohn Baldwin return (0); 1363744bfb21SJohn Baldwin } 1364744bfb21SJohn Baldwin 1365744bfb21SJohn Baldwin static void 1366744bfb21SJohn Baldwin noise_msg_ephemeral(uint8_t ck[NOISE_HASH_LEN], uint8_t hash[NOISE_HASH_LEN], 1367744bfb21SJohn Baldwin const uint8_t src[NOISE_PUBLIC_KEY_LEN]) 1368744bfb21SJohn Baldwin { 1369744bfb21SJohn Baldwin noise_mix_hash(hash, src, NOISE_PUBLIC_KEY_LEN); 1370744bfb21SJohn Baldwin noise_kdf(ck, NULL, NULL, src, NOISE_HASH_LEN, 0, 0, 1371744bfb21SJohn Baldwin NOISE_PUBLIC_KEY_LEN, ck); 1372744bfb21SJohn Baldwin } 1373744bfb21SJohn Baldwin 1374744bfb21SJohn Baldwin static void 1375744bfb21SJohn Baldwin noise_tai64n_now(uint8_t output[NOISE_TIMESTAMP_LEN]) 1376744bfb21SJohn Baldwin { 1377744bfb21SJohn Baldwin struct timespec time; 1378744bfb21SJohn Baldwin uint64_t sec; 1379744bfb21SJohn Baldwin uint32_t nsec; 1380744bfb21SJohn Baldwin 1381744bfb21SJohn Baldwin getnanotime(&time); 1382744bfb21SJohn Baldwin 1383744bfb21SJohn Baldwin /* Round down the nsec counter to limit precise timing leak. */ 1384744bfb21SJohn Baldwin time.tv_nsec &= REJECT_INTERVAL_MASK; 1385744bfb21SJohn Baldwin 1386744bfb21SJohn Baldwin /* https://cr.yp.to/libtai/tai64.html */ 1387744bfb21SJohn Baldwin sec = htobe64(0x400000000000000aULL + time.tv_sec); 1388744bfb21SJohn Baldwin nsec = htobe32(time.tv_nsec); 1389744bfb21SJohn Baldwin 1390744bfb21SJohn Baldwin /* memcpy to output buffer, assuming output could be unaligned. */ 1391744bfb21SJohn Baldwin memcpy(output, &sec, sizeof(sec)); 1392744bfb21SJohn Baldwin memcpy(output + sizeof(sec), &nsec, sizeof(nsec)); 1393744bfb21SJohn Baldwin } 1394744bfb21SJohn Baldwin 1395744bfb21SJohn Baldwin static inline int 1396744bfb21SJohn Baldwin noise_timer_expired(sbintime_t timer, uint32_t sec, uint32_t nsec) 1397744bfb21SJohn Baldwin { 1398744bfb21SJohn Baldwin sbintime_t now = getsbinuptime(); 1399744bfb21SJohn Baldwin return (now > (timer + sec * SBT_1S + nstosbt(nsec))) ? ETIMEDOUT : 0; 1400744bfb21SJohn Baldwin } 1401744bfb21SJohn Baldwin 1402744bfb21SJohn Baldwin static uint64_t siphash24(const uint8_t key[SIPHASH_KEY_LENGTH], const void *src, size_t len) 1403744bfb21SJohn Baldwin { 1404744bfb21SJohn Baldwin SIPHASH_CTX ctx; 1405744bfb21SJohn Baldwin return (SipHashX(&ctx, 2, 4, key, src, len)); 1406744bfb21SJohn Baldwin } 1407744bfb21SJohn Baldwin 1408744bfb21SJohn Baldwin #ifdef SELFTESTS 1409744bfb21SJohn Baldwin #include "selftest/counter.c" 1410744bfb21SJohn Baldwin #endif /* SELFTESTS */ 1411