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