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