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