1 /*	$OpenBSD: cert.c,v 1.56 2022/02/04 16:50:49 tb Exp $ */
2 /*
3  * Copyright (c) 2021 Job Snijders <job@openbsd.org>
4  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/socket.h>
20 
21 #include <arpa/inet.h>
22 #include <assert.h>
23 #include <err.h>
24 #include <inttypes.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 
30 #include <openssl/asn1.h>
31 #include <openssl/x509.h>
32 #include <openssl/x509v3.h>
33 
34 #include "extern.h"
35 
36 /*
37  * Type of ASIdentifier (RFC 3779, 3.2.3).
38  */
39 #define	ASID_TYPE_ASNUM	0x00
40 #define ASID_TYPE_RDI	0x01
41 #define ASID_TYPE_MAX	ASID_TYPE_RDI
42 
43 /*
44  * A parsing sequence of a file (which may just be <stdin>).
45  */
46 struct	parse {
47 	struct cert	*res; /* result */
48 	const char	*fn; /* currently-parsed file */
49 };
50 
51 extern ASN1_OBJECT	*certpol_oid;	/* id-cp-ipAddr-asNumber cert policy */
52 extern ASN1_OBJECT	*carepo_oid;	/* 1.3.6.1.5.5.7.48.5 (caRepository) */
53 extern ASN1_OBJECT	*manifest_oid;	/* 1.3.6.1.5.5.7.48.10 (rpkiManifest) */
54 extern ASN1_OBJECT	*notify_oid;	/* 1.3.6.1.5.5.7.48.13 (rpkiNotify) */
55 
56 /*
57  * Append an IP address structure to our list of results.
58  * This will also constrain us to having at most one inheritance
59  * statement per AFI and also not have overlapping ranges (as prohibited
60  * in section 2.2.3.6).
61  * It does not make sure that ranges can't coalesce, that is, that any
62  * two ranges abut each other.
63  * This is warned against in section 2.2.3.6, but doesn't change the
64  * semantics of the system.
65  * Returns zero on failure (IP overlap) non-zero on success.
66  */
67 static int
append_ip(struct parse * p,const struct cert_ip * ip)68 append_ip(struct parse *p, const struct cert_ip *ip)
69 {
70 	struct cert	*res = p->res;
71 
72 	if (!ip_addr_check_overlap(ip, p->fn, p->res->ips, p->res->ipsz))
73 		return 0;
74 	if (res->ipsz >= MAX_IP_SIZE)
75 		return 0;
76 	res->ips = reallocarray(res->ips, res->ipsz + 1,
77 	    sizeof(struct cert_ip));
78 	if (res->ips == NULL)
79 		err(1, NULL);
80 	res->ips[res->ipsz++] = *ip;
81 	return 1;
82 }
83 
84 /*
85  * Append an AS identifier structure to our list of results.
86  * Makes sure that the identifiers do not overlap or improperly inherit
87  * as defined by RFC 3779 section 3.3.
88  */
89 static int
append_as(struct parse * p,const struct cert_as * as)90 append_as(struct parse *p, const struct cert_as *as)
91 {
92 
93 	if (!as_check_overlap(as, p->fn, p->res->as, p->res->asz))
94 		return 0;
95 	if (p->res->asz >= MAX_AS_SIZE)
96 		return 0;
97 	p->res->as = reallocarray(p->res->as, p->res->asz + 1,
98 	    sizeof(struct cert_as));
99 	if (p->res->as == NULL)
100 		err(1, NULL);
101 	p->res->as[p->res->asz++] = *as;
102 	return 1;
103 }
104 
105 /*
106  * Construct a RFC 3779 2.2.3.8 range by its bit string.
107  * Returns zero on failure, non-zero on success.
108  */
109 static int
sbgp_addr(struct parse * p,struct cert_ip * ip,const ASN1_BIT_STRING * bs)110 sbgp_addr(struct parse *p,
111 	struct cert_ip *ip, const ASN1_BIT_STRING *bs)
112 {
113 
114 	if (!ip_addr_parse(bs, ip->afi, p->fn, &ip->ip)) {
115 		warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
116 		    "invalid IP address", p->fn);
117 		return 0;
118 	}
119 	if (!ip_cert_compose_ranges(ip)) {
120 		warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
121 		    "IP address range reversed", p->fn);
122 		return 0;
123 	}
124 	return append_ip(p, ip);
125 }
126 
127 /*
128  * Parse the SIA notify URL, 4.8.8.1.
129  * Returns zero on failure, non-zero on success.
130  */
131 static int
sbgp_sia_resource_notify(struct parse * p,const char * d,size_t dsz)132 sbgp_sia_resource_notify(struct parse *p, const char *d, size_t dsz)
133 {
134 	if (p->res->notify != NULL) {
135 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
136 		    "Notify location already specified", p->fn);
137 		return 0;
138 	}
139 
140 	/* Make sure it's a https:// address. */
141 	if (!valid_uri(d, dsz, "https://")) {
142 		warnx("%s: RFC 8182 section 3.2: bad Notify URI", p->fn);
143 		return 0;
144 	}
145 
146 	if ((p->res->notify = strndup(d, dsz)) == NULL)
147 		err(1, NULL);
148 
149 	return 1;
150 }
151 
152 /*
153  * Parse the SIA manifest, 4.8.8.1.
154  * Returns zero on failure, non-zero on success.
155  */
156 static int
sbgp_sia_resource_mft(struct parse * p,const char * d,size_t dsz)157 sbgp_sia_resource_mft(struct parse *p, const char *d, size_t dsz)
158 {
159 	if (p->res->mft != NULL) {
160 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
161 		    "MFT location already specified", p->fn);
162 		return 0;
163 	}
164 
165 	/* Make sure it's an MFT rsync address. */
166 	if (!valid_uri(d, dsz, "rsync://")) {
167 		warnx("%s: RFC 6487 section 4.8.8: bad MFT location", p->fn);
168 		return 0;
169 	}
170 
171 	if (dsz < 4 || strcasecmp(d + dsz - 4, ".mft") != 0) {
172 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
173 		    "not an MFT file", p->fn);
174 		return 0;
175 	}
176 
177 	if ((p->res->mft = strndup(d, dsz)) == NULL)
178 		err(1, NULL);
179 
180 	return 1;
181 }
182 
183 /*
184  * Parse the SIA manifest, 4.8.8.1.
185  * Returns zero on failure, non-zero on success.
186  */
187 static int
sbgp_sia_resource_carepo(struct parse * p,const char * d,size_t dsz)188 sbgp_sia_resource_carepo(struct parse *p, const char *d, size_t dsz)
189 {
190 	if (p->res->repo != NULL) {
191 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
192 		    "CA repository already specified", p->fn);
193 		return 0;
194 	}
195 
196 	/* Make sure it's an rsync:// address. */
197 	if (!valid_uri(d, dsz, "rsync://")) {
198 		warnx("%s: RFC 6487 section 4.8.8: bad CA repository URI",
199 		    p->fn);
200 		return 0;
201 	}
202 
203 	if ((p->res->repo = strndup(d, dsz)) == NULL)
204 		err(1, NULL);
205 
206 	return 1;
207 }
208 
209 /*
210  * Parse the SIA entries, 4.8.8.1.
211  * There may be multiple different resources at this location, so throw
212  * out all but the matching resource type. Currently only two entries
213  * are of interest: rpkiManifest and rpkiNotify.
214  * Returns zero on failure, non-zero on success.
215  */
216 static int
sbgp_sia_resource_entry(struct parse * p,const unsigned char * d,size_t dsz)217 sbgp_sia_resource_entry(struct parse *p,
218 	const unsigned char *d, size_t dsz)
219 {
220 	ASN1_SEQUENCE_ANY	*seq;
221 	ASN1_OBJECT		*oid;
222 	const ASN1_TYPE		*t;
223 	int			 rc = 0, ptag;
224 	long			 plen;
225 
226 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
227 		cryptowarnx("%s: RFC 6487 section 4.8.8: SIA: "
228 		    "failed ASN.1 sequence parse", p->fn);
229 		goto out;
230 	}
231 	if (sk_ASN1_TYPE_num(seq) != 2) {
232 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
233 		    "want 2 elements, have %d",
234 		    p->fn, sk_ASN1_TYPE_num(seq));
235 		goto out;
236 	}
237 
238 	/* Composed of an OID and its continuation. */
239 
240 	t = sk_ASN1_TYPE_value(seq, 0);
241 	if (t->type != V_ASN1_OBJECT) {
242 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
243 		    "want ASN.1 object, have %s (NID %d)",
244 		    p->fn, ASN1_tag2str(t->type), t->type);
245 		goto out;
246 	}
247 	oid = t->value.object;
248 
249 	t = sk_ASN1_TYPE_value(seq, 1);
250 	if (t->type != V_ASN1_OTHER) {
251 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
252 		    "want ASN.1 external, have %s (NID %d)",
253 		    p->fn, ASN1_tag2str(t->type), t->type);
254 		goto out;
255 	}
256 
257 	/* FIXME: there must be a way to do this without ASN1_frame. */
258 
259 	d = t->value.asn1_string->data;
260 	dsz = t->value.asn1_string->length;
261 	if (!ASN1_frame(p->fn, dsz, &d, &plen, &ptag))
262 		goto out;
263 
264 	if (OBJ_cmp(oid, carepo_oid) == 0)
265 		rc = sbgp_sia_resource_carepo(p, d, plen);
266 	else if (OBJ_cmp(oid, manifest_oid) == 0)
267 		rc = sbgp_sia_resource_mft(p, d, plen);
268 	else if (OBJ_cmp(oid, notify_oid) == 0)
269 		rc = sbgp_sia_resource_notify(p, d, plen);
270 	else
271 		rc = 1;	/* silently ignore */
272 out:
273 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
274 	return rc;
275 }
276 
277 /*
278  * Multiple locations as defined in RFC 6487, 4.8.8.1.
279  * Returns zero on failure, non-zero on success.
280  */
281 static int
sbgp_sia_resource(struct parse * p,const unsigned char * d,size_t dsz)282 sbgp_sia_resource(struct parse *p, const unsigned char *d, size_t dsz)
283 {
284 	ASN1_SEQUENCE_ANY	*seq;
285 	const ASN1_TYPE		*t;
286 	int			 rc = 0, i;
287 
288 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
289 		cryptowarnx("%s: RFC 6487 section 4.8.8: SIA: "
290 		    "failed ASN.1 sequence parse", p->fn);
291 		goto out;
292 	}
293 
294 	for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) {
295 		t = sk_ASN1_TYPE_value(seq, i);
296 		if (t->type != V_ASN1_SEQUENCE) {
297 			warnx("%s: RFC 6487 section 4.8.8: SIA: "
298 			    "want ASN.1 sequence, have %s (NID %d)",
299 			    p->fn, ASN1_tag2str(t->type), t->type);
300 			goto out;
301 		}
302 		d = t->value.asn1_string->data;
303 		dsz = t->value.asn1_string->length;
304 		if (!sbgp_sia_resource_entry(p, d, dsz))
305 			goto out;
306 	}
307 
308 	if (strstr(p->res->mft, p->res->repo) != p->res->mft) {
309 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
310 		    "conflicting URIs for caRepository and rpkiManifest",
311 		    p->fn);
312 		goto out;
313 	}
314 	rc = 1;
315 out:
316 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
317 	return rc;
318 }
319 
320 /*
321  * Parse "Subject Information Access" extension, RFC 6487 4.8.8.
322  * Returns zero on failure, non-zero on success.
323  */
324 static int
sbgp_sia(struct parse * p,X509_EXTENSION * ext)325 sbgp_sia(struct parse *p, X509_EXTENSION *ext)
326 {
327 	unsigned char		*sv = NULL;
328 	const unsigned char	*d;
329 	ASN1_SEQUENCE_ANY	*seq = NULL;
330 	const ASN1_TYPE		*t;
331 	int			 dsz, rc = 0;
332 
333 	if ((dsz = i2d_X509_EXTENSION(ext, &sv)) < 0) {
334 		cryptowarnx("%s: RFC 6487 section 4.8.8: SIA: "
335 		    "failed extension parse", p->fn);
336 		goto out;
337 	}
338 	d = sv;
339 
340 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
341 		cryptowarnx("%s: RFC 6487 section 4.8.8: SIA: "
342 		    "failed ASN.1 sequence parse", p->fn);
343 		goto out;
344 	}
345 	if (sk_ASN1_TYPE_num(seq) != 2) {
346 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
347 		    "want 2 elements, have %d", p->fn,
348 		    sk_ASN1_TYPE_num(seq));
349 		goto out;
350 	}
351 
352 	t = sk_ASN1_TYPE_value(seq, 0);
353 	if (t->type != V_ASN1_OBJECT) {
354 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
355 		    "want ASN.1 object, have %s (NID %d)",
356 		    p->fn, ASN1_tag2str(t->type), t->type);
357 		goto out;
358 	}
359 	if (OBJ_obj2nid(t->value.object) != NID_sinfo_access) {
360 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
361 		    "incorrect OID, have %s (NID %d)", p->fn,
362 		    ASN1_tag2str(OBJ_obj2nid(t->value.object)),
363 		    OBJ_obj2nid(t->value.object));
364 		goto out;
365 	}
366 
367 	t = sk_ASN1_TYPE_value(seq, 1);
368 	if (t->type != V_ASN1_OCTET_STRING) {
369 		warnx("%s: RFC 6487 section 4.8.8: SIA: "
370 		    "want ASN.1 octet string, have %s (NID %d)",
371 		    p->fn, ASN1_tag2str(t->type), t->type);
372 		goto out;
373 	}
374 
375 	d = t->value.octet_string->data;
376 	dsz = t->value.octet_string->length;
377 	if (!sbgp_sia_resource(p, d, dsz))
378 		goto out;
379 
380 	rc = 1;
381 out:
382 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
383 	free(sv);
384 	return rc;
385 }
386 
387 /*
388  * Parse a range of addresses as in 3.2.3.8.
389  * Returns zero on failure, non-zero on success.
390  */
391 static int
sbgp_asrange(struct parse * p,const unsigned char * d,size_t dsz)392 sbgp_asrange(struct parse *p, const unsigned char *d, size_t dsz)
393 {
394 	struct cert_as		 as;
395 	ASN1_SEQUENCE_ANY	*seq;
396 	const ASN1_TYPE		*t;
397 	int			 rc = 0;
398 
399 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
400 		cryptowarnx("%s: RFC 3779 section 3.2.3.8: ASRange: "
401 		    "failed ASN.1 sequence parse", p->fn);
402 		goto out;
403 	}
404 	if (sk_ASN1_TYPE_num(seq) != 2) {
405 		warnx("%s: RFC 3779 section 3.2.3.8: ASRange: "
406 		    "want 2 elements, have %d", p->fn,
407 		    sk_ASN1_TYPE_num(seq));
408 		goto out;
409 	}
410 
411 	memset(&as, 0, sizeof(struct cert_as));
412 	as.type = CERT_AS_RANGE;
413 
414 	t = sk_ASN1_TYPE_value(seq, 0);
415 	if (t->type != V_ASN1_INTEGER) {
416 		warnx("%s: RFC 3779 section 3.2.3.8: ASRange: "
417 		    "want ASN.1 integer, have %s (NID %d)",
418 		    p->fn, ASN1_tag2str(t->type), t->type);
419 		goto out;
420 	}
421 	if (!as_id_parse(t->value.integer, &as.range.min)) {
422 		warnx("%s: RFC 3779 section 3.2.3.8 (via RFC 1930): "
423 		    "malformed AS identifier", p->fn);
424 		return 0;
425 	}
426 
427 	t = sk_ASN1_TYPE_value(seq, 1);
428 	if (t->type != V_ASN1_INTEGER) {
429 		warnx("%s: RFC 3779 section 3.2.3.8: ASRange: "
430 		    "want ASN.1 integer, have %s (NID %d)",
431 		    p->fn, ASN1_tag2str(t->type), t->type);
432 		goto out;
433 	}
434 	if (!as_id_parse(t->value.integer, &as.range.max)) {
435 		warnx("%s: RFC 3779 section 3.2.3.8 (via RFC 1930): "
436 		    "malformed AS identifier", p->fn);
437 		return 0;
438 	}
439 
440 	if (as.range.max == as.range.min) {
441 		warnx("%s: RFC 3379 section 3.2.3.8: ASRange: "
442 		    "range is singular", p->fn);
443 		goto out;
444 	} else if (as.range.max < as.range.min) {
445 		warnx("%s: RFC 3379 section 3.2.3.8: ASRange: "
446 		    "range is out of order", p->fn);
447 		goto out;
448 	}
449 
450 	if (!append_as(p, &as))
451 		goto out;
452 	rc = 1;
453 out:
454 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
455 	return rc;
456 }
457 
458 /*
459  * Parse an entire 3.2.3.10 integer type.
460  */
461 static int
sbgp_asid(struct parse * p,const ASN1_INTEGER * i)462 sbgp_asid(struct parse *p, const ASN1_INTEGER *i)
463 {
464 	struct cert_as	 as;
465 
466 	memset(&as, 0, sizeof(struct cert_as));
467 	as.type = CERT_AS_ID;
468 
469 	if (!as_id_parse(i, &as.id)) {
470 		warnx("%s: RFC 3779 section 3.2.3.10 (via RFC 1930): "
471 		    "malformed AS identifier", p->fn);
472 		return 0;
473 	}
474 	if (as.id == 0) {
475 		warnx("%s: RFC 3779 section 3.2.3.10 (via RFC 1930): "
476 		    "AS identifier zero is reserved", p->fn);
477 		return 0;
478 	}
479 
480 	return append_as(p, &as);
481 }
482 
483 /*
484  * Parse one of RFC 3779 3.2.3.2.
485  * Returns zero on failure, non-zero on success.
486  */
487 static int
sbgp_asnum(struct parse * p,const unsigned char * d,size_t dsz)488 sbgp_asnum(struct parse *p, const unsigned char *d, size_t dsz)
489 {
490 	struct cert_as		 as;
491 	ASN1_TYPE		*t, *tt;
492 	ASN1_SEQUENCE_ANY	*seq = NULL;
493 	int			 i, rc = 0;
494 	const unsigned char	*sv = d;
495 
496 	/* We can either be a null (inherit) or sequence. */
497 
498 	if ((t = d2i_ASN1_TYPE(NULL, &d, dsz)) == NULL) {
499 		cryptowarnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
500 		    "failed ASN.1 type parse", p->fn);
501 		goto out;
502 	}
503 
504 	/*
505 	 * Section 3779 3.2.3.3 is to inherit with an ASN.1 NULL type,
506 	 * which is the easy case.
507 	 */
508 
509 	switch (t->type) {
510 	case V_ASN1_NULL:
511 		memset(&as, 0, sizeof(struct cert_as));
512 		as.type = CERT_AS_INHERIT;
513 		if (!append_as(p, &as))
514 			goto out;
515 		rc = 1;
516 		goto out;
517 	case V_ASN1_SEQUENCE:
518 		break;
519 	default:
520 		warnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
521 		    "want ASN.1 sequence or null, have %s (NID %d)",
522 		    p->fn, ASN1_tag2str(t->type), t->type);
523 		goto out;
524 	}
525 
526 	/* This is RFC 3779 3.2.3.4. */
527 
528 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &sv, dsz)) == NULL) {
529 		cryptowarnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
530 		    "failed ASN.1 sequence parse", p->fn);
531 		goto out;
532 	}
533 
534 	/* Accepts RFC 3779 3.2.3.6 or 3.2.3.7 (sequence). */
535 
536 	for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) {
537 		tt = sk_ASN1_TYPE_value(seq, i);
538 		switch (tt->type) {
539 		case V_ASN1_INTEGER:
540 			if (!sbgp_asid(p, tt->value.integer))
541 				goto out;
542 			break;
543 		case V_ASN1_SEQUENCE:
544 			d = tt->value.asn1_string->data;
545 			dsz = tt->value.asn1_string->length;
546 			if (!sbgp_asrange(p, d, dsz))
547 				goto out;
548 			break;
549 		default:
550 			warnx("%s: RFC 3779 section 3.2.3.5: ASIdOrRange: "
551 			    "want ASN.1 sequence or integer, have %s (NID %d)",
552 			    p->fn, ASN1_tag2str(tt->type), tt->type);
553 			goto out;
554 		}
555 	}
556 
557 	rc = 1;
558 out:
559 	ASN1_TYPE_free(t);
560 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
561 	return rc;
562 }
563 
564 /*
565  * Parse RFC 6487 4.8.11 X509v3 extension, with syntax documented in RFC
566  * 3779 starting in section 3.2.
567  * Returns zero on failure, non-zero on success.
568  */
569 static int
sbgp_assysnum(struct parse * p,X509_EXTENSION * ext)570 sbgp_assysnum(struct parse *p, X509_EXTENSION *ext)
571 {
572 	unsigned char		*sv = NULL;
573 	const unsigned char	*d;
574 	ASN1_SEQUENCE_ANY	*seq = NULL, *sseq = NULL;
575 	const ASN1_TYPE		*t;
576 	int			 dsz, rc = 0, i, ptag;
577 	long			 plen;
578 
579 	if (!X509_EXTENSION_get_critical(ext)) {
580 		cryptowarnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
581 		    "extension not critical", p->fn);
582 		goto out;
583 	}
584 
585 	if ((dsz = i2d_X509_EXTENSION(ext, &sv)) < 0) {
586 		cryptowarnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
587 		    "failed extension parse", p->fn);
588 		goto out;
589 	}
590 
591 	/* Start with RFC 3779, section 3.2 top-level. */
592 
593 	d = sv;
594 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
595 		cryptowarnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
596 		    "failed ASN.1 sequence parse", p->fn);
597 		goto out;
598 	}
599 	if (sk_ASN1_TYPE_num(seq) != 3) {
600 		warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
601 		    "want 3 elements, have %d", p->fn,
602 		    sk_ASN1_TYPE_num(seq));
603 		goto out;
604 	}
605 
606 	t = sk_ASN1_TYPE_value(seq, 0);
607 	if (t->type != V_ASN1_OBJECT) {
608 		warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
609 		    "want ASN.1 object, have %s (NID %d)",
610 		    p->fn, ASN1_tag2str(t->type), t->type);
611 		goto out;
612 	}
613 
614 	/* FIXME: verify OID. */
615 
616 	t = sk_ASN1_TYPE_value(seq, 1);
617 	if (t->type != V_ASN1_BOOLEAN) {
618 		warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
619 		    "want ASN.1 boolean, have %s (NID %d)",
620 		    p->fn, ASN1_tag2str(t->type), t->type);
621 		goto out;
622 	}
623 
624 	t = sk_ASN1_TYPE_value(seq, 2);
625 	if (t->type != V_ASN1_OCTET_STRING) {
626 		warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
627 		    "want ASN.1 octet string, have %s (NID %d)",
628 		    p->fn, ASN1_tag2str(t->type), t->type);
629 		goto out;
630 	}
631 
632 	/* Within RFC 3779 3.2.3, check 3.2.3.1. */
633 
634 	d = t->value.octet_string->data;
635 	dsz = t->value.octet_string->length;
636 
637 	if ((sseq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
638 		cryptowarnx("%s: RFC 3779 section 3.2.3.1: ASIdentifiers: "
639 		    "failed ASN.1 sequence parse", p->fn);
640 		goto out;
641 	}
642 
643 	/* Scan through for private 3.2.3.2 classes. */
644 
645 	for (i = 0; i < sk_ASN1_TYPE_num(sseq); i++) {
646 		t = sk_ASN1_TYPE_value(sseq, i);
647 		if (t->type != V_ASN1_OTHER) {
648 			warnx("%s: RFC 3779 section 3.2.3.1: ASIdentifiers: "
649 			    "want ASN.1 explicit, have %s (NID %d)", p->fn,
650 			    ASN1_tag2str(t->type), t->type);
651 			goto out;
652 		}
653 
654 		/* Use the low-level ASN1_frame. */
655 
656 		d = t->value.asn1_string->data;
657 		dsz = t->value.asn1_string->length;
658 		if (!ASN1_frame(p->fn, dsz, &d, &plen, &ptag))
659 			goto out;
660 
661 		/* Ignore bad AS identifiers and RDI entries. */
662 
663 		if (ptag > ASID_TYPE_MAX) {
664 			warnx("%s: RFC 3779 section 3.2.3.1: ASIdentifiers: "
665 			    "unknown explicit tag 0x%02x", p->fn, ptag);
666 			goto out;
667 		} else if (ptag == ASID_TYPE_RDI)
668 			continue;
669 
670 		if (!sbgp_asnum(p, d, plen))
671 			goto out;
672 	}
673 
674 	rc = 1;
675 out:
676 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
677 	sk_ASN1_TYPE_pop_free(sseq, ASN1_TYPE_free);
678 	free(sv);
679 	return rc;
680 }
681 
682 /*
683  * Parse RFC 3779 2.2.3.9 range of addresses.
684  * Returns zero on failure, non-zero on success.
685  */
686 static int
sbgp_addr_range(struct parse * p,struct cert_ip * ip,const unsigned char * d,size_t dsz)687 sbgp_addr_range(struct parse *p, struct cert_ip *ip,
688 	const unsigned char *d, size_t dsz)
689 {
690 	ASN1_SEQUENCE_ANY	*seq;
691 	const ASN1_TYPE		*t;
692 	int			 rc = 0;
693 
694 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
695 		cryptowarnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
696 		    "failed ASN.1 sequence parse", p->fn);
697 		goto out;
698 	}
699 	if (sk_ASN1_TYPE_num(seq) != 2) {
700 		warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
701 		    "want 2 elements, have %d", p->fn, sk_ASN1_TYPE_num(seq));
702 		goto out;
703 	}
704 
705 	t = sk_ASN1_TYPE_value(seq, 0);
706 	if (t->type != V_ASN1_BIT_STRING) {
707 		warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
708 		    "want ASN.1 bit string, have %s (NID %d)",
709 		    p->fn, ASN1_tag2str(t->type), t->type);
710 		goto out;
711 	}
712 	if (!ip_addr_parse(t->value.bit_string,
713 	    ip->afi, p->fn, &ip->range.min)) {
714 		warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
715 		    "invalid IP address", p->fn);
716 		goto out;
717 	}
718 
719 	t = sk_ASN1_TYPE_value(seq, 1);
720 	if (t->type != V_ASN1_BIT_STRING) {
721 		warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
722 		    "want ASN.1 bit string, have %s (NID %d)",
723 		    p->fn, ASN1_tag2str(t->type), t->type);
724 		goto out;
725 	}
726 	if (!ip_addr_parse(t->value.bit_string,
727 	    ip->afi, p->fn, &ip->range.max)) {
728 		warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
729 		    "invalid IP address", p->fn);
730 		goto out;
731 	}
732 
733 	if (!ip_cert_compose_ranges(ip)) {
734 		warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
735 		    "IP address range reversed", p->fn);
736 		return 0;
737 	}
738 
739 	rc = append_ip(p, ip);
740 out:
741 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
742 	return rc;
743 }
744 
745 /*
746  * Parse an IP address or range, RFC 3779 2.2.3.7.
747  * We don't constrain this parse (as specified in section 2.2.3.6) to
748  * having any kind of order.
749  * Returns zero on failure, non-zero on success.
750  */
751 static int
sbgp_addr_or_range(struct parse * p,struct cert_ip * ip,const unsigned char * d,size_t dsz)752 sbgp_addr_or_range(struct parse *p, struct cert_ip *ip,
753 	const unsigned char *d, size_t dsz)
754 {
755 	struct cert_ip		 nip;
756 	ASN1_SEQUENCE_ANY	*seq;
757 	const ASN1_TYPE		*t;
758 	int			 i, rc = 0;
759 
760 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
761 		cryptowarnx("%s: RFC 3779 section 2.2.3.7: IPAddressOrRange: "
762 		    "failed ASN.1 sequence parse", p->fn);
763 		goto out;
764 	}
765 
766 	/* Either RFC 3779 2.2.3.8 or 2.2.3.9. */
767 
768 	for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) {
769 		nip = *ip;
770 		t = sk_ASN1_TYPE_value(seq, i);
771 		switch (t->type) {
772 		case V_ASN1_BIT_STRING:
773 			nip.type = CERT_IP_ADDR;
774 			if (!sbgp_addr(p, &nip, t->value.bit_string))
775 				goto out;
776 			break;
777 		case V_ASN1_SEQUENCE:
778 			nip.type = CERT_IP_RANGE;
779 			d = t->value.asn1_string->data;
780 			dsz = t->value.asn1_string->length;
781 			if (!sbgp_addr_range(p, &nip, d, dsz))
782 				goto out;
783 			break;
784 		default:
785 			warnx("%s: RFC 3779 section 2.2.3.7: IPAddressOrRange: "
786 			    "want ASN.1 sequence or bit string, have %s (NID %d)",
787 			    p->fn, ASN1_tag2str(t->type), t->type);
788 			goto out;
789 		}
790 	}
791 
792 	rc = 1;
793 out:
794 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
795 	return rc;
796 }
797 
798 /*
799  * Parse a sequence of address families as in RFC 3779 sec. 2.2.3.2.
800  * Ignore several stipulations of the RFC (2.2.3.3).
801  * Namely, we don't require entries to be ordered in any way (type, AFI
802  * or SAFI group, etc.).
803  * This is because it doesn't matter for our purposes: we're going to
804  * validate in the same way regardless.
805  * Returns zero no failure, non-zero on success.
806  */
807 static int
sbgp_ipaddrfam(struct parse * p,const unsigned char * d,size_t dsz)808 sbgp_ipaddrfam(struct parse *p, const unsigned char *d, size_t dsz)
809 {
810 	struct cert_ip		 ip;
811 	ASN1_SEQUENCE_ANY	*seq;
812 	const ASN1_TYPE		*t;
813 	int			 rc = 0;
814 
815 	memset(&ip, 0, sizeof(struct cert_ip));
816 
817 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
818 		cryptowarnx("%s: RFC 3779 section 2.2.3.2: IPAddressFamily: "
819 		    "failed ASN.1 sequence parse", p->fn);
820 		goto out;
821 	}
822 	if (sk_ASN1_TYPE_num(seq) != 2) {
823 		warnx("%s: RFC 3779 section 2.2.3.2: IPAddressFamily: "
824 		    "want 2 elements, have %d",
825 		    p->fn, sk_ASN1_TYPE_num(seq));
826 		goto out;
827 	}
828 
829 	/* Get address family, RFC 3779, 2.2.3.3. */
830 
831 	t = sk_ASN1_TYPE_value(seq, 0);
832 	if (t->type != V_ASN1_OCTET_STRING) {
833 		warnx("%s: RFC 3779 section 2.2.3.2: addressFamily: "
834 		    "want ASN.1 octet string, have %s (NID %d)",
835 		    p->fn, ASN1_tag2str(t->type), t->type);
836 		goto out;
837 	}
838 
839 	if (!ip_addr_afi_parse(p->fn, t->value.octet_string, &ip.afi)) {
840 		warnx("%s: RFC 3779 section 2.2.3.2: addressFamily: "
841 		    "invalid AFI", p->fn);
842 		goto out;
843 	}
844 
845 	/* Either sequence or null (inherit), RFC 3779 sec. 2.2.3.4. */
846 
847 	t = sk_ASN1_TYPE_value(seq, 1);
848 	switch (t->type) {
849 	case V_ASN1_SEQUENCE:
850 		d = t->value.asn1_string->data;
851 		dsz = t->value.asn1_string->length;
852 		if (!sbgp_addr_or_range(p, &ip, d, dsz))
853 			goto out;
854 		break;
855 	case V_ASN1_NULL:
856 		ip.type = CERT_IP_INHERIT;
857 		if (!append_ip(p, &ip))
858 			goto out;
859 		break;
860 	default:
861 		warnx("%s: RFC 3779 section 2.2.3.2: IPAddressChoice: "
862 		    "want ASN.1 sequence or null, have %s (NID %d)",
863 		    p->fn, ASN1_tag2str(t->type), t->type);
864 		goto out;
865 	}
866 
867 	rc = 1;
868 out:
869 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
870 	return rc;
871 }
872 
873 /*
874  * Parse an sbgp-ipAddrBlock X509 extension, RFC 6487 4.8.10, with
875  * syntax documented in RFC 3779 starting in section 2.2.
876  * Returns zero on failure, non-zero on success.
877  */
878 static int
sbgp_ipaddrblk(struct parse * p,X509_EXTENSION * ext)879 sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext)
880 {
881 	int			 dsz, rc = 0;
882 	unsigned char		*sv = NULL;
883 	const unsigned char	*d;
884 	ASN1_SEQUENCE_ANY	*seq = NULL, *sseq = NULL;
885 	const ASN1_TYPE		*t = NULL;
886 	int			 i;
887 
888 	if (!X509_EXTENSION_get_critical(ext)) {
889 		cryptowarnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
890 		    "extension not critical", p->fn);
891 		goto out;
892 	}
893 
894 	if ((dsz = i2d_X509_EXTENSION(ext, &sv)) < 0) {
895 		cryptowarnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
896 		    "failed extension parse", p->fn);
897 		goto out;
898 	}
899 	d = sv;
900 
901 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
902 		cryptowarnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
903 		    "failed ASN.1 sequence parse", p->fn);
904 		goto out;
905 	}
906 	if (sk_ASN1_TYPE_num(seq) != 3) {
907 		warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
908 		    "want 3 elements, have %d",
909 		    p->fn, sk_ASN1_TYPE_num(seq));
910 		goto out;
911 	}
912 
913 	t = sk_ASN1_TYPE_value(seq, 0);
914 	if (t->type != V_ASN1_OBJECT) {
915 		warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
916 		    "want ASN.1 object, have %s (NID %d)",
917 		    p->fn, ASN1_tag2str(t->type), t->type);
918 		goto out;
919 	}
920 
921 	/* FIXME: verify OID. */
922 
923 	t = sk_ASN1_TYPE_value(seq, 1);
924 	if (t->type != V_ASN1_BOOLEAN) {
925 		warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
926 		    "want ASN.1 boolean, have %s (NID %d)",
927 		    p->fn, ASN1_tag2str(t->type), t->type);
928 		goto out;
929 	}
930 
931 	t = sk_ASN1_TYPE_value(seq, 2);
932 	if (t->type != V_ASN1_OCTET_STRING) {
933 		warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
934 		    "want ASN.1 octet string, have %s (NID %d)",
935 		    p->fn, ASN1_tag2str(t->type), t->type);
936 		goto out;
937 	}
938 
939 	/* The blocks sequence, RFC 3779 2.2.3.1. */
940 
941 	d = t->value.octet_string->data;
942 	dsz = t->value.octet_string->length;
943 
944 	if ((sseq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
945 		cryptowarnx("%s: RFC 3779 section 2.2.3.1: IPAddrBlocks: "
946 		    "failed ASN.1 sequence parse", p->fn);
947 		goto out;
948 	}
949 
950 	/* Each sequence element contains RFC 3779 sec. 2.2.3.2. */
951 
952 	for (i = 0; i < sk_ASN1_TYPE_num(sseq); i++) {
953 		t = sk_ASN1_TYPE_value(sseq, i);
954 		if (t->type != V_ASN1_SEQUENCE) {
955 			warnx("%s: RFC 3779 section 2.2.3.2: IPAddressFamily: "
956 			    "want ASN.1 sequence, have %s (NID %d)",
957 			    p->fn, ASN1_tag2str(t->type), t->type);
958 			goto out;
959 		}
960 		d = t->value.asn1_string->data;
961 		dsz = t->value.asn1_string->length;
962 		if (!sbgp_ipaddrfam(p, d, dsz))
963 			goto out;
964 	}
965 
966 	rc = 1;
967 out:
968 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
969 	sk_ASN1_TYPE_pop_free(sseq, ASN1_TYPE_free);
970 	free(sv);
971 	return rc;
972 }
973 
974 /*
975  * Parse the certificate policies extension and check that it follows RFC 7318.
976  * Returns zero on failure, non-zero on success.
977  */
978 static int
certificate_policies(struct parse * p,X509_EXTENSION * ext)979 certificate_policies(struct parse *p, X509_EXTENSION *ext)
980 {
981 	STACK_OF(POLICYINFO)		*policies = NULL;
982 	POLICYINFO			*policy;
983 	STACK_OF(POLICYQUALINFO)	*qualifiers;
984 	POLICYQUALINFO			*qualifier;
985 	int				 nid;
986 	int				 rc = 0;
987 
988 	if (!X509_EXTENSION_get_critical(ext)) {
989 		cryptowarnx("%s: RFC 6487 section 4.8.9: certificatePolicies: "
990 		    "extension not critical", p->fn);
991 		goto out;
992 	}
993 
994 	if ((policies = X509V3_EXT_d2i(ext)) == NULL) {
995 		cryptowarnx("%s: RFC 6487 section 4.8.9: certificatePolicies: "
996 		    "failed extension parse", p->fn);
997 		goto out;
998 	}
999 
1000 	if (sk_POLICYINFO_num(policies) != 1) {
1001 		warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: "
1002 		    "want 1 policy, got %d", p->fn,
1003 		    sk_POLICYINFO_num(policies));
1004 		goto out;
1005 	}
1006 
1007 	policy = sk_POLICYINFO_value(policies, 0);
1008 	assert(policy != NULL && policy->policyid != NULL);
1009 
1010 	if (OBJ_cmp(policy->policyid, certpol_oid) != 0) {
1011 		char pbuf[128], cbuf[128];
1012 
1013 		OBJ_obj2txt(pbuf, sizeof(pbuf), policy->policyid, 1);
1014 		OBJ_obj2txt(cbuf, sizeof(cbuf), certpol_oid, 1);
1015 		warnx("%s: RFC 7318 section 2: certificatePolicies: "
1016 		    "unexpected OID: %s, want %s", p->fn, pbuf, cbuf);
1017 		goto out;
1018 	}
1019 
1020 	/* Policy qualifiers are optional. If they're absent, we're done. */
1021 	if ((qualifiers = policy->qualifiers) == NULL) {
1022 		rc = 1;
1023 		goto out;
1024 	}
1025 
1026 	if (sk_POLICYQUALINFO_num(qualifiers) != 1) {
1027 		warnx("%s: RFC 7318 section 2: certificatePolicies: "
1028 		    "want 1 policy qualifier, got %d", p->fn,
1029 		    sk_POLICYQUALINFO_num(qualifiers));
1030 		goto out;
1031 	}
1032 
1033 	qualifier = sk_POLICYQUALINFO_value(qualifiers, 0);
1034 	assert(qualifier != NULL && qualifier->pqualid != NULL);
1035 
1036 	if ((nid = OBJ_obj2nid(qualifier->pqualid)) != NID_id_qt_cps) {
1037 		warnx("%s: RFC 7318 section 2: certificatePolicies: "
1038 		    "want CPS, got %d (%s)", p->fn, nid, OBJ_nid2sn(nid));
1039 		goto out;
1040 	}
1041 
1042 	if (verbose > 1)
1043 		warnx("%s: CPS %.*s", p->fn, qualifier->d.cpsuri->length,
1044 		    qualifier->d.cpsuri->data);
1045 
1046 	rc = 1;
1047  out:
1048 	sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
1049 	return rc;
1050 }
1051 
1052 /*
1053  * Parse and partially validate an RPKI X509 certificate (either a trust
1054  * anchor or a certificate) as defined in RFC 6487.
1055  * If "ta" is set, this is a trust anchor and must be self-signed.
1056  * Returns the parse results or NULL on failure ("xp" will be NULL too).
1057  * On success, free the pointer with cert_free() and make sure that "xp"
1058  * is also dereferenced.
1059  */
1060 static struct cert *
cert_parse_inner(const char * fn,const unsigned char * der,size_t len,int ta)1061 cert_parse_inner(const char *fn, const unsigned char *der, size_t len, int ta)
1062 {
1063 	int		 rc = 0, extsz, c;
1064 	int		 sia_present = 0;
1065 	size_t		 i;
1066 	X509		*x = NULL;
1067 	X509_EXTENSION	*ext = NULL;
1068 	ASN1_OBJECT	*obj;
1069 	struct parse	 p;
1070 
1071 	/* just fail for empty buffers, the warning was printed elsewhere */
1072 	if (der == NULL)
1073 		return NULL;
1074 
1075 	memset(&p, 0, sizeof(struct parse));
1076 	p.fn = fn;
1077 	if ((p.res = calloc(1, sizeof(struct cert))) == NULL)
1078 		err(1, NULL);
1079 
1080 	if ((x = d2i_X509(NULL, &der, len)) == NULL) {
1081 		cryptowarnx("%s: d2i_X509_bio", p.fn);
1082 		goto out;
1083 	}
1084 
1085 	/* Look for X509v3 extensions. */
1086 
1087 	if ((extsz = X509_get_ext_count(x)) < 0)
1088 		cryptoerrx("X509_get_ext_count");
1089 
1090 	for (i = 0; i < (size_t)extsz; i++) {
1091 		ext = X509_get_ext(x, i);
1092 		assert(ext != NULL);
1093 		obj = X509_EXTENSION_get_object(ext);
1094 		assert(obj != NULL);
1095 		c = 1;
1096 
1097 		switch (OBJ_obj2nid(obj)) {
1098 		case NID_sbgp_ipAddrBlock:
1099 			c = sbgp_ipaddrblk(&p, ext);
1100 			break;
1101 		case NID_sbgp_autonomousSysNum:
1102 			c = sbgp_assysnum(&p, ext);
1103 			break;
1104 		case NID_sinfo_access:
1105 			sia_present = 1;
1106 			c = sbgp_sia(&p, ext);
1107 			break;
1108 		case NID_certificate_policies:
1109 			c = certificate_policies(&p, ext);
1110 			break;
1111 		case NID_crl_distribution_points:
1112 			/* ignored here, handled later */
1113 			break;
1114 		case NID_info_access:
1115 			break;
1116 		case NID_authority_key_identifier:
1117 			break;
1118 		case NID_subject_key_identifier:
1119 			break;
1120 		case NID_ext_key_usage:
1121 			break;
1122 		default:
1123 			/* {
1124 				char objn[64];
1125 				OBJ_obj2txt(objn, sizeof(objn), obj, 0);
1126 				warnx("%s: ignoring %s (NID %d)",
1127 					p.fn, objn, OBJ_obj2nid(obj));
1128 			} */
1129 			break;
1130 		}
1131 		if (c == 0)
1132 			goto out;
1133 	}
1134 
1135 	p.res->aki = x509_get_aki(x, ta, p.fn);
1136 	p.res->ski = x509_get_ski(x, p.fn);
1137 	if (!ta) {
1138 		p.res->aia = x509_get_aia(x, p.fn);
1139 		p.res->crl = x509_get_crl(x, p.fn);
1140 	}
1141 	if (!x509_get_expire(x, p.fn, &p.res->expires))
1142 		goto out;
1143 	p.res->purpose = x509_get_purpose(x, p.fn);
1144 
1145 	/* Validation on required fields. */
1146 
1147 	switch (p.res->purpose) {
1148 	case CERT_PURPOSE_CA:
1149 		if (p.res->mft == NULL) {
1150 			warnx("%s: RFC 6487 section 4.8.8: missing SIA", p.fn);
1151 			goto out;
1152 		}
1153 		if (p.res->asz == 0 && p.res->ipsz == 0) {
1154 			warnx("%s: missing IP or AS resources", p.fn);
1155 			goto out;
1156 		}
1157 		break;
1158 	case CERT_PURPOSE_BGPSEC_ROUTER:
1159 		p.res->pubkey = x509_get_pubkey(x, p.fn);
1160 		if (p.res->pubkey == NULL) {
1161 			warnx("%s: x509_get_pubkey failed", p.fn);
1162 			goto out;
1163 		}
1164 		if (p.res->ipsz > 0) {
1165 			warnx("%s: unexpected IP resources in BGPsec cert",
1166 			   p.fn);
1167 			goto out;
1168 		}
1169 		if (sia_present) {
1170 			warnx("%s: unexpected SIA extension in BGPsec cert",
1171 			   p.fn);
1172 			goto out;
1173 		}
1174 		if (ta) {
1175 			warnx("%s: BGPsec cert can not be a trust anchor",
1176 			   p.fn);
1177 			goto out;
1178 		}
1179 		break;
1180 	default:
1181 		warnx("%s: x509_get_purpose failed in %s", p.fn, __func__);
1182 		goto out;
1183 	}
1184 
1185 	if (p.res->ski == NULL) {
1186 		warnx("%s: RFC 6487 section 8.4.2: missing SKI", p.fn);
1187 		goto out;
1188 	}
1189 
1190 	if (ta && p.res->aki != NULL && strcmp(p.res->aki, p.res->ski)) {
1191 		warnx("%s: RFC 6487 section 8.4.2: "
1192 		    "trust anchor AKI, if specified, must match SKI", p.fn);
1193 		goto out;
1194 	}
1195 
1196 	if (!ta && p.res->aki == NULL) {
1197 		warnx("%s: RFC 6487 section 8.4.2: "
1198 		    "non-trust anchor missing AKI", p.fn);
1199 		goto out;
1200 	} else if (!ta && strcmp(p.res->aki, p.res->ski) == 0) {
1201 		warnx("%s: RFC 6487 section 8.4.2: "
1202 		    "non-trust anchor AKI may not match SKI", p.fn);
1203 		goto out;
1204 	}
1205 
1206 	if (!ta && p.res->aia == NULL) {
1207 		warnx("%s: RFC 6487 section 8.4.7: "
1208 		    "non-trust anchor missing AIA", p.fn);
1209 		goto out;
1210 	} else if (ta && p.res->aia != NULL) {
1211 		warnx("%s: RFC 6487 section 8.4.7: "
1212 		    "trust anchor must not have AIA", p.fn);
1213 		goto out;
1214 	}
1215 
1216 	if (ta && p.res->crl != NULL) {
1217 		warnx("%s: RFC 6487 section 8.4.2: "
1218 		    "trust anchor may not specify CRL resource", p.fn);
1219 		goto out;
1220 	}
1221 
1222 	p.res->x509 = x;
1223 
1224 	rc = 1;
1225 out:
1226 	if (rc == 0) {
1227 		cert_free(p.res);
1228 		X509_free(x);
1229 	}
1230 	return (rc == 0) ? NULL : p.res;
1231 }
1232 
1233 struct cert *
cert_parse(const char * fn,const unsigned char * der,size_t len)1234 cert_parse(const char *fn, const unsigned char *der, size_t len)
1235 {
1236 	return cert_parse_inner(fn, der, len, 0);
1237 }
1238 
1239 struct cert *
ta_parse(const char * fn,const unsigned char * der,size_t len,const unsigned char * pkey,size_t pkeysz)1240 ta_parse(const char *fn, const unsigned char *der, size_t len,
1241     const unsigned char *pkey, size_t pkeysz)
1242 {
1243 	ASN1_TIME	*notBefore, *notAfter;
1244 	EVP_PKEY	*pk = NULL, *opk = NULL;
1245 	struct cert	*p;
1246 	int		 rc = 0;
1247 
1248 	if ((p = cert_parse_inner(fn, der, len, 1)) == NULL)
1249 		return NULL;
1250 
1251 	/* first check pubkey against the one from the TAL */
1252 	pk = d2i_PUBKEY(NULL, &pkey, pkeysz);
1253 	if (pk == NULL) {
1254 		cryptowarnx("%s: RFC 6487 (trust anchor): bad TAL pubkey", fn);
1255 		goto badcert;
1256 	}
1257 	if ((opk = X509_get0_pubkey(p->x509)) == NULL) {
1258 		cryptowarnx("%s: RFC 6487 (trust anchor): missing pubkey", fn);
1259 		goto badcert;
1260 	} else if (EVP_PKEY_cmp(pk, opk) != 1) {
1261 		cryptowarnx("%s: RFC 6487 (trust anchor): "
1262 		    "pubkey does not match TAL pubkey", fn);
1263 		goto badcert;
1264 	}
1265 
1266 	if ((notBefore = X509_get_notBefore(p->x509)) == NULL) {
1267 		warnx("%s: certificate has invalid notBefore", fn);
1268 		goto badcert;
1269 	}
1270 	if ((notAfter = X509_get_notAfter(p->x509)) == NULL) {
1271 		warnx("%s: certificate has invalid notAfter", fn);
1272 		goto badcert;
1273 	}
1274 	if (X509_cmp_current_time(notBefore) != -1) {
1275 		warnx("%s: certificate not yet valid", fn);
1276 		goto badcert;
1277 	}
1278 	if (X509_cmp_current_time(notAfter) != 1)  {
1279 		warnx("%s: certificate has expired", fn);
1280 		goto badcert;
1281 	}
1282 
1283 	rc = 1;
1284 
1285 badcert:
1286 	EVP_PKEY_free(pk);
1287 	if (rc == 0) {
1288 		cert_free(p);
1289 		p = NULL;
1290 	}
1291 
1292 	return p;
1293 }
1294 
1295 /*
1296  * Free parsed certificate contents.
1297  * Passing NULL is a noop.
1298  */
1299 void
cert_free(struct cert * p)1300 cert_free(struct cert *p)
1301 {
1302 	if (p == NULL)
1303 		return;
1304 
1305 	free(p->crl);
1306 	free(p->repo);
1307 	free(p->mft);
1308 	free(p->notify);
1309 	free(p->ips);
1310 	free(p->as);
1311 	free(p->aia);
1312 	free(p->aki);
1313 	free(p->ski);
1314 	free(p->pubkey);
1315 	X509_free(p->x509);
1316 	free(p);
1317 }
1318 
1319 /*
1320  * Write certificate parsed content into buffer.
1321  * See cert_read() for the other side of the pipe.
1322  */
1323 void
cert_buffer(struct ibuf * b,const struct cert * p)1324 cert_buffer(struct ibuf *b, const struct cert *p)
1325 {
1326 	io_simple_buffer(b, &p->expires, sizeof(p->expires));
1327 	io_simple_buffer(b, &p->purpose, sizeof(p->purpose));
1328 	io_simple_buffer(b, &p->talid, sizeof(p->talid));
1329 	io_simple_buffer(b, &p->ipsz, sizeof(p->ipsz));
1330 	io_simple_buffer(b, &p->asz, sizeof(p->asz));
1331 
1332 	io_simple_buffer(b, p->ips, p->ipsz * sizeof(p->ips[0]));
1333 	io_simple_buffer(b, p->as, p->asz * sizeof(p->as[0]));
1334 
1335 	io_str_buffer(b, p->mft);
1336 	io_str_buffer(b, p->notify);
1337 	io_str_buffer(b, p->repo);
1338 	io_str_buffer(b, p->crl);
1339 	io_str_buffer(b, p->aia);
1340 	io_str_buffer(b, p->aki);
1341 	io_str_buffer(b, p->ski);
1342 	io_str_buffer(b, p->pubkey);
1343 }
1344 
1345 /*
1346  * Allocate and read parsed certificate content from descriptor.
1347  * The pointer must be freed with cert_free().
1348  * Always returns a valid pointer.
1349  */
1350 struct cert *
cert_read(struct ibuf * b)1351 cert_read(struct ibuf *b)
1352 {
1353 	struct cert	*p;
1354 
1355 	if ((p = calloc(1, sizeof(struct cert))) == NULL)
1356 		err(1, NULL);
1357 
1358 	io_read_buf(b, &p->expires, sizeof(p->expires));
1359 	io_read_buf(b, &p->purpose, sizeof(p->purpose));
1360 	io_read_buf(b, &p->talid, sizeof(p->talid));
1361 	io_read_buf(b, &p->ipsz, sizeof(p->ipsz));
1362 	io_read_buf(b, &p->asz, sizeof(p->asz));
1363 
1364 	p->ips = calloc(p->ipsz, sizeof(struct cert_ip));
1365 	if (p->ips == NULL)
1366 		err(1, NULL);
1367 	io_read_buf(b, p->ips, p->ipsz * sizeof(p->ips[0]));
1368 
1369 	p->as = calloc(p->asz, sizeof(struct cert_as));
1370 	if (p->as == NULL)
1371 		err(1, NULL);
1372 	io_read_buf(b, p->as, p->asz * sizeof(p->as[0]));
1373 
1374 	io_read_str(b, &p->mft);
1375 	io_read_str(b, &p->notify);
1376 	io_read_str(b, &p->repo);
1377 	io_read_str(b, &p->crl);
1378 	io_read_str(b, &p->aia);
1379 	io_read_str(b, &p->aki);
1380 	io_read_str(b, &p->ski);
1381 	io_read_str(b, &p->pubkey);
1382 
1383 	assert(p->mft != NULL || p->purpose == CERT_PURPOSE_BGPSEC_ROUTER);
1384 	assert(p->ski);
1385 	return p;
1386 }
1387 
1388 struct auth *
auth_find(struct auth_tree * auths,const char * aki)1389 auth_find(struct auth_tree *auths, const char *aki)
1390 {
1391 	struct auth a;
1392 	struct cert c;
1393 
1394 	/* we look up the cert where the ski == aki */
1395 	c.ski = (char *)aki;
1396 	a.cert = &c;
1397 
1398 	return RB_FIND(auth_tree, auths, &a);
1399 }
1400 
1401 void
auth_insert(struct auth_tree * auths,struct cert * cert,struct auth * parent)1402 auth_insert(struct auth_tree *auths, struct cert *cert, struct auth *parent)
1403 {
1404 	struct auth *na;
1405 
1406 	na = malloc(sizeof(*na));
1407 	if (na == NULL)
1408 		err(1, NULL);
1409 
1410 	na->parent = parent;
1411 	na->cert = cert;
1412 
1413 	if (RB_INSERT(auth_tree, auths, na) != NULL)
1414 		err(1, "auth tree corrupted");
1415 }
1416 
1417 static inline int
authcmp(struct auth * a,struct auth * b)1418 authcmp(struct auth *a, struct auth *b)
1419 {
1420 	return strcmp(a->cert->ski, b->cert->ski);
1421 }
1422 
1423 RB_GENERATE(auth_tree, auth, entry, authcmp);
1424 
1425 static void
insert_brk(struct brk_tree * tree,struct cert * cert,int asid)1426 insert_brk(struct brk_tree *tree, struct cert *cert, int asid)
1427 {
1428 	struct brk	*b, *found;
1429 
1430 	if ((b = calloc(1, sizeof(*b))) == NULL)
1431 		err(1, NULL);
1432 
1433 	b->asid = asid;
1434 	b->expires = cert->expires;
1435 	b->talid = cert->talid;
1436 	if ((b->ski = strdup(cert->ski)) == NULL)
1437 		err(1, NULL);
1438 	if ((b->pubkey = strdup(cert->pubkey)) == NULL)
1439 		err(1, NULL);
1440 
1441 	/*
1442 	 * Check if a similar BRK already exists in the tree. If the found BRK
1443 	 * expires sooner, update it to this BRK's later expiry moment.
1444 	 */
1445 	if ((found = RB_INSERT(brk_tree, tree, b)) != NULL) {
1446 		if (found->expires < b->expires) {
1447 			found->expires = b->expires;
1448 			found->talid = b->talid;
1449 		}
1450 		free(b->ski);
1451 		free(b->pubkey);
1452 		free(b);
1453 	}
1454 }
1455 
1456 /*
1457  * Add each BGPsec Router Key into the BRK tree.
1458  */
1459 void
cert_insert_brks(struct brk_tree * tree,struct cert * cert)1460 cert_insert_brks(struct brk_tree *tree, struct cert *cert)
1461 {
1462 	size_t		 i, asid;
1463 
1464 	for (i = 0; i < cert->asz; i++) {
1465 		switch (cert->as[i].type) {
1466 		case CERT_AS_ID:
1467 			insert_brk(tree, cert, cert->as[i].id);
1468 			break;
1469 		case CERT_AS_RANGE:
1470 			for (asid = cert->as[i].range.min;
1471 			    asid <= cert->as[i].range.max; asid++)
1472 				insert_brk(tree, cert, asid);
1473 			break;
1474 		default:
1475 			warnx("invalid AS identifier type");
1476 			continue;
1477 		}
1478 	}
1479 }
1480 
1481 static inline int
brkcmp(struct brk * a,struct brk * b)1482 brkcmp(struct brk *a, struct brk *b)
1483 {
1484 	int rv;
1485 
1486 	if (a->asid > b->asid)
1487 		return 1;
1488 	if (a->asid < b->asid)
1489 		return -1;
1490 
1491 	rv = strcmp(a->ski, b->ski);
1492 	if (rv > 0)
1493 		return 1;
1494 	if (rv < 0)
1495 		return -1;
1496 
1497 	return strcmp(a->pubkey, b->pubkey);
1498 }
1499 
1500 RB_GENERATE(brk_tree, brk, entry, brkcmp);
1501