xref: /openbsd/usr.sbin/rpki-client/cert.c (revision 7cc1142d)
1 /*	$OpenBSD: cert.c,v 1.115 2023/09/12 09:33:30 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))
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))
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 /*
157  * Parse RFC 6487 4.8.11 X509v3 extension, with syntax documented in RFC
158  * 3779 starting in section 3.2.
159  * Returns zero on failure, non-zero on success.
160  */
161 static int
162 sbgp_assysnum(struct parse *p, X509_EXTENSION *ext)
163 {
164 	ASIdentifiers		*asidentifiers = NULL;
165 	const ASIdOrRanges	*aors = NULL;
166 	size_t			 asz;
167 	int			 i, rc = 0;
168 
169 	if (!X509_EXTENSION_get_critical(ext)) {
170 		warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
171 		    "extension not critical", p->fn);
172 		goto out;
173 	}
174 
175 	if ((asidentifiers = X509V3_EXT_d2i(ext)) == NULL) {
176 		warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
177 		    "failed extension parse", p->fn);
178 		goto out;
179 	}
180 
181 	if (asidentifiers->rdi != NULL) {
182 		warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
183 		    "should not have RDI values", p->fn);
184 		goto out;
185 	}
186 
187 	if (asidentifiers->asnum == NULL) {
188 		warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
189 		    "no AS number resource set", p->fn);
190 		goto out;
191 	}
192 
193 	switch (asidentifiers->asnum->type) {
194 	case ASIdentifierChoice_inherit:
195 		asz = 1;
196 		break;
197 	case ASIdentifierChoice_asIdsOrRanges:
198 		aors = asidentifiers->asnum->u.asIdsOrRanges;
199 		asz = sk_ASIdOrRange_num(aors);
200 		break;
201 	default:
202 		warnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
203 		    "unknown type %d", p->fn, asidentifiers->asnum->type);
204 		goto out;
205 	}
206 
207 	if (asz == 0) {
208 		warnx("%s: RFC 6487 section 4.8.11: empty asIdsOrRanges",
209 		    p->fn);
210 		goto out;
211 	}
212 	if (asz >= MAX_AS_SIZE) {
213 		warnx("%s: too many AS number entries: limit %d",
214 		    p->fn, MAX_AS_SIZE);
215 		goto out;
216 	}
217 	p->res->as = calloc(asz, sizeof(struct cert_as));
218 	if (p->res->as == NULL)
219 		err(1, NULL);
220 
221 	if (aors == NULL) {
222 		if (!sbgp_as_inherit(p->fn, p->res->as, &p->res->asz))
223 			goto out;
224 	}
225 
226 	for (i = 0; i < sk_ASIdOrRange_num(aors); i++) {
227 		const ASIdOrRange *aor;
228 
229 		aor = sk_ASIdOrRange_value(aors, i);
230 		switch (aor->type) {
231 		case ASIdOrRange_id:
232 			if (!sbgp_as_id(p->fn, p->res->as, &p->res->asz,
233 			    aor->u.id))
234 				goto out;
235 			break;
236 		case ASIdOrRange_range:
237 			if (!sbgp_as_range(p->fn, p->res->as, &p->res->asz,
238 			    aor->u.range))
239 				goto out;
240 			break;
241 		default:
242 			warnx("%s: RFC 3779 section 3.2.3.5: ASIdOrRange: "
243 			    "unknown type %d", p->fn, aor->type);
244 			goto out;
245 		}
246 	}
247 
248 	rc = 1;
249  out:
250 	ASIdentifiers_free(asidentifiers);
251 	return rc;
252 }
253 
254 /*
255  * Construct a RFC 3779 2.2.3.8 range from its bit string.
256  * Returns zero on failure, non-zero on success.
257  */
258 int
259 sbgp_addr(const char *fn, struct cert_ip *ips, size_t *ipsz, enum afi afi,
260     const ASN1_BIT_STRING *bs)
261 {
262 	struct cert_ip	ip;
263 
264 	memset(&ip, 0, sizeof(struct cert_ip));
265 
266 	ip.afi = afi;
267 	ip.type = CERT_IP_ADDR;
268 
269 	if (!ip_addr_parse(bs, afi, fn, &ip.ip)) {
270 		warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
271 		    "invalid IP address", fn);
272 		return 0;
273 	}
274 
275 	if (!ip_cert_compose_ranges(&ip)) {
276 		warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
277 		    "IP address range reversed", fn);
278 		return 0;
279 	}
280 
281 	return append_ip(fn, ips, ipsz, &ip);
282 }
283 
284 /*
285  * Parse RFC 3779 2.2.3.9 range of addresses.
286  * Returns zero on failure, non-zero on success.
287  */
288 int
289 sbgp_addr_range(const char *fn, struct cert_ip *ips, size_t *ipsz,
290     enum afi afi, const IPAddressRange *range)
291 {
292 	struct cert_ip	ip;
293 
294 	memset(&ip, 0, sizeof(struct cert_ip));
295 
296 	ip.afi = afi;
297 	ip.type = CERT_IP_RANGE;
298 
299 	if (!ip_addr_parse(range->min, afi, fn, &ip.range.min)) {
300 		warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
301 		    "invalid IP address", fn);
302 		return 0;
303 	}
304 
305 	if (!ip_addr_parse(range->max, afi, fn, &ip.range.max)) {
306 		warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
307 		    "invalid IP address", fn);
308 		return 0;
309 	}
310 
311 	if (!ip_cert_compose_ranges(&ip)) {
312 		warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
313 		    "IP address range reversed", fn);
314 		return 0;
315 	}
316 
317 	return append_ip(fn, ips, ipsz, &ip);
318 }
319 
320 static int
321 sbgp_addr_inherit(const char *fn, struct cert_ip *ips, size_t *ipsz,
322     enum afi afi)
323 {
324 	struct cert_ip	ip;
325 
326 	memset(&ip, 0, sizeof(struct cert_ip));
327 
328 	ip.afi = afi;
329 	ip.type = CERT_IP_INHERIT;
330 
331 	return append_ip(fn, ips, ipsz, &ip);
332 }
333 
334 /*
335  * Parse an sbgp-ipAddrBlock X509 extension, RFC 6487 4.8.10, with
336  * syntax documented in RFC 3779 starting in section 2.2.
337  * Returns zero on failure, non-zero on success.
338  */
339 static int
340 sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext)
341 {
342 	STACK_OF(IPAddressFamily)	*addrblk = NULL;
343 	const IPAddressFamily		*af;
344 	const IPAddressOrRanges		*aors;
345 	const IPAddressOrRange		*aor;
346 	enum afi			 afi;
347 	size_t				 ipsz;
348 	int				 i, j, rc = 0;
349 
350 	if (!X509_EXTENSION_get_critical(ext)) {
351 		warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
352 		    "extension not critical", p->fn);
353 		goto out;
354 	}
355 
356 	if ((addrblk = X509V3_EXT_d2i(ext)) == NULL) {
357 		warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
358 		    "failed extension parse", p->fn);
359 		goto out;
360 	}
361 
362 	for (i = 0; i < sk_IPAddressFamily_num(addrblk); i++) {
363 		af = sk_IPAddressFamily_value(addrblk, i);
364 
365 		switch (af->ipAddressChoice->type) {
366 		case IPAddressChoice_inherit:
367 			aors = NULL;
368 			ipsz = p->res->ipsz + 1;
369 			break;
370 		case IPAddressChoice_addressesOrRanges:
371 			aors = af->ipAddressChoice->u.addressesOrRanges;
372 			ipsz = p->res->ipsz + sk_IPAddressOrRange_num(aors);
373 			break;
374 		default:
375 			warnx("%s: RFC 3779: IPAddressChoice: unknown type %d",
376 			    p->fn, af->ipAddressChoice->type);
377 			goto out;
378 		}
379 		if (ipsz == p->res->ipsz) {
380 			warnx("%s: RFC 6487 section 4.8.10: "
381 			    "empty ipAddressesOrRanges", p->fn);
382 			goto out;
383 		}
384 
385 		if (ipsz >= MAX_IP_SIZE)
386 			goto out;
387 		p->res->ips = recallocarray(p->res->ips, p->res->ipsz, ipsz,
388 		    sizeof(struct cert_ip));
389 		if (p->res->ips == NULL)
390 			err(1, NULL);
391 
392 		if (!ip_addr_afi_parse(p->fn, af->addressFamily, &afi)) {
393 			warnx("%s: RFC 3779: invalid AFI", p->fn);
394 			goto out;
395 		}
396 
397 		if (aors == NULL) {
398 			if (!sbgp_addr_inherit(p->fn, p->res->ips,
399 			    &p->res->ipsz, afi))
400 				goto out;
401 			continue;
402 		}
403 
404 		for (j = 0; j < sk_IPAddressOrRange_num(aors); j++) {
405 			aor = sk_IPAddressOrRange_value(aors, j);
406 			switch (aor->type) {
407 			case IPAddressOrRange_addressPrefix:
408 				if (!sbgp_addr(p->fn, p->res->ips,
409 				    &p->res->ipsz, afi, aor->u.addressPrefix))
410 					goto out;
411 				break;
412 			case IPAddressOrRange_addressRange:
413 				if (!sbgp_addr_range(p->fn, p->res->ips,
414 				    &p->res->ipsz, afi, aor->u.addressRange))
415 					goto out;
416 				break;
417 			default:
418 				warnx("%s: RFC 3779: IPAddressOrRange: "
419 				    "unknown type %d", p->fn, aor->type);
420 				goto out;
421 			}
422 		}
423 	}
424 
425 	if (p->res->ipsz == 0) {
426 		warnx("%s: RFC 6487 section 4.8.10: empty ipAddrBlock", p->fn);
427 		goto out;
428 	}
429 
430 	rc = 1;
431  out:
432 	sk_IPAddressFamily_pop_free(addrblk, IPAddressFamily_free);
433 	return rc;
434 }
435 
436 /*
437  * Parse "Subject Information Access" extension, RFC 6487 4.8.8.
438  * Returns zero on failure, non-zero on success.
439  */
440 static int
441 sbgp_sia(struct parse *p, X509_EXTENSION *ext)
442 {
443 	AUTHORITY_INFO_ACCESS	*sia = NULL;
444 	ACCESS_DESCRIPTION	*ad;
445 	ASN1_OBJECT		*oid;
446 	const char		*mftfilename;
447 	int			 i, rc = 0;
448 
449 	if (X509_EXTENSION_get_critical(ext)) {
450 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
451 		    "extension not non-critical", p->fn);
452 		goto out;
453 	}
454 
455 	if ((sia = X509V3_EXT_d2i(ext)) == NULL) {
456 		warnx("%s: RFC 6487 section 4.8.8: SIA: failed extension parse",
457 		    p->fn);
458 		goto out;
459 	}
460 
461 	for (i = 0; i < sk_ACCESS_DESCRIPTION_num(sia); i++) {
462 		ad = sk_ACCESS_DESCRIPTION_value(sia, i);
463 
464 		oid = ad->method;
465 
466 		if (OBJ_cmp(oid, carepo_oid) == 0) {
467 			if (!x509_location(p->fn, "SIA: caRepository",
468 			    "rsync://", ad->location, &p->res->repo))
469 				goto out;
470 		} else if (OBJ_cmp(oid, manifest_oid) == 0) {
471 			if (!x509_location(p->fn, "SIA: rpkiManifest",
472 			    "rsync://", ad->location, &p->res->mft))
473 				goto out;
474 		} else if (OBJ_cmp(oid, notify_oid) == 0) {
475 			if (!x509_location(p->fn, "SIA: rpkiNotify",
476 			    "https://", ad->location, &p->res->notify))
477 				goto out;
478 		}
479 	}
480 
481 	if (p->res->mft == NULL || p->res->repo == NULL) {
482 		warnx("%s: RFC 6487 section 4.8.8: SIA: missing caRepository "
483 		    "or rpkiManifest", p->fn);
484 		goto out;
485 	}
486 
487 	mftfilename = strrchr(p->res->mft, '/');
488 	if (mftfilename == NULL) {
489 		warnx("%s: SIA: invalid rpkiManifest entry", p->fn);
490 		goto out;
491 	}
492 	mftfilename++;
493 	if (!valid_filename(mftfilename, strlen(mftfilename))) {
494 		warnx("%s: SIA: rpkiManifest filename contains invalid "
495 		    "characters", p->fn);
496 		goto out;
497 	}
498 
499 	if (strstr(p->res->mft, p->res->repo) != p->res->mft) {
500 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
501 		    "conflicting URIs for caRepository and rpkiManifest",
502 		    p->fn);
503 		goto out;
504 	}
505 
506 	if (rtype_from_file_extension(p->res->mft) != RTYPE_MFT) {
507 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
508 		    "not an MFT file", p->fn);
509 		goto out;
510 	}
511 
512 	rc = 1;
513  out:
514 	AUTHORITY_INFO_ACCESS_free(sia);
515 	return rc;
516 }
517 
518 /*
519  * Parse the certificate policies extension and check that it follows RFC 7318.
520  * Returns zero on failure, non-zero on success.
521  */
522 static int
523 certificate_policies(struct parse *p, X509_EXTENSION *ext)
524 {
525 	STACK_OF(POLICYINFO)		*policies = NULL;
526 	POLICYINFO			*policy;
527 	STACK_OF(POLICYQUALINFO)	*qualifiers;
528 	POLICYQUALINFO			*qualifier;
529 	int				 nid;
530 	int				 rc = 0;
531 
532 	if (!X509_EXTENSION_get_critical(ext)) {
533 		warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: "
534 		    "extension not critical", p->fn);
535 		goto out;
536 	}
537 
538 	if ((policies = X509V3_EXT_d2i(ext)) == NULL) {
539 		warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: "
540 		    "failed extension parse", p->fn);
541 		goto out;
542 	}
543 
544 	if (sk_POLICYINFO_num(policies) != 1) {
545 		warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: "
546 		    "want 1 policy, got %d", p->fn,
547 		    sk_POLICYINFO_num(policies));
548 		goto out;
549 	}
550 
551 	policy = sk_POLICYINFO_value(policies, 0);
552 	assert(policy != NULL && policy->policyid != NULL);
553 
554 	if (OBJ_cmp(policy->policyid, certpol_oid) != 0) {
555 		char pbuf[128], cbuf[128];
556 
557 		OBJ_obj2txt(pbuf, sizeof(pbuf), policy->policyid, 1);
558 		OBJ_obj2txt(cbuf, sizeof(cbuf), certpol_oid, 1);
559 		warnx("%s: RFC 7318 section 2: certificatePolicies: "
560 		    "unexpected OID: %s, want %s", p->fn, pbuf, cbuf);
561 		goto out;
562 	}
563 
564 	/* Policy qualifiers are optional. If they're absent, we're done. */
565 	if ((qualifiers = policy->qualifiers) == NULL) {
566 		rc = 1;
567 		goto out;
568 	}
569 
570 	if (sk_POLICYQUALINFO_num(qualifiers) != 1) {
571 		warnx("%s: RFC 7318 section 2: certificatePolicies: "
572 		    "want 1 policy qualifier, got %d", p->fn,
573 		    sk_POLICYQUALINFO_num(qualifiers));
574 		goto out;
575 	}
576 
577 	qualifier = sk_POLICYQUALINFO_value(qualifiers, 0);
578 	assert(qualifier != NULL && qualifier->pqualid != NULL);
579 
580 	if ((nid = OBJ_obj2nid(qualifier->pqualid)) != NID_id_qt_cps) {
581 		warnx("%s: RFC 7318 section 2: certificatePolicies: "
582 		    "want CPS, got %d (%s)", p->fn, nid, OBJ_nid2sn(nid));
583 		goto out;
584 	}
585 
586 	if (verbose > 1 && !filemode)
587 		warnx("%s: CPS %.*s", p->fn, qualifier->d.cpsuri->length,
588 		    qualifier->d.cpsuri->data);
589 
590 	rc = 1;
591  out:
592 	sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
593 	return rc;
594 }
595 
596 /*
597  * Lightweight version of cert_parse_pre() for EE certs.
598  * Parses the two RFC 3779 extensions, and performs some sanity checks.
599  * Returns cert on success and NULL on failure.
600  */
601 struct cert *
602 cert_parse_ee_cert(const char *fn, X509 *x)
603 {
604 	struct parse		 p;
605 	X509_EXTENSION		*ext;
606 	int			 index;
607 
608 	memset(&p, 0, sizeof(struct parse));
609 	p.fn = fn;
610 	if ((p.res = calloc(1, sizeof(struct cert))) == NULL)
611 		err(1, NULL);
612 
613 	if (X509_get_version(x) != 2) {
614 		warnx("%s: RFC 6487 4.1: X.509 version must be v3", fn);
615 		goto out;
616 	}
617 
618 	if (!x509_valid_subject(fn, x))
619 		goto out;
620 
621 	if (X509_get_key_usage(x) != KU_DIGITAL_SIGNATURE) {
622 		warnx("%s: RFC 6487 section 4.8.4: KU must be digitalSignature",
623 		    fn);
624 		goto out;
625 	}
626 
627 	/* EKU may be allowed for some purposes in the future. */
628 	if (X509_get_extended_key_usage(x) != UINT32_MAX) {
629 		warnx("%s: RFC 6487 section 4.8.5: EKU not allowed", fn);
630 		goto out;
631 	}
632 
633 	index = X509_get_ext_by_NID(x, NID_sbgp_ipAddrBlock, -1);
634 	if ((ext = X509_get_ext(x, index)) != NULL) {
635 		if (!sbgp_ipaddrblk(&p, ext))
636 			goto out;
637 	}
638 
639 	index = X509_get_ext_by_NID(x, NID_sbgp_autonomousSysNum, -1);
640 	if ((ext = X509_get_ext(x, index)) != NULL) {
641 		if (!sbgp_assysnum(&p, ext))
642 			goto out;
643 	}
644 
645 	if (!X509_up_ref(x)) {
646 		warnx("%s: X509_up_ref failed", fn);
647 		goto out;
648 	}
649 
650 	p.res->x509 = x;
651 	return p.res;
652 
653  out:
654 	cert_free(p.res);
655 	return NULL;
656 }
657 
658 /*
659  * Parse and partially validate an RPKI X509 certificate (either a trust
660  * anchor or a certificate) as defined in RFC 6487.
661  * Returns the parse results or NULL on failure.
662  */
663 struct cert *
664 cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
665 {
666 	const unsigned char	*oder;
667 	int			 extsz;
668 	size_t			 i;
669 	X509			*x = NULL;
670 	X509_EXTENSION		*ext = NULL;
671 	const X509_ALGOR	*palg;
672 	const ASN1_BIT_STRING	*piuid = NULL, *psuid = NULL;
673 	const ASN1_OBJECT	*cobj;
674 	ASN1_OBJECT		*obj;
675 	EVP_PKEY		*pkey;
676 	struct parse		 p;
677 	int			 nid, ip, as, sia, cp, crldp, aia, aki, ski,
678 				 eku, bc, ku;
679 
680 	nid = ip = as = sia = cp = crldp = aia = aki = ski = eku = bc = ku = 0;
681 
682 	/* just fail for empty buffers, the warning was printed elsewhere */
683 	if (der == NULL)
684 		return NULL;
685 
686 	memset(&p, 0, sizeof(struct parse));
687 	p.fn = fn;
688 	if ((p.res = calloc(1, sizeof(struct cert))) == NULL)
689 		err(1, NULL);
690 
691 	oder = der;
692 	if ((x = d2i_X509(NULL, &der, len)) == NULL) {
693 		warnx("%s: d2i_X509", p.fn);
694 		goto out;
695 	}
696 	if (der != oder + len) {
697 		warnx("%s: %td bytes trailing garbage", fn, oder + len - der);
698 		goto out;
699 	}
700 
701 	/* Cache X509v3 extensions, see X509_check_ca(3). */
702 	if (X509_check_purpose(x, -1, -1) <= 0) {
703 		warnx("%s: could not cache X509v3 extensions", p.fn);
704 		goto out;
705 	}
706 
707 	if (X509_get_version(x) != 2) {
708 		warnx("%s: RFC 6487 4.1: X.509 version must be v3", fn);
709 		goto out;
710 	}
711 
712 	X509_get0_signature(NULL, &palg, x);
713 	if (palg == NULL) {
714 		warnx("%s: X509_get0_signature", p.fn);
715 		goto out;
716 	}
717 	X509_ALGOR_get0(&cobj, NULL, NULL, palg);
718 	if ((nid = OBJ_obj2nid(cobj)) != NID_sha256WithRSAEncryption) {
719 		warnx("%s: RFC 7935: wrong signature algorithm %s, want %s",
720 		    fn, OBJ_nid2ln(nid),
721 		    OBJ_nid2ln(NID_sha256WithRSAEncryption));
722 		goto out;
723 	}
724 
725 	X509_get0_uids(x, &piuid, &psuid);
726 	if (piuid != NULL || psuid != NULL) {
727 		warnx("%s: issuer or subject unique identifiers not allowed",
728 		    fn);
729 		goto out;
730 	}
731 
732 	if (!x509_valid_subject(p.fn, x))
733 		goto out;
734 
735 	/* Look for X509v3 extensions. */
736 
737 	if ((extsz = X509_get_ext_count(x)) < 0)
738 		errx(1, "X509_get_ext_count");
739 
740 	for (i = 0; i < (size_t)extsz; i++) {
741 		ext = X509_get_ext(x, i);
742 		assert(ext != NULL);
743 		obj = X509_EXTENSION_get_object(ext);
744 		assert(obj != NULL);
745 
746 		switch (nid = OBJ_obj2nid(obj)) {
747 		case NID_sbgp_ipAddrBlock:
748 			if (ip++ > 0)
749 				goto dup;
750 			if (!sbgp_ipaddrblk(&p, ext))
751 				goto out;
752 			break;
753 		case NID_sbgp_autonomousSysNum:
754 			if (as++ > 0)
755 				goto dup;
756 			if (!sbgp_assysnum(&p, ext))
757 				goto out;
758 			break;
759 		case NID_sinfo_access:
760 			if (sia++ > 0)
761 				goto dup;
762 			if (!sbgp_sia(&p, ext))
763 				goto out;
764 			break;
765 		case NID_certificate_policies:
766 			if (cp++ > 0)
767 				goto dup;
768 			if (!certificate_policies(&p, ext))
769 				goto out;
770 			break;
771 		case NID_crl_distribution_points:
772 			if (crldp++ > 0)
773 				goto dup;
774 			break;
775 		case NID_info_access:
776 			if (aia++ > 0)
777 				goto dup;
778 			break;
779 		case NID_authority_key_identifier:
780 			if (aki++ > 0)
781 				goto dup;
782 			break;
783 		case NID_subject_key_identifier:
784 			if (ski++ > 0)
785 				goto dup;
786 			break;
787 		case NID_ext_key_usage:
788 			if (eku++ > 0)
789 				goto dup;
790 			break;
791 		case NID_basic_constraints:
792 			if (bc++ > 0)
793 				goto dup;
794 			break;
795 		case NID_key_usage:
796 			if (ku++ > 0)
797 				goto dup;
798 			break;
799 		default:
800 			/* unexpected extensions warrant investigation */
801 			{
802 				char objn[64];
803 				OBJ_obj2txt(objn, sizeof(objn), obj, 0);
804 				warnx("%s: ignoring %s (NID %d)",
805 				    p.fn, objn, OBJ_obj2nid(obj));
806 			}
807 			break;
808 		}
809 	}
810 
811 	if (!x509_get_aki(x, p.fn, &p.res->aki))
812 		goto out;
813 	if (!x509_get_ski(x, p.fn, &p.res->ski))
814 		goto out;
815 	if (!x509_get_aia(x, p.fn, &p.res->aia))
816 		goto out;
817 	if (!x509_get_crl(x, p.fn, &p.res->crl))
818 		goto out;
819 	if (!x509_get_notbefore(x, p.fn, &p.res->notbefore))
820 		goto out;
821 	if (!x509_get_notafter(x, p.fn, &p.res->notafter))
822 		goto out;
823 	p.res->purpose = x509_get_purpose(x, p.fn);
824 
825 	/* Validation on required fields. */
826 
827 	switch (p.res->purpose) {
828 	case CERT_PURPOSE_CA:
829 		if ((pkey = X509_get0_pubkey(x)) == NULL) {
830 			warnx("%s: X509_get0_pubkey failed", p.fn);
831 			goto out;
832 		}
833 		if (!valid_ca_pkey(p.fn, pkey))
834 			goto out;
835 
836 		if (X509_get_key_usage(x) != (KU_KEY_CERT_SIGN | KU_CRL_SIGN)) {
837 			warnx("%s: RFC 6487 section 4.8.4: key usage violation",
838 			    p.fn);
839 			goto out;
840 		}
841 
842 		/* EKU may be allowed for some purposes in the future. */
843 		if (X509_get_extended_key_usage(x) != UINT32_MAX) {
844 			warnx("%s: RFC 6487 section 4.8.5: EKU not allowed",
845 			    fn);
846 			goto out;
847 		}
848 
849 		if (p.res->mft == NULL) {
850 			warnx("%s: RFC 6487 section 4.8.8: missing SIA", p.fn);
851 			goto out;
852 		}
853 		if (p.res->asz == 0 && p.res->ipsz == 0) {
854 			warnx("%s: missing IP or AS resources", p.fn);
855 			goto out;
856 		}
857 		break;
858 	case CERT_PURPOSE_BGPSEC_ROUTER:
859 		p.res->pubkey = x509_get_pubkey(x, p.fn);
860 		if (p.res->pubkey == NULL) {
861 			warnx("%s: x509_get_pubkey failed", p.fn);
862 			goto out;
863 		}
864 		if (p.res->ipsz > 0) {
865 			warnx("%s: unexpected IP resources in BGPsec cert",
866 			    p.fn);
867 			goto out;
868 		}
869 		for (i = 0; i < p.res->asz; i++) {
870 			if (p.res->as[i].type == CERT_AS_INHERIT) {
871 				warnx("%s: inherit elements not allowed in EE"
872 				    " cert", p.fn);
873 				goto out;
874 			}
875 		}
876 		if (sia) {
877 			warnx("%s: unexpected SIA extension in BGPsec cert",
878 			    p.fn);
879 			goto out;
880 		}
881 		break;
882 	default:
883 		warnx("%s: x509_get_purpose failed in %s", p.fn, __func__);
884 		goto out;
885 	}
886 
887 	if (p.res->ski == NULL) {
888 		warnx("%s: RFC 6487 section 8.4.2: missing SKI", p.fn);
889 		goto out;
890 	}
891 
892 	p.res->x509 = x;
893 	return p.res;
894 
895  dup:
896 	warnx("%s: RFC 5280 section 4.2: duplicate %s extension", fn,
897 	    OBJ_nid2sn(nid));
898  out:
899 	cert_free(p.res);
900 	X509_free(x);
901 	return NULL;
902 }
903 
904 struct cert *
905 cert_parse(const char *fn, struct cert *p)
906 {
907 	if (p == NULL)
908 		return NULL;
909 
910 	if (p->aki == NULL) {
911 		warnx("%s: RFC 6487 section 8.4.2: "
912 		    "non-trust anchor missing AKI", fn);
913 		goto badcert;
914 	}
915 	if (strcmp(p->aki, p->ski) == 0) {
916 		warnx("%s: RFC 6487 section 8.4.2: "
917 		    "non-trust anchor AKI may not match SKI", fn);
918 		goto badcert;
919 	}
920 	if (p->aia == NULL) {
921 		warnx("%s: RFC 6487 section 8.4.7: AIA: extension missing", fn);
922 		goto badcert;
923 	}
924 	if (p->crl == NULL) {
925 		warnx("%s: RFC 6487 section 4.8.6: CRL: "
926 		    "no CRL distribution point extension", fn);
927 		goto badcert;
928 	}
929 	return p;
930 
931 badcert:
932 	cert_free(p);
933 	return NULL;
934 }
935 
936 struct cert *
937 ta_parse(const char *fn, struct cert *p, const unsigned char *pkey,
938     size_t pkeysz)
939 {
940 	ASN1_TIME	*notBefore, *notAfter;
941 	EVP_PKEY	*pk, *opk;
942 
943 	if (p == NULL)
944 		return NULL;
945 
946 	/* first check pubkey against the one from the TAL */
947 	pk = d2i_PUBKEY(NULL, &pkey, pkeysz);
948 	if (pk == NULL) {
949 		warnx("%s: RFC 6487 (trust anchor): bad TAL pubkey", fn);
950 		goto badcert;
951 	}
952 	if ((opk = X509_get0_pubkey(p->x509)) == NULL) {
953 		warnx("%s: RFC 6487 (trust anchor): missing pubkey", fn);
954 		goto badcert;
955 	}
956 	if (EVP_PKEY_cmp(pk, opk) != 1) {
957 		warnx("%s: RFC 6487 (trust anchor): "
958 		    "pubkey does not match TAL pubkey", fn);
959 		goto badcert;
960 	}
961 
962 	if ((notBefore = X509_get_notBefore(p->x509)) == NULL) {
963 		warnx("%s: certificate has invalid notBefore", fn);
964 		goto badcert;
965 	}
966 	if ((notAfter = X509_get_notAfter(p->x509)) == NULL) {
967 		warnx("%s: certificate has invalid notAfter", fn);
968 		goto badcert;
969 	}
970 	if (X509_cmp_current_time(notBefore) != -1) {
971 		warnx("%s: certificate not yet valid", fn);
972 		goto badcert;
973 	}
974 	if (X509_cmp_current_time(notAfter) != 1) {
975 		warnx("%s: certificate has expired", fn);
976 		goto badcert;
977 	}
978 	if (p->aki != NULL && strcmp(p->aki, p->ski)) {
979 		warnx("%s: RFC 6487 section 8.4.2: "
980 		    "trust anchor AKI, if specified, must match SKI", fn);
981 		goto badcert;
982 	}
983 	if (p->aia != NULL) {
984 		warnx("%s: RFC 6487 section 8.4.7: "
985 		    "trust anchor must not have AIA", fn);
986 		goto badcert;
987 	}
988 	if (p->crl != NULL) {
989 		warnx("%s: RFC 6487 section 8.4.2: "
990 		    "trust anchor may not specify CRL resource", fn);
991 		goto badcert;
992 	}
993 	if (p->purpose == CERT_PURPOSE_BGPSEC_ROUTER) {
994 		warnx("%s: BGPsec cert cannot be a trust anchor", fn);
995 		goto badcert;
996 	}
997 	if (x509_any_inherits(p->x509)) {
998 		warnx("%s: Trust anchor IP/AS resources may not inherit", fn);
999 		goto badcert;
1000 	}
1001 
1002 	EVP_PKEY_free(pk);
1003 	return p;
1004 
1005 badcert:
1006 	EVP_PKEY_free(pk);
1007 	cert_free(p);
1008 	return NULL;
1009 }
1010 
1011 /*
1012  * Free parsed certificate contents.
1013  * Passing NULL is a noop.
1014  */
1015 void
1016 cert_free(struct cert *p)
1017 {
1018 	if (p == NULL)
1019 		return;
1020 
1021 	free(p->crl);
1022 	free(p->repo);
1023 	free(p->mft);
1024 	free(p->notify);
1025 	free(p->ips);
1026 	free(p->as);
1027 	free(p->aia);
1028 	free(p->aki);
1029 	free(p->ski);
1030 	free(p->pubkey);
1031 	X509_free(p->x509);
1032 	free(p);
1033 }
1034 
1035 /*
1036  * Write certificate parsed content into buffer.
1037  * See cert_read() for the other side of the pipe.
1038  */
1039 void
1040 cert_buffer(struct ibuf *b, const struct cert *p)
1041 {
1042 	io_simple_buffer(b, &p->notafter, sizeof(p->notafter));
1043 	io_simple_buffer(b, &p->purpose, sizeof(p->purpose));
1044 	io_simple_buffer(b, &p->talid, sizeof(p->talid));
1045 	io_simple_buffer(b, &p->repoid, sizeof(p->repoid));
1046 	io_simple_buffer(b, &p->ipsz, sizeof(p->ipsz));
1047 	io_simple_buffer(b, &p->asz, sizeof(p->asz));
1048 
1049 	io_simple_buffer(b, p->ips, p->ipsz * sizeof(p->ips[0]));
1050 	io_simple_buffer(b, p->as, p->asz * sizeof(p->as[0]));
1051 
1052 	io_str_buffer(b, p->mft);
1053 	io_str_buffer(b, p->notify);
1054 	io_str_buffer(b, p->repo);
1055 	io_str_buffer(b, p->crl);
1056 	io_str_buffer(b, p->aia);
1057 	io_str_buffer(b, p->aki);
1058 	io_str_buffer(b, p->ski);
1059 	io_str_buffer(b, p->pubkey);
1060 }
1061 
1062 /*
1063  * Allocate and read parsed certificate content from descriptor.
1064  * The pointer must be freed with cert_free().
1065  * Always returns a valid pointer.
1066  */
1067 struct cert *
1068 cert_read(struct ibuf *b)
1069 {
1070 	struct cert	*p;
1071 
1072 	if ((p = calloc(1, sizeof(struct cert))) == NULL)
1073 		err(1, NULL);
1074 
1075 	io_read_buf(b, &p->notafter, sizeof(p->notafter));
1076 	io_read_buf(b, &p->purpose, sizeof(p->purpose));
1077 	io_read_buf(b, &p->talid, sizeof(p->talid));
1078 	io_read_buf(b, &p->repoid, sizeof(p->repoid));
1079 	io_read_buf(b, &p->ipsz, sizeof(p->ipsz));
1080 	io_read_buf(b, &p->asz, sizeof(p->asz));
1081 
1082 	p->ips = calloc(p->ipsz, sizeof(struct cert_ip));
1083 	if (p->ips == NULL)
1084 		err(1, NULL);
1085 	io_read_buf(b, p->ips, p->ipsz * sizeof(p->ips[0]));
1086 
1087 	p->as = calloc(p->asz, sizeof(struct cert_as));
1088 	if (p->as == NULL)
1089 		err(1, NULL);
1090 	io_read_buf(b, p->as, p->asz * sizeof(p->as[0]));
1091 
1092 	io_read_str(b, &p->mft);
1093 	io_read_str(b, &p->notify);
1094 	io_read_str(b, &p->repo);
1095 	io_read_str(b, &p->crl);
1096 	io_read_str(b, &p->aia);
1097 	io_read_str(b, &p->aki);
1098 	io_read_str(b, &p->ski);
1099 	io_read_str(b, &p->pubkey);
1100 
1101 	assert(p->mft != NULL || p->purpose == CERT_PURPOSE_BGPSEC_ROUTER);
1102 	assert(p->ski);
1103 	return p;
1104 }
1105 
1106 static inline int
1107 authcmp(struct auth *a, struct auth *b)
1108 {
1109 	return strcmp(a->cert->ski, b->cert->ski);
1110 }
1111 
1112 RB_GENERATE_STATIC(auth_tree, auth, entry, authcmp);
1113 
1114 void
1115 auth_tree_free(struct auth_tree *auths)
1116 {
1117 	struct auth	*auth, *tauth;
1118 
1119 	RB_FOREACH_SAFE(auth, auth_tree, auths, tauth) {
1120 		RB_REMOVE(auth_tree, auths, auth);
1121 		cert_free(auth->cert);
1122 		free(auth);
1123 	}
1124 }
1125 
1126 struct auth *
1127 auth_find(struct auth_tree *auths, const char *aki)
1128 {
1129 	struct auth a;
1130 	struct cert c;
1131 
1132 	/* we look up the cert where the ski == aki */
1133 	c.ski = (char *)aki;
1134 	a.cert = &c;
1135 
1136 	return RB_FIND(auth_tree, auths, &a);
1137 }
1138 
1139 struct auth *
1140 auth_insert(struct auth_tree *auths, struct cert *cert, struct auth *parent)
1141 {
1142 	struct auth *na;
1143 
1144 	na = malloc(sizeof(*na));
1145 	if (na == NULL)
1146 		err(1, NULL);
1147 
1148 	na->parent = parent;
1149 	na->cert = cert;
1150 	na->any_inherits = x509_any_inherits(cert->x509);
1151 
1152 	if (RB_INSERT(auth_tree, auths, na) != NULL)
1153 		err(1, "auth tree corrupted");
1154 
1155 	return na;
1156 }
1157 
1158 static void
1159 insert_brk(struct brk_tree *tree, struct cert *cert, int asid)
1160 {
1161 	struct brk	*b, *found;
1162 
1163 	if ((b = calloc(1, sizeof(*b))) == NULL)
1164 		err(1, NULL);
1165 
1166 	b->asid = asid;
1167 	b->expires = cert->notafter;
1168 	b->talid = cert->talid;
1169 	if ((b->ski = strdup(cert->ski)) == NULL)
1170 		err(1, NULL);
1171 	if ((b->pubkey = strdup(cert->pubkey)) == NULL)
1172 		err(1, NULL);
1173 
1174 	/*
1175 	 * Check if a similar BRK already exists in the tree. If the found BRK
1176 	 * expires sooner, update it to this BRK's later expiry moment.
1177 	 */
1178 	if ((found = RB_INSERT(brk_tree, tree, b)) != NULL) {
1179 		if (found->expires < b->expires) {
1180 			found->expires = b->expires;
1181 			found->talid = b->talid;
1182 		}
1183 		free(b->ski);
1184 		free(b->pubkey);
1185 		free(b);
1186 	}
1187 }
1188 
1189 /*
1190  * Add each BGPsec Router Key into the BRK tree.
1191  */
1192 void
1193 cert_insert_brks(struct brk_tree *tree, struct cert *cert)
1194 {
1195 	size_t		 i, asid;
1196 
1197 	for (i = 0; i < cert->asz; i++) {
1198 		switch (cert->as[i].type) {
1199 		case CERT_AS_ID:
1200 			insert_brk(tree, cert, cert->as[i].id);
1201 			break;
1202 		case CERT_AS_RANGE:
1203 			for (asid = cert->as[i].range.min;
1204 			    asid <= cert->as[i].range.max; asid++)
1205 				insert_brk(tree, cert, asid);
1206 			break;
1207 		default:
1208 			warnx("invalid AS identifier type");
1209 			continue;
1210 		}
1211 	}
1212 }
1213 
1214 static inline int
1215 brkcmp(struct brk *a, struct brk *b)
1216 {
1217 	int rv;
1218 
1219 	if (a->asid > b->asid)
1220 		return 1;
1221 	if (a->asid < b->asid)
1222 		return -1;
1223 
1224 	rv = strcmp(a->ski, b->ski);
1225 	if (rv > 0)
1226 		return 1;
1227 	if (rv < 0)
1228 		return -1;
1229 
1230 	return strcmp(a->pubkey, b->pubkey);
1231 }
1232 
1233 RB_GENERATE(brk_tree, brk, entry, brkcmp);
1234