]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/if_wg/include/sys/wg_noise.h
Import kernel WireGuard support
[FreeBSD/FreeBSD.git] / sys / dev / if_wg / include / sys / wg_noise.h
1 /*
2  * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
3  * Copyright (C) 2019-2020 Matt Dunwoodie <ncon@noconroy.net>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  *
17  * ======== wg_noise.h ========
18  *
19  * This file provides a thread safe interface to the Noise protocol as used in
20  * WireGuard. The three user facing components are:
21  *
22  *   * noise_local
23  *           Stores the local state for a noise peer.
24  *   * noise_remote
25  *           Stores the remote state for a noise peer.
26  *   * noise_upcall
27  *           Stores callback routines for index and peers
28  *
29  * Additionally a noise_counter, which is invsible to the user is used to track
30  * message nonces, to prevent message replay.
31  *
32  * This module uses Curve25519 for asymmetric crypto, and ChaCha20Poly1305 for
33  * symmetric crypto. The handshake uses ephemeral keys, which provide perfect
34  * forward secrecy.  Keys are NOISE_KEY_SIZE (32) bytes long and can be
35  * generated with a CSRNG. While this module will clamp the key to form a valid
36  * Curve25519 key, it is recommended that keys are stored in Curve25519 form to
37  * preserve interoperability with other systems. Additionally, there is an
38  * optional PresharedKey of length NOISE_PSK_SIZE (also 32 bytes), which when
39  * used, will provide protection against known quantum attacks. Without it,
40  * Curve25519 is broken by Shor's algorithm.
41  *
42  * -------- noise_local --------
43  *
44  * void noise_local_init(noise_local *, noise_upcall *)
45  *   - Initialise noise_local, should only be called once and before use.
46  *
47  * int noise_local_set_private(noise_local *, uint8_t *private)
48  *   - Set the local private key. This will also calculate the corresponding
49  *     public key.
50  *
51  * int  noise_local_keys(noise_local *, uint8_t *public, uint8_t *private)
52  *   - Get the local keys. It will ensure that a key has been set and if
53  *     not, will return ENXIO.
54  *
55  * -------- noise_remote --------
56  *
57  * void noise_remote_init(noise_remote *, uint8_t *public)
58  *   - Initialise noise_local, should only be called once and before use. Key
59  *     must be provided and it cannot be changed once set.
60  *
61  * void noise_remote_set_psk(noise_remote *, uint8_t *psk)
62  *   - Set the shared key. To remove the shared key, set a key of all 0x00.
63  *
64  * void noise_remote_keys(noise_remote *, uint8_t *public, uint8_t *psk)
65  *   - Get the remote keys.
66  *
67  * -------- noise_upcall --------
68  *
69  * The noise_upcall struct is used to lookup incoming public keys, as well as
70  * allocate and deallocate index for a remote. The allocation and deallocation
71  * are serialised per noise_remote and guaranteed to only have 3 allocated
72  * indexes at once.
73  *
74  * u_arg        - passed to callback functions as void *
75  * u_get_remote - lookup noise_remote based on public key.
76  * u_set_index  - allocate index for noise_remote. any further packets that
77  *                arrive with this index should be passed to noise_* functions
78  *                with the corresponding noise_remote.
79  * u_drop_index - dealloate index passed to callback.
80  *
81  * -------- crypto --------
82  *
83  * The following functions are used for the crypto side of things:
84  *
85  * int noise_create_initiation(noise_remote *, noise_initiation *)
86  * int noise_consume_initiation(noise_local *, noise_remote **, noise_initiation *)
87  * int noise_create_response(noise_remote *, noise_response *)
88  * int noise_consume_response(noise_remote *, noise_response *)
89  *
90  * int noise_remote_promote(noise_remote *)
91  * void noise_remote_clear(noise_remote *)
92  * void noise_remote_expire_current(noise_remote *)
93  * int noise_remote_encrypt(noise_remote *, noise_data *, size_t)
94  * int noise_remote_decrypt(noise_remote *, noise_data *, size_t)
95  *
96  * $FreeBSD$
97  */
98
99 #ifndef __NOISE_H__
100 #define __NOISE_H__
101
102 #include <sys/types.h>
103 #include <sys/time.h>
104 #include <sys/rwlock.h>
105 #include <sys/support.h>
106
107 #include <crypto/blake2s.h>
108 #include <zinc/chacha20poly1305.h>
109 #include <crypto/curve25519.h>
110
111 #define NOISE_KEY_SIZE          CURVE25519_KEY_SIZE
112 #define NOISE_PSK_SIZE          32
113 #define NOISE_MAC_SIZE          CHACHA20POLY1305_AUTHTAG_SIZE
114 #define NOISE_HASH_SIZE         BLAKE2S_HASH_SIZE
115 #define NOISE_SYMMETRIC_SIZE    CHACHA20POLY1305_KEY_SIZE
116 #define NOISE_TIMESTAMP_SIZE    12
117
118 /* Protocol string constants */
119 #define NOISE_HANDSHAKE_NAME    "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"
120 #define NOISE_IDENTIFIER_NAME   "WireGuard v1 zx2c4 Jason@zx2c4.com"
121
122 /* Constants for the counter */
123 #define COUNTER_TYPE            size_t
124 #define COUNTER_BITS_TOTAL      512
125 #define COUNTER_TYPE_BITS       (sizeof(COUNTER_TYPE) * 8)
126 #define COUNTER_TYPE_NUM        (COUNTER_BITS_TOTAL / COUNTER_TYPE_BITS)
127 #define COUNTER_WINDOW_SIZE     (COUNTER_BITS_TOTAL - COUNTER_TYPE_BITS)
128
129 /* Constants for the keypair */
130 #define REKEY_AFTER_MESSAGES    (1ull << 60)
131 #define REJECT_AFTER_MESSAGES   (UINT64_MAX - COUNTER_WINDOW_SIZE - 1)
132 #define REKEY_AFTER_TIME        120
133 #define REKEY_AFTER_TIME_RECV   165
134 #define REJECT_AFTER_TIME       180
135 #define REJECT_INTERVAL         (1000000000 / 50) /* fifty times per sec */
136 /* 24 = floor(log2(REJECT_INTERVAL)) */
137 #define REJECT_INTERVAL_MASK    (~((1ull<<24)-1))
138
139 enum noise_state_hs {
140         HS_ZEROED = 0,
141         CREATED_INITIATION,
142         CONSUMED_INITIATION,
143         CREATED_RESPONSE,
144         CONSUMED_RESPONSE,
145 };
146
147 struct noise_handshake {
148         enum noise_state_hs      hs_state;
149         uint32_t                 hs_local_index;
150         uint32_t                 hs_remote_index;
151         uint8_t                  hs_e[NOISE_KEY_SIZE];
152         uint8_t                  hs_hash[NOISE_HASH_SIZE];
153         uint8_t                  hs_ck[NOISE_HASH_SIZE];
154 };
155
156 struct noise_counter {
157         struct rwlock            c_lock;
158         uint64_t                 c_send;
159         uint64_t                 c_recv;
160         COUNTER_TYPE             c_backtrack[COUNTER_TYPE_NUM];
161 };
162
163 enum noise_state_kp {
164         KP_ZEROED = 0,
165         INITIATOR,
166         RESPONDER,
167 };
168
169 struct noise_keypair {
170         SLIST_ENTRY(noise_keypair)      kp_entry;
171         int                             kp_valid;
172         int                             kp_is_initiator;
173         uint32_t                        kp_local_index;
174         uint32_t                        kp_remote_index;
175         uint8_t                         kp_send[NOISE_SYMMETRIC_SIZE];
176         uint8_t                         kp_recv[NOISE_SYMMETRIC_SIZE];
177         struct timespec                 kp_birthdate; /* nanouptime */
178         struct noise_counter            kp_ctr;
179 };
180
181 struct noise_remote {
182         uint8_t                          r_public[NOISE_KEY_SIZE];
183         struct noise_local              *r_local;
184         uint8_t                          r_ss[NOISE_KEY_SIZE];
185
186         struct rwlock                    r_handshake_lock;
187         struct noise_handshake           r_handshake;
188         uint8_t                          r_psk[NOISE_PSK_SIZE];
189         uint8_t                          r_timestamp[NOISE_TIMESTAMP_SIZE];
190         struct timespec                  r_last_init; /* nanouptime */
191
192         struct rwlock                    r_keypair_lock;
193         SLIST_HEAD(,noise_keypair)       r_unused_keypairs;
194         struct noise_keypair            *r_next, *r_current, *r_previous;
195         struct noise_keypair             r_keypair[3]; /* 3: next, current, previous. */
196
197 };
198
199 struct noise_local {
200         struct rwlock           l_identity_lock;
201         int                     l_has_identity;
202         uint8_t                 l_public[NOISE_KEY_SIZE];
203         uint8_t                 l_private[NOISE_KEY_SIZE];
204
205         struct noise_upcall {
206                 void     *u_arg;
207                 struct noise_remote *
208                         (*u_remote_get)(void *, uint8_t[NOISE_KEY_SIZE]);
209                 uint32_t
210                         (*u_index_set)(void *, struct noise_remote *);
211                 void    (*u_index_drop)(void *, uint32_t);
212         }                       l_upcall;
213 };
214
215 struct noise_initiation {
216         uint32_t        s_idx;
217         uint8_t         ue[NOISE_KEY_SIZE];
218         uint8_t         es[NOISE_KEY_SIZE + NOISE_MAC_SIZE];
219         uint8_t         ets[NOISE_TIMESTAMP_SIZE + NOISE_MAC_SIZE];
220 } __packed;
221
222 struct noise_response {
223         uint32_t        s_idx;
224         uint32_t        r_idx;
225         uint8_t         ue[NOISE_KEY_SIZE];
226         uint8_t         en[0 + NOISE_MAC_SIZE];
227 } __packed;
228
229 struct noise_data {
230         uint32_t        r_idx;
231         uint64_t        nonce;
232         uint8_t         buf[];
233 } __packed;
234
235
236 /* Set/Get noise parameters */
237 void    noise_local_init(struct noise_local *, struct noise_upcall *);
238 void    noise_local_lock_identity(struct noise_local *);
239 void    noise_local_unlock_identity(struct noise_local *);
240 int     noise_local_set_private(struct noise_local *, uint8_t[NOISE_KEY_SIZE]);
241 int     noise_local_keys(struct noise_local *, uint8_t[NOISE_KEY_SIZE],
242             uint8_t[NOISE_KEY_SIZE]);
243
244 void    noise_remote_init(struct noise_remote *, const uint8_t[NOISE_KEY_SIZE],
245             struct noise_local *);
246 int     noise_remote_set_psk(struct noise_remote *, const uint8_t[NOISE_PSK_SIZE]);
247 int     noise_remote_keys(struct noise_remote *, uint8_t[NOISE_KEY_SIZE],
248             uint8_t[NOISE_PSK_SIZE]);
249
250 /* Should be called anytime noise_local_set_private is called */
251 void    noise_remote_precompute(struct noise_remote *);
252
253 /* Cryptographic functions */
254 int     noise_create_initiation(
255             struct noise_remote *,
256             struct noise_initiation *);
257
258 int     noise_consume_initiation(
259             struct noise_local *,
260             struct noise_remote **,
261             struct noise_initiation *);
262
263 int     noise_create_response(
264             struct noise_remote *,
265             struct noise_response *);
266
267 int     noise_consume_response(
268             struct noise_remote *,
269             struct noise_response *);
270
271  int    noise_remote_begin_session(struct noise_remote *);
272 void    noise_remote_clear(struct noise_remote *);
273 void    noise_remote_expire_current(struct noise_remote *);
274
275 int     noise_remote_ready(struct noise_remote *);
276
277 int     noise_remote_encrypt(
278             struct noise_remote *,
279             struct noise_data *,
280             size_t);
281 int     noise_remote_decrypt(
282             struct noise_remote *,
283             struct noise_data *,
284             size_t);
285
286 #endif /* __NOISE_H__ */