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