xref: /openbsd/usr.sbin/rpki-client/cert.c (revision 8bce0c52)
1 /*	$OpenBSD: cert.c,v 1.124 2024/02/03 14:43:15 tb Exp $ */
2 /*
3  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
4  * Copyright (c) 2021 Job Snijders <job@openbsd.org>
5  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <assert.h>
21 #include <err.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 
26 #include <openssl/asn1.h>
27 #include <openssl/x509.h>
28 #include <openssl/x509v3.h>
29 
30 #include "extern.h"
31 
32 /*
33  * A parsing sequence of a file (which may just be <stdin>).
34  */
35 struct	parse {
36 	struct cert	*res; /* result */
37 	const char	*fn; /* currently-parsed file */
38 };
39 
40 extern ASN1_OBJECT	*certpol_oid;	/* id-cp-ipAddr-asNumber cert policy */
41 extern ASN1_OBJECT	*carepo_oid;	/* 1.3.6.1.5.5.7.48.5 (caRepository) */
42 extern ASN1_OBJECT	*manifest_oid;	/* 1.3.6.1.5.5.7.48.10 (rpkiManifest) */
43 extern ASN1_OBJECT	*notify_oid;	/* 1.3.6.1.5.5.7.48.13 (rpkiNotify) */
44 
45 /*
46  * Append an IP address structure to our list of results.
47  * This will also constrain us to having at most one inheritance
48  * statement per AFI and also not have overlapping ranges (as prohibited
49  * in section 2.2.3.6).
50  * It does not make sure that ranges can't coalesce, that is, that any
51  * two ranges abut each other.
52  * This is warned against in section 2.2.3.6, but doesn't change the
53  * semantics of the system.
54  * Returns zero on failure (IP overlap) non-zero on success.
55  */
56 static int
57 append_ip(const char *fn, struct cert_ip *ips, size_t *ipsz,
58     const struct cert_ip *ip)
59 {
60 	if (!ip_addr_check_overlap(ip, fn, ips, *ipsz, 0))
61 		return 0;
62 	ips[(*ipsz)++] = *ip;
63 	return 1;
64 }
65 
66 /*
67  * Append an AS identifier structure to our list of results.
68  * Makes sure that the identifiers do not overlap or improperly inherit
69  * as defined by RFC 3779 section 3.3.
70  */
71 static int
72 append_as(const char *fn, struct cert_as *ases, size_t *asz,
73     const struct cert_as *as)
74 {
75 	if (!as_check_overlap(as, fn, ases, *asz, 0))
76 		return 0;
77 	ases[(*asz)++] = *as;
78 	return 1;
79 }
80 
81 /*
82  * Parse a range of AS identifiers as in 3.2.3.8.
83  * Returns zero on failure, non-zero on success.
84  */
85 int
86 sbgp_as_range(const char *fn, struct cert_as *ases, size_t *asz,
87     const ASRange *range)
88 {
89 	struct cert_as		 as;
90 
91 	memset(&as, 0, sizeof(struct cert_as));
92 	as.type = CERT_AS_RANGE;
93 
94 	if (!as_id_parse(range->min, &as.range.min)) {
95 		warnx("%s: RFC 3779 section 3.2.3.8 (via RFC 1930): "
96 		    "malformed AS identifier", fn);
97 		return 0;
98 	}
99 
100 	if (!as_id_parse(range->max, &as.range.max)) {
101 		warnx("%s: RFC 3779 section 3.2.3.8 (via RFC 1930): "
102 		    "malformed AS identifier", fn);
103 		return 0;
104 	}
105 
106 	if (as.range.max == as.range.min) {
107 		warnx("%s: RFC 3379 section 3.2.3.8: ASRange: "
108 		    "range is singular", fn);
109 		return 0;
110 	} else if (as.range.max < as.range.min) {
111 		warnx("%s: RFC 3379 section 3.2.3.8: ASRange: "
112 		    "range is out of order", fn);
113 		return 0;
114 	}
115 
116 	return append_as(fn, ases, asz, &as);
117 }
118 
119 /*
120  * Parse an entire 3.2.3.10 integer type.
121  */
122 int
123 sbgp_as_id(const char *fn, struct cert_as *ases, size_t *asz,
124     const ASN1_INTEGER *i)
125 {
126 	struct cert_as	 as;
127 
128 	memset(&as, 0, sizeof(struct cert_as));
129 	as.type = CERT_AS_ID;
130 
131 	if (!as_id_parse(i, &as.id)) {
132 		warnx("%s: RFC 3779 section 3.2.3.10 (via RFC 1930): "
133 		    "malformed AS identifier", fn);
134 		return 0;
135 	}
136 	if (as.id == 0) {
137 		warnx("%s: RFC 3779 section 3.2.3.10 (via RFC 1930): "
138 		    "AS identifier zero is reserved", fn);
139 		return 0;
140 	}
141 
142 	return append_as(fn, ases, asz, &as);
143 }
144 
145 static int
146 sbgp_as_inherit(const char *fn, struct cert_as *ases, size_t *asz)
147 {
148 	struct cert_as as;
149 
150 	memset(&as, 0, sizeof(struct cert_as));
151 	as.type = CERT_AS_INHERIT;
152 
153 	return append_as(fn, ases, asz, &as);
154 }
155 
156 int
157 sbgp_parse_assysnum(const char *fn, const ASIdentifiers *asidentifiers,
158     struct cert_as **out_as, size_t *out_asz)
159 {
160 	const ASIdOrRanges	*aors = NULL;
161 	struct cert_as		*as = NULL;
162 	size_t			 asz = 0, sz;
163 	int			 i;
164 
165 	assert(*out_as == NULL && *out_asz == 0);
166 
167 	if (asidentifiers->rdi != NULL) {
168 		warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
169 		    "should not have RDI values", fn);
170 		goto out;
171 	}
172 
173 	if (asidentifiers->asnum == NULL) {
174 		warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
175 		    "no AS number resource set", fn);
176 		goto out;
177 	}
178 
179 	switch (asidentifiers->asnum->type) {
180 	case ASIdentifierChoice_inherit:
181 		sz = 1;
182 		break;
183 	case ASIdentifierChoice_asIdsOrRanges:
184 		aors = asidentifiers->asnum->u.asIdsOrRanges;
185 		sz = sk_ASIdOrRange_num(aors);
186 		break;
187 	default:
188 		warnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
189 		    "unknown type %d", fn, asidentifiers->asnum->type);
190 		goto out;
191 	}
192 
193 	if (sz == 0) {
194 		warnx("%s: RFC 6487 section 4.8.11: empty asIdsOrRanges", fn);
195 		goto out;
196 	}
197 	if (sz >= MAX_AS_SIZE) {
198 		warnx("%s: too many AS number entries: limit %d",
199 		    fn, MAX_AS_SIZE);
200 		goto out;
201 	}
202 	as = calloc(sz, sizeof(struct cert_as));
203 	if (as == NULL)
204 		err(1, NULL);
205 
206 	if (aors == NULL) {
207 		if (!sbgp_as_inherit(fn, as, &asz))
208 			goto out;
209 	}
210 
211 	for (i = 0; i < sk_ASIdOrRange_num(aors); i++) {
212 		const ASIdOrRange *aor;
213 
214 		aor = sk_ASIdOrRange_value(aors, i);
215 		switch (aor->type) {
216 		case ASIdOrRange_id:
217 			if (!sbgp_as_id(fn, as, &asz, aor->u.id))
218 				goto out;
219 			break;
220 		case ASIdOrRange_range:
221 			if (!sbgp_as_range(fn, as, &asz, aor->u.range))
222 				goto out;
223 			break;
224 		default:
225 			warnx("%s: RFC 3779 section 3.2.3.5: ASIdOrRange: "
226 			    "unknown type %d", fn, aor->type);
227 			goto out;
228 		}
229 	}
230 
231 	*out_as = as;
232 	*out_asz = asz;
233 
234 	return 1;
235 
236  out:
237 	free(as);
238 
239 	return 0;
240 }
241 
242 /*
243  * Parse RFC 6487 4.8.11 X509v3 extension, with syntax documented in RFC
244  * 3779 starting in section 3.2.
245  * Returns zero on failure, non-zero on success.
246  */
247 static int
248 sbgp_assysnum(struct parse *p, X509_EXTENSION *ext)
249 {
250 	ASIdentifiers		*asidentifiers = NULL;
251 	int			 rc = 0;
252 
253 	if (!X509_EXTENSION_get_critical(ext)) {
254 		warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
255 		    "extension not critical", p->fn);
256 		goto out;
257 	}
258 
259 	if ((asidentifiers = X509V3_EXT_d2i(ext)) == NULL) {
260 		warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
261 		    "failed extension parse", p->fn);
262 		goto out;
263 	}
264 
265 	if (!sbgp_parse_assysnum(p->fn, asidentifiers,
266 	    &p->res->as, &p->res->asz))
267 		goto out;
268 
269 	rc = 1;
270  out:
271 	ASIdentifiers_free(asidentifiers);
272 	return rc;
273 }
274 
275 /*
276  * Construct a RFC 3779 2.2.3.8 range from its bit string.
277  * Returns zero on failure, non-zero on success.
278  */
279 int
280 sbgp_addr(const char *fn, struct cert_ip *ips, size_t *ipsz, enum afi afi,
281     const ASN1_BIT_STRING *bs)
282 {
283 	struct cert_ip	ip;
284 
285 	memset(&ip, 0, sizeof(struct cert_ip));
286 
287 	ip.afi = afi;
288 	ip.type = CERT_IP_ADDR;
289 
290 	if (!ip_addr_parse(bs, afi, fn, &ip.ip)) {
291 		warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
292 		    "invalid IP address", fn);
293 		return 0;
294 	}
295 
296 	if (!ip_cert_compose_ranges(&ip)) {
297 		warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
298 		    "IP address range reversed", fn);
299 		return 0;
300 	}
301 
302 	return append_ip(fn, ips, ipsz, &ip);
303 }
304 
305 /*
306  * Parse RFC 3779 2.2.3.9 range of addresses.
307  * Returns zero on failure, non-zero on success.
308  */
309 int
310 sbgp_addr_range(const char *fn, struct cert_ip *ips, size_t *ipsz,
311     enum afi afi, const IPAddressRange *range)
312 {
313 	struct cert_ip	ip;
314 
315 	memset(&ip, 0, sizeof(struct cert_ip));
316 
317 	ip.afi = afi;
318 	ip.type = CERT_IP_RANGE;
319 
320 	if (!ip_addr_parse(range->min, afi, fn, &ip.range.min)) {
321 		warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
322 		    "invalid IP address", fn);
323 		return 0;
324 	}
325 
326 	if (!ip_addr_parse(range->max, afi, fn, &ip.range.max)) {
327 		warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
328 		    "invalid IP address", fn);
329 		return 0;
330 	}
331 
332 	if (!ip_cert_compose_ranges(&ip)) {
333 		warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
334 		    "IP address range reversed", fn);
335 		return 0;
336 	}
337 
338 	return append_ip(fn, ips, ipsz, &ip);
339 }
340 
341 static int
342 sbgp_addr_inherit(const char *fn, struct cert_ip *ips, size_t *ipsz,
343     enum afi afi)
344 {
345 	struct cert_ip	ip;
346 
347 	memset(&ip, 0, sizeof(struct cert_ip));
348 
349 	ip.afi = afi;
350 	ip.type = CERT_IP_INHERIT;
351 
352 	return append_ip(fn, ips, ipsz, &ip);
353 }
354 
355 int
356 sbgp_parse_ipaddrblk(const char *fn, const IPAddrBlocks *addrblk,
357     struct cert_ip **out_ips, size_t *out_ipsz)
358 {
359 	const IPAddressFamily	*af;
360 	const IPAddressOrRanges	*aors;
361 	const IPAddressOrRange	*aor;
362 	enum afi		 afi;
363 	struct cert_ip		*ips = NULL;
364 	size_t			 ipsz = 0, sz;
365 	int			 ipv4_seen = 0, ipv6_seen = 0;
366 	int			 i, j, ipaddrblocksz;
367 
368 	assert(*out_ips == NULL && *out_ipsz == 0);
369 
370 	ipaddrblocksz = sk_IPAddressFamily_num(addrblk);
371 	if (ipaddrblocksz != 1 && ipaddrblocksz != 2) {
372 		warnx("%s: RFC 6487 section 4.8.10: unexpected number of "
373 		    "ipAddrBlocks (got %d, expected 1 or 2)",
374 		    fn, ipaddrblocksz);
375 		goto out;
376 	}
377 
378 	for (i = 0; i < ipaddrblocksz; i++) {
379 		af = sk_IPAddressFamily_value(addrblk, i);
380 
381 		switch (af->ipAddressChoice->type) {
382 		case IPAddressChoice_inherit:
383 			aors = NULL;
384 			sz = ipsz + 1;
385 			break;
386 		case IPAddressChoice_addressesOrRanges:
387 			aors = af->ipAddressChoice->u.addressesOrRanges;
388 			sz = ipsz + sk_IPAddressOrRange_num(aors);
389 			break;
390 		default:
391 			warnx("%s: RFC 3779: IPAddressChoice: unknown type %d",
392 			    fn, af->ipAddressChoice->type);
393 			goto out;
394 		}
395 		if (sz == ipsz) {
396 			warnx("%s: RFC 6487 section 4.8.10: "
397 			    "empty ipAddressesOrRanges", fn);
398 			goto out;
399 		}
400 
401 		if (sz >= MAX_IP_SIZE)
402 			goto out;
403 		ips = recallocarray(ips, ipsz, sz, sizeof(struct cert_ip));
404 		if (ips == NULL)
405 			err(1, NULL);
406 
407 		if (!ip_addr_afi_parse(fn, af->addressFamily, &afi)) {
408 			warnx("%s: RFC 3779: invalid AFI", fn);
409 			goto out;
410 		}
411 
412 		switch(afi) {
413 		case AFI_IPV4:
414 			if (ipv4_seen++ > 0) {
415 				warnx("%s: RFC 6487 section 4.8.10: "
416 				    "IPv4 appears twice", fn);
417 				goto out;
418 			}
419 			break;
420 		case AFI_IPV6:
421 			if (ipv6_seen++ > 0) {
422 				warnx("%s: RFC 6487 section 4.8.10: "
423 				    "IPv6 appears twice", fn);
424 				goto out;
425 			}
426 			break;
427 		}
428 
429 		if (aors == NULL) {
430 			if (!sbgp_addr_inherit(fn, ips, &ipsz, afi))
431 				goto out;
432 			continue;
433 		}
434 
435 		for (j = 0; j < sk_IPAddressOrRange_num(aors); j++) {
436 			aor = sk_IPAddressOrRange_value(aors, j);
437 			switch (aor->type) {
438 			case IPAddressOrRange_addressPrefix:
439 				if (!sbgp_addr(fn, ips, &ipsz, afi,
440 				    aor->u.addressPrefix))
441 					goto out;
442 				break;
443 			case IPAddressOrRange_addressRange:
444 				if (!sbgp_addr_range(fn, ips, &ipsz, afi,
445 				    aor->u.addressRange))
446 					goto out;
447 				break;
448 			default:
449 				warnx("%s: RFC 3779: IPAddressOrRange: "
450 				    "unknown type %d", fn, aor->type);
451 				goto out;
452 			}
453 		}
454 	}
455 
456 	*out_ips = ips;
457 	*out_ipsz = ipsz;
458 
459 	return 1;
460 
461  out:
462 	free(ips);
463 
464 	return 0;
465 }
466 
467 /*
468  * Parse an sbgp-ipAddrBlock X509 extension, RFC 6487 4.8.10, with
469  * syntax documented in RFC 3779 starting in section 2.2.
470  * Returns zero on failure, non-zero on success.
471  */
472 static int
473 sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext)
474 {
475 	IPAddrBlocks	*addrblk = NULL;
476 	int		 rc = 0;
477 
478 	if (!X509_EXTENSION_get_critical(ext)) {
479 		warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
480 		    "extension not critical", p->fn);
481 		goto out;
482 	}
483 
484 	if ((addrblk = X509V3_EXT_d2i(ext)) == NULL) {
485 		warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
486 		    "failed extension parse", p->fn);
487 		goto out;
488 	}
489 
490 	if (!sbgp_parse_ipaddrblk(p->fn, addrblk, &p->res->ips, &p->res->ipsz))
491 		goto out;
492 
493 	if (p->res->ipsz == 0) {
494 		warnx("%s: RFC 6487 section 4.8.10: empty ipAddrBlock", p->fn);
495 		goto out;
496 	}
497 
498 	rc = 1;
499  out:
500 	IPAddrBlocks_free(addrblk);
501 	return rc;
502 }
503 
504 /*
505  * Parse "Subject Information Access" extension, RFC 6487 4.8.8.
506  * Returns zero on failure, non-zero on success.
507  */
508 static int
509 sbgp_sia(struct parse *p, X509_EXTENSION *ext)
510 {
511 	AUTHORITY_INFO_ACCESS	*sia = NULL;
512 	ACCESS_DESCRIPTION	*ad;
513 	ASN1_OBJECT		*oid;
514 	const char		*mftfilename;
515 	int			 i, rc = 0;
516 
517 	if (X509_EXTENSION_get_critical(ext)) {
518 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
519 		    "extension not non-critical", p->fn);
520 		goto out;
521 	}
522 
523 	if ((sia = X509V3_EXT_d2i(ext)) == NULL) {
524 		warnx("%s: RFC 6487 section 4.8.8: SIA: failed extension parse",
525 		    p->fn);
526 		goto out;
527 	}
528 
529 	for (i = 0; i < sk_ACCESS_DESCRIPTION_num(sia); i++) {
530 		ad = sk_ACCESS_DESCRIPTION_value(sia, i);
531 
532 		oid = ad->method;
533 
534 		if (OBJ_cmp(oid, carepo_oid) == 0) {
535 			if (!x509_location(p->fn, "SIA: caRepository",
536 			    "rsync://", ad->location, &p->res->repo))
537 				goto out;
538 		} else if (OBJ_cmp(oid, manifest_oid) == 0) {
539 			if (!x509_location(p->fn, "SIA: rpkiManifest",
540 			    "rsync://", ad->location, &p->res->mft))
541 				goto out;
542 		} else if (OBJ_cmp(oid, notify_oid) == 0) {
543 			if (!x509_location(p->fn, "SIA: rpkiNotify",
544 			    "https://", ad->location, &p->res->notify))
545 				goto out;
546 		}
547 	}
548 
549 	if (p->res->mft == NULL || p->res->repo == NULL) {
550 		warnx("%s: RFC 6487 section 4.8.8: SIA: missing caRepository "
551 		    "or rpkiManifest", p->fn);
552 		goto out;
553 	}
554 
555 	mftfilename = strrchr(p->res->mft, '/');
556 	if (mftfilename == NULL) {
557 		warnx("%s: SIA: invalid rpkiManifest entry", p->fn);
558 		goto out;
559 	}
560 	mftfilename++;
561 	if (!valid_filename(mftfilename, strlen(mftfilename))) {
562 		warnx("%s: SIA: rpkiManifest filename contains invalid "
563 		    "characters", p->fn);
564 		goto out;
565 	}
566 
567 	if (strstr(p->res->mft, p->res->repo) != p->res->mft) {
568 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
569 		    "conflicting URIs for caRepository and rpkiManifest",
570 		    p->fn);
571 		goto out;
572 	}
573 
574 	if (rtype_from_file_extension(p->res->mft) != RTYPE_MFT) {
575 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
576 		    "not an MFT file", p->fn);
577 		goto out;
578 	}
579 
580 	rc = 1;
581  out:
582 	AUTHORITY_INFO_ACCESS_free(sia);
583 	return rc;
584 }
585 
586 /*
587  * Parse the certificate policies extension and check that it follows RFC 7318.
588  * Returns zero on failure, non-zero on success.
589  */
590 static int
591 certificate_policies(struct parse *p, X509_EXTENSION *ext)
592 {
593 	STACK_OF(POLICYINFO)		*policies = NULL;
594 	POLICYINFO			*policy;
595 	STACK_OF(POLICYQUALINFO)	*qualifiers;
596 	POLICYQUALINFO			*qualifier;
597 	int				 nid;
598 	int				 rc = 0;
599 
600 	if (!X509_EXTENSION_get_critical(ext)) {
601 		warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: "
602 		    "extension not critical", p->fn);
603 		goto out;
604 	}
605 
606 	if ((policies = X509V3_EXT_d2i(ext)) == NULL) {
607 		warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: "
608 		    "failed extension parse", p->fn);
609 		goto out;
610 	}
611 
612 	if (sk_POLICYINFO_num(policies) != 1) {
613 		warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: "
614 		    "want 1 policy, got %d", p->fn,
615 		    sk_POLICYINFO_num(policies));
616 		goto out;
617 	}
618 
619 	policy = sk_POLICYINFO_value(policies, 0);
620 	assert(policy != NULL && policy->policyid != NULL);
621 
622 	if (OBJ_cmp(policy->policyid, certpol_oid) != 0) {
623 		char pbuf[128], cbuf[128];
624 
625 		OBJ_obj2txt(pbuf, sizeof(pbuf), policy->policyid, 1);
626 		OBJ_obj2txt(cbuf, sizeof(cbuf), certpol_oid, 1);
627 		warnx("%s: RFC 7318 section 2: certificatePolicies: "
628 		    "unexpected OID: %s, want %s", p->fn, pbuf, cbuf);
629 		goto out;
630 	}
631 
632 	/* Policy qualifiers are optional. If they're absent, we're done. */
633 	if ((qualifiers = policy->qualifiers) == NULL) {
634 		rc = 1;
635 		goto out;
636 	}
637 
638 	if (sk_POLICYQUALINFO_num(qualifiers) != 1) {
639 		warnx("%s: RFC 7318 section 2: certificatePolicies: "
640 		    "want 1 policy qualifier, got %d", p->fn,
641 		    sk_POLICYQUALINFO_num(qualifiers));
642 		goto out;
643 	}
644 
645 	qualifier = sk_POLICYQUALINFO_value(qualifiers, 0);
646 	assert(qualifier != NULL && qualifier->pqualid != NULL);
647 
648 	if ((nid = OBJ_obj2nid(qualifier->pqualid)) != NID_id_qt_cps) {
649 		warnx("%s: RFC 7318 section 2: certificatePolicies: "
650 		    "want CPS, got %s", p->fn, nid2str(nid));
651 		goto out;
652 	}
653 
654 	if (verbose > 1 && !filemode)
655 		warnx("%s: CPS %.*s", p->fn, qualifier->d.cpsuri->length,
656 		    qualifier->d.cpsuri->data);
657 
658 	rc = 1;
659  out:
660 	sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
661 	return rc;
662 }
663 
664 /*
665  * Lightweight version of cert_parse_pre() for EE certs.
666  * Parses the two RFC 3779 extensions, and performs some sanity checks.
667  * Returns cert on success and NULL on failure.
668  */
669 struct cert *
670 cert_parse_ee_cert(const char *fn, int talid, X509 *x)
671 {
672 	struct parse		 p;
673 	X509_EXTENSION		*ext;
674 	int			 index;
675 
676 	memset(&p, 0, sizeof(struct parse));
677 	p.fn = fn;
678 	if ((p.res = calloc(1, sizeof(struct cert))) == NULL)
679 		err(1, NULL);
680 
681 	if (X509_get_version(x) != 2) {
682 		warnx("%s: RFC 6487 4.1: X.509 version must be v3", fn);
683 		goto out;
684 	}
685 
686 	if (!x509_valid_subject(fn, x))
687 		goto out;
688 
689 	if (X509_get_key_usage(x) != KU_DIGITAL_SIGNATURE) {
690 		warnx("%s: RFC 6487 section 4.8.4: KU must be digitalSignature",
691 		    fn);
692 		goto out;
693 	}
694 
695 	/* EKU may be allowed for some purposes in the future. */
696 	if (X509_get_extended_key_usage(x) != UINT32_MAX) {
697 		warnx("%s: RFC 6487 section 4.8.5: EKU not allowed", fn);
698 		goto out;
699 	}
700 
701 	index = X509_get_ext_by_NID(x, NID_sbgp_ipAddrBlock, -1);
702 	if ((ext = X509_get_ext(x, index)) != NULL) {
703 		if (!sbgp_ipaddrblk(&p, ext))
704 			goto out;
705 	}
706 
707 	index = X509_get_ext_by_NID(x, NID_sbgp_autonomousSysNum, -1);
708 	if ((ext = X509_get_ext(x, index)) != NULL) {
709 		if (!sbgp_assysnum(&p, ext))
710 			goto out;
711 	}
712 
713 	if (!X509_up_ref(x)) {
714 		warnx("%s: X509_up_ref failed", fn);
715 		goto out;
716 	}
717 
718 	p.res->x509 = x;
719 	p.res->talid = talid;
720 
721 	if (!constraints_validate(fn, p.res))
722 		goto out;
723 
724 	return p.res;
725 
726  out:
727 	cert_free(p.res);
728 	return NULL;
729 }
730 
731 /*
732  * Parse and partially validate an RPKI X509 certificate (either a trust
733  * anchor or a certificate) as defined in RFC 6487.
734  * Returns the parse results or NULL on failure.
735  */
736 struct cert *
737 cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
738 {
739 	const unsigned char	*oder;
740 	int			 i;
741 	X509			*x = NULL;
742 	X509_EXTENSION		*ext = NULL;
743 	const X509_ALGOR	*palg;
744 	const ASN1_BIT_STRING	*piuid = NULL, *psuid = NULL;
745 	const ASN1_OBJECT	*cobj;
746 	ASN1_OBJECT		*obj;
747 	EVP_PKEY		*pkey;
748 	struct parse		 p;
749 	int			 nid, ip, as, sia, cp, crldp, aia, aki, ski,
750 				 eku, bc, ku;
751 
752 	nid = ip = as = sia = cp = crldp = aia = aki = ski = eku = bc = ku = 0;
753 
754 	/* just fail for empty buffers, the warning was printed elsewhere */
755 	if (der == NULL)
756 		return NULL;
757 
758 	memset(&p, 0, sizeof(struct parse));
759 	p.fn = fn;
760 	if ((p.res = calloc(1, sizeof(struct cert))) == NULL)
761 		err(1, NULL);
762 
763 	oder = der;
764 	if ((x = d2i_X509(NULL, &der, len)) == NULL) {
765 		warnx("%s: d2i_X509", p.fn);
766 		goto out;
767 	}
768 	if (der != oder + len) {
769 		warnx("%s: %td bytes trailing garbage", fn, oder + len - der);
770 		goto out;
771 	}
772 
773 	/* Cache X509v3 extensions, see X509_check_ca(3). */
774 	if (X509_check_purpose(x, -1, -1) <= 0) {
775 		warnx("%s: could not cache X509v3 extensions", p.fn);
776 		goto out;
777 	}
778 
779 	if (X509_get_version(x) != 2) {
780 		warnx("%s: RFC 6487 4.1: X.509 version must be v3", fn);
781 		goto out;
782 	}
783 
784 	X509_get0_signature(NULL, &palg, x);
785 	if (palg == NULL) {
786 		warnx("%s: X509_get0_signature", p.fn);
787 		goto out;
788 	}
789 	X509_ALGOR_get0(&cobj, NULL, NULL, palg);
790 	nid = OBJ_obj2nid(cobj);
791 	if (nid == NID_ecdsa_with_SHA256) {
792 		if (verbose)
793 			warnx("%s: P-256 support is experimental", fn);
794 	} else if (nid != NID_sha256WithRSAEncryption) {
795 		warnx("%s: RFC 7935: wrong signature algorithm %s, want %s",
796 		    fn, nid2str(nid), LN_sha256WithRSAEncryption);
797 		goto out;
798 	}
799 
800 	X509_get0_uids(x, &piuid, &psuid);
801 	if (piuid != NULL || psuid != NULL) {
802 		warnx("%s: issuer or subject unique identifiers not allowed",
803 		    fn);
804 		goto out;
805 	}
806 
807 	if (!x509_valid_subject(p.fn, x))
808 		goto out;
809 
810 	/* Look for X509v3 extensions. */
811 
812 	for (i = 0; i < X509_get_ext_count(x); i++) {
813 		ext = X509_get_ext(x, i);
814 		assert(ext != NULL);
815 		obj = X509_EXTENSION_get_object(ext);
816 		assert(obj != NULL);
817 
818 		switch (nid = OBJ_obj2nid(obj)) {
819 		case NID_sbgp_ipAddrBlock:
820 			if (ip++ > 0)
821 				goto dup;
822 			if (!sbgp_ipaddrblk(&p, ext))
823 				goto out;
824 			break;
825 		case NID_sbgp_autonomousSysNum:
826 			if (as++ > 0)
827 				goto dup;
828 			if (!sbgp_assysnum(&p, ext))
829 				goto out;
830 			break;
831 		case NID_sinfo_access:
832 			if (sia++ > 0)
833 				goto dup;
834 			if (!sbgp_sia(&p, ext))
835 				goto out;
836 			break;
837 		case NID_certificate_policies:
838 			if (cp++ > 0)
839 				goto dup;
840 			if (!certificate_policies(&p, ext))
841 				goto out;
842 			break;
843 		case NID_crl_distribution_points:
844 			if (crldp++ > 0)
845 				goto dup;
846 			break;
847 		case NID_info_access:
848 			if (aia++ > 0)
849 				goto dup;
850 			break;
851 		case NID_authority_key_identifier:
852 			if (aki++ > 0)
853 				goto dup;
854 			break;
855 		case NID_subject_key_identifier:
856 			if (ski++ > 0)
857 				goto dup;
858 			break;
859 		case NID_ext_key_usage:
860 			if (eku++ > 0)
861 				goto dup;
862 			break;
863 		case NID_basic_constraints:
864 			if (bc++ > 0)
865 				goto dup;
866 			break;
867 		case NID_key_usage:
868 			if (ku++ > 0)
869 				goto dup;
870 			break;
871 		default:
872 			/* unexpected extensions warrant investigation */
873 			{
874 				char objn[64];
875 				OBJ_obj2txt(objn, sizeof(objn), obj, 0);
876 				warnx("%s: ignoring %s (NID %d)",
877 				    p.fn, objn, OBJ_obj2nid(obj));
878 			}
879 			break;
880 		}
881 	}
882 
883 	if (!x509_get_aki(x, p.fn, &p.res->aki))
884 		goto out;
885 	if (!x509_get_ski(x, p.fn, &p.res->ski))
886 		goto out;
887 	if (!x509_get_aia(x, p.fn, &p.res->aia))
888 		goto out;
889 	if (!x509_get_crl(x, p.fn, &p.res->crl))
890 		goto out;
891 	if (!x509_get_notbefore(x, p.fn, &p.res->notbefore))
892 		goto out;
893 	if (!x509_get_notafter(x, p.fn, &p.res->notafter))
894 		goto out;
895 	p.res->purpose = x509_get_purpose(x, p.fn);
896 
897 	/* Validation on required fields. */
898 
899 	switch (p.res->purpose) {
900 	case CERT_PURPOSE_CA:
901 		if ((pkey = X509_get0_pubkey(x)) == NULL) {
902 			warnx("%s: X509_get0_pubkey failed", p.fn);
903 			goto out;
904 		}
905 		if (!valid_ca_pkey(p.fn, pkey))
906 			goto out;
907 
908 		if (X509_get_key_usage(x) != (KU_KEY_CERT_SIGN | KU_CRL_SIGN)) {
909 			warnx("%s: RFC 6487 section 4.8.4: key usage violation",
910 			    p.fn);
911 			goto out;
912 		}
913 
914 		/* EKU may be allowed for some purposes in the future. */
915 		if (X509_get_extended_key_usage(x) != UINT32_MAX) {
916 			warnx("%s: RFC 6487 section 4.8.5: EKU not allowed",
917 			    fn);
918 			goto out;
919 		}
920 
921 		if (p.res->mft == NULL) {
922 			warnx("%s: RFC 6487 section 4.8.8: missing SIA", p.fn);
923 			goto out;
924 		}
925 		if (p.res->asz == 0 && p.res->ipsz == 0) {
926 			warnx("%s: missing IP or AS resources", p.fn);
927 			goto out;
928 		}
929 		break;
930 	case CERT_PURPOSE_BGPSEC_ROUTER:
931 		p.res->pubkey = x509_get_pubkey(x, p.fn);
932 		if (p.res->pubkey == NULL) {
933 			warnx("%s: x509_get_pubkey failed", p.fn);
934 			goto out;
935 		}
936 		if (p.res->ipsz > 0) {
937 			warnx("%s: unexpected IP resources in BGPsec cert",
938 			    p.fn);
939 			goto out;
940 		}
941 		for (i = 0; (size_t)i < p.res->asz; i++) {
942 			if (p.res->as[i].type == CERT_AS_INHERIT) {
943 				warnx("%s: inherit elements not allowed in EE"
944 				    " cert", p.fn);
945 				goto out;
946 			}
947 		}
948 		if (sia) {
949 			warnx("%s: unexpected SIA extension in BGPsec cert",
950 			    p.fn);
951 			goto out;
952 		}
953 		break;
954 	default:
955 		warnx("%s: x509_get_purpose failed in %s", p.fn, __func__);
956 		goto out;
957 	}
958 
959 	if (p.res->ski == NULL) {
960 		warnx("%s: RFC 6487 section 8.4.2: missing SKI", p.fn);
961 		goto out;
962 	}
963 
964 	p.res->x509 = x;
965 	return p.res;
966 
967  dup:
968 	warnx("%s: RFC 5280 section 4.2: duplicate extension: %s", fn,
969 	    nid2str(nid));
970  out:
971 	cert_free(p.res);
972 	X509_free(x);
973 	return NULL;
974 }
975 
976 struct cert *
977 cert_parse(const char *fn, struct cert *p)
978 {
979 	if (p == NULL)
980 		return NULL;
981 
982 	if (p->aki == NULL) {
983 		warnx("%s: RFC 6487 section 8.4.2: "
984 		    "non-trust anchor missing AKI", fn);
985 		goto badcert;
986 	}
987 	if (strcmp(p->aki, p->ski) == 0) {
988 		warnx("%s: RFC 6487 section 8.4.2: "
989 		    "non-trust anchor AKI may not match SKI", fn);
990 		goto badcert;
991 	}
992 	if (p->aia == NULL) {
993 		warnx("%s: RFC 6487 section 8.4.7: AIA: extension missing", fn);
994 		goto badcert;
995 	}
996 	if (p->crl == NULL) {
997 		warnx("%s: RFC 6487 section 4.8.6: CRL: "
998 		    "no CRL distribution point extension", fn);
999 		goto badcert;
1000 	}
1001 	return p;
1002 
1003 badcert:
1004 	cert_free(p);
1005 	return NULL;
1006 }
1007 
1008 struct cert *
1009 ta_parse(const char *fn, struct cert *p, const unsigned char *pkey,
1010     size_t pkeysz)
1011 {
1012 	ASN1_TIME	*notBefore, *notAfter;
1013 	EVP_PKEY	*pk, *opk;
1014 	time_t		 now = get_current_time();
1015 
1016 	if (p == NULL)
1017 		return NULL;
1018 
1019 	/* first check pubkey against the one from the TAL */
1020 	pk = d2i_PUBKEY(NULL, &pkey, pkeysz);
1021 	if (pk == NULL) {
1022 		warnx("%s: RFC 6487 (trust anchor): bad TAL pubkey", fn);
1023 		goto badcert;
1024 	}
1025 	if ((opk = X509_get0_pubkey(p->x509)) == NULL) {
1026 		warnx("%s: RFC 6487 (trust anchor): missing pubkey", fn);
1027 		goto badcert;
1028 	}
1029 	if (EVP_PKEY_cmp(pk, opk) != 1) {
1030 		warnx("%s: RFC 6487 (trust anchor): "
1031 		    "pubkey does not match TAL pubkey", fn);
1032 		goto badcert;
1033 	}
1034 
1035 	if ((notBefore = X509_get_notBefore(p->x509)) == NULL) {
1036 		warnx("%s: certificate has invalid notBefore", fn);
1037 		goto badcert;
1038 	}
1039 	if ((notAfter = X509_get_notAfter(p->x509)) == NULL) {
1040 		warnx("%s: certificate has invalid notAfter", fn);
1041 		goto badcert;
1042 	}
1043 	if (X509_cmp_time(notBefore, &now) != -1) {
1044 		warnx("%s: certificate not yet valid", fn);
1045 		goto badcert;
1046 	}
1047 	if (X509_cmp_time(notAfter, &now) != 1) {
1048 		warnx("%s: certificate has expired", fn);
1049 		goto badcert;
1050 	}
1051 	if (p->aki != NULL && strcmp(p->aki, p->ski)) {
1052 		warnx("%s: RFC 6487 section 8.4.2: "
1053 		    "trust anchor AKI, if specified, must match SKI", fn);
1054 		goto badcert;
1055 	}
1056 	if (p->aia != NULL) {
1057 		warnx("%s: RFC 6487 section 8.4.7: "
1058 		    "trust anchor must not have AIA", fn);
1059 		goto badcert;
1060 	}
1061 	if (p->crl != NULL) {
1062 		warnx("%s: RFC 6487 section 8.4.2: "
1063 		    "trust anchor may not specify CRL resource", fn);
1064 		goto badcert;
1065 	}
1066 	if (p->purpose == CERT_PURPOSE_BGPSEC_ROUTER) {
1067 		warnx("%s: BGPsec cert cannot be a trust anchor", fn);
1068 		goto badcert;
1069 	}
1070 	if (x509_any_inherits(p->x509)) {
1071 		warnx("%s: Trust anchor IP/AS resources may not inherit", fn);
1072 		goto badcert;
1073 	}
1074 
1075 	EVP_PKEY_free(pk);
1076 	return p;
1077 
1078 badcert:
1079 	EVP_PKEY_free(pk);
1080 	cert_free(p);
1081 	return NULL;
1082 }
1083 
1084 /*
1085  * Free parsed certificate contents.
1086  * Passing NULL is a noop.
1087  */
1088 void
1089 cert_free(struct cert *p)
1090 {
1091 	if (p == NULL)
1092 		return;
1093 
1094 	free(p->crl);
1095 	free(p->repo);
1096 	free(p->mft);
1097 	free(p->notify);
1098 	free(p->ips);
1099 	free(p->as);
1100 	free(p->aia);
1101 	free(p->aki);
1102 	free(p->ski);
1103 	free(p->pubkey);
1104 	X509_free(p->x509);
1105 	free(p);
1106 }
1107 
1108 /*
1109  * Write certificate parsed content into buffer.
1110  * See cert_read() for the other side of the pipe.
1111  */
1112 void
1113 cert_buffer(struct ibuf *b, const struct cert *p)
1114 {
1115 	io_simple_buffer(b, &p->notafter, sizeof(p->notafter));
1116 	io_simple_buffer(b, &p->purpose, sizeof(p->purpose));
1117 	io_simple_buffer(b, &p->talid, sizeof(p->talid));
1118 	io_simple_buffer(b, &p->repoid, sizeof(p->repoid));
1119 	io_simple_buffer(b, &p->ipsz, sizeof(p->ipsz));
1120 	io_simple_buffer(b, &p->asz, sizeof(p->asz));
1121 
1122 	io_simple_buffer(b, p->ips, p->ipsz * sizeof(p->ips[0]));
1123 	io_simple_buffer(b, p->as, p->asz * sizeof(p->as[0]));
1124 
1125 	io_str_buffer(b, p->mft);
1126 	io_str_buffer(b, p->notify);
1127 	io_str_buffer(b, p->repo);
1128 	io_str_buffer(b, p->crl);
1129 	io_str_buffer(b, p->aia);
1130 	io_str_buffer(b, p->aki);
1131 	io_str_buffer(b, p->ski);
1132 	io_str_buffer(b, p->pubkey);
1133 }
1134 
1135 /*
1136  * Allocate and read parsed certificate content from descriptor.
1137  * The pointer must be freed with cert_free().
1138  * Always returns a valid pointer.
1139  */
1140 struct cert *
1141 cert_read(struct ibuf *b)
1142 {
1143 	struct cert	*p;
1144 
1145 	if ((p = calloc(1, sizeof(struct cert))) == NULL)
1146 		err(1, NULL);
1147 
1148 	io_read_buf(b, &p->notafter, sizeof(p->notafter));
1149 	io_read_buf(b, &p->purpose, sizeof(p->purpose));
1150 	io_read_buf(b, &p->talid, sizeof(p->talid));
1151 	io_read_buf(b, &p->repoid, sizeof(p->repoid));
1152 	io_read_buf(b, &p->ipsz, sizeof(p->ipsz));
1153 	io_read_buf(b, &p->asz, sizeof(p->asz));
1154 
1155 	p->ips = calloc(p->ipsz, sizeof(struct cert_ip));
1156 	if (p->ips == NULL)
1157 		err(1, NULL);
1158 	io_read_buf(b, p->ips, p->ipsz * sizeof(p->ips[0]));
1159 
1160 	p->as = calloc(p->asz, sizeof(struct cert_as));
1161 	if (p->as == NULL)
1162 		err(1, NULL);
1163 	io_read_buf(b, p->as, p->asz * sizeof(p->as[0]));
1164 
1165 	io_read_str(b, &p->mft);
1166 	io_read_str(b, &p->notify);
1167 	io_read_str(b, &p->repo);
1168 	io_read_str(b, &p->crl);
1169 	io_read_str(b, &p->aia);
1170 	io_read_str(b, &p->aki);
1171 	io_read_str(b, &p->ski);
1172 	io_read_str(b, &p->pubkey);
1173 
1174 	assert(p->mft != NULL || p->purpose == CERT_PURPOSE_BGPSEC_ROUTER);
1175 	assert(p->ski);
1176 	return p;
1177 }
1178 
1179 static inline int
1180 authcmp(struct auth *a, struct auth *b)
1181 {
1182 	return strcmp(a->cert->ski, b->cert->ski);
1183 }
1184 
1185 RB_GENERATE_STATIC(auth_tree, auth, entry, authcmp);
1186 
1187 void
1188 auth_tree_free(struct auth_tree *auths)
1189 {
1190 	struct auth	*auth, *tauth;
1191 
1192 	RB_FOREACH_SAFE(auth, auth_tree, auths, tauth) {
1193 		RB_REMOVE(auth_tree, auths, auth);
1194 		cert_free(auth->cert);
1195 		free(auth);
1196 	}
1197 }
1198 
1199 struct auth *
1200 auth_find(struct auth_tree *auths, const char *aki)
1201 {
1202 	struct auth a;
1203 	struct cert c;
1204 
1205 	/* we look up the cert where the ski == aki */
1206 	c.ski = (char *)aki;
1207 	a.cert = &c;
1208 
1209 	return RB_FIND(auth_tree, auths, &a);
1210 }
1211 
1212 struct auth *
1213 auth_insert(struct auth_tree *auths, struct cert *cert, struct auth *parent)
1214 {
1215 	struct auth *na;
1216 
1217 	na = malloc(sizeof(*na));
1218 	if (na == NULL)
1219 		err(1, NULL);
1220 
1221 	na->parent = parent;
1222 	na->cert = cert;
1223 	na->any_inherits = x509_any_inherits(cert->x509);
1224 
1225 	if (RB_INSERT(auth_tree, auths, na) != NULL)
1226 		err(1, "auth tree corrupted");
1227 
1228 	return na;
1229 }
1230 
1231 static void
1232 insert_brk(struct brk_tree *tree, struct cert *cert, int asid)
1233 {
1234 	struct brk	*b, *found;
1235 
1236 	if ((b = calloc(1, sizeof(*b))) == NULL)
1237 		err(1, NULL);
1238 
1239 	b->asid = asid;
1240 	b->expires = cert->notafter;
1241 	b->talid = cert->talid;
1242 	if ((b->ski = strdup(cert->ski)) == NULL)
1243 		err(1, NULL);
1244 	if ((b->pubkey = strdup(cert->pubkey)) == NULL)
1245 		err(1, NULL);
1246 
1247 	/*
1248 	 * Check if a similar BRK already exists in the tree. If the found BRK
1249 	 * expires sooner, update it to this BRK's later expiry moment.
1250 	 */
1251 	if ((found = RB_INSERT(brk_tree, tree, b)) != NULL) {
1252 		if (found->expires < b->expires) {
1253 			found->expires = b->expires;
1254 			found->talid = b->talid;
1255 		}
1256 		free(b->ski);
1257 		free(b->pubkey);
1258 		free(b);
1259 	}
1260 }
1261 
1262 /*
1263  * Add each BGPsec Router Key into the BRK tree.
1264  */
1265 void
1266 cert_insert_brks(struct brk_tree *tree, struct cert *cert)
1267 {
1268 	size_t		 i, asid;
1269 
1270 	for (i = 0; i < cert->asz; i++) {
1271 		switch (cert->as[i].type) {
1272 		case CERT_AS_ID:
1273 			insert_brk(tree, cert, cert->as[i].id);
1274 			break;
1275 		case CERT_AS_RANGE:
1276 			for (asid = cert->as[i].range.min;
1277 			    asid <= cert->as[i].range.max; asid++)
1278 				insert_brk(tree, cert, asid);
1279 			break;
1280 		default:
1281 			warnx("invalid AS identifier type");
1282 			continue;
1283 		}
1284 	}
1285 }
1286 
1287 static inline int
1288 brkcmp(struct brk *a, struct brk *b)
1289 {
1290 	int rv;
1291 
1292 	if (a->asid > b->asid)
1293 		return 1;
1294 	if (a->asid < b->asid)
1295 		return -1;
1296 
1297 	rv = strcmp(a->ski, b->ski);
1298 	if (rv > 0)
1299 		return 1;
1300 	if (rv < 0)
1301 		return -1;
1302 
1303 	return strcmp(a->pubkey, b->pubkey);
1304 }
1305 
1306 RB_GENERATE(brk_tree, brk, entry, brkcmp);
1307