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