xref: /openbsd/usr.sbin/rpki-client/roa.c (revision 55cc5ba3)
1 /*	$OpenBSD: roa.c,v 1.13 2021/02/04 08:58:19 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 <assert.h>
19 #include <err.h>
20 #include <stdarg.h>
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 
26 #include <openssl/asn1.h>
27 #include <openssl/x509.h>
28 
29 #include "extern.h"
30 
31 /*
32  * Parse results and data of the manifest file.
33  */
34 struct	parse {
35 	const char	 *fn; /* manifest file name */
36 	struct roa	 *res; /* results */
37 };
38 
39 /*
40  * Parse IP address (ROAIPAddress), RFC 6482, section 3.3.
41  * Returns zero on failure, non-zero on success.
42  */
43 static int
44 roa_parse_addr(const ASN1_OCTET_STRING *os, enum afi afi, struct parse *p)
45 {
46 	ASN1_SEQUENCE_ANY	*seq;
47 	const unsigned char	*d = os->data;
48 	size_t			 dsz = os->length;
49 	int			 rc = 0;
50 	const ASN1_TYPE		*t;
51 	const ASN1_INTEGER	*maxlength = NULL;
52 	struct ip_addr		 addr;
53 	struct roa_ip		*res;
54 
55 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
56 		cryptowarnx("%s: RFC 6482 section 3.3: address: "
57 		    "failed ASN.1 sequence parse", p->fn);
58 		goto out;
59 	}
60 
61 	/* ROAIPAddress has the address and optional maxlength. */
62 
63 	if (sk_ASN1_TYPE_num(seq) != 1 &&
64 	    sk_ASN1_TYPE_num(seq) != 2) {
65 		warnx("%s: RFC 6482 section 3.3: adddress: "
66 		    "want 1 or 2 elements, have %d",
67 		    p->fn, sk_ASN1_TYPE_num(seq));
68 		goto out;
69 	}
70 
71 	t = sk_ASN1_TYPE_value(seq, 0);
72 	if (t->type != V_ASN1_BIT_STRING) {
73 		warnx("%s: RFC 6482 section 3.3: address: "
74 		    "want ASN.1 bit string, have %s (NID %d)",
75 		    p->fn, ASN1_tag2str(t->type), t->type);
76 		goto out;
77 	}
78 	if (!ip_addr_parse(t->value.bit_string, afi, p->fn, &addr)) {
79 		warnx("%s: RFC 6482 section 3.3: address: "
80 		    "invalid IP address", p->fn);
81 		goto out;
82 	}
83 
84 	/*
85 	 * RFC 6482, section 3.3 doesn't ever actually state that the
86 	 * maximum length can't be negative, but it needs to be >=0.
87 	 */
88 
89 	if (sk_ASN1_TYPE_num(seq) == 2) {
90 		t = sk_ASN1_TYPE_value(seq, 1);
91 		if (t->type != V_ASN1_INTEGER) {
92 			warnx("%s: RFC 6482 section 3.1: maxLength: "
93 			    "want ASN.1 integer, have %s (NID %d)",
94 			    p->fn, ASN1_tag2str(t->type), t->type);
95 			goto out;
96 		}
97 		maxlength = t->value.integer;
98 
99 		/*
100 		 * It's safe to use ASN1_INTEGER_get() here
101 		 * because we're not going to have more than signed 32
102 		 * bit maximum of length.
103 		 */
104 
105 		if (ASN1_INTEGER_get(maxlength) < 0) {
106 			warnx("%s: RFC 6482 section 3.2: maxLength: "
107 			    "want positive integer, have %ld",
108 			    p->fn, ASN1_INTEGER_get(maxlength));
109 			goto out;
110 		}
111 		/* FIXME: maximum check. */
112 	}
113 
114 	p->res->ips = reallocarray(p->res->ips,
115 		p->res->ipsz + 1, sizeof(struct roa_ip));
116 	if (p->res->ips == NULL)
117 		err(1, NULL);
118 	res = &p->res->ips[p->res->ipsz++];
119 	memset(res, 0, sizeof(struct roa_ip));
120 
121 	res->addr = addr;
122 	res->afi = afi;
123 	res->maxlength = (maxlength == NULL) ? addr.prefixlen :
124 	    ASN1_INTEGER_get(maxlength);
125 	ip_roa_compose_ranges(res);
126 
127 	rc = 1;
128 out:
129 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
130 	return rc;
131 }
132 
133 /*
134  * Parse IP address family, RFC 6482, section 3.3.
135  * Returns zero on failure, non-zero on success.
136  */
137 static int
138 roa_parse_ipfam(const ASN1_OCTET_STRING *os, struct parse *p)
139 {
140 	ASN1_SEQUENCE_ANY	*seq, *sseq = NULL;
141 	const unsigned char	*d = os->data;
142 	size_t			 dsz = os->length;
143 	int			 i, rc = 0;
144 	const ASN1_TYPE		*t;
145 	enum afi		 afi;
146 
147 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
148 		cryptowarnx("%s: RFC 6482 section 3.3: ROAIPAddressFamily: "
149 		    "failed ASN.1 sequence parse", p->fn);
150 		goto out;
151 	} else if (sk_ASN1_TYPE_num(seq) != 2) {
152 		warnx("%s: RFC 6482 section 3.3: ROAIPAddressFamily: "
153 		    "want 2 elements, have %d",
154 		    p->fn, sk_ASN1_TYPE_num(seq));
155 		goto out;
156 	}
157 
158 	t = sk_ASN1_TYPE_value(seq, 0);
159 	if (t->type != V_ASN1_OCTET_STRING) {
160 		warnx("%s: RFC 6482 section 3.3: addressFamily: "
161 		    "want ASN.1 octet string, have %s (NID %d)",
162 		    p->fn, ASN1_tag2str(t->type), t->type);
163 		goto out;
164 	}
165 	if (!ip_addr_afi_parse(p->fn, t->value.octet_string, &afi)) {
166 		warnx("%s: RFC 6482 section 3.3: addressFamily: "
167 		    "invalid", p->fn);
168 		goto out;
169 	}
170 
171 	t = sk_ASN1_TYPE_value(seq, 1);
172 	if (t->type != V_ASN1_SEQUENCE) {
173 		warnx("%s: RFC 6482 section 3.3: addresses: "
174 		    "want ASN.1 sequence, have %s (NID %d)",
175 		    p->fn, ASN1_tag2str(t->type), t->type);
176 		goto out;
177 	}
178 
179 	d = t->value.octet_string->data;
180 	dsz = t->value.octet_string->length;
181 
182 	if ((sseq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
183 		cryptowarnx("%s: RFC 6482 section 3.3: addresses: "
184 		    "failed ASN.1 sequence parse", p->fn);
185 		goto out;
186 	}
187 
188 	for (i = 0; i < sk_ASN1_TYPE_num(sseq); i++) {
189 		t = sk_ASN1_TYPE_value(sseq, i);
190 		if (t->type != V_ASN1_SEQUENCE) {
191 			warnx("%s: RFC 6482 section 3.3: ROAIPAddress: "
192 			    "want ASN.1 sequence, have %s (NID %d)",
193 			    p->fn, ASN1_tag2str(t->type), t->type);
194 			goto out;
195 		}
196 		if (!roa_parse_addr(t->value.octet_string, afi, p))
197 			goto out;
198 	}
199 
200 	rc = 1;
201 out:
202 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
203 	sk_ASN1_TYPE_pop_free(sseq, ASN1_TYPE_free);
204 	return rc;
205 }
206 
207 /*
208  * Parse IP blocks, RFC 6482, section 3.3.
209  * Returns zero on failure, non-zero on success.
210  */
211 static int
212 roa_parse_ipblocks(const ASN1_OCTET_STRING *os, struct parse *p)
213 {
214 	ASN1_SEQUENCE_ANY	*seq;
215 	const unsigned char	*d = os->data;
216 	size_t			 dsz = os->length;
217 	int			 i, rc = 0;
218 	const ASN1_TYPE		*t;
219 
220 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
221 		cryptowarnx("%s: RFC 6482 section 3.3: ipAddrBlocks: "
222 		    "failed ASN.1 sequence parse", p->fn);
223 		goto out;
224 	}
225 
226 	for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) {
227 		t = sk_ASN1_TYPE_value(seq, i);
228 		if (t->type != V_ASN1_SEQUENCE) {
229 			warnx("%s: RFC 6482 section 3.3: ROAIPAddressFamily: "
230 			    "want ASN.1 sequence, have %s (NID %d)",
231 			    p->fn, ASN1_tag2str(t->type), t->type);
232 			goto out;
233 		} else if (!roa_parse_ipfam(t->value.octet_string, p))
234 			goto out;
235 	}
236 
237 	rc = 1;
238 out:
239 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
240 	return rc;
241 }
242 
243 /*
244  * Parses the eContent section of an ROA file, RFC 6482, section 3.
245  * Returns zero on failure, non-zero on success.
246  */
247 static int
248 roa_parse_econtent(const unsigned char *d, size_t dsz, struct parse *p)
249 {
250 	ASN1_SEQUENCE_ANY	*seq;
251 	int			 i = 0, rc = 0, sz;
252 	const ASN1_TYPE		*t;
253 
254 	/* RFC 6482, section 3. */
255 
256 	if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
257 		cryptowarnx("%s: RFC 6482 section 3: RouteOriginAttestation: "
258 		    "failed ASN.1 sequence parse", p->fn);
259 		goto out;
260 	}
261 
262 	if ((sz = sk_ASN1_TYPE_num(seq)) != 2 && sz != 3) {
263 		warnx("%s: RFC 6482 section 3: RouteOriginAttestation: "
264 		    "want 2 or 3 elements, have %d",
265 		    p->fn, sk_ASN1_TYPE_num(seq));
266 		goto out;
267 	}
268 
269 	/* RFC 6482, section 3.1. */
270 
271 	if (sz == 3) {
272 		t = sk_ASN1_TYPE_value(seq, i++);
273 
274 		/*
275 		 * This check with ASN1_INTEGER_get() is fine since
276 		 * we're looking for a value of zero anyway, so any
277 		 * overflowing number will be definition be wrong.
278 		 */
279 
280 		if (t->type != V_ASN1_INTEGER) {
281 			warnx("%s: RFC 6482 section 3.1: version: "
282 			    "want ASN.1 integer, have %s (NID %d)",
283 			    p->fn, ASN1_tag2str(t->type), t->type);
284 			goto out;
285 		} else if (ASN1_INTEGER_get(t->value.integer) != 0) {
286 			warnx("%s: RFC 6482 section 3.1: version: "
287 			    "want version 0, have %ld",
288 			    p->fn, ASN1_INTEGER_get(t->value.integer));
289 			goto out;
290 		}
291 	}
292 
293 	/*
294 	 * RFC 6482, section 3.2.
295 	 * It doesn't ever actually state that AS numbers can't be
296 	 * negative, but...?
297 	 */
298 
299 	t = sk_ASN1_TYPE_value(seq, i++);
300 	if (t->type != V_ASN1_INTEGER) {
301 		warnx("%s: RFC 6482 section 3.2: asID: "
302 		    "want ASN.1 integer, have %s (NID %d)",
303 		    p->fn, ASN1_tag2str(t->type), t->type);
304 		goto out;
305 	} else if (!as_id_parse(t->value.integer, &p->res->asid)) {
306 		warnx("%s: RFC 6482 section 3.2: asID: "
307 		    "malformed AS identifier", p->fn);
308 		goto out;
309 	}
310 
311 	/* RFC 6482, section 3.3. */
312 
313 	t = sk_ASN1_TYPE_value(seq, i++);
314 	if (t->type != V_ASN1_SEQUENCE) {
315 		warnx("%s: RFC 6482 section 3.3: ipAddrBlocks: "
316 		    "want ASN.1 sequence, have %s (NID %d)",
317 		    p->fn, ASN1_tag2str(t->type), t->type);
318 		goto out;
319 	} else if (!roa_parse_ipblocks(t->value.octet_string, p))
320 		goto out;
321 
322 	rc = 1;
323 out:
324 	sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
325 	return rc;
326 }
327 
328 /*
329  * Parse a full RFC 6482 file.
330  * Returns the ROA or NULL if the document was malformed.
331  */
332 struct roa *
333 roa_parse(X509 **x509, const char *fn)
334 {
335 	struct parse	 p;
336 	size_t		 cmsz;
337 	unsigned char	*cms;
338 	int		 rc = 0;
339 
340 	memset(&p, 0, sizeof(struct parse));
341 	p.fn = fn;
342 
343 	/* OID from section 2, RFC 6482. */
344 
345 	cms = cms_parse_validate(x509, fn,
346 	    "1.2.840.113549.1.9.16.1.24", &cmsz);
347 	if (cms == NULL)
348 		return NULL;
349 
350 	if ((p.res = calloc(1, sizeof(struct roa))) == NULL)
351 		err(1, NULL);
352 	if (!x509_get_ski_aki(*x509, fn, &p.res->ski, &p.res->aki))
353 		goto out;
354 	if (!roa_parse_econtent(cms, cmsz, &p))
355 		goto out;
356 
357 	rc = 1;
358 out:
359 	if (rc == 0) {
360 		roa_free(p.res);
361 		p.res = NULL;
362 		X509_free(*x509);
363 		*x509 = NULL;
364 	}
365 	free(cms);
366 	return p.res;
367 
368 }
369 
370 /*
371  * Free an ROA pointer.
372  * Safe to call with NULL.
373  */
374 void
375 roa_free(struct roa *p)
376 {
377 
378 	if (p == NULL)
379 		return;
380 	free(p->aki);
381 	free(p->ski);
382 	free(p->ips);
383 	free(p->tal);
384 	free(p);
385 }
386 
387 /*
388  * Serialise parsed ROA content.
389  * See roa_read() for reader.
390  */
391 void
392 roa_buffer(struct ibuf *b, const struct roa *p)
393 {
394 	size_t	 i;
395 
396 	io_simple_buffer(b, &p->valid, sizeof(int));
397 	io_simple_buffer(b, &p->asid, sizeof(uint32_t));
398 	io_simple_buffer(b, &p->ipsz, sizeof(size_t));
399 
400 	for (i = 0; i < p->ipsz; i++) {
401 		io_simple_buffer(b, &p->ips[i].afi, sizeof(enum afi));
402 		io_simple_buffer(b, &p->ips[i].maxlength, sizeof(size_t));
403 		io_simple_buffer(b, p->ips[i].min, sizeof(p->ips[i].min));
404 		io_simple_buffer(b, p->ips[i].max, sizeof(p->ips[i].max));
405 		ip_addr_buffer(b, &p->ips[i].addr);
406 	}
407 
408 	io_str_buffer(b, p->aki);
409 	io_str_buffer(b, p->ski);
410 	io_str_buffer(b, p->tal);
411 }
412 
413 /*
414  * Read parsed ROA content from descriptor.
415  * See roa_buffer() for writer.
416  * Result must be passed to roa_free().
417  */
418 struct roa *
419 roa_read(int fd)
420 {
421 	struct roa	*p;
422 	size_t		 i;
423 
424 	if ((p = calloc(1, sizeof(struct roa))) == NULL)
425 		err(1, NULL);
426 
427 	io_simple_read(fd, &p->valid, sizeof(int));
428 	io_simple_read(fd, &p->asid, sizeof(uint32_t));
429 	io_simple_read(fd, &p->ipsz, sizeof(size_t));
430 
431 	if ((p->ips = calloc(p->ipsz, sizeof(struct roa_ip))) == NULL)
432 		err(1, NULL);
433 
434 	for (i = 0; i < p->ipsz; i++) {
435 		io_simple_read(fd, &p->ips[i].afi, sizeof(enum afi));
436 		io_simple_read(fd, &p->ips[i].maxlength, sizeof(size_t));
437 		io_simple_read(fd, &p->ips[i].min, sizeof(p->ips[i].min));
438 		io_simple_read(fd, &p->ips[i].max, sizeof(p->ips[i].max));
439 		ip_addr_read(fd, &p->ips[i].addr);
440 	}
441 
442 	io_str_read(fd, &p->aki);
443 	io_str_read(fd, &p->ski);
444 	io_str_read(fd, &p->tal);
445 	assert(p->aki && p->ski && p->tal);
446 
447 	return p;
448 }
449 
450 /*
451  * Add each IP address in the ROA into the VRP tree.
452  * Updates "vrps" to be the number of VRPs and "uniqs" to be the unique
453  * number of addresses.
454  */
455 void
456 roa_insert_vrps(struct vrp_tree *tree, struct roa *roa, size_t *vrps,
457     size_t *uniqs)
458 {
459 	struct vrp *v;
460 	size_t i;
461 
462 	for (i = 0; i < roa->ipsz; i++) {
463 		if ((v = malloc(sizeof(*v))) == NULL)
464 			err(1, NULL);
465 		v->afi = roa->ips[i].afi;
466 		v->addr = roa->ips[i].addr;
467 		v->maxlength = roa->ips[i].maxlength;
468 		v->asid = roa->asid;
469 		if ((v->tal = strdup(roa->tal)) == NULL)
470 			err(1, NULL);
471 		if (RB_INSERT(vrp_tree, tree, v) == NULL)
472 			(*uniqs)++;
473 		else /* already exists */
474 			free(v);
475 		(*vrps)++;
476 	}
477 }
478 
479 static inline int
480 vrpcmp(struct vrp *a, struct vrp *b)
481 {
482 	int rv;
483 
484 	if (a->afi > b->afi)
485 		return 1;
486 	if (a->afi < b->afi)
487 		return -1;
488 	switch (a->afi) {
489 	case AFI_IPV4:
490 		rv = memcmp(&a->addr.addr, &b->addr.addr, 4);
491 		if (rv)
492 			return rv;
493 		break;
494 	case AFI_IPV6:
495 		rv = memcmp(&a->addr.addr, &b->addr.addr, 16);
496 		if (rv)
497 			return rv;
498 		break;
499 	}
500 	/* a smaller prefixlen is considered bigger, e.g. /8 vs /10 */
501 	if (a->addr.prefixlen < b->addr.prefixlen)
502 		return 1;
503 	if (a->addr.prefixlen > b->addr.prefixlen)
504 		return -1;
505 	if (a->maxlength < b->maxlength)
506 		return 1;
507 	if (a->maxlength > b->maxlength)
508 		return -1;
509 
510 	if (a->asid > b->asid)
511 		return 1;
512 	if (a->asid < b->asid)
513 		return -1;
514 
515 	return 0;
516 }
517 
518 RB_GENERATE(vrp_tree, vrp, entry, vrpcmp);
519