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