1 /* $OpenBSD: cert.c,v 1.122 2024/01/11 11:55:14 job Exp $ */ 2 /* 3 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2021 Job Snijders <job@openbsd.org> 5 * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <assert.h> 21 #include <err.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 #include <openssl/x509v3.h> 29 30 #include "extern.h" 31 32 /* 33 * A parsing sequence of a file (which may just be <stdin>). 34 */ 35 struct parse { 36 struct cert *res; /* result */ 37 const char *fn; /* currently-parsed file */ 38 }; 39 40 extern ASN1_OBJECT *certpol_oid; /* id-cp-ipAddr-asNumber cert policy */ 41 extern ASN1_OBJECT *carepo_oid; /* 1.3.6.1.5.5.7.48.5 (caRepository) */ 42 extern ASN1_OBJECT *manifest_oid; /* 1.3.6.1.5.5.7.48.10 (rpkiManifest) */ 43 extern ASN1_OBJECT *notify_oid; /* 1.3.6.1.5.5.7.48.13 (rpkiNotify) */ 44 45 /* 46 * Append an IP address structure to our list of results. 47 * This will also constrain us to having at most one inheritance 48 * statement per AFI and also not have overlapping ranges (as prohibited 49 * in section 2.2.3.6). 50 * It does not make sure that ranges can't coalesce, that is, that any 51 * two ranges abut each other. 52 * This is warned against in section 2.2.3.6, but doesn't change the 53 * semantics of the system. 54 * Returns zero on failure (IP overlap) non-zero on success. 55 */ 56 static int 57 append_ip(const char *fn, struct cert_ip *ips, size_t *ipsz, 58 const struct cert_ip *ip) 59 { 60 if (!ip_addr_check_overlap(ip, fn, ips, *ipsz, 0)) 61 return 0; 62 ips[(*ipsz)++] = *ip; 63 return 1; 64 } 65 66 /* 67 * Append an AS identifier structure to our list of results. 68 * Makes sure that the identifiers do not overlap or improperly inherit 69 * as defined by RFC 3779 section 3.3. 70 */ 71 static int 72 append_as(const char *fn, struct cert_as *ases, size_t *asz, 73 const struct cert_as *as) 74 { 75 if (!as_check_overlap(as, fn, ases, *asz, 0)) 76 return 0; 77 ases[(*asz)++] = *as; 78 return 1; 79 } 80 81 /* 82 * Parse a range of AS identifiers as in 3.2.3.8. 83 * Returns zero on failure, non-zero on success. 84 */ 85 int 86 sbgp_as_range(const char *fn, struct cert_as *ases, size_t *asz, 87 const ASRange *range) 88 { 89 struct cert_as as; 90 91 memset(&as, 0, sizeof(struct cert_as)); 92 as.type = CERT_AS_RANGE; 93 94 if (!as_id_parse(range->min, &as.range.min)) { 95 warnx("%s: RFC 3779 section 3.2.3.8 (via RFC 1930): " 96 "malformed AS identifier", fn); 97 return 0; 98 } 99 100 if (!as_id_parse(range->max, &as.range.max)) { 101 warnx("%s: RFC 3779 section 3.2.3.8 (via RFC 1930): " 102 "malformed AS identifier", fn); 103 return 0; 104 } 105 106 if (as.range.max == as.range.min) { 107 warnx("%s: RFC 3379 section 3.2.3.8: ASRange: " 108 "range is singular", fn); 109 return 0; 110 } else if (as.range.max < as.range.min) { 111 warnx("%s: RFC 3379 section 3.2.3.8: ASRange: " 112 "range is out of order", fn); 113 return 0; 114 } 115 116 return append_as(fn, ases, asz, &as); 117 } 118 119 /* 120 * Parse an entire 3.2.3.10 integer type. 121 */ 122 int 123 sbgp_as_id(const char *fn, struct cert_as *ases, size_t *asz, 124 const ASN1_INTEGER *i) 125 { 126 struct cert_as as; 127 128 memset(&as, 0, sizeof(struct cert_as)); 129 as.type = CERT_AS_ID; 130 131 if (!as_id_parse(i, &as.id)) { 132 warnx("%s: RFC 3779 section 3.2.3.10 (via RFC 1930): " 133 "malformed AS identifier", fn); 134 return 0; 135 } 136 if (as.id == 0) { 137 warnx("%s: RFC 3779 section 3.2.3.10 (via RFC 1930): " 138 "AS identifier zero is reserved", fn); 139 return 0; 140 } 141 142 return append_as(fn, ases, asz, &as); 143 } 144 145 static int 146 sbgp_as_inherit(const char *fn, struct cert_as *ases, size_t *asz) 147 { 148 struct cert_as as; 149 150 memset(&as, 0, sizeof(struct cert_as)); 151 as.type = CERT_AS_INHERIT; 152 153 return append_as(fn, ases, asz, &as); 154 } 155 156 int 157 sbgp_parse_assysnum(const char *fn, const ASIdentifiers *asidentifiers, 158 struct cert_as **out_as, size_t *out_asz) 159 { 160 const ASIdOrRanges *aors = NULL; 161 struct cert_as *as = NULL; 162 size_t asz = 0, sz; 163 int i; 164 165 assert(*out_as == NULL && *out_asz == 0); 166 167 if (asidentifiers->rdi != NULL) { 168 warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: " 169 "should not have RDI values", fn); 170 goto out; 171 } 172 173 if (asidentifiers->asnum == NULL) { 174 warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: " 175 "no AS number resource set", fn); 176 goto out; 177 } 178 179 switch (asidentifiers->asnum->type) { 180 case ASIdentifierChoice_inherit: 181 sz = 1; 182 break; 183 case ASIdentifierChoice_asIdsOrRanges: 184 aors = asidentifiers->asnum->u.asIdsOrRanges; 185 sz = sk_ASIdOrRange_num(aors); 186 break; 187 default: 188 warnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: " 189 "unknown type %d", fn, asidentifiers->asnum->type); 190 goto out; 191 } 192 193 if (sz == 0) { 194 warnx("%s: RFC 6487 section 4.8.11: empty asIdsOrRanges", fn); 195 goto out; 196 } 197 if (sz >= MAX_AS_SIZE) { 198 warnx("%s: too many AS number entries: limit %d", 199 fn, MAX_AS_SIZE); 200 goto out; 201 } 202 as = calloc(sz, sizeof(struct cert_as)); 203 if (as == NULL) 204 err(1, NULL); 205 206 if (aors == NULL) { 207 if (!sbgp_as_inherit(fn, as, &asz)) 208 goto out; 209 } 210 211 for (i = 0; i < sk_ASIdOrRange_num(aors); i++) { 212 const ASIdOrRange *aor; 213 214 aor = sk_ASIdOrRange_value(aors, i); 215 switch (aor->type) { 216 case ASIdOrRange_id: 217 if (!sbgp_as_id(fn, as, &asz, aor->u.id)) 218 goto out; 219 break; 220 case ASIdOrRange_range: 221 if (!sbgp_as_range(fn, as, &asz, aor->u.range)) 222 goto out; 223 break; 224 default: 225 warnx("%s: RFC 3779 section 3.2.3.5: ASIdOrRange: " 226 "unknown type %d", fn, aor->type); 227 goto out; 228 } 229 } 230 231 *out_as = as; 232 *out_asz = asz; 233 234 return 1; 235 236 out: 237 free(as); 238 239 return 0; 240 } 241 242 /* 243 * Parse RFC 6487 4.8.11 X509v3 extension, with syntax documented in RFC 244 * 3779 starting in section 3.2. 245 * Returns zero on failure, non-zero on success. 246 */ 247 static int 248 sbgp_assysnum(struct parse *p, X509_EXTENSION *ext) 249 { 250 ASIdentifiers *asidentifiers = NULL; 251 int rc = 0; 252 253 if (!X509_EXTENSION_get_critical(ext)) { 254 warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: " 255 "extension not critical", p->fn); 256 goto out; 257 } 258 259 if ((asidentifiers = X509V3_EXT_d2i(ext)) == NULL) { 260 warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: " 261 "failed extension parse", p->fn); 262 goto out; 263 } 264 265 if (!sbgp_parse_assysnum(p->fn, asidentifiers, 266 &p->res->as, &p->res->asz)) 267 goto out; 268 269 rc = 1; 270 out: 271 ASIdentifiers_free(asidentifiers); 272 return rc; 273 } 274 275 /* 276 * Construct a RFC 3779 2.2.3.8 range from its bit string. 277 * Returns zero on failure, non-zero on success. 278 */ 279 int 280 sbgp_addr(const char *fn, struct cert_ip *ips, size_t *ipsz, enum afi afi, 281 const ASN1_BIT_STRING *bs) 282 { 283 struct cert_ip ip; 284 285 memset(&ip, 0, sizeof(struct cert_ip)); 286 287 ip.afi = afi; 288 ip.type = CERT_IP_ADDR; 289 290 if (!ip_addr_parse(bs, afi, fn, &ip.ip)) { 291 warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: " 292 "invalid IP address", fn); 293 return 0; 294 } 295 296 if (!ip_cert_compose_ranges(&ip)) { 297 warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: " 298 "IP address range reversed", fn); 299 return 0; 300 } 301 302 return append_ip(fn, ips, ipsz, &ip); 303 } 304 305 /* 306 * Parse RFC 3779 2.2.3.9 range of addresses. 307 * Returns zero on failure, non-zero on success. 308 */ 309 int 310 sbgp_addr_range(const char *fn, struct cert_ip *ips, size_t *ipsz, 311 enum afi afi, const IPAddressRange *range) 312 { 313 struct cert_ip ip; 314 315 memset(&ip, 0, sizeof(struct cert_ip)); 316 317 ip.afi = afi; 318 ip.type = CERT_IP_RANGE; 319 320 if (!ip_addr_parse(range->min, afi, fn, &ip.range.min)) { 321 warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: " 322 "invalid IP address", fn); 323 return 0; 324 } 325 326 if (!ip_addr_parse(range->max, afi, fn, &ip.range.max)) { 327 warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: " 328 "invalid IP address", fn); 329 return 0; 330 } 331 332 if (!ip_cert_compose_ranges(&ip)) { 333 warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: " 334 "IP address range reversed", fn); 335 return 0; 336 } 337 338 return append_ip(fn, ips, ipsz, &ip); 339 } 340 341 static int 342 sbgp_addr_inherit(const char *fn, struct cert_ip *ips, size_t *ipsz, 343 enum afi afi) 344 { 345 struct cert_ip ip; 346 347 memset(&ip, 0, sizeof(struct cert_ip)); 348 349 ip.afi = afi; 350 ip.type = CERT_IP_INHERIT; 351 352 return append_ip(fn, ips, ipsz, &ip); 353 } 354 355 int 356 sbgp_parse_ipaddrblk(const char *fn, const IPAddrBlocks *addrblk, 357 struct cert_ip **out_ips, size_t *out_ipsz) 358 { 359 const IPAddressFamily *af; 360 const IPAddressOrRanges *aors; 361 const IPAddressOrRange *aor; 362 enum afi afi; 363 struct cert_ip *ips = NULL; 364 size_t ipsz = 0, sz; 365 int ipv4_seen = 0, ipv6_seen = 0; 366 int i, j, ipaddrblocksz; 367 368 assert(*out_ips == NULL && *out_ipsz == 0); 369 370 ipaddrblocksz = sk_IPAddressFamily_num(addrblk); 371 if (ipaddrblocksz != 1 && ipaddrblocksz != 2) { 372 warnx("%s: RFC 6487 section 4.8.10: unexpected number of " 373 "ipAddrBlocks (got %d, expected 1 or 2)", 374 fn, ipaddrblocksz); 375 goto out; 376 } 377 378 for (i = 0; i < ipaddrblocksz; i++) { 379 af = sk_IPAddressFamily_value(addrblk, i); 380 381 switch (af->ipAddressChoice->type) { 382 case IPAddressChoice_inherit: 383 aors = NULL; 384 sz = ipsz + 1; 385 break; 386 case IPAddressChoice_addressesOrRanges: 387 aors = af->ipAddressChoice->u.addressesOrRanges; 388 sz = ipsz + sk_IPAddressOrRange_num(aors); 389 break; 390 default: 391 warnx("%s: RFC 3779: IPAddressChoice: unknown type %d", 392 fn, af->ipAddressChoice->type); 393 goto out; 394 } 395 if (sz == ipsz) { 396 warnx("%s: RFC 6487 section 4.8.10: " 397 "empty ipAddressesOrRanges", fn); 398 goto out; 399 } 400 401 if (sz >= MAX_IP_SIZE) 402 goto out; 403 ips = recallocarray(ips, ipsz, sz, sizeof(struct cert_ip)); 404 if (ips == NULL) 405 err(1, NULL); 406 407 if (!ip_addr_afi_parse(fn, af->addressFamily, &afi)) { 408 warnx("%s: RFC 3779: invalid AFI", fn); 409 goto out; 410 } 411 412 switch(afi) { 413 case AFI_IPV4: 414 if (ipv4_seen++ > 0) { 415 warnx("%s: RFC 6487 section 4.8.10: " 416 "IPv4 appears twice", fn); 417 goto out; 418 } 419 break; 420 case AFI_IPV6: 421 if (ipv6_seen++ > 0) { 422 warnx("%s: RFC 6487 section 4.8.10: " 423 "IPv6 appears twice", fn); 424 goto out; 425 } 426 break; 427 } 428 429 if (aors == NULL) { 430 if (!sbgp_addr_inherit(fn, ips, &ipsz, afi)) 431 goto out; 432 continue; 433 } 434 435 for (j = 0; j < sk_IPAddressOrRange_num(aors); j++) { 436 aor = sk_IPAddressOrRange_value(aors, j); 437 switch (aor->type) { 438 case IPAddressOrRange_addressPrefix: 439 if (!sbgp_addr(fn, ips, &ipsz, afi, 440 aor->u.addressPrefix)) 441 goto out; 442 break; 443 case IPAddressOrRange_addressRange: 444 if (!sbgp_addr_range(fn, ips, &ipsz, afi, 445 aor->u.addressRange)) 446 goto out; 447 break; 448 default: 449 warnx("%s: RFC 3779: IPAddressOrRange: " 450 "unknown type %d", fn, aor->type); 451 goto out; 452 } 453 } 454 } 455 456 *out_ips = ips; 457 *out_ipsz = ipsz; 458 459 return 1; 460 461 out: 462 free(ips); 463 464 return 0; 465 } 466 467 /* 468 * Parse an sbgp-ipAddrBlock X509 extension, RFC 6487 4.8.10, with 469 * syntax documented in RFC 3779 starting in section 2.2. 470 * Returns zero on failure, non-zero on success. 471 */ 472 static int 473 sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext) 474 { 475 IPAddrBlocks *addrblk = NULL; 476 int rc = 0; 477 478 if (!X509_EXTENSION_get_critical(ext)) { 479 warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: " 480 "extension not critical", p->fn); 481 goto out; 482 } 483 484 if ((addrblk = X509V3_EXT_d2i(ext)) == NULL) { 485 warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: " 486 "failed extension parse", p->fn); 487 goto out; 488 } 489 490 if (!sbgp_parse_ipaddrblk(p->fn, addrblk, &p->res->ips, &p->res->ipsz)) 491 goto out; 492 493 if (p->res->ipsz == 0) { 494 warnx("%s: RFC 6487 section 4.8.10: empty ipAddrBlock", p->fn); 495 goto out; 496 } 497 498 rc = 1; 499 out: 500 IPAddrBlocks_free(addrblk); 501 return rc; 502 } 503 504 /* 505 * Parse "Subject Information Access" extension, RFC 6487 4.8.8. 506 * Returns zero on failure, non-zero on success. 507 */ 508 static int 509 sbgp_sia(struct parse *p, X509_EXTENSION *ext) 510 { 511 AUTHORITY_INFO_ACCESS *sia = NULL; 512 ACCESS_DESCRIPTION *ad; 513 ASN1_OBJECT *oid; 514 const char *mftfilename; 515 int i, rc = 0; 516 517 if (X509_EXTENSION_get_critical(ext)) { 518 warnx("%s: RFC 6487 section 4.8.8: SIA: " 519 "extension not non-critical", p->fn); 520 goto out; 521 } 522 523 if ((sia = X509V3_EXT_d2i(ext)) == NULL) { 524 warnx("%s: RFC 6487 section 4.8.8: SIA: failed extension parse", 525 p->fn); 526 goto out; 527 } 528 529 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(sia); i++) { 530 ad = sk_ACCESS_DESCRIPTION_value(sia, i); 531 532 oid = ad->method; 533 534 if (OBJ_cmp(oid, carepo_oid) == 0) { 535 if (!x509_location(p->fn, "SIA: caRepository", 536 "rsync://", ad->location, &p->res->repo)) 537 goto out; 538 } else if (OBJ_cmp(oid, manifest_oid) == 0) { 539 if (!x509_location(p->fn, "SIA: rpkiManifest", 540 "rsync://", ad->location, &p->res->mft)) 541 goto out; 542 } else if (OBJ_cmp(oid, notify_oid) == 0) { 543 if (!x509_location(p->fn, "SIA: rpkiNotify", 544 "https://", ad->location, &p->res->notify)) 545 goto out; 546 } 547 } 548 549 if (p->res->mft == NULL || p->res->repo == NULL) { 550 warnx("%s: RFC 6487 section 4.8.8: SIA: missing caRepository " 551 "or rpkiManifest", p->fn); 552 goto out; 553 } 554 555 mftfilename = strrchr(p->res->mft, '/'); 556 if (mftfilename == NULL) { 557 warnx("%s: SIA: invalid rpkiManifest entry", p->fn); 558 goto out; 559 } 560 mftfilename++; 561 if (!valid_filename(mftfilename, strlen(mftfilename))) { 562 warnx("%s: SIA: rpkiManifest filename contains invalid " 563 "characters", p->fn); 564 goto out; 565 } 566 567 if (strstr(p->res->mft, p->res->repo) != p->res->mft) { 568 warnx("%s: RFC 6487 section 4.8.8: SIA: " 569 "conflicting URIs for caRepository and rpkiManifest", 570 p->fn); 571 goto out; 572 } 573 574 if (rtype_from_file_extension(p->res->mft) != RTYPE_MFT) { 575 warnx("%s: RFC 6487 section 4.8.8: SIA: " 576 "not an MFT file", p->fn); 577 goto out; 578 } 579 580 rc = 1; 581 out: 582 AUTHORITY_INFO_ACCESS_free(sia); 583 return rc; 584 } 585 586 /* 587 * Parse the certificate policies extension and check that it follows RFC 7318. 588 * Returns zero on failure, non-zero on success. 589 */ 590 static int 591 certificate_policies(struct parse *p, X509_EXTENSION *ext) 592 { 593 STACK_OF(POLICYINFO) *policies = NULL; 594 POLICYINFO *policy; 595 STACK_OF(POLICYQUALINFO) *qualifiers; 596 POLICYQUALINFO *qualifier; 597 int nid; 598 int rc = 0; 599 600 if (!X509_EXTENSION_get_critical(ext)) { 601 warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: " 602 "extension not critical", p->fn); 603 goto out; 604 } 605 606 if ((policies = X509V3_EXT_d2i(ext)) == NULL) { 607 warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: " 608 "failed extension parse", p->fn); 609 goto out; 610 } 611 612 if (sk_POLICYINFO_num(policies) != 1) { 613 warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: " 614 "want 1 policy, got %d", p->fn, 615 sk_POLICYINFO_num(policies)); 616 goto out; 617 } 618 619 policy = sk_POLICYINFO_value(policies, 0); 620 assert(policy != NULL && policy->policyid != NULL); 621 622 if (OBJ_cmp(policy->policyid, certpol_oid) != 0) { 623 char pbuf[128], cbuf[128]; 624 625 OBJ_obj2txt(pbuf, sizeof(pbuf), policy->policyid, 1); 626 OBJ_obj2txt(cbuf, sizeof(cbuf), certpol_oid, 1); 627 warnx("%s: RFC 7318 section 2: certificatePolicies: " 628 "unexpected OID: %s, want %s", p->fn, pbuf, cbuf); 629 goto out; 630 } 631 632 /* Policy qualifiers are optional. If they're absent, we're done. */ 633 if ((qualifiers = policy->qualifiers) == NULL) { 634 rc = 1; 635 goto out; 636 } 637 638 if (sk_POLICYQUALINFO_num(qualifiers) != 1) { 639 warnx("%s: RFC 7318 section 2: certificatePolicies: " 640 "want 1 policy qualifier, got %d", p->fn, 641 sk_POLICYQUALINFO_num(qualifiers)); 642 goto out; 643 } 644 645 qualifier = sk_POLICYQUALINFO_value(qualifiers, 0); 646 assert(qualifier != NULL && qualifier->pqualid != NULL); 647 648 if ((nid = OBJ_obj2nid(qualifier->pqualid)) != NID_id_qt_cps) { 649 warnx("%s: RFC 7318 section 2: certificatePolicies: " 650 "want CPS, got %d (%s)", p->fn, nid, OBJ_nid2sn(nid)); 651 goto out; 652 } 653 654 if (verbose > 1 && !filemode) 655 warnx("%s: CPS %.*s", p->fn, qualifier->d.cpsuri->length, 656 qualifier->d.cpsuri->data); 657 658 rc = 1; 659 out: 660 sk_POLICYINFO_pop_free(policies, POLICYINFO_free); 661 return rc; 662 } 663 664 /* 665 * Lightweight version of cert_parse_pre() for EE certs. 666 * Parses the two RFC 3779 extensions, and performs some sanity checks. 667 * Returns cert on success and NULL on failure. 668 */ 669 struct cert * 670 cert_parse_ee_cert(const char *fn, int talid, X509 *x) 671 { 672 struct parse p; 673 X509_EXTENSION *ext; 674 int index; 675 676 memset(&p, 0, sizeof(struct parse)); 677 p.fn = fn; 678 if ((p.res = calloc(1, sizeof(struct cert))) == NULL) 679 err(1, NULL); 680 681 if (X509_get_version(x) != 2) { 682 warnx("%s: RFC 6487 4.1: X.509 version must be v3", fn); 683 goto out; 684 } 685 686 if (!x509_valid_subject(fn, x)) 687 goto out; 688 689 if (X509_get_key_usage(x) != KU_DIGITAL_SIGNATURE) { 690 warnx("%s: RFC 6487 section 4.8.4: KU must be digitalSignature", 691 fn); 692 goto out; 693 } 694 695 /* EKU may be allowed for some purposes in the future. */ 696 if (X509_get_extended_key_usage(x) != UINT32_MAX) { 697 warnx("%s: RFC 6487 section 4.8.5: EKU not allowed", fn); 698 goto out; 699 } 700 701 index = X509_get_ext_by_NID(x, NID_sbgp_ipAddrBlock, -1); 702 if ((ext = X509_get_ext(x, index)) != NULL) { 703 if (!sbgp_ipaddrblk(&p, ext)) 704 goto out; 705 } 706 707 index = X509_get_ext_by_NID(x, NID_sbgp_autonomousSysNum, -1); 708 if ((ext = X509_get_ext(x, index)) != NULL) { 709 if (!sbgp_assysnum(&p, ext)) 710 goto out; 711 } 712 713 if (!X509_up_ref(x)) { 714 warnx("%s: X509_up_ref failed", fn); 715 goto out; 716 } 717 718 p.res->x509 = x; 719 p.res->talid = talid; 720 721 if (!constraints_validate(fn, p.res)) 722 goto out; 723 724 return p.res; 725 726 out: 727 cert_free(p.res); 728 return NULL; 729 } 730 731 /* 732 * Parse and partially validate an RPKI X509 certificate (either a trust 733 * anchor or a certificate) as defined in RFC 6487. 734 * Returns the parse results or NULL on failure. 735 */ 736 struct cert * 737 cert_parse_pre(const char *fn, const unsigned char *der, size_t len) 738 { 739 const unsigned char *oder; 740 int extsz; 741 size_t i; 742 X509 *x = NULL; 743 X509_EXTENSION *ext = NULL; 744 const X509_ALGOR *palg; 745 const ASN1_BIT_STRING *piuid = NULL, *psuid = NULL; 746 const ASN1_OBJECT *cobj; 747 ASN1_OBJECT *obj; 748 EVP_PKEY *pkey; 749 struct parse p; 750 int nid, ip, as, sia, cp, crldp, aia, aki, ski, 751 eku, bc, ku; 752 753 nid = ip = as = sia = cp = crldp = aia = aki = ski = eku = bc = ku = 0; 754 755 /* just fail for empty buffers, the warning was printed elsewhere */ 756 if (der == NULL) 757 return NULL; 758 759 memset(&p, 0, sizeof(struct parse)); 760 p.fn = fn; 761 if ((p.res = calloc(1, sizeof(struct cert))) == NULL) 762 err(1, NULL); 763 764 oder = der; 765 if ((x = d2i_X509(NULL, &der, len)) == NULL) { 766 warnx("%s: d2i_X509", p.fn); 767 goto out; 768 } 769 if (der != oder + len) { 770 warnx("%s: %td bytes trailing garbage", fn, oder + len - der); 771 goto out; 772 } 773 774 /* Cache X509v3 extensions, see X509_check_ca(3). */ 775 if (X509_check_purpose(x, -1, -1) <= 0) { 776 warnx("%s: could not cache X509v3 extensions", p.fn); 777 goto out; 778 } 779 780 if (X509_get_version(x) != 2) { 781 warnx("%s: RFC 6487 4.1: X.509 version must be v3", fn); 782 goto out; 783 } 784 785 X509_get0_signature(NULL, &palg, x); 786 if (palg == NULL) { 787 warnx("%s: X509_get0_signature", p.fn); 788 goto out; 789 } 790 X509_ALGOR_get0(&cobj, NULL, NULL, palg); 791 nid = OBJ_obj2nid(cobj); 792 if (nid == NID_ecdsa_with_SHA256) { 793 if (verbose) 794 warnx("%s: P-256 support is experimental", fn); 795 } else if (nid != NID_sha256WithRSAEncryption) { 796 warnx("%s: RFC 7935: wrong signature algorithm %s, want %s", 797 fn, OBJ_nid2ln(nid), 798 OBJ_nid2ln(NID_sha256WithRSAEncryption)); 799 goto out; 800 } 801 802 X509_get0_uids(x, &piuid, &psuid); 803 if (piuid != NULL || psuid != NULL) { 804 warnx("%s: issuer or subject unique identifiers not allowed", 805 fn); 806 goto out; 807 } 808 809 if (!x509_valid_subject(p.fn, x)) 810 goto out; 811 812 /* Look for X509v3 extensions. */ 813 814 if ((extsz = X509_get_ext_count(x)) < 0) 815 errx(1, "X509_get_ext_count"); 816 817 for (i = 0; i < (size_t)extsz; i++) { 818 ext = X509_get_ext(x, i); 819 assert(ext != NULL); 820 obj = X509_EXTENSION_get_object(ext); 821 assert(obj != NULL); 822 823 switch (nid = OBJ_obj2nid(obj)) { 824 case NID_sbgp_ipAddrBlock: 825 if (ip++ > 0) 826 goto dup; 827 if (!sbgp_ipaddrblk(&p, ext)) 828 goto out; 829 break; 830 case NID_sbgp_autonomousSysNum: 831 if (as++ > 0) 832 goto dup; 833 if (!sbgp_assysnum(&p, ext)) 834 goto out; 835 break; 836 case NID_sinfo_access: 837 if (sia++ > 0) 838 goto dup; 839 if (!sbgp_sia(&p, ext)) 840 goto out; 841 break; 842 case NID_certificate_policies: 843 if (cp++ > 0) 844 goto dup; 845 if (!certificate_policies(&p, ext)) 846 goto out; 847 break; 848 case NID_crl_distribution_points: 849 if (crldp++ > 0) 850 goto dup; 851 break; 852 case NID_info_access: 853 if (aia++ > 0) 854 goto dup; 855 break; 856 case NID_authority_key_identifier: 857 if (aki++ > 0) 858 goto dup; 859 break; 860 case NID_subject_key_identifier: 861 if (ski++ > 0) 862 goto dup; 863 break; 864 case NID_ext_key_usage: 865 if (eku++ > 0) 866 goto dup; 867 break; 868 case NID_basic_constraints: 869 if (bc++ > 0) 870 goto dup; 871 break; 872 case NID_key_usage: 873 if (ku++ > 0) 874 goto dup; 875 break; 876 default: 877 /* unexpected extensions warrant investigation */ 878 { 879 char objn[64]; 880 OBJ_obj2txt(objn, sizeof(objn), obj, 0); 881 warnx("%s: ignoring %s (NID %d)", 882 p.fn, objn, OBJ_obj2nid(obj)); 883 } 884 break; 885 } 886 } 887 888 if (!x509_get_aki(x, p.fn, &p.res->aki)) 889 goto out; 890 if (!x509_get_ski(x, p.fn, &p.res->ski)) 891 goto out; 892 if (!x509_get_aia(x, p.fn, &p.res->aia)) 893 goto out; 894 if (!x509_get_crl(x, p.fn, &p.res->crl)) 895 goto out; 896 if (!x509_get_notbefore(x, p.fn, &p.res->notbefore)) 897 goto out; 898 if (!x509_get_notafter(x, p.fn, &p.res->notafter)) 899 goto out; 900 p.res->purpose = x509_get_purpose(x, p.fn); 901 902 /* Validation on required fields. */ 903 904 switch (p.res->purpose) { 905 case CERT_PURPOSE_CA: 906 if ((pkey = X509_get0_pubkey(x)) == NULL) { 907 warnx("%s: X509_get0_pubkey failed", p.fn); 908 goto out; 909 } 910 if (!valid_ca_pkey(p.fn, pkey)) 911 goto out; 912 913 if (X509_get_key_usage(x) != (KU_KEY_CERT_SIGN | KU_CRL_SIGN)) { 914 warnx("%s: RFC 6487 section 4.8.4: key usage violation", 915 p.fn); 916 goto out; 917 } 918 919 /* EKU may be allowed for some purposes in the future. */ 920 if (X509_get_extended_key_usage(x) != UINT32_MAX) { 921 warnx("%s: RFC 6487 section 4.8.5: EKU not allowed", 922 fn); 923 goto out; 924 } 925 926 if (p.res->mft == NULL) { 927 warnx("%s: RFC 6487 section 4.8.8: missing SIA", p.fn); 928 goto out; 929 } 930 if (p.res->asz == 0 && p.res->ipsz == 0) { 931 warnx("%s: missing IP or AS resources", p.fn); 932 goto out; 933 } 934 break; 935 case CERT_PURPOSE_BGPSEC_ROUTER: 936 p.res->pubkey = x509_get_pubkey(x, p.fn); 937 if (p.res->pubkey == NULL) { 938 warnx("%s: x509_get_pubkey failed", p.fn); 939 goto out; 940 } 941 if (p.res->ipsz > 0) { 942 warnx("%s: unexpected IP resources in BGPsec cert", 943 p.fn); 944 goto out; 945 } 946 for (i = 0; i < p.res->asz; i++) { 947 if (p.res->as[i].type == CERT_AS_INHERIT) { 948 warnx("%s: inherit elements not allowed in EE" 949 " cert", p.fn); 950 goto out; 951 } 952 } 953 if (sia) { 954 warnx("%s: unexpected SIA extension in BGPsec cert", 955 p.fn); 956 goto out; 957 } 958 break; 959 default: 960 warnx("%s: x509_get_purpose failed in %s", p.fn, __func__); 961 goto out; 962 } 963 964 if (p.res->ski == NULL) { 965 warnx("%s: RFC 6487 section 8.4.2: missing SKI", p.fn); 966 goto out; 967 } 968 969 p.res->x509 = x; 970 return p.res; 971 972 dup: 973 warnx("%s: RFC 5280 section 4.2: duplicate %s extension", fn, 974 OBJ_nid2sn(nid)); 975 out: 976 cert_free(p.res); 977 X509_free(x); 978 return NULL; 979 } 980 981 struct cert * 982 cert_parse(const char *fn, struct cert *p) 983 { 984 if (p == NULL) 985 return NULL; 986 987 if (p->aki == NULL) { 988 warnx("%s: RFC 6487 section 8.4.2: " 989 "non-trust anchor missing AKI", fn); 990 goto badcert; 991 } 992 if (strcmp(p->aki, p->ski) == 0) { 993 warnx("%s: RFC 6487 section 8.4.2: " 994 "non-trust anchor AKI may not match SKI", fn); 995 goto badcert; 996 } 997 if (p->aia == NULL) { 998 warnx("%s: RFC 6487 section 8.4.7: AIA: extension missing", fn); 999 goto badcert; 1000 } 1001 if (p->crl == NULL) { 1002 warnx("%s: RFC 6487 section 4.8.6: CRL: " 1003 "no CRL distribution point extension", fn); 1004 goto badcert; 1005 } 1006 return p; 1007 1008 badcert: 1009 cert_free(p); 1010 return NULL; 1011 } 1012 1013 struct cert * 1014 ta_parse(const char *fn, struct cert *p, const unsigned char *pkey, 1015 size_t pkeysz) 1016 { 1017 ASN1_TIME *notBefore, *notAfter; 1018 EVP_PKEY *pk, *opk; 1019 time_t now = get_current_time(); 1020 1021 if (p == NULL) 1022 return NULL; 1023 1024 /* first check pubkey against the one from the TAL */ 1025 pk = d2i_PUBKEY(NULL, &pkey, pkeysz); 1026 if (pk == NULL) { 1027 warnx("%s: RFC 6487 (trust anchor): bad TAL pubkey", fn); 1028 goto badcert; 1029 } 1030 if ((opk = X509_get0_pubkey(p->x509)) == NULL) { 1031 warnx("%s: RFC 6487 (trust anchor): missing pubkey", fn); 1032 goto badcert; 1033 } 1034 if (EVP_PKEY_cmp(pk, opk) != 1) { 1035 warnx("%s: RFC 6487 (trust anchor): " 1036 "pubkey does not match TAL pubkey", fn); 1037 goto badcert; 1038 } 1039 1040 if ((notBefore = X509_get_notBefore(p->x509)) == NULL) { 1041 warnx("%s: certificate has invalid notBefore", fn); 1042 goto badcert; 1043 } 1044 if ((notAfter = X509_get_notAfter(p->x509)) == NULL) { 1045 warnx("%s: certificate has invalid notAfter", fn); 1046 goto badcert; 1047 } 1048 if (X509_cmp_time(notBefore, &now) != -1) { 1049 warnx("%s: certificate not yet valid", fn); 1050 goto badcert; 1051 } 1052 if (X509_cmp_time(notAfter, &now) != 1) { 1053 warnx("%s: certificate has expired", fn); 1054 goto badcert; 1055 } 1056 if (p->aki != NULL && strcmp(p->aki, p->ski)) { 1057 warnx("%s: RFC 6487 section 8.4.2: " 1058 "trust anchor AKI, if specified, must match SKI", fn); 1059 goto badcert; 1060 } 1061 if (p->aia != NULL) { 1062 warnx("%s: RFC 6487 section 8.4.7: " 1063 "trust anchor must not have AIA", fn); 1064 goto badcert; 1065 } 1066 if (p->crl != NULL) { 1067 warnx("%s: RFC 6487 section 8.4.2: " 1068 "trust anchor may not specify CRL resource", fn); 1069 goto badcert; 1070 } 1071 if (p->purpose == CERT_PURPOSE_BGPSEC_ROUTER) { 1072 warnx("%s: BGPsec cert cannot be a trust anchor", fn); 1073 goto badcert; 1074 } 1075 if (x509_any_inherits(p->x509)) { 1076 warnx("%s: Trust anchor IP/AS resources may not inherit", fn); 1077 goto badcert; 1078 } 1079 1080 EVP_PKEY_free(pk); 1081 return p; 1082 1083 badcert: 1084 EVP_PKEY_free(pk); 1085 cert_free(p); 1086 return NULL; 1087 } 1088 1089 /* 1090 * Free parsed certificate contents. 1091 * Passing NULL is a noop. 1092 */ 1093 void 1094 cert_free(struct cert *p) 1095 { 1096 if (p == NULL) 1097 return; 1098 1099 free(p->crl); 1100 free(p->repo); 1101 free(p->mft); 1102 free(p->notify); 1103 free(p->ips); 1104 free(p->as); 1105 free(p->aia); 1106 free(p->aki); 1107 free(p->ski); 1108 free(p->pubkey); 1109 X509_free(p->x509); 1110 free(p); 1111 } 1112 1113 /* 1114 * Write certificate parsed content into buffer. 1115 * See cert_read() for the other side of the pipe. 1116 */ 1117 void 1118 cert_buffer(struct ibuf *b, const struct cert *p) 1119 { 1120 io_simple_buffer(b, &p->notafter, sizeof(p->notafter)); 1121 io_simple_buffer(b, &p->purpose, sizeof(p->purpose)); 1122 io_simple_buffer(b, &p->talid, sizeof(p->talid)); 1123 io_simple_buffer(b, &p->repoid, sizeof(p->repoid)); 1124 io_simple_buffer(b, &p->ipsz, sizeof(p->ipsz)); 1125 io_simple_buffer(b, &p->asz, sizeof(p->asz)); 1126 1127 io_simple_buffer(b, p->ips, p->ipsz * sizeof(p->ips[0])); 1128 io_simple_buffer(b, p->as, p->asz * sizeof(p->as[0])); 1129 1130 io_str_buffer(b, p->mft); 1131 io_str_buffer(b, p->notify); 1132 io_str_buffer(b, p->repo); 1133 io_str_buffer(b, p->crl); 1134 io_str_buffer(b, p->aia); 1135 io_str_buffer(b, p->aki); 1136 io_str_buffer(b, p->ski); 1137 io_str_buffer(b, p->pubkey); 1138 } 1139 1140 /* 1141 * Allocate and read parsed certificate content from descriptor. 1142 * The pointer must be freed with cert_free(). 1143 * Always returns a valid pointer. 1144 */ 1145 struct cert * 1146 cert_read(struct ibuf *b) 1147 { 1148 struct cert *p; 1149 1150 if ((p = calloc(1, sizeof(struct cert))) == NULL) 1151 err(1, NULL); 1152 1153 io_read_buf(b, &p->notafter, sizeof(p->notafter)); 1154 io_read_buf(b, &p->purpose, sizeof(p->purpose)); 1155 io_read_buf(b, &p->talid, sizeof(p->talid)); 1156 io_read_buf(b, &p->repoid, sizeof(p->repoid)); 1157 io_read_buf(b, &p->ipsz, sizeof(p->ipsz)); 1158 io_read_buf(b, &p->asz, sizeof(p->asz)); 1159 1160 p->ips = calloc(p->ipsz, sizeof(struct cert_ip)); 1161 if (p->ips == NULL) 1162 err(1, NULL); 1163 io_read_buf(b, p->ips, p->ipsz * sizeof(p->ips[0])); 1164 1165 p->as = calloc(p->asz, sizeof(struct cert_as)); 1166 if (p->as == NULL) 1167 err(1, NULL); 1168 io_read_buf(b, p->as, p->asz * sizeof(p->as[0])); 1169 1170 io_read_str(b, &p->mft); 1171 io_read_str(b, &p->notify); 1172 io_read_str(b, &p->repo); 1173 io_read_str(b, &p->crl); 1174 io_read_str(b, &p->aia); 1175 io_read_str(b, &p->aki); 1176 io_read_str(b, &p->ski); 1177 io_read_str(b, &p->pubkey); 1178 1179 assert(p->mft != NULL || p->purpose == CERT_PURPOSE_BGPSEC_ROUTER); 1180 assert(p->ski); 1181 return p; 1182 } 1183 1184 static inline int 1185 authcmp(struct auth *a, struct auth *b) 1186 { 1187 return strcmp(a->cert->ski, b->cert->ski); 1188 } 1189 1190 RB_GENERATE_STATIC(auth_tree, auth, entry, authcmp); 1191 1192 void 1193 auth_tree_free(struct auth_tree *auths) 1194 { 1195 struct auth *auth, *tauth; 1196 1197 RB_FOREACH_SAFE(auth, auth_tree, auths, tauth) { 1198 RB_REMOVE(auth_tree, auths, auth); 1199 cert_free(auth->cert); 1200 free(auth); 1201 } 1202 } 1203 1204 struct auth * 1205 auth_find(struct auth_tree *auths, const char *aki) 1206 { 1207 struct auth a; 1208 struct cert c; 1209 1210 /* we look up the cert where the ski == aki */ 1211 c.ski = (char *)aki; 1212 a.cert = &c; 1213 1214 return RB_FIND(auth_tree, auths, &a); 1215 } 1216 1217 struct auth * 1218 auth_insert(struct auth_tree *auths, struct cert *cert, struct auth *parent) 1219 { 1220 struct auth *na; 1221 1222 na = malloc(sizeof(*na)); 1223 if (na == NULL) 1224 err(1, NULL); 1225 1226 na->parent = parent; 1227 na->cert = cert; 1228 na->any_inherits = x509_any_inherits(cert->x509); 1229 1230 if (RB_INSERT(auth_tree, auths, na) != NULL) 1231 err(1, "auth tree corrupted"); 1232 1233 return na; 1234 } 1235 1236 static void 1237 insert_brk(struct brk_tree *tree, struct cert *cert, int asid) 1238 { 1239 struct brk *b, *found; 1240 1241 if ((b = calloc(1, sizeof(*b))) == NULL) 1242 err(1, NULL); 1243 1244 b->asid = asid; 1245 b->expires = cert->notafter; 1246 b->talid = cert->talid; 1247 if ((b->ski = strdup(cert->ski)) == NULL) 1248 err(1, NULL); 1249 if ((b->pubkey = strdup(cert->pubkey)) == NULL) 1250 err(1, NULL); 1251 1252 /* 1253 * Check if a similar BRK already exists in the tree. If the found BRK 1254 * expires sooner, update it to this BRK's later expiry moment. 1255 */ 1256 if ((found = RB_INSERT(brk_tree, tree, b)) != NULL) { 1257 if (found->expires < b->expires) { 1258 found->expires = b->expires; 1259 found->talid = b->talid; 1260 } 1261 free(b->ski); 1262 free(b->pubkey); 1263 free(b); 1264 } 1265 } 1266 1267 /* 1268 * Add each BGPsec Router Key into the BRK tree. 1269 */ 1270 void 1271 cert_insert_brks(struct brk_tree *tree, struct cert *cert) 1272 { 1273 size_t i, asid; 1274 1275 for (i = 0; i < cert->asz; i++) { 1276 switch (cert->as[i].type) { 1277 case CERT_AS_ID: 1278 insert_brk(tree, cert, cert->as[i].id); 1279 break; 1280 case CERT_AS_RANGE: 1281 for (asid = cert->as[i].range.min; 1282 asid <= cert->as[i].range.max; asid++) 1283 insert_brk(tree, cert, asid); 1284 break; 1285 default: 1286 warnx("invalid AS identifier type"); 1287 continue; 1288 } 1289 } 1290 } 1291 1292 static inline int 1293 brkcmp(struct brk *a, struct brk *b) 1294 { 1295 int rv; 1296 1297 if (a->asid > b->asid) 1298 return 1; 1299 if (a->asid < b->asid) 1300 return -1; 1301 1302 rv = strcmp(a->ski, b->ski); 1303 if (rv > 0) 1304 return 1; 1305 if (rv < 0) 1306 return -1; 1307 1308 return strcmp(a->pubkey, b->pubkey); 1309 } 1310 1311 RB_GENERATE(brk_tree, brk, entry, brkcmp); 1312