Home | History | Annotate | Line # | Download | only in tests
packetProcessing.c revision 1.5
      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