1*efbb2e09Smvs /* $OpenBSD: wg_noise.h,v 1.3 2024/03/05 17:48:01 mvs Exp $ */ 258360b13Sdlg /* 358360b13Sdlg * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 458360b13Sdlg * Copyright (C) 2019-2020 Matt Dunwoodie <ncon@noconroy.net> 558360b13Sdlg * 658360b13Sdlg * Permission to use, copy, modify, and distribute this software for any 758360b13Sdlg * purpose with or without fee is hereby granted, provided that the above 858360b13Sdlg * copyright notice and this permission notice appear in all copies. 958360b13Sdlg * 1058360b13Sdlg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1158360b13Sdlg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1258360b13Sdlg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1358360b13Sdlg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1458360b13Sdlg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1558360b13Sdlg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1658360b13Sdlg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1758360b13Sdlg */ 1858360b13Sdlg 1958360b13Sdlg #ifndef __NOISE_H__ 2058360b13Sdlg #define __NOISE_H__ 2158360b13Sdlg 2258360b13Sdlg #include <sys/types.h> 2358360b13Sdlg #include <sys/time.h> 24*efbb2e09Smvs #include <sys/mutex.h> 2558360b13Sdlg #include <sys/rwlock.h> 2658360b13Sdlg 2758360b13Sdlg #include <crypto/blake2s.h> 2858360b13Sdlg #include <crypto/chachapoly.h> 2958360b13Sdlg #include <crypto/curve25519.h> 3058360b13Sdlg 3158360b13Sdlg #define NOISE_PUBLIC_KEY_LEN CURVE25519_KEY_SIZE 3258360b13Sdlg #define NOISE_SYMMETRIC_KEY_LEN CHACHA20POLY1305_KEY_SIZE 3358360b13Sdlg #define NOISE_TIMESTAMP_LEN (sizeof(uint64_t) + sizeof(uint32_t)) 3458360b13Sdlg #define NOISE_AUTHTAG_LEN CHACHA20POLY1305_AUTHTAG_SIZE 3558360b13Sdlg #define NOISE_HASH_LEN BLAKE2S_HASH_SIZE 3658360b13Sdlg 3758360b13Sdlg /* Protocol string constants */ 3858360b13Sdlg #define NOISE_HANDSHAKE_NAME "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s" 3958360b13Sdlg #define NOISE_IDENTIFIER_NAME "WireGuard v1 zx2c4 Jason@zx2c4.com" 4058360b13Sdlg 4158360b13Sdlg /* Constants for the counter */ 4258360b13Sdlg #define COUNTER_BITS_TOTAL 8192 4358360b13Sdlg #define COUNTER_BITS (sizeof(unsigned long) * 8) 4458360b13Sdlg #define COUNTER_NUM (COUNTER_BITS_TOTAL / COUNTER_BITS) 4558360b13Sdlg #define COUNTER_WINDOW_SIZE (COUNTER_BITS_TOTAL - COUNTER_BITS) 4658360b13Sdlg 4758360b13Sdlg /* Constants for the keypair */ 4858360b13Sdlg #define REKEY_AFTER_MESSAGES (1ull << 60) 4958360b13Sdlg #define REJECT_AFTER_MESSAGES (UINT64_MAX - COUNTER_WINDOW_SIZE - 1) 5058360b13Sdlg #define REKEY_AFTER_TIME 120 5158360b13Sdlg #define REKEY_AFTER_TIME_RECV 165 5258360b13Sdlg #define REJECT_AFTER_TIME 180 5358360b13Sdlg #define REJECT_INTERVAL (1000000000 / 50) /* fifty times per sec */ 5458360b13Sdlg /* 24 = floor(log2(REJECT_INTERVAL)) */ 5558360b13Sdlg #define REJECT_INTERVAL_MASK (~((1ull<<24)-1)) 5658360b13Sdlg 5758360b13Sdlg enum noise_state_hs { 5858360b13Sdlg HS_ZEROED = 0, 5958360b13Sdlg CREATED_INITIATION, 6058360b13Sdlg CONSUMED_INITIATION, 6158360b13Sdlg CREATED_RESPONSE, 6258360b13Sdlg CONSUMED_RESPONSE, 6358360b13Sdlg }; 6458360b13Sdlg 6558360b13Sdlg struct noise_handshake { 6658360b13Sdlg enum noise_state_hs hs_state; 6758360b13Sdlg uint32_t hs_local_index; 6858360b13Sdlg uint32_t hs_remote_index; 6958360b13Sdlg uint8_t hs_e[NOISE_PUBLIC_KEY_LEN]; 7058360b13Sdlg uint8_t hs_hash[NOISE_HASH_LEN]; 7158360b13Sdlg uint8_t hs_ck[NOISE_HASH_LEN]; 7258360b13Sdlg }; 7358360b13Sdlg 7458360b13Sdlg struct noise_counter { 75*efbb2e09Smvs struct mutex c_mtx; 7658360b13Sdlg uint64_t c_send; 7758360b13Sdlg uint64_t c_recv; 7858360b13Sdlg unsigned long c_backtrack[COUNTER_NUM]; 7958360b13Sdlg }; 8058360b13Sdlg 8158360b13Sdlg struct noise_keypair { 8258360b13Sdlg SLIST_ENTRY(noise_keypair) kp_entry; 8358360b13Sdlg int kp_valid; 8458360b13Sdlg int kp_is_initiator; 8558360b13Sdlg uint32_t kp_local_index; 8658360b13Sdlg uint32_t kp_remote_index; 8758360b13Sdlg uint8_t kp_send[NOISE_SYMMETRIC_KEY_LEN]; 8858360b13Sdlg uint8_t kp_recv[NOISE_SYMMETRIC_KEY_LEN]; 8958360b13Sdlg struct timespec kp_birthdate; /* nanouptime */ 9058360b13Sdlg struct noise_counter kp_ctr; 9158360b13Sdlg }; 9258360b13Sdlg 9358360b13Sdlg struct noise_remote { 9458360b13Sdlg uint8_t r_public[NOISE_PUBLIC_KEY_LEN]; 9558360b13Sdlg struct noise_local *r_local; 9658360b13Sdlg uint8_t r_ss[NOISE_PUBLIC_KEY_LEN]; 9758360b13Sdlg 9858360b13Sdlg struct rwlock r_handshake_lock; 9958360b13Sdlg struct noise_handshake r_handshake; 10058360b13Sdlg uint8_t r_psk[NOISE_SYMMETRIC_KEY_LEN]; 10158360b13Sdlg uint8_t r_timestamp[NOISE_TIMESTAMP_LEN]; 10258360b13Sdlg struct timespec r_last_init; /* nanouptime */ 10358360b13Sdlg 104*efbb2e09Smvs struct mutex r_keypair_mtx; 10558360b13Sdlg SLIST_HEAD(,noise_keypair) r_unused_keypairs; 10658360b13Sdlg struct noise_keypair *r_next, *r_current, *r_previous; 10758360b13Sdlg struct noise_keypair r_keypair[3]; /* 3: next, current, previous. */ 10858360b13Sdlg 10958360b13Sdlg }; 11058360b13Sdlg 11158360b13Sdlg struct noise_local { 11258360b13Sdlg struct rwlock l_identity_lock; 11358360b13Sdlg int l_has_identity; 11458360b13Sdlg uint8_t l_public[NOISE_PUBLIC_KEY_LEN]; 11558360b13Sdlg uint8_t l_private[NOISE_PUBLIC_KEY_LEN]; 11658360b13Sdlg 11758360b13Sdlg struct noise_upcall { 11858360b13Sdlg void *u_arg; 11958360b13Sdlg struct noise_remote * 12058360b13Sdlg (*u_remote_get)(void *, uint8_t[NOISE_PUBLIC_KEY_LEN]); 12158360b13Sdlg uint32_t 12258360b13Sdlg (*u_index_set)(void *, struct noise_remote *); 12358360b13Sdlg void (*u_index_drop)(void *, uint32_t); 12458360b13Sdlg } l_upcall; 12558360b13Sdlg }; 12658360b13Sdlg 12758360b13Sdlg /* Set/Get noise parameters */ 12858360b13Sdlg void noise_local_init(struct noise_local *, struct noise_upcall *); 12958360b13Sdlg void noise_local_lock_identity(struct noise_local *); 13058360b13Sdlg void noise_local_unlock_identity(struct noise_local *); 13158360b13Sdlg int noise_local_set_private(struct noise_local *, uint8_t[NOISE_PUBLIC_KEY_LEN]); 13258360b13Sdlg int noise_local_keys(struct noise_local *, uint8_t[NOISE_PUBLIC_KEY_LEN], 13358360b13Sdlg uint8_t[NOISE_PUBLIC_KEY_LEN]); 13458360b13Sdlg 13558360b13Sdlg void noise_remote_init(struct noise_remote *, uint8_t[NOISE_PUBLIC_KEY_LEN], 13658360b13Sdlg struct noise_local *); 13758360b13Sdlg int noise_remote_set_psk(struct noise_remote *, uint8_t[NOISE_SYMMETRIC_KEY_LEN]); 13858360b13Sdlg int noise_remote_keys(struct noise_remote *, uint8_t[NOISE_PUBLIC_KEY_LEN], 13958360b13Sdlg uint8_t[NOISE_SYMMETRIC_KEY_LEN]); 14058360b13Sdlg 14158360b13Sdlg /* Should be called anytime noise_local_set_private is called */ 14258360b13Sdlg void noise_remote_precompute(struct noise_remote *); 14358360b13Sdlg 14458360b13Sdlg /* Cryptographic functions */ 14558360b13Sdlg int noise_create_initiation( 14658360b13Sdlg struct noise_remote *, 14758360b13Sdlg uint32_t *s_idx, 14858360b13Sdlg uint8_t ue[NOISE_PUBLIC_KEY_LEN], 14958360b13Sdlg uint8_t es[NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN], 15058360b13Sdlg uint8_t ets[NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN]); 15158360b13Sdlg 15258360b13Sdlg int noise_consume_initiation( 15358360b13Sdlg struct noise_local *, 15458360b13Sdlg struct noise_remote **, 15558360b13Sdlg uint32_t s_idx, 15658360b13Sdlg uint8_t ue[NOISE_PUBLIC_KEY_LEN], 15758360b13Sdlg uint8_t es[NOISE_PUBLIC_KEY_LEN + NOISE_AUTHTAG_LEN], 15858360b13Sdlg uint8_t ets[NOISE_TIMESTAMP_LEN + NOISE_AUTHTAG_LEN]); 15958360b13Sdlg 16058360b13Sdlg int noise_create_response( 16158360b13Sdlg struct noise_remote *, 16258360b13Sdlg uint32_t *s_idx, 16358360b13Sdlg uint32_t *r_idx, 16458360b13Sdlg uint8_t ue[NOISE_PUBLIC_KEY_LEN], 16558360b13Sdlg uint8_t en[0 + NOISE_AUTHTAG_LEN]); 16658360b13Sdlg 16758360b13Sdlg int noise_consume_response( 16858360b13Sdlg struct noise_remote *, 16958360b13Sdlg uint32_t s_idx, 17058360b13Sdlg uint32_t r_idx, 17158360b13Sdlg uint8_t ue[NOISE_PUBLIC_KEY_LEN], 17258360b13Sdlg uint8_t en[0 + NOISE_AUTHTAG_LEN]); 17358360b13Sdlg 17458360b13Sdlg int noise_remote_begin_session(struct noise_remote *); 17558360b13Sdlg void noise_remote_clear(struct noise_remote *); 17658360b13Sdlg void noise_remote_expire_current(struct noise_remote *); 17758360b13Sdlg 17858360b13Sdlg int noise_remote_ready(struct noise_remote *); 17958360b13Sdlg 18058360b13Sdlg int noise_remote_encrypt( 18158360b13Sdlg struct noise_remote *, 18258360b13Sdlg uint32_t *r_idx, 18358360b13Sdlg uint64_t *nonce, 18458360b13Sdlg uint8_t *buf, 18558360b13Sdlg size_t buflen); 18658360b13Sdlg int noise_remote_decrypt( 18758360b13Sdlg struct noise_remote *, 18858360b13Sdlg uint32_t r_idx, 18958360b13Sdlg uint64_t nonce, 19058360b13Sdlg uint8_t *buf, 19158360b13Sdlg size_t buflen); 19258360b13Sdlg 19358360b13Sdlg #ifdef WGTEST 19458360b13Sdlg void noise_test(); 19558360b13Sdlg #endif /* WGTEST */ 19658360b13Sdlg 19758360b13Sdlg #endif /* __NOISE_H__ */ 198