1 /* $OpenBSD: roa.c,v 1.80 2024/11/12 09:23:07 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->num_ips + 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->num_ips,
183 roa->num_ips + 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->num_ips++];
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->num_ases > 0) {
288 warnx("%s: superfluous AS Resources extension present", fn);
289 goto out;
290 }
291
292 if (cert->num_ips == 0) {
293 warnx("%s: no IP address present", fn);
294 goto out;
295 }
296
297 /*
298 * If the ROA isn't valid, we accept it anyway and depend upon
299 * the code around roa_read() to check the "valid" field itself.
300 */
301 roa->valid = valid_roa(fn, cert, roa);
302
303 rc = 1;
304 out:
305 if (rc == 0) {
306 roa_free(roa);
307 roa = NULL;
308 X509_free(*x509);
309 *x509 = NULL;
310 }
311 cert_free(cert);
312 free(cms);
313 return roa;
314 }
315
316 /*
317 * Free an ROA pointer.
318 * Safe to call with NULL.
319 */
320 void
roa_free(struct roa * p)321 roa_free(struct roa *p)
322 {
323
324 if (p == NULL)
325 return;
326 free(p->aia);
327 free(p->aki);
328 free(p->sia);
329 free(p->ski);
330 free(p->ips);
331 free(p);
332 }
333
334 /*
335 * Serialise parsed ROA content.
336 * See roa_read() for reader.
337 */
338 void
roa_buffer(struct ibuf * b,const struct roa * p)339 roa_buffer(struct ibuf *b, const struct roa *p)
340 {
341 io_simple_buffer(b, &p->valid, sizeof(p->valid));
342 io_simple_buffer(b, &p->asid, sizeof(p->asid));
343 io_simple_buffer(b, &p->talid, sizeof(p->talid));
344 io_simple_buffer(b, &p->num_ips, sizeof(p->num_ips));
345 io_simple_buffer(b, &p->expires, sizeof(p->expires));
346
347 io_simple_buffer(b, p->ips, p->num_ips * sizeof(p->ips[0]));
348
349 io_str_buffer(b, p->aia);
350 io_str_buffer(b, p->aki);
351 io_str_buffer(b, p->ski);
352 }
353
354 /*
355 * Read parsed ROA content from descriptor.
356 * See roa_buffer() for writer.
357 * Result must be passed to roa_free().
358 */
359 struct roa *
roa_read(struct ibuf * b)360 roa_read(struct ibuf *b)
361 {
362 struct roa *p;
363
364 if ((p = calloc(1, sizeof(struct roa))) == NULL)
365 err(1, NULL);
366
367 io_read_buf(b, &p->valid, sizeof(p->valid));
368 io_read_buf(b, &p->asid, sizeof(p->asid));
369 io_read_buf(b, &p->talid, sizeof(p->talid));
370 io_read_buf(b, &p->num_ips, sizeof(p->num_ips));
371 io_read_buf(b, &p->expires, sizeof(p->expires));
372
373 if (p->num_ips > 0) {
374 if ((p->ips = calloc(p->num_ips, sizeof(p->ips[0]))) == NULL)
375 err(1, NULL);
376 io_read_buf(b, p->ips, p->num_ips * sizeof(p->ips[0]));
377 }
378
379 io_read_str(b, &p->aia);
380 io_read_str(b, &p->aki);
381 io_read_str(b, &p->ski);
382 assert(p->aia && p->aki && p->ski);
383
384 return p;
385 }
386
387 /*
388 * Add each IP address in the ROA into the VRP tree.
389 * Updates "vrps" to be the number of VRPs and "uniqs" to be the unique
390 * number of addresses.
391 */
392 void
roa_insert_vrps(struct vrp_tree * tree,struct roa * roa,struct repo * rp)393 roa_insert_vrps(struct vrp_tree *tree, struct roa *roa, struct repo *rp)
394 {
395 struct vrp *v, *found;
396 size_t i;
397
398 for (i = 0; i < roa->num_ips; i++) {
399 if ((v = malloc(sizeof(*v))) == NULL)
400 err(1, NULL);
401 v->afi = roa->ips[i].afi;
402 v->addr = roa->ips[i].addr;
403 v->maxlength = roa->ips[i].maxlength;
404 v->asid = roa->asid;
405 v->talid = roa->talid;
406 if (rp != NULL)
407 v->repoid = repo_id(rp);
408 else
409 v->repoid = 0;
410 v->expires = roa->expires;
411
412 /*
413 * Check if a similar VRP already exists in the tree.
414 * If the found VRP expires sooner, update it to this
415 * ROAs later expiry moment.
416 */
417 if ((found = RB_INSERT(vrp_tree, tree, v)) != NULL) {
418 /* already exists */
419 if (found->expires < v->expires) {
420 /* update found with preferred data */
421 /* adjust unique count */
422 repo_stat_inc(repo_byid(found->repoid),
423 found->talid, RTYPE_ROA, STYPE_DEC_UNIQUE);
424 found->expires = v->expires;
425 found->talid = v->talid;
426 found->repoid = v->repoid;
427 repo_stat_inc(rp, v->talid, RTYPE_ROA,
428 STYPE_UNIQUE);
429 }
430 free(v);
431 } else
432 repo_stat_inc(rp, v->talid, RTYPE_ROA, STYPE_UNIQUE);
433
434 repo_stat_inc(rp, roa->talid, RTYPE_ROA, STYPE_TOTAL);
435 }
436 }
437
438 static inline int
vrpcmp(struct vrp * a,struct vrp * b)439 vrpcmp(struct vrp *a, struct vrp *b)
440 {
441 int rv;
442
443 if (a->afi > b->afi)
444 return 1;
445 if (a->afi < b->afi)
446 return -1;
447 switch (a->afi) {
448 case AFI_IPV4:
449 rv = memcmp(&a->addr.addr, &b->addr.addr, 4);
450 if (rv)
451 return rv;
452 break;
453 case AFI_IPV6:
454 rv = memcmp(&a->addr.addr, &b->addr.addr, 16);
455 if (rv)
456 return rv;
457 break;
458 default:
459 break;
460 }
461 /* a smaller prefixlen is considered bigger, e.g. /8 vs /10 */
462 if (a->addr.prefixlen < b->addr.prefixlen)
463 return 1;
464 if (a->addr.prefixlen > b->addr.prefixlen)
465 return -1;
466 if (a->maxlength < b->maxlength)
467 return 1;
468 if (a->maxlength > b->maxlength)
469 return -1;
470
471 if (a->asid > b->asid)
472 return 1;
473 if (a->asid < b->asid)
474 return -1;
475
476 return 0;
477 }
478
479 RB_GENERATE(vrp_tree, vrp, entry, vrpcmp);
480