1 /* $OpenBSD: wg_cookie.c,v 1.5 2023/08/18 08:11:47 jsg Exp $ */
2 /*
3 * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
4 * Copyright (C) 2019-2020 Matt Dunwoodie <ncon@noconroy.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/types.h>
20 #include <sys/systm.h>
21 #include <sys/param.h>
22 #include <sys/rwlock.h>
23 #include <sys/malloc.h> /* Because systm doesn't include M_NOWAIT, M_DEVBUF */
24 #include <sys/pool.h>
25 #include <sys/socket.h>
26
27 #include <crypto/chachapoly.h>
28
29 #include <net/wg_cookie.h>
30
31 static void cookie_precompute_key(uint8_t *,
32 const uint8_t[COOKIE_INPUT_SIZE], const char *);
33 static void cookie_macs_mac1(struct cookie_macs *, const void *, size_t,
34 const uint8_t[COOKIE_KEY_SIZE]);
35 static void cookie_macs_mac2(struct cookie_macs *, const void *, size_t,
36 const uint8_t[COOKIE_COOKIE_SIZE]);
37 static int cookie_timer_expired(struct timespec *, time_t, long);
38 static void cookie_checker_make_cookie(struct cookie_checker *,
39 uint8_t[COOKIE_COOKIE_SIZE], struct sockaddr *);
40 static int ratelimit_init(struct ratelimit *, struct pool *);
41 static void ratelimit_deinit(struct ratelimit *);
42 static void ratelimit_gc(struct ratelimit *, int);
43 static int ratelimit_allow(struct ratelimit *, struct sockaddr *);
44
45 /* Public Functions */
46 void
cookie_maker_init(struct cookie_maker * cp,uint8_t key[COOKIE_INPUT_SIZE])47 cookie_maker_init(struct cookie_maker *cp, uint8_t key[COOKIE_INPUT_SIZE])
48 {
49 bzero(cp, sizeof(*cp));
50 cookie_precompute_key(cp->cp_mac1_key, key, COOKIE_MAC1_KEY_LABEL);
51 cookie_precompute_key(cp->cp_cookie_key, key, COOKIE_COOKIE_KEY_LABEL);
52 rw_init(&cp->cp_lock, "cookie_maker");
53 }
54
55 int
cookie_checker_init(struct cookie_checker * cc,struct pool * pool)56 cookie_checker_init(struct cookie_checker *cc, struct pool *pool)
57 {
58 int res;
59 bzero(cc, sizeof(*cc));
60
61 rw_init(&cc->cc_key_lock, "cookie_checker_key");
62 rw_init(&cc->cc_secret_lock, "cookie_checker_secret");
63
64 if ((res = ratelimit_init(&cc->cc_ratelimit_v4, pool)) != 0)
65 return res;
66 #ifdef INET6
67 if ((res = ratelimit_init(&cc->cc_ratelimit_v6, pool)) != 0) {
68 ratelimit_deinit(&cc->cc_ratelimit_v4);
69 return res;
70 }
71 #endif
72 return 0;
73 }
74
75 void
cookie_checker_update(struct cookie_checker * cc,uint8_t key[COOKIE_INPUT_SIZE])76 cookie_checker_update(struct cookie_checker *cc,
77 uint8_t key[COOKIE_INPUT_SIZE])
78 {
79 rw_enter_write(&cc->cc_key_lock);
80 if (key) {
81 cookie_precompute_key(cc->cc_mac1_key, key, COOKIE_MAC1_KEY_LABEL);
82 cookie_precompute_key(cc->cc_cookie_key, key, COOKIE_COOKIE_KEY_LABEL);
83 } else {
84 bzero(cc->cc_mac1_key, sizeof(cc->cc_mac1_key));
85 bzero(cc->cc_cookie_key, sizeof(cc->cc_cookie_key));
86 }
87 rw_exit_write(&cc->cc_key_lock);
88 }
89
90 void
cookie_checker_deinit(struct cookie_checker * cc)91 cookie_checker_deinit(struct cookie_checker *cc)
92 {
93 ratelimit_deinit(&cc->cc_ratelimit_v4);
94 #ifdef INET6
95 ratelimit_deinit(&cc->cc_ratelimit_v6);
96 #endif
97 }
98
99 void
cookie_checker_create_payload(struct cookie_checker * cc,struct cookie_macs * cm,uint8_t nonce[COOKIE_NONCE_SIZE],uint8_t ecookie[COOKIE_ENCRYPTED_SIZE],struct sockaddr * sa)100 cookie_checker_create_payload(struct cookie_checker *cc,
101 struct cookie_macs *cm, uint8_t nonce[COOKIE_NONCE_SIZE],
102 uint8_t ecookie[COOKIE_ENCRYPTED_SIZE], struct sockaddr *sa)
103 {
104 uint8_t cookie[COOKIE_COOKIE_SIZE];
105
106 cookie_checker_make_cookie(cc, cookie, sa);
107 arc4random_buf(nonce, COOKIE_NONCE_SIZE);
108
109 rw_enter_read(&cc->cc_key_lock);
110 xchacha20poly1305_encrypt(ecookie, cookie, COOKIE_COOKIE_SIZE,
111 cm->mac1, COOKIE_MAC_SIZE, nonce, cc->cc_cookie_key);
112 rw_exit_read(&cc->cc_key_lock);
113
114 explicit_bzero(cookie, sizeof(cookie));
115 }
116
117 int
cookie_maker_consume_payload(struct cookie_maker * cp,uint8_t nonce[COOKIE_NONCE_SIZE],uint8_t ecookie[COOKIE_ENCRYPTED_SIZE])118 cookie_maker_consume_payload(struct cookie_maker *cp,
119 uint8_t nonce[COOKIE_NONCE_SIZE], uint8_t ecookie[COOKIE_ENCRYPTED_SIZE])
120 {
121 int ret = 0;
122 uint8_t cookie[COOKIE_COOKIE_SIZE];
123
124 rw_enter_write(&cp->cp_lock);
125
126 if (cp->cp_mac1_valid == 0) {
127 ret = ETIMEDOUT;
128 goto error;
129 }
130
131 if (xchacha20poly1305_decrypt(cookie, ecookie, COOKIE_ENCRYPTED_SIZE,
132 cp->cp_mac1_last, COOKIE_MAC_SIZE, nonce, cp->cp_cookie_key) == 0) {
133 ret = EINVAL;
134 goto error;
135 }
136
137 memcpy(cp->cp_cookie, cookie, COOKIE_COOKIE_SIZE);
138 getnanouptime(&cp->cp_birthdate);
139 cp->cp_mac1_valid = 0;
140
141 error:
142 rw_exit_write(&cp->cp_lock);
143 return ret;
144 }
145
146 void
cookie_maker_mac(struct cookie_maker * cp,struct cookie_macs * cm,void * buf,size_t len)147 cookie_maker_mac(struct cookie_maker *cp, struct cookie_macs *cm, void *buf,
148 size_t len)
149 {
150 rw_enter_read(&cp->cp_lock);
151
152 cookie_macs_mac1(cm, buf, len, cp->cp_mac1_key);
153
154 memcpy(cp->cp_mac1_last, cm->mac1, COOKIE_MAC_SIZE);
155 cp->cp_mac1_valid = 1;
156
157 if (!cookie_timer_expired(&cp->cp_birthdate,
158 COOKIE_SECRET_MAX_AGE - COOKIE_SECRET_LATENCY, 0))
159 cookie_macs_mac2(cm, buf, len, cp->cp_cookie);
160 else
161 bzero(cm->mac2, COOKIE_MAC_SIZE);
162
163 rw_exit_read(&cp->cp_lock);
164 }
165
166 int
cookie_checker_validate_macs(struct cookie_checker * cc,struct cookie_macs * cm,void * buf,size_t len,int busy,struct sockaddr * sa)167 cookie_checker_validate_macs(struct cookie_checker *cc, struct cookie_macs *cm,
168 void *buf, size_t len, int busy, struct sockaddr *sa)
169 {
170 struct cookie_macs our_cm;
171 uint8_t cookie[COOKIE_COOKIE_SIZE];
172
173 /* Validate incoming MACs */
174 rw_enter_read(&cc->cc_key_lock);
175 cookie_macs_mac1(&our_cm, buf, len, cc->cc_mac1_key);
176 rw_exit_read(&cc->cc_key_lock);
177
178 /* If mac1 is invalid, we want to drop the packet */
179 if (timingsafe_bcmp(our_cm.mac1, cm->mac1, COOKIE_MAC_SIZE) != 0)
180 return EINVAL;
181
182 if (busy != 0) {
183 cookie_checker_make_cookie(cc, cookie, sa);
184 cookie_macs_mac2(&our_cm, buf, len, cookie);
185
186 /* If the mac2 is invalid, we want to send a cookie response */
187 if (timingsafe_bcmp(our_cm.mac2, cm->mac2, COOKIE_MAC_SIZE) != 0)
188 return EAGAIN;
189
190 /* If the mac2 is valid, we may want rate limit the peer.
191 * ratelimit_allow will return either 0 or ECONNREFUSED,
192 * implying there is no ratelimiting, or we should ratelimit
193 * (refuse) respectively. */
194 if (sa->sa_family == AF_INET)
195 return ratelimit_allow(&cc->cc_ratelimit_v4, sa);
196 #ifdef INET6
197 else if (sa->sa_family == AF_INET6)
198 return ratelimit_allow(&cc->cc_ratelimit_v6, sa);
199 #endif
200 else
201 return EAFNOSUPPORT;
202 }
203 return 0;
204 }
205
206 /* Private functions */
207 static void
cookie_precompute_key(uint8_t * key,const uint8_t input[COOKIE_INPUT_SIZE],const char * label)208 cookie_precompute_key(uint8_t *key, const uint8_t input[COOKIE_INPUT_SIZE],
209 const char *label)
210 {
211 struct blake2s_state blake;
212
213 blake2s_init(&blake, COOKIE_KEY_SIZE);
214 blake2s_update(&blake, label, strlen(label));
215 blake2s_update(&blake, input, COOKIE_INPUT_SIZE);
216 blake2s_final(&blake, key);
217 }
218
219 static void
cookie_macs_mac1(struct cookie_macs * cm,const void * buf,size_t len,const uint8_t key[COOKIE_KEY_SIZE])220 cookie_macs_mac1(struct cookie_macs *cm, const void *buf, size_t len,
221 const uint8_t key[COOKIE_KEY_SIZE])
222 {
223 struct blake2s_state state;
224 blake2s_init_key(&state, COOKIE_MAC_SIZE, key, COOKIE_KEY_SIZE);
225 blake2s_update(&state, buf, len);
226 blake2s_final(&state, cm->mac1);
227 }
228
229 static void
cookie_macs_mac2(struct cookie_macs * cm,const void * buf,size_t len,const uint8_t key[COOKIE_COOKIE_SIZE])230 cookie_macs_mac2(struct cookie_macs *cm, const void *buf, size_t len,
231 const uint8_t key[COOKIE_COOKIE_SIZE])
232 {
233 struct blake2s_state state;
234 blake2s_init_key(&state, COOKIE_MAC_SIZE, key, COOKIE_COOKIE_SIZE);
235 blake2s_update(&state, buf, len);
236 blake2s_update(&state, cm->mac1, COOKIE_MAC_SIZE);
237 blake2s_final(&state, cm->mac2);
238 }
239
240 static int
cookie_timer_expired(struct timespec * birthdate,time_t sec,long nsec)241 cookie_timer_expired(struct timespec *birthdate, time_t sec, long nsec)
242 {
243 struct timespec uptime;
244 struct timespec expire = { .tv_sec = sec, .tv_nsec = nsec };
245
246 if (birthdate->tv_sec == 0 && birthdate->tv_nsec == 0)
247 return ETIMEDOUT;
248
249 getnanouptime(&uptime);
250 timespecadd(birthdate, &expire, &expire);
251 return timespeccmp(&uptime, &expire, >) ? ETIMEDOUT : 0;
252 }
253
254 static void
cookie_checker_make_cookie(struct cookie_checker * cc,uint8_t cookie[COOKIE_COOKIE_SIZE],struct sockaddr * sa)255 cookie_checker_make_cookie(struct cookie_checker *cc,
256 uint8_t cookie[COOKIE_COOKIE_SIZE], struct sockaddr *sa)
257 {
258 struct blake2s_state state;
259
260 rw_enter_write(&cc->cc_secret_lock);
261 if (cookie_timer_expired(&cc->cc_secret_birthdate,
262 COOKIE_SECRET_MAX_AGE, 0)) {
263 arc4random_buf(cc->cc_secret, COOKIE_SECRET_SIZE);
264 getnanouptime(&cc->cc_secret_birthdate);
265 }
266 blake2s_init_key(&state, COOKIE_COOKIE_SIZE, cc->cc_secret,
267 COOKIE_SECRET_SIZE);
268 rw_exit_write(&cc->cc_secret_lock);
269
270 if (sa->sa_family == AF_INET) {
271 blake2s_update(&state, (uint8_t *)&satosin(sa)->sin_addr,
272 sizeof(struct in_addr));
273 blake2s_update(&state, (uint8_t *)&satosin(sa)->sin_port,
274 sizeof(in_port_t));
275 blake2s_final(&state, cookie);
276 #ifdef INET6
277 } else if (sa->sa_family == AF_INET6) {
278 blake2s_update(&state, (uint8_t *)&satosin6(sa)->sin6_addr,
279 sizeof(struct in6_addr));
280 blake2s_update(&state, (uint8_t *)&satosin6(sa)->sin6_port,
281 sizeof(in_port_t));
282 blake2s_final(&state, cookie);
283 #endif
284 } else {
285 arc4random_buf(cookie, COOKIE_COOKIE_SIZE);
286 }
287 }
288
289 static int
ratelimit_init(struct ratelimit * rl,struct pool * pool)290 ratelimit_init(struct ratelimit *rl, struct pool *pool)
291 {
292 rw_init(&rl->rl_lock, "ratelimit_lock");
293 arc4random_buf(&rl->rl_secret, sizeof(rl->rl_secret));
294 rl->rl_table = hashinit(RATELIMIT_SIZE, M_DEVBUF, M_NOWAIT,
295 &rl->rl_table_mask);
296 rl->rl_pool = pool;
297 rl->rl_table_num = 0;
298 return rl->rl_table == NULL ? ENOBUFS : 0;
299 }
300
301 static void
ratelimit_deinit(struct ratelimit * rl)302 ratelimit_deinit(struct ratelimit *rl)
303 {
304 rw_enter_write(&rl->rl_lock);
305 ratelimit_gc(rl, 1);
306 hashfree(rl->rl_table, RATELIMIT_SIZE, M_DEVBUF);
307 rw_exit_write(&rl->rl_lock);
308 }
309
310 static void
ratelimit_gc(struct ratelimit * rl,int force)311 ratelimit_gc(struct ratelimit *rl, int force)
312 {
313 size_t i;
314 struct ratelimit_entry *r, *tr;
315 struct timespec expiry;
316
317 rw_assert_wrlock(&rl->rl_lock);
318
319 if (force) {
320 for (i = 0; i < RATELIMIT_SIZE; i++) {
321 LIST_FOREACH_SAFE(r, &rl->rl_table[i], r_entry, tr) {
322 rl->rl_table_num--;
323 LIST_REMOVE(r, r_entry);
324 pool_put(rl->rl_pool, r);
325 }
326 }
327 return;
328 }
329
330 if ((cookie_timer_expired(&rl->rl_last_gc, ELEMENT_TIMEOUT, 0) &&
331 rl->rl_table_num > 0)) {
332 getnanouptime(&rl->rl_last_gc);
333 getnanouptime(&expiry);
334 expiry.tv_sec -= ELEMENT_TIMEOUT;
335
336 for (i = 0; i < RATELIMIT_SIZE; i++) {
337 LIST_FOREACH_SAFE(r, &rl->rl_table[i], r_entry, tr) {
338 if (timespeccmp(&r->r_last_time, &expiry, <)) {
339 rl->rl_table_num--;
340 LIST_REMOVE(r, r_entry);
341 pool_put(rl->rl_pool, r);
342 }
343 }
344 }
345 }
346 }
347
348 static int
ratelimit_allow(struct ratelimit * rl,struct sockaddr * sa)349 ratelimit_allow(struct ratelimit *rl, struct sockaddr *sa)
350 {
351 uint64_t key, tokens;
352 struct timespec diff;
353 struct ratelimit_entry *r;
354 int ret = ECONNREFUSED;
355
356 if (sa->sa_family == AF_INET)
357 key = SipHash24(&rl->rl_secret, &satosin(sa)->sin_addr,
358 IPV4_MASK_SIZE);
359 #ifdef INET6
360 else if (sa->sa_family == AF_INET6)
361 key = SipHash24(&rl->rl_secret, &satosin6(sa)->sin6_addr,
362 IPV6_MASK_SIZE);
363 #endif
364 else
365 return ret;
366
367 rw_enter_write(&rl->rl_lock);
368
369 LIST_FOREACH(r, &rl->rl_table[key & rl->rl_table_mask], r_entry) {
370 if (r->r_af != sa->sa_family)
371 continue;
372
373 if (r->r_af == AF_INET && bcmp(&r->r_in,
374 &satosin(sa)->sin_addr, IPV4_MASK_SIZE) != 0)
375 continue;
376
377 #ifdef INET6
378 if (r->r_af == AF_INET6 && bcmp(&r->r_in6,
379 &satosin6(sa)->sin6_addr, IPV6_MASK_SIZE) != 0)
380 continue;
381 #endif
382
383 /* If we get to here, we've found an entry for the endpoint.
384 * We apply standard token bucket, by calculating the time
385 * lapsed since our last_time, adding that, ensuring that we
386 * cap the tokens at TOKEN_MAX. If the endpoint has no tokens
387 * left (that is tokens <= INITIATION_COST) then we block the
388 * request, otherwise we subtract the INITIATION_COST and
389 * return OK. */
390 diff = r->r_last_time;
391 getnanouptime(&r->r_last_time);
392 timespecsub(&r->r_last_time, &diff, &diff);
393
394 tokens = r->r_tokens + diff.tv_sec * NSEC_PER_SEC + diff.tv_nsec;
395
396 if (tokens > TOKEN_MAX)
397 tokens = TOKEN_MAX;
398
399 if (tokens >= INITIATION_COST) {
400 r->r_tokens = tokens - INITIATION_COST;
401 goto ok;
402 } else {
403 r->r_tokens = tokens;
404 goto error;
405 }
406 }
407
408 /* If we get to here, we didn't have an entry for the endpoint. */
409 ratelimit_gc(rl, 0);
410
411 /* Hard limit on number of entries */
412 if (rl->rl_table_num >= RATELIMIT_SIZE_MAX)
413 goto error;
414
415 /* Goto error if out of memory */
416 if ((r = pool_get(rl->rl_pool, PR_NOWAIT)) == NULL)
417 goto error;
418
419 rl->rl_table_num++;
420
421 /* Insert entry into the hashtable and ensure it's initialised */
422 LIST_INSERT_HEAD(&rl->rl_table[key & rl->rl_table_mask], r, r_entry);
423 r->r_af = sa->sa_family;
424 if (r->r_af == AF_INET)
425 memcpy(&r->r_in, &satosin(sa)->sin_addr, IPV4_MASK_SIZE);
426 #ifdef INET6
427 else if (r->r_af == AF_INET6)
428 memcpy(&r->r_in6, &satosin6(sa)->sin6_addr, IPV6_MASK_SIZE);
429 #endif
430
431 getnanouptime(&r->r_last_time);
432 r->r_tokens = TOKEN_MAX - INITIATION_COST;
433 ok:
434 ret = 0;
435 error:
436 rw_exit_write(&rl->rl_lock);
437 return ret;
438 }
439
440 #ifdef WGTEST
441
442 #define MESSAGE_LEN 64
443 #define T_FAILED_ITER(test) do { \
444 printf("%s %s: failed. iter: %d\n", __func__, test, i); \
445 goto cleanup; \
446 } while (0)
447 #define T_FAILED(test) do { \
448 printf("%s %s: failed.\n", __func__, test); \
449 goto cleanup; \
450 } while (0)
451 #define T_PASSED printf("%s: passed.\n", __func__)
452
453 static const struct expected_results {
454 int result;
455 int sleep_time;
456 } rl_expected[] = {
457 [0 ... INITIATIONS_BURSTABLE - 1] = { 0, 0 },
458 [INITIATIONS_BURSTABLE] = { ECONNREFUSED, 0 },
459 [INITIATIONS_BURSTABLE + 1] = { 0, NSEC_PER_SEC / INITIATIONS_PER_SECOND },
460 [INITIATIONS_BURSTABLE + 2] = { ECONNREFUSED, 0 },
461 [INITIATIONS_BURSTABLE + 3] = { 0, (NSEC_PER_SEC / INITIATIONS_PER_SECOND) * 2 },
462 [INITIATIONS_BURSTABLE + 4] = { 0, 0 },
463 [INITIATIONS_BURSTABLE + 5] = { ECONNREFUSED, 0 }
464 };
465
466 static void
cookie_ratelimit_timings_test()467 cookie_ratelimit_timings_test()
468 {
469 struct ratelimit rl;
470 struct pool rl_pool;
471 struct sockaddr_in sin;
472 #ifdef INET6
473 struct sockaddr_in6 sin6;
474 #endif
475 int i;
476
477 pool_init(&rl_pool, sizeof(struct ratelimit_entry), 0,
478 IPL_NONE, 0, "rl", NULL);
479 ratelimit_init(&rl, &rl_pool);
480
481 sin.sin_family = AF_INET;
482 #ifdef INET6
483 sin6.sin6_family = AF_INET6;
484 #endif
485
486 for (i = 0; i < sizeof(rl_expected)/sizeof(*rl_expected); i++) {
487 if (rl_expected[i].sleep_time != 0)
488 tsleep_nsec(&rl, PWAIT, "rl", rl_expected[i].sleep_time);
489
490 /* The first v4 ratelimit_allow is against a constant address,
491 * and should be indifferent to the port. */
492 sin.sin_addr.s_addr = 0x01020304;
493 sin.sin_port = arc4random();
494
495 if (ratelimit_allow(&rl, sintosa(&sin)) != rl_expected[i].result)
496 T_FAILED_ITER("malicious v4");
497
498 /* The second ratelimit_allow is to test that an arbitrary
499 * address is still allowed. */
500 sin.sin_addr.s_addr += i + 1;
501 sin.sin_port = arc4random();
502
503 if (ratelimit_allow(&rl, sintosa(&sin)) != 0)
504 T_FAILED_ITER("non-malicious v4");
505
506 #ifdef INET6
507 /* The first v6 ratelimit_allow is against a constant address,
508 * and should be indifferent to the port. We also mutate the
509 * lower 64 bits of the address as we want to ensure ratelimit
510 * occurs against the higher 64 bits (/64 network). */
511 sin6.sin6_addr.s6_addr32[0] = 0x01020304;
512 sin6.sin6_addr.s6_addr32[1] = 0x05060708;
513 sin6.sin6_addr.s6_addr32[2] = i;
514 sin6.sin6_addr.s6_addr32[3] = i;
515 sin6.sin6_port = arc4random();
516
517 if (ratelimit_allow(&rl, sin6tosa(&sin6)) != rl_expected[i].result)
518 T_FAILED_ITER("malicious v6");
519
520 /* Again, test that an address different to above is still
521 * allowed. */
522 sin6.sin6_addr.s6_addr32[0] += i + 1;
523 sin6.sin6_port = arc4random();
524
525 if (ratelimit_allow(&rl, sintosa(&sin)) != 0)
526 T_FAILED_ITER("non-malicious v6");
527 #endif
528 }
529 T_PASSED;
530 cleanup:
531 ratelimit_deinit(&rl);
532 pool_destroy(&rl_pool);
533 }
534
535 static void
cookie_ratelimit_capacity_test()536 cookie_ratelimit_capacity_test()
537 {
538 struct ratelimit rl;
539 struct pool rl_pool;
540 struct sockaddr_in sin;
541 int i;
542
543 pool_init(&rl_pool, sizeof(struct ratelimit_entry), 0,
544 IPL_NONE, 0, "rl", NULL);
545 ratelimit_init(&rl, &rl_pool);
546
547 sin.sin_family = AF_INET;
548 sin.sin_port = 1234;
549
550 /* Here we test that the ratelimiter has an upper bound on the number
551 * of addresses to be limited */
552 for (i = 0; i <= RATELIMIT_SIZE_MAX; i++) {
553 sin.sin_addr.s_addr = i;
554 if (i == RATELIMIT_SIZE_MAX) {
555 if (ratelimit_allow(&rl, sintosa(&sin)) != ECONNREFUSED)
556 T_FAILED_ITER("reject");
557 } else {
558 if (ratelimit_allow(&rl, sintosa(&sin)) != 0)
559 T_FAILED_ITER("allow");
560 }
561 }
562 T_PASSED;
563 cleanup:
564 ratelimit_deinit(&rl);
565 pool_destroy(&rl_pool);
566 }
567
568 static void
cookie_mac_test()569 cookie_mac_test()
570 {
571 struct pool rl_pool;
572 struct cookie_checker checker;
573 struct cookie_maker maker;
574 struct cookie_macs cm;
575 struct sockaddr_in sin;
576 int res, i;
577
578 uint8_t nonce[COOKIE_NONCE_SIZE];
579 uint8_t cookie[COOKIE_ENCRYPTED_SIZE];
580 uint8_t shared[COOKIE_INPUT_SIZE];
581 uint8_t message[MESSAGE_LEN];
582
583 arc4random_buf(shared, COOKIE_INPUT_SIZE);
584 arc4random_buf(message, MESSAGE_LEN);
585
586 /* Init cookie_maker. */
587 cookie_maker_init(&maker, shared);
588
589 /* Init cookie_checker. */
590 pool_init(&rl_pool, sizeof(struct ratelimit_entry), 0,
591 IPL_NONE, 0, "rl", NULL);
592
593 if (cookie_checker_init(&checker, &rl_pool) != 0)
594 T_FAILED("cookie_checker_allocate");
595 cookie_checker_update(&checker, shared);
596
597 /* Create dummy sockaddr */
598 sin.sin_family = AF_INET;
599 sin.sin_len = sizeof(sin);
600 sin.sin_addr.s_addr = 1;
601 sin.sin_port = 51820;
602
603 /* MAC message */
604 cookie_maker_mac(&maker, &cm, message, MESSAGE_LEN);
605
606 /* Check we have a null mac2 */
607 for (i = 0; i < sizeof(cm.mac2); i++)
608 if (cm.mac2[i] != 0)
609 T_FAILED("validate_macs_noload_mac2_zeroed");
610
611 /* Validate all bytes are checked in mac1 */
612 for (i = 0; i < sizeof(cm.mac1); i++) {
613 cm.mac1[i] = ~cm.mac1[i];
614 if (cookie_checker_validate_macs(&checker, &cm, message,
615 MESSAGE_LEN, 0, sintosa(&sin)) != EINVAL)
616 T_FAILED("validate_macs_noload_munge");
617 cm.mac1[i] = ~cm.mac1[i];
618 }
619
620 /* Check mac2 is zeroed */
621 res = 0;
622 for (i = 0; i < sizeof(cm.mac2); i++)
623 res |= cm.mac2[i];
624 if (res != 0)
625 T_FAILED("validate_macs_mac2_checkzero");
626
627
628 /* Check we can successfully validate the MAC */
629 if (cookie_checker_validate_macs(&checker, &cm, message,
630 MESSAGE_LEN, 0, sintosa(&sin)) != 0)
631 T_FAILED("validate_macs_noload_normal");
632
633 /* Check we get a EAGAIN if no mac2 and under load */
634 if (cookie_checker_validate_macs(&checker, &cm, message,
635 MESSAGE_LEN, 1, sintosa(&sin)) != EAGAIN)
636 T_FAILED("validate_macs_load_normal");
637
638 /* Simulate a cookie message */
639 cookie_checker_create_payload(&checker, &cm, nonce, cookie, sintosa(&sin));
640
641 /* Validate all bytes are checked in cookie */
642 for (i = 0; i < sizeof(cookie); i++) {
643 cookie[i] = ~cookie[i];
644 if (cookie_maker_consume_payload(&maker, nonce, cookie) != EINVAL)
645 T_FAILED("consume_payload_munge");
646 cookie[i] = ~cookie[i];
647 }
648
649 /* Check we can actually consume the payload */
650 if (cookie_maker_consume_payload(&maker, nonce, cookie) != 0)
651 T_FAILED("consume_payload_normal");
652
653 /* Check replay isn't allowed */
654 if (cookie_maker_consume_payload(&maker, nonce, cookie) != ETIMEDOUT)
655 T_FAILED("consume_payload_normal_replay");
656
657 /* MAC message again, with MAC2 */
658 cookie_maker_mac(&maker, &cm, message, MESSAGE_LEN);
659
660 /* Check we added a mac2 */
661 res = 0;
662 for (i = 0; i < sizeof(cm.mac2); i++)
663 res |= cm.mac2[i];
664 if (res == 0)
665 T_FAILED("validate_macs_make_mac2");
666
667 /* Check we get OK if mac2 and under load */
668 if (cookie_checker_validate_macs(&checker, &cm, message,
669 MESSAGE_LEN, 1, sintosa(&sin)) != 0)
670 T_FAILED("validate_macs_load_normal_mac2");
671
672 sin.sin_addr.s_addr = ~sin.sin_addr.s_addr;
673 /* Check we get EAGAIN if we munge the source IP */
674 if (cookie_checker_validate_macs(&checker, &cm, message,
675 MESSAGE_LEN, 1, sintosa(&sin)) != EAGAIN)
676 T_FAILED("validate_macs_load_spoofip_mac2");
677 sin.sin_addr.s_addr = ~sin.sin_addr.s_addr;
678
679 /* Check we get OK if mac2 and under load */
680 if (cookie_checker_validate_macs(&checker, &cm, message,
681 MESSAGE_LEN, 1, sintosa(&sin)) != 0)
682 T_FAILED("validate_macs_load_normal_mac2_retry");
683
684 printf("cookie_mac: passed.\n");
685 cleanup:
686 cookie_checker_deinit(&checker);
687 pool_destroy(&rl_pool);
688 }
689
690 void
cookie_test()691 cookie_test()
692 {
693 cookie_ratelimit_timings_test();
694 cookie_ratelimit_capacity_test();
695 cookie_mac_test();
696 }
697
698 #endif /* WGTEST */
699