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