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