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