xref: /xnu-8796.101.5/tests/ipsec.m (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
1#import <darwintest.h>
2#import <darwintest_utils.h>
3#import <dispatch/dispatch.h>
4#import <net/pfkeyv2.h>
5#import <netinet6/ipsec.h>
6#import <arpa/inet.h>
7#import <NetworkExtension/NetworkExtensionPrivate.h>
8#import <System/net/bpf.h>
9#import <System/netinet/ip.h>
10#import <System/netinet/ip6.h>
11
12T_GLOBAL_META(
13	T_META_NAMESPACE("xnu.ipsec"),
14	T_META_ASROOT(true),
15	T_META_CHECK_LEAKS(false));
16
17typedef enum {
18	TEST_INVALID = 0,
19	TEST_IPSEC_IPv4_ENCAPSULATE_PANIC = 1,
20	TEST_IPSEC_IPv6_ENCAPSULATE_PANIC = 2,
21} test_identifier;
22
23#define TEST_SRC_ADDRESS_IPv4                           "10.0.0.2"
24#define TEST_DST_ADDRESS_IPv4                           "10.0.0.3"
25#define TEST_IPSEC_IPv4_INTERFACE_ADDRESS               "192.168.10.10"
26#define TEST_IPSEC_IPv6_INTERFACE_ADDRESS               "fdd3:0f89:9afd:9b9c::1234"
27#define TEST_DELEGATE_IPSEC_INTERFACE_ADDRESS           "192.168.20.10"
28#define TEST_IPSEC_IPv4_INTERFACE_MASK                  "255.255.255.255"
29#define TEST_IPSEC_IPv6_INTERFACE_MASK                  "ffff:ffff:ffff:ffff::"
30
31static test_identifier test_id = TEST_INVALID;
32static dispatch_source_t pfkey_source = NULL;
33static NEVirtualInterfaceRef ipsecInterface = NULL;
34static NEVirtualInterfaceRef delegateIPsecInterface = NULL;
35static int bpf_fd = -1;
36
37static void bpf_write(int fd);
38static void pfkey_cleanup(void);
39static void pfkey_process_message_test_encapsulate_panic(uint8_t **mhp, int pfkey_socket);
40
41static void(*const process_pfkey_message_tests[])(uint8_t * *mhp, int pfkey_socket) =
42{
43	NULL,
44	pfkey_process_message_test_encapsulate_panic,    // TEST_IPSEC_IPv4_ENCAPSULATE_PANIC
45	pfkey_process_message_test_encapsulate_panic,    // TEST_IPSEC_IPv6_ENCAPSULATE_PANIC
46};
47
48static void
49send_pkey_add_sa(int pfkey_socket, uint32_t spi, const char *src, const char *dst, int family)
50{
51	uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
52	bzero(payload, sizeof(payload));
53	uint16_t tlen = 0;
54
55	struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
56	msg_payload->sadb_msg_version = PF_KEY_V2;
57	msg_payload->sadb_msg_type = SADB_ADD;
58	msg_payload->sadb_msg_errno = 0;
59	msg_payload->sadb_msg_satype = SADB_SATYPE_ESP;
60	msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
61	msg_payload->sadb_msg_reserved = 0;
62	msg_payload->sadb_msg_seq = 0;
63	msg_payload->sadb_msg_pid = (u_int32_t)getpid();
64	tlen += sizeof(*msg_payload);
65
66	struct sadb_sa_2 *sa2_payload = (struct sadb_sa_2 *)(void *)(payload + tlen);
67	sa2_payload->sa.sadb_sa_len = PFKEY_UNIT64(sizeof(*sa2_payload));
68	sa2_payload->sa.sadb_sa_exttype = SADB_EXT_SA;
69	sa2_payload->sa.sadb_sa_spi = htonl(spi);
70	sa2_payload->sa.sadb_sa_replay = 4;
71	sa2_payload->sa.sadb_sa_state = SADB_SASTATE_LARVAL;
72	sa2_payload->sa.sadb_sa_auth = SADB_X_AALG_SHA2_256;
73	sa2_payload->sa.sadb_sa_encrypt = SADB_X_EALG_AESCBC;
74	sa2_payload->sa.sadb_sa_flags |= (SADB_X_EXT_NATT | SADB_X_EXT_NATT_KEEPALIVE);
75	sa2_payload->sadb_sa_natt_src_port = htons(4500);
76	sa2_payload->sadb_sa_natt_port = 4500;
77	sa2_payload->sadb_sa_natt_interval = 20;
78	sa2_payload->sadb_sa_natt_offload_interval = 0;
79	tlen += sizeof(*sa2_payload);
80
81	struct sadb_x_sa2 *sa2_x_payload = (struct sadb_x_sa2 *)(void *)(payload + tlen);
82	sa2_x_payload->sadb_x_sa2_len = PFKEY_UNIT64(sizeof(*sa2_x_payload));
83	sa2_x_payload->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
84	sa2_x_payload->sadb_x_sa2_mode = IPSEC_MODE_TUNNEL;
85	sa2_x_payload->sadb_x_sa2_reqid = 0;
86	tlen += sizeof(*sa2_x_payload);
87
88	uint8_t prefixlen = (family == AF_INET) ? (sizeof(struct in_addr) << 3) : (sizeof(struct in6_addr) << 3);
89
90	struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen);
91	src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff;
92	src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
93	src_address_payload->sadb_address_prefixlen = prefixlen;
94	src_address_payload->sadb_address_reserved = 0;
95	tlen += sizeof(*src_address_payload);
96
97	if (family == AF_INET) {
98		struct sockaddr_in *src4 = (struct sockaddr_in *)(void *)(payload + tlen);
99		T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, src, &src4->sin_addr), 1, "src address fail");
100		src4->sin_family = AF_INET;
101		src4->sin_len = sizeof(*src4);
102		uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src4->sin_len);
103		src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
104		tlen += PFKEY_ALIGN8(src4->sin_len);
105	} else {
106		struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
107		T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, src, &src6->sin6_addr), 1, "src address fail");
108		src6->sin6_family = AF_INET6;
109		src6->sin6_len = sizeof(*src6);
110		uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src6->sin6_len);
111		src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
112		tlen += PFKEY_ALIGN8(src6->sin6_len);
113	}
114
115	struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen);
116	dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff;
117	dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
118	dst_address_payload->sadb_address_prefixlen = prefixlen;
119	dst_address_payload->sadb_address_reserved = 0;
120	tlen += sizeof(*dst_address_payload);
121
122	if (family == AF_INET) {
123		struct sockaddr_in *dst4 = (struct sockaddr_in *)(void *)(payload + tlen);
124		T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, dst, &dst4->sin_addr), 1, "dst address fail");
125		dst4->sin_family = AF_INET;
126		dst4->sin_len = sizeof(*dst4);
127		uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst4->sin_len);
128		dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
129		tlen += PFKEY_ALIGN8(dst4->sin_len);
130	} else {
131		struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
132		T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, dst, &dst6->sin6_addr), 1, "dst address fail");
133		dst6->sin6_family = AF_INET6;
134		dst6->sin6_len = sizeof(*dst6);
135		uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst6->sin6_len);
136		dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
137		tlen += PFKEY_ALIGN8(dst6->sin6_len);
138	}
139
140	CFStringRef ipsecIfName = NEVirtualInterfaceCopyName(ipsecInterface);
141	T_QUIET; T_ASSERT_NOTNULL(ipsecIfName, "failed to get ipsec interface name");
142	char ifname[IFNAMSIZ];
143	CFStringGetCString(ipsecIfName, ifname, IFNAMSIZ, kCFStringEncodingUTF8);
144
145	CFStringRef delegateIPsecIfName = NEVirtualInterfaceCopyName(delegateIPsecInterface);
146	T_QUIET; T_ASSERT_NOTNULL(delegateIPsecIfName, "failed to get delegate ipsec interface name");
147	char delegateIfname[IFNAMSIZ];
148	CFStringGetCString(delegateIPsecIfName, delegateIfname, IFNAMSIZ, kCFStringEncodingUTF8);
149
150	struct sadb_x_ipsecif *ipsec_if_payload = (struct sadb_x_ipsecif *)(void *)(payload + tlen);
151	ipsec_if_payload->sadb_x_ipsecif_len = PFKEY_UNIT64(sizeof(*ipsec_if_payload));
152	ipsec_if_payload->sadb_x_ipsecif_exttype = SADB_X_EXT_IPSECIF;
153	strncpy(ipsec_if_payload->sadb_x_ipsecif_ipsec_if, ifname, strlen(ifname));
154	strncpy(ipsec_if_payload->sadb_x_ipsecif_outgoing_if, delegateIfname, strlen(delegateIfname));
155	tlen += sizeof(*ipsec_if_payload);
156
157	struct sadb_key *encrypt_key_payload = (struct sadb_key *)(void *)(payload + tlen);
158	uint16_t len = sizeof(*encrypt_key_payload) + PFKEY_ALIGN8(32);
159	encrypt_key_payload->sadb_key_len = PFKEY_UNIT64(len);
160	encrypt_key_payload->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
161	encrypt_key_payload->sadb_key_bits = (uint16_t)(32 << 3);
162	encrypt_key_payload->sadb_key_reserved = 0;
163	tlen += sizeof(*encrypt_key_payload);
164	arc4random_buf(payload + tlen, 32);
165	tlen += PFKEY_ALIGN8(32);
166
167	struct sadb_key *auth_key_payload = (struct sadb_key *)(void *)(payload + tlen);
168	len = sizeof(*auth_key_payload) + PFKEY_ALIGN8(32);
169	auth_key_payload->sadb_key_len = PFKEY_UNIT64(len);
170	auth_key_payload->sadb_key_exttype = SADB_EXT_KEY_AUTH;
171	auth_key_payload->sadb_key_bits = (uint16_t)(32 << 3);
172	auth_key_payload->sadb_key_reserved = 0;
173	tlen += sizeof(*auth_key_payload);
174	arc4random_buf(payload + tlen, 32);
175	tlen += PFKEY_ALIGN8(32);
176
177	struct sadb_lifetime *hard_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen);
178	hard_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*hard_lifetime_payload));
179	hard_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
180	tlen += sizeof(*hard_lifetime_payload);
181
182	struct sadb_lifetime *soft_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen);
183	soft_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*soft_lifetime_payload));
184	soft_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
185	tlen += sizeof(*soft_lifetime_payload);
186
187	// Update the total length
188	msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
189	T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send update sa");
190}
191
192static void
193send_pfkey_flush_sa(int pfkey_socket)
194{
195	uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
196	bzero(payload, sizeof(payload));
197	uint16_t tlen = 0;
198
199	struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
200	msg_payload->sadb_msg_version = PF_KEY_V2;
201	msg_payload->sadb_msg_type = SADB_FLUSH;
202	msg_payload->sadb_msg_errno = 0;
203	msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
204	msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
205	msg_payload->sadb_msg_reserved = 0;
206	msg_payload->sadb_msg_seq = 0;
207	msg_payload->sadb_msg_pid = (u_int32_t)getpid();
208	tlen += sizeof(*msg_payload);
209
210	// Update the total length
211	msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
212	T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey flush sa");
213}
214
215static void
216pfkey_cleanup(void)
217{
218	if (pfkey_source != NULL) {
219		int pfkey_socket = (int)dispatch_source_get_handle(pfkey_source);
220		if (pfkey_socket > 0) {
221			send_pfkey_flush_sa(pfkey_socket);
222		}
223		dispatch_source_cancel(pfkey_source);
224		pfkey_source = NULL;
225	}
226}
227
228static void
229pfkey_align(struct sadb_msg *msg, uint8_t **mhp)
230{
231	struct sadb_ext *ext;
232	int i;
233	uint8_t *p;
234	uint8_t *ep;     /* XXX should be passed from upper layer */
235
236	/* validity check */
237	T_QUIET; T_ASSERT_NOTNULL(msg, "pfkey align msg");
238	T_QUIET; T_ASSERT_NOTNULL(mhp, "pfkey align mhp");
239
240	/* initialize */
241	for (i = 0; i < SADB_EXT_MAX + 1; i++) {
242		mhp[i] = NULL;
243	}
244
245	mhp[0] = (void *)msg;
246
247	/* initialize */
248	p = (void *) msg;
249	ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
250
251	/* skip base header */
252	p += sizeof(struct sadb_msg);
253
254	while (p < ep) {
255		ext = (void *)p;
256		T_QUIET; T_ASSERT_GE_PTR((void *)ep, (void *)(p + sizeof(*ext)), "pfkey extension header beyond end of buffer");
257		T_QUIET; T_ASSERT_GE_ULONG((unsigned long)PFKEY_EXTLEN(ext), sizeof(*ext), "pfkey extension shorter than extension header");
258		T_QUIET; T_ASSERT_GE_PTR((void *)ep, (void *)(p + PFKEY_EXTLEN(ext)), "pfkey extension length beyond end of buffer");
259
260		T_QUIET; T_EXPECT_NULL(mhp[ext->sadb_ext_type], "duplicate extension type %u payload", ext->sadb_ext_type);
261
262		/* set pointer */
263		switch (ext->sadb_ext_type) {
264		case SADB_EXT_SA:
265		case SADB_EXT_LIFETIME_CURRENT:
266		case SADB_EXT_LIFETIME_HARD:
267		case SADB_EXT_LIFETIME_SOFT:
268		case SADB_EXT_ADDRESS_SRC:
269		case SADB_EXT_ADDRESS_DST:
270		case SADB_EXT_ADDRESS_PROXY:
271		case SADB_EXT_KEY_AUTH:
272		/* XXX should to be check weak keys. */
273		case SADB_EXT_KEY_ENCRYPT:
274		/* XXX should to be check weak keys. */
275		case SADB_EXT_IDENTITY_SRC:
276		case SADB_EXT_IDENTITY_DST:
277		case SADB_EXT_SENSITIVITY:
278		case SADB_EXT_PROPOSAL:
279		case SADB_EXT_SUPPORTED_AUTH:
280		case SADB_EXT_SUPPORTED_ENCRYPT:
281		case SADB_EXT_SPIRANGE:
282		case SADB_X_EXT_POLICY:
283		case SADB_X_EXT_SA2:
284		case SADB_EXT_SESSION_ID:
285		case SADB_EXT_SASTAT:
286#ifdef SADB_X_EXT_NAT_T_TYPE
287		case SADB_X_EXT_NAT_T_TYPE:
288		case SADB_X_EXT_NAT_T_SPORT:
289		case SADB_X_EXT_NAT_T_DPORT:
290		case SADB_X_EXT_NAT_T_OA:
291#endif
292#ifdef SADB_X_EXT_TAG
293		case SADB_X_EXT_TAG:
294#endif
295#ifdef SADB_X_EXT_PACKET
296		case SADB_X_EXT_PACKET:
297#endif
298		case SADB_X_EXT_IPSECIF:
299		case SADB_X_EXT_ADDR_RANGE_SRC_START:
300		case SADB_X_EXT_ADDR_RANGE_SRC_END:
301		case SADB_X_EXT_ADDR_RANGE_DST_START:
302		case SADB_X_EXT_ADDR_RANGE_DST_END:
303#ifdef SADB_MIGRATE
304		case SADB_EXT_MIGRATE_ADDRESS_SRC:
305		case SADB_EXT_MIGRATE_ADDRESS_DST:
306		case SADB_X_EXT_MIGRATE_IPSECIF:
307#endif
308			mhp[ext->sadb_ext_type] = (void *)ext;
309			break;
310		default:
311			T_FAIL("bad extension type %u", ext->sadb_ext_type);
312			T_END;
313		}
314
315		p += PFKEY_EXTLEN(ext);
316	}
317
318	T_QUIET; T_EXPECT_EQ_PTR((void *)ep, (void *)p, "invalid pfkey message length");
319	return;
320}
321
322static void
323pfkey_process_message_test_encapsulate_panic(uint8_t **mhp, __unused int pfkey_socket)
324{
325	struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
326	static uint32_t spi = 0;
327	static uint8_t added_sa_counter = 0;
328
329	if (message->sadb_msg_pid != (uint32_t)getpid()) {
330		return;
331	}
332
333	if (message->sadb_msg_errno != 0) {
334		T_FAIL("SADB add SA received error %d", message->sadb_msg_errno);
335		T_END;
336	}
337
338	switch (message->sadb_msg_type) {
339	case SADB_ADD:
340	{
341		struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA];
342		T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL");
343		spi = ntohl(sa_message->sadb_sa_spi);
344		T_LOG("added sa 0x%x", spi);
345		added_sa_counter++;
346		if (added_sa_counter == 2) {
347			bpf_write(bpf_fd);
348		}
349		break;
350	}
351	case SADB_FLUSH:
352	case SADB_X_SPDFLUSH:
353		break;
354	default:
355		T_FAIL("bad SADB message type %u", message->sadb_msg_type);
356		T_END;
357	}
358	return;
359}
360
361static void
362recv_pfkey_message(int pfkey_socket)
363{
364	uint8_t buffer[8192] __attribute__((aligned(4)));
365	struct iovec iovecs[1] = {
366		{ buffer, sizeof(buffer) },
367	};
368	struct msghdr msg = {
369		NULL,
370		0,
371		iovecs,
372		sizeof(iovecs) / sizeof(iovecs[0]),
373		NULL,
374		0,
375		0,
376	};
377
378	do {
379		ssize_t result = -1;
380		memset(buffer, 0, sizeof(buffer));
381		T_QUIET; T_ASSERT_POSIX_SUCCESS(result = recvmsg(pfkey_socket, &msg, 0), NULL);
382
383		if (result > 0) {
384			T_QUIET; T_ASSERT_GE_ULONG((size_t)result, sizeof(struct sadb_msg), "Invalid PFKey message size: %zu", result);
385			struct sadb_msg *hdr = (struct sadb_msg *)buffer;
386			uint8_t *mhp[SADB_EXT_MAX + 1];
387			pfkey_align(hdr, mhp);
388			(*process_pfkey_message_tests[test_id])(mhp, pfkey_socket);
389		} else if (result == 0) {
390			T_LOG("PFKey socket received EOF");
391			break;
392		}
393	} while (1);
394}
395
396static int
397pfkey_setup_socket(void)
398{
399	int pfkey_socket = -1;
400	int bufsiz = 0;
401	const unsigned long newbufk = 1536;
402	unsigned long oldmax;
403	size_t  oldmaxsize = sizeof(oldmax);
404	unsigned long newmax = newbufk * (1024 + 128);
405
406	T_QUIET; T_ASSERT_POSIX_SUCCESS(pfkey_socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2), NULL);
407
408	if (sysctlbyname("kern.ipc.maxsockbuf", &oldmax, &oldmaxsize, &newmax, sizeof(newmax)) != 0) {
409		bufsiz = 233016;        /* Max allowed by default */
410	} else {
411		bufsiz = newbufk * 1024;
412	}
413
414	T_QUIET; T_ASSERT_POSIX_SUCCESS(setsockopt(pfkey_socket, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz)), "pfkey set snd socket buf failed %d", bufsiz);
415	T_QUIET; T_ASSERT_POSIX_SUCCESS(setsockopt(pfkey_socket, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)), "pfkey set recv socket buf failed %d", bufsiz);
416
417	pfkey_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, (uintptr_t)pfkey_socket, 0, dispatch_get_main_queue());
418	T_QUIET; T_ASSERT_NOTNULL(pfkey_source, "dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, ...)");
419	dispatch_source_set_event_handler(pfkey_source, ^{
420		recv_pfkey_message(pfkey_socket);
421	});
422	dispatch_source_set_cancel_handler(pfkey_source, ^{
423		close(pfkey_socket);
424	});
425	dispatch_resume(pfkey_source);
426	return pfkey_socket;
427}
428
429static int
430bpf_new(void)
431{
432	char bpfdev[256];
433	int i;
434	int fd = -1;
435
436	for (i = 0; true; i++) {
437		snprintf(bpfdev, sizeof(bpfdev), "/dev/bpf%d", i);
438		fd = open(bpfdev, O_RDWR, 0);
439		if (fd >= 0) {
440			break;
441		}
442		if (errno != EBUSY) {
443			break;
444		}
445	}
446	return fd;
447}
448
449static int
450bpf_setif(int fd, const char *en_name)
451{
452	struct ifreq ifr;
453
454	strlcpy(ifr.ifr_name, en_name, sizeof(ifr.ifr_name));
455	return ioctl(fd, BIOCSETIF, &ifr);
456}
457
458static int
459bpf_sethdr_complete(int fd)
460{
461	u_int8_t hdr_complete = 1;
462	return ioctl(fd, BIOCSHDRCMPLT, &hdr_complete);
463}
464
465static void
466bpf_write(int fd)
467{
468	if (test_id == TEST_IPSEC_IPv4_ENCAPSULATE_PANIC) {
469		char buffer[500];
470		struct ip *ipheader = (void *)buffer;
471		ipheader->ip_v = IPVERSION;
472		ipheader->ip_hl = (sizeof(struct ip) - 4) >> 2;
473		ipheader->ip_ttl = MAXTTL;
474		ipheader->ip_p = IPPROTO_UDP;
475		T_QUIET; T_ASSERT_POSIX_SUCCESS(write(fd, buffer, 500), "bpf write call failed");
476		T_PASS("wrote bad ip header successfully");
477		T_END;
478	} else if (test_id == TEST_IPSEC_IPv6_ENCAPSULATE_PANIC) {
479		struct ip6_hdr ip6 = {0};
480		ip6.ip6_vfc |= IPV6_VERSION;
481		T_QUIET; T_ASSERT_POSIX_SUCCESS(write(fd, &ip6, sizeof(ip6) - 4), "bpf write call failed");
482		T_PASS("wrote bad ipv6 header successfully");
483		T_END;
484	}
485}
486
487static void
488bpf_socket_setup(void)
489{
490	int status = -1;
491
492	bpf_fd = bpf_new();
493	T_QUIET; T_ASSERT_NE(bpf_fd, -1, "failed to create bpf file descriptor");
494
495	CFStringRef ipsecIfName = NEVirtualInterfaceCopyName(ipsecInterface);
496	T_QUIET; T_ASSERT_NOTNULL(ipsecIfName, "failed to get ipsec interface name");
497
498	char ifname[IFNAMSIZ];
499	CFStringGetCString(ipsecIfName, ifname, IFNAMSIZ, kCFStringEncodingUTF8);
500
501	status = bpf_setif(bpf_fd, ifname);
502	T_QUIET; T_ASSERT_NE(status, -1, "failed to set bpf interface");
503
504	status = bpf_sethdr_complete(bpf_fd);
505	T_QUIET; T_ASSERT_NE(status, -1, "failed to set bpf header complete");
506}
507
508static NEVirtualInterfaceRef
509ipsec_interface_setup(CFStringRef interfaceAddress, CFStringRef interfaceMask)
510{
511	Boolean status = FALSE;
512
513	NEVirtualInterfaceRef interface = NEVirtualInterfaceCreate(NULL, kNEVirtualInterfaceValTypeIPSec, dispatch_get_main_queue(), NULL);
514	T_QUIET; T_ASSERT_NOTNULL(interface, "ipsec interface creation failed");
515	status = NEVirtualInterfaceSetMTU(interface, 1400);
516	if (status == FALSE) {
517		T_FAIL("Failed to set MTU on ipsec interface");
518		T_END;
519	}
520
521	status = NEVirtualInterfaceAddAddress(interface, interfaceAddress, interfaceMask);
522	if (status == FALSE) {
523		T_FAIL("Failed to set address on ipsec interface");
524		T_END;
525	}
526
527	CFStringRef ipsecIfName = NEVirtualInterfaceCopyName(interface);
528	T_QUIET; T_ASSERT_NOTNULL(ipsecIfName, "failed to get ipsec interface name");
529
530	char ifname[IFNAMSIZ];
531	CFStringGetCString(ipsecIfName, ifname, IFNAMSIZ, kCFStringEncodingUTF8);
532
533	T_LOG("%s interface setup", ifname);
534	return interface;
535}
536
537static void
538ipsec_interface_set_delegate(NEVirtualInterfaceRef interface, CFStringRef delegateInterfaceName)
539{
540	Boolean status = NEVirtualInterfaceSetDelegateInterface(interface, delegateInterfaceName);
541	if (status == FALSE) {
542		T_FAIL("Failed to set delegate on ipsec interface");
543		T_END;
544	}
545
546	return;
547}
548
549static void
550ipsec_cleanup(void)
551{
552	pfkey_cleanup();
553
554	if (ipsecInterface != NULL) {
555		NEVirtualInterfaceInvalidate(ipsecInterface);
556		ipsecInterface = NULL;
557	}
558
559	if (delegateIPsecInterface != NULL) {
560		NEVirtualInterfaceInvalidate(delegateIPsecInterface);
561		delegateIPsecInterface = NULL;
562	}
563
564	if (bpf_fd != -1) {
565		close(bpf_fd);
566		bpf_fd = -1;
567	}
568}
569
570T_DECL(ipsec_ipv4_encapsulate_panic_63139357, "ipsec: outer ip header length less than 20")
571{
572	test_id = TEST_IPSEC_IPv4_ENCAPSULATE_PANIC;
573
574	T_ATEND(ipsec_cleanup);
575
576	ipsecInterface = ipsec_interface_setup(CFSTR(TEST_IPSEC_IPv4_INTERFACE_ADDRESS), CFSTR(TEST_IPSEC_IPv4_INTERFACE_MASK));
577	delegateIPsecInterface = ipsec_interface_setup(CFSTR(TEST_DELEGATE_IPSEC_INTERFACE_ADDRESS), CFSTR(TEST_IPSEC_IPv4_INTERFACE_MASK));
578
579	CFStringRef delegateIPsecIfName = NEVirtualInterfaceCopyName(delegateIPsecInterface);
580	T_QUIET; T_ASSERT_NOTNULL(delegateIPsecIfName, "failed to get ipsec interface name");
581	ipsec_interface_set_delegate(ipsecInterface, delegateIPsecIfName);
582
583	bpf_socket_setup();
584
585	int pfkey_socket = pfkey_setup_socket();
586	send_pfkey_flush_sa(pfkey_socket);
587
588	send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
589	send_pkey_add_sa(pfkey_socket, 0x23456789, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
590
591	dispatch_main();
592}
593
594T_DECL(ipsec_ipv6_encapsulate_panic_63139357, "ipsec: payload less than IPv6 header")
595{
596	test_id = TEST_IPSEC_IPv6_ENCAPSULATE_PANIC;
597
598	T_ATEND(ipsec_cleanup);
599
600	ipsecInterface = ipsec_interface_setup(CFSTR(TEST_IPSEC_IPv6_INTERFACE_ADDRESS), CFSTR(TEST_IPSEC_IPv6_INTERFACE_MASK));
601	delegateIPsecInterface = ipsec_interface_setup(CFSTR(TEST_DELEGATE_IPSEC_INTERFACE_ADDRESS), CFSTR(TEST_IPSEC_IPv4_INTERFACE_MASK));
602
603	CFStringRef delegateIPsecIfName = NEVirtualInterfaceCopyName(delegateIPsecInterface);
604	T_QUIET; T_ASSERT_NOTNULL(delegateIPsecIfName, "failed to get ipsec interface name");
605	ipsec_interface_set_delegate(ipsecInterface, delegateIPsecIfName);
606
607	bpf_socket_setup();
608
609	int pfkey_socket = pfkey_setup_socket();
610	send_pfkey_flush_sa(pfkey_socket);
611
612	send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
613	send_pkey_add_sa(pfkey_socket, 0x23456789, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
614
615	dispatch_main();
616}
617