1 // SPDX-License-Identifier: GPL-2.0 2 /* Author: Dmitry Safonov <dima@arista.com> */ 3 #include <inttypes.h> 4 #include "../../../../include/linux/kernel.h" 5 #include "aolib.h" 6 7 const size_t nr_packets = 20; 8 const size_t msg_len = 100; 9 const size_t quota = nr_packets * msg_len; 10 union tcp_addr wrong_addr; 11 #define SECOND_PASSWORD "at all times sincere friends of freedom have been rare" 12 #define fault(type) (inj == FAULT_ ## type) 13 14 static const int test_vrf_ifindex = 200; 15 static const uint8_t test_vrf_tabid = 42; 16 static void setup_vrfs(void) 17 { 18 int err; 19 20 if (!kernel_config_has(KCONFIG_NET_VRF)) 21 return; 22 23 err = add_vrf("ksft-vrf", test_vrf_tabid, test_vrf_ifindex, -1); 24 if (err) 25 test_error("Failed to add a VRF: %d", err); 26 27 err = link_set_up("ksft-vrf"); 28 if (err) 29 test_error("Failed to bring up a VRF"); 30 31 err = ip_route_add_vrf(veth_name, TEST_FAMILY, 32 this_ip_addr, this_ip_dest, test_vrf_tabid); 33 if (err) 34 test_error("Failed to add a route to VRF"); 35 } 36 37 38 static int prepare_sk(union tcp_addr *addr, uint8_t sndid, uint8_t rcvid) 39 { 40 int sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP); 41 42 if (sk < 0) 43 test_error("socket()"); 44 45 if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, 46 DEFAULT_TEST_PREFIX, 100, 100)) 47 test_error("test_add_key()"); 48 49 if (addr && test_add_key(sk, SECOND_PASSWORD, *addr, 50 DEFAULT_TEST_PREFIX, sndid, rcvid)) 51 test_error("test_add_key()"); 52 53 return sk; 54 } 55 56 static int prepare_lsk(union tcp_addr *addr, uint8_t sndid, uint8_t rcvid) 57 { 58 int sk = prepare_sk(addr, sndid, rcvid); 59 60 if (listen(sk, 10)) 61 test_error("listen()"); 62 63 return sk; 64 } 65 66 static int test_del_key(int sk, uint8_t sndid, uint8_t rcvid, int ifindex, 67 bool async, int current_key, int rnext_key) 68 { 69 struct tcp_ao_info_opt ao_info = {}; 70 struct tcp_ao_getsockopt key = {}; 71 struct tcp_ao_del del = {}; 72 sockaddr_af sockaddr; 73 int err; 74 75 tcp_addr_to_sockaddr_in(&del.addr, &this_ip_dest, 0); 76 del.prefix = DEFAULT_TEST_PREFIX; 77 del.sndid = sndid; 78 del.rcvid = rcvid; 79 if (ifindex) { 80 del.keyflags = TCP_AO_KEYF_IFINDEX; 81 del.ifindex = ifindex; 82 } 83 84 if (current_key >= 0) { 85 del.set_current = 1; 86 del.current_key = (uint8_t)current_key; 87 } 88 if (rnext_key >= 0) { 89 del.set_rnext = 1; 90 del.rnext = (uint8_t)rnext_key; 91 } 92 93 err = setsockopt(sk, IPPROTO_TCP, TCP_AO_DEL_KEY, &del, sizeof(del)); 94 if (err < 0) 95 return -errno; 96 97 if (async) 98 return 0; 99 100 tcp_addr_to_sockaddr_in(&sockaddr, &this_ip_dest, 0); 101 err = test_get_one_ao(sk, &key, &sockaddr, sizeof(sockaddr), 102 DEFAULT_TEST_PREFIX, sndid, rcvid, 103 del.keyflags, del.ifindex); 104 if (!err) 105 return -EEXIST; 106 if (err != -E2BIG) 107 test_error("getsockopt()"); 108 if (current_key < 0 && rnext_key < 0) 109 return 0; 110 if (test_get_ao_info(sk, &ao_info)) 111 test_error("getsockopt(TCP_AO_INFO) failed"); 112 if (current_key >= 0 && ao_info.current_key != (uint8_t)current_key) 113 return -ENOTRECOVERABLE; 114 if (rnext_key >= 0 && ao_info.rnext != (uint8_t)rnext_key) 115 return -ENOTRECOVERABLE; 116 return 0; 117 } 118 119 static void try_delete_key(char *tst_name, int sk, uint8_t sndid, uint8_t rcvid, 120 int ifindex, bool async, int current_key, int rnext_key, 121 fault_t inj) 122 { 123 int err; 124 125 err = test_del_key(sk, sndid, rcvid, ifindex, async, current_key, rnext_key); 126 if ((err == -EBUSY && fault(BUSY)) || (err == -EINVAL && fault(CURRNEXT))) { 127 test_ok("%s: key deletion was prevented", tst_name); 128 return; 129 } 130 if (err && fault(FIXME)) { 131 test_xfail("%s: failed to delete the key %u:%u %d", 132 tst_name, sndid, rcvid, err); 133 return; 134 } 135 if (!err) { 136 if (fault(BUSY) || fault(CURRNEXT)) { 137 test_fail("%s: the key was deleted %u:%u %d", tst_name, 138 sndid, rcvid, err); 139 } else { 140 test_ok("%s: the key was deleted", tst_name); 141 } 142 return; 143 } 144 test_fail("%s: can't delete the key %u:%u %d", tst_name, sndid, rcvid, err); 145 } 146 147 static int test_set_key(int sk, int current_keyid, int rnext_keyid) 148 { 149 struct tcp_ao_info_opt ao_info = {}; 150 int err; 151 152 if (current_keyid >= 0) { 153 ao_info.set_current = 1; 154 ao_info.current_key = (uint8_t)current_keyid; 155 } 156 if (rnext_keyid >= 0) { 157 ao_info.set_rnext = 1; 158 ao_info.rnext = (uint8_t)rnext_keyid; 159 } 160 161 err = test_set_ao_info(sk, &ao_info); 162 if (err) 163 return err; 164 if (test_get_ao_info(sk, &ao_info)) 165 test_error("getsockopt(TCP_AO_INFO) failed"); 166 if (current_keyid >= 0 && ao_info.current_key != (uint8_t)current_keyid) 167 return -ENOTRECOVERABLE; 168 if (rnext_keyid >= 0 && ao_info.rnext != (uint8_t)rnext_keyid) 169 return -ENOTRECOVERABLE; 170 return 0; 171 } 172 173 static int test_add_current_rnext_key(int sk, const char *key, uint8_t keyflags, 174 union tcp_addr in_addr, uint8_t prefix, 175 bool set_current, bool set_rnext, 176 uint8_t sndid, uint8_t rcvid) 177 { 178 struct tcp_ao_add tmp = {}; 179 int err; 180 181 err = test_prepare_key(&tmp, DEFAULT_TEST_ALGO, in_addr, 182 set_current, set_rnext, 183 prefix, 0, sndid, rcvid, 0, keyflags, 184 strlen(key), key); 185 if (err) 186 return err; 187 188 189 err = setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &tmp, sizeof(tmp)); 190 if (err < 0) 191 return -errno; 192 193 return test_verify_socket_key(sk, &tmp); 194 } 195 196 static int __try_add_current_rnext_key(int sk, const char *key, uint8_t keyflags, 197 union tcp_addr in_addr, uint8_t prefix, 198 bool set_current, bool set_rnext, 199 uint8_t sndid, uint8_t rcvid) 200 { 201 struct tcp_ao_info_opt ao_info = {}; 202 int err; 203 204 err = test_add_current_rnext_key(sk, key, keyflags, in_addr, prefix, 205 set_current, set_rnext, sndid, rcvid); 206 if (err) 207 return err; 208 209 if (test_get_ao_info(sk, &ao_info)) 210 test_error("getsockopt(TCP_AO_INFO) failed"); 211 if (set_current && ao_info.current_key != sndid) 212 return -ENOTRECOVERABLE; 213 if (set_rnext && ao_info.rnext != rcvid) 214 return -ENOTRECOVERABLE; 215 return 0; 216 } 217 218 static void try_add_current_rnext_key(char *tst_name, int sk, const char *key, 219 uint8_t keyflags, 220 union tcp_addr in_addr, uint8_t prefix, 221 bool set_current, bool set_rnext, 222 uint8_t sndid, uint8_t rcvid, fault_t inj) 223 { 224 int err; 225 226 err = __try_add_current_rnext_key(sk, key, keyflags, in_addr, prefix, 227 set_current, set_rnext, sndid, rcvid); 228 if (!err && !fault(CURRNEXT)) { 229 test_ok("%s", tst_name); 230 return; 231 } 232 if (err == -EINVAL && fault(CURRNEXT)) { 233 test_ok("%s", tst_name); 234 return; 235 } 236 test_fail("%s", tst_name); 237 } 238 239 static void check_closed_socket(void) 240 { 241 int sk; 242 243 sk = prepare_sk(&this_ip_dest, 200, 200); 244 try_delete_key("closed socket, delete a key", sk, 200, 200, 0, 0, -1, -1, 0); 245 try_delete_key("closed socket, delete all keys", sk, 100, 100, 0, 0, -1, -1, 0); 246 close(sk); 247 248 sk = prepare_sk(&this_ip_dest, 200, 200); 249 if (test_set_key(sk, 100, 200)) 250 test_error("failed to set current/rnext keys"); 251 try_delete_key("closed socket, delete current key", sk, 100, 100, 0, 0, -1, -1, FAULT_BUSY); 252 try_delete_key("closed socket, delete rnext key", sk, 200, 200, 0, 0, -1, -1, FAULT_BUSY); 253 close(sk); 254 255 sk = prepare_sk(&this_ip_dest, 200, 200); 256 if (test_add_key(sk, "Glory to heros!", this_ip_dest, 257 DEFAULT_TEST_PREFIX, 10, 11)) 258 test_error("test_add_key()"); 259 if (test_add_key(sk, "Glory to Ukraine!", this_ip_dest, 260 DEFAULT_TEST_PREFIX, 12, 13)) 261 test_error("test_add_key()"); 262 try_delete_key("closed socket, delete a key + set current/rnext", sk, 263 100, 100, 0, 0, 10, 13, 0); 264 try_delete_key("closed socket, force-delete current key", sk, 10, 11, 0, 0, 200, -1, 0); 265 try_delete_key("closed socket, force-delete rnext key", sk, 12, 13, 0, 0, -1, 200, 0); 266 try_delete_key("closed socket, delete current+rnext key", sk, 267 200, 200, 0, 0, -1, -1, FAULT_BUSY); 268 close(sk); 269 270 sk = prepare_sk(&this_ip_dest, 200, 200); 271 if (test_set_key(sk, 100, 200)) 272 test_error("failed to set current/rnext keys"); 273 try_add_current_rnext_key("closed socket, add + change current key", 274 sk, "Laaaa! Lalala-la-la-lalala...", 0, 275 this_ip_dest, DEFAULT_TEST_PREFIX, 276 true, false, 10, 20, 0); 277 try_add_current_rnext_key("closed socket, add + change rnext key", 278 sk, "Laaaa! Lalala-la-la-lalala...", 0, 279 this_ip_dest, DEFAULT_TEST_PREFIX, 280 false, true, 20, 10, 0); 281 close(sk); 282 283 if (!should_skip_test("closed socket, add + delete VRF-scoped key", 284 KCONFIG_NET_VRF)) { 285 sk = prepare_sk(&this_ip_dest, 200, 200); 286 if (test_add_key_vrf(sk, SECOND_PASSWORD, TCP_AO_KEYF_IFINDEX, 287 this_ip_dest, DEFAULT_TEST_PREFIX, 288 test_vrf_ifindex, 201, 201)) 289 test_error("test_add_key_vrf()"); 290 try_delete_key("closed socket, add + delete VRF-scoped key", sk, 201, 201, 291 test_vrf_ifindex, 0, -1, -1, 0); 292 close(sk); 293 } 294 } 295 296 static void assert_no_current_rnext(const char *tst_msg, int sk) 297 { 298 struct tcp_ao_info_opt ao_info = {}; 299 300 if (test_get_ao_info(sk, &ao_info)) 301 test_error("getsockopt(TCP_AO_INFO) failed"); 302 303 errno = 0; 304 if (ao_info.set_current || ao_info.set_rnext) { 305 test_xfail("%s: the socket has current/rnext keys: %d:%d", 306 tst_msg, 307 (ao_info.set_current) ? ao_info.current_key : -1, 308 (ao_info.set_rnext) ? ao_info.rnext : -1); 309 } else { 310 test_ok("%s: the socket has no current/rnext keys", tst_msg); 311 } 312 } 313 314 static void assert_no_tcp_repair(void) 315 { 316 struct tcp_ao_repair ao_img = {}; 317 socklen_t len = sizeof(ao_img); 318 int sk, err; 319 320 sk = prepare_sk(&this_ip_dest, 200, 200); 321 test_enable_repair(sk); 322 if (listen(sk, 10)) 323 test_error("listen()"); 324 errno = 0; 325 err = getsockopt(sk, SOL_TCP, TCP_AO_REPAIR, &ao_img, &len); 326 if (err && errno == EPERM) 327 test_ok("listen socket, getsockopt(TCP_AO_REPAIR) is restricted"); 328 else 329 test_fail("listen socket, getsockopt(TCP_AO_REPAIR) works"); 330 errno = 0; 331 err = setsockopt(sk, SOL_TCP, TCP_AO_REPAIR, &ao_img, sizeof(ao_img)); 332 if (err && errno == EPERM) 333 test_ok("listen socket, setsockopt(TCP_AO_REPAIR) is restricted"); 334 else 335 test_fail("listen socket, setsockopt(TCP_AO_REPAIR) works"); 336 close(sk); 337 } 338 339 static void check_listen_socket(void) 340 { 341 int sk, err; 342 343 sk = prepare_lsk(&this_ip_dest, 200, 200); 344 try_delete_key("listen socket, delete a key", sk, 200, 200, 0, 0, -1, -1, 0); 345 try_delete_key("listen socket, delete all keys", sk, 100, 100, 0, 0, -1, -1, 0); 346 close(sk); 347 348 sk = prepare_lsk(&this_ip_dest, 200, 200); 349 err = test_set_key(sk, 100, -1); 350 if (err == -EINVAL) 351 test_ok("listen socket, setting current key not allowed"); 352 else 353 test_fail("listen socket, set current key"); 354 err = test_set_key(sk, -1, 200); 355 if (err == -EINVAL) 356 test_ok("listen socket, setting rnext key not allowed"); 357 else 358 test_fail("listen socket, set rnext key"); 359 close(sk); 360 361 sk = prepare_sk(&this_ip_dest, 200, 200); 362 if (test_set_key(sk, 100, 200)) 363 test_error("failed to set current/rnext keys"); 364 if (listen(sk, 10)) 365 test_error("listen()"); 366 assert_no_current_rnext("listen() after current/rnext keys set", sk); 367 try_delete_key("listen socket, delete current key from before listen()", sk, 368 100, 100, 0, 0, -1, -1, FAULT_FIXME); 369 try_delete_key("listen socket, delete rnext key from before listen()", sk, 370 200, 200, 0, 0, -1, -1, FAULT_FIXME); 371 close(sk); 372 373 assert_no_tcp_repair(); 374 375 sk = prepare_lsk(&this_ip_dest, 200, 200); 376 if (test_add_key(sk, "Glory to heros!", this_ip_dest, 377 DEFAULT_TEST_PREFIX, 10, 11)) 378 test_error("test_add_key()"); 379 if (test_add_key(sk, "Glory to Ukraine!", this_ip_dest, 380 DEFAULT_TEST_PREFIX, 12, 13)) 381 test_error("test_add_key()"); 382 try_delete_key("listen socket, delete a key + set current/rnext", sk, 383 100, 100, 0, 0, 10, 13, FAULT_CURRNEXT); 384 try_delete_key("listen socket, force-delete current key", sk, 385 10, 11, 0, 0, 200, -1, FAULT_CURRNEXT); 386 try_delete_key("listen socket, force-delete rnext key", sk, 387 12, 13, 0, 0, -1, 200, FAULT_CURRNEXT); 388 try_delete_key("listen socket, delete a key", sk, 389 200, 200, 0, 0, -1, -1, 0); 390 close(sk); 391 392 sk = prepare_lsk(&this_ip_dest, 200, 200); 393 try_add_current_rnext_key("listen socket, add + change current key", 394 sk, "Laaaa! Lalala-la-la-lalala...", 0, 395 this_ip_dest, DEFAULT_TEST_PREFIX, 396 true, false, 10, 20, FAULT_CURRNEXT); 397 try_add_current_rnext_key("listen socket, add + change rnext key", 398 sk, "Laaaa! Lalala-la-la-lalala...", 0, 399 this_ip_dest, DEFAULT_TEST_PREFIX, 400 false, true, 20, 10, FAULT_CURRNEXT); 401 close(sk); 402 } 403 404 struct test_key { 405 char password[TCP_AO_MAXKEYLEN]; 406 const char *alg; 407 unsigned int len; 408 uint8_t client_keyid; 409 uint8_t server_keyid; 410 uint8_t maclen; 411 uint8_t matches_client : 1, 412 matches_server : 1, 413 matches_vrf : 1, 414 is_current : 1, 415 is_rnext : 1, 416 used_on_server_tx : 1, 417 used_on_client_tx : 1, 418 skip_counters_checks : 1; 419 }; 420 421 struct key_collection { 422 unsigned int nr_keys; 423 struct test_key *keys; 424 }; 425 426 static struct key_collection collection; 427 428 #define TEST_MAX_MACLEN 16 429 const char *test_algos[] = { "cmac(aes128)", "hmac(sha1)", "hmac(sha256)" }; 430 const unsigned int test_maclens[] = { 1, 4, 12, 16 }; 431 #define MACLEN_SHIFT 2 432 #define ALGOS_SHIFT 4 433 434 static unsigned int make_mask(unsigned int shift, unsigned int prev_shift) 435 { 436 unsigned int ret = BIT(shift) - 1; 437 438 return ret << prev_shift; 439 } 440 441 static void init_key_in_collection(unsigned int index, bool randomized) 442 { 443 struct test_key *key = &collection.keys[index]; 444 unsigned int algos_index; 445 446 /* Same for randomized and non-randomized test flows */ 447 key->client_keyid = index; 448 key->server_keyid = 127 + index; 449 key->matches_client = 1; 450 key->matches_server = 1; 451 key->matches_vrf = 1; 452 /* not really even random, but good enough for a test */ 453 key->len = rand() % (TCP_AO_MAXKEYLEN - TEST_TCP_AO_MINKEYLEN); 454 key->len += TEST_TCP_AO_MINKEYLEN; 455 randomize_buffer(key->password, key->len); 456 457 if (randomized) { 458 key->maclen = (rand() % TEST_MAX_MACLEN) + 1; 459 algos_index = rand(); 460 } else { 461 unsigned int shift = MACLEN_SHIFT; 462 463 key->maclen = test_maclens[index & make_mask(shift, 0)]; 464 algos_index = index & make_mask(ALGOS_SHIFT, shift); 465 } 466 key->alg = test_algos[algos_index % ARRAY_SIZE(test_algos)]; 467 } 468 469 static int init_default_key_collection(unsigned int nr_keys, bool randomized) 470 { 471 size_t key_sz = sizeof(collection.keys[0]); 472 473 if (!nr_keys) { 474 free(collection.keys); 475 collection.keys = NULL; 476 return 0; 477 } 478 479 /* 480 * All keys have uniq sndid/rcvid and sndid != rcvid in order to 481 * check for any bugs/issues for different keyids, visible to both 482 * peers. Keyid == 254 is unused. 483 */ 484 if (nr_keys > 127) 485 test_error("Test requires too many keys, correct the source"); 486 487 collection.keys = reallocarray(collection.keys, nr_keys, key_sz); 488 if (!collection.keys) 489 return -ENOMEM; 490 491 memset(collection.keys, 0, nr_keys * key_sz); 492 collection.nr_keys = nr_keys; 493 while (nr_keys--) 494 init_key_in_collection(nr_keys, randomized); 495 496 return 0; 497 } 498 499 static void test_key_error(const char *msg, struct test_key *key) 500 { 501 test_error("%s: key: { %s, %u:%u, %u, %u:%u:%u:%u:%u (%u)}", 502 msg, key->alg, key->client_keyid, key->server_keyid, 503 key->maclen, key->matches_client, key->matches_server, 504 key->matches_vrf, key->is_current, key->is_rnext, key->len); 505 } 506 507 static int test_add_key_cr(int sk, const char *pwd, unsigned int pwd_len, 508 union tcp_addr addr, uint8_t vrf, 509 uint8_t sndid, uint8_t rcvid, 510 uint8_t maclen, const char *alg, 511 bool set_current, bool set_rnext) 512 { 513 struct tcp_ao_add tmp = {}; 514 uint8_t keyflags = 0; 515 int err; 516 517 if (!alg) 518 alg = DEFAULT_TEST_ALGO; 519 520 if (vrf) 521 keyflags |= TCP_AO_KEYF_IFINDEX; 522 err = test_prepare_key(&tmp, alg, addr, set_current, set_rnext, 523 DEFAULT_TEST_PREFIX, vrf, sndid, rcvid, maclen, 524 keyflags, pwd_len, pwd); 525 if (err) 526 return err; 527 528 err = setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &tmp, sizeof(tmp)); 529 if (err < 0) 530 return -errno; 531 532 return test_verify_socket_key(sk, &tmp); 533 } 534 535 static void verify_current_rnext(const char *tst, int sk, 536 int current_keyid, int rnext_keyid) 537 { 538 struct tcp_ao_info_opt ao_info = {}; 539 540 if (test_get_ao_info(sk, &ao_info)) 541 test_error("getsockopt(TCP_AO_INFO) failed"); 542 543 errno = 0; 544 if (current_keyid >= 0) { 545 if (!ao_info.set_current) 546 test_fail("%s: the socket doesn't have current key", tst); 547 else if (ao_info.current_key != current_keyid) 548 test_fail("%s: current key is not the expected one %d != %u", 549 tst, current_keyid, ao_info.current_key); 550 else 551 test_ok("%s: current key %u as expected", 552 tst, ao_info.current_key); 553 } 554 if (rnext_keyid >= 0) { 555 if (!ao_info.set_rnext) 556 test_fail("%s: the socket doesn't have rnext key", tst); 557 else if (ao_info.rnext != rnext_keyid) 558 test_fail("%s: rnext key is not the expected one %d != %u", 559 tst, rnext_keyid, ao_info.rnext); 560 else 561 test_ok("%s: rnext key %u as expected", tst, ao_info.rnext); 562 } 563 } 564 565 566 static int key_collection_socket(bool server, unsigned int port) 567 { 568 unsigned int i; 569 int sk; 570 571 if (server) 572 sk = test_listen_socket(this_ip_addr, port, 1); 573 else 574 sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP); 575 if (sk < 0) 576 test_error("socket()"); 577 578 for (i = 0; i < collection.nr_keys; i++) { 579 struct test_key *key = &collection.keys[i]; 580 union tcp_addr *addr = &wrong_addr; 581 uint8_t sndid, rcvid, vrf; 582 bool set_current = false, set_rnext = false; 583 584 if (key->matches_vrf) 585 vrf = 0; 586 else 587 vrf = test_vrf_ifindex; 588 if (server) { 589 if (key->matches_client) 590 addr = &this_ip_dest; 591 sndid = key->server_keyid; 592 rcvid = key->client_keyid; 593 } else { 594 if (key->matches_server) 595 addr = &this_ip_dest; 596 sndid = key->client_keyid; 597 rcvid = key->server_keyid; 598 key->used_on_client_tx = set_current = key->is_current; 599 key->used_on_server_tx = set_rnext = key->is_rnext; 600 } 601 602 if (test_add_key_cr(sk, key->password, key->len, 603 *addr, vrf, sndid, rcvid, key->maclen, 604 key->alg, set_current, set_rnext)) 605 test_key_error("setsockopt(TCP_AO_ADD_KEY)", key); 606 #ifdef DEBUG 607 test_print("%s [%u/%u] key: { %s, %u:%u, %u, %u:%u:%u:%u (%u)}", 608 server ? "server" : "client", i, collection.nr_keys, 609 key->alg, rcvid, sndid, key->maclen, 610 key->matches_client, key->matches_server, 611 key->is_current, key->is_rnext, key->len); 612 #endif 613 } 614 return sk; 615 } 616 617 static void verify_counters(const char *tst_name, bool is_listen_sk, bool server, 618 struct tcp_counters *a, struct tcp_counters *b) 619 { 620 unsigned int i; 621 622 test_assert_counters_sk(tst_name, a, b, TEST_CNT_GOOD); 623 624 for (i = 0; i < collection.nr_keys; i++) { 625 struct test_key *key = &collection.keys[i]; 626 uint8_t sndid, rcvid; 627 bool rx_cnt_expected; 628 629 if (key->skip_counters_checks) 630 continue; 631 if (server) { 632 sndid = key->server_keyid; 633 rcvid = key->client_keyid; 634 rx_cnt_expected = key->used_on_client_tx; 635 } else { 636 sndid = key->client_keyid; 637 rcvid = key->server_keyid; 638 rx_cnt_expected = key->used_on_server_tx; 639 } 640 641 test_assert_counters_key(tst_name, &a->ao, &b->ao, 642 rx_cnt_expected ? TEST_CNT_KEY_GOOD : 0, 643 sndid, rcvid); 644 } 645 test_tcp_counters_free(a); 646 test_tcp_counters_free(b); 647 test_ok("%s: passed counters checks", tst_name); 648 } 649 650 static struct tcp_ao_getsockopt *lookup_key(struct tcp_ao_getsockopt *buf, 651 size_t len, int sndid, int rcvid) 652 { 653 size_t i; 654 655 for (i = 0; i < len; i++) { 656 if (sndid >= 0 && buf[i].sndid != sndid) 657 continue; 658 if (rcvid >= 0 && buf[i].rcvid != rcvid) 659 continue; 660 return &buf[i]; 661 } 662 return NULL; 663 } 664 665 static void verify_keys(const char *tst_name, int sk, 666 bool is_listen_sk, bool server) 667 { 668 socklen_t len = sizeof(struct tcp_ao_getsockopt); 669 struct tcp_ao_getsockopt *keys; 670 bool passed_test = true; 671 unsigned int i; 672 673 keys = calloc(collection.nr_keys, len); 674 if (!keys) 675 test_error("calloc()"); 676 677 keys->nkeys = collection.nr_keys; 678 keys->get_all = 1; 679 680 if (getsockopt(sk, IPPROTO_TCP, TCP_AO_GET_KEYS, keys, &len)) { 681 free(keys); 682 test_error("getsockopt(TCP_AO_GET_KEYS)"); 683 } 684 685 for (i = 0; i < collection.nr_keys; i++) { 686 struct test_key *key = &collection.keys[i]; 687 struct tcp_ao_getsockopt *dump_key; 688 bool is_kdf_aes_128_cmac = false; 689 bool is_cmac_aes = false; 690 uint8_t sndid, rcvid; 691 bool matches = false; 692 693 if (server) { 694 if (key->matches_client) 695 matches = true; 696 sndid = key->server_keyid; 697 rcvid = key->client_keyid; 698 } else { 699 if (key->matches_server) 700 matches = true; 701 sndid = key->client_keyid; 702 rcvid = key->server_keyid; 703 } 704 if (!key->matches_vrf) 705 matches = false; 706 /* no keys get removed on the original listener socket */ 707 if (is_listen_sk) 708 matches = true; 709 710 dump_key = lookup_key(keys, keys->nkeys, sndid, rcvid); 711 if (matches != !!dump_key) { 712 test_fail("%s: key %u:%u %s%s on the socket", 713 tst_name, sndid, rcvid, 714 key->matches_vrf ? "" : "[vrf] ", 715 matches ? "disappeared" : "yet present"); 716 passed_test = false; 717 goto out; 718 } 719 if (!dump_key) 720 continue; 721 722 if (!strcmp("cmac(aes128)", key->alg)) { 723 is_kdf_aes_128_cmac = (key->len != 16); 724 is_cmac_aes = true; 725 } 726 727 if (is_cmac_aes) { 728 if (strcmp(dump_key->alg_name, "cmac(aes)")) { 729 test_fail("%s: key %u:%u cmac(aes) has unexpected alg %s", 730 tst_name, sndid, rcvid, 731 dump_key->alg_name); 732 passed_test = false; 733 continue; 734 } 735 } else if (strcmp(dump_key->alg_name, key->alg)) { 736 test_fail("%s: key %u:%u has unexpected alg %s != %s", 737 tst_name, sndid, rcvid, 738 dump_key->alg_name, key->alg); 739 passed_test = false; 740 continue; 741 } 742 if (is_kdf_aes_128_cmac) { 743 if (dump_key->keylen != 16) { 744 test_fail("%s: key %u:%u cmac(aes128) has unexpected len %u", 745 tst_name, sndid, rcvid, 746 dump_key->keylen); 747 continue; 748 } 749 } else if (dump_key->keylen != key->len) { 750 test_fail("%s: key %u:%u changed password len %u != %u", 751 tst_name, sndid, rcvid, 752 dump_key->keylen, key->len); 753 passed_test = false; 754 continue; 755 } 756 if (!is_kdf_aes_128_cmac && 757 memcmp(dump_key->key, key->password, key->len)) { 758 test_fail("%s: key %u:%u has different password", 759 tst_name, sndid, rcvid); 760 passed_test = false; 761 continue; 762 } 763 if (dump_key->maclen != key->maclen) { 764 test_fail("%s: key %u:%u changed maclen %u != %u", 765 tst_name, sndid, rcvid, 766 dump_key->maclen, key->maclen); 767 passed_test = false; 768 continue; 769 } 770 } 771 772 if (passed_test) 773 test_ok("%s: The socket keys are consistent with the expectations", 774 tst_name); 775 out: 776 free(keys); 777 } 778 779 static int start_server(const char *tst_name, unsigned int port, size_t quota, 780 struct tcp_counters *begin, 781 unsigned int current_index, unsigned int rnext_index) 782 { 783 struct tcp_counters lsk_c1, lsk_c2; 784 ssize_t bytes; 785 int sk, lsk; 786 787 synchronize_threads(); /* 1: key collection initialized */ 788 lsk = key_collection_socket(true, port); 789 if (test_get_tcp_counters(lsk, &lsk_c1)) 790 test_error("test_get_tcp_counters()"); 791 synchronize_threads(); /* 2: MKTs added => connect() */ 792 if (test_wait_fd(lsk, TEST_TIMEOUT_SEC, 0)) 793 test_error("test_wait_fd()"); 794 795 sk = accept(lsk, NULL, NULL); 796 if (sk < 0) 797 test_error("accept()"); 798 if (test_get_tcp_counters(sk, begin)) 799 test_error("test_get_tcp_counters()"); 800 801 synchronize_threads(); /* 3: accepted => send data */ 802 if (test_get_tcp_counters(lsk, &lsk_c2)) 803 test_error("test_get_tcp_counters()"); 804 verify_keys(tst_name, lsk, true, true); 805 close(lsk); 806 807 bytes = test_server_run(sk, quota, TEST_TIMEOUT_SEC); 808 if (bytes != quota) 809 test_fail("%s: server served: %zd", tst_name, bytes); 810 else 811 test_ok("%s: server alive", tst_name); 812 813 verify_counters(tst_name, true, true, &lsk_c1, &lsk_c2); 814 815 return sk; 816 } 817 818 static void end_server(const char *tst_name, int sk, 819 struct tcp_counters *begin) 820 { 821 struct tcp_counters end; 822 823 if (test_get_tcp_counters(sk, &end)) 824 test_error("test_get_tcp_counters()"); 825 verify_keys(tst_name, sk, false, true); 826 827 synchronize_threads(); /* 4: verified => closed */ 828 close(sk); 829 830 verify_counters(tst_name, false, true, begin, &end); 831 synchronize_threads(); /* 5: counters */ 832 } 833 834 static void try_server_run(const char *tst_name, unsigned int port, size_t quota, 835 unsigned int current_index, unsigned int rnext_index) 836 { 837 struct tcp_counters tmp; 838 int sk; 839 840 sk = start_server(tst_name, port, quota, &tmp, 841 current_index, rnext_index); 842 end_server(tst_name, sk, &tmp); 843 } 844 845 static void server_rotations(const char *tst_name, unsigned int port, 846 size_t quota, unsigned int rotations, 847 unsigned int current_index, unsigned int rnext_index) 848 { 849 struct tcp_counters tmp; 850 unsigned int i; 851 int sk; 852 853 sk = start_server(tst_name, port, quota, &tmp, 854 current_index, rnext_index); 855 856 for (i = current_index + 1; rotations > 0; i++, rotations--) { 857 ssize_t bytes; 858 859 if (i >= collection.nr_keys) 860 i = 0; 861 bytes = test_server_run(sk, quota, TEST_TIMEOUT_SEC); 862 if (bytes != quota) { 863 test_fail("%s: server served: %zd", tst_name, bytes); 864 return; 865 } 866 verify_current_rnext(tst_name, sk, 867 collection.keys[i].server_keyid, -1); 868 synchronize_threads(); /* verify current/rnext */ 869 } 870 end_server(tst_name, sk, &tmp); 871 } 872 873 static int run_client(const char *tst_name, unsigned int port, 874 unsigned int nr_keys, int current_index, int rnext_index, 875 struct tcp_counters *before, 876 const size_t msg_sz, const size_t msg_nr) 877 { 878 int sk; 879 880 synchronize_threads(); /* 1: key collection initialized */ 881 sk = key_collection_socket(false, port); 882 883 if (current_index >= 0 || rnext_index >= 0) { 884 int sndid = -1, rcvid = -1; 885 886 if (current_index >= 0) 887 sndid = collection.keys[current_index].client_keyid; 888 if (rnext_index >= 0) 889 rcvid = collection.keys[rnext_index].server_keyid; 890 if (test_set_key(sk, sndid, rcvid)) 891 test_error("failed to set current/rnext keys"); 892 } 893 if (before && test_get_tcp_counters(sk, before)) 894 test_error("test_get_tcp_counters()"); 895 896 synchronize_threads(); /* 2: MKTs added => connect() */ 897 if (test_connect_socket(sk, this_ip_dest, port++) <= 0) 898 test_error("failed to connect()"); 899 if (current_index < 0) 900 current_index = nr_keys - 1; 901 if (rnext_index < 0) 902 rnext_index = nr_keys - 1; 903 collection.keys[current_index].used_on_client_tx = 1; 904 collection.keys[rnext_index].used_on_server_tx = 1; 905 906 synchronize_threads(); /* 3: accepted => send data */ 907 if (test_client_verify(sk, msg_sz, msg_nr)) { 908 test_fail("verify failed"); 909 close(sk); 910 if (before) 911 test_tcp_counters_free(before); 912 return -1; 913 } 914 915 return sk; 916 } 917 918 static int start_client(const char *tst_name, unsigned int port, 919 unsigned int nr_keys, int current_index, int rnext_index, 920 struct tcp_counters *before, 921 const size_t msg_sz, const size_t msg_nr) 922 { 923 if (init_default_key_collection(nr_keys, true)) 924 test_error("Failed to init the key collection"); 925 926 return run_client(tst_name, port, nr_keys, current_index, 927 rnext_index, before, msg_sz, msg_nr); 928 } 929 930 static void end_client(const char *tst_name, int sk, unsigned int nr_keys, 931 int current_index, int rnext_index, 932 struct tcp_counters *start) 933 { 934 struct tcp_counters end; 935 936 /* Some application may become dependent on this kernel choice */ 937 if (current_index < 0) 938 current_index = nr_keys - 1; 939 if (rnext_index < 0) 940 rnext_index = nr_keys - 1; 941 verify_current_rnext(tst_name, sk, 942 collection.keys[current_index].client_keyid, 943 collection.keys[rnext_index].server_keyid); 944 if (start && test_get_tcp_counters(sk, &end)) 945 test_error("test_get_tcp_counters()"); 946 verify_keys(tst_name, sk, false, false); 947 synchronize_threads(); /* 4: verify => closed */ 948 close(sk); 949 if (start) 950 verify_counters(tst_name, false, false, start, &end); 951 synchronize_threads(); /* 5: counters */ 952 } 953 954 static void try_unmatched_keys(int sk, int *rnext_index, unsigned int port) 955 { 956 struct test_key *key; 957 unsigned int i = 0; 958 int err; 959 960 do { 961 key = &collection.keys[i]; 962 if (!key->matches_server) 963 break; 964 } while (++i < collection.nr_keys); 965 if (key->matches_server) 966 test_error("all keys on client match the server"); 967 968 err = test_add_key_cr(sk, key->password, key->len, wrong_addr, 969 0, key->client_keyid, key->server_keyid, 970 key->maclen, key->alg, 0, 0); 971 if (!err) { 972 test_fail("Added a key with non-matching ip-address for established sk"); 973 return; 974 } 975 if (err == -EINVAL) 976 test_ok("Can't add a key with non-matching ip-address for established sk"); 977 else 978 test_error("Failed to add a key"); 979 980 err = test_add_key_cr(sk, key->password, key->len, this_ip_dest, 981 test_vrf_ifindex, 982 key->client_keyid, key->server_keyid, 983 key->maclen, key->alg, 0, 0); 984 if (!err) { 985 test_fail("Added a key with non-matching VRF for established sk"); 986 return; 987 } 988 if (err == -EINVAL) 989 test_ok("Can't add a key with non-matching VRF for established sk"); 990 else 991 test_error("Failed to add a key"); 992 993 for (i = 0; i < collection.nr_keys; i++) { 994 key = &collection.keys[i]; 995 if (!key->matches_client) 996 break; 997 } 998 if (key->matches_client) 999 test_error("all keys on server match the client"); 1000 if (test_set_key(sk, -1, key->server_keyid)) 1001 test_error("Can't change the current key"); 1002 trace_ao_event_expect(TCP_AO_RNEXT_REQUEST, this_ip_addr, this_ip_dest, 1003 -1, port, 0, -1, -1, -1, -1, -1, 1004 -1, key->server_keyid, -1); 1005 if (test_client_verify(sk, msg_len, nr_packets)) 1006 test_fail("verify failed"); 1007 *rnext_index = i; 1008 } 1009 1010 static int client_non_matching(const char *tst_name, unsigned int port, 1011 unsigned int nr_keys, 1012 int current_index, int rnext_index, 1013 const size_t msg_sz, const size_t msg_nr) 1014 { 1015 unsigned int i; 1016 1017 if (init_default_key_collection(nr_keys, true)) 1018 test_error("Failed to init the key collection"); 1019 1020 for (i = 0; i < nr_keys; i++) { 1021 /* key (0, 0) matches */ 1022 collection.keys[i].matches_client = !!((i + 3) % 4); 1023 collection.keys[i].matches_server = !!((i + 2) % 4); 1024 if (kernel_config_has(KCONFIG_NET_VRF)) 1025 collection.keys[i].matches_vrf = !!((i + 1) % 4); 1026 } 1027 1028 return run_client(tst_name, port, nr_keys, current_index, 1029 rnext_index, NULL, msg_sz, msg_nr); 1030 } 1031 1032 static void check_current_back(const char *tst_name, unsigned int port, 1033 unsigned int nr_keys, 1034 unsigned int current_index, unsigned int rnext_index, 1035 unsigned int rotate_to_index) 1036 { 1037 struct tcp_counters tmp; 1038 int sk; 1039 1040 sk = start_client(tst_name, port, nr_keys, current_index, rnext_index, 1041 &tmp, msg_len, nr_packets); 1042 if (sk < 0) 1043 return; 1044 if (test_set_key(sk, collection.keys[rotate_to_index].client_keyid, -1)) 1045 test_error("Can't change the current key"); 1046 trace_ao_event_expect(TCP_AO_RNEXT_REQUEST, this_ip_dest, this_ip_addr, 1047 port, -1, 0, -1, -1, -1, -1, -1, 1048 collection.keys[rotate_to_index].client_keyid, 1049 collection.keys[current_index].client_keyid, -1); 1050 if (test_client_verify(sk, msg_len, nr_packets)) 1051 test_fail("verify failed"); 1052 /* There is a race here: between setting the current_key with 1053 * setsockopt(TCP_AO_INFO) and starting to send some data - there 1054 * might have been a segment received with the desired 1055 * RNext_key set. In turn that would mean that the first outgoing 1056 * segment will have the desired current_key (flipped back). 1057 * Which is what the user/test wants. As it's racy, skip checking 1058 * the counters, yet check what are the resulting current/rnext 1059 * keys on both sides. 1060 */ 1061 collection.keys[rotate_to_index].skip_counters_checks = 1; 1062 1063 end_client(tst_name, sk, nr_keys, current_index, rnext_index, &tmp); 1064 } 1065 1066 static void roll_over_keys(const char *tst_name, unsigned int port, 1067 unsigned int nr_keys, unsigned int rotations, 1068 unsigned int current_index, unsigned int rnext_index) 1069 { 1070 struct tcp_counters tmp; 1071 unsigned int i; 1072 int sk; 1073 1074 sk = start_client(tst_name, port, nr_keys, current_index, rnext_index, 1075 &tmp, msg_len, nr_packets); 1076 if (sk < 0) 1077 return; 1078 for (i = rnext_index + 1; rotations > 0; i++, rotations--) { 1079 if (i >= collection.nr_keys) 1080 i = 0; 1081 trace_ao_event_expect(TCP_AO_RNEXT_REQUEST, 1082 this_ip_addr, this_ip_dest, 1083 -1, port, 0, -1, -1, -1, -1, -1, 1084 i == 0 ? -1 : collection.keys[i - 1].server_keyid, 1085 collection.keys[i].server_keyid, -1); 1086 if (test_set_key(sk, -1, collection.keys[i].server_keyid)) 1087 test_error("Can't change the Rnext key"); 1088 if (test_client_verify(sk, msg_len, nr_packets)) { 1089 test_fail("verify failed"); 1090 close(sk); 1091 test_tcp_counters_free(&tmp); 1092 return; 1093 } 1094 verify_current_rnext(tst_name, sk, -1, 1095 collection.keys[i].server_keyid); 1096 collection.keys[i].used_on_server_tx = 1; 1097 synchronize_threads(); /* verify current/rnext */ 1098 } 1099 end_client(tst_name, sk, nr_keys, current_index, rnext_index, &tmp); 1100 } 1101 1102 static void try_client_run(const char *tst_name, unsigned int port, 1103 unsigned int nr_keys, int current_index, int rnext_index) 1104 { 1105 struct tcp_counters tmp; 1106 int sk; 1107 1108 sk = start_client(tst_name, port, nr_keys, current_index, rnext_index, 1109 &tmp, msg_len, nr_packets); 1110 if (sk < 0) 1111 return; 1112 end_client(tst_name, sk, nr_keys, current_index, rnext_index, &tmp); 1113 } 1114 1115 static void try_client_match(const char *tst_name, unsigned int port, 1116 unsigned int nr_keys, 1117 int current_index, int rnext_index) 1118 { 1119 int sk; 1120 1121 sk = client_non_matching(tst_name, port, nr_keys, current_index, 1122 rnext_index, msg_len, nr_packets); 1123 if (sk < 0) 1124 return; 1125 try_unmatched_keys(sk, &rnext_index, port); 1126 end_client(tst_name, sk, nr_keys, current_index, rnext_index, NULL); 1127 } 1128 1129 static void *server_fn(void *arg) 1130 { 1131 unsigned int port = test_server_port; 1132 1133 setup_vrfs(); 1134 try_server_run("server: Check current/rnext keys unset before connect()", 1135 port++, quota, 19, 19); 1136 try_server_run("server: Check current/rnext keys set before connect()", 1137 port++, quota, 10, 10); 1138 try_server_run("server: Check current != rnext keys set before connect()", 1139 port++, quota, 5, 10); 1140 try_server_run("server: Check current flapping back on peer's RnextKey request", 1141 port++, quota * 2, 5, 10); 1142 server_rotations("server: Rotate over all different keys", port++, 1143 quota, 20, 0, 0); 1144 try_server_run("server: Check accept() => established key matching", 1145 port++, quota * 2, 0, 0); 1146 1147 synchronize_threads(); /* don't race to exit: client exits */ 1148 return NULL; 1149 } 1150 1151 static void check_established_socket(void) 1152 { 1153 unsigned int port = test_server_port; 1154 1155 try_client_run("client: Check current/rnext keys unset before connect()", 1156 port++, 20, -1, -1); 1157 try_client_run("client: Check current/rnext keys set before connect()", 1158 port++, 20, 10, 10); 1159 try_client_run("client: Check current != rnext keys set before connect()", 1160 port++, 20, 10, 5); 1161 check_current_back("client: Check current flapping back on peer's RnextKey request", 1162 port++, 20, 10, 5, 2); 1163 roll_over_keys("client: Rotate over all different keys", port++, 1164 20, 20, 0, 0); 1165 try_client_match("client: Check connect() => established key matching", 1166 port++, 20, 0, 0); 1167 } 1168 1169 static void *client_fn(void *arg) 1170 { 1171 if (inet_pton(TEST_FAMILY, TEST_WRONG_IP, &wrong_addr) != 1) 1172 test_error("Can't convert ip address %s", TEST_WRONG_IP); 1173 setup_vrfs(); 1174 check_closed_socket(); 1175 check_listen_socket(); 1176 check_established_socket(); 1177 return NULL; 1178 } 1179 1180 int main(int argc, char *argv[]) 1181 { 1182 test_init(122, server_fn, client_fn); 1183 return 0; 1184 } 1185