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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 691 cookie_test() 692 { 693 cookie_ratelimit_timings_test(); 694 cookie_ratelimit_capacity_test(); 695 cookie_mac_test(); 696 } 697 698 #endif /* WGTEST */ 699