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