]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/wg/wg_cookie.c
zfs: merge openzfs/zfs@887a3c533
[FreeBSD/FreeBSD.git] / sys / dev / wg / wg_cookie.c
1 /* SPDX-License-Identifier: ISC
2  *
3  * Copyright (C) 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
4  * Copyright (C) 2019-2021 Matt Dunwoodie <ncon@noconroy.net>
5  */
6
7 #include "opt_inet.h"
8 #include "opt_inet6.h"
9
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/kernel.h>
13 #include <sys/lock.h>
14 #include <sys/mutex.h>
15 #include <sys/rwlock.h>
16 #include <sys/socket.h>
17 #include <crypto/siphash/siphash.h>
18 #include <netinet/in.h>
19 #include <vm/uma.h>
20
21 #include "wg_cookie.h"
22
23 #define COOKIE_MAC1_KEY_LABEL   "mac1----"
24 #define COOKIE_COOKIE_KEY_LABEL "cookie--"
25 #define COOKIE_SECRET_MAX_AGE   120
26 #define COOKIE_SECRET_LATENCY   5
27
28 /* Constants for initiation rate limiting */
29 #define RATELIMIT_SIZE          (1 << 13)
30 #define RATELIMIT_MASK          (RATELIMIT_SIZE - 1)
31 #define RATELIMIT_SIZE_MAX      (RATELIMIT_SIZE * 8)
32 #define INITIATIONS_PER_SECOND  20
33 #define INITIATIONS_BURSTABLE   5
34 #define INITIATION_COST         (SBT_1S / INITIATIONS_PER_SECOND)
35 #define TOKEN_MAX               (INITIATION_COST * INITIATIONS_BURSTABLE)
36 #define ELEMENT_TIMEOUT         1
37 #define IPV4_MASK_SIZE          4 /* Use all 4 bytes of IPv4 address */
38 #define IPV6_MASK_SIZE          8 /* Use top 8 bytes (/64) of IPv6 address */
39
40 struct ratelimit_key {
41         struct vnet *vnet;
42         uint8_t ip[IPV6_MASK_SIZE];
43 };
44
45 struct ratelimit_entry {
46         LIST_ENTRY(ratelimit_entry)     r_entry;
47         struct ratelimit_key            r_key;
48         sbintime_t                      r_last_time;    /* sbinuptime */
49         uint64_t                        r_tokens;
50 };
51
52 struct ratelimit {
53         uint8_t                         rl_secret[SIPHASH_KEY_LENGTH];
54         struct mtx                      rl_mtx;
55         struct callout                  rl_gc;
56         LIST_HEAD(, ratelimit_entry)    rl_table[RATELIMIT_SIZE];
57         size_t                          rl_table_num;
58         bool                            rl_initialized;
59 };
60
61 static void     precompute_key(uint8_t *,
62                         const uint8_t[COOKIE_INPUT_SIZE], const char *);
63 static void     macs_mac1(struct cookie_macs *, const void *, size_t,
64                         const uint8_t[COOKIE_KEY_SIZE]);
65 static void     macs_mac2(struct cookie_macs *, const void *, size_t,
66                         const uint8_t[COOKIE_COOKIE_SIZE]);
67 static int      timer_expired(sbintime_t, uint32_t, uint32_t);
68 static void     make_cookie(struct cookie_checker *,
69                         uint8_t[COOKIE_COOKIE_SIZE], struct sockaddr *);
70 static void     ratelimit_init(struct ratelimit *);
71 static void     ratelimit_deinit(struct ratelimit *);
72 static void     ratelimit_gc_callout(void *);
73 static void     ratelimit_gc_schedule(struct ratelimit *);
74 static void     ratelimit_gc(struct ratelimit *, bool);
75 static int      ratelimit_allow(struct ratelimit *, struct sockaddr *, struct vnet *);
76 static uint64_t siphash13(const uint8_t [SIPHASH_KEY_LENGTH], const void *, size_t);
77
78 static struct ratelimit ratelimit_v4;
79 #ifdef INET6
80 static struct ratelimit ratelimit_v6;
81 #endif
82 static uma_zone_t ratelimit_zone;
83
84 /* Public Functions */
85 int
86 cookie_init(void)
87 {
88         if ((ratelimit_zone = uma_zcreate("wg ratelimit",
89             sizeof(struct ratelimit_entry), NULL, NULL, NULL, NULL, 0, 0)) == NULL)
90                 return ENOMEM;
91
92         ratelimit_init(&ratelimit_v4);
93 #ifdef INET6
94         ratelimit_init(&ratelimit_v6);
95 #endif
96         return (0);
97 }
98
99 void
100 cookie_deinit(void)
101 {
102         ratelimit_deinit(&ratelimit_v4);
103 #ifdef INET6
104         ratelimit_deinit(&ratelimit_v6);
105 #endif
106         if (ratelimit_zone != NULL)
107                 uma_zdestroy(ratelimit_zone);
108 }
109
110 void
111 cookie_checker_init(struct cookie_checker *cc)
112 {
113         bzero(cc, sizeof(*cc));
114
115         rw_init(&cc->cc_key_lock, "cookie_checker_key");
116         mtx_init(&cc->cc_secret_mtx, "cookie_checker_secret", NULL, MTX_DEF);
117 }
118
119 void
120 cookie_checker_free(struct cookie_checker *cc)
121 {
122         rw_destroy(&cc->cc_key_lock);
123         mtx_destroy(&cc->cc_secret_mtx);
124         explicit_bzero(cc, sizeof(*cc));
125 }
126
127 void
128 cookie_checker_update(struct cookie_checker *cc,
129     const uint8_t key[COOKIE_INPUT_SIZE])
130 {
131         rw_wlock(&cc->cc_key_lock);
132         if (key) {
133                 precompute_key(cc->cc_mac1_key, key, COOKIE_MAC1_KEY_LABEL);
134                 precompute_key(cc->cc_cookie_key, key, COOKIE_COOKIE_KEY_LABEL);
135         } else {
136                 bzero(cc->cc_mac1_key, sizeof(cc->cc_mac1_key));
137                 bzero(cc->cc_cookie_key, sizeof(cc->cc_cookie_key));
138         }
139         rw_wunlock(&cc->cc_key_lock);
140 }
141
142 void
143 cookie_checker_create_payload(struct cookie_checker *cc,
144     struct cookie_macs *macs, uint8_t nonce[COOKIE_NONCE_SIZE],
145     uint8_t ecookie[COOKIE_ENCRYPTED_SIZE], struct sockaddr *sa)
146 {
147         uint8_t cookie[COOKIE_COOKIE_SIZE];
148
149         make_cookie(cc, cookie, sa);
150         arc4random_buf(nonce, COOKIE_NONCE_SIZE);
151
152         rw_rlock(&cc->cc_key_lock);
153         xchacha20poly1305_encrypt(ecookie, cookie, COOKIE_COOKIE_SIZE,
154             macs->mac1, COOKIE_MAC_SIZE, nonce, cc->cc_cookie_key);
155         rw_runlock(&cc->cc_key_lock);
156
157         explicit_bzero(cookie, sizeof(cookie));
158 }
159
160 void
161 cookie_maker_init(struct cookie_maker *cm, const uint8_t key[COOKIE_INPUT_SIZE])
162 {
163         bzero(cm, sizeof(*cm));
164         precompute_key(cm->cm_mac1_key, key, COOKIE_MAC1_KEY_LABEL);
165         precompute_key(cm->cm_cookie_key, key, COOKIE_COOKIE_KEY_LABEL);
166         rw_init(&cm->cm_lock, "cookie_maker");
167 }
168
169 void
170 cookie_maker_free(struct cookie_maker *cm)
171 {
172         rw_destroy(&cm->cm_lock);
173         explicit_bzero(cm, sizeof(*cm));
174 }
175
176 int
177 cookie_maker_consume_payload(struct cookie_maker *cm,
178     uint8_t nonce[COOKIE_NONCE_SIZE], uint8_t ecookie[COOKIE_ENCRYPTED_SIZE])
179 {
180         uint8_t cookie[COOKIE_COOKIE_SIZE];
181         int ret;
182
183         rw_rlock(&cm->cm_lock);
184         if (!cm->cm_mac1_sent) {
185                 ret = ETIMEDOUT;
186                 goto error;
187         }
188
189         if (!xchacha20poly1305_decrypt(cookie, ecookie, COOKIE_ENCRYPTED_SIZE,
190             cm->cm_mac1_last, COOKIE_MAC_SIZE, nonce, cm->cm_cookie_key)) {
191                 ret = EINVAL;
192                 goto error;
193         }
194         rw_runlock(&cm->cm_lock);
195
196         rw_wlock(&cm->cm_lock);
197         memcpy(cm->cm_cookie, cookie, COOKIE_COOKIE_SIZE);
198         cm->cm_cookie_birthdate = getsbinuptime();
199         cm->cm_cookie_valid = true;
200         cm->cm_mac1_sent = false;
201         rw_wunlock(&cm->cm_lock);
202
203         return 0;
204 error:
205         rw_runlock(&cm->cm_lock);
206         return ret;
207 }
208
209 void
210 cookie_maker_mac(struct cookie_maker *cm, struct cookie_macs *macs, void *buf,
211     size_t len)
212 {
213         rw_wlock(&cm->cm_lock);
214         macs_mac1(macs, buf, len, cm->cm_mac1_key);
215         memcpy(cm->cm_mac1_last, macs->mac1, COOKIE_MAC_SIZE);
216         cm->cm_mac1_sent = true;
217
218         if (cm->cm_cookie_valid &&
219             !timer_expired(cm->cm_cookie_birthdate,
220             COOKIE_SECRET_MAX_AGE - COOKIE_SECRET_LATENCY, 0)) {
221                 macs_mac2(macs, buf, len, cm->cm_cookie);
222         } else {
223                 bzero(macs->mac2, COOKIE_MAC_SIZE);
224                 cm->cm_cookie_valid = false;
225         }
226         rw_wunlock(&cm->cm_lock);
227 }
228
229 int
230 cookie_checker_validate_macs(struct cookie_checker *cc, struct cookie_macs *macs,
231     void *buf, size_t len, bool check_cookie, struct sockaddr *sa, struct vnet *vnet)
232 {
233         struct cookie_macs our_macs;
234         uint8_t cookie[COOKIE_COOKIE_SIZE];
235
236         /* Validate incoming MACs */
237         rw_rlock(&cc->cc_key_lock);
238         macs_mac1(&our_macs, buf, len, cc->cc_mac1_key);
239         rw_runlock(&cc->cc_key_lock);
240
241         /* If mac1 is invald, we want to drop the packet */
242         if (timingsafe_bcmp(our_macs.mac1, macs->mac1, COOKIE_MAC_SIZE) != 0)
243                 return EINVAL;
244
245         if (check_cookie) {
246                 make_cookie(cc, cookie, sa);
247                 macs_mac2(&our_macs, buf, len, cookie);
248
249                 /* If the mac2 is invalid, we want to send a cookie response */
250                 if (timingsafe_bcmp(our_macs.mac2, macs->mac2, COOKIE_MAC_SIZE) != 0)
251                         return EAGAIN;
252
253                 /* If the mac2 is valid, we may want rate limit the peer.
254                  * ratelimit_allow will return either 0 or ECONNREFUSED,
255                  * implying there is no ratelimiting, or we should ratelimit
256                  * (refuse) respectively. */
257                 if (sa->sa_family == AF_INET)
258                         return ratelimit_allow(&ratelimit_v4, sa, vnet);
259 #ifdef INET6
260                 else if (sa->sa_family == AF_INET6)
261                         return ratelimit_allow(&ratelimit_v6, sa, vnet);
262 #endif
263                 else
264                         return EAFNOSUPPORT;
265         }
266
267         return 0;
268 }
269
270 /* Private functions */
271 static void
272 precompute_key(uint8_t *key, const uint8_t input[COOKIE_INPUT_SIZE],
273     const char *label)
274 {
275         struct blake2s_state blake;
276         blake2s_init(&blake, COOKIE_KEY_SIZE);
277         blake2s_update(&blake, label, strlen(label));
278         blake2s_update(&blake, input, COOKIE_INPUT_SIZE);
279         blake2s_final(&blake, key);
280 }
281
282 static void
283 macs_mac1(struct cookie_macs *macs, const void *buf, size_t len,
284     const uint8_t key[COOKIE_KEY_SIZE])
285 {
286         struct blake2s_state state;
287         blake2s_init_key(&state, COOKIE_MAC_SIZE, key, COOKIE_KEY_SIZE);
288         blake2s_update(&state, buf, len);
289         blake2s_final(&state, macs->mac1);
290 }
291
292 static void
293 macs_mac2(struct cookie_macs *macs, const void *buf, size_t len,
294     const uint8_t key[COOKIE_COOKIE_SIZE])
295 {
296         struct blake2s_state state;
297         blake2s_init_key(&state, COOKIE_MAC_SIZE, key, COOKIE_COOKIE_SIZE);
298         blake2s_update(&state, buf, len);
299         blake2s_update(&state, macs->mac1, COOKIE_MAC_SIZE);
300         blake2s_final(&state, macs->mac2);
301 }
302
303 static __inline int
304 timer_expired(sbintime_t timer, uint32_t sec, uint32_t nsec)
305 {
306         sbintime_t now = getsbinuptime();
307         return (now > (timer + sec * SBT_1S + nstosbt(nsec))) ? ETIMEDOUT : 0;
308 }
309
310 static void
311 make_cookie(struct cookie_checker *cc, uint8_t cookie[COOKIE_COOKIE_SIZE],
312     struct sockaddr *sa)
313 {
314         struct blake2s_state state;
315
316         mtx_lock(&cc->cc_secret_mtx);
317         if (timer_expired(cc->cc_secret_birthdate,
318             COOKIE_SECRET_MAX_AGE, 0)) {
319                 arc4random_buf(cc->cc_secret, COOKIE_SECRET_SIZE);
320                 cc->cc_secret_birthdate = getsbinuptime();
321         }
322         blake2s_init_key(&state, COOKIE_COOKIE_SIZE, cc->cc_secret,
323             COOKIE_SECRET_SIZE);
324         mtx_unlock(&cc->cc_secret_mtx);
325
326         if (sa->sa_family == AF_INET) {
327                 blake2s_update(&state, (uint8_t *)&satosin(sa)->sin_addr,
328                                 sizeof(struct in_addr));
329                 blake2s_update(&state, (uint8_t *)&satosin(sa)->sin_port,
330                                 sizeof(in_port_t));
331                 blake2s_final(&state, cookie);
332 #ifdef INET6
333         } else if (sa->sa_family == AF_INET6) {
334                 blake2s_update(&state, (uint8_t *)&satosin6(sa)->sin6_addr,
335                                 sizeof(struct in6_addr));
336                 blake2s_update(&state, (uint8_t *)&satosin6(sa)->sin6_port,
337                                 sizeof(in_port_t));
338                 blake2s_final(&state, cookie);
339 #endif
340         } else {
341                 arc4random_buf(cookie, COOKIE_COOKIE_SIZE);
342         }
343 }
344
345 static void
346 ratelimit_init(struct ratelimit *rl)
347 {
348         size_t i;
349         mtx_init(&rl->rl_mtx, "ratelimit_lock", NULL, MTX_DEF);
350         callout_init_mtx(&rl->rl_gc, &rl->rl_mtx, 0);
351         arc4random_buf(rl->rl_secret, sizeof(rl->rl_secret));
352         for (i = 0; i < RATELIMIT_SIZE; i++)
353                 LIST_INIT(&rl->rl_table[i]);
354         rl->rl_table_num = 0;
355         rl->rl_initialized = true;
356 }
357
358 static void
359 ratelimit_deinit(struct ratelimit *rl)
360 {
361         if (!rl->rl_initialized)
362                 return;
363         mtx_lock(&rl->rl_mtx);
364         callout_stop(&rl->rl_gc);
365         ratelimit_gc(rl, true);
366         mtx_unlock(&rl->rl_mtx);
367         mtx_destroy(&rl->rl_mtx);
368
369         rl->rl_initialized = false;
370 }
371
372 static void
373 ratelimit_gc_callout(void *_rl)
374 {
375         /* callout will lock rl_mtx for us */
376         ratelimit_gc(_rl, false);
377 }
378
379 static void
380 ratelimit_gc_schedule(struct ratelimit *rl)
381 {
382         /* Trigger another GC if needed. There is no point calling GC if there
383          * are no entries in the table. We also want to ensure that GC occurs
384          * on a regular interval, so don't override a currently pending GC.
385          *
386          * In the case of a forced ratelimit_gc, there will be no entries left
387          * so we will will not schedule another GC. */
388         if (rl->rl_table_num > 0 && !callout_pending(&rl->rl_gc))
389                 callout_reset(&rl->rl_gc, ELEMENT_TIMEOUT * hz,
390                     ratelimit_gc_callout, rl);
391 }
392
393 static void
394 ratelimit_gc(struct ratelimit *rl, bool force)
395 {
396         size_t i;
397         struct ratelimit_entry *r, *tr;
398         sbintime_t expiry;
399
400         mtx_assert(&rl->rl_mtx, MA_OWNED);
401
402         if (rl->rl_table_num == 0)
403                 return;
404
405         expiry = getsbinuptime() - ELEMENT_TIMEOUT * SBT_1S;
406
407         for (i = 0; i < RATELIMIT_SIZE; i++) {
408                 LIST_FOREACH_SAFE(r, &rl->rl_table[i], r_entry, tr) {
409                         if (r->r_last_time < expiry || force) {
410                                 rl->rl_table_num--;
411                                 LIST_REMOVE(r, r_entry);
412                                 uma_zfree(ratelimit_zone, r);
413                         }
414                 }
415         }
416
417         ratelimit_gc_schedule(rl);
418 }
419
420 static int
421 ratelimit_allow(struct ratelimit *rl, struct sockaddr *sa, struct vnet *vnet)
422 {
423         uint64_t bucket, tokens;
424         sbintime_t diff, now;
425         struct ratelimit_entry *r;
426         int ret = ECONNREFUSED;
427         struct ratelimit_key key = { .vnet = vnet };
428         size_t len = sizeof(key);
429
430         if (sa->sa_family == AF_INET) {
431                 memcpy(key.ip, &satosin(sa)->sin_addr, IPV4_MASK_SIZE);
432                 len -= IPV6_MASK_SIZE - IPV4_MASK_SIZE;
433         }
434 #ifdef INET6
435         else if (sa->sa_family == AF_INET6)
436                 memcpy(key.ip, &satosin6(sa)->sin6_addr, IPV6_MASK_SIZE);
437 #endif
438         else
439                 return ret;
440
441         bucket = siphash13(rl->rl_secret, &key, len) & RATELIMIT_MASK;
442         mtx_lock(&rl->rl_mtx);
443
444         LIST_FOREACH(r, &rl->rl_table[bucket], r_entry) {
445                 if (bcmp(&r->r_key, &key, len) != 0)
446                         continue;
447
448                 /* If we get to here, we've found an entry for the endpoint.
449                  * We apply standard token bucket, by calculating the time
450                  * lapsed since our last_time, adding that, ensuring that we
451                  * cap the tokens at TOKEN_MAX. If the endpoint has no tokens
452                  * left (that is tokens <= INITIATION_COST) then we block the
453                  * request, otherwise we subtract the INITITIATION_COST and
454                  * return OK. */
455                 now = getsbinuptime();
456                 diff = now - r->r_last_time;
457                 r->r_last_time = now;
458
459                 tokens = r->r_tokens + diff;
460
461                 if (tokens > TOKEN_MAX)
462                         tokens = TOKEN_MAX;
463
464                 if (tokens >= INITIATION_COST) {
465                         r->r_tokens = tokens - INITIATION_COST;
466                         goto ok;
467                 } else {
468                         r->r_tokens = tokens;
469                         goto error;
470                 }
471         }
472
473         /* If we get to here, we didn't have an entry for the endpoint, let's
474          * add one if we have space. */
475         if (rl->rl_table_num >= RATELIMIT_SIZE_MAX)
476                 goto error;
477
478         /* Goto error if out of memory */
479         if ((r = uma_zalloc(ratelimit_zone, M_NOWAIT | M_ZERO)) == NULL)
480                 goto error;
481
482         rl->rl_table_num++;
483
484         /* Insert entry into the hashtable and ensure it's initialised */
485         LIST_INSERT_HEAD(&rl->rl_table[bucket], r, r_entry);
486         r->r_key = key;
487         r->r_last_time = getsbinuptime();
488         r->r_tokens = TOKEN_MAX - INITIATION_COST;
489
490         /* If we've added a new entry, let's trigger GC. */
491         ratelimit_gc_schedule(rl);
492 ok:
493         ret = 0;
494 error:
495         mtx_unlock(&rl->rl_mtx);
496         return ret;
497 }
498
499 static uint64_t siphash13(const uint8_t key[SIPHASH_KEY_LENGTH], const void *src, size_t len)
500 {
501         SIPHASH_CTX ctx;
502         return (SipHashX(&ctx, 1, 3, key, src, len));
503 }
504
505 #ifdef SELFTESTS
506 #include "selftest/cookie.c"
507 #endif /* SELFTESTS */