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