xref: /netbsd-src/external/bsd/ntp/dist/sntp/tests/packetProcessing.c (revision 3117ece4fc4a4ca4489ba793710b60b0d26bab6c)
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