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