1 /* $OpenBSD: roa.c,v 1.19 2021/05/11 11:32:51 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 = recallocarray(p->res->ips, p->res->ipsz, p->res->ipsz + 1, 115 sizeof(struct roa_ip)); 116 if (p->res->ips == NULL) 117 err(1, NULL); 118 res = &p->res->ips[p->res->ipsz++]; 119 120 res->addr = addr; 121 res->afi = afi; 122 res->maxlength = (maxlength == NULL) ? addr.prefixlen : 123 ASN1_INTEGER_get(maxlength); 124 ip_roa_compose_ranges(res); 125 126 rc = 1; 127 out: 128 sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free); 129 return rc; 130 } 131 132 /* 133 * Parse IP address family, RFC 6482, section 3.3. 134 * Returns zero on failure, non-zero on success. 135 */ 136 static int 137 roa_parse_ipfam(const ASN1_OCTET_STRING *os, struct parse *p) 138 { 139 ASN1_SEQUENCE_ANY *seq, *sseq = NULL; 140 const unsigned char *d = os->data; 141 size_t dsz = os->length; 142 int i, rc = 0; 143 const ASN1_TYPE *t; 144 enum afi afi; 145 146 if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) { 147 cryptowarnx("%s: RFC 6482 section 3.3: ROAIPAddressFamily: " 148 "failed ASN.1 sequence parse", p->fn); 149 goto out; 150 } else if (sk_ASN1_TYPE_num(seq) != 2) { 151 warnx("%s: RFC 6482 section 3.3: ROAIPAddressFamily: " 152 "want 2 elements, have %d", 153 p->fn, sk_ASN1_TYPE_num(seq)); 154 goto out; 155 } 156 157 t = sk_ASN1_TYPE_value(seq, 0); 158 if (t->type != V_ASN1_OCTET_STRING) { 159 warnx("%s: RFC 6482 section 3.3: addressFamily: " 160 "want ASN.1 octet string, have %s (NID %d)", 161 p->fn, ASN1_tag2str(t->type), t->type); 162 goto out; 163 } 164 if (!ip_addr_afi_parse(p->fn, t->value.octet_string, &afi)) { 165 warnx("%s: RFC 6482 section 3.3: addressFamily: " 166 "invalid", p->fn); 167 goto out; 168 } 169 170 t = sk_ASN1_TYPE_value(seq, 1); 171 if (t->type != V_ASN1_SEQUENCE) { 172 warnx("%s: RFC 6482 section 3.3: addresses: " 173 "want ASN.1 sequence, have %s (NID %d)", 174 p->fn, ASN1_tag2str(t->type), t->type); 175 goto out; 176 } 177 178 d = t->value.octet_string->data; 179 dsz = t->value.octet_string->length; 180 181 if ((sseq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) { 182 cryptowarnx("%s: RFC 6482 section 3.3: addresses: " 183 "failed ASN.1 sequence parse", p->fn); 184 goto out; 185 } 186 187 for (i = 0; i < sk_ASN1_TYPE_num(sseq); i++) { 188 t = sk_ASN1_TYPE_value(sseq, i); 189 if (t->type != V_ASN1_SEQUENCE) { 190 warnx("%s: RFC 6482 section 3.3: ROAIPAddress: " 191 "want ASN.1 sequence, have %s (NID %d)", 192 p->fn, ASN1_tag2str(t->type), t->type); 193 goto out; 194 } 195 if (!roa_parse_addr(t->value.octet_string, afi, p)) 196 goto out; 197 } 198 199 rc = 1; 200 out: 201 sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free); 202 sk_ASN1_TYPE_pop_free(sseq, ASN1_TYPE_free); 203 return rc; 204 } 205 206 /* 207 * Parse IP blocks, RFC 6482, section 3.3. 208 * Returns zero on failure, non-zero on success. 209 */ 210 static int 211 roa_parse_ipblocks(const ASN1_OCTET_STRING *os, struct parse *p) 212 { 213 ASN1_SEQUENCE_ANY *seq; 214 const unsigned char *d = os->data; 215 size_t dsz = os->length; 216 int i, rc = 0; 217 const ASN1_TYPE *t; 218 219 if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) { 220 cryptowarnx("%s: RFC 6482 section 3.3: ipAddrBlocks: " 221 "failed ASN.1 sequence parse", p->fn); 222 goto out; 223 } 224 225 for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) { 226 t = sk_ASN1_TYPE_value(seq, i); 227 if (t->type != V_ASN1_SEQUENCE) { 228 warnx("%s: RFC 6482 section 3.3: ROAIPAddressFamily: " 229 "want ASN.1 sequence, have %s (NID %d)", 230 p->fn, ASN1_tag2str(t->type), t->type); 231 goto out; 232 } else if (!roa_parse_ipfam(t->value.octet_string, p)) 233 goto out; 234 } 235 236 rc = 1; 237 out: 238 sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free); 239 return rc; 240 } 241 242 /* 243 * Parses the eContent section of an ROA file, RFC 6482, section 3. 244 * Returns zero on failure, non-zero on success. 245 */ 246 static int 247 roa_parse_econtent(const unsigned char *d, size_t dsz, struct parse *p) 248 { 249 ASN1_SEQUENCE_ANY *seq; 250 int i = 0, rc = 0, sz; 251 const ASN1_TYPE *t; 252 253 /* RFC 6482, section 3. */ 254 255 if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) { 256 cryptowarnx("%s: RFC 6482 section 3: RouteOriginAttestation: " 257 "failed ASN.1 sequence parse", p->fn); 258 goto out; 259 } 260 261 if ((sz = sk_ASN1_TYPE_num(seq)) != 2 && sz != 3) { 262 warnx("%s: RFC 6482 section 3: RouteOriginAttestation: " 263 "want 2 or 3 elements, have %d", 264 p->fn, sk_ASN1_TYPE_num(seq)); 265 goto out; 266 } 267 268 /* RFC 6482, section 3.1. */ 269 270 if (sz == 3) { 271 t = sk_ASN1_TYPE_value(seq, i++); 272 273 /* 274 * This check with ASN1_INTEGER_get() is fine since 275 * we're looking for a value of zero anyway, so any 276 * overflowing number will be definition be wrong. 277 */ 278 279 if (t->type != V_ASN1_INTEGER) { 280 warnx("%s: RFC 6482 section 3.1: version: " 281 "want ASN.1 integer, have %s (NID %d)", 282 p->fn, ASN1_tag2str(t->type), t->type); 283 goto out; 284 } else if (ASN1_INTEGER_get(t->value.integer) != 0) { 285 warnx("%s: RFC 6482 section 3.1: version: " 286 "want version 0, have %ld", 287 p->fn, ASN1_INTEGER_get(t->value.integer)); 288 goto out; 289 } 290 } 291 292 /* 293 * RFC 6482, section 3.2. 294 * It doesn't ever actually state that AS numbers can't be 295 * negative, but...? 296 */ 297 298 t = sk_ASN1_TYPE_value(seq, i++); 299 if (t->type != V_ASN1_INTEGER) { 300 warnx("%s: RFC 6482 section 3.2: asID: " 301 "want ASN.1 integer, have %s (NID %d)", 302 p->fn, ASN1_tag2str(t->type), t->type); 303 goto out; 304 } else if (!as_id_parse(t->value.integer, &p->res->asid)) { 305 warnx("%s: RFC 6482 section 3.2: asID: " 306 "malformed AS identifier", p->fn); 307 goto out; 308 } 309 310 /* RFC 6482, section 3.3. */ 311 312 t = sk_ASN1_TYPE_value(seq, i++); 313 if (t->type != V_ASN1_SEQUENCE) { 314 warnx("%s: RFC 6482 section 3.3: ipAddrBlocks: " 315 "want ASN.1 sequence, have %s (NID %d)", 316 p->fn, ASN1_tag2str(t->type), t->type); 317 goto out; 318 } else if (!roa_parse_ipblocks(t->value.octet_string, p)) 319 goto out; 320 321 rc = 1; 322 out: 323 sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free); 324 return rc; 325 } 326 327 /* 328 * Parse a full RFC 6482 file. 329 * Returns the ROA or NULL if the document was malformed. 330 */ 331 struct roa * 332 roa_parse(X509 **x509, const char *fn) 333 { 334 struct parse p; 335 size_t cmsz; 336 unsigned char *cms; 337 int rc = 0; 338 const ASN1_TIME *at; 339 struct tm expires_tm; 340 time_t expires; 341 342 memset(&p, 0, sizeof(struct parse)); 343 p.fn = fn; 344 345 /* OID from section 2, RFC 6482. */ 346 347 cms = cms_parse_validate(x509, fn, 348 "1.2.840.113549.1.9.16.1.24", &cmsz); 349 if (cms == NULL) 350 return NULL; 351 352 if ((p.res = calloc(1, sizeof(struct roa))) == NULL) 353 err(1, NULL); 354 355 p.res->aia = x509_get_aia(*x509, fn); 356 p.res->aki = x509_get_aki(*x509, 0, fn); 357 p.res->ski = x509_get_ski(*x509, fn); 358 if (p.res->aia == NULL || p.res->aki == NULL || p.res->ski == NULL) { 359 warnx("%s: RFC 6487 section 4.8: " 360 "missing AIA, AKI or SKI X509 extension", fn); 361 goto out; 362 } 363 364 at = X509_get0_notAfter(*x509); 365 if (at == NULL) { 366 warnx("%s: X509_get0_notAfter failed", fn); 367 goto out; 368 } 369 memset(&expires_tm, 0, sizeof(expires_tm)); 370 if (ASN1_time_parse(at->data, at->length, &expires_tm, 0) == -1) { 371 warnx("%s: ASN1_time_parse failed", fn); 372 goto out; 373 } 374 if ((expires = mktime(&expires_tm)) == -1) { 375 err(1, "mktime failed"); 376 goto out; 377 } 378 p.res->expires = expires; 379 380 if (!roa_parse_econtent(cms, cmsz, &p)) 381 goto out; 382 383 rc = 1; 384 out: 385 if (rc == 0) { 386 roa_free(p.res); 387 p.res = NULL; 388 X509_free(*x509); 389 *x509 = NULL; 390 } 391 free(cms); 392 return p.res; 393 394 } 395 396 /* 397 * Free an ROA pointer. 398 * Safe to call with NULL. 399 */ 400 void 401 roa_free(struct roa *p) 402 { 403 404 if (p == NULL) 405 return; 406 free(p->aia); 407 free(p->aki); 408 free(p->ski); 409 free(p->ips); 410 free(p->tal); 411 free(p); 412 } 413 414 /* 415 * Serialise parsed ROA content. 416 * See roa_read() for reader. 417 */ 418 void 419 roa_buffer(struct ibuf *b, const struct roa *p) 420 { 421 size_t i; 422 423 io_simple_buffer(b, &p->valid, sizeof(int)); 424 io_simple_buffer(b, &p->asid, sizeof(uint32_t)); 425 io_simple_buffer(b, &p->ipsz, sizeof(size_t)); 426 io_simple_buffer(b, &p->expires, sizeof(time_t)); 427 428 for (i = 0; i < p->ipsz; i++) { 429 io_simple_buffer(b, &p->ips[i].afi, sizeof(enum afi)); 430 io_simple_buffer(b, &p->ips[i].maxlength, sizeof(size_t)); 431 io_simple_buffer(b, p->ips[i].min, sizeof(p->ips[i].min)); 432 io_simple_buffer(b, p->ips[i].max, sizeof(p->ips[i].max)); 433 ip_addr_buffer(b, &p->ips[i].addr); 434 } 435 436 io_str_buffer(b, p->aia); 437 io_str_buffer(b, p->aki); 438 io_str_buffer(b, p->ski); 439 io_str_buffer(b, p->tal); 440 } 441 442 /* 443 * Read parsed ROA content from descriptor. 444 * See roa_buffer() for writer. 445 * Result must be passed to roa_free(). 446 */ 447 struct roa * 448 roa_read(int fd) 449 { 450 struct roa *p; 451 size_t i; 452 453 if ((p = calloc(1, sizeof(struct roa))) == NULL) 454 err(1, NULL); 455 456 io_simple_read(fd, &p->valid, sizeof(int)); 457 io_simple_read(fd, &p->asid, sizeof(uint32_t)); 458 io_simple_read(fd, &p->ipsz, sizeof(size_t)); 459 io_simple_read(fd, &p->expires, sizeof(time_t)); 460 461 if ((p->ips = calloc(p->ipsz, sizeof(struct roa_ip))) == NULL) 462 err(1, NULL); 463 464 for (i = 0; i < p->ipsz; i++) { 465 io_simple_read(fd, &p->ips[i].afi, sizeof(enum afi)); 466 io_simple_read(fd, &p->ips[i].maxlength, sizeof(size_t)); 467 io_simple_read(fd, &p->ips[i].min, sizeof(p->ips[i].min)); 468 io_simple_read(fd, &p->ips[i].max, sizeof(p->ips[i].max)); 469 ip_addr_read(fd, &p->ips[i].addr); 470 } 471 472 io_str_read(fd, &p->aia); 473 io_str_read(fd, &p->aki); 474 io_str_read(fd, &p->ski); 475 io_str_read(fd, &p->tal); 476 assert(p->aia && p->aki && p->ski && p->tal); 477 478 return p; 479 } 480 481 /* 482 * Add each IP address in the ROA into the VRP tree. 483 * Updates "vrps" to be the number of VRPs and "uniqs" to be the unique 484 * number of addresses. 485 */ 486 void 487 roa_insert_vrps(struct vrp_tree *tree, struct roa *roa, size_t *vrps, 488 size_t *uniqs) 489 { 490 struct vrp *v, *found; 491 size_t i; 492 493 for (i = 0; i < roa->ipsz; i++) { 494 if ((v = malloc(sizeof(*v))) == NULL) 495 err(1, NULL); 496 v->afi = roa->ips[i].afi; 497 v->addr = roa->ips[i].addr; 498 v->maxlength = roa->ips[i].maxlength; 499 v->asid = roa->asid; 500 if ((v->tal = strdup(roa->tal)) == NULL) 501 err(1, NULL); 502 v->expires = roa->expires; 503 504 /* 505 * Check if a similar VRP already exists in the tree. 506 * If the found VRP expires sooner, update it to this 507 * ROAs later expiry moment. 508 */ 509 if ((found = RB_INSERT(vrp_tree, tree, v)) != NULL) { 510 /* already exists */ 511 if (found->expires < v->expires) { 512 /* update found with preferred data */ 513 found->expires = roa->expires; 514 free(found->tal); 515 found->tal = v->tal; 516 v->tal = NULL; 517 } 518 free(v->tal); 519 free(v); 520 } else 521 (*uniqs)++; 522 523 (*vrps)++; 524 } 525 } 526 527 static inline int 528 vrpcmp(struct vrp *a, struct vrp *b) 529 { 530 int rv; 531 532 if (a->afi > b->afi) 533 return 1; 534 if (a->afi < b->afi) 535 return -1; 536 switch (a->afi) { 537 case AFI_IPV4: 538 rv = memcmp(&a->addr.addr, &b->addr.addr, 4); 539 if (rv) 540 return rv; 541 break; 542 case AFI_IPV6: 543 rv = memcmp(&a->addr.addr, &b->addr.addr, 16); 544 if (rv) 545 return rv; 546 break; 547 } 548 /* a smaller prefixlen is considered bigger, e.g. /8 vs /10 */ 549 if (a->addr.prefixlen < b->addr.prefixlen) 550 return 1; 551 if (a->addr.prefixlen > b->addr.prefixlen) 552 return -1; 553 if (a->maxlength < b->maxlength) 554 return 1; 555 if (a->maxlength > b->maxlength) 556 return -1; 557 558 if (a->asid > b->asid) 559 return 1; 560 if (a->asid < b->asid) 561 return -1; 562 563 return 0; 564 } 565 566 RB_GENERATE(vrp_tree, vrp, entry, vrpcmp); 567