summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2021-12-24 03:00:37 +0000
committertb <>2021-12-24 03:00:37 +0000
commite9b5d4af374b8c6dcad775059c5243b684e88357 (patch)
treeebbbe941ba9cb12e20db55c8bec72195636fd4b6
parentef7405266983f910fc9afc376bbebd84ec03e0b0 (diff)
downloadopenbsd-e9b5d4af374b8c6dcad775059c5243b684e88357.tar.gz
openbsd-e9b5d4af374b8c6dcad775059c5243b684e88357.tar.bz2
openbsd-e9b5d4af374b8c6dcad775059c5243b684e88357.zip
Add initial test coverage for RFC 3779 code.
This exercises the code paths that are reached from the validator and also tests that the public API behaves as expected. There is a lot more that could be done here, but this test is already big enough. Missing are tests for X509v3_{addr,asid}_validate_{path,resource_set}() themselves. One test failure is ignored and will be fixed in the near future when a bad logic error in range_should_be_prefix() is fixed. A consequence of this bug is that we will currently accept and generate DER that doesn't conform to RFC 3779.
-rw-r--r--src/regress/lib/libcrypto/x509/rfc3779/Makefile11
-rw-r--r--src/regress/lib/libcrypto/x509/rfc3779/rfc3779.c1793
2 files changed, 1804 insertions, 0 deletions
diff --git a/src/regress/lib/libcrypto/x509/rfc3779/Makefile b/src/regress/lib/libcrypto/x509/rfc3779/Makefile
new file mode 100644
index 0000000000..3709471c8f
--- /dev/null
+++ b/src/regress/lib/libcrypto/x509/rfc3779/Makefile
@@ -0,0 +1,11 @@
1# $OpenBSD: Makefile,v 1.1 2021/12/24 03:00:37 tb Exp $
2
3.include "../../Makefile.inc"
4
5PROG= rfc3779
6LDADD= ${CRYPTO_INT}
7DPADD= ${LIBCRYPTO}
8WARNINGS= Yes
9CFLAGS+= -DLIBRESSL_INTERNAL -Werror -g -O0
10
11.include <bsd.regress.mk>
diff --git a/src/regress/lib/libcrypto/x509/rfc3779/rfc3779.c b/src/regress/lib/libcrypto/x509/rfc3779/rfc3779.c
new file mode 100644
index 0000000000..65bbf2294b
--- /dev/null
+++ b/src/regress/lib/libcrypto/x509/rfc3779/rfc3779.c
@@ -0,0 +1,1793 @@
1/* $OpenBSD: rfc3779.c,v 1.1 2021/12/24 03:00:37 tb Exp $ */
2/*
3 * Copyright (c) 2021 Theo Buehler <tb@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <stdio.h>
19#include <string.h>
20
21#include <openssl/asn1.h>
22#include <openssl/asn1t.h>
23#include <openssl/x509v3.h>
24
25#define RAW_ADDRESS_SIZE 16
26
27static void
28hexdump(const unsigned char *buf, size_t len)
29{
30 size_t i;
31
32 for (i = 1; i <= len; i++)
33 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
34
35 if (len % 8)
36 fprintf(stderr, "\n");
37}
38
39static void
40report_hexdump(const char *func, const char *description, const char *msg,
41 const unsigned char *want, size_t want_len,
42 const unsigned char *got, size_t got_len)
43{
44 fprintf(stderr, "%s: \"%s\" %s\nwant:\n", func, description, msg);
45 hexdump(want, want_len);
46 fprintf(stderr, "got:\n");
47 hexdump(got, got_len);
48}
49
50static int
51afi_size(int afi)
52{
53 switch (afi) {
54 case IANA_AFI_IPV4:
55 return 4;
56 case IANA_AFI_IPV6:
57 return 16;
58 }
59 return 0;
60}
61
62struct IPAddressOrRange_test {
63 const char *description;
64 const uint8_t der[32];
65 size_t der_len;
66 unsigned afi;
67 const uint8_t min[RAW_ADDRESS_SIZE];
68 const uint8_t max[RAW_ADDRESS_SIZE];
69};
70
71const struct IPAddressOrRange_test IPAddressOrRange_test_data[] = {
72 /* Examples from RFC 3779, section 2.1.1 */
73 {
74 .description = "address 10.5.0.4",
75 .der = {
76 0x03, 0x05, 0x00, 0x0a, 0x05, 0x00, 0x04,
77 },
78 .der_len = 7,
79 .afi = IANA_AFI_IPV4,
80 .min = {
81 0x0a, 0x05, 0x00, 0x04,
82 },
83 .max = {
84 0x0a, 0x05, 0x00, 0x04,
85 }
86 },
87 {
88 .description = "prefix 10.5.0/23",
89 .der = {
90 0x03, 0x04, 0x01, 0x0a, 0x05, 0x00,
91 },
92 .der_len = 6,
93 .afi = IANA_AFI_IPV4,
94 .min = {
95 0x0a, 0x05, 0x00, 0x00,
96 },
97 .max = {
98 0x0a, 0x05, 0x01, 0xff,
99 }
100 },
101 {
102 .description = "address 2001:0:200:3::1",
103 .der = {
104 0x03, 0x11, 0x00, 0x20, 0x01, 0x00, 0x00, 0x02,
105 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x01,
107 },
108 .der_len = 19,
109 .afi = IANA_AFI_IPV6,
110 .min = {
111 0x20, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03,
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
113 },
114 .max = {
115 0x20, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03,
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
117 },
118 },
119 {
120 .description = "prefix 2001:0:200/39",
121 .der = {
122 0x03, 0x06, 0x01, 0x20, 0x01, 0x00, 0x00, 0x02,
123 },
124 .der_len = 8,
125 .afi = IANA_AFI_IPV6,
126 .min = {
127 0x20, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 },
130 .max = {
131 0x20, 0x01, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff,
132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
133 },
134 },
135
136 /* Examples from RFC 3779, Section 2.1.2 */
137 {
138 .description = "prefix 10.5.0/23 as a range",
139 .der = {
140 /* Sequence */
141 0x30, 0x0b,
142 /* 10.5.0.0 */
143 0x03, 0x03, 0x00, 0x0a, 0x05,
144 /* 10.5.1.255 */
145 0x03, 0x04, 0x01, 0x0a, 0x05, 0x00,
146 },
147 .der_len = 13,
148 .afi = IANA_AFI_IPV4,
149 .min = {
150 0x0a, 0x05, 0x00, 0x00,
151 },
152 .max = {
153 0x0a, 0x05, 0x01, 0xff,
154 }
155 },
156 {
157 .description = "prefix 2001:0:200/39 as a range",
158 .der = {
159 /* Sequence */
160 0x30, 0x10,
161 /* 2001:0:200:: */
162 0x03, 0x06, 0x01, 0x20, 0x01, 0x00, 0x00, 0x02,
163 /* 2001:0:3ff:ffff:ffff:ffff:ffff:ffff */
164 0x03, 0x06, 0x02, 0x20, 0x01, 0x00, 0x00, 0x00,
165 },
166 .der_len = 18,
167 .afi = IANA_AFI_IPV6,
168 .min = {
169 0x20, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 },
172 .max = {
173 0x20, 0x01, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff,
174 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
175 }
176 },
177 {
178 .description = "prefix 0/0",
179 .der = {
180 0x03, 0x01, 0x00,
181 },
182 .der_len = 3,
183 .afi = IANA_AFI_IPV4,
184 .min = {
185 0x00, 0x00, 0x00, 0x00,
186 },
187 .max = {
188 0xff, 0xff, 0xff, 0xff,
189 }
190 },
191 {
192 .description = "prefix 10.64/12",
193 .der = {
194 0x03, 0x03, 0x04, 0x0a, 0x40,
195 },
196 .der_len = 5,
197 .afi = IANA_AFI_IPV4,
198 .min = {
199 0x0a, 0x40, 0x00, 0x00,
200 },
201 .max = {
202 0x0a, 0x4f, 0xff, 0xff,
203 },
204 },
205 {
206 .description = "prefix 10.64/20",
207 .der = {
208 0x03, 0x04, 0x04, 0x0a, 0x40, 0x00,
209 },
210 .der_len = 6,
211 .afi = IANA_AFI_IPV4,
212 .min = {
213 0x0a, 0x40, 0x00, 0x00,
214 },
215 .max = {
216 0x0a, 0x40, 0x0f, 0xff,
217 },
218 },
219};
220
221const size_t N_IPADDRESSORRANGE_TESTS =
222 sizeof(IPAddressOrRange_test_data) / sizeof(IPAddressOrRange_test_data[0]);
223
224static int
225test_IPAddressOrRange(const struct IPAddressOrRange_test *test)
226{
227 IPAddressOrRange *aor;
228 const unsigned char *p;
229 unsigned char min[RAW_ADDRESS_SIZE] = {0}, max[RAW_ADDRESS_SIZE] = {0};
230 unsigned char *out = NULL;
231 int out_len;
232 int afi_len;
233 int memcmp_failed = 0;
234 int failed = 1;
235
236 /*
237 * First, decode DER from the test case.
238 */
239
240 p = &test->der[0];
241 if ((aor = d2i_IPAddressOrRange(NULL, &p, test->der_len)) == NULL) {
242 fprintf(stderr, "%s: \"%s\" d2i_IPAddressOrRange failed\n",
243 __func__, test->description);
244 goto err;
245 }
246
247 /*
248 * Now extract minimum and maximum from the parsed range.
249 */
250
251 afi_len = afi_size(test->afi);
252
253 if (X509v3_addr_get_range(aor, test->afi, min, max, sizeof min) !=
254 afi_len) {
255 fprintf(stderr, "%s: \"%s\" X509v3_addr_get_range failed\n",
256 __func__, test->description);
257 goto err;
258 }
259
260 /*
261 * Check that min and max match expectations.
262 */
263
264 if (memcmp(min, test->min, afi_len) != 0) {
265 memcmp_failed |= 1;
266 report_hexdump(__func__, test->description, "memcmp min failed",
267 test->min, afi_len, min, afi_len);
268 }
269 if (memcmp(max, test->max, afi_len) != 0) {
270 memcmp_failed |= 1;
271 report_hexdump(__func__, test->description, "memcmp max failed",
272 test->max, afi_len, max, afi_len);
273 }
274 if (memcmp_failed)
275 goto err;
276
277 /*
278 * Now turn the parsed IPAddressOrRange back into DER and check that
279 * it matches the DER in the test case.
280 */
281
282 out = NULL;
283 if ((out_len = i2d_IPAddressOrRange(aor, &out)) <= 0) {
284 fprintf(stderr, "%s: \"%s\" i2d_IPAddressOrRange failed\n",
285 __func__, test->description);
286 goto err;
287 }
288
289 memcmp_failed = (size_t)out_len != test->der_len;
290 if (!memcmp_failed)
291 memcmp_failed = memcmp(test->der, out, out_len);
292
293 if (memcmp_failed) {
294 report_hexdump(__func__, test->description, "memcmp DER failed",
295 test->der, test->der_len, out, out_len);
296 goto err;
297 }
298
299 failed = 0;
300 err:
301 IPAddressOrRange_free(aor);
302 free(out);
303
304 return failed;
305}
306
307static int
308run_IPAddressOrRange_tests(void)
309{
310 size_t i;
311 int failed = 0;
312
313 for (i = 0; i < N_IPADDRESSORRANGE_TESTS; i++)
314 failed |=
315 test_IPAddressOrRange(&IPAddressOrRange_test_data[i]);
316
317 return failed;
318}
319
320/*
321 * XXX: These should really be part of the public API...
322 */
323static IPAddrBlocks *IPAddrBlocks_new(void);
324static void IPAddrBlocks_free(IPAddrBlocks *addr);
325static __unused IPAddrBlocks *d2i_IPAddrBlocks(IPAddrBlocks **addrs,
326 const unsigned char **in, long len);
327static int i2d_IPAddrBlocks(IPAddrBlocks *addrs, unsigned char **out);
328
329static IPAddrBlocks *
330IPAddrBlocks_new(void)
331{
332 IPAddrBlocks *addrs;
333
334 /*
335 * XXX The comparison function IPAddressFamily_cmp() isn't public.
336 * Start with the default and exploit a side effect of the lovely API
337 * which helpfully sets the correct function in a few places. Let's
338 * use the cheapest and easiest to reach one.
339 */
340 if ((addrs = sk_IPAddressFamily_new_null()) == NULL)
341 return NULL;
342 if (!X509v3_addr_canonize(addrs)) {
343 IPAddrBlocks_free(addrs);
344 return NULL;
345 }
346
347 return addrs;
348}
349
350static void
351IPAddrBlocks_free(IPAddrBlocks *addr)
352{
353 sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free);
354}
355
356/*
357 * We want {d2i,i2d}_IPAddrBlocks() to play with the DER of the extension.
358 * These don't exist, so we have to implement them ourselves. IPAddrBlocks_it
359 * isn't public, so we need to fetch it from the library. We cache it in a
360 * static variable to avoid the cost of a binary search through all supported
361 * extensions on each call.
362 */
363
364static const ASN1_ITEM_EXP *
365get_IPAddrBlocks_it(void)
366{
367 static const ASN1_ITEM_EXP *my_IPAddrBlocks_it;
368 const X509V3_EXT_METHOD *v3_addr;
369
370 if (my_IPAddrBlocks_it != NULL)
371 return my_IPAddrBlocks_it;
372
373 if ((v3_addr = X509V3_EXT_get_nid(NID_sbgp_ipAddrBlock)) == NULL) {
374 fprintf(stderr, "could not get v3_addr\n");
375 return NULL;
376 }
377
378 my_IPAddrBlocks_it = v3_addr->it;
379
380 return my_IPAddrBlocks_it;
381}
382
383static __unused IPAddrBlocks *
384d2i_IPAddrBlocks(IPAddrBlocks **addrs, const unsigned char **in, long len)
385{
386 const ASN1_ITEM_EXP *my_IPAddrBlocks_it = get_IPAddrBlocks_it();
387
388 if (my_IPAddrBlocks_it == NULL)
389 return NULL;
390
391 return (IPAddrBlocks *)ASN1_item_d2i((ASN1_VALUE **)addrs, in, len,
392 my_IPAddrBlocks_it);
393}
394
395static int
396i2d_IPAddrBlocks(IPAddrBlocks *addrs, unsigned char **out)
397{
398 const ASN1_ITEM_EXP *my_IPAddrBlocks_it = get_IPAddrBlocks_it();
399
400 if (my_IPAddrBlocks_it == NULL)
401 return -1;
402
403 return ASN1_item_i2d((ASN1_VALUE *)addrs, out, my_IPAddrBlocks_it);
404}
405
406struct ipv4_prefix {
407 unsigned char addr[4];
408 size_t addr_len;
409 size_t prefix_len;
410};
411
412struct ipv4_range {
413 unsigned char min[4];
414 unsigned char max[4];
415};
416
417union ipv4_choice {
418 struct ipv4_prefix prefix;
419 struct ipv4_range range;
420};
421
422struct ipv6_prefix {
423 unsigned char addr[16];
424 size_t addr_len;
425 size_t prefix_len;
426};
427
428struct ipv6_range {
429 unsigned char min[16];
430 unsigned char max[16];
431};
432
433union ipv6_choice {
434 struct ipv6_prefix prefix;
435 struct ipv6_range range;
436};
437
438enum choice_type {
439 choice_prefix,
440 choice_range,
441 choice_inherit,
442 choice_last,
443};
444
445union ip {
446 union ipv4_choice ipv4;
447 union ipv6_choice ipv6;
448};
449
450enum safi {
451 safi_none,
452 safi_unicast,
453 safi_multicast,
454};
455
456struct ip_addr_block {
457 unsigned int afi;
458 enum safi safi;
459 enum choice_type type;
460 union ip addr;
461};
462
463struct build_addr_block_test_data {
464 char *description;
465 struct ip_addr_block addrs[16];
466 char der[128];
467 size_t der_len;
468 int memcmp_fails;
469 int is_canonical;
470 int inherits;
471 unsigned int afis[4];
472 int afi_len;
473};
474
475struct build_addr_block_test_data build_addr_block_tests[] = {
476 {
477 .description = "RFC 3779, Appendix B, example 1",
478 .addrs = {
479 {
480 .afi = IANA_AFI_IPV4,
481 .safi = safi_unicast,
482 .type = choice_prefix,
483 .addr.ipv4.prefix = {
484 .addr = {
485 10, 0, 32,
486 },
487 .addr_len = 3,
488 .prefix_len = 20,
489 },
490 },
491 {
492 .afi = IANA_AFI_IPV4,
493 .safi = safi_unicast,
494 .type = choice_prefix,
495 .addr.ipv4.prefix = {
496 .addr = {
497 10, 0, 64,
498 },
499 .addr_len = 3,
500 .prefix_len = 24,
501 },
502 },
503 {
504 .afi = IANA_AFI_IPV4,
505 .safi = safi_unicast,
506 .type = choice_prefix,
507 .addr.ipv4.prefix = {
508 .addr = {
509 10, 1,
510 },
511 .addr_len = 2,
512 .prefix_len = 16,
513 },
514 },
515 {
516 .afi = IANA_AFI_IPV4,
517 .safi = safi_unicast,
518 .type = choice_prefix,
519 .addr.ipv4.prefix = {
520 .addr = {
521 10, 2, 48,
522 },
523 .addr_len = 3,
524 .prefix_len = 20,
525 },
526 },
527 {
528 .afi = IANA_AFI_IPV4,
529 .safi = safi_unicast,
530 .type = choice_prefix,
531 .addr.ipv4.prefix = {
532 .addr = {
533 10, 2, 64,
534 },
535 .addr_len = 3,
536 .prefix_len = 24,
537 },
538 },
539 {
540 .afi = IANA_AFI_IPV4,
541 .safi = safi_unicast,
542 .type = choice_prefix,
543 .addr.ipv4.prefix = {
544 .addr = {
545 10, 3,
546 },
547 .addr_len = 2,
548 .prefix_len = 16,
549 },
550 },
551 {
552 .afi = IANA_AFI_IPV6,
553 .safi = safi_none,
554 .type = choice_inherit,
555 },
556 {
557 .type = choice_last,
558 },
559 },
560 .der = {
561 0x30, 0x35, 0x30, 0x2b, 0x04, 0x03, 0x00, 0x01,
562 0x01, 0x30, 0x24, 0x03, 0x04, 0x04, 0x0a, 0x00,
563 0x20, 0x03, 0x04, 0x00, 0x0a, 0x00, 0x40, 0x03,
564 0x03, 0x00, 0x0a, 0x01, 0x30, 0x0c, 0x03, 0x04,
565 0x04, 0x0a, 0x02, 0x30, 0x03, 0x04, 0x00, 0x0a,
566 0x02, 0x40, 0x03, 0x03, 0x00, 0x0a, 0x03, 0x30,
567 0x06, 0x04, 0x02, 0x00, 0x02, 0x05, 0x00,
568 },
569 .der_len = 55,
570 .is_canonical = 0,
571 .inherits = 1,
572 .afis = {
573 IANA_AFI_IPV4, IANA_AFI_IPV6,
574 },
575 .afi_len = 2,
576 },
577 {
578 .description = "RFC 3779, Appendix B, example 1 canonical",
579 .addrs = {
580 {
581 .afi = IANA_AFI_IPV4,
582 .safi = safi_unicast,
583 .type = choice_prefix,
584 .addr.ipv4.prefix = {
585 .addr = {
586 10, 0, 32,
587 },
588 .addr_len = 3,
589 .prefix_len = 20,
590 },
591 },
592 {
593 .afi = IANA_AFI_IPV4,
594 .safi = safi_unicast,
595 .type = choice_prefix,
596 .addr.ipv4.prefix = {
597 .addr = {
598 10, 0, 64,
599 },
600 .addr_len = 3,
601 .prefix_len = 24,
602 },
603 },
604 {
605 .afi = IANA_AFI_IPV4,
606 .safi = safi_unicast,
607 .type = choice_prefix,
608 .addr.ipv4.prefix = {
609 .addr = {
610 10, 1,
611 },
612 .addr_len = 2,
613 .prefix_len = 16,
614 },
615 },
616 {
617 .afi = IANA_AFI_IPV4,
618 .safi = safi_unicast,
619 .type = choice_range,
620 .addr.ipv4.range = {
621 .min = {
622 10, 2, 48, 00,
623 },
624 .max = {
625 10, 2, 64, 255,
626 },
627 },
628 },
629 {
630 .afi = IANA_AFI_IPV4,
631 .safi = safi_unicast,
632 .type = choice_prefix,
633 .addr.ipv4.prefix = {
634 .addr = {
635 10, 3,
636 },
637 .addr_len = 2,
638 .prefix_len = 16,
639 },
640 },
641 {
642 .afi = IANA_AFI_IPV6,
643 .safi = safi_none,
644 .type = choice_inherit,
645 },
646 {
647 .type = choice_last,
648 },
649 },
650 .der = {
651 0x30, 0x35, 0x30, 0x2b, 0x04, 0x03, 0x00, 0x01,
652 0x01, 0x30, 0x24, 0x03, 0x04, 0x04, 0x0a, 0x00,
653 0x20, 0x03, 0x04, 0x00, 0x0a, 0x00, 0x40, 0x03,
654 0x03, 0x00, 0x0a, 0x01, 0x30, 0x0c, 0x03, 0x04,
655 0x04, 0x0a, 0x02, 0x30, 0x03, 0x04, 0x00, 0x0a,
656 0x02, 0x40, 0x03, 0x03, 0x00, 0x0a, 0x03, 0x30,
657 0x06, 0x04, 0x02, 0x00, 0x02, 0x05, 0x00,
658 },
659 .der_len = 55,
660 .is_canonical = 1,
661 .inherits = 1,
662 .afis = {
663 IANA_AFI_IPV4, IANA_AFI_IPV6,
664 },
665 .afi_len = 2,
666 },
667 {
668 .description = "RFC 3779, Appendix B, example 2",
669 .addrs = {
670 {
671 .afi = IANA_AFI_IPV6,
672 .safi = safi_none,
673 .type = choice_prefix,
674 .addr.ipv6.prefix = {
675 .addr = {
676 0x20, 0x01, 0x00, 0x00,
677 0x00, 0x02,
678 },
679 .addr_len = 6,
680 .prefix_len = 48,
681 },
682 },
683 {
684 .afi = IANA_AFI_IPV4,
685 .safi = safi_unicast,
686 .type = choice_prefix,
687 .addr.ipv4.prefix = {
688 .addr = {
689 10,
690 },
691 .addr_len = 1,
692 .prefix_len = 8,
693 },
694 },
695 {
696 .afi = IANA_AFI_IPV4,
697 .safi = safi_unicast,
698 .type = choice_prefix,
699 .addr.ipv4.prefix = {
700 .addr = {
701 172, 16,
702 },
703 .addr_len = 2,
704 .prefix_len = 12,
705 },
706 },
707 {
708 .afi = IANA_AFI_IPV4,
709 .safi = safi_multicast,
710 .type = choice_inherit,
711 },
712 {
713 .type = choice_last,
714 },
715 },
716 .der = {
717 0x30, 0x2c, 0x30, 0x10, 0x04, 0x03, 0x00, 0x01,
718 0x01, 0x30, 0x09, 0x03, 0x02, 0x00, 0x0a, 0x03,
719 0x03, 0x04, 0xac, 0x10, 0x30, 0x07, 0x04, 0x03,
720 0x00, 0x01, 0x02, 0x05, 0x00, 0x30, 0x0f, 0x04,
721 0x02, 0x00, 0x02, 0x30, 0x09, 0x03, 0x07, 0x00,
722 0x20, 0x01, 0x00, 0x00, 0x00, 0x02,
723 },
724 .der_len = 46,
725 .is_canonical = 0,
726 .inherits = 1,
727 .afis = {
728 IANA_AFI_IPV4, IANA_AFI_IPV4,
729 },
730 .afi_len = 2,
731 },
732 {
733 .description = "Range should be prefix 127/8",
734 .addrs = {
735 {
736 .afi = IANA_AFI_IPV4,
737 .safi = safi_none,
738 .type = choice_range,
739 .addr.ipv4.range = {
740 .min = {
741 127, 0, 0, 0,
742 },
743 .max = {
744 127, 255, 255, 255,
745 },
746 },
747 },
748 {
749 .type = choice_last,
750 },
751 },
752 .der = {
753 0x30, 0x0c, 0x30, 0x0a, 0x04, 0x02, 0x00, 0x01,
754 0x30, 0x04, 0x03, 0x02, 0x00, 0x7f,
755 },
756 .der_len = 14,
757 .memcmp_fails = 1,
758 .is_canonical = 1,
759 .inherits = 0,
760 .afis = {
761 IANA_AFI_IPV4,
762 },
763 .afi_len = 1,
764 },
765};
766
767const size_t N_BUILD_ADDR_BLOCK_TESTS =
768 sizeof(build_addr_block_tests) / sizeof(build_addr_block_tests[0]);
769
770static unsigned int *
771addr_block_get_safi(const struct ip_addr_block *addr)
772{
773 static unsigned int safi;
774
775 switch (addr->safi) {
776 case safi_none:
777 return NULL;
778 case safi_unicast:
779 safi = 1;
780 break;
781 case safi_multicast:
782 safi = 2;
783 break;
784 }
785
786 return &safi;
787}
788
789static int
790addr_block_add_ipv4_addr(IPAddrBlocks *block, enum choice_type type,
791 union ipv4_choice *ipv4, unsigned int *safi)
792{
793 switch (type) {
794 case choice_prefix:
795 return X509v3_addr_add_prefix(block, IANA_AFI_IPV4, safi,
796 ipv4->prefix.addr, ipv4->prefix.prefix_len);
797 case choice_range:
798 return X509v3_addr_add_range(block, IANA_AFI_IPV4, safi,
799 ipv4->range.min, ipv4->range.max);
800 case choice_inherit:
801 return X509v3_addr_add_inherit(block, IANA_AFI_IPV4, safi);
802 case choice_last:
803 default:
804 return 0;
805 }
806}
807
808static int
809addr_block_add_ipv6_addr(IPAddrBlocks *block, enum choice_type type,
810 union ipv6_choice *ipv6, unsigned int *safi)
811{
812 switch (type) {
813 case choice_prefix:
814 return X509v3_addr_add_prefix(block, IANA_AFI_IPV6, safi,
815 ipv6->prefix.addr, ipv6->prefix.prefix_len);
816 case choice_range:
817 return X509v3_addr_add_range(block, IANA_AFI_IPV6, safi,
818 ipv6->range.min, ipv6->range.max);
819 case choice_inherit:
820 return X509v3_addr_add_inherit(block, IANA_AFI_IPV6, safi);
821 case choice_last:
822 default:
823 return 0;
824 }
825}
826
827static int
828addr_block_add_addrs(IPAddrBlocks *block, struct ip_addr_block addrs[])
829{
830 struct ip_addr_block *addr;
831 unsigned int *safi;
832
833 for (addr = &addrs[0]; addr->type != choice_last; addr++) {
834 safi = addr_block_get_safi(addr);
835 switch (addr->afi) {
836 case IANA_AFI_IPV4:
837 if (!addr_block_add_ipv4_addr(block, addr->type,
838 &addr->addr.ipv4, safi))
839 return 0;
840 break;
841 case IANA_AFI_IPV6:
842 if (!addr_block_add_ipv6_addr(block, addr->type,
843 &addr->addr.ipv6, safi))
844 return 0;
845 break;
846 default:
847 fprintf(stderr, "%s: corrupt test data", __func__);
848 exit(1);
849 }
850 }
851
852 return 1;
853}
854
855static int
856build_addr_block_test(struct build_addr_block_test_data *test)
857{
858 IPAddrBlocks *addrs = NULL;
859 unsigned char *out = NULL;
860 int out_len;
861 int i;
862 int memcmp_failed = 1;
863 int failed = 1;
864
865 if ((addrs = IPAddrBlocks_new()) == NULL)
866 goto err;
867
868 if (!addr_block_add_addrs(addrs, test->addrs))
869 goto err;
870
871 if (X509v3_addr_is_canonical(addrs) != test->is_canonical) {
872 fprintf(stderr, "%s: \"%s\" X509v3_addr_is_canonical not %d\n",
873 __func__, test->description, test->is_canonical);
874 goto err;
875 }
876
877 if (!X509v3_addr_canonize(addrs)) {
878 fprintf(stderr, "%s: \"%s\" failed to canonize\n",
879 __func__, test->description);
880 goto err;
881 }
882
883 if (!X509v3_addr_is_canonical(addrs)) {
884 fprintf(stderr, "%s: \"%s\" canonization wasn't canonical\n",
885 __func__, test->description);
886 goto err;
887 }
888
889 if ((out_len = i2d_IPAddrBlocks(addrs, &out)) <= 0) {
890 fprintf(stderr, "%s: \"%s\" i2d_IPAddrBlocks failed\n",
891 __func__, test->description);
892 goto err;
893 }
894
895 memcmp_failed = (size_t)out_len != test->der_len;
896 if (!memcmp_failed)
897 memcmp_failed = memcmp(out, test->der, test->der_len);
898 if (memcmp_failed) {
899 report_hexdump(__func__, test->description, "memcmp DER failed",
900 test->der, test->der_len, out, out_len);
901 if (!test->memcmp_fails)
902 goto err;
903 fprintf(stderr, "ignoring expected failure\n");
904 }
905
906 if (X509v3_addr_inherits(addrs) != test->inherits) {
907 fprintf(stderr, "%s: \"%s\" X509v3_addr_inherits not %d\n",
908 __func__, test->description, test->inherits);
909 goto err;
910 }
911
912 for (i = 0; i < sk_IPAddressFamily_num(addrs) && i < test->afi_len; i++) {
913 IPAddressFamily *family;
914 unsigned int afi;
915
916 family = sk_IPAddressFamily_value(addrs, i);
917
918 if ((afi = X509v3_addr_get_afi(family)) == 0) {
919 fprintf(stderr, "%s: \"%s\" X509v3_addr_get_afi"
920 " failed\n", __func__, test->description);
921 goto err;
922 }
923 if (test->afis[i] != afi){
924 fprintf(stderr, "%s: \"%s\" afi[%d] mismatch. "
925 "want: %u, got: %u\n", __func__,
926 test->description, i, test->afis[i], afi);
927 goto err;
928 }
929 }
930 if (i != test->afi_len) {
931 fprintf(stderr, "%s: \"%s\" checked %d afis, expected %d\n",
932 __func__, test->description, i, test->afi_len);
933 goto err;
934 }
935
936 failed = 0;
937
938 err:
939 IPAddrBlocks_free(addrs);
940 free(out);
941
942 return failed;
943}
944
945static int
946run_IPAddrBlock_tests(void)
947{
948 size_t i;
949 int failed = 0;
950
951 for (i = 0; i < N_BUILD_ADDR_BLOCK_TESTS; i++)
952 failed |= build_addr_block_test(&build_addr_block_tests[i]);
953
954 return failed;
955}
956
957struct asid_or_range {
958 int type;
959 int inherit;
960 const unsigned char *min;
961 const unsigned char *max;
962};
963
964struct ASIdentifiers_build_test {
965 const char *description;
966 int should_build;
967 int inherits;
968 int canonical;
969 int should_canonize;
970 struct asid_or_range delegations[8];
971 const unsigned char der[128];
972 size_t der_len;
973};
974
975/* Sentinel value used for marking the end of the delegations table. */
976#define V3_ASID_END -1
977
978const struct ASIdentifiers_build_test ASIdentifiers_build_data[] = {
979 {
980 .description = "RFC 3779, Appendix C",
981 .should_build = 1,
982 .inherits = 1,
983 .canonical = 1,
984 .delegations = {
985 {
986 .type = V3_ASID_ASNUM,
987 .inherit = 0,
988 .min = "135",
989 .max = NULL,
990 },
991 {
992 .type = V3_ASID_ASNUM,
993 .inherit = 0,
994 .min = "3000",
995 .max = "3999",
996 },
997 {
998 .type = V3_ASID_ASNUM,
999 .inherit = 0,
1000 .min = "5001",
1001 .max = NULL,
1002 },
1003 {
1004 .type = V3_ASID_RDI,
1005 .inherit = 1,
1006 .min = NULL,
1007 .max = NULL,
1008 },
1009 {
1010 .type = V3_ASID_END,
1011 },
1012 },
1013 .der = {
1014 0x30, 0x1a, 0xa0, 0x14, 0x30, 0x12, 0x02, 0x02,
1015 0x00, 0x87, 0x30, 0x08, 0x02, 0x02, 0x0b, 0xb8,
1016 0x02, 0x02, 0x0f, 0x9f, 0x02, 0x02, 0x13, 0x89,
1017 0xa1, 0x02, 0x05, 0x00,
1018 },
1019 .der_len = 28,
1020 },
1021 {
1022 .description = "RFC 3779, Appendix C without rdi",
1023 .should_build = 1,
1024 .inherits = 0,
1025 .canonical = 1,
1026 .delegations = {
1027 {
1028 .type = V3_ASID_ASNUM,
1029 .inherit = 0,
1030 .min = "135",
1031 .max = NULL,
1032 },
1033 {
1034 .type = V3_ASID_ASNUM,
1035 .inherit = 0,
1036 .min = "3000",
1037 .max = "3999",
1038 },
1039 {
1040 .type = V3_ASID_ASNUM,
1041 .inherit = 0,
1042 .min = "5001",
1043 .max = NULL,
1044 },
1045 {
1046 .type = V3_ASID_END,
1047 },
1048 },
1049 .der = {
1050 0x30, 0x16, 0xa0, 0x14, 0x30, 0x12, 0x02, 0x02,
1051 0x00, 0x87, 0x30, 0x08, 0x02, 0x02, 0x0b, 0xb8,
1052 0x02, 0x02, 0x0f, 0x9f, 0x02, 0x02, 0x13, 0x89,
1053 },
1054 .der_len = 24,
1055 },
1056 {
1057 .description = "RFC 3779, Appendix C variant",
1058 .should_build = 1,
1059 .inherits = 0,
1060 .canonical = 1,
1061 .delegations = {
1062 {
1063 .type = V3_ASID_ASNUM,
1064 .inherit = 0,
1065 .min = "135",
1066 .max = NULL,
1067 },
1068 {
1069 .type = V3_ASID_ASNUM,
1070 .inherit = 0,
1071 .min = "3000",
1072 .max = "3999",
1073 },
1074 {
1075 .type = V3_ASID_ASNUM,
1076 .inherit = 0,
1077 .min = "5001",
1078 .max = NULL,
1079 },
1080 {
1081 .type = V3_ASID_RDI,
1082 .inherit = 0,
1083 .min = "135",
1084 .max = NULL,
1085 },
1086 {
1087 .type = V3_ASID_RDI,
1088 .inherit = 0,
1089 .min = "3000",
1090 .max = "3999",
1091 },
1092 {
1093 .type = V3_ASID_RDI,
1094 .inherit = 0,
1095 .min = "5001",
1096 .max = NULL,
1097 },
1098 {
1099 .type = V3_ASID_END,
1100 },
1101 },
1102 .der = {
1103 0x30, 0x2c, 0xa0, 0x14, 0x30, 0x12, 0x02, 0x02,
1104 0x00, 0x87, 0x30, 0x08, 0x02, 0x02, 0x0b, 0xb8,
1105 0x02, 0x02, 0x0f, 0x9f, 0x02, 0x02, 0x13, 0x89,
1106 0xa1, 0x14, 0x30, 0x12, 0x02, 0x02, 0x00, 0x87,
1107 0x30, 0x08, 0x02, 0x02, 0x0b, 0xb8, 0x02, 0x02,
1108 0x0f, 0x9f, 0x02, 0x02, 0x13, 0x89,
1109 },
1110 .der_len = 46,
1111 },
1112 {
1113 .description = "inherit only",
1114 .should_build = 1,
1115 .inherits = 1,
1116 .canonical = 1,
1117 .delegations = {
1118 {
1119 .type = V3_ASID_ASNUM,
1120 .inherit = 1,
1121 },
1122 {
1123 .type = V3_ASID_RDI,
1124 .inherit = 1,
1125 },
1126 {
1127 .type = V3_ASID_END,
1128 },
1129 },
1130 .der = {
1131 0x30, 0x08, 0xa0, 0x02, 0x05, 0x00, 0xa1, 0x02,
1132 0x05, 0x00,
1133 },
1134 .der_len = 10,
1135 },
1136 {
1137 .description = "adjacent unsorted ranges are merged",
1138 .should_build = 1,
1139 .inherits = 0,
1140 .canonical = 0,
1141 .should_canonize = 1,
1142 .delegations = {
1143 {
1144 .type = V3_ASID_RDI,
1145 .inherit = 0,
1146 .min = "27",
1147 .max = NULL,
1148 },
1149 {
1150 .type = V3_ASID_RDI,
1151 .inherit = 0,
1152 .min = "28",
1153 .max = "57",
1154 },
1155 {
1156 .type = V3_ASID_RDI,
1157 .inherit = 0,
1158 .min = "66",
1159 .max = "68",
1160 },
1161 {
1162 .type = V3_ASID_RDI,
1163 .inherit = 0,
1164 .min = "58",
1165 .max = "63",
1166 },
1167 {
1168 .type = V3_ASID_RDI,
1169 .inherit = 0,
1170 .min = "64",
1171 .max = NULL,
1172 },
1173 {
1174 .type = V3_ASID_END,
1175 },
1176 },
1177 .der = {
1178 0x30, 0x14, 0xa1, 0x12, 0x30, 0x10, 0x30, 0x06,
1179 0x02, 0x01, 0x1b, 0x02, 0x01, 0x40, 0x30, 0x06,
1180 0x02, 0x01, 0x42, 0x02, 0x01, 0x44,
1181 },
1182 .der_len = 22,
1183 },
1184 {
1185 .description = "range of length 0",
1186 .should_build = 1,
1187 .inherits = 1,
1188 .canonical = 1,
1189 .should_canonize = 1,
1190 .delegations = {
1191 {
1192 .type = V3_ASID_RDI,
1193 .inherit = 0,
1194 .min = "27",
1195 .max = "27",
1196 },
1197 {
1198 .type = V3_ASID_ASNUM,
1199 .inherit = 1,
1200 },
1201 {
1202 .type = V3_ASID_END,
1203 },
1204 },
1205 .der = {
1206 0x30, 0x10, 0xa0, 0x02, 0x05, 0x00, 0xa1, 0x0a,
1207 0x30, 0x08, 0x30, 0x06, 0x02, 0x01, 0x1b, 0x02,
1208 0x01, 0x1b,
1209 },
1210 .der_len = 18,
1211 },
1212 {
1213 .description = "reversed range doesn't canonize",
1214 .should_build = 1,
1215 .inherits = 0,
1216 .canonical = 0,
1217 .should_canonize = 0,
1218 .delegations = {
1219 {
1220 .type = V3_ASID_ASNUM,
1221 .inherit = 0,
1222 .min = "57",
1223 .max = "42",
1224 },
1225 {
1226 .type = V3_ASID_END,
1227 },
1228 },
1229 },
1230 {
1231 .description = "overlapping ranges don't canonize",
1232 .should_build = 1,
1233 .inherits = 0,
1234 .canonical = 0,
1235 .should_canonize = 0,
1236 .delegations = {
1237 {
1238 .type = V3_ASID_ASNUM,
1239 .inherit = 0,
1240 .min = "42",
1241 .max = "57",
1242 },
1243 {
1244 .type = V3_ASID_ASNUM,
1245 .inherit = 0,
1246 .min = "57",
1247 .max = "60",
1248 },
1249 {
1250 .type = V3_ASID_END,
1251 },
1252 },
1253 },
1254 {
1255 .description = "reversed interior range doesn't canonize",
1256 .should_build = 1,
1257 .inherits = 0,
1258 .canonical = 0,
1259 .should_canonize = 0,
1260 .delegations = {
1261 {
1262 .type = V3_ASID_ASNUM,
1263 .inherit = 0,
1264 .min = "1",
1265 .max = "2",
1266 },
1267 {
1268 .type = V3_ASID_ASNUM,
1269 .inherit = 0,
1270 .min = "57",
1271 .max = "42",
1272 },
1273 {
1274 .type = V3_ASID_ASNUM,
1275 .inherit = 0,
1276 .min = "65523",
1277 .max = "65535",
1278 },
1279 {
1280 .type = V3_ASID_END,
1281 },
1282 },
1283 },
1284 {
1285 .description = "can't inherit and add AS ids",
1286 .should_build = 0,
1287 .inherits = 0,
1288 .canonical = 0,
1289 .should_canonize = 0,
1290 .delegations = {
1291 {
1292 .type = V3_ASID_ASNUM,
1293 .inherit = 0,
1294 .min = "1",
1295 .max = "2",
1296 },
1297 {
1298 .type = V3_ASID_ASNUM,
1299 .inherit = 1,
1300 },
1301 {
1302 .type = V3_ASID_END,
1303 },
1304 },
1305 },
1306 {
1307 .description = "can't inherit and add rdis",
1308 .should_build = 0,
1309 .inherits = 0,
1310 .canonical = 0,
1311 .should_canonize = 0,
1312 .delegations = {
1313 {
1314 .type = V3_ASID_RDI,
1315 .inherit = 0,
1316 .min = "1",
1317 .max = "2",
1318 },
1319 {
1320 .type = V3_ASID_RDI,
1321 .inherit = 1,
1322 },
1323 {
1324 .type = V3_ASID_END,
1325 },
1326 },
1327 },
1328};
1329
1330const size_t N_ASIDENTIFIERS_BUILD_TESTS =
1331 sizeof(ASIdentifiers_build_data) / sizeof(ASIdentifiers_build_data[0]);
1332
1333static int
1334add_as_delegation(ASIdentifiers *asid, const struct asid_or_range *delegation)
1335{
1336 ASN1_INTEGER *min = NULL, *max = NULL;
1337 int ret = 0;
1338
1339 if (delegation->inherit)
1340 return X509v3_asid_add_inherit(asid, delegation->type);
1341
1342 if ((min = s2i_ASN1_INTEGER(NULL, delegation->min)) == NULL)
1343 goto err;
1344
1345 if (delegation->max != NULL) {
1346 if ((max = s2i_ASN1_INTEGER(NULL, delegation->max)) == NULL)
1347 goto err;
1348 }
1349
1350 if (!X509v3_asid_add_id_or_range(asid, delegation->type, min, max))
1351 goto err;
1352 min = NULL;
1353 max = NULL;
1354
1355 ret = 1;
1356
1357 err:
1358 ASN1_INTEGER_free(min);
1359 ASN1_INTEGER_free(max);
1360
1361 return ret;
1362}
1363
1364static ASIdentifiers *
1365build_asid(const struct asid_or_range delegations[])
1366{
1367 ASIdentifiers *asid = NULL;
1368 const struct asid_or_range *delegation;
1369
1370 if ((asid = ASIdentifiers_new()) == NULL)
1371 goto err;
1372
1373 for (delegation = &delegations[0]; delegation->type != V3_ASID_END;
1374 delegation++) {
1375 if (!add_as_delegation(asid, delegation))
1376 goto err;
1377 }
1378
1379 return asid;
1380
1381 err:
1382 ASIdentifiers_free(asid);
1383 return NULL;
1384}
1385
1386static int
1387build_asid_test(const struct ASIdentifiers_build_test *test)
1388{
1389 ASIdentifiers *asid = NULL;
1390 unsigned char *out = NULL;
1391 int out_len;
1392 int memcmp_failed = 1;
1393 int failed = 1;
1394
1395 if ((asid = build_asid(test->delegations)) == NULL) {
1396 if (!test->should_build) {
1397 failed = 0;
1398 return failed;
1399 }
1400 fprintf(stderr, "%s: \"%s\" failed to build\n", __func__,
1401 test->description);
1402 return failed;
1403 }
1404
1405 if (!test->canonical) {
1406 if (X509v3_asid_is_canonical(asid)) {
1407 fprintf(stderr, "%s: \"%s\" shouldn't be canonical\n",
1408 __func__, test->description);
1409 goto err;
1410 }
1411 if (X509v3_asid_canonize(asid) != test->should_canonize) {
1412 fprintf(stderr, "%s: \"%s\" failed to canonize\n",
1413 __func__, test->description);
1414 goto err;
1415 }
1416 if (!test->should_canonize) {
1417 failed = 0;
1418 goto err;
1419 }
1420 }
1421
1422 /*
1423 * Verify that asid is in canonical form before converting it to DER.
1424 */
1425 if (!X509v3_asid_is_canonical(asid)) {
1426 fprintf(stderr, "%s: asid is not canonical\n", __func__);
1427 goto err;
1428 }
1429
1430 /*
1431 * Convert asid to DER and check that it matches expectations
1432 */
1433 out = NULL;
1434 if ((out_len = i2d_ASIdentifiers(asid, &out)) <= 0) {
1435 fprintf(stderr, "%s: \"%s\" i2d_ASIdentifiers failed\n",
1436 __func__, test->description);
1437 goto err;
1438 }
1439
1440
1441 memcmp_failed = (size_t)out_len != test->der_len;
1442 if (!memcmp_failed)
1443 memcmp_failed = memcmp(out, test->der, test->der_len);
1444 if (memcmp_failed) {
1445 report_hexdump(__func__, test->description, "memcmp DER failed",
1446 test->der, test->der_len, out, out_len);
1447 goto err;
1448 }
1449
1450 /*
1451 * Verify that asid inherits as expected
1452 */
1453 if (X509v3_asid_inherits(asid) != test->inherits) {
1454 fprintf(stderr, "%s: \"%s\" unexpected asid inherit %d\n",
1455 __func__, test->description, test->inherits);
1456 goto err;
1457 }
1458
1459 failed = 0;
1460
1461 err:
1462 free(out);
1463 ASIdentifiers_free(asid);
1464
1465 return failed;
1466}
1467
1468static int
1469run_ASIdentifiers_build_test(void)
1470{
1471 size_t i;
1472 int failed = 0;
1473
1474 for (i = 0; i < N_ASIDENTIFIERS_BUILD_TESTS; i++)
1475 failed |= build_asid_test(&ASIdentifiers_build_data[i]);
1476
1477 return failed;
1478}
1479
1480struct ASIdentifiers_subset_test {
1481 const char *description;
1482 struct asid_or_range delegationsA[8];
1483 struct asid_or_range delegationsB[8];
1484 int is_subset;
1485 int is_subset_if_canonized;
1486};
1487
1488/*
1489 * XXX: X509v3_asid_subset() assumes that both asnum and rdi are present
1490 * while they are both marked OPTIONAL in RFC 3779, 3.2.3...
1491 */
1492const struct ASIdentifiers_subset_test ASIdentifiers_subset_data[] = {
1493 {
1494 .description = "simple subset relation",
1495 .delegationsA = {
1496 {
1497 .type = V3_ASID_ASNUM,
1498 .inherit = 0,
1499 .min = "2",
1500 .max = "4",
1501 },
1502 {
1503 .type = V3_ASID_RDI,
1504 .inherit = 0,
1505 .min = "2",
1506 .max = NULL,
1507 },
1508 {
1509 .type = V3_ASID_END,
1510 },
1511 },
1512 .delegationsB = {
1513 {
1514 .type = V3_ASID_ASNUM,
1515 .inherit = 0,
1516 .min = "1",
1517 .max = "5",
1518 },
1519 {
1520 .type = V3_ASID_RDI,
1521 .inherit = 0,
1522 .min = "1",
1523 .max = "5",
1524 },
1525 {
1526 .type = V3_ASID_END,
1527 },
1528 },
1529 .is_subset = 1,
1530 .is_subset_if_canonized = 1,
1531 },
1532 {
1533 .description = "subset relation only after canonization",
1534 .delegationsA = {
1535 {
1536 .type = V3_ASID_ASNUM,
1537 .inherit = 0,
1538 .min = "2",
1539 .max = NULL,
1540 },
1541 {
1542 .type = V3_ASID_ASNUM,
1543 .inherit = 0,
1544 .min = "3",
1545 .max = "4",
1546 },
1547 {
1548 .type = V3_ASID_RDI,
1549 .inherit = 0,
1550 .min = "2",
1551 .max = NULL,
1552 },
1553 {
1554 .type = V3_ASID_END,
1555 },
1556 },
1557 .delegationsB = {
1558 {
1559 .type = V3_ASID_ASNUM,
1560 .inherit = 0,
1561 .min = "1",
1562 .max = "3",
1563 },
1564 {
1565 .type = V3_ASID_ASNUM,
1566 .inherit = 0,
1567 .min = "4",
1568 .max = "5",
1569 },
1570 {
1571 .type = V3_ASID_RDI,
1572 .inherit = 0,
1573 .min = "1",
1574 .max = "5",
1575 },
1576 {
1577 .type = V3_ASID_END,
1578 },
1579 },
1580 .is_subset = 0,
1581 .is_subset_if_canonized = 1,
1582 },
1583 {
1584 .description = "no subset if A inherits",
1585 .delegationsA = {
1586 {
1587 .type = V3_ASID_ASNUM,
1588 .inherit = 0,
1589 .min = "2",
1590 .max = NULL,
1591 },
1592 {
1593 .type = V3_ASID_ASNUM,
1594 .inherit = 0,
1595 .min = "3",
1596 .max = "4",
1597 },
1598 {
1599 .type = V3_ASID_RDI,
1600 .inherit = 1,
1601 },
1602 {
1603 .type = V3_ASID_END,
1604 },
1605 },
1606 .delegationsB = {
1607 {
1608 .type = V3_ASID_ASNUM,
1609 .inherit = 0,
1610 .min = "1",
1611 .max = "3",
1612 },
1613 {
1614 .type = V3_ASID_ASNUM,
1615 .inherit = 0,
1616 .min = "4",
1617 .max = "5",
1618 },
1619 {
1620 .type = V3_ASID_RDI,
1621 .inherit = 0,
1622 .min = "1",
1623 .max = "5",
1624 },
1625 {
1626 .type = V3_ASID_END,
1627 },
1628 },
1629 .is_subset = 0,
1630 .is_subset_if_canonized = 0,
1631 },
1632 {
1633 .description = "no subset if B inherits",
1634 .delegationsA = {
1635 {
1636 .type = V3_ASID_ASNUM,
1637 .inherit = 0,
1638 .min = "2",
1639 .max = NULL,
1640 },
1641 {
1642 .type = V3_ASID_ASNUM,
1643 .inherit = 0,
1644 .min = "3",
1645 .max = "4",
1646 },
1647 {
1648 .type = V3_ASID_RDI,
1649 .inherit = 0,
1650 .min = "5",
1651 .max = NULL,
1652 },
1653 {
1654 .type = V3_ASID_END,
1655 },
1656 },
1657 .delegationsB = {
1658 {
1659 .type = V3_ASID_ASNUM,
1660 .inherit = 0,
1661 .min = "1",
1662 .max = "3",
1663 },
1664 {
1665 .type = V3_ASID_ASNUM,
1666 .inherit = 0,
1667 .min = "4",
1668 .max = "5",
1669 },
1670 {
1671 .type = V3_ASID_RDI,
1672 .inherit = 1,
1673 },
1674 {
1675 .type = V3_ASID_END,
1676 },
1677 },
1678 .is_subset = 0,
1679 .is_subset_if_canonized = 0,
1680 },
1681 {
1682 .description = "no subset if both inherit",
1683 .delegationsA = {
1684 {
1685 .type = V3_ASID_ASNUM,
1686 .inherit = 0,
1687 .min = "2",
1688 .max = NULL,
1689 },
1690 {
1691 .type = V3_ASID_ASNUM,
1692 .inherit = 0,
1693 .min = "3",
1694 .max = "4",
1695 },
1696 {
1697 .type = V3_ASID_RDI,
1698 .inherit = 1,
1699 },
1700 {
1701 .type = V3_ASID_END,
1702 },
1703 },
1704 .delegationsB = {
1705 {
1706 .type = V3_ASID_ASNUM,
1707 .inherit = 0,
1708 .min = "1",
1709 .max = "3",
1710 },
1711 {
1712 .type = V3_ASID_ASNUM,
1713 .inherit = 0,
1714 .min = "4",
1715 .max = "5",
1716 },
1717 {
1718 .type = V3_ASID_RDI,
1719 .inherit = 1,
1720 },
1721 {
1722 .type = V3_ASID_END,
1723 },
1724 },
1725 .is_subset = 0,
1726 .is_subset_if_canonized = 0,
1727 },
1728};
1729
1730const size_t N_ASIDENTIFIERS_SUBSET_TESTS =
1731 sizeof(ASIdentifiers_build_data) / sizeof(ASIdentifiers_build_data[0]);
1732
1733static int
1734asid_subset_test(const struct ASIdentifiers_subset_test *test)
1735{
1736 ASIdentifiers *asidA = NULL, *asidB = NULL;
1737 int failed = 0;
1738
1739 if ((asidA = build_asid(test->delegationsA)) == NULL)
1740 goto err;
1741 if ((asidB = build_asid(test->delegationsB)) == NULL)
1742 goto err;
1743
1744 if (X509v3_asid_subset(asidA, asidB) != test->is_subset) {
1745 fprintf(stderr, "%s: \"%s\" X509v3_asid_subset failed\n",
1746 __func__, test->description);
1747 failed = 1;
1748 }
1749
1750 if (!test->is_subset) {
1751 if (!X509v3_asid_canonize(asidA))
1752 goto err;
1753 if (!X509v3_asid_canonize(asidB))
1754 goto err;
1755 if (X509v3_asid_subset(asidA, asidB) !=
1756 test->is_subset_if_canonized) {
1757 fprintf(stderr, "%s: \"%s\" canonized subset failed\n",
1758 __func__, test->description);
1759 failed = 1;
1760 }
1761 }
1762
1763 err:
1764 ASIdentifiers_free(asidA);
1765 ASIdentifiers_free(asidB);
1766
1767 return failed;
1768}
1769
1770static int
1771run_ASIdentifiers_subset_test(void)
1772{
1773 size_t i;
1774 int failed = 0;
1775
1776 for (i = 0; i < N_ASIDENTIFIERS_SUBSET_TESTS; i++)
1777 failed |= asid_subset_test(&ASIdentifiers_subset_data[i]);
1778
1779 return failed;
1780}
1781
1782int
1783main(void)
1784{
1785 int failed = 0;
1786
1787 failed |= run_IPAddressOrRange_tests();
1788 failed |= run_IPAddrBlock_tests();
1789 failed |= run_ASIdentifiers_build_test();
1790 failed |= run_ASIdentifiers_subset_test();
1791
1792 return failed;
1793}