xref: /openbsd-src/regress/lib/libcrypto/x509/rfc3779/rfc3779.c (revision d3ce54f2613e5bd018465fe0fb3f656756d0ae8d)
1*d3ce54f2Stb /*	$OpenBSD: rfc3779.c,v 1.10 2023/12/13 07:19:37 tb Exp $ */
24defbdf5Stb /*
34defbdf5Stb  * Copyright (c) 2021 Theo Buehler <tb@openbsd.org>
44defbdf5Stb  *
54defbdf5Stb  * Permission to use, copy, modify, and distribute this software for any
64defbdf5Stb  * purpose with or without fee is hereby granted, provided that the above
74defbdf5Stb  * copyright notice and this permission notice appear in all copies.
84defbdf5Stb  *
94defbdf5Stb  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
104defbdf5Stb  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
114defbdf5Stb  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
124defbdf5Stb  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
134defbdf5Stb  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
144defbdf5Stb  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
154defbdf5Stb  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
164defbdf5Stb  */
174defbdf5Stb 
184defbdf5Stb #include <stdio.h>
194defbdf5Stb #include <string.h>
204defbdf5Stb 
214defbdf5Stb #include <openssl/asn1.h>
224defbdf5Stb #include <openssl/asn1t.h>
234defbdf5Stb #include <openssl/x509v3.h>
244defbdf5Stb 
254defbdf5Stb #define RAW_ADDRESS_SIZE	16
264defbdf5Stb 
274defbdf5Stb static void
hexdump(const unsigned char * buf,size_t len)284defbdf5Stb hexdump(const unsigned char *buf, size_t len)
294defbdf5Stb {
304defbdf5Stb 	size_t i;
314defbdf5Stb 
324defbdf5Stb 	for (i = 1; i <= len; i++)
334defbdf5Stb 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
344defbdf5Stb 
354defbdf5Stb 	if (len % 8)
364defbdf5Stb 		fprintf(stderr, "\n");
374defbdf5Stb }
384defbdf5Stb 
394defbdf5Stb static void
report_hexdump(const char * func,const char * description,const char * msg,const unsigned char * want,size_t want_len,const unsigned char * got,size_t got_len)404defbdf5Stb report_hexdump(const char *func, const char *description, const char *msg,
414defbdf5Stb     const unsigned char *want, size_t want_len,
424defbdf5Stb     const unsigned char *got, size_t got_len)
434defbdf5Stb {
444defbdf5Stb 	fprintf(stderr, "%s: \"%s\" %s\nwant:\n", func, description, msg);
454defbdf5Stb 	hexdump(want, want_len);
464defbdf5Stb 	fprintf(stderr, "got:\n");
474defbdf5Stb 	hexdump(got, got_len);
484defbdf5Stb }
494defbdf5Stb 
504defbdf5Stb static int
afi_size(int afi)514defbdf5Stb afi_size(int afi)
524defbdf5Stb {
534defbdf5Stb 	switch (afi) {
544defbdf5Stb 	case IANA_AFI_IPV4:
554defbdf5Stb 		return 4;
564defbdf5Stb 	case IANA_AFI_IPV6:
574defbdf5Stb 		return 16;
584defbdf5Stb 	}
594defbdf5Stb 	return 0;
604defbdf5Stb }
614defbdf5Stb 
624defbdf5Stb struct IPAddressOrRange_test {
634defbdf5Stb 	const char	*description;
644defbdf5Stb 	const uint8_t	 der[32];
654defbdf5Stb 	size_t		 der_len;
664defbdf5Stb 	unsigned	 afi;
674defbdf5Stb 	const uint8_t	 min[RAW_ADDRESS_SIZE];
684defbdf5Stb 	const uint8_t	 max[RAW_ADDRESS_SIZE];
694defbdf5Stb };
704defbdf5Stb 
714defbdf5Stb const struct IPAddressOrRange_test IPAddressOrRange_test_data[] = {
724defbdf5Stb 	/* Examples from RFC 3779, section 2.1.1 */
734defbdf5Stb 	{
744defbdf5Stb 		.description = "address 10.5.0.4",
754defbdf5Stb 		.der = {
764defbdf5Stb 			0x03, 0x05, 0x00, 0x0a, 0x05, 0x00, 0x04,
774defbdf5Stb 		},
784defbdf5Stb 		.der_len = 7,
794defbdf5Stb 		.afi = IANA_AFI_IPV4,
804defbdf5Stb 		.min = {
814defbdf5Stb 			0x0a, 0x05, 0x00, 0x04,
824defbdf5Stb 		},
834defbdf5Stb 		.max = {
844defbdf5Stb 			0x0a, 0x05, 0x00, 0x04,
854defbdf5Stb 		}
864defbdf5Stb 	},
874defbdf5Stb 	{
884defbdf5Stb 		.description = "prefix 10.5.0/23",
894defbdf5Stb 		.der = {
904defbdf5Stb 			0x03, 0x04, 0x01, 0x0a, 0x05, 0x00,
914defbdf5Stb 		},
924defbdf5Stb 		.der_len = 6,
934defbdf5Stb 		.afi = IANA_AFI_IPV4,
944defbdf5Stb 		.min = {
954defbdf5Stb 			0x0a, 0x05, 0x00, 0x00,
964defbdf5Stb 		},
974defbdf5Stb 		.max = {
984defbdf5Stb 			0x0a, 0x05, 0x01, 0xff,
994defbdf5Stb 		}
1004defbdf5Stb 	},
1014defbdf5Stb 	{
1024defbdf5Stb 		.description = "address 2001:0:200:3::1",
1034defbdf5Stb 		.der = {
1044defbdf5Stb 			0x03, 0x11, 0x00, 0x20, 0x01, 0x00, 0x00, 0x02,
1054defbdf5Stb 			0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1064defbdf5Stb 			0x00, 0x00, 0x01,
1074defbdf5Stb 		},
1084defbdf5Stb 		.der_len = 19,
1094defbdf5Stb 		.afi = IANA_AFI_IPV6,
1104defbdf5Stb 		.min = {
1114defbdf5Stb 			0x20, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03,
1124defbdf5Stb 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1134defbdf5Stb 		},
1144defbdf5Stb 		.max = {
1154defbdf5Stb 			0x20, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03,
1164defbdf5Stb 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1174defbdf5Stb 		},
1184defbdf5Stb 	},
1194defbdf5Stb 	{
1204defbdf5Stb 		.description = "prefix 2001:0:200/39",
1214defbdf5Stb 		.der = {
1224defbdf5Stb 			0x03, 0x06, 0x01, 0x20, 0x01, 0x00, 0x00, 0x02,
1234defbdf5Stb 		},
1244defbdf5Stb 		.der_len = 8,
1254defbdf5Stb 		.afi = IANA_AFI_IPV6,
1264defbdf5Stb 		.min = {
1274defbdf5Stb 			0x20, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1284defbdf5Stb 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1294defbdf5Stb 		},
1304defbdf5Stb 		.max = {
1314defbdf5Stb 			0x20, 0x01, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff,
1324defbdf5Stb 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1334defbdf5Stb 		},
1344defbdf5Stb 	},
1354defbdf5Stb 
1364defbdf5Stb 	/* Examples from RFC 3779, Section 2.1.2 */
1374defbdf5Stb 	{
1384defbdf5Stb 		.description = "prefix 10.5.0/23 as a range",
1394defbdf5Stb 		.der = {
1404defbdf5Stb 			/* Sequence */
1414defbdf5Stb 			0x30, 0x0b,
1424defbdf5Stb 			/* 10.5.0.0 */
1434defbdf5Stb 			0x03, 0x03, 0x00, 0x0a, 0x05,
1444defbdf5Stb 			/* 10.5.1.255 */
1454defbdf5Stb 			0x03, 0x04, 0x01, 0x0a, 0x05, 0x00,
1464defbdf5Stb 		},
1474defbdf5Stb 		.der_len = 13,
1484defbdf5Stb 		.afi = IANA_AFI_IPV4,
1494defbdf5Stb 		.min = {
1504defbdf5Stb 			0x0a, 0x05, 0x00, 0x00,
1514defbdf5Stb 		},
1524defbdf5Stb 		.max = {
1534defbdf5Stb 			0x0a, 0x05, 0x01, 0xff,
1544defbdf5Stb 		}
1554defbdf5Stb 	},
1564defbdf5Stb 	{
1574defbdf5Stb 		.description = "prefix 2001:0:200/39 as a range",
1584defbdf5Stb 		.der = {
1594defbdf5Stb 			/* Sequence */
1604defbdf5Stb 			0x30, 0x10,
1614defbdf5Stb 			/* 2001:0:200:: */
1624defbdf5Stb 			0x03, 0x06, 0x01, 0x20, 0x01, 0x00, 0x00, 0x02,
1634defbdf5Stb 			/* 2001:0:3ff:ffff:ffff:ffff:ffff:ffff */
1644defbdf5Stb 			0x03, 0x06, 0x02, 0x20, 0x01, 0x00, 0x00, 0x00,
1654defbdf5Stb 		},
1664defbdf5Stb 		.der_len = 18,
1674defbdf5Stb 		.afi = IANA_AFI_IPV6,
1684defbdf5Stb 		.min = {
1694defbdf5Stb 			0x20, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1704defbdf5Stb 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1714defbdf5Stb 		},
1724defbdf5Stb 		.max = {
1734defbdf5Stb 			0x20, 0x01, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff,
1744defbdf5Stb 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1754defbdf5Stb 		}
1764defbdf5Stb 	},
1774defbdf5Stb 	{
1784defbdf5Stb 		.description = "prefix 0/0",
1794defbdf5Stb 		.der = {
1804defbdf5Stb 			0x03, 0x01, 0x00,
1814defbdf5Stb 		},
1824defbdf5Stb 		.der_len = 3,
1834defbdf5Stb 		.afi = IANA_AFI_IPV4,
1844defbdf5Stb 		.min = {
1854defbdf5Stb 			0x00, 0x00, 0x00, 0x00,
1864defbdf5Stb 		},
1874defbdf5Stb 		.max = {
1884defbdf5Stb 			0xff, 0xff, 0xff, 0xff,
1894defbdf5Stb 		}
1904defbdf5Stb 	},
1914defbdf5Stb 	{
1924defbdf5Stb 		.description = "prefix 10.64/12",
1934defbdf5Stb 		.der = {
1944defbdf5Stb 			0x03, 0x03, 0x04, 0x0a, 0x40,
1954defbdf5Stb 		},
1964defbdf5Stb 		.der_len = 5,
1974defbdf5Stb 		.afi = IANA_AFI_IPV4,
1984defbdf5Stb 		.min = {
1994defbdf5Stb 			0x0a, 0x40, 0x00, 0x00,
2004defbdf5Stb 		},
2014defbdf5Stb 		.max = {
2024defbdf5Stb 			0x0a, 0x4f, 0xff, 0xff,
2034defbdf5Stb 		},
2044defbdf5Stb 	},
2054defbdf5Stb 	{
2064defbdf5Stb 		.description = "prefix 10.64/20",
2074defbdf5Stb 		.der = {
2084defbdf5Stb 			0x03, 0x04, 0x04, 0x0a, 0x40, 0x00,
2094defbdf5Stb 		},
2104defbdf5Stb 		.der_len = 6,
2114defbdf5Stb 		.afi = IANA_AFI_IPV4,
2124defbdf5Stb 		.min = {
2134defbdf5Stb 			0x0a, 0x40, 0x00, 0x00,
2144defbdf5Stb 		},
2154defbdf5Stb 		.max = {
2164defbdf5Stb 			0x0a, 0x40, 0x0f, 0xff,
2174defbdf5Stb 		},
2184defbdf5Stb 	},
2194defbdf5Stb };
2204defbdf5Stb 
2214defbdf5Stb const size_t N_IPADDRESSORRANGE_TESTS =
2224defbdf5Stb     sizeof(IPAddressOrRange_test_data) / sizeof(IPAddressOrRange_test_data[0]);
2234defbdf5Stb 
2244defbdf5Stb static int
test_IPAddressOrRange(const struct IPAddressOrRange_test * test)2254defbdf5Stb test_IPAddressOrRange(const struct IPAddressOrRange_test *test)
2264defbdf5Stb {
2274defbdf5Stb 	IPAddressOrRange *aor;
2284defbdf5Stb 	const unsigned char *p;
2294defbdf5Stb 	unsigned char min[RAW_ADDRESS_SIZE] = {0}, max[RAW_ADDRESS_SIZE] = {0};
2304defbdf5Stb 	unsigned char *out = NULL;
2314defbdf5Stb 	int out_len;
2324defbdf5Stb 	int afi_len;
2334defbdf5Stb 	int memcmp_failed = 0;
2344defbdf5Stb 	int failed = 1;
2354defbdf5Stb 
2364defbdf5Stb 	/*
2374defbdf5Stb 	 * First, decode DER from the test case.
2384defbdf5Stb 	 */
2394defbdf5Stb 
2404defbdf5Stb 	p = &test->der[0];
2414defbdf5Stb 	if ((aor = d2i_IPAddressOrRange(NULL, &p, test->der_len)) == NULL) {
2424defbdf5Stb 		fprintf(stderr, "%s: \"%s\" d2i_IPAddressOrRange failed\n",
2434defbdf5Stb 		    __func__, test->description);
2444defbdf5Stb 		goto err;
2454defbdf5Stb 	}
2464defbdf5Stb 
2474defbdf5Stb 	/*
2484defbdf5Stb 	 * Now extract minimum and maximum from the parsed range.
2494defbdf5Stb 	 */
2504defbdf5Stb 
2514defbdf5Stb 	afi_len = afi_size(test->afi);
2524defbdf5Stb 
2534defbdf5Stb 	if (X509v3_addr_get_range(aor, test->afi, min, max, sizeof min) !=
2544defbdf5Stb 	    afi_len) {
2554defbdf5Stb 		fprintf(stderr, "%s: \"%s\" X509v3_addr_get_range failed\n",
2564defbdf5Stb 		    __func__, test->description);
2574defbdf5Stb 		goto err;
2584defbdf5Stb 	}
2594defbdf5Stb 
2604defbdf5Stb 	/*
2614defbdf5Stb 	 * Check that min and max match expectations.
2624defbdf5Stb 	 */
2634defbdf5Stb 
2644defbdf5Stb 	if (memcmp(min, test->min, afi_len) != 0) {
2654defbdf5Stb 		memcmp_failed |= 1;
2664defbdf5Stb 		report_hexdump(__func__, test->description, "memcmp min failed",
2674defbdf5Stb 		    test->min, afi_len, min, afi_len);
2684defbdf5Stb 	}
2694defbdf5Stb 	if (memcmp(max, test->max, afi_len) != 0) {
2704defbdf5Stb 		memcmp_failed |= 1;
2714defbdf5Stb 		report_hexdump(__func__, test->description, "memcmp max failed",
2724defbdf5Stb 		    test->max, afi_len, max, afi_len);
2734defbdf5Stb 	}
2744defbdf5Stb 	if (memcmp_failed)
2754defbdf5Stb 		goto err;
2764defbdf5Stb 
2774defbdf5Stb 	/*
2784defbdf5Stb 	 * Now turn the parsed IPAddressOrRange back into DER and check that
2794defbdf5Stb 	 * it matches the DER in the test case.
2804defbdf5Stb 	 */
2814defbdf5Stb 
2824defbdf5Stb 	out = NULL;
2834defbdf5Stb 	if ((out_len = i2d_IPAddressOrRange(aor, &out)) <= 0) {
2844defbdf5Stb 		fprintf(stderr, "%s: \"%s\" i2d_IPAddressOrRange failed\n",
2854defbdf5Stb 		    __func__, test->description);
2864defbdf5Stb 		goto err;
2874defbdf5Stb 	}
2884defbdf5Stb 
2894defbdf5Stb 	memcmp_failed = (size_t)out_len != test->der_len;
2904defbdf5Stb 	if (!memcmp_failed)
2914defbdf5Stb 		memcmp_failed = memcmp(test->der, out, out_len);
2924defbdf5Stb 
2934defbdf5Stb 	if (memcmp_failed) {
2944defbdf5Stb 		report_hexdump(__func__, test->description, "memcmp DER failed",
2954defbdf5Stb 		    test->der, test->der_len, out, out_len);
2964defbdf5Stb 		goto err;
2974defbdf5Stb 	}
2984defbdf5Stb 
2994defbdf5Stb 	failed = 0;
3004defbdf5Stb  err:
3014defbdf5Stb 	IPAddressOrRange_free(aor);
3024defbdf5Stb 	free(out);
3034defbdf5Stb 
3044defbdf5Stb 	return failed;
3054defbdf5Stb }
3064defbdf5Stb 
3074defbdf5Stb static int
run_IPAddressOrRange_tests(void)3084defbdf5Stb run_IPAddressOrRange_tests(void)
3094defbdf5Stb {
3104defbdf5Stb 	size_t i;
3114defbdf5Stb 	int failed = 0;
3124defbdf5Stb 
3134defbdf5Stb 	for (i = 0; i < N_IPADDRESSORRANGE_TESTS; i++)
3144defbdf5Stb 		failed |=
3154defbdf5Stb 		    test_IPAddressOrRange(&IPAddressOrRange_test_data[i]);
3164defbdf5Stb 
3174defbdf5Stb 	return failed;
3184defbdf5Stb }
3194defbdf5Stb 
3204defbdf5Stb /*
3214defbdf5Stb  * XXX: These should really be part of the public API...
3224defbdf5Stb  */
3234defbdf5Stb static IPAddrBlocks *IPAddrBlocks_new(void);
3244defbdf5Stb static void IPAddrBlocks_free(IPAddrBlocks *addr);
325f911aa70Stb static IPAddrBlocks *d2i_IPAddrBlocks(IPAddrBlocks **addrs,
3264defbdf5Stb     const unsigned char **in, long len);
3274defbdf5Stb static int i2d_IPAddrBlocks(IPAddrBlocks *addrs, unsigned char **out);
3284defbdf5Stb 
3294defbdf5Stb static IPAddrBlocks *
IPAddrBlocks_new(void)3304defbdf5Stb IPAddrBlocks_new(void)
3314defbdf5Stb {
3324defbdf5Stb 	IPAddrBlocks *addrs;
3334defbdf5Stb 
3344defbdf5Stb 	/*
3354defbdf5Stb 	 * XXX The comparison function IPAddressFamily_cmp() isn't public.
3364defbdf5Stb 	 * Start with the default and exploit a side effect of the lovely API
3374defbdf5Stb 	 * which helpfully sets the correct function in a few places. Let's
3384defbdf5Stb 	 * use the cheapest and easiest to reach one.
3394defbdf5Stb 	 */
3404defbdf5Stb 	if ((addrs = sk_IPAddressFamily_new_null()) == NULL)
3414defbdf5Stb 		return NULL;
3424defbdf5Stb 	if (!X509v3_addr_canonize(addrs)) {
3434defbdf5Stb 		IPAddrBlocks_free(addrs);
3444defbdf5Stb 		return NULL;
3454defbdf5Stb 	}
3464defbdf5Stb 
3474defbdf5Stb 	return addrs;
3484defbdf5Stb }
3494defbdf5Stb 
3504defbdf5Stb static void
IPAddrBlocks_free(IPAddrBlocks * addr)3514defbdf5Stb IPAddrBlocks_free(IPAddrBlocks *addr)
3524defbdf5Stb {
3534defbdf5Stb 	sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free);
3544defbdf5Stb }
3554defbdf5Stb 
3564defbdf5Stb /*
3574defbdf5Stb  * We want {d2i,i2d}_IPAddrBlocks() to play with the DER of the extension.
3584defbdf5Stb  * These don't exist, so we have to implement them ourselves.  IPAddrBlocks_it
3594defbdf5Stb  * isn't public, so we need to fetch it from the library.  We cache it in a
3604defbdf5Stb  * static variable to avoid the cost of a binary search through all supported
3614defbdf5Stb  * extensions on each call.
3624defbdf5Stb  */
3634defbdf5Stb 
364*d3ce54f2Stb static ASN1_ITEM_EXP *
get_IPAddrBlocks_it(void)3654defbdf5Stb get_IPAddrBlocks_it(void)
3664defbdf5Stb {
367*d3ce54f2Stb 	static ASN1_ITEM_EXP *my_IPAddrBlocks_it;
3684defbdf5Stb 	const X509V3_EXT_METHOD *v3_addr;
3694defbdf5Stb 
3704defbdf5Stb 	if (my_IPAddrBlocks_it != NULL)
3714defbdf5Stb 		return my_IPAddrBlocks_it;
3724defbdf5Stb 
3734defbdf5Stb 	if ((v3_addr = X509V3_EXT_get_nid(NID_sbgp_ipAddrBlock)) == NULL) {
3744defbdf5Stb 		fprintf(stderr, "could not get v3_addr\n");
3754defbdf5Stb 		return NULL;
3764defbdf5Stb 	}
3774defbdf5Stb 
3784defbdf5Stb 	my_IPAddrBlocks_it = v3_addr->it;
3794defbdf5Stb 
3804defbdf5Stb 	return my_IPAddrBlocks_it;
3814defbdf5Stb }
3824defbdf5Stb 
383f911aa70Stb static IPAddrBlocks *
d2i_IPAddrBlocks(IPAddrBlocks ** addrs,const unsigned char ** in,long len)3844defbdf5Stb d2i_IPAddrBlocks(IPAddrBlocks **addrs, const unsigned char **in, long len)
3854defbdf5Stb {
386*d3ce54f2Stb 	ASN1_ITEM_EXP *my_IPAddrBlocks_it;
3874defbdf5Stb 
388bd5381c8Stb 	if ((my_IPAddrBlocks_it = get_IPAddrBlocks_it()) == NULL)
3894defbdf5Stb 		return NULL;
3904defbdf5Stb 
3914defbdf5Stb 	return (IPAddrBlocks *)ASN1_item_d2i((ASN1_VALUE **)addrs, in, len,
3924defbdf5Stb 	    my_IPAddrBlocks_it);
3934defbdf5Stb }
3944defbdf5Stb 
3954defbdf5Stb static int
i2d_IPAddrBlocks(IPAddrBlocks * addrs,unsigned char ** out)3964defbdf5Stb i2d_IPAddrBlocks(IPAddrBlocks *addrs, unsigned char **out)
3974defbdf5Stb {
398*d3ce54f2Stb 	ASN1_ITEM_EXP *my_IPAddrBlocks_it;
3994defbdf5Stb 
400bd5381c8Stb 	if ((my_IPAddrBlocks_it = get_IPAddrBlocks_it()) == NULL)
4014defbdf5Stb 		return -1;
4024defbdf5Stb 
4034defbdf5Stb 	return ASN1_item_i2d((ASN1_VALUE *)addrs, out, my_IPAddrBlocks_it);
4044defbdf5Stb }
4054defbdf5Stb 
4064defbdf5Stb struct ipv4_prefix {
4074defbdf5Stb 	unsigned char			addr[4];
4084defbdf5Stb 	size_t				addr_len;
4094defbdf5Stb 	size_t				prefix_len;
4104defbdf5Stb };
4114defbdf5Stb 
4124defbdf5Stb struct ipv4_range {
4134defbdf5Stb 	unsigned char			min[4];
4144defbdf5Stb 	unsigned char			max[4];
4154defbdf5Stb };
4164defbdf5Stb 
4174defbdf5Stb union ipv4_choice {
4184defbdf5Stb 	struct ipv4_prefix	prefix;
4194defbdf5Stb 	struct ipv4_range	range;
4204defbdf5Stb };
4214defbdf5Stb 
4224defbdf5Stb struct ipv6_prefix {
4234defbdf5Stb 	unsigned char		addr[16];
4244defbdf5Stb 	size_t			addr_len;
4254defbdf5Stb 	size_t			prefix_len;
4264defbdf5Stb };
4274defbdf5Stb 
4284defbdf5Stb struct ipv6_range {
4294defbdf5Stb 	unsigned char		min[16];
4304defbdf5Stb 	unsigned char		max[16];
4314defbdf5Stb };
4324defbdf5Stb 
4334defbdf5Stb union ipv6_choice {
4344defbdf5Stb 	struct ipv6_prefix	prefix;
4354defbdf5Stb 	struct ipv6_range	range;
4364defbdf5Stb };
4374defbdf5Stb 
4384defbdf5Stb enum choice_type {
4394defbdf5Stb 	choice_prefix,
4404defbdf5Stb 	choice_range,
4414defbdf5Stb 	choice_inherit,
4424defbdf5Stb 	choice_last,
4434defbdf5Stb };
4444defbdf5Stb 
4454defbdf5Stb union ip {
4464defbdf5Stb 	union ipv4_choice	ipv4;
4474defbdf5Stb 	union ipv6_choice	ipv6;
4484defbdf5Stb };
4494defbdf5Stb 
4504defbdf5Stb enum safi {
4514defbdf5Stb 	safi_none,
4524defbdf5Stb 	safi_unicast,
4534defbdf5Stb 	safi_multicast,
4544defbdf5Stb };
4554defbdf5Stb 
4564defbdf5Stb struct ip_addr_block {
4574defbdf5Stb 	unsigned int		afi;
4584defbdf5Stb 	enum safi		safi;
4594defbdf5Stb 	enum choice_type	type;
4604defbdf5Stb 	union ip		addr;
4614defbdf5Stb };
4624defbdf5Stb 
4634defbdf5Stb struct build_addr_block_test_data {
4644defbdf5Stb 	char			*description;
4654defbdf5Stb 	struct ip_addr_block	 addrs[16];
4664defbdf5Stb 	char			 der[128];
4674defbdf5Stb 	size_t			 der_len;
4684defbdf5Stb 	int			 is_canonical;
4694defbdf5Stb 	int			 inherits;
4704defbdf5Stb 	unsigned int		 afis[4];
4714defbdf5Stb 	int			 afi_len;
4724defbdf5Stb };
4734defbdf5Stb 
4749dd2bbd1Stb const struct build_addr_block_test_data build_addr_block_tests[] = {
4754defbdf5Stb 	{
4764defbdf5Stb 		.description = "RFC 3779, Appendix B, example 1",
4774defbdf5Stb 		.addrs = {
4784defbdf5Stb 			{
4794defbdf5Stb 				.afi = IANA_AFI_IPV4,
4804defbdf5Stb 				.safi = safi_unicast,
4814defbdf5Stb 				.type = choice_prefix,
4824defbdf5Stb 				.addr.ipv4.prefix = {
4834defbdf5Stb 					.addr = {
4844defbdf5Stb 						10, 0, 32,
4854defbdf5Stb 					},
4864defbdf5Stb 					.addr_len = 3,
4874defbdf5Stb 					.prefix_len = 20,
4884defbdf5Stb 				},
4894defbdf5Stb 			},
4904defbdf5Stb 			{
4914defbdf5Stb 				.afi = IANA_AFI_IPV4,
4924defbdf5Stb 				.safi = safi_unicast,
4934defbdf5Stb 				.type = choice_prefix,
4944defbdf5Stb 				.addr.ipv4.prefix = {
4954defbdf5Stb 					.addr = {
4964defbdf5Stb 						10, 0, 64,
4974defbdf5Stb 					},
4984defbdf5Stb 					.addr_len = 3,
4994defbdf5Stb 					.prefix_len = 24,
5004defbdf5Stb 				},
5014defbdf5Stb 			},
5024defbdf5Stb 			{
5034defbdf5Stb 				.afi = IANA_AFI_IPV4,
5044defbdf5Stb 				.safi = safi_unicast,
5054defbdf5Stb 				.type = choice_prefix,
5064defbdf5Stb 				.addr.ipv4.prefix = {
5074defbdf5Stb 					.addr = {
5084defbdf5Stb 						10, 1,
5094defbdf5Stb 					},
5104defbdf5Stb 					.addr_len = 2,
5114defbdf5Stb 					.prefix_len = 16,
5124defbdf5Stb 				},
5134defbdf5Stb 			},
5144defbdf5Stb 			{
5154defbdf5Stb 				.afi = IANA_AFI_IPV4,
5164defbdf5Stb 				.safi = safi_unicast,
5174defbdf5Stb 				.type = choice_prefix,
5184defbdf5Stb 				.addr.ipv4.prefix = {
5194defbdf5Stb 					.addr = {
5204defbdf5Stb 						10, 2, 48,
5214defbdf5Stb 					},
5224defbdf5Stb 					.addr_len = 3,
5234defbdf5Stb 					.prefix_len = 20,
5244defbdf5Stb 				},
5254defbdf5Stb 			},
5264defbdf5Stb 			{
5274defbdf5Stb 				.afi = IANA_AFI_IPV4,
5284defbdf5Stb 				.safi = safi_unicast,
5294defbdf5Stb 				.type = choice_prefix,
5304defbdf5Stb 				.addr.ipv4.prefix = {
5314defbdf5Stb 					.addr = {
5324defbdf5Stb 						10, 2, 64,
5334defbdf5Stb 					},
5344defbdf5Stb 					.addr_len = 3,
5354defbdf5Stb 					.prefix_len = 24,
5364defbdf5Stb 				},
5374defbdf5Stb 			},
5384defbdf5Stb 			{
5394defbdf5Stb 				.afi = IANA_AFI_IPV4,
5404defbdf5Stb 				.safi = safi_unicast,
5414defbdf5Stb 				.type = choice_prefix,
5424defbdf5Stb 				.addr.ipv4.prefix = {
5434defbdf5Stb 					.addr = {
5444defbdf5Stb 						10, 3,
5454defbdf5Stb 					},
5464defbdf5Stb 					.addr_len = 2,
5474defbdf5Stb 					.prefix_len = 16,
5484defbdf5Stb 				},
5494defbdf5Stb 			},
5504defbdf5Stb 			{
5514defbdf5Stb 				.afi = IANA_AFI_IPV6,
5524defbdf5Stb 				.safi = safi_none,
5534defbdf5Stb 				.type = choice_inherit,
5544defbdf5Stb 			},
5554defbdf5Stb 			{
5564defbdf5Stb 				.type = choice_last,
5574defbdf5Stb 			},
5584defbdf5Stb 		},
5594defbdf5Stb 		.der = {
5604defbdf5Stb 			0x30, 0x35, 0x30, 0x2b, 0x04, 0x03, 0x00, 0x01,
5614defbdf5Stb 			0x01, 0x30, 0x24, 0x03, 0x04, 0x04, 0x0a, 0x00,
5624defbdf5Stb 			0x20, 0x03, 0x04, 0x00, 0x0a, 0x00, 0x40, 0x03,
5634defbdf5Stb 			0x03, 0x00, 0x0a, 0x01, 0x30, 0x0c, 0x03, 0x04,
5644defbdf5Stb 			0x04, 0x0a, 0x02, 0x30, 0x03, 0x04, 0x00, 0x0a,
5654defbdf5Stb 			0x02, 0x40, 0x03, 0x03, 0x00, 0x0a, 0x03, 0x30,
5664defbdf5Stb 			0x06, 0x04, 0x02, 0x00, 0x02, 0x05, 0x00,
5674defbdf5Stb 		},
5684defbdf5Stb 		.der_len = 55,
5694defbdf5Stb 		.is_canonical = 0,
5704defbdf5Stb 		.inherits = 1,
5714defbdf5Stb 		.afis = {
5724defbdf5Stb 			IANA_AFI_IPV4, IANA_AFI_IPV6,
5734defbdf5Stb 		},
5744defbdf5Stb 		.afi_len = 2,
5754defbdf5Stb 	},
5764defbdf5Stb 	{
5774defbdf5Stb 		.description = "RFC 3779, Appendix B, example 1 canonical",
5784defbdf5Stb 		.addrs = {
5794defbdf5Stb 			{
5804defbdf5Stb 				.afi = IANA_AFI_IPV4,
5814defbdf5Stb 				.safi = safi_unicast,
5824defbdf5Stb 				.type = choice_prefix,
5834defbdf5Stb 				.addr.ipv4.prefix = {
5844defbdf5Stb 					.addr = {
5854defbdf5Stb 						10, 0, 32,
5864defbdf5Stb 					},
5874defbdf5Stb 					.addr_len = 3,
5884defbdf5Stb 					.prefix_len = 20,
5894defbdf5Stb 				},
5904defbdf5Stb 			},
5914defbdf5Stb 			{
5924defbdf5Stb 				.afi = IANA_AFI_IPV4,
5934defbdf5Stb 				.safi = safi_unicast,
5944defbdf5Stb 				.type = choice_prefix,
5954defbdf5Stb 				.addr.ipv4.prefix = {
5964defbdf5Stb 					.addr = {
5974defbdf5Stb 						10, 0, 64,
5984defbdf5Stb 					},
5994defbdf5Stb 					.addr_len = 3,
6004defbdf5Stb 					.prefix_len = 24,
6014defbdf5Stb 				},
6024defbdf5Stb 			},
6034defbdf5Stb 			{
6044defbdf5Stb 				.afi = IANA_AFI_IPV4,
6054defbdf5Stb 				.safi = safi_unicast,
6064defbdf5Stb 				.type = choice_prefix,
6074defbdf5Stb 				.addr.ipv4.prefix = {
6084defbdf5Stb 					.addr = {
6094defbdf5Stb 						10, 1,
6104defbdf5Stb 					},
6114defbdf5Stb 					.addr_len = 2,
6124defbdf5Stb 					.prefix_len = 16,
6134defbdf5Stb 				},
6144defbdf5Stb 			},
6154defbdf5Stb 			{
6164defbdf5Stb 				.afi = IANA_AFI_IPV4,
6174defbdf5Stb 				.safi = safi_unicast,
6184defbdf5Stb 				.type = choice_range,
6194defbdf5Stb 				.addr.ipv4.range = {
6204defbdf5Stb 					.min = {
6214defbdf5Stb 						10, 2, 48, 00,
6224defbdf5Stb 					},
6234defbdf5Stb 					.max = {
6244defbdf5Stb 						10, 2, 64, 255,
6254defbdf5Stb 					},
6264defbdf5Stb 				},
6274defbdf5Stb 			},
6284defbdf5Stb 			{
6294defbdf5Stb 				.afi = IANA_AFI_IPV4,
6304defbdf5Stb 				.safi = safi_unicast,
6314defbdf5Stb 				.type = choice_prefix,
6324defbdf5Stb 				.addr.ipv4.prefix = {
6334defbdf5Stb 					.addr = {
6344defbdf5Stb 						10, 3,
6354defbdf5Stb 					},
6364defbdf5Stb 					.addr_len = 2,
6374defbdf5Stb 					.prefix_len = 16,
6384defbdf5Stb 				},
6394defbdf5Stb 			},
6404defbdf5Stb 			{
6414defbdf5Stb 				.afi = IANA_AFI_IPV6,
6424defbdf5Stb 				.safi = safi_none,
6434defbdf5Stb 				.type = choice_inherit,
6444defbdf5Stb 			},
6454defbdf5Stb 			{
6464defbdf5Stb 				.type = choice_last,
6474defbdf5Stb 			},
6484defbdf5Stb 		},
6494defbdf5Stb 		.der = {
6504defbdf5Stb 			0x30, 0x35, 0x30, 0x2b, 0x04, 0x03, 0x00, 0x01,
6514defbdf5Stb 			0x01, 0x30, 0x24, 0x03, 0x04, 0x04, 0x0a, 0x00,
6524defbdf5Stb 			0x20, 0x03, 0x04, 0x00, 0x0a, 0x00, 0x40, 0x03,
6534defbdf5Stb 			0x03, 0x00, 0x0a, 0x01, 0x30, 0x0c, 0x03, 0x04,
6544defbdf5Stb 			0x04, 0x0a, 0x02, 0x30, 0x03, 0x04, 0x00, 0x0a,
6554defbdf5Stb 			0x02, 0x40, 0x03, 0x03, 0x00, 0x0a, 0x03, 0x30,
6564defbdf5Stb 			0x06, 0x04, 0x02, 0x00, 0x02, 0x05, 0x00,
6574defbdf5Stb 		},
6584defbdf5Stb 		.der_len = 55,
6594defbdf5Stb 		.is_canonical = 1,
6604defbdf5Stb 		.inherits = 1,
6614defbdf5Stb 		.afis = {
6624defbdf5Stb 			IANA_AFI_IPV4, IANA_AFI_IPV6,
6634defbdf5Stb 		},
6644defbdf5Stb 		.afi_len = 2,
6654defbdf5Stb 	},
6664defbdf5Stb 	{
6674defbdf5Stb 		.description = "RFC 3779, Appendix B, example 2",
6684defbdf5Stb 		.addrs = {
6694defbdf5Stb 			{
6704defbdf5Stb 				.afi = IANA_AFI_IPV6,
6714defbdf5Stb 				.safi = safi_none,
6724defbdf5Stb 				.type = choice_prefix,
6734defbdf5Stb 				.addr.ipv6.prefix = {
6744defbdf5Stb 					.addr = {
6754defbdf5Stb 						0x20, 0x01, 0x00, 0x00,
6764defbdf5Stb 						0x00, 0x02,
6774defbdf5Stb 					},
6784defbdf5Stb 					.addr_len = 6,
6794defbdf5Stb 					.prefix_len = 48,
6804defbdf5Stb 				},
6814defbdf5Stb 			},
6824defbdf5Stb 			{
6834defbdf5Stb 				.afi = IANA_AFI_IPV4,
6844defbdf5Stb 				.safi = safi_unicast,
6854defbdf5Stb 				.type = choice_prefix,
6864defbdf5Stb 				.addr.ipv4.prefix = {
6874defbdf5Stb 					.addr = {
6884defbdf5Stb 						10,
6894defbdf5Stb 					},
6904defbdf5Stb 					.addr_len = 1,
6914defbdf5Stb 					.prefix_len = 8,
6924defbdf5Stb 				},
6934defbdf5Stb 			},
6944defbdf5Stb 			{
6954defbdf5Stb 				.afi = IANA_AFI_IPV4,
6964defbdf5Stb 				.safi = safi_unicast,
6974defbdf5Stb 				.type = choice_prefix,
6984defbdf5Stb 				.addr.ipv4.prefix = {
6994defbdf5Stb 					.addr = {
7004defbdf5Stb 						172, 16,
7014defbdf5Stb 					},
7024defbdf5Stb 					.addr_len = 2,
7034defbdf5Stb 					.prefix_len = 12,
7044defbdf5Stb 				},
7054defbdf5Stb 			},
7064defbdf5Stb 			{
7074defbdf5Stb 				.afi = IANA_AFI_IPV4,
7084defbdf5Stb 				.safi = safi_multicast,
7094defbdf5Stb 				.type = choice_inherit,
7104defbdf5Stb 			},
7114defbdf5Stb 			{
7124defbdf5Stb 				.type = choice_last,
7134defbdf5Stb 			},
7144defbdf5Stb 		},
7154defbdf5Stb 		.der = {
7164defbdf5Stb 			0x30, 0x2c, 0x30, 0x10, 0x04, 0x03, 0x00, 0x01,
7174defbdf5Stb 			0x01, 0x30, 0x09, 0x03, 0x02, 0x00, 0x0a, 0x03,
7184defbdf5Stb 			0x03, 0x04, 0xac, 0x10, 0x30, 0x07, 0x04, 0x03,
7194defbdf5Stb 			0x00, 0x01, 0x02, 0x05, 0x00, 0x30, 0x0f, 0x04,
7204defbdf5Stb 			0x02, 0x00, 0x02, 0x30, 0x09, 0x03, 0x07, 0x00,
7214defbdf5Stb 			0x20, 0x01, 0x00, 0x00, 0x00, 0x02,
7224defbdf5Stb 		},
7234defbdf5Stb 		.der_len = 46,
7244defbdf5Stb 		.is_canonical = 0,
7254defbdf5Stb 		.inherits = 1,
7264defbdf5Stb 		.afis = {
7274defbdf5Stb 			IANA_AFI_IPV4, IANA_AFI_IPV4,
7284defbdf5Stb 		},
7294defbdf5Stb 		.afi_len = 2,
7304defbdf5Stb 	},
7314defbdf5Stb 	{
7324defbdf5Stb 		.description = "Range should be prefix 127/8",
7334defbdf5Stb 		.addrs = {
7344defbdf5Stb 			{
7354defbdf5Stb 				.afi = IANA_AFI_IPV4,
7364defbdf5Stb 				.safi = safi_none,
7374defbdf5Stb 				.type = choice_range,
7384defbdf5Stb 				.addr.ipv4.range = {
7394defbdf5Stb 					.min = {
7404defbdf5Stb 						127, 0, 0, 0,
7414defbdf5Stb 					},
7424defbdf5Stb 					.max = {
7434defbdf5Stb 						127, 255, 255, 255,
7444defbdf5Stb 					},
7454defbdf5Stb 				},
7464defbdf5Stb 			},
7474defbdf5Stb 			{
7484defbdf5Stb 				.type = choice_last,
7494defbdf5Stb 			},
7504defbdf5Stb 		},
7514defbdf5Stb 		.der = {
7524defbdf5Stb 			0x30, 0x0c, 0x30, 0x0a, 0x04, 0x02, 0x00, 0x01,
7534defbdf5Stb 			0x30, 0x04, 0x03, 0x02, 0x00, 0x7f,
7544defbdf5Stb 		},
7554defbdf5Stb 		.der_len = 14,
7564defbdf5Stb 		.is_canonical = 1,
7574defbdf5Stb 		.inherits = 0,
7584defbdf5Stb 		.afis = {
7594defbdf5Stb 			IANA_AFI_IPV4,
7604defbdf5Stb 		},
7614defbdf5Stb 		.afi_len = 1,
7624defbdf5Stb 	},
7634defbdf5Stb };
7644defbdf5Stb 
7654defbdf5Stb const size_t N_BUILD_ADDR_BLOCK_TESTS =
7664defbdf5Stb     sizeof(build_addr_block_tests) / sizeof(build_addr_block_tests[0]);
7674defbdf5Stb 
7684defbdf5Stb static unsigned int *
addr_block_get_safi(const struct ip_addr_block * addr)7694defbdf5Stb addr_block_get_safi(const struct ip_addr_block *addr)
7704defbdf5Stb {
7714defbdf5Stb 	static unsigned int safi;
7724defbdf5Stb 
7734defbdf5Stb 	switch (addr->safi) {
7744defbdf5Stb 	case safi_none:
7754defbdf5Stb 		return NULL;
7764defbdf5Stb 	case safi_unicast:
7774defbdf5Stb 		safi = 1;
7784defbdf5Stb 		break;
7794defbdf5Stb 	case safi_multicast:
7804defbdf5Stb 		safi = 2;
7814defbdf5Stb 		break;
7824defbdf5Stb 	}
7834defbdf5Stb 
7844defbdf5Stb 	return &safi;
7854defbdf5Stb }
7864defbdf5Stb 
7874defbdf5Stb static int
addr_block_add_ipv4_addr(IPAddrBlocks * block,enum choice_type type,const union ipv4_choice * ipv4,unsigned int * safi)7884defbdf5Stb addr_block_add_ipv4_addr(IPAddrBlocks *block, enum choice_type type,
7899dd2bbd1Stb     const union ipv4_choice *ipv4, unsigned int *safi)
7904defbdf5Stb {
7919dd2bbd1Stb 	unsigned char addr[RAW_ADDRESS_SIZE] = {0};
7929dd2bbd1Stb 	unsigned char min[RAW_ADDRESS_SIZE];
7939dd2bbd1Stb 	unsigned char max[RAW_ADDRESS_SIZE];
7949dd2bbd1Stb 
7954defbdf5Stb 	switch (type) {
7964defbdf5Stb 	case choice_prefix:
7979dd2bbd1Stb 		memcpy(addr, ipv4->prefix.addr, ipv4->prefix.addr_len);
7984defbdf5Stb 		return X509v3_addr_add_prefix(block, IANA_AFI_IPV4, safi,
7999dd2bbd1Stb 		    addr, ipv4->prefix.prefix_len);
8004defbdf5Stb 	case choice_range:
8019dd2bbd1Stb 		memcpy(min, ipv4->range.min, sizeof(ipv4->range.min));
8029dd2bbd1Stb 		memcpy(max, ipv4->range.max, sizeof(ipv4->range.max));
8034defbdf5Stb 		return X509v3_addr_add_range(block, IANA_AFI_IPV4, safi,
8049dd2bbd1Stb 		    min, max);
8054defbdf5Stb 	case choice_inherit:
8064defbdf5Stb 		return X509v3_addr_add_inherit(block, IANA_AFI_IPV4, safi);
8074defbdf5Stb 	case choice_last:
8084defbdf5Stb 	default:
8094defbdf5Stb 		return 0;
8104defbdf5Stb 	}
8114defbdf5Stb }
8124defbdf5Stb 
8134defbdf5Stb static int
addr_block_add_ipv6_addr(IPAddrBlocks * block,enum choice_type type,const union ipv6_choice * ipv6,unsigned int * safi)8144defbdf5Stb addr_block_add_ipv6_addr(IPAddrBlocks *block, enum choice_type type,
8159dd2bbd1Stb     const union ipv6_choice *ipv6, unsigned int *safi)
8164defbdf5Stb {
8179dd2bbd1Stb 	unsigned char addr[RAW_ADDRESS_SIZE] = {0};
8189dd2bbd1Stb 	unsigned char min[RAW_ADDRESS_SIZE];
8199dd2bbd1Stb 	unsigned char max[RAW_ADDRESS_SIZE];
8209dd2bbd1Stb 
8214defbdf5Stb 	switch (type) {
8224defbdf5Stb 	case choice_prefix:
8239dd2bbd1Stb 		memcpy(addr, ipv6->prefix.addr, ipv6->prefix.addr_len);
8244defbdf5Stb 		return X509v3_addr_add_prefix(block, IANA_AFI_IPV6, safi,
8259dd2bbd1Stb 		    addr, ipv6->prefix.prefix_len);
8264defbdf5Stb 	case choice_range:
8279dd2bbd1Stb 		memcpy(min, ipv6->range.min, sizeof(ipv6->range.min));
8289dd2bbd1Stb 		memcpy(max, ipv6->range.max, sizeof(ipv6->range.max));
8294defbdf5Stb 		return X509v3_addr_add_range(block, IANA_AFI_IPV6, safi,
8309dd2bbd1Stb 		    min, max);
8314defbdf5Stb 	case choice_inherit:
8324defbdf5Stb 		return X509v3_addr_add_inherit(block, IANA_AFI_IPV6, safi);
8334defbdf5Stb 	case choice_last:
8344defbdf5Stb 	default:
8354defbdf5Stb 		return 0;
8364defbdf5Stb 	}
8374defbdf5Stb }
8384defbdf5Stb 
8394defbdf5Stb static int
addr_block_add_addrs(IPAddrBlocks * block,const struct ip_addr_block addrs[])8409dd2bbd1Stb addr_block_add_addrs(IPAddrBlocks *block, const struct ip_addr_block addrs[])
8414defbdf5Stb {
8429dd2bbd1Stb 	const struct ip_addr_block	*addr;
8434defbdf5Stb 	unsigned int			*safi;
8444defbdf5Stb 
8454defbdf5Stb 	for (addr = &addrs[0]; addr->type != choice_last; addr++) {
8464defbdf5Stb 		safi = addr_block_get_safi(addr);
8474defbdf5Stb 		switch (addr->afi) {
8484defbdf5Stb 		case IANA_AFI_IPV4:
8494defbdf5Stb 			if (!addr_block_add_ipv4_addr(block, addr->type,
8504defbdf5Stb 			    &addr->addr.ipv4, safi))
8514defbdf5Stb 				return 0;
8524defbdf5Stb 			break;
8534defbdf5Stb 		case IANA_AFI_IPV6:
8544defbdf5Stb 			if (!addr_block_add_ipv6_addr(block, addr->type,
8554defbdf5Stb 			    &addr->addr.ipv6, safi))
8564defbdf5Stb 				return 0;
8574defbdf5Stb 			break;
8584defbdf5Stb 		default:
8594defbdf5Stb 			fprintf(stderr, "%s: corrupt test data", __func__);
8604defbdf5Stb 			exit(1);
8614defbdf5Stb 		}
8624defbdf5Stb 	}
8634defbdf5Stb 
8644defbdf5Stb 	return 1;
8654defbdf5Stb }
8664defbdf5Stb 
8674defbdf5Stb static int
build_addr_block_test(const struct build_addr_block_test_data * test)8689dd2bbd1Stb build_addr_block_test(const struct build_addr_block_test_data *test)
8694defbdf5Stb {
870f911aa70Stb 	IPAddrBlocks *addrs = NULL, *parsed = NULL;
871f911aa70Stb 	const unsigned char *p;
8724defbdf5Stb 	unsigned char *out = NULL;
8734defbdf5Stb 	int out_len;
8744defbdf5Stb 	int i;
8754defbdf5Stb 	int memcmp_failed = 1;
8764defbdf5Stb 	int failed = 1;
8774defbdf5Stb 
8784defbdf5Stb 	if ((addrs = IPAddrBlocks_new()) == NULL)
8794defbdf5Stb 		goto err;
8804defbdf5Stb 
8814defbdf5Stb 	if (!addr_block_add_addrs(addrs, test->addrs))
8824defbdf5Stb 		goto err;
8834defbdf5Stb 
8844defbdf5Stb 	if (X509v3_addr_is_canonical(addrs) != test->is_canonical) {
8854defbdf5Stb 		fprintf(stderr, "%s: \"%s\" X509v3_addr_is_canonical not %d\n",
8864defbdf5Stb 		    __func__, test->description, test->is_canonical);
8874defbdf5Stb 		goto err;
8884defbdf5Stb 	}
8894defbdf5Stb 
8904defbdf5Stb 	if (!X509v3_addr_canonize(addrs)) {
8914defbdf5Stb 		fprintf(stderr, "%s: \"%s\" failed to canonize\n",
8924defbdf5Stb 		    __func__, test->description);
8934defbdf5Stb 		goto err;
8944defbdf5Stb 	}
8954defbdf5Stb 
8964defbdf5Stb 	if (!X509v3_addr_is_canonical(addrs)) {
8974defbdf5Stb 		fprintf(stderr, "%s: \"%s\" canonization wasn't canonical\n",
8984defbdf5Stb 		    __func__, test->description);
8994defbdf5Stb 		goto err;
9004defbdf5Stb 	}
9014defbdf5Stb 
9024defbdf5Stb 	if ((out_len = i2d_IPAddrBlocks(addrs, &out)) <= 0) {
9034defbdf5Stb 		fprintf(stderr, "%s: \"%s\" i2d_IPAddrBlocks failed\n",
9044defbdf5Stb 		    __func__, test->description);
9054defbdf5Stb 		goto err;
9064defbdf5Stb 	}
9074defbdf5Stb 
9084defbdf5Stb 	memcmp_failed = (size_t)out_len != test->der_len;
9094defbdf5Stb 	if (!memcmp_failed)
9104defbdf5Stb 		memcmp_failed = memcmp(out, test->der, test->der_len);
9114defbdf5Stb 	if (memcmp_failed) {
9124defbdf5Stb 		report_hexdump(__func__, test->description, "memcmp DER failed",
9134defbdf5Stb 		    test->der, test->der_len, out, out_len);
9144defbdf5Stb 		goto err;
9154defbdf5Stb 	}
9164defbdf5Stb 
9174defbdf5Stb 	if (X509v3_addr_inherits(addrs) != test->inherits) {
9184defbdf5Stb 		fprintf(stderr, "%s: \"%s\" X509v3_addr_inherits not %d\n",
9194defbdf5Stb 		    __func__, test->description, test->inherits);
9204defbdf5Stb 		goto err;
9214defbdf5Stb 	}
9224defbdf5Stb 
9234defbdf5Stb 	for (i = 0; i < sk_IPAddressFamily_num(addrs) && i < test->afi_len; i++) {
9244defbdf5Stb 		IPAddressFamily *family;
9254defbdf5Stb 		unsigned int afi;
9264defbdf5Stb 
9274defbdf5Stb 		family = sk_IPAddressFamily_value(addrs, i);
9284defbdf5Stb 
9294defbdf5Stb 		if ((afi = X509v3_addr_get_afi(family)) == 0) {
9304defbdf5Stb 			fprintf(stderr, "%s: \"%s\" X509v3_addr_get_afi"
9314defbdf5Stb 			    " failed\n", __func__, test->description);
9324defbdf5Stb 			goto err;
9334defbdf5Stb 		}
9344defbdf5Stb 		if (test->afis[i] != afi){
9354defbdf5Stb 			fprintf(stderr, "%s: \"%s\" afi[%d] mismatch. "
9364defbdf5Stb 			    "want: %u, got: %u\n", __func__,
9374defbdf5Stb 			    test->description, i, test->afis[i], afi);
9384defbdf5Stb 			goto err;
9394defbdf5Stb 		}
9404defbdf5Stb 	}
9414defbdf5Stb 	if (i != test->afi_len) {
9424defbdf5Stb 		fprintf(stderr, "%s: \"%s\" checked %d afis, expected %d\n",
9434defbdf5Stb 		    __func__, test->description, i, test->afi_len);
9444defbdf5Stb 		goto err;
9454defbdf5Stb 	}
9464defbdf5Stb 
947f911aa70Stb 	p = test->der;
948f911aa70Stb 	if ((parsed = d2i_IPAddrBlocks(NULL, &p, test->der_len)) == NULL) {
949f911aa70Stb 		fprintf(stderr, "%s: \"%s\" d2i_IPAddrBlocks failed\n",
950f911aa70Stb 		    __func__, test->description);
951f911aa70Stb 		goto err;
952f911aa70Stb 	}
953f911aa70Stb 	if (!X509v3_addr_is_canonical(parsed)) {
954f911aa70Stb 		fprintf(stderr, "%s: \"%s\" parsed AddrBlocks isn't canonical\n",
955f911aa70Stb 		    __func__, test->description);
956f911aa70Stb 		goto err;
957f911aa70Stb 	}
958f911aa70Stb 	/* Can't compare IPAddrBlocks with inheritance. */
959f911aa70Stb 	if (!X509v3_addr_inherits(addrs) && !X509v3_addr_inherits(parsed)) {
960f911aa70Stb 		if (!X509v3_addr_subset(addrs, parsed)) {
961f911aa70Stb 			fprintf(stderr, "%s: \"%s\" addrs not subset of parsed\n",
962f911aa70Stb 			    __func__, test->description);
963f911aa70Stb 		}
964f911aa70Stb 		if (!X509v3_addr_subset(parsed, addrs)) {
965f911aa70Stb 			fprintf(stderr, "%s: \"%s\" parsed not subset of addrs\n",
966f911aa70Stb 			    __func__, test->description);
967f911aa70Stb 		}
968f911aa70Stb 	}
969f911aa70Stb 
9704defbdf5Stb 	failed = 0;
9714defbdf5Stb 
9724defbdf5Stb  err:
9734defbdf5Stb 	IPAddrBlocks_free(addrs);
974f911aa70Stb 	IPAddrBlocks_free(parsed);
9754defbdf5Stb 	free(out);
9764defbdf5Stb 
9774defbdf5Stb 	return failed;
9784defbdf5Stb }
9794defbdf5Stb 
9804defbdf5Stb static int
run_IPAddrBlock_tests(void)9814defbdf5Stb run_IPAddrBlock_tests(void)
9824defbdf5Stb {
9834defbdf5Stb 	size_t i;
9844defbdf5Stb 	int failed = 0;
9854defbdf5Stb 
9864defbdf5Stb 	for (i = 0; i < N_BUILD_ADDR_BLOCK_TESTS; i++)
9874defbdf5Stb 		failed |= build_addr_block_test(&build_addr_block_tests[i]);
9884defbdf5Stb 
9894defbdf5Stb 	return failed;
9904defbdf5Stb }
9914defbdf5Stb 
9924defbdf5Stb struct asid_or_range {
9934defbdf5Stb 	int			 type;
9944defbdf5Stb 	int			 inherit;
9954defbdf5Stb 	const unsigned char	*min;
9964defbdf5Stb 	const unsigned char	*max;
9974defbdf5Stb };
9984defbdf5Stb 
9994defbdf5Stb struct ASIdentifiers_build_test {
10004defbdf5Stb 	const char		*description;
10014defbdf5Stb 	int			 should_build;
10024defbdf5Stb 	int			 inherits;
10034defbdf5Stb 	int			 canonical;
10044defbdf5Stb 	int			 should_canonize;
10054defbdf5Stb 	struct asid_or_range	 delegations[8];
10064defbdf5Stb 	const unsigned char	 der[128];
10074defbdf5Stb 	size_t			 der_len;
10084defbdf5Stb };
10094defbdf5Stb 
10104defbdf5Stb /* Sentinel value used for marking the end of the delegations table. */
10114defbdf5Stb #define V3_ASID_END -1
10124defbdf5Stb 
10134defbdf5Stb const struct ASIdentifiers_build_test ASIdentifiers_build_data[] = {
10144defbdf5Stb 	{
10154defbdf5Stb 		.description = "RFC 3779, Appendix C",
10164defbdf5Stb 		.should_build = 1,
10174defbdf5Stb 		.inherits = 1,
10184defbdf5Stb 		.canonical = 1,
10194defbdf5Stb 		.delegations = {
10204defbdf5Stb 			{
10214defbdf5Stb 				.type = V3_ASID_ASNUM,
10224defbdf5Stb 				.inherit = 0,
10234defbdf5Stb 				.min = "135",
10244defbdf5Stb 				.max = NULL,
10254defbdf5Stb 			},
10264defbdf5Stb 			{
10274defbdf5Stb 				.type = V3_ASID_ASNUM,
10284defbdf5Stb 				.inherit = 0,
10294defbdf5Stb 				.min = "3000",
10304defbdf5Stb 				.max = "3999",
10314defbdf5Stb 			},
10324defbdf5Stb 			{
10334defbdf5Stb 				.type = V3_ASID_ASNUM,
10344defbdf5Stb 				.inherit = 0,
10354defbdf5Stb 				.min = "5001",
10364defbdf5Stb 				.max = NULL,
10374defbdf5Stb 			},
10384defbdf5Stb 			{
10394defbdf5Stb 				.type = V3_ASID_RDI,
10404defbdf5Stb 				.inherit = 1,
10414defbdf5Stb 				.min = NULL,
10424defbdf5Stb 				.max = NULL,
10434defbdf5Stb 			},
10444defbdf5Stb 			{
10454defbdf5Stb 				.type = V3_ASID_END,
10464defbdf5Stb 			},
10474defbdf5Stb 		},
10484defbdf5Stb 		.der = {
10494defbdf5Stb 			0x30, 0x1a, 0xa0, 0x14, 0x30, 0x12, 0x02, 0x02,
10504defbdf5Stb 			0x00, 0x87, 0x30, 0x08, 0x02, 0x02, 0x0b, 0xb8,
10514defbdf5Stb 			0x02, 0x02, 0x0f, 0x9f, 0x02, 0x02, 0x13, 0x89,
10524defbdf5Stb 			0xa1, 0x02, 0x05, 0x00,
10534defbdf5Stb 		},
10544defbdf5Stb 		.der_len = 28,
10554defbdf5Stb 	},
10564defbdf5Stb 	{
10574defbdf5Stb 		.description = "RFC 3779, Appendix C without rdi",
10584defbdf5Stb 		.should_build = 1,
10594defbdf5Stb 		.inherits = 0,
10604defbdf5Stb 		.canonical = 1,
10614defbdf5Stb 		.delegations = {
10624defbdf5Stb 			{
10634defbdf5Stb 				.type = V3_ASID_ASNUM,
10644defbdf5Stb 				.inherit = 0,
10654defbdf5Stb 				.min = "135",
10664defbdf5Stb 				.max = NULL,
10674defbdf5Stb 			},
10684defbdf5Stb 			{
10694defbdf5Stb 				.type = V3_ASID_ASNUM,
10704defbdf5Stb 				.inherit = 0,
10714defbdf5Stb 				.min = "3000",
10724defbdf5Stb 				.max = "3999",
10734defbdf5Stb 			},
10744defbdf5Stb 			{
10754defbdf5Stb 				.type = V3_ASID_ASNUM,
10764defbdf5Stb 				.inherit = 0,
10774defbdf5Stb 				.min = "5001",
10784defbdf5Stb 				.max = NULL,
10794defbdf5Stb 			},
10804defbdf5Stb 			{
10814defbdf5Stb 				.type = V3_ASID_END,
10824defbdf5Stb 			},
10834defbdf5Stb 		},
10844defbdf5Stb 		.der = {
10854defbdf5Stb 			0x30, 0x16, 0xa0, 0x14, 0x30, 0x12, 0x02, 0x02,
10864defbdf5Stb 			0x00, 0x87, 0x30, 0x08, 0x02, 0x02, 0x0b, 0xb8,
10874defbdf5Stb 			0x02, 0x02, 0x0f, 0x9f, 0x02, 0x02, 0x13, 0x89,
10884defbdf5Stb 		},
10894defbdf5Stb 		.der_len = 24,
10904defbdf5Stb 	},
10914defbdf5Stb 	{
10924defbdf5Stb 		.description = "RFC 3779, Appendix C variant",
10934defbdf5Stb 		.should_build = 1,
10944defbdf5Stb 		.inherits = 0,
10954defbdf5Stb 		.canonical = 1,
10964defbdf5Stb 		.delegations = {
10974defbdf5Stb 			{
10984defbdf5Stb 				.type = V3_ASID_ASNUM,
10994defbdf5Stb 				.inherit = 0,
11004defbdf5Stb 				.min = "135",
11014defbdf5Stb 				.max = NULL,
11024defbdf5Stb 			},
11034defbdf5Stb 			{
11044defbdf5Stb 				.type = V3_ASID_ASNUM,
11054defbdf5Stb 				.inherit = 0,
11064defbdf5Stb 				.min = "3000",
11074defbdf5Stb 				.max = "3999",
11084defbdf5Stb 			},
11094defbdf5Stb 			{
11104defbdf5Stb 				.type = V3_ASID_ASNUM,
11114defbdf5Stb 				.inherit = 0,
11124defbdf5Stb 				.min = "5001",
11134defbdf5Stb 				.max = NULL,
11144defbdf5Stb 			},
11154defbdf5Stb 			{
11164defbdf5Stb 				.type = V3_ASID_RDI,
11174defbdf5Stb 				.inherit = 0,
11184defbdf5Stb 				.min = "135",
11194defbdf5Stb 				.max = NULL,
11204defbdf5Stb 			},
11214defbdf5Stb 			{
11224defbdf5Stb 				.type = V3_ASID_RDI,
11234defbdf5Stb 				.inherit = 0,
11244defbdf5Stb 				.min = "3000",
11254defbdf5Stb 				.max = "3999",
11264defbdf5Stb 			},
11274defbdf5Stb 			{
11284defbdf5Stb 				.type = V3_ASID_RDI,
11294defbdf5Stb 				.inherit = 0,
11304defbdf5Stb 				.min = "5001",
11314defbdf5Stb 				.max = NULL,
11324defbdf5Stb 			},
11334defbdf5Stb 			{
11344defbdf5Stb 				.type = V3_ASID_END,
11354defbdf5Stb 			},
11364defbdf5Stb 		},
11374defbdf5Stb 		.der = {
11384defbdf5Stb 			0x30, 0x2c, 0xa0, 0x14, 0x30, 0x12, 0x02, 0x02,
11394defbdf5Stb 			0x00, 0x87, 0x30, 0x08, 0x02, 0x02, 0x0b, 0xb8,
11404defbdf5Stb 			0x02, 0x02, 0x0f, 0x9f, 0x02, 0x02, 0x13, 0x89,
11414defbdf5Stb 			0xa1, 0x14, 0x30, 0x12, 0x02, 0x02, 0x00, 0x87,
11424defbdf5Stb 			0x30, 0x08, 0x02, 0x02, 0x0b, 0xb8, 0x02, 0x02,
11434defbdf5Stb 			0x0f, 0x9f, 0x02, 0x02, 0x13, 0x89,
11444defbdf5Stb 		},
11454defbdf5Stb 		.der_len = 46,
11464defbdf5Stb 	},
11474defbdf5Stb 	{
11484defbdf5Stb 		.description = "inherit only",
11494defbdf5Stb 		.should_build = 1,
11504defbdf5Stb 		.inherits = 1,
11514defbdf5Stb 		.canonical = 1,
11524defbdf5Stb 		.delegations = {
11534defbdf5Stb 			{
11544defbdf5Stb 				.type = V3_ASID_ASNUM,
11554defbdf5Stb 				.inherit = 1,
11564defbdf5Stb 			},
11574defbdf5Stb 			{
11584defbdf5Stb 				.type = V3_ASID_RDI,
11594defbdf5Stb 				.inherit = 1,
11604defbdf5Stb 			},
11614defbdf5Stb 			{
11624defbdf5Stb 				.type = V3_ASID_END,
11634defbdf5Stb 			},
11644defbdf5Stb 		},
11654defbdf5Stb 		.der = {
11664defbdf5Stb 			0x30, 0x08, 0xa0, 0x02, 0x05, 0x00, 0xa1, 0x02,
11674defbdf5Stb 			0x05, 0x00,
11684defbdf5Stb 		},
11694defbdf5Stb 		.der_len = 10,
11704defbdf5Stb 	},
11714defbdf5Stb 	{
11724defbdf5Stb 		.description = "adjacent unsorted ranges are merged",
11734defbdf5Stb 		.should_build = 1,
11744defbdf5Stb 		.inherits = 0,
11754defbdf5Stb 		.canonical = 0,
11764defbdf5Stb 		.should_canonize = 1,
11774defbdf5Stb 		.delegations = {
11784defbdf5Stb 			{
11794defbdf5Stb 				.type = V3_ASID_RDI,
11804defbdf5Stb 				.inherit = 0,
11814defbdf5Stb 				.min = "27",
11824defbdf5Stb 				.max = NULL,
11834defbdf5Stb 			},
11844defbdf5Stb 			{
11854defbdf5Stb 				.type = V3_ASID_RDI,
11864defbdf5Stb 				.inherit = 0,
11874defbdf5Stb 				.min = "28",
11884defbdf5Stb 				.max = "57",
11894defbdf5Stb 			},
11904defbdf5Stb 			{
11914defbdf5Stb 				.type = V3_ASID_RDI,
11924defbdf5Stb 				.inherit = 0,
11934defbdf5Stb 				.min = "66",
11944defbdf5Stb 				.max = "68",
11954defbdf5Stb 			},
11964defbdf5Stb 			{
11974defbdf5Stb 				.type = V3_ASID_RDI,
11984defbdf5Stb 				.inherit = 0,
11994defbdf5Stb 				.min = "58",
12004defbdf5Stb 				.max = "63",
12014defbdf5Stb 			},
12024defbdf5Stb 			{
12034defbdf5Stb 				.type = V3_ASID_RDI,
12044defbdf5Stb 				.inherit = 0,
12054defbdf5Stb 				.min = "64",
12064defbdf5Stb 				.max = NULL,
12074defbdf5Stb 			},
12084defbdf5Stb 			{
12094defbdf5Stb 				.type = V3_ASID_END,
12104defbdf5Stb 			},
12114defbdf5Stb 		},
12124defbdf5Stb 		.der = {
12134defbdf5Stb 			0x30, 0x14, 0xa1, 0x12, 0x30, 0x10, 0x30, 0x06,
12144defbdf5Stb 			0x02, 0x01, 0x1b, 0x02, 0x01, 0x40, 0x30, 0x06,
12154defbdf5Stb 			0x02, 0x01, 0x42, 0x02, 0x01, 0x44,
12164defbdf5Stb 		},
12174defbdf5Stb 		.der_len = 22,
12184defbdf5Stb 	},
12194defbdf5Stb 	{
12204defbdf5Stb 		.description = "range of length 0",
12214defbdf5Stb 		.should_build = 1,
12224defbdf5Stb 		.inherits = 1,
12234defbdf5Stb 		.canonical = 1,
12244defbdf5Stb 		.should_canonize = 1,
12254defbdf5Stb 		.delegations = {
12264defbdf5Stb 			{
12274defbdf5Stb 				.type = V3_ASID_RDI,
12284defbdf5Stb 				.inherit = 0,
12294defbdf5Stb 				.min = "27",
12304defbdf5Stb 				.max = "27",
12314defbdf5Stb 			},
12324defbdf5Stb 			{
12334defbdf5Stb 				.type = V3_ASID_ASNUM,
12344defbdf5Stb 				.inherit = 1,
12354defbdf5Stb 			},
12364defbdf5Stb 			{
12374defbdf5Stb 				.type = V3_ASID_END,
12384defbdf5Stb 			},
12394defbdf5Stb 		},
12404defbdf5Stb 		.der = {
12414defbdf5Stb 			0x30, 0x10, 0xa0, 0x02, 0x05, 0x00, 0xa1, 0x0a,
12424defbdf5Stb 			0x30, 0x08, 0x30, 0x06, 0x02, 0x01, 0x1b, 0x02,
12434defbdf5Stb 			0x01, 0x1b,
12444defbdf5Stb 		},
12454defbdf5Stb 		.der_len = 18,
12464defbdf5Stb 	},
12474defbdf5Stb 	{
12484defbdf5Stb 		.description = "reversed range doesn't canonize",
12494defbdf5Stb 		.should_build = 1,
12504defbdf5Stb 		.inherits = 0,
12514defbdf5Stb 		.canonical = 0,
12524defbdf5Stb 		.should_canonize = 0,
12534defbdf5Stb 		.delegations = {
12544defbdf5Stb 			{
12554defbdf5Stb 				.type = V3_ASID_ASNUM,
12564defbdf5Stb 				.inherit = 0,
12574defbdf5Stb 				.min = "57",
12584defbdf5Stb 				.max = "42",
12594defbdf5Stb 			},
12604defbdf5Stb 			{
12614defbdf5Stb 				.type = V3_ASID_END,
12624defbdf5Stb 			},
12634defbdf5Stb 		},
12644defbdf5Stb 	},
12654defbdf5Stb 	{
12664defbdf5Stb 		.description = "overlapping ranges don't canonize",
12674defbdf5Stb 		.should_build = 1,
12684defbdf5Stb 		.inherits = 0,
12694defbdf5Stb 		.canonical = 0,
12704defbdf5Stb 		.should_canonize = 0,
12714defbdf5Stb 		.delegations = {
12724defbdf5Stb 			{
12734defbdf5Stb 				.type = V3_ASID_ASNUM,
12744defbdf5Stb 				.inherit = 0,
12754defbdf5Stb 				.min = "42",
12764defbdf5Stb 				.max = "57",
12774defbdf5Stb 			},
12784defbdf5Stb 			{
12794defbdf5Stb 				.type = V3_ASID_ASNUM,
12804defbdf5Stb 				.inherit = 0,
12814defbdf5Stb 				.min = "57",
12824defbdf5Stb 				.max = "60",
12834defbdf5Stb 			},
12844defbdf5Stb 			{
12854defbdf5Stb 				.type = V3_ASID_END,
12864defbdf5Stb 			},
12874defbdf5Stb 		},
12884defbdf5Stb 	},
12894defbdf5Stb 	{
12904defbdf5Stb 		.description = "reversed interior range doesn't canonize",
12914defbdf5Stb 		.should_build = 1,
12924defbdf5Stb 		.inherits = 0,
12934defbdf5Stb 		.canonical = 0,
12944defbdf5Stb 		.should_canonize = 0,
12954defbdf5Stb 		.delegations = {
12964defbdf5Stb 			{
12974defbdf5Stb 				.type = V3_ASID_ASNUM,
12984defbdf5Stb 				.inherit = 0,
12994defbdf5Stb 				.min = "1",
13004defbdf5Stb 				.max = "2",
13014defbdf5Stb 			},
13024defbdf5Stb 			{
13034defbdf5Stb 				.type = V3_ASID_ASNUM,
13044defbdf5Stb 				.inherit = 0,
13054defbdf5Stb 				.min = "57",
13064defbdf5Stb 				.max = "42",
13074defbdf5Stb 			},
13084defbdf5Stb 			{
13094defbdf5Stb 				.type = V3_ASID_ASNUM,
13104defbdf5Stb 				.inherit = 0,
13114defbdf5Stb 				.min = "65523",
13124defbdf5Stb 				.max = "65535",
13134defbdf5Stb 			},
13144defbdf5Stb 			{
13154defbdf5Stb 				.type = V3_ASID_END,
13164defbdf5Stb 			},
13174defbdf5Stb 		},
13184defbdf5Stb 	},
13194defbdf5Stb 	{
13204defbdf5Stb 		.description = "can't inherit and add AS ids",
13214defbdf5Stb 		.should_build = 0,
13224defbdf5Stb 		.inherits = 0,
13234defbdf5Stb 		.canonical = 0,
13244defbdf5Stb 		.should_canonize = 0,
13254defbdf5Stb 		.delegations = {
13264defbdf5Stb 			{
13274defbdf5Stb 				.type = V3_ASID_ASNUM,
13284defbdf5Stb 				.inherit = 0,
13294defbdf5Stb 				.min = "1",
13304defbdf5Stb 				.max = "2",
13314defbdf5Stb 			},
13324defbdf5Stb 			{
13334defbdf5Stb 				.type = V3_ASID_ASNUM,
13344defbdf5Stb 				.inherit = 1,
13354defbdf5Stb 			},
13364defbdf5Stb 			{
13374defbdf5Stb 				.type = V3_ASID_END,
13384defbdf5Stb 			},
13394defbdf5Stb 		},
13404defbdf5Stb 	},
13414defbdf5Stb 	{
13424defbdf5Stb 		.description = "can't inherit and add rdis",
13434defbdf5Stb 		.should_build = 0,
13444defbdf5Stb 		.inherits = 0,
13454defbdf5Stb 		.canonical = 0,
13464defbdf5Stb 		.should_canonize = 0,
13474defbdf5Stb 		.delegations = {
13484defbdf5Stb 			{
13494defbdf5Stb 				.type = V3_ASID_RDI,
13504defbdf5Stb 				.inherit = 0,
13514defbdf5Stb 				.min = "1",
13524defbdf5Stb 				.max = "2",
13534defbdf5Stb 			},
13544defbdf5Stb 			{
13554defbdf5Stb 				.type = V3_ASID_RDI,
13564defbdf5Stb 				.inherit = 1,
13574defbdf5Stb 			},
13584defbdf5Stb 			{
13594defbdf5Stb 				.type = V3_ASID_END,
13604defbdf5Stb 			},
13614defbdf5Stb 		},
13624defbdf5Stb 	},
13634defbdf5Stb };
13644defbdf5Stb 
13654defbdf5Stb const size_t N_ASIDENTIFIERS_BUILD_TESTS =
13664defbdf5Stb     sizeof(ASIdentifiers_build_data) / sizeof(ASIdentifiers_build_data[0]);
13674defbdf5Stb 
13684defbdf5Stb static int
add_as_delegation(ASIdentifiers * asid,const struct asid_or_range * delegation)13694defbdf5Stb add_as_delegation(ASIdentifiers *asid, const struct asid_or_range *delegation)
13704defbdf5Stb {
13714defbdf5Stb 	ASN1_INTEGER	*min = NULL, *max = NULL;
13724defbdf5Stb 	int		 ret = 0;
13734defbdf5Stb 
13744defbdf5Stb 	if (delegation->inherit)
13754defbdf5Stb 		return X509v3_asid_add_inherit(asid, delegation->type);
13764defbdf5Stb 
13774defbdf5Stb 	if ((min = s2i_ASN1_INTEGER(NULL, delegation->min)) == NULL)
13784defbdf5Stb 		goto err;
13794defbdf5Stb 
13804defbdf5Stb 	if (delegation->max != NULL) {
13814defbdf5Stb 		if ((max = s2i_ASN1_INTEGER(NULL, delegation->max)) == NULL)
13824defbdf5Stb 			goto err;
13834defbdf5Stb 	}
13844defbdf5Stb 
13854defbdf5Stb 	if (!X509v3_asid_add_id_or_range(asid, delegation->type, min, max))
13864defbdf5Stb 		goto err;
13874defbdf5Stb 	min = NULL;
13884defbdf5Stb 	max = NULL;
13894defbdf5Stb 
13904defbdf5Stb 	ret = 1;
13914defbdf5Stb 
13924defbdf5Stb  err:
13934defbdf5Stb 	ASN1_INTEGER_free(min);
13944defbdf5Stb 	ASN1_INTEGER_free(max);
13954defbdf5Stb 
13964defbdf5Stb 	return ret;
13974defbdf5Stb }
13984defbdf5Stb 
13994defbdf5Stb static ASIdentifiers *
build_asid(const struct asid_or_range delegations[])14004defbdf5Stb build_asid(const struct asid_or_range delegations[])
14014defbdf5Stb {
14024defbdf5Stb 	ASIdentifiers			*asid = NULL;
14034defbdf5Stb 	const struct asid_or_range	*delegation;
14044defbdf5Stb 
14054defbdf5Stb 	if ((asid = ASIdentifiers_new()) == NULL)
14064defbdf5Stb 		goto err;
14074defbdf5Stb 
14084defbdf5Stb 	for (delegation = &delegations[0]; delegation->type != V3_ASID_END;
14094defbdf5Stb 	    delegation++) {
14104defbdf5Stb 		if (!add_as_delegation(asid, delegation))
14114defbdf5Stb 			goto err;
14124defbdf5Stb 	}
14134defbdf5Stb 
14144defbdf5Stb 	return asid;
14154defbdf5Stb 
14164defbdf5Stb  err:
14174defbdf5Stb 	ASIdentifiers_free(asid);
14184defbdf5Stb 	return NULL;
14194defbdf5Stb }
14204defbdf5Stb 
14214defbdf5Stb static int
build_asid_test(const struct ASIdentifiers_build_test * test)14224defbdf5Stb build_asid_test(const struct ASIdentifiers_build_test *test)
14234defbdf5Stb {
14244defbdf5Stb 	ASIdentifiers	*asid = NULL;
14254defbdf5Stb 	unsigned char	*out = NULL;
14264defbdf5Stb 	int		 out_len;
14274defbdf5Stb 	int		 memcmp_failed = 1;
14284defbdf5Stb 	int		 failed = 1;
14294defbdf5Stb 
14304defbdf5Stb 	if ((asid = build_asid(test->delegations)) == NULL) {
14314defbdf5Stb 		if (!test->should_build) {
14324defbdf5Stb 			failed = 0;
14334defbdf5Stb 			return failed;
14344defbdf5Stb 		}
14354defbdf5Stb 		fprintf(stderr, "%s: \"%s\" failed to build\n", __func__,
14364defbdf5Stb 		    test->description);
14374defbdf5Stb 		return failed;
14384defbdf5Stb 	}
14394defbdf5Stb 
14404defbdf5Stb 	if (!test->canonical) {
14414defbdf5Stb 		if (X509v3_asid_is_canonical(asid)) {
14424defbdf5Stb 			fprintf(stderr, "%s: \"%s\" shouldn't be canonical\n",
14434defbdf5Stb 			    __func__, test->description);
14444defbdf5Stb 			goto err;
14454defbdf5Stb 		}
14464defbdf5Stb 		if (X509v3_asid_canonize(asid) != test->should_canonize) {
14474defbdf5Stb 			fprintf(stderr, "%s: \"%s\" failed to canonize\n",
14484defbdf5Stb 			    __func__, test->description);
14494defbdf5Stb 			goto err;
14504defbdf5Stb 		}
14514defbdf5Stb 		if (!test->should_canonize) {
14524defbdf5Stb 			failed = 0;
14534defbdf5Stb 			goto err;
14544defbdf5Stb 		}
14554defbdf5Stb 	}
14564defbdf5Stb 
14574defbdf5Stb 	/*
14584defbdf5Stb 	 * Verify that asid is in canonical form before converting it to DER.
14594defbdf5Stb 	 */
14604defbdf5Stb 	if (!X509v3_asid_is_canonical(asid)) {
14614defbdf5Stb 		fprintf(stderr, "%s: asid is not canonical\n", __func__);
14624defbdf5Stb 		goto err;
14634defbdf5Stb 	}
14644defbdf5Stb 
14654defbdf5Stb 	/*
14664defbdf5Stb 	 * Convert asid to DER and check that it matches expectations
14674defbdf5Stb 	 */
14684defbdf5Stb 	out = NULL;
14694defbdf5Stb 	if ((out_len = i2d_ASIdentifiers(asid, &out)) <= 0) {
14704defbdf5Stb 		fprintf(stderr, "%s: \"%s\" i2d_ASIdentifiers failed\n",
14714defbdf5Stb 		    __func__, test->description);
14724defbdf5Stb 		goto err;
14734defbdf5Stb 	}
14744defbdf5Stb 
14754defbdf5Stb 
14764defbdf5Stb 	memcmp_failed = (size_t)out_len != test->der_len;
14774defbdf5Stb 	if (!memcmp_failed)
14784defbdf5Stb 		memcmp_failed = memcmp(out, test->der, test->der_len);
14794defbdf5Stb 	if (memcmp_failed) {
14804defbdf5Stb 		report_hexdump(__func__, test->description, "memcmp DER failed",
14814defbdf5Stb 		    test->der, test->der_len, out, out_len);
14824defbdf5Stb 		goto err;
14834defbdf5Stb 	}
14844defbdf5Stb 
14854defbdf5Stb 	/*
14864defbdf5Stb 	 * Verify that asid inherits as expected
14874defbdf5Stb 	 */
14884defbdf5Stb 	if (X509v3_asid_inherits(asid) != test->inherits) {
14894defbdf5Stb 		fprintf(stderr, "%s: \"%s\" unexpected asid inherit %d\n",
14904defbdf5Stb 		    __func__, test->description, test->inherits);
14914defbdf5Stb 		goto err;
14924defbdf5Stb 	}
14934defbdf5Stb 
14944defbdf5Stb 	failed = 0;
14954defbdf5Stb 
14964defbdf5Stb  err:
14974defbdf5Stb 	free(out);
14984defbdf5Stb 	ASIdentifiers_free(asid);
14994defbdf5Stb 
15004defbdf5Stb 	return failed;
15014defbdf5Stb }
15024defbdf5Stb 
15034defbdf5Stb static int
run_ASIdentifiers_build_test(void)15044defbdf5Stb run_ASIdentifiers_build_test(void)
15054defbdf5Stb {
15064defbdf5Stb 	size_t i;
15074defbdf5Stb 	int failed = 0;
15084defbdf5Stb 
15094defbdf5Stb 	for (i = 0; i < N_ASIDENTIFIERS_BUILD_TESTS; i++)
15104defbdf5Stb 		failed |= build_asid_test(&ASIdentifiers_build_data[i]);
15114defbdf5Stb 
15124defbdf5Stb 	return failed;
15134defbdf5Stb }
15144defbdf5Stb 
15154defbdf5Stb struct ASIdentifiers_subset_test {
15164defbdf5Stb 	const char		*description;
15174defbdf5Stb 	struct asid_or_range	 delegationsA[8];
15184defbdf5Stb 	struct asid_or_range	 delegationsB[8];
15194defbdf5Stb 	int			 is_subset;
15204defbdf5Stb 	int			 is_subset_if_canonized;
15214defbdf5Stb };
15224defbdf5Stb 
15234defbdf5Stb const struct ASIdentifiers_subset_test ASIdentifiers_subset_data[] = {
15244defbdf5Stb 	{
15254defbdf5Stb 		.description = "simple subset relation",
15264defbdf5Stb 		.delegationsA = {
15274defbdf5Stb 			{
15284defbdf5Stb 				.type = V3_ASID_ASNUM,
15294defbdf5Stb 				.inherit = 0,
15304defbdf5Stb 				.min = "2",
15314defbdf5Stb 				.max = "4",
15324defbdf5Stb 			},
15334defbdf5Stb 			{
15344defbdf5Stb 				.type = V3_ASID_RDI,
15354defbdf5Stb 				.inherit = 0,
15364defbdf5Stb 				.min = "2",
15374defbdf5Stb 				.max = NULL,
15384defbdf5Stb 			},
15394defbdf5Stb 			{
15404defbdf5Stb 				.type = V3_ASID_END,
15414defbdf5Stb 			},
15424defbdf5Stb 		},
15434defbdf5Stb 		.delegationsB = {
15444defbdf5Stb 			{
15454defbdf5Stb 				.type = V3_ASID_ASNUM,
15464defbdf5Stb 				.inherit = 0,
15474defbdf5Stb 				.min = "1",
15484defbdf5Stb 				.max = "5",
15494defbdf5Stb 			},
15504defbdf5Stb 			{
15514defbdf5Stb 				.type = V3_ASID_RDI,
15524defbdf5Stb 				.inherit = 0,
15534defbdf5Stb 				.min = "1",
15544defbdf5Stb 				.max = "5",
15554defbdf5Stb 			},
15564defbdf5Stb 			{
15574defbdf5Stb 				.type = V3_ASID_END,
15584defbdf5Stb 			},
15594defbdf5Stb 		},
15604defbdf5Stb 		.is_subset = 1,
15614defbdf5Stb 		.is_subset_if_canonized = 1,
15624defbdf5Stb 	},
15631a2187c2Stb 	{
15641a2187c2Stb 		.description = "only asnums",
15651a2187c2Stb 		.delegationsA = {
15661a2187c2Stb 			{
15671a2187c2Stb 				.type = V3_ASID_ASNUM,
15681a2187c2Stb 				.inherit = 0,
15691a2187c2Stb 				.min = "2",
15701a2187c2Stb 				.max = "4",
15711a2187c2Stb 			},
15721a2187c2Stb 			{
15731a2187c2Stb 				.type = V3_ASID_END,
15741a2187c2Stb 			},
15751a2187c2Stb 		},
15761a2187c2Stb 		.delegationsB = {
15771a2187c2Stb 			{
15781a2187c2Stb 				.type = V3_ASID_ASNUM,
15791a2187c2Stb 				.inherit = 0,
15801a2187c2Stb 				.min = "1",
15811a2187c2Stb 				.max = "5",
15821a2187c2Stb 			},
15831a2187c2Stb 			{
15841a2187c2Stb 				.type = V3_ASID_END,
15851a2187c2Stb 			},
15861a2187c2Stb 		},
15871a2187c2Stb 		.is_subset = 1,
15881a2187c2Stb 		.is_subset_if_canonized = 1,
15891a2187c2Stb 	},
15901a2187c2Stb 	{
15911a2187c2Stb 		.description = "only rdis",
15921a2187c2Stb 		.delegationsA = {
15931a2187c2Stb 			{
15941a2187c2Stb 				.type = V3_ASID_RDI,
15951a2187c2Stb 				.inherit = 0,
15961a2187c2Stb 				.min = "2",
15971a2187c2Stb 				.max = NULL,
15981a2187c2Stb 			},
15991a2187c2Stb 			{
16001a2187c2Stb 				.type = V3_ASID_END,
16011a2187c2Stb 			},
16021a2187c2Stb 		},
16031a2187c2Stb 		.delegationsB = {
16041a2187c2Stb 			{
16051a2187c2Stb 				.type = V3_ASID_RDI,
16061a2187c2Stb 				.inherit = 0,
16071a2187c2Stb 				.min = "1",
16081a2187c2Stb 				.max = "5",
16091a2187c2Stb 			},
16101a2187c2Stb 			{
16111a2187c2Stb 				.type = V3_ASID_END,
16121a2187c2Stb 			},
16131a2187c2Stb 		},
16141a2187c2Stb 		.is_subset = 1,
16151a2187c2Stb 		.is_subset_if_canonized = 1,
16161a2187c2Stb 	},
16171a2187c2Stb 	{
16181a2187c2Stb 		.description = "child only has asnums, parent only has rdis",
16191a2187c2Stb 		.delegationsA = {
16201a2187c2Stb 			{
16211a2187c2Stb 				.type = V3_ASID_ASNUM,
16221a2187c2Stb 				.inherit = 0,
16231a2187c2Stb 				.min = "2",
16241a2187c2Stb 				.max = "4",
16251a2187c2Stb 			},
16261a2187c2Stb 			{
16271a2187c2Stb 				.type = V3_ASID_END,
16281a2187c2Stb 			},
16291a2187c2Stb 		},
16301a2187c2Stb 		.delegationsB = {
16311a2187c2Stb 			{
16321a2187c2Stb 				.type = V3_ASID_RDI,
16331a2187c2Stb 				.inherit = 0,
16341a2187c2Stb 				.min = "1",
16351a2187c2Stb 				.max = "5",
16361a2187c2Stb 			},
16371a2187c2Stb 			{
16381a2187c2Stb 				.type = V3_ASID_END,
16391a2187c2Stb 			},
16401a2187c2Stb 		},
16411a2187c2Stb 		.is_subset = 0,
16421a2187c2Stb 		.is_subset_if_canonized = 0,
16431a2187c2Stb 	},
16441a2187c2Stb 	{
16451a2187c2Stb 		.description = "child only has rdis, parent only has asnums",
16461a2187c2Stb 		.delegationsA = {
16471a2187c2Stb 			{
16481a2187c2Stb 				.type = V3_ASID_RDI,
16491a2187c2Stb 				.inherit = 0,
16501a2187c2Stb 				.min = "2",
16511a2187c2Stb 				.max = "4",
16521a2187c2Stb 			},
16531a2187c2Stb 			{
16541a2187c2Stb 				.type = V3_ASID_END,
16551a2187c2Stb 			},
16561a2187c2Stb 		},
16571a2187c2Stb 		.delegationsB = {
16581a2187c2Stb 			{
16591a2187c2Stb 				.type = V3_ASID_ASNUM,
16601a2187c2Stb 				.inherit = 0,
16611a2187c2Stb 				.min = "1",
16621a2187c2Stb 				.max = "5",
16631a2187c2Stb 			},
16641a2187c2Stb 			{
16651a2187c2Stb 				.type = V3_ASID_END,
16661a2187c2Stb 			},
16671a2187c2Stb 		},
16681a2187c2Stb 		.is_subset = 0,
16691a2187c2Stb 		.is_subset_if_canonized = 0,
16701a2187c2Stb 	},
16711a2187c2Stb 	{
16721a2187c2Stb 		.description = "child only has rdis, parent has both",
16731a2187c2Stb 		.delegationsA = {
16741a2187c2Stb 			{
16751a2187c2Stb 				.type = V3_ASID_RDI,
16761a2187c2Stb 				.inherit = 0,
16771a2187c2Stb 				.min = "2",
16781a2187c2Stb 				.max = "4",
16791a2187c2Stb 			},
16801a2187c2Stb 			{
16811a2187c2Stb 				.type = V3_ASID_END,
16821a2187c2Stb 			},
16831a2187c2Stb 		},
16841a2187c2Stb 		.delegationsB = {
16851a2187c2Stb 			{
16861a2187c2Stb 				.type = V3_ASID_ASNUM,
16871a2187c2Stb 				.inherit = 0,
16881a2187c2Stb 				.min = "1",
16891a2187c2Stb 				.max = "5",
16901a2187c2Stb 			},
16911a2187c2Stb 			{
16921a2187c2Stb 				.type = V3_ASID_RDI,
16931a2187c2Stb 				.inherit = 0,
16941a2187c2Stb 				.min = "1",
16951a2187c2Stb 				.max = "5",
16961a2187c2Stb 			},
16971a2187c2Stb 			{
16981a2187c2Stb 				.type = V3_ASID_END,
16991a2187c2Stb 			},
17001a2187c2Stb 		},
17011a2187c2Stb 		.is_subset = 1,
17021a2187c2Stb 		.is_subset_if_canonized = 1,
17031a2187c2Stb 	},
17044defbdf5Stb 	{
17054defbdf5Stb 		.description = "subset relation only after canonization",
17064defbdf5Stb 		.delegationsA = {
17074defbdf5Stb 			{
17084defbdf5Stb 				.type = V3_ASID_ASNUM,
17094defbdf5Stb 				.inherit = 0,
17104defbdf5Stb 				.min = "2",
17114defbdf5Stb 				.max = NULL,
17124defbdf5Stb 			},
17134defbdf5Stb 			{
17144defbdf5Stb 				.type = V3_ASID_ASNUM,
17154defbdf5Stb 				.inherit = 0,
17164defbdf5Stb 				.min = "3",
17174defbdf5Stb 				.max = "4",
17184defbdf5Stb 			},
17194defbdf5Stb 			{
17204defbdf5Stb 				.type = V3_ASID_RDI,
17214defbdf5Stb 				.inherit = 0,
17224defbdf5Stb 				.min = "2",
17234defbdf5Stb 				.max = NULL,
17244defbdf5Stb 			},
17254defbdf5Stb 			{
17264defbdf5Stb 				.type = V3_ASID_END,
17274defbdf5Stb 			},
17284defbdf5Stb 		},
17294defbdf5Stb 		.delegationsB = {
17304defbdf5Stb 			{
17314defbdf5Stb 				.type = V3_ASID_ASNUM,
17324defbdf5Stb 				.inherit = 0,
17334defbdf5Stb 				.min = "1",
17344defbdf5Stb 				.max = "3",
17354defbdf5Stb 			},
17364defbdf5Stb 			{
17374defbdf5Stb 				.type = V3_ASID_ASNUM,
17384defbdf5Stb 				.inherit = 0,
17394defbdf5Stb 				.min = "4",
17404defbdf5Stb 				.max = "5",
17414defbdf5Stb 			},
17424defbdf5Stb 			{
17434defbdf5Stb 				.type = V3_ASID_RDI,
17444defbdf5Stb 				.inherit = 0,
17454defbdf5Stb 				.min = "1",
17464defbdf5Stb 				.max = "5",
17474defbdf5Stb 			},
17484defbdf5Stb 			{
17494defbdf5Stb 				.type = V3_ASID_END,
17504defbdf5Stb 			},
17514defbdf5Stb 		},
17524defbdf5Stb 		.is_subset = 0,
17534defbdf5Stb 		.is_subset_if_canonized = 1,
17544defbdf5Stb 	},
17554defbdf5Stb 	{
17564defbdf5Stb 		.description = "no subset if A inherits",
17574defbdf5Stb 		.delegationsA = {
17584defbdf5Stb 			{
17594defbdf5Stb 				.type = V3_ASID_ASNUM,
17604defbdf5Stb 				.inherit = 0,
17614defbdf5Stb 				.min = "2",
17624defbdf5Stb 				.max = NULL,
17634defbdf5Stb 			},
17644defbdf5Stb 			{
17654defbdf5Stb 				.type = V3_ASID_ASNUM,
17664defbdf5Stb 				.inherit = 0,
17674defbdf5Stb 				.min = "3",
17684defbdf5Stb 				.max = "4",
17694defbdf5Stb 			},
17704defbdf5Stb 			{
17714defbdf5Stb 				.type = V3_ASID_RDI,
17724defbdf5Stb 				.inherit = 1,
17734defbdf5Stb 			},
17744defbdf5Stb 			{
17754defbdf5Stb 				.type = V3_ASID_END,
17764defbdf5Stb 			},
17774defbdf5Stb 		},
17784defbdf5Stb 		.delegationsB = {
17794defbdf5Stb 			{
17804defbdf5Stb 				.type = V3_ASID_ASNUM,
17814defbdf5Stb 				.inherit = 0,
17824defbdf5Stb 				.min = "1",
17834defbdf5Stb 				.max = "3",
17844defbdf5Stb 			},
17854defbdf5Stb 			{
17864defbdf5Stb 				.type = V3_ASID_ASNUM,
17874defbdf5Stb 				.inherit = 0,
17884defbdf5Stb 				.min = "4",
17894defbdf5Stb 				.max = "5",
17904defbdf5Stb 			},
17914defbdf5Stb 			{
17924defbdf5Stb 				.type = V3_ASID_RDI,
17934defbdf5Stb 				.inherit = 0,
17944defbdf5Stb 				.min = "1",
17954defbdf5Stb 				.max = "5",
17964defbdf5Stb 			},
17974defbdf5Stb 			{
17984defbdf5Stb 				.type = V3_ASID_END,
17994defbdf5Stb 			},
18004defbdf5Stb 		},
18014defbdf5Stb 		.is_subset = 0,
18024defbdf5Stb 		.is_subset_if_canonized = 0,
18034defbdf5Stb 	},
18044defbdf5Stb 	{
18054defbdf5Stb 		.description = "no subset if B inherits",
18064defbdf5Stb 		.delegationsA = {
18074defbdf5Stb 			{
18084defbdf5Stb 				.type = V3_ASID_ASNUM,
18094defbdf5Stb 				.inherit = 0,
18104defbdf5Stb 				.min = "2",
18114defbdf5Stb 				.max = NULL,
18124defbdf5Stb 			},
18134defbdf5Stb 			{
18144defbdf5Stb 				.type = V3_ASID_ASNUM,
18154defbdf5Stb 				.inherit = 0,
18164defbdf5Stb 				.min = "3",
18174defbdf5Stb 				.max = "4",
18184defbdf5Stb 			},
18194defbdf5Stb 			{
18204defbdf5Stb 				.type = V3_ASID_RDI,
18214defbdf5Stb 				.inherit = 0,
18224defbdf5Stb 				.min = "5",
18234defbdf5Stb 				.max = NULL,
18244defbdf5Stb 			},
18254defbdf5Stb 			{
18264defbdf5Stb 				.type = V3_ASID_END,
18274defbdf5Stb 			},
18284defbdf5Stb 		},
18294defbdf5Stb 		.delegationsB = {
18304defbdf5Stb 			{
18314defbdf5Stb 				.type = V3_ASID_ASNUM,
18324defbdf5Stb 				.inherit = 0,
18334defbdf5Stb 				.min = "1",
18344defbdf5Stb 				.max = "3",
18354defbdf5Stb 			},
18364defbdf5Stb 			{
18374defbdf5Stb 				.type = V3_ASID_ASNUM,
18384defbdf5Stb 				.inherit = 0,
18394defbdf5Stb 				.min = "4",
18404defbdf5Stb 				.max = "5",
18414defbdf5Stb 			},
18424defbdf5Stb 			{
18434defbdf5Stb 				.type = V3_ASID_RDI,
18444defbdf5Stb 				.inherit = 1,
18454defbdf5Stb 			},
18464defbdf5Stb 			{
18474defbdf5Stb 				.type = V3_ASID_END,
18484defbdf5Stb 			},
18494defbdf5Stb 		},
18504defbdf5Stb 		.is_subset = 0,
18514defbdf5Stb 		.is_subset_if_canonized = 0,
18524defbdf5Stb 	},
18534defbdf5Stb 	{
18544defbdf5Stb 		.description = "no subset if both inherit",
18554defbdf5Stb 		.delegationsA = {
18564defbdf5Stb 			{
18574defbdf5Stb 				.type = V3_ASID_ASNUM,
18584defbdf5Stb 				.inherit = 0,
18594defbdf5Stb 				.min = "2",
18604defbdf5Stb 				.max = NULL,
18614defbdf5Stb 			},
18624defbdf5Stb 			{
18634defbdf5Stb 				.type = V3_ASID_ASNUM,
18644defbdf5Stb 				.inherit = 0,
18654defbdf5Stb 				.min = "3",
18664defbdf5Stb 				.max = "4",
18674defbdf5Stb 			},
18684defbdf5Stb 			{
18694defbdf5Stb 				.type = V3_ASID_RDI,
18704defbdf5Stb 				.inherit = 1,
18714defbdf5Stb 			},
18724defbdf5Stb 			{
18734defbdf5Stb 				.type = V3_ASID_END,
18744defbdf5Stb 			},
18754defbdf5Stb 		},
18764defbdf5Stb 		.delegationsB = {
18774defbdf5Stb 			{
18784defbdf5Stb 				.type = V3_ASID_ASNUM,
18794defbdf5Stb 				.inherit = 0,
18804defbdf5Stb 				.min = "1",
18814defbdf5Stb 				.max = "3",
18824defbdf5Stb 			},
18834defbdf5Stb 			{
18844defbdf5Stb 				.type = V3_ASID_ASNUM,
18854defbdf5Stb 				.inherit = 0,
18864defbdf5Stb 				.min = "4",
18874defbdf5Stb 				.max = "5",
18884defbdf5Stb 			},
18894defbdf5Stb 			{
18904defbdf5Stb 				.type = V3_ASID_RDI,
18914defbdf5Stb 				.inherit = 1,
18924defbdf5Stb 			},
18934defbdf5Stb 			{
18944defbdf5Stb 				.type = V3_ASID_END,
18954defbdf5Stb 			},
18964defbdf5Stb 		},
18974defbdf5Stb 		.is_subset = 0,
18984defbdf5Stb 		.is_subset_if_canonized = 0,
18994defbdf5Stb 	},
19004defbdf5Stb };
19014defbdf5Stb 
19024defbdf5Stb const size_t N_ASIDENTIFIERS_SUBSET_TESTS =
1903e84a01fbStb     sizeof(ASIdentifiers_subset_data) / sizeof(ASIdentifiers_subset_data[0]);
19044defbdf5Stb 
19054defbdf5Stb static int
asid_subset_test(const struct ASIdentifiers_subset_test * test)19064defbdf5Stb asid_subset_test(const struct ASIdentifiers_subset_test *test)
19074defbdf5Stb {
19084defbdf5Stb 	ASIdentifiers	*asidA = NULL, *asidB = NULL;
19094defbdf5Stb 	int		 failed = 0;
19104defbdf5Stb 
19114defbdf5Stb 	if ((asidA = build_asid(test->delegationsA)) == NULL)
19124defbdf5Stb 		goto err;
19134defbdf5Stb 	if ((asidB = build_asid(test->delegationsB)) == NULL)
19144defbdf5Stb 		goto err;
19154defbdf5Stb 
19164defbdf5Stb 	if (X509v3_asid_subset(asidA, asidB) != test->is_subset) {
19174defbdf5Stb 		fprintf(stderr, "%s: \"%s\" X509v3_asid_subset failed\n",
19184defbdf5Stb 		    __func__, test->description);
19194defbdf5Stb 		failed = 1;
19204defbdf5Stb 	}
19214defbdf5Stb 
19224defbdf5Stb 	if (!test->is_subset) {
19234defbdf5Stb 		if (!X509v3_asid_canonize(asidA))
19244defbdf5Stb 			goto err;
19254defbdf5Stb 		if (!X509v3_asid_canonize(asidB))
19264defbdf5Stb 			goto err;
19274defbdf5Stb 		if (X509v3_asid_subset(asidA, asidB) !=
19284defbdf5Stb 		    test->is_subset_if_canonized) {
19294defbdf5Stb 			fprintf(stderr, "%s: \"%s\" canonized subset failed\n",
19304defbdf5Stb 			    __func__, test->description);
19314defbdf5Stb 			failed = 1;
19324defbdf5Stb 		}
19334defbdf5Stb 	}
19344defbdf5Stb 
19354defbdf5Stb  err:
19364defbdf5Stb 	ASIdentifiers_free(asidA);
19374defbdf5Stb 	ASIdentifiers_free(asidB);
19384defbdf5Stb 
19394defbdf5Stb 	return failed;
19404defbdf5Stb }
19414defbdf5Stb 
19424defbdf5Stb static int
run_ASIdentifiers_subset_test(void)19434defbdf5Stb run_ASIdentifiers_subset_test(void)
19444defbdf5Stb {
19454defbdf5Stb 	size_t i;
19464defbdf5Stb 	int failed = 0;
19474defbdf5Stb 
19484defbdf5Stb 	for (i = 0; i < N_ASIDENTIFIERS_SUBSET_TESTS; i++)
19494defbdf5Stb 		failed |= asid_subset_test(&ASIdentifiers_subset_data[i]);
19504defbdf5Stb 
19514defbdf5Stb 	return failed;
19524defbdf5Stb }
19534defbdf5Stb 
19544defbdf5Stb int
main(void)19554defbdf5Stb main(void)
19564defbdf5Stb {
19574defbdf5Stb 	int failed = 0;
19584defbdf5Stb 
19594defbdf5Stb 	failed |= run_IPAddressOrRange_tests();
19604defbdf5Stb 	failed |= run_IPAddrBlock_tests();
19614defbdf5Stb 	failed |= run_ASIdentifiers_build_test();
19624defbdf5Stb 	failed |= run_ASIdentifiers_subset_test();
19634defbdf5Stb 
19644defbdf5Stb 	return failed;
19654defbdf5Stb }
1966