xref: /openbsd/usr.sbin/rpki-client/cert.c (revision 3bef86f7)
1 /*	$OpenBSD: cert.c,v 1.122 2024/01/11 11:55:14 job 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 %d (%s)", p->fn, nid, OBJ_nid2sn(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			 extsz;
741 	size_t			 i;
742 	X509			*x = NULL;
743 	X509_EXTENSION		*ext = NULL;
744 	const X509_ALGOR	*palg;
745 	const ASN1_BIT_STRING	*piuid = NULL, *psuid = NULL;
746 	const ASN1_OBJECT	*cobj;
747 	ASN1_OBJECT		*obj;
748 	EVP_PKEY		*pkey;
749 	struct parse		 p;
750 	int			 nid, ip, as, sia, cp, crldp, aia, aki, ski,
751 				 eku, bc, ku;
752 
753 	nid = ip = as = sia = cp = crldp = aia = aki = ski = eku = bc = ku = 0;
754 
755 	/* just fail for empty buffers, the warning was printed elsewhere */
756 	if (der == NULL)
757 		return NULL;
758 
759 	memset(&p, 0, sizeof(struct parse));
760 	p.fn = fn;
761 	if ((p.res = calloc(1, sizeof(struct cert))) == NULL)
762 		err(1, NULL);
763 
764 	oder = der;
765 	if ((x = d2i_X509(NULL, &der, len)) == NULL) {
766 		warnx("%s: d2i_X509", p.fn);
767 		goto out;
768 	}
769 	if (der != oder + len) {
770 		warnx("%s: %td bytes trailing garbage", fn, oder + len - der);
771 		goto out;
772 	}
773 
774 	/* Cache X509v3 extensions, see X509_check_ca(3). */
775 	if (X509_check_purpose(x, -1, -1) <= 0) {
776 		warnx("%s: could not cache X509v3 extensions", p.fn);
777 		goto out;
778 	}
779 
780 	if (X509_get_version(x) != 2) {
781 		warnx("%s: RFC 6487 4.1: X.509 version must be v3", fn);
782 		goto out;
783 	}
784 
785 	X509_get0_signature(NULL, &palg, x);
786 	if (palg == NULL) {
787 		warnx("%s: X509_get0_signature", p.fn);
788 		goto out;
789 	}
790 	X509_ALGOR_get0(&cobj, NULL, NULL, palg);
791 	nid = OBJ_obj2nid(cobj);
792 	if (nid == NID_ecdsa_with_SHA256) {
793 		if (verbose)
794 			warnx("%s: P-256 support is experimental", fn);
795 	} else if (nid != NID_sha256WithRSAEncryption) {
796 		warnx("%s: RFC 7935: wrong signature algorithm %s, want %s",
797 		    fn, OBJ_nid2ln(nid),
798 		    OBJ_nid2ln(NID_sha256WithRSAEncryption));
799 		goto out;
800 	}
801 
802 	X509_get0_uids(x, &piuid, &psuid);
803 	if (piuid != NULL || psuid != NULL) {
804 		warnx("%s: issuer or subject unique identifiers not allowed",
805 		    fn);
806 		goto out;
807 	}
808 
809 	if (!x509_valid_subject(p.fn, x))
810 		goto out;
811 
812 	/* Look for X509v3 extensions. */
813 
814 	if ((extsz = X509_get_ext_count(x)) < 0)
815 		errx(1, "X509_get_ext_count");
816 
817 	for (i = 0; i < (size_t)extsz; i++) {
818 		ext = X509_get_ext(x, i);
819 		assert(ext != NULL);
820 		obj = X509_EXTENSION_get_object(ext);
821 		assert(obj != NULL);
822 
823 		switch (nid = OBJ_obj2nid(obj)) {
824 		case NID_sbgp_ipAddrBlock:
825 			if (ip++ > 0)
826 				goto dup;
827 			if (!sbgp_ipaddrblk(&p, ext))
828 				goto out;
829 			break;
830 		case NID_sbgp_autonomousSysNum:
831 			if (as++ > 0)
832 				goto dup;
833 			if (!sbgp_assysnum(&p, ext))
834 				goto out;
835 			break;
836 		case NID_sinfo_access:
837 			if (sia++ > 0)
838 				goto dup;
839 			if (!sbgp_sia(&p, ext))
840 				goto out;
841 			break;
842 		case NID_certificate_policies:
843 			if (cp++ > 0)
844 				goto dup;
845 			if (!certificate_policies(&p, ext))
846 				goto out;
847 			break;
848 		case NID_crl_distribution_points:
849 			if (crldp++ > 0)
850 				goto dup;
851 			break;
852 		case NID_info_access:
853 			if (aia++ > 0)
854 				goto dup;
855 			break;
856 		case NID_authority_key_identifier:
857 			if (aki++ > 0)
858 				goto dup;
859 			break;
860 		case NID_subject_key_identifier:
861 			if (ski++ > 0)
862 				goto dup;
863 			break;
864 		case NID_ext_key_usage:
865 			if (eku++ > 0)
866 				goto dup;
867 			break;
868 		case NID_basic_constraints:
869 			if (bc++ > 0)
870 				goto dup;
871 			break;
872 		case NID_key_usage:
873 			if (ku++ > 0)
874 				goto dup;
875 			break;
876 		default:
877 			/* unexpected extensions warrant investigation */
878 			{
879 				char objn[64];
880 				OBJ_obj2txt(objn, sizeof(objn), obj, 0);
881 				warnx("%s: ignoring %s (NID %d)",
882 				    p.fn, objn, OBJ_obj2nid(obj));
883 			}
884 			break;
885 		}
886 	}
887 
888 	if (!x509_get_aki(x, p.fn, &p.res->aki))
889 		goto out;
890 	if (!x509_get_ski(x, p.fn, &p.res->ski))
891 		goto out;
892 	if (!x509_get_aia(x, p.fn, &p.res->aia))
893 		goto out;
894 	if (!x509_get_crl(x, p.fn, &p.res->crl))
895 		goto out;
896 	if (!x509_get_notbefore(x, p.fn, &p.res->notbefore))
897 		goto out;
898 	if (!x509_get_notafter(x, p.fn, &p.res->notafter))
899 		goto out;
900 	p.res->purpose = x509_get_purpose(x, p.fn);
901 
902 	/* Validation on required fields. */
903 
904 	switch (p.res->purpose) {
905 	case CERT_PURPOSE_CA:
906 		if ((pkey = X509_get0_pubkey(x)) == NULL) {
907 			warnx("%s: X509_get0_pubkey failed", p.fn);
908 			goto out;
909 		}
910 		if (!valid_ca_pkey(p.fn, pkey))
911 			goto out;
912 
913 		if (X509_get_key_usage(x) != (KU_KEY_CERT_SIGN | KU_CRL_SIGN)) {
914 			warnx("%s: RFC 6487 section 4.8.4: key usage violation",
915 			    p.fn);
916 			goto out;
917 		}
918 
919 		/* EKU may be allowed for some purposes in the future. */
920 		if (X509_get_extended_key_usage(x) != UINT32_MAX) {
921 			warnx("%s: RFC 6487 section 4.8.5: EKU not allowed",
922 			    fn);
923 			goto out;
924 		}
925 
926 		if (p.res->mft == NULL) {
927 			warnx("%s: RFC 6487 section 4.8.8: missing SIA", p.fn);
928 			goto out;
929 		}
930 		if (p.res->asz == 0 && p.res->ipsz == 0) {
931 			warnx("%s: missing IP or AS resources", p.fn);
932 			goto out;
933 		}
934 		break;
935 	case CERT_PURPOSE_BGPSEC_ROUTER:
936 		p.res->pubkey = x509_get_pubkey(x, p.fn);
937 		if (p.res->pubkey == NULL) {
938 			warnx("%s: x509_get_pubkey failed", p.fn);
939 			goto out;
940 		}
941 		if (p.res->ipsz > 0) {
942 			warnx("%s: unexpected IP resources in BGPsec cert",
943 			    p.fn);
944 			goto out;
945 		}
946 		for (i = 0; i < p.res->asz; i++) {
947 			if (p.res->as[i].type == CERT_AS_INHERIT) {
948 				warnx("%s: inherit elements not allowed in EE"
949 				    " cert", p.fn);
950 				goto out;
951 			}
952 		}
953 		if (sia) {
954 			warnx("%s: unexpected SIA extension in BGPsec cert",
955 			    p.fn);
956 			goto out;
957 		}
958 		break;
959 	default:
960 		warnx("%s: x509_get_purpose failed in %s", p.fn, __func__);
961 		goto out;
962 	}
963 
964 	if (p.res->ski == NULL) {
965 		warnx("%s: RFC 6487 section 8.4.2: missing SKI", p.fn);
966 		goto out;
967 	}
968 
969 	p.res->x509 = x;
970 	return p.res;
971 
972  dup:
973 	warnx("%s: RFC 5280 section 4.2: duplicate %s extension", fn,
974 	    OBJ_nid2sn(nid));
975  out:
976 	cert_free(p.res);
977 	X509_free(x);
978 	return NULL;
979 }
980 
981 struct cert *
982 cert_parse(const char *fn, struct cert *p)
983 {
984 	if (p == NULL)
985 		return NULL;
986 
987 	if (p->aki == NULL) {
988 		warnx("%s: RFC 6487 section 8.4.2: "
989 		    "non-trust anchor missing AKI", fn);
990 		goto badcert;
991 	}
992 	if (strcmp(p->aki, p->ski) == 0) {
993 		warnx("%s: RFC 6487 section 8.4.2: "
994 		    "non-trust anchor AKI may not match SKI", fn);
995 		goto badcert;
996 	}
997 	if (p->aia == NULL) {
998 		warnx("%s: RFC 6487 section 8.4.7: AIA: extension missing", fn);
999 		goto badcert;
1000 	}
1001 	if (p->crl == NULL) {
1002 		warnx("%s: RFC 6487 section 4.8.6: CRL: "
1003 		    "no CRL distribution point extension", fn);
1004 		goto badcert;
1005 	}
1006 	return p;
1007 
1008 badcert:
1009 	cert_free(p);
1010 	return NULL;
1011 }
1012 
1013 struct cert *
1014 ta_parse(const char *fn, struct cert *p, const unsigned char *pkey,
1015     size_t pkeysz)
1016 {
1017 	ASN1_TIME	*notBefore, *notAfter;
1018 	EVP_PKEY	*pk, *opk;
1019 	time_t		 now = get_current_time();
1020 
1021 	if (p == NULL)
1022 		return NULL;
1023 
1024 	/* first check pubkey against the one from the TAL */
1025 	pk = d2i_PUBKEY(NULL, &pkey, pkeysz);
1026 	if (pk == NULL) {
1027 		warnx("%s: RFC 6487 (trust anchor): bad TAL pubkey", fn);
1028 		goto badcert;
1029 	}
1030 	if ((opk = X509_get0_pubkey(p->x509)) == NULL) {
1031 		warnx("%s: RFC 6487 (trust anchor): missing pubkey", fn);
1032 		goto badcert;
1033 	}
1034 	if (EVP_PKEY_cmp(pk, opk) != 1) {
1035 		warnx("%s: RFC 6487 (trust anchor): "
1036 		    "pubkey does not match TAL pubkey", fn);
1037 		goto badcert;
1038 	}
1039 
1040 	if ((notBefore = X509_get_notBefore(p->x509)) == NULL) {
1041 		warnx("%s: certificate has invalid notBefore", fn);
1042 		goto badcert;
1043 	}
1044 	if ((notAfter = X509_get_notAfter(p->x509)) == NULL) {
1045 		warnx("%s: certificate has invalid notAfter", fn);
1046 		goto badcert;
1047 	}
1048 	if (X509_cmp_time(notBefore, &now) != -1) {
1049 		warnx("%s: certificate not yet valid", fn);
1050 		goto badcert;
1051 	}
1052 	if (X509_cmp_time(notAfter, &now) != 1) {
1053 		warnx("%s: certificate has expired", fn);
1054 		goto badcert;
1055 	}
1056 	if (p->aki != NULL && strcmp(p->aki, p->ski)) {
1057 		warnx("%s: RFC 6487 section 8.4.2: "
1058 		    "trust anchor AKI, if specified, must match SKI", fn);
1059 		goto badcert;
1060 	}
1061 	if (p->aia != NULL) {
1062 		warnx("%s: RFC 6487 section 8.4.7: "
1063 		    "trust anchor must not have AIA", fn);
1064 		goto badcert;
1065 	}
1066 	if (p->crl != NULL) {
1067 		warnx("%s: RFC 6487 section 8.4.2: "
1068 		    "trust anchor may not specify CRL resource", fn);
1069 		goto badcert;
1070 	}
1071 	if (p->purpose == CERT_PURPOSE_BGPSEC_ROUTER) {
1072 		warnx("%s: BGPsec cert cannot be a trust anchor", fn);
1073 		goto badcert;
1074 	}
1075 	if (x509_any_inherits(p->x509)) {
1076 		warnx("%s: Trust anchor IP/AS resources may not inherit", fn);
1077 		goto badcert;
1078 	}
1079 
1080 	EVP_PKEY_free(pk);
1081 	return p;
1082 
1083 badcert:
1084 	EVP_PKEY_free(pk);
1085 	cert_free(p);
1086 	return NULL;
1087 }
1088 
1089 /*
1090  * Free parsed certificate contents.
1091  * Passing NULL is a noop.
1092  */
1093 void
1094 cert_free(struct cert *p)
1095 {
1096 	if (p == NULL)
1097 		return;
1098 
1099 	free(p->crl);
1100 	free(p->repo);
1101 	free(p->mft);
1102 	free(p->notify);
1103 	free(p->ips);
1104 	free(p->as);
1105 	free(p->aia);
1106 	free(p->aki);
1107 	free(p->ski);
1108 	free(p->pubkey);
1109 	X509_free(p->x509);
1110 	free(p);
1111 }
1112 
1113 /*
1114  * Write certificate parsed content into buffer.
1115  * See cert_read() for the other side of the pipe.
1116  */
1117 void
1118 cert_buffer(struct ibuf *b, const struct cert *p)
1119 {
1120 	io_simple_buffer(b, &p->notafter, sizeof(p->notafter));
1121 	io_simple_buffer(b, &p->purpose, sizeof(p->purpose));
1122 	io_simple_buffer(b, &p->talid, sizeof(p->talid));
1123 	io_simple_buffer(b, &p->repoid, sizeof(p->repoid));
1124 	io_simple_buffer(b, &p->ipsz, sizeof(p->ipsz));
1125 	io_simple_buffer(b, &p->asz, sizeof(p->asz));
1126 
1127 	io_simple_buffer(b, p->ips, p->ipsz * sizeof(p->ips[0]));
1128 	io_simple_buffer(b, p->as, p->asz * sizeof(p->as[0]));
1129 
1130 	io_str_buffer(b, p->mft);
1131 	io_str_buffer(b, p->notify);
1132 	io_str_buffer(b, p->repo);
1133 	io_str_buffer(b, p->crl);
1134 	io_str_buffer(b, p->aia);
1135 	io_str_buffer(b, p->aki);
1136 	io_str_buffer(b, p->ski);
1137 	io_str_buffer(b, p->pubkey);
1138 }
1139 
1140 /*
1141  * Allocate and read parsed certificate content from descriptor.
1142  * The pointer must be freed with cert_free().
1143  * Always returns a valid pointer.
1144  */
1145 struct cert *
1146 cert_read(struct ibuf *b)
1147 {
1148 	struct cert	*p;
1149 
1150 	if ((p = calloc(1, sizeof(struct cert))) == NULL)
1151 		err(1, NULL);
1152 
1153 	io_read_buf(b, &p->notafter, sizeof(p->notafter));
1154 	io_read_buf(b, &p->purpose, sizeof(p->purpose));
1155 	io_read_buf(b, &p->talid, sizeof(p->talid));
1156 	io_read_buf(b, &p->repoid, sizeof(p->repoid));
1157 	io_read_buf(b, &p->ipsz, sizeof(p->ipsz));
1158 	io_read_buf(b, &p->asz, sizeof(p->asz));
1159 
1160 	p->ips = calloc(p->ipsz, sizeof(struct cert_ip));
1161 	if (p->ips == NULL)
1162 		err(1, NULL);
1163 	io_read_buf(b, p->ips, p->ipsz * sizeof(p->ips[0]));
1164 
1165 	p->as = calloc(p->asz, sizeof(struct cert_as));
1166 	if (p->as == NULL)
1167 		err(1, NULL);
1168 	io_read_buf(b, p->as, p->asz * sizeof(p->as[0]));
1169 
1170 	io_read_str(b, &p->mft);
1171 	io_read_str(b, &p->notify);
1172 	io_read_str(b, &p->repo);
1173 	io_read_str(b, &p->crl);
1174 	io_read_str(b, &p->aia);
1175 	io_read_str(b, &p->aki);
1176 	io_read_str(b, &p->ski);
1177 	io_read_str(b, &p->pubkey);
1178 
1179 	assert(p->mft != NULL || p->purpose == CERT_PURPOSE_BGPSEC_ROUTER);
1180 	assert(p->ski);
1181 	return p;
1182 }
1183 
1184 static inline int
1185 authcmp(struct auth *a, struct auth *b)
1186 {
1187 	return strcmp(a->cert->ski, b->cert->ski);
1188 }
1189 
1190 RB_GENERATE_STATIC(auth_tree, auth, entry, authcmp);
1191 
1192 void
1193 auth_tree_free(struct auth_tree *auths)
1194 {
1195 	struct auth	*auth, *tauth;
1196 
1197 	RB_FOREACH_SAFE(auth, auth_tree, auths, tauth) {
1198 		RB_REMOVE(auth_tree, auths, auth);
1199 		cert_free(auth->cert);
1200 		free(auth);
1201 	}
1202 }
1203 
1204 struct auth *
1205 auth_find(struct auth_tree *auths, const char *aki)
1206 {
1207 	struct auth a;
1208 	struct cert c;
1209 
1210 	/* we look up the cert where the ski == aki */
1211 	c.ski = (char *)aki;
1212 	a.cert = &c;
1213 
1214 	return RB_FIND(auth_tree, auths, &a);
1215 }
1216 
1217 struct auth *
1218 auth_insert(struct auth_tree *auths, struct cert *cert, struct auth *parent)
1219 {
1220 	struct auth *na;
1221 
1222 	na = malloc(sizeof(*na));
1223 	if (na == NULL)
1224 		err(1, NULL);
1225 
1226 	na->parent = parent;
1227 	na->cert = cert;
1228 	na->any_inherits = x509_any_inherits(cert->x509);
1229 
1230 	if (RB_INSERT(auth_tree, auths, na) != NULL)
1231 		err(1, "auth tree corrupted");
1232 
1233 	return na;
1234 }
1235 
1236 static void
1237 insert_brk(struct brk_tree *tree, struct cert *cert, int asid)
1238 {
1239 	struct brk	*b, *found;
1240 
1241 	if ((b = calloc(1, sizeof(*b))) == NULL)
1242 		err(1, NULL);
1243 
1244 	b->asid = asid;
1245 	b->expires = cert->notafter;
1246 	b->talid = cert->talid;
1247 	if ((b->ski = strdup(cert->ski)) == NULL)
1248 		err(1, NULL);
1249 	if ((b->pubkey = strdup(cert->pubkey)) == NULL)
1250 		err(1, NULL);
1251 
1252 	/*
1253 	 * Check if a similar BRK already exists in the tree. If the found BRK
1254 	 * expires sooner, update it to this BRK's later expiry moment.
1255 	 */
1256 	if ((found = RB_INSERT(brk_tree, tree, b)) != NULL) {
1257 		if (found->expires < b->expires) {
1258 			found->expires = b->expires;
1259 			found->talid = b->talid;
1260 		}
1261 		free(b->ski);
1262 		free(b->pubkey);
1263 		free(b);
1264 	}
1265 }
1266 
1267 /*
1268  * Add each BGPsec Router Key into the BRK tree.
1269  */
1270 void
1271 cert_insert_brks(struct brk_tree *tree, struct cert *cert)
1272 {
1273 	size_t		 i, asid;
1274 
1275 	for (i = 0; i < cert->asz; i++) {
1276 		switch (cert->as[i].type) {
1277 		case CERT_AS_ID:
1278 			insert_brk(tree, cert, cert->as[i].id);
1279 			break;
1280 		case CERT_AS_RANGE:
1281 			for (asid = cert->as[i].range.min;
1282 			    asid <= cert->as[i].range.max; asid++)
1283 				insert_brk(tree, cert, asid);
1284 			break;
1285 		default:
1286 			warnx("invalid AS identifier type");
1287 			continue;
1288 		}
1289 	}
1290 }
1291 
1292 static inline int
1293 brkcmp(struct brk *a, struct brk *b)
1294 {
1295 	int rv;
1296 
1297 	if (a->asid > b->asid)
1298 		return 1;
1299 	if (a->asid < b->asid)
1300 		return -1;
1301 
1302 	rv = strcmp(a->ski, b->ski);
1303 	if (rv > 0)
1304 		return 1;
1305 	if (rv < 0)
1306 		return -1;
1307 
1308 	return strcmp(a->pubkey, b->pubkey);
1309 }
1310 
1311 RB_GENERATE(brk_tree, brk, entry, brkcmp);
1312