1 /* $NetBSD: packetProcessing.c,v 1.5 2024/08/18 20:47:26 christos Exp $ */ 2 3 #include "config.h" 4 5 #include "sntptest.h" 6 #include "networking.h" 7 #include "ntp_stdlib.h" 8 #include "unity.h" 9 10 #define CMAC "AES128CMAC" 11 #define CMAC_LENGTH 16 12 13 14 /* Hacks into the key database. */ 15 extern struct key* key_ptr; 16 extern int key_cnt; 17 18 19 void PrepareAuthenticationTest(int key_id,int key_len,const char* type,const void* key_seq); 20 void setUp(void); 21 void tearDown(void); 22 void test_TooShortLength(void); 23 void test_LengthNotMultipleOfFour(void); 24 void test_TooShortExtensionFieldLength(void); 25 void test_UnauthenticatedPacketReject(void); 26 void test_CryptoNAKPacketReject(void); 27 void test_AuthenticatedPacketInvalid(void); 28 void test_AuthenticatedPacketUnknownKey(void); 29 void test_ServerVersionTooOld(void); 30 void test_ServerVersionTooNew(void); 31 void test_NonWantedMode(void); 32 void test_KoDRate(void); 33 void test_KoDDeny(void); 34 void test_RejectUnsyncedServer(void); 35 void test_RejectWrongResponseServerMode(void); 36 void test_AcceptNoSentPacketBroadcastMode(void); 37 void test_CorrectUnauthenticatedPacket(void); 38 void test_CorrectAuthenticatedPacketMD5(void); 39 void test_CorrectAuthenticatedPacketSHAKE128(void); 40 void test_CorrectAuthenticatedPacketSHA1(void); 41 void test_CorrectAuthenticatedPacketCMAC(void); 42 43 /* [Bug 2998] There are some issues whith the definition of 'struct pkt' 44 * when AUTOKEY is undefined -- the formal struct is too small to hold 45 * all the extension fields that are going to be tested. We have to make 46 * sure we have the extra bytes, or the test yields undefined results due 47 * to buffer overrun. 48 */ 49 #ifndef AUTOKEY 50 # define EXTRA_BUFSIZE 256 51 #else 52 # define EXTRA_BUFSIZE 0 53 #endif 54 55 union tpkt { 56 struct pkt p; 57 u_char b[sizeof(struct pkt) + EXTRA_BUFSIZE]; 58 }; 59 60 static union tpkt testpkt; 61 static union tpkt testspkt; 62 static sockaddr_u testsock; 63 bool restoreKeyDb; 64 65 66 void 67 PrepareAuthenticationTest( 68 int key_id, 69 int key_len, 70 const char * type, 71 const void * key_seq 72 ) 73 { 74 char str[25]; 75 76 snprintf(str, sizeof(str), "%d", key_id); 77 ActivateOption("-a", str); 78 79 key_cnt = 1; 80 if (NULL == key_ptr) { 81 key_ptr = emalloc(sizeof(*key_ptr)); 82 } 83 key_ptr->next = NULL; 84 key_ptr->key_id = key_id; 85 key_ptr->key_len = key_len; 86 strncpy(key_ptr->typen, type, sizeof(key_ptr->typen)); 87 88 TEST_ASSERT_TRUE(key_len < sizeof(key_ptr->key_seq)); 89 90 memcpy(key_ptr->key_seq, key_seq, 91 min(key_len, sizeof(key_ptr->key_seq))); 92 restoreKeyDb = true; 93 } 94 95 96 void 97 setUp(void) 98 { 99 100 sntptest(); 101 restoreKeyDb = false; 102 103 /* Initialize the test packet and socket, 104 * so they contain at least some valid data. 105 */ 106 testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION, 107 MODE_SERVER); 108 testpkt.p.stratum = STRATUM_REFCLOCK; 109 memcpy(&testpkt.p.refid, "GPS\0", 4); 110 111 /* Set the origin timestamp of the received packet to the 112 * same value as the transmit timestamp of the sent packet. 113 */ 114 l_fp tmp; 115 tmp.l_ui = 1000UL; 116 tmp.l_uf = 0UL; 117 118 HTONL_FP(&tmp, &testpkt.p.org); 119 HTONL_FP(&tmp, &testspkt.p.xmt); 120 } 121 122 123 void 124 tearDown(void) 125 { 126 if (restoreKeyDb) { 127 key_cnt = 0; 128 free(key_ptr); 129 key_ptr = NULL; 130 } 131 132 sntptest_destroy(); /* only on the final test!! if counter == 0 etc... */ 133 } 134 135 136 void 137 test_TooShortLength(void) 138 { 139 TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 140 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1, 141 MODE_SERVER, &testspkt.p, "UnitTest")); 142 TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 143 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC - 1, 144 MODE_BROADCAST, &testspkt.p, "UnitTest")); 145 } 146 147 148 void 149 test_LengthNotMultipleOfFour(void) 150 { 151 TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 152 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 6, 153 MODE_SERVER, &testspkt.p, "UnitTest")); 154 TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 155 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC + 3, 156 MODE_BROADCAST, &testspkt.p, "UnitTest")); 157 } 158 159 160 void 161 test_TooShortExtensionFieldLength(void) 162 { 163 /* [Bug 2998] We have to get around the formal specification of 164 * the extension field if AUTOKEY is undefined. (At least CLANG 165 * issues a warning in this case. It's just a warning, but 166 * still... 167 */ 168 uint32_t * pe = testpkt.p.exten + 7; 169 170 /* The lower 16-bits are the length of the extension field. 171 * This lengths must be multiples of 4 bytes, which gives 172 * a minimum of 4 byte extension field length. 173 */ 174 *pe = htonl(3); /* 3 bytes is too short. */ 175 176 /* We send in a pkt_len of header size + 4 byte extension 177 * header + 24 byte MAC, this prevents the length error to 178 * be caught at an earlier stage 179 */ 180 int pkt_len = LEN_PKT_NOMAC + 4 + 24; 181 182 TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 183 process_pkt(&testpkt.p, &testsock, pkt_len, 184 MODE_SERVER, &testspkt.p, "UnitTest")); 185 } 186 187 188 void 189 test_UnauthenticatedPacketReject(void) 190 { 191 /* Activate authentication option */ 192 ActivateOption("-a", "123"); 193 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 194 195 int pkt_len = LEN_PKT_NOMAC; 196 197 /* We demand authentication, but no MAC header is present. */ 198 TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL, 199 process_pkt(&testpkt.p, &testsock, pkt_len, 200 MODE_SERVER, &testspkt.p, "UnitTest")); 201 } 202 203 204 void 205 test_CryptoNAKPacketReject(void) 206 { 207 /* Activate authentication option */ 208 ActivateOption("-a", "123"); 209 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 210 211 int pkt_len = LEN_PKT_NOMAC + 4; /* + 4 byte MAC = Crypto-NAK */ 212 213 TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL, 214 process_pkt(&testpkt.p, &testsock, pkt_len, 215 MODE_SERVER, &testspkt.p, "UnitTest")); 216 } 217 218 219 void 220 test_AuthenticatedPacketInvalid(void) 221 { 222 #ifdef OPENSSL 223 size_t pkt_len = LEN_PKT_NOMAC; 224 size_t mac_len; 225 226 /* Activate authentication option */ 227 PrepareAuthenticationTest(50, 9, "SHAKE128", "123456789"); 228 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 229 230 /* Prepare the packet. */ 231 testpkt.p.exten[0] = htonl(50); 232 mac_len = make_mac(&testpkt.p, pkt_len, key_ptr, 233 &testpkt.p.exten[1], MAX_MDG_LEN); 234 235 pkt_len += KEY_MAC_LEN + mac_len; 236 237 /* Now, alter the MAC so it becomes invalid. */ 238 testpkt.p.exten[1] += 1; 239 240 TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL, 241 process_pkt(&testpkt.p, &testsock, pkt_len, 242 MODE_SERVER, &testspkt.p, "UnitTest")); 243 244 #else 245 246 TEST_IGNORE_MESSAGE("OpenSSL not enabled, skipping..."); 247 248 #endif 249 } 250 251 252 void 253 test_AuthenticatedPacketUnknownKey(void) 254 { 255 #ifdef OPENSSL 256 size_t pkt_len = LEN_PKT_NOMAC; 257 size_t mac_len; 258 259 /* Activate authentication option */ 260 PrepareAuthenticationTest(30, 9, "SHAKE128", "123456789"); 261 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 262 263 /* Prepare the packet. Note that the Key-ID expected is 30, but 264 * the packet has a key id of 50. 265 */ 266 testpkt.p.exten[0] = htonl(50); 267 mac_len = make_mac(&testpkt.p, pkt_len, key_ptr, 268 &testpkt.p.exten[1], MAX_MDG_LEN); 269 pkt_len += KEY_MAC_LEN + mac_len; 270 271 TEST_ASSERT_EQUAL(SERVER_AUTH_FAIL, 272 process_pkt(&testpkt.p, &testsock, pkt_len, 273 MODE_SERVER, &testspkt.p, "UnitTest")); 274 275 #else 276 277 TEST_IGNORE_MESSAGE("OpenSSL not enabled, skipping..."); 278 279 #endif 280 } 281 282 283 void 284 test_ServerVersionTooOld(void) 285 { 286 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 287 288 testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, 289 NTP_OLDVERSION - 1, 290 MODE_CLIENT); 291 TEST_ASSERT_TRUE(PKT_VERSION(testpkt.p.li_vn_mode) < NTP_OLDVERSION); 292 293 int pkt_len = LEN_PKT_NOMAC; 294 295 TEST_ASSERT_EQUAL(SERVER_UNUSEABLE, 296 process_pkt(&testpkt.p, &testsock, pkt_len, 297 MODE_SERVER, &testspkt.p, "UnitTest")); 298 } 299 300 301 void 302 test_ServerVersionTooNew(void) 303 { 304 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 305 306 testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, 307 NTP_VERSION + 1, 308 MODE_CLIENT); 309 TEST_ASSERT_TRUE(PKT_VERSION(testpkt.p.li_vn_mode) > NTP_VERSION); 310 311 int pkt_len = LEN_PKT_NOMAC; 312 313 TEST_ASSERT_EQUAL(SERVER_UNUSEABLE, 314 process_pkt(&testpkt.p, &testsock, pkt_len, 315 MODE_SERVER, &testspkt.p, "UnitTest")); 316 } 317 318 319 void 320 test_NonWantedMode(void) 321 { 322 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 323 324 testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, 325 NTP_VERSION, 326 MODE_CLIENT); 327 328 /* The packet has a mode of MODE_CLIENT, but process_pkt expects 329 * MODE_SERVER 330 */ 331 TEST_ASSERT_EQUAL(SERVER_UNUSEABLE, 332 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 333 MODE_SERVER, &testspkt.p, "UnitTest")); 334 } 335 336 337 /* Tests bug 1597 */ 338 void 339 test_KoDRate(void) 340 { 341 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 342 343 testpkt.p.stratum = STRATUM_PKT_UNSPEC; 344 memcpy(&testpkt.p.refid, "RATE", 4); 345 346 TEST_ASSERT_EQUAL(KOD_RATE, 347 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 348 MODE_SERVER, &testspkt.p, "UnitTest")); 349 } 350 351 352 void 353 test_KoDDeny(void) 354 { 355 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 356 357 testpkt.p.stratum = STRATUM_PKT_UNSPEC; 358 memcpy(&testpkt.p.refid, "DENY", 4); 359 360 TEST_ASSERT_EQUAL(KOD_DEMOBILIZE, 361 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 362 MODE_SERVER, &testspkt.p, "UnitTest")); 363 } 364 365 366 void 367 test_RejectUnsyncedServer(void) 368 { 369 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 370 371 testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC, 372 NTP_VERSION, 373 MODE_SERVER); 374 375 TEST_ASSERT_EQUAL(SERVER_UNUSEABLE, 376 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 377 MODE_SERVER, &testspkt.p, "UnitTest")); 378 } 379 380 381 void 382 test_RejectWrongResponseServerMode(void) 383 { 384 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 385 386 l_fp tmp; 387 tmp.l_ui = 1000UL; 388 tmp.l_uf = 0UL; 389 HTONL_FP(&tmp, &testpkt.p.org); 390 391 tmp.l_ui = 2000UL; 392 tmp.l_uf = 0UL; 393 HTONL_FP(&tmp, &testspkt.p.xmt); 394 395 TEST_ASSERT_EQUAL(PACKET_UNUSEABLE, 396 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 397 MODE_SERVER, &testspkt.p, "UnitTest")); 398 } 399 400 401 void 402 test_AcceptNoSentPacketBroadcastMode(void) 403 { 404 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 405 406 testpkt.p.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, 407 NTP_VERSION, 408 MODE_BROADCAST); 409 410 TEST_ASSERT_EQUAL(LEN_PKT_NOMAC, 411 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 412 MODE_BROADCAST, NULL, "UnitTest")); 413 } 414 415 416 void 417 test_CorrectUnauthenticatedPacket(void) 418 { 419 TEST_ASSERT_FALSE(ENABLED_OPT(AUTHENTICATION)); 420 421 TEST_ASSERT_EQUAL(LEN_PKT_NOMAC, 422 process_pkt(&testpkt.p, &testsock, LEN_PKT_NOMAC, 423 MODE_SERVER, &testspkt.p, "UnitTest")); 424 } 425 426 427 void 428 test_CorrectAuthenticatedPacketMD5(void) 429 { 430 #ifdef OPENSSL 431 432 keyid_t k_id = 10; 433 int pkt_len = LEN_PKT_NOMAC; 434 int mac_len; 435 436 PrepareAuthenticationTest(k_id, 15, "MD5", "123456789abcdef"); 437 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 438 439 /* Prepare the packet. */ 440 testpkt.p.exten[0] = htonl(k_id); 441 mac_len = make_mac(&testpkt.p, pkt_len, key_ptr, 442 &testpkt.p.exten[1], MAX_MDG_LEN); 443 444 /* TODO: Should not expect failure if non-FIPS OpenSSL */ 445 TEST_EXPECT_FAIL_MESSAGE("FIPS OpenSSL bars MD5"); 446 447 pkt_len += KEY_MAC_LEN + mac_len; 448 449 TEST_ASSERT_EQUAL(pkt_len, 450 process_pkt(&testpkt.p, &testsock, pkt_len, 451 MODE_SERVER, &testspkt.p, "UnitTest")); 452 453 #else 454 455 TEST_IGNORE_MESSAGE("OpenSSL not enabled, skipping..."); 456 457 #endif 458 } 459 460 461 void 462 test_CorrectAuthenticatedPacketSHAKE128(void) 463 { 464 #ifdef OPENSSL 465 466 keyid_t k_id = 10; 467 int pkt_len = LEN_PKT_NOMAC; 468 int mac_len; 469 470 PrepareAuthenticationTest(k_id, 15, "SHAKE128", "123456789abcdef"); 471 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 472 473 /* Prepare the packet. */ 474 testpkt.p.exten[0] = htonl(k_id); 475 mac_len = make_mac(&testpkt.p, pkt_len, key_ptr, &testpkt.p.exten[1], 476 SHAKE128_LENGTH); 477 478 pkt_len += KEY_MAC_LEN + mac_len; 479 480 TEST_ASSERT_EQUAL(pkt_len, 481 process_pkt(&testpkt.p, &testsock, pkt_len, 482 MODE_SERVER, &testspkt.p, "UnitTest")); 483 484 #else 485 486 TEST_IGNORE_MESSAGE("OpenSSL not enabled, skipping..."); 487 488 #endif 489 } 490 491 492 void 493 test_CorrectAuthenticatedPacketSHA1(void) 494 { 495 #ifdef OPENSSL 496 497 keyid_t k_id = 20; 498 int pkt_len = LEN_PKT_NOMAC; 499 int mac_len; 500 501 PrepareAuthenticationTest(k_id, 15, "SHA1", "abcdefghijklmno"); 502 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 503 504 /* Prepare the packet. */ 505 testpkt.p.exten[0] = htonl(k_id); 506 mac_len = make_mac(&testpkt.p, pkt_len, key_ptr, &testpkt.p.exten[1], 507 SHA1_LENGTH); 508 509 pkt_len += KEY_MAC_LEN + mac_len; 510 511 TEST_ASSERT_EQUAL(pkt_len, 512 process_pkt(&testpkt.p, &testsock, pkt_len, 513 MODE_SERVER, &testspkt.p, "UnitTest")); 514 515 #else 516 517 TEST_IGNORE_MESSAGE("OpenSSL not enabled, skipping..."); 518 519 #endif 520 } 521 522 523 void 524 test_CorrectAuthenticatedPacketCMAC(void) 525 { 526 #if defined(OPENSSL) && defined(ENABLE_CMAC) 527 528 PrepareAuthenticationTest(30, CMAC_LENGTH, CMAC, "abcdefghijklmnop"); 529 TEST_ASSERT_TRUE(ENABLED_OPT(AUTHENTICATION)); 530 531 int pkt_len = LEN_PKT_NOMAC; 532 533 /* Prepare the packet. */ 534 testpkt.p.exten[0] = htonl(30); 535 int mac_len = make_mac(&testpkt.p, pkt_len, key_ptr, 536 &testpkt.p.exten[1], MAX_MAC_LEN); 537 538 pkt_len += 4 + mac_len; 539 540 TEST_ASSERT_EQUAL(pkt_len, 541 process_pkt(&testpkt.p, &testsock, pkt_len, 542 MODE_SERVER, &testspkt.p, "UnitTest")); 543 544 #else 545 546 TEST_IGNORE_MESSAGE("CMAC not enabled, skipping..."); 547 548 #endif /* OPENSSL */ 549 } 550 551