xref: /openbsd/sys/net/wg_cookie.c (revision f55a249e)
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