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