xref: /openbsd/usr.sbin/rpki-client/roa.c (revision c7a965b3)
1 /*	$OpenBSD: roa.c,v 1.78 2024/05/24 12:57:20 tb Exp $ */
2 /*
3  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
4  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <assert.h>
20 #include <err.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/asn1t.h>
28 #include <openssl/stack.h>
29 #include <openssl/safestack.h>
30 #include <openssl/x509.h>
31 
32 #include "extern.h"
33 
34 extern ASN1_OBJECT	*roa_oid;
35 
36 /*
37  * Types and templates for the ROA eContent, RFC 6482, section 3.
38  */
39 
40 ASN1_ITEM_EXP ROAIPAddress_it;
41 ASN1_ITEM_EXP ROAIPAddressFamily_it;
42 ASN1_ITEM_EXP RouteOriginAttestation_it;
43 
44 typedef struct {
45 	ASN1_BIT_STRING		*address;
46 	ASN1_INTEGER		*maxLength;
47 } ROAIPAddress;
48 
49 DECLARE_STACK_OF(ROAIPAddress);
50 
51 typedef struct {
52 	ASN1_OCTET_STRING	*addressFamily;
53 	STACK_OF(ROAIPAddress)	*addresses;
54 } ROAIPAddressFamily;
55 
56 DECLARE_STACK_OF(ROAIPAddressFamily);
57 
58 #ifndef DEFINE_STACK_OF
59 #define sk_ROAIPAddress_num(st)		SKM_sk_num(ROAIPAddress, (st))
60 #define sk_ROAIPAddress_value(st, i)	SKM_sk_value(ROAIPAddress, (st), (i))
61 
62 #define sk_ROAIPAddressFamily_num(st)	SKM_sk_num(ROAIPAddressFamily, (st))
63 #define sk_ROAIPAddressFamily_value(st, i) \
64     SKM_sk_value(ROAIPAddressFamily, (st), (i))
65 #endif
66 
67 typedef struct {
68 	ASN1_INTEGER			*version;
69 	ASN1_INTEGER			*asid;
70 	STACK_OF(ROAIPAddressFamily)	*ipAddrBlocks;
71 } RouteOriginAttestation;
72 
73 ASN1_SEQUENCE(ROAIPAddress) = {
74 	ASN1_SIMPLE(ROAIPAddress, address, ASN1_BIT_STRING),
75 	ASN1_OPT(ROAIPAddress, maxLength, ASN1_INTEGER),
76 } ASN1_SEQUENCE_END(ROAIPAddress);
77 
78 ASN1_SEQUENCE(ROAIPAddressFamily) = {
79 	ASN1_SIMPLE(ROAIPAddressFamily, addressFamily, ASN1_OCTET_STRING),
80 	ASN1_SEQUENCE_OF(ROAIPAddressFamily, addresses, ROAIPAddress),
81 } ASN1_SEQUENCE_END(ROAIPAddressFamily);
82 
83 ASN1_SEQUENCE(RouteOriginAttestation) = {
84 	ASN1_EXP_OPT(RouteOriginAttestation, version, ASN1_INTEGER, 0),
85 	ASN1_SIMPLE(RouteOriginAttestation, asid, ASN1_INTEGER),
86 	ASN1_SEQUENCE_OF(RouteOriginAttestation, ipAddrBlocks,
87 	    ROAIPAddressFamily),
88 } ASN1_SEQUENCE_END(RouteOriginAttestation);
89 
90 DECLARE_ASN1_FUNCTIONS(RouteOriginAttestation);
91 IMPLEMENT_ASN1_FUNCTIONS(RouteOriginAttestation);
92 
93 /*
94  * Parses the eContent section of an ROA file, RFC 6482, section 3.
95  * Returns zero on failure, non-zero on success.
96  */
97 static int
roa_parse_econtent(const char * fn,struct roa * roa,const unsigned char * d,size_t dsz)98 roa_parse_econtent(const char *fn, struct roa *roa, const unsigned char *d,
99     size_t dsz)
100 {
101 	const unsigned char		*oder;
102 	RouteOriginAttestation		*roa_asn1;
103 	const ROAIPAddressFamily	*addrfam;
104 	const STACK_OF(ROAIPAddress)	*addrs;
105 	int				 addrsz, ipv4_seen = 0, ipv6_seen = 0;
106 	enum afi			 afi;
107 	const ROAIPAddress		*addr;
108 	uint64_t			 maxlen;
109 	struct ip_addr			 ipaddr;
110 	struct roa_ip			*res;
111 	int				 ipaddrblocksz;
112 	int				 i, j, rc = 0;
113 
114 	oder = d;
115 	if ((roa_asn1 = d2i_RouteOriginAttestation(NULL, &d, dsz)) == NULL) {
116 		warnx("%s: RFC 6482 section 3: failed to parse "
117 		    "RouteOriginAttestation", fn);
118 		goto out;
119 	}
120 	if (d != oder + dsz) {
121 		warnx("%s: %td bytes trailing garbage in eContent", fn,
122 		    oder + dsz - d);
123 		goto out;
124 	}
125 
126 	if (!valid_econtent_version(fn, roa_asn1->version, 0))
127 		goto out;
128 
129 	if (!as_id_parse(roa_asn1->asid, &roa->asid)) {
130 		warnx("%s: RFC 6482 section 3.2: asID: "
131 		    "malformed AS identifier", fn);
132 		goto out;
133 	}
134 
135 	ipaddrblocksz = sk_ROAIPAddressFamily_num(roa_asn1->ipAddrBlocks);
136 	if (ipaddrblocksz != 1 && ipaddrblocksz != 2) {
137 		warnx("%s: RFC 9582: unexpected number of ipAddrBlocks "
138 		    "(got %d, expected 1 or 2)", fn, ipaddrblocksz);
139 		goto out;
140 	}
141 
142 	for (i = 0; i < ipaddrblocksz; i++) {
143 		addrfam = sk_ROAIPAddressFamily_value(roa_asn1->ipAddrBlocks,
144 		    i);
145 		addrs = addrfam->addresses;
146 		addrsz = sk_ROAIPAddress_num(addrs);
147 
148 		if (!ip_addr_afi_parse(fn, addrfam->addressFamily, &afi)) {
149 			warnx("%s: RFC 6482 section 3.3: addressFamily: "
150 			    "invalid", fn);
151 			goto out;
152 		}
153 
154 		switch (afi) {
155 		case AFI_IPV4:
156 			if (ipv4_seen++ > 0) {
157 				warnx("%s: RFC 9582 section 4.3.2: "
158 				    "IPv4 appears twice", fn);
159 				goto out;
160 			}
161 			break;
162 		case AFI_IPV6:
163 			if (ipv6_seen++ > 0) {
164 				warnx("%s: RFC 9582 section 4.3.2: "
165 				    "IPv6 appears twice", fn);
166 				goto out;
167 			}
168 			break;
169 		}
170 
171 		if (addrsz == 0) {
172 			warnx("%s: RFC 9582, section 4.3.2: "
173 			    "empty ROAIPAddressFamily", fn);
174 			goto out;
175 		}
176 
177 		if (roa->ipsz + addrsz >= MAX_IP_SIZE) {
178 			warnx("%s: too many ROAIPAddress entries: limit %d",
179 			    fn, MAX_IP_SIZE);
180 			goto out;
181 		}
182 		roa->ips = recallocarray(roa->ips, roa->ipsz,
183 		    roa->ipsz + addrsz, sizeof(struct roa_ip));
184 		if (roa->ips == NULL)
185 			err(1, NULL);
186 
187 		for (j = 0; j < addrsz; j++) {
188 			addr = sk_ROAIPAddress_value(addrs, j);
189 
190 			if (!ip_addr_parse(addr->address, afi, fn, &ipaddr)) {
191 				warnx("%s: RFC 6482 section 3.3: address: "
192 				    "invalid IP address", fn);
193 				goto out;
194 			}
195 			maxlen = ipaddr.prefixlen;
196 
197 			if (addr->maxLength != NULL) {
198 				if (!ASN1_INTEGER_get_uint64(&maxlen,
199 				    addr->maxLength)) {
200 					warnx("%s: RFC 6482 section 3.2: "
201 					    "ASN1_INTEGER_get_uint64 failed",
202 					    fn);
203 					goto out;
204 				}
205 				if (ipaddr.prefixlen > maxlen) {
206 					warnx("%s: prefixlen (%d) larger than "
207 					    "maxLength (%llu)", fn,
208 					    ipaddr.prefixlen,
209 					    (unsigned long long)maxlen);
210 					goto out;
211 				}
212 				if (maxlen > ((afi == AFI_IPV4) ? 32 : 128)) {
213 					warnx("%s: maxLength (%llu) too large",
214 					    fn, (unsigned long long)maxlen);
215 					goto out;
216 				}
217 			}
218 
219 			res = &roa->ips[roa->ipsz++];
220 			res->addr = ipaddr;
221 			res->afi = afi;
222 			res->maxlength = maxlen;
223 			ip_roa_compose_ranges(res);
224 		}
225 	}
226 
227 	rc = 1;
228  out:
229 	RouteOriginAttestation_free(roa_asn1);
230 	return rc;
231 }
232 
233 /*
234  * Parse a full RFC 6482 file.
235  * Returns the ROA or NULL if the document was malformed.
236  */
237 struct roa *
roa_parse(X509 ** x509,const char * fn,int talid,const unsigned char * der,size_t len)238 roa_parse(X509 **x509, const char *fn, int talid, const unsigned char *der,
239     size_t len)
240 {
241 	struct roa	*roa;
242 	size_t		 cmsz;
243 	unsigned char	*cms;
244 	struct cert	*cert = NULL;
245 	time_t		 signtime = 0;
246 	int		 rc = 0;
247 
248 	cms = cms_parse_validate(x509, fn, der, len, roa_oid, &cmsz, &signtime);
249 	if (cms == NULL)
250 		return NULL;
251 
252 	if ((roa = calloc(1, sizeof(struct roa))) == NULL)
253 		err(1, NULL);
254 	roa->signtime = signtime;
255 
256 	if (!x509_get_aia(*x509, fn, &roa->aia))
257 		goto out;
258 	if (!x509_get_aki(*x509, fn, &roa->aki))
259 		goto out;
260 	if (!x509_get_sia(*x509, fn, &roa->sia))
261 		goto out;
262 	if (!x509_get_ski(*x509, fn, &roa->ski))
263 		goto out;
264 	if (roa->aia == NULL || roa->aki == NULL || roa->sia == NULL ||
265 	    roa->ski == NULL) {
266 		warnx("%s: RFC 6487 section 4.8: "
267 		    "missing AIA, AKI, SIA, or SKI X509 extension", fn);
268 		goto out;
269 	}
270 
271 	if (!x509_get_notbefore(*x509, fn, &roa->notbefore))
272 		goto out;
273 	if (!x509_get_notafter(*x509, fn, &roa->notafter))
274 		goto out;
275 
276 	if (!roa_parse_econtent(fn, roa, cms, cmsz))
277 		goto out;
278 
279 	if (x509_any_inherits(*x509)) {
280 		warnx("%s: inherit elements not allowed in EE cert", fn);
281 		goto out;
282 	}
283 
284 	if ((cert = cert_parse_ee_cert(fn, talid, *x509)) == NULL)
285 		goto out;
286 
287 	if (cert->asz > 0) {
288 		warnx("%s: superfluous AS Resources extension present", fn);
289 		goto out;
290 	}
291 
292 	/*
293 	 * If the ROA isn't valid, we accept it anyway and depend upon
294 	 * the code around roa_read() to check the "valid" field itself.
295 	 */
296 	roa->valid = valid_roa(fn, cert, roa);
297 
298 	rc = 1;
299 out:
300 	if (rc == 0) {
301 		roa_free(roa);
302 		roa = NULL;
303 		X509_free(*x509);
304 		*x509 = NULL;
305 	}
306 	cert_free(cert);
307 	free(cms);
308 	return roa;
309 }
310 
311 /*
312  * Free an ROA pointer.
313  * Safe to call with NULL.
314  */
315 void
roa_free(struct roa * p)316 roa_free(struct roa *p)
317 {
318 
319 	if (p == NULL)
320 		return;
321 	free(p->aia);
322 	free(p->aki);
323 	free(p->sia);
324 	free(p->ski);
325 	free(p->ips);
326 	free(p);
327 }
328 
329 /*
330  * Serialise parsed ROA content.
331  * See roa_read() for reader.
332  */
333 void
roa_buffer(struct ibuf * b,const struct roa * p)334 roa_buffer(struct ibuf *b, const struct roa *p)
335 {
336 	io_simple_buffer(b, &p->valid, sizeof(p->valid));
337 	io_simple_buffer(b, &p->asid, sizeof(p->asid));
338 	io_simple_buffer(b, &p->talid, sizeof(p->talid));
339 	io_simple_buffer(b, &p->ipsz, sizeof(p->ipsz));
340 	io_simple_buffer(b, &p->expires, sizeof(p->expires));
341 
342 	io_simple_buffer(b, p->ips, p->ipsz * sizeof(p->ips[0]));
343 
344 	io_str_buffer(b, p->aia);
345 	io_str_buffer(b, p->aki);
346 	io_str_buffer(b, p->ski);
347 }
348 
349 /*
350  * Read parsed ROA content from descriptor.
351  * See roa_buffer() for writer.
352  * Result must be passed to roa_free().
353  */
354 struct roa *
roa_read(struct ibuf * b)355 roa_read(struct ibuf *b)
356 {
357 	struct roa	*p;
358 
359 	if ((p = calloc(1, sizeof(struct roa))) == NULL)
360 		err(1, NULL);
361 
362 	io_read_buf(b, &p->valid, sizeof(p->valid));
363 	io_read_buf(b, &p->asid, sizeof(p->asid));
364 	io_read_buf(b, &p->talid, sizeof(p->talid));
365 	io_read_buf(b, &p->ipsz, sizeof(p->ipsz));
366 	io_read_buf(b, &p->expires, sizeof(p->expires));
367 
368 	if ((p->ips = calloc(p->ipsz, sizeof(struct roa_ip))) == NULL)
369 		err(1, NULL);
370 	io_read_buf(b, p->ips, p->ipsz * sizeof(p->ips[0]));
371 
372 	io_read_str(b, &p->aia);
373 	io_read_str(b, &p->aki);
374 	io_read_str(b, &p->ski);
375 	assert(p->aia && p->aki && p->ski);
376 
377 	return p;
378 }
379 
380 /*
381  * Add each IP address in the ROA into the VRP tree.
382  * Updates "vrps" to be the number of VRPs and "uniqs" to be the unique
383  * number of addresses.
384  */
385 void
roa_insert_vrps(struct vrp_tree * tree,struct roa * roa,struct repo * rp)386 roa_insert_vrps(struct vrp_tree *tree, struct roa *roa, struct repo *rp)
387 {
388 	struct vrp	*v, *found;
389 	size_t		 i;
390 
391 	for (i = 0; i < roa->ipsz; i++) {
392 		if ((v = malloc(sizeof(*v))) == NULL)
393 			err(1, NULL);
394 		v->afi = roa->ips[i].afi;
395 		v->addr = roa->ips[i].addr;
396 		v->maxlength = roa->ips[i].maxlength;
397 		v->asid = roa->asid;
398 		v->talid = roa->talid;
399 		if (rp != NULL)
400 			v->repoid = repo_id(rp);
401 		else
402 			v->repoid = 0;
403 		v->expires = roa->expires;
404 
405 		/*
406 		 * Check if a similar VRP already exists in the tree.
407 		 * If the found VRP expires sooner, update it to this
408 		 * ROAs later expiry moment.
409 		 */
410 		if ((found = RB_INSERT(vrp_tree, tree, v)) != NULL) {
411 			/* already exists */
412 			if (found->expires < v->expires) {
413 				/* update found with preferred data */
414 				/* adjust unique count */
415 				repo_stat_inc(repo_byid(found->repoid),
416 				    found->talid, RTYPE_ROA, STYPE_DEC_UNIQUE);
417 				found->expires = v->expires;
418 				found->talid = v->talid;
419 				found->repoid = v->repoid;
420 				repo_stat_inc(rp, v->talid, RTYPE_ROA,
421 				    STYPE_UNIQUE);
422 			}
423 			free(v);
424 		} else
425 			repo_stat_inc(rp, v->talid, RTYPE_ROA, STYPE_UNIQUE);
426 
427 		repo_stat_inc(rp, roa->talid, RTYPE_ROA, STYPE_TOTAL);
428 	}
429 }
430 
431 static inline int
vrpcmp(struct vrp * a,struct vrp * b)432 vrpcmp(struct vrp *a, struct vrp *b)
433 {
434 	int rv;
435 
436 	if (a->afi > b->afi)
437 		return 1;
438 	if (a->afi < b->afi)
439 		return -1;
440 	switch (a->afi) {
441 	case AFI_IPV4:
442 		rv = memcmp(&a->addr.addr, &b->addr.addr, 4);
443 		if (rv)
444 			return rv;
445 		break;
446 	case AFI_IPV6:
447 		rv = memcmp(&a->addr.addr, &b->addr.addr, 16);
448 		if (rv)
449 			return rv;
450 		break;
451 	default:
452 		break;
453 	}
454 	/* a smaller prefixlen is considered bigger, e.g. /8 vs /10 */
455 	if (a->addr.prefixlen < b->addr.prefixlen)
456 		return 1;
457 	if (a->addr.prefixlen > b->addr.prefixlen)
458 		return -1;
459 	if (a->maxlength < b->maxlength)
460 		return 1;
461 	if (a->maxlength > b->maxlength)
462 		return -1;
463 
464 	if (a->asid > b->asid)
465 		return 1;
466 	if (a->asid < b->asid)
467 		return -1;
468 
469 	return 0;
470 }
471 
472 RB_GENERATE(vrp_tree, vrp, entry, vrpcmp);
473