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