1 /* 2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <stdint.h> 29 30 #ifdef _WIN32 31 #include <windows.h> 32 #else 33 #include <unistd.h> 34 #endif 35 36 #include "bearssl.h" 37 38 #define STR(x) STR_(x) 39 #define STR_(x) #x 40 #ifdef SRCDIRNAME 41 #define DIRNAME STR(SRCDIRNAME) "/test/x509" 42 #else 43 #define DIRNAME "test/x509" 44 #endif 45 #define CONFFILE DIRNAME "/alltests.txt" 46 #define DEFAULT_TIME "2016-08-30T18:00:00Z" 47 48 static void * 49 xmalloc(size_t len) 50 { 51 void *buf; 52 53 if (len == 0) { 54 return NULL; 55 } 56 buf = malloc(len); 57 if (buf == NULL) { 58 fprintf(stderr, "error: cannot allocate %lu byte(s)\n", 59 (unsigned long)len); 60 exit(EXIT_FAILURE); 61 } 62 return buf; 63 } 64 65 static void 66 xfree(void *buf) 67 { 68 if (buf != NULL) { 69 free(buf); 70 } 71 } 72 73 static char * 74 xstrdup(const char *name) 75 { 76 size_t n; 77 char *s; 78 79 if (name == NULL) { 80 return NULL; 81 } 82 n = strlen(name) + 1; 83 s = xmalloc(n); 84 memcpy(s, name, n); 85 return s; 86 } 87 88 typedef struct { 89 char *buf; 90 size_t ptr, len; 91 } string_builder; 92 93 static string_builder * 94 SB_new(void) 95 { 96 string_builder *sb; 97 98 sb = xmalloc(sizeof *sb); 99 sb->len = 8; 100 sb->buf = xmalloc(sb->len); 101 sb->ptr = 0; 102 return sb; 103 } 104 105 static void 106 SB_expand(string_builder *sb, size_t extra_len) 107 { 108 size_t nlen; 109 char *nbuf; 110 111 if (extra_len < (sb->len - sb->ptr)) { 112 return; 113 } 114 nlen = sb->len << 1; 115 if (extra_len > (nlen - sb->ptr)) { 116 nlen = sb->ptr + extra_len; 117 } 118 nbuf = xmalloc(nlen); 119 memcpy(nbuf, sb->buf, sb->ptr); 120 xfree(sb->buf); 121 sb->buf = nbuf; 122 sb->len = nlen; 123 } 124 125 static void 126 SB_append_char(string_builder *sb, int c) 127 { 128 SB_expand(sb, 1); 129 sb->buf[sb->ptr ++] = c; 130 } 131 132 /* unused 133 static void 134 SB_append_string(string_builder *sb, const char *s) 135 { 136 size_t n; 137 138 n = strlen(s); 139 SB_expand(sb, n); 140 memcpy(sb->buf + sb->ptr, s, n); 141 sb->ptr += n; 142 } 143 */ 144 145 /* unused 146 static char * 147 SB_to_string(string_builder *sb) 148 { 149 char *s; 150 151 s = xmalloc(sb->ptr + 1); 152 memcpy(s, sb->buf, sb->ptr); 153 s[sb->ptr] = 0; 154 return s; 155 } 156 */ 157 158 static char * 159 SB_contents(string_builder *sb) 160 { 161 return sb->buf; 162 } 163 164 static size_t 165 SB_length(string_builder *sb) 166 { 167 return sb->ptr; 168 } 169 170 static void 171 SB_set_length(string_builder *sb, size_t len) 172 { 173 if (sb->ptr < len) { 174 SB_expand(sb, len - sb->ptr); 175 memset(sb->buf + sb->ptr, ' ', len - sb->ptr); 176 } 177 sb->ptr = len; 178 } 179 180 static void 181 SB_reset(string_builder *sb) 182 { 183 SB_set_length(sb, 0); 184 } 185 186 static void 187 SB_free(string_builder *sb) 188 { 189 xfree(sb->buf); 190 xfree(sb); 191 } 192 193 typedef struct ht_elt_ { 194 char *name; 195 void *value; 196 struct ht_elt_ *next; 197 } ht_elt; 198 199 typedef struct { 200 size_t size; 201 ht_elt **buckets; 202 size_t num_buckets; 203 } HT; 204 205 static HT * 206 HT_new(void) 207 { 208 HT *ht; 209 size_t u; 210 211 ht = xmalloc(sizeof *ht); 212 ht->size = 0; 213 ht->num_buckets = 8; 214 ht->buckets = xmalloc(ht->num_buckets * sizeof(ht_elt *)); 215 for (u = 0; u < ht->num_buckets; u ++) { 216 ht->buckets[u] = NULL; 217 } 218 return ht; 219 } 220 221 static uint32_t 222 hash_string(const char *name) 223 { 224 uint32_t hc; 225 226 hc = 0; 227 while (*name) { 228 int x; 229 230 hc = (hc << 5) - hc; 231 x = *(const unsigned char *)name; 232 if (x >= 'A' && x <= 'Z') { 233 x += 'a' - 'A'; 234 } 235 hc += (uint32_t)x; 236 name ++; 237 } 238 return hc; 239 } 240 241 static int 242 eqstring(const char *s1, const char *s2) 243 { 244 while (*s1 && *s2) { 245 int x1, x2; 246 247 x1 = *(const unsigned char *)s1; 248 x2 = *(const unsigned char *)s2; 249 if (x1 >= 'A' && x1 <= 'Z') { 250 x1 += 'a' - 'A'; 251 } 252 if (x2 >= 'A' && x2 <= 'Z') { 253 x2 += 'a' - 'A'; 254 } 255 if (x1 != x2) { 256 return 0; 257 } 258 s1 ++; 259 s2 ++; 260 } 261 return !(*s1 || *s2); 262 } 263 264 static void 265 HT_expand(HT *ht) 266 { 267 size_t n, n2, u; 268 ht_elt **new_buckets; 269 270 n = ht->num_buckets; 271 n2 = n << 1; 272 new_buckets = xmalloc(n2 * sizeof *new_buckets); 273 for (u = 0; u < n2; u ++) { 274 new_buckets[u] = NULL; 275 } 276 for (u = 0; u < n; u ++) { 277 ht_elt *e, *f; 278 279 f = NULL; 280 for (e = ht->buckets[u]; e != NULL; e = f) { 281 uint32_t hc; 282 size_t v; 283 284 hc = hash_string(e->name); 285 v = (size_t)(hc & ((uint32_t)n2 - 1)); 286 f = e->next; 287 e->next = new_buckets[v]; 288 new_buckets[v] = e; 289 } 290 } 291 xfree(ht->buckets); 292 ht->buckets = new_buckets; 293 ht->num_buckets = n2; 294 } 295 296 static void * 297 HT_put(HT *ht, const char *name, void *value) 298 { 299 uint32_t hc; 300 size_t k; 301 ht_elt *e, **prev; 302 303 hc = hash_string(name); 304 k = (size_t)(hc & ((uint32_t)ht->num_buckets - 1)); 305 prev = &ht->buckets[k]; 306 e = *prev; 307 while (e != NULL) { 308 if (eqstring(name, e->name)) { 309 void *old_value; 310 311 old_value = e->value; 312 if (value == NULL) { 313 *prev = e->next; 314 xfree(e->name); 315 xfree(e); 316 ht->size --; 317 } else { 318 e->value = value; 319 } 320 return old_value; 321 } 322 prev = &e->next; 323 e = *prev; 324 } 325 if (value != NULL) { 326 e = xmalloc(sizeof *e); 327 e->name = xstrdup(name); 328 e->value = value; 329 e->next = ht->buckets[k]; 330 ht->buckets[k] = e; 331 ht->size ++; 332 if (ht->size > ht->num_buckets) { 333 HT_expand(ht); 334 } 335 } 336 return NULL; 337 } 338 339 /* unused 340 static void * 341 HT_remove(HT *ht, const char *name) 342 { 343 return HT_put(ht, name, NULL); 344 } 345 */ 346 347 static void * 348 HT_get(const HT *ht, const char *name) 349 { 350 uint32_t hc; 351 size_t k; 352 ht_elt *e; 353 354 hc = hash_string(name); 355 k = (size_t)(hc & ((uint32_t)ht->num_buckets - 1)); 356 for (e = ht->buckets[k]; e != NULL; e = e->next) { 357 if (eqstring(name, e->name)) { 358 return e->value; 359 } 360 } 361 return NULL; 362 } 363 364 static void 365 HT_clear(HT *ht, void (*free_value)(void *value)) 366 { 367 size_t u; 368 369 for (u = 0; u < ht->num_buckets; u ++) { 370 ht_elt *e, *f; 371 372 f = NULL; 373 for (e = ht->buckets[u]; e != NULL; e = f) { 374 f = e->next; 375 xfree(e->name); 376 if (free_value != 0) { 377 free_value(e->value); 378 } 379 xfree(e); 380 } 381 ht->buckets[u] = NULL; 382 } 383 ht->size = 0; 384 } 385 386 static void 387 HT_free(HT *ht, void (*free_value)(void *value)) 388 { 389 HT_clear(ht, free_value); 390 xfree(ht->buckets); 391 xfree(ht); 392 } 393 394 /* unused 395 static size_t 396 HT_size(HT *ht) 397 { 398 return ht->size; 399 } 400 */ 401 402 static unsigned char * 403 read_all(FILE *f, size_t *len) 404 { 405 unsigned char *buf; 406 size_t ptr, blen; 407 408 blen = 1024; 409 buf = xmalloc(blen); 410 ptr = 0; 411 for (;;) { 412 size_t rlen; 413 414 if (ptr == blen) { 415 unsigned char *buf2; 416 417 blen <<= 1; 418 buf2 = xmalloc(blen); 419 memcpy(buf2, buf, ptr); 420 xfree(buf); 421 buf = buf2; 422 } 423 rlen = fread(buf + ptr, 1, blen - ptr, f); 424 if (rlen == 0) { 425 unsigned char *buf3; 426 427 buf3 = xmalloc(ptr); 428 memcpy(buf3, buf, ptr); 429 xfree(buf); 430 *len = ptr; 431 return buf3; 432 } 433 ptr += rlen; 434 } 435 } 436 437 static unsigned char * 438 read_file(const char *name, size_t *len) 439 { 440 FILE *f; 441 unsigned char *buf; 442 443 #ifdef DIRNAME 444 char *dname; 445 446 dname = xmalloc(strlen(DIRNAME) + strlen(name) + 2); 447 sprintf(dname, "%s/%s", DIRNAME, name); 448 name = dname; 449 #endif 450 f = fopen(name, "rb"); 451 if (f == NULL) { 452 fprintf(stderr, "could not open file '%s'\n", name); 453 exit(EXIT_FAILURE); 454 } 455 buf = read_all(f, len); 456 if (ferror(f)) { 457 fprintf(stderr, "read error on file '%s'\n", name); 458 exit(EXIT_FAILURE); 459 } 460 fclose(f); 461 #ifdef DIRNAME 462 xfree(dname); 463 #endif 464 return buf; 465 } 466 467 static int 468 parse_dec(const char *s, unsigned len, int *val) 469 { 470 int acc; 471 472 acc = 0; 473 while (len -- > 0) { 474 int c; 475 476 c = *s ++; 477 if (c >= '0' && c <= '9') { 478 acc = (acc * 10) + (c - '0'); 479 } else { 480 return -1; 481 } 482 } 483 *val = acc; 484 return 0; 485 } 486 487 static int 488 parse_choice(const char *s, const char *acceptable) 489 { 490 int c; 491 492 c = *s; 493 while (*acceptable) { 494 if (c == *acceptable ++) { 495 return 0; 496 } 497 } 498 return -1; 499 } 500 501 static int 502 month_length(int year, int month) 503 { 504 static const int base_month_length[] = { 505 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 506 }; 507 508 int x; 509 510 x = base_month_length[month - 1]; 511 if (month == 2 && year % 4 == 0 512 && (year % 100 != 0 || year % 400 == 0)) 513 { 514 x ++; 515 } 516 return x; 517 } 518 519 /* 520 * Convert a time string to a days+seconds count. Returned value is 0 521 * on success, -1 on error. 522 */ 523 static int 524 string_to_time(const char *s, uint32_t *days, uint32_t *seconds) 525 { 526 int year, month, day, hour, minute, second; 527 int day_of_year, leaps, i; 528 529 if (parse_dec(s, 4, &year) < 0) { 530 return -1; 531 } 532 s += 4; 533 if (parse_choice(s ++, "-:/ ") < 0) { 534 return -1; 535 } 536 if (parse_dec(s, 2, &month) < 0) { 537 return -1; 538 } 539 s += 2; 540 if (parse_choice(s ++, "-:/ ") < 0) { 541 return -1; 542 } 543 if (parse_dec(s, 2, &day) < 0) { 544 return -1; 545 } 546 s += 2; 547 if (parse_choice(s ++, " T") < 0) { 548 return -1; 549 } 550 if (parse_dec(s, 2, &hour) < 0) { 551 return -1; 552 } 553 s += 2; 554 if (parse_choice(s ++, "-:/ ") < 0) { 555 return -1; 556 } 557 if (parse_dec(s, 2, &minute) < 0) { 558 return -1; 559 } 560 s += 2; 561 if (parse_choice(s ++, "-:/ ") < 0) { 562 return -1; 563 } 564 if (parse_dec(s, 2, &second) < 0) { 565 return -1; 566 } 567 s += 2; 568 if (*s == '.') { 569 while (*s && *s >= '0' && *s <= '9') { 570 s ++; 571 } 572 } 573 if (*s) { 574 if (*s ++ != 'Z') { 575 return -1; 576 } 577 if (*s) { 578 return -1; 579 } 580 } 581 582 if (month < 1 || month > 12) { 583 return -1; 584 } 585 day_of_year = 0; 586 for (i = 1; i < month; i ++) { 587 day_of_year += month_length(year, i); 588 } 589 if (day < 1 || day > month_length(year, month)) { 590 return -1; 591 } 592 day_of_year += (day - 1); 593 leaps = (year + 3) / 4 - (year + 99) / 100 + (year + 399) / 400; 594 595 if (hour > 23 || minute > 59 || second > 60) { 596 return -1; 597 } 598 *days = (uint32_t)year * 365 + (uint32_t)leaps + day_of_year; 599 *seconds = (uint32_t)hour * 3600 + minute * 60 + second; 600 return 0; 601 } 602 603 static FILE *conf; 604 static int conf_delayed_char; 605 static long conf_linenum; 606 static string_builder *line_builder; 607 static long current_linenum; 608 609 static void 610 conf_init(const char *fname) 611 { 612 conf = fopen(fname, "r"); 613 if (conf == NULL) { 614 fprintf(stderr, "could not open file '%s'\n", fname); 615 exit(EXIT_FAILURE); 616 } 617 conf_delayed_char = -1; 618 conf_linenum = 1; 619 line_builder = SB_new(); 620 } 621 622 static void 623 conf_close(void) 624 { 625 if (conf != NULL) { 626 if (ferror(conf)) { 627 fprintf(stderr, "read error on configuration file\n"); 628 exit(EXIT_FAILURE); 629 } 630 fclose(conf); 631 conf = NULL; 632 } 633 if (line_builder != NULL) { 634 SB_free(line_builder); 635 line_builder = NULL; 636 } 637 } 638 639 /* 640 * Get next character from the config file. 641 */ 642 static int 643 conf_next_low(void) 644 { 645 int x; 646 647 x = conf_delayed_char; 648 if (x >= 0) { 649 conf_delayed_char = -1; 650 } else { 651 x = fgetc(conf); 652 if (x == EOF) { 653 x = -1; 654 } 655 } 656 if (x == '\r') { 657 x = fgetc(conf); 658 if (x == EOF) { 659 x = -1; 660 } 661 if (x != '\n') { 662 conf_delayed_char = x; 663 x = '\n'; 664 } 665 } 666 if (x == '\n') { 667 conf_linenum ++; 668 } 669 return x; 670 } 671 672 static int 673 is_ws(int x) 674 { 675 return x <= 32; 676 } 677 678 static int 679 is_name_char(int c) 680 { 681 return (c >= 'A' && c <= 'Z') 682 || (c >= 'a' && c <= 'z') 683 || (c >= '0' && c <= '9') 684 || (c == '_' || c == '-' || c == '.'); 685 } 686 687 /* 688 * Read a complete line. This handles line continuation; empty lines and 689 * comment lines are skipped; leading and trailing whitespace is removed. 690 * Returned value is 0 (line read) or -1 (no line, EOF reached). The line 691 * contents are accumulated in the line_builder. 692 */ 693 static int 694 conf_next_line(void) 695 { 696 for (;;) { 697 int c; 698 int lcwb; 699 700 SB_reset(line_builder); 701 702 /* 703 * Get first non-whitespace character. This skips empty 704 * lines. Comment lines (first non-whitespace character 705 * is a semicolon) are also skipped. 706 */ 707 for (;;) { 708 c = conf_next_low(); 709 if (c < 0) { 710 return -1; 711 } 712 if (is_ws(c)) { 713 continue; 714 } 715 if (c == ';') { 716 for (;;) { 717 c = conf_next_low(); 718 if (c < 0) { 719 return -1; 720 } 721 if (c == '\n') { 722 break; 723 } 724 } 725 continue; 726 } 727 break; 728 } 729 730 /* 731 * Read up the remaining of the line. The line continuation 732 * sequence (final backslash) is detected and processed. 733 */ 734 current_linenum = conf_linenum; 735 lcwb = (c == '\\'); 736 SB_append_char(line_builder, c); 737 for (;;) { 738 c = conf_next_low(); 739 if (c < 0) { 740 break; 741 } 742 if (lcwb) { 743 if (c == '\n') { 744 SB_set_length(line_builder, 745 SB_length(line_builder) - 1); 746 } 747 lcwb = 0; 748 continue; 749 } 750 if (c == '\n') { 751 break; 752 } else if (c == '\\') { 753 lcwb = 1; 754 } 755 SB_append_char(line_builder, c); 756 } 757 758 /* 759 * Remove trailing whitespace (if any). 760 */ 761 for (;;) { 762 size_t u; 763 764 u = SB_length(line_builder); 765 if (u == 0 || !is_ws( 766 SB_contents(line_builder)[u - 1])) 767 { 768 break; 769 } 770 SB_set_length(line_builder, u - 1); 771 } 772 773 /* 774 * We might end up with a totally empty line (in case there 775 * was a line continuation but nothing else), in which case 776 * we must loop. 777 */ 778 if (SB_length(line_builder) > 0) { 779 return 0; 780 } 781 } 782 } 783 784 /* 785 * Test whether the current line is a section header. If yes, then the 786 * header name is extracted, and returned as a newly allocated string. 787 * Otherwise, NULL is returned. 788 */ 789 static char * 790 parse_header_name(void) 791 { 792 char *buf, *name; 793 size_t u, v, w, len; 794 795 buf = SB_contents(line_builder); 796 len = SB_length(line_builder); 797 if (len < 2 || buf[0] != '[' || buf[len - 1] != ']') { 798 return NULL; 799 } 800 u = 1; 801 v = len - 1; 802 while (u < v && is_ws(buf[u])) { 803 u ++; 804 } 805 while (u < v && is_ws(buf[v - 1])) { 806 v --; 807 } 808 if (u == v) { 809 return NULL; 810 } 811 for (w = u; w < v; w ++) { 812 if (!is_name_char(buf[w])) { 813 return NULL; 814 } 815 } 816 len = v - u; 817 name = xmalloc(len + 1); 818 memcpy(name, buf + u, len); 819 name[len] = 0; 820 return name; 821 } 822 823 /* 824 * Parse the current line as a 'name = value' pair. The pair is pushed into 825 * the provided hash table. On error (including a duplicate key name), 826 * this function returns -1; otherwise, it returns 0. 827 */ 828 static int 829 parse_keyvalue(HT *d) 830 { 831 char *buf, *name, *value; 832 size_t u, len; 833 834 buf = SB_contents(line_builder); 835 len = SB_length(line_builder); 836 for (u = 0; u < len; u ++) { 837 if (!is_name_char(buf[u])) { 838 break; 839 } 840 } 841 if (u == 0) { 842 return -1; 843 } 844 name = xmalloc(u + 1); 845 memcpy(name, buf, u); 846 name[u] = 0; 847 if (HT_get(d, name) != NULL) { 848 xfree(name); 849 return -1; 850 } 851 while (u < len && is_ws(buf[u])) { 852 u ++; 853 } 854 if (u >= len || buf[u] != '=') { 855 xfree(name); 856 return -1; 857 } 858 u ++; 859 while (u < len && is_ws(buf[u])) { 860 u ++; 861 } 862 value = xmalloc(len - u + 1); 863 memcpy(value, buf + u, len - u); 864 value[len - u] = 0; 865 HT_put(d, name, value); 866 xfree(name); 867 return 0; 868 } 869 870 /* 871 * Public keys, indexed by name. Elements are pointers to br_x509_pkey 872 * structures. 873 */ 874 static HT *keys; 875 876 /* 877 * Trust anchors, indexed by name. Elements are pointers to 878 * test_trust_anchor structures. 879 */ 880 static HT *trust_anchors; 881 882 typedef struct { 883 unsigned char *dn; 884 size_t dn_len; 885 unsigned flags; 886 char *key_name; 887 } test_trust_anchor; 888 889 /* 890 * Test case: trust anchors, certificates (file names), key type and 891 * usage, expected status and EE public key. 892 */ 893 typedef struct { 894 char *name; 895 char **ta_names; 896 char **cert_names; 897 char *servername; 898 unsigned key_type_usage; 899 unsigned status; 900 char *ee_key_name; 901 unsigned hashes; 902 uint32_t days, seconds; 903 } test_case; 904 905 static test_case *all_chains; 906 static size_t all_chains_ptr, all_chains_len; 907 908 static void 909 free_key(void *value) 910 { 911 br_x509_pkey *pk; 912 913 pk = value; 914 switch (pk->key_type) { 915 case BR_KEYTYPE_RSA: 916 xfree((void *)pk->key.rsa.n); 917 xfree((void *)pk->key.rsa.e); 918 break; 919 case BR_KEYTYPE_EC: 920 xfree((void *)pk->key.ec.q); 921 break; 922 default: 923 fprintf(stderr, "unknown key type: %d\n", pk->key_type); 924 exit(EXIT_FAILURE); 925 break; 926 } 927 xfree(pk); 928 } 929 930 static void 931 free_trust_anchor(void *value) 932 { 933 test_trust_anchor *ttc; 934 935 ttc = value; 936 xfree(ttc->dn); 937 xfree(ttc->key_name); 938 xfree(ttc); 939 } 940 941 static void 942 free_test_case_contents(test_case *tc) 943 { 944 size_t u; 945 946 xfree(tc->name); 947 for (u = 0; tc->ta_names[u]; u ++) { 948 xfree(tc->ta_names[u]); 949 } 950 xfree(tc->ta_names); 951 for (u = 0; tc->cert_names[u]; u ++) { 952 xfree(tc->cert_names[u]); 953 } 954 xfree(tc->cert_names); 955 xfree(tc->servername); 956 xfree(tc->ee_key_name); 957 } 958 959 static char * 960 get_value(char *objtype, HT *objdata, long linenum, char *name) 961 { 962 char *value; 963 964 value = HT_get(objdata, name); 965 if (value == NULL) { 966 fprintf(stderr, 967 "missing property '%s' in section '%s' (line %ld)\n", 968 name, objtype, linenum); 969 exit(EXIT_FAILURE); 970 } 971 return value; 972 } 973 974 static unsigned char * 975 parse_hex(const char *name, long linenum, const char *value, size_t *len) 976 { 977 unsigned char *buf; 978 979 buf = NULL; 980 for (;;) { 981 size_t u, ptr; 982 int acc, z; 983 984 ptr = 0; 985 acc = 0; 986 z = 0; 987 for (u = 0; value[u]; u ++) { 988 int c; 989 990 c = value[u]; 991 if (c >= '0' && c <= '9') { 992 c -= '0'; 993 } else if (c >= 'A' && c <= 'F') { 994 c -= 'A' - 10; 995 } else if (c >= 'a' && c <= 'f') { 996 c -= 'a' - 10; 997 } else if (c == ' ' || c == ':') { 998 continue; 999 } else { 1000 fprintf(stderr, "invalid hexadecimal character" 1001 " in '%s' (line %ld)\n", 1002 name, linenum); 1003 exit(EXIT_FAILURE); 1004 } 1005 if (z) { 1006 if (buf != NULL) { 1007 buf[ptr] = (acc << 4) + c; 1008 } 1009 ptr ++; 1010 } else { 1011 acc = c; 1012 } 1013 z = !z; 1014 } 1015 if (z) { 1016 fprintf(stderr, "invalid hexadecimal value (partial" 1017 " byte) in '%s' (line %ld)\n", 1018 name, linenum); 1019 exit(EXIT_FAILURE); 1020 } 1021 if (buf == NULL) { 1022 buf = xmalloc(ptr); 1023 } else { 1024 *len = ptr; 1025 return buf; 1026 } 1027 } 1028 } 1029 1030 static char ** 1031 split_names(const char *value) 1032 { 1033 char **names; 1034 size_t len; 1035 1036 names = NULL; 1037 len = strlen(value); 1038 for (;;) { 1039 size_t u, ptr; 1040 1041 ptr = 0; 1042 u = 0; 1043 while (u < len) { 1044 size_t v; 1045 1046 while (u < len && is_ws(value[u])) { 1047 u ++; 1048 } 1049 v = u; 1050 while (v < len && !is_ws(value[v])) { 1051 v ++; 1052 } 1053 if (v > u) { 1054 if (names != NULL) { 1055 char *name; 1056 1057 name = xmalloc(v - u + 1); 1058 memcpy(name, value + u, v - u); 1059 name[v - u] = 0; 1060 names[ptr] = name; 1061 } 1062 ptr ++; 1063 } 1064 u = v; 1065 } 1066 if (names == NULL) { 1067 names = xmalloc((ptr + 1) * sizeof *names); 1068 } else { 1069 names[ptr] = NULL; 1070 return names; 1071 } 1072 } 1073 } 1074 1075 static int 1076 string_to_hash(const char *name) 1077 { 1078 char tmp[20]; 1079 size_t u, v; 1080 1081 for (u = 0, v = 0; name[u]; u ++) { 1082 int c; 1083 1084 c = name[u]; 1085 if ((c >= '0' && c <= '9') 1086 || (c >= 'A' && c <= 'Z') 1087 || (c >= 'a' && c <= 'z')) 1088 { 1089 tmp[v ++] = c; 1090 if (v == sizeof tmp) { 1091 return -1; 1092 } 1093 } 1094 } 1095 tmp[v] = 0; 1096 if (eqstring(tmp, "md5")) { 1097 return br_md5_ID; 1098 } else if (eqstring(tmp, "sha1")) { 1099 return br_sha1_ID; 1100 } else if (eqstring(tmp, "sha224")) { 1101 return br_sha224_ID; 1102 } else if (eqstring(tmp, "sha256")) { 1103 return br_sha256_ID; 1104 } else if (eqstring(tmp, "sha384")) { 1105 return br_sha384_ID; 1106 } else if (eqstring(tmp, "sha512")) { 1107 return br_sha512_ID; 1108 } else { 1109 return -1; 1110 } 1111 } 1112 1113 static int 1114 string_to_curve(const char *name) 1115 { 1116 char tmp[20]; 1117 size_t u, v; 1118 1119 for (u = 0, v = 0; name[u]; u ++) { 1120 int c; 1121 1122 c = name[u]; 1123 if ((c >= '0' && c <= '9') 1124 || (c >= 'A' && c <= 'Z') 1125 || (c >= 'a' && c <= 'z')) 1126 { 1127 tmp[v ++] = c; 1128 if (v == sizeof tmp) { 1129 return -1; 1130 } 1131 } 1132 } 1133 tmp[v] = 0; 1134 if (eqstring(tmp, "p256") || eqstring(tmp, "secp256r1")) { 1135 return BR_EC_secp256r1; 1136 } else if (eqstring(tmp, "p384") || eqstring(tmp, "secp384r1")) { 1137 return BR_EC_secp384r1; 1138 } else if (eqstring(tmp, "p521") || eqstring(tmp, "secp521r1")) { 1139 return BR_EC_secp521r1; 1140 } else { 1141 return -1; 1142 } 1143 } 1144 1145 static void 1146 parse_object(char *objtype, HT *objdata, long linenum) 1147 { 1148 char *name; 1149 1150 name = get_value(objtype, objdata, linenum, "name"); 1151 if (eqstring(objtype, "key")) { 1152 char *stype; 1153 br_x509_pkey *pk; 1154 1155 stype = get_value(objtype, objdata, linenum, "type"); 1156 pk = xmalloc(sizeof *pk); 1157 if (eqstring(stype, "RSA")) { 1158 char *sn, *se; 1159 1160 sn = get_value(objtype, objdata, linenum, "n"); 1161 se = get_value(objtype, objdata, linenum, "e"); 1162 pk->key_type = BR_KEYTYPE_RSA; 1163 pk->key.rsa.n = parse_hex("modulus", linenum, 1164 sn, &pk->key.rsa.nlen); 1165 pk->key.rsa.e = parse_hex("exponent", linenum, 1166 se, &pk->key.rsa.elen); 1167 } else if (eqstring(stype, "EC")) { 1168 char *sc, *sq; 1169 int curve; 1170 1171 sc = get_value(objtype, objdata, linenum, "curve"); 1172 sq = get_value(objtype, objdata, linenum, "q"); 1173 curve = string_to_curve(sc); 1174 if (curve < 0) { 1175 fprintf(stderr, "unknown curve name: '%s'" 1176 " (line %ld)\n", sc, linenum); 1177 exit(EXIT_FAILURE); 1178 } 1179 pk->key_type = BR_KEYTYPE_EC; 1180 pk->key.ec.curve = curve; 1181 pk->key.ec.q = parse_hex("public point", linenum, 1182 sq, &pk->key.ec.qlen); 1183 } else { 1184 fprintf(stderr, "unknown key type '%s' (line %ld)\n", 1185 stype, linenum); 1186 exit(EXIT_FAILURE); 1187 } 1188 if (HT_put(keys, name, pk) != NULL) { 1189 fprintf(stderr, "duplicate key: '%s' (line %ld)\n", 1190 name, linenum); 1191 exit(EXIT_FAILURE); 1192 } 1193 } else if (eqstring(objtype, "anchor")) { 1194 char *dnfile, *kname, *tatype; 1195 test_trust_anchor *tta; 1196 1197 dnfile = get_value(objtype, objdata, linenum, "DN_file"); 1198 kname = get_value(objtype, objdata, linenum, "key"); 1199 tatype = get_value(objtype, objdata, linenum, "type"); 1200 tta = xmalloc(sizeof *tta); 1201 tta->dn = read_file(dnfile, &tta->dn_len); 1202 tta->key_name = xstrdup(kname); 1203 if (eqstring(tatype, "CA")) { 1204 tta->flags = BR_X509_TA_CA; 1205 } else if (eqstring(tatype, "EE")) { 1206 tta->flags = 0; 1207 } else { 1208 fprintf(stderr, 1209 "unknown trust anchor type: '%s' (line %ld)\n", 1210 tatype, linenum); 1211 } 1212 if (HT_put(trust_anchors, name, tta) != NULL) { 1213 fprintf(stderr, 1214 "duplicate trust anchor: '%s' (line %ld)\n", 1215 name, linenum); 1216 exit(EXIT_FAILURE); 1217 } 1218 } else if (eqstring(objtype, "chain")) { 1219 test_case tc; 1220 char *ktype, *kusage, *sstatus, *shashes, *stime; 1221 1222 ktype = get_value(objtype, objdata, linenum, "keytype"); 1223 kusage = get_value(objtype, objdata, linenum, "keyusage"); 1224 sstatus = get_value(objtype, objdata, linenum, "status"); 1225 tc.name = xstrdup(name); 1226 tc.ta_names = split_names( 1227 get_value(objtype, objdata, linenum, "anchors")); 1228 tc.cert_names = split_names( 1229 get_value(objtype, objdata, linenum, "chain")); 1230 tc.servername = xstrdup(HT_get(objdata, "servername")); 1231 if (eqstring(ktype, "RSA")) { 1232 tc.key_type_usage = BR_KEYTYPE_RSA; 1233 } else if (eqstring(ktype, "EC")) { 1234 tc.key_type_usage = BR_KEYTYPE_EC; 1235 } else { 1236 fprintf(stderr, 1237 "unknown key type: '%s' (line %ld)\n", 1238 ktype, linenum); 1239 exit(EXIT_FAILURE); 1240 } 1241 if (eqstring(kusage, "KEYX")) { 1242 tc.key_type_usage |= BR_KEYTYPE_KEYX; 1243 } else if (eqstring(kusage, "SIGN")) { 1244 tc.key_type_usage |= BR_KEYTYPE_SIGN; 1245 } else { 1246 fprintf(stderr, 1247 "unknown key usage: '%s' (line %ld)\n", 1248 kusage, linenum); 1249 exit(EXIT_FAILURE); 1250 } 1251 tc.status = (unsigned)atoi(sstatus); 1252 if (tc.status == 0) { 1253 tc.ee_key_name = xstrdup( 1254 get_value(objtype, objdata, linenum, "eekey")); 1255 } else { 1256 tc.ee_key_name = NULL; 1257 } 1258 shashes = HT_get(objdata, "hashes"); 1259 if (shashes == NULL) { 1260 tc.hashes = (unsigned)-1; 1261 } else { 1262 char **hns; 1263 size_t u; 1264 1265 tc.hashes = 0; 1266 hns = split_names(shashes); 1267 for (u = 0;; u ++) { 1268 char *hn; 1269 int id; 1270 1271 hn = hns[u]; 1272 if (hn == NULL) { 1273 break; 1274 } 1275 id = string_to_hash(hn); 1276 if (id < 0) { 1277 fprintf(stderr, 1278 "unknown hash function '%s'" 1279 " (line %ld)\n", hn, linenum); 1280 exit(EXIT_FAILURE); 1281 } 1282 tc.hashes |= (unsigned)1 << id; 1283 xfree(hn); 1284 } 1285 xfree(hns); 1286 } 1287 stime = HT_get(objdata, "time"); 1288 if (stime == NULL) { 1289 stime = DEFAULT_TIME; 1290 } 1291 if (string_to_time(stime, &tc.days, &tc.seconds) < 0) { 1292 fprintf(stderr, "invalid time string '%s' (line %ld)\n", 1293 stime, linenum); 1294 exit(EXIT_FAILURE); 1295 } 1296 if (all_chains_ptr == all_chains_len) { 1297 if (all_chains_len == 0) { 1298 all_chains_len = 8; 1299 all_chains = xmalloc( 1300 all_chains_len * sizeof *all_chains); 1301 } else { 1302 test_case *ntc; 1303 size_t nlen; 1304 1305 nlen = all_chains_len << 1; 1306 ntc = xmalloc(nlen * sizeof *ntc); 1307 memcpy(ntc, all_chains, 1308 all_chains_len * sizeof *all_chains); 1309 xfree(all_chains); 1310 all_chains = ntc; 1311 all_chains_len = nlen; 1312 } 1313 } 1314 all_chains[all_chains_ptr ++] = tc; 1315 } else { 1316 fprintf(stderr, "unknown section type '%s' (line %ld)\n", 1317 objtype, linenum); 1318 exit(EXIT_FAILURE); 1319 } 1320 } 1321 1322 static void 1323 process_conf_file(const char *fname) 1324 { 1325 char *objtype; 1326 HT *objdata; 1327 long objlinenum; 1328 1329 keys = HT_new(); 1330 trust_anchors = HT_new(); 1331 all_chains = NULL; 1332 all_chains_ptr = 0; 1333 all_chains_len = 0; 1334 conf_init(fname); 1335 objtype = NULL; 1336 objdata = HT_new(); 1337 objlinenum = 0; 1338 for (;;) { 1339 char *hname; 1340 1341 if (conf_next_line() < 0) { 1342 break; 1343 } 1344 hname = parse_header_name(); 1345 if (hname != NULL) { 1346 if (objtype != NULL) { 1347 parse_object(objtype, objdata, objlinenum); 1348 HT_clear(objdata, xfree); 1349 xfree(objtype); 1350 } 1351 objtype = hname; 1352 objlinenum = current_linenum; 1353 continue; 1354 } 1355 if (objtype == NULL) { 1356 fprintf(stderr, "no current section (line %ld)\n", 1357 current_linenum); 1358 exit(EXIT_FAILURE); 1359 } 1360 if (parse_keyvalue(objdata) < 0) { 1361 fprintf(stderr, "wrong configuration, line %ld\n", 1362 current_linenum); 1363 exit(EXIT_FAILURE); 1364 } 1365 } 1366 if (objtype != NULL) { 1367 parse_object(objtype, objdata, objlinenum); 1368 xfree(objtype); 1369 } 1370 HT_free(objdata, xfree); 1371 conf_close(); 1372 } 1373 1374 static const struct { 1375 int id; 1376 const br_hash_class *impl; 1377 } hash_impls[] = { 1378 { br_md5_ID, &br_md5_vtable }, 1379 { br_sha1_ID, &br_sha1_vtable }, 1380 { br_sha224_ID, &br_sha224_vtable }, 1381 { br_sha256_ID, &br_sha256_vtable }, 1382 { br_sha384_ID, &br_sha384_vtable }, 1383 { br_sha512_ID, &br_sha512_vtable }, 1384 { 0, NULL } 1385 }; 1386 1387 typedef struct { 1388 unsigned char *data; 1389 size_t len; 1390 } blob; 1391 1392 static int 1393 eqbigint(const unsigned char *b1, size_t b1_len, 1394 const unsigned char *b2, size_t b2_len) 1395 { 1396 while (b1_len > 0 && *b1 == 0) { 1397 b1 ++; 1398 b1_len --; 1399 } 1400 while (b2_len > 0 && *b2 == 0) { 1401 b2 ++; 1402 b2_len --; 1403 } 1404 return b1_len == b2_len && memcmp(b1, b2, b1_len) == 0; 1405 } 1406 1407 static int 1408 eqpkey(const br_x509_pkey *pk1, const br_x509_pkey *pk2) 1409 { 1410 if (pk1 == pk2) { 1411 return 1; 1412 } 1413 if (pk1 == NULL || pk2 == NULL) { 1414 return 0; 1415 } 1416 if (pk1->key_type != pk2->key_type) { 1417 return 0; 1418 } 1419 switch (pk1->key_type) { 1420 case BR_KEYTYPE_RSA: 1421 return eqbigint(pk1->key.rsa.n, pk1->key.rsa.nlen, 1422 pk2->key.rsa.n, pk2->key.rsa.nlen) 1423 && eqbigint(pk1->key.rsa.e, pk1->key.rsa.elen, 1424 pk2->key.rsa.e, pk2->key.rsa.elen); 1425 case BR_KEYTYPE_EC: 1426 return pk1->key.ec.curve == pk2->key.ec.curve 1427 && pk1->key.ec.qlen == pk2->key.ec.qlen 1428 && memcmp(pk1->key.ec.q, 1429 pk2->key.ec.q, pk1->key.ec.qlen) == 0; 1430 default: 1431 fprintf(stderr, "unknown key type: %d\n", pk1->key_type); 1432 exit(EXIT_FAILURE); 1433 break; 1434 } 1435 return 0; 1436 } 1437 1438 static size_t max_dp_usage; 1439 static size_t max_rp_usage; 1440 1441 static int 1442 check_time(void *ctx, uint32_t nbd, uint32_t nbs, uint32_t nad, uint32_t nas) 1443 { 1444 test_case *tc; 1445 1446 tc = ctx; 1447 if (tc->days < nbd || (tc->days == nbd && tc->seconds < nbs)) { 1448 return -1; 1449 } 1450 if (tc->days > nad || (tc->days == nad && tc->seconds > nas)) { 1451 return 1; 1452 } 1453 return 0; 1454 } 1455 1456 static void 1457 run_test_case(test_case *tc) 1458 { 1459 br_x509_minimal_context ctx; 1460 br_x509_trust_anchor *anchors; 1461 size_t num_anchors; 1462 size_t u; 1463 const br_hash_class *dnhash; 1464 size_t num_certs; 1465 blob *certs; 1466 br_x509_pkey *ee_pkey_ref; 1467 const br_x509_pkey *ee_pkey; 1468 unsigned usages; 1469 unsigned status; 1470 int j; 1471 1472 printf("%s: ", tc->name); 1473 fflush(stdout); 1474 1475 /* 1476 * Get the hash function to use for hashing DN. We can use just 1477 * any supported hash function, but for the elegance of things, 1478 * we will use one of the hash function implementations 1479 * supported for this test case (with SHA-1 as fallback). 1480 */ 1481 dnhash = &br_sha1_vtable; 1482 for (u = 0; hash_impls[u].id; u ++) { 1483 if ((tc->hashes & ((unsigned)1 << (hash_impls[u].id))) != 0) { 1484 dnhash = hash_impls[u].impl; 1485 } 1486 } 1487 1488 /* 1489 * Get trust anchors. 1490 */ 1491 for (num_anchors = 0; tc->ta_names[num_anchors]; num_anchors ++); 1492 anchors = xmalloc(num_anchors * sizeof *anchors); 1493 for (u = 0; tc->ta_names[u]; u ++) { 1494 test_trust_anchor *tta; 1495 br_x509_pkey *tak; 1496 1497 tta = HT_get(trust_anchors, tc->ta_names[u]); 1498 if (tta == NULL) { 1499 fprintf(stderr, "no such trust anchor: '%s'\n", 1500 tc->ta_names[u]); 1501 exit(EXIT_FAILURE); 1502 } 1503 tak = HT_get(keys, tta->key_name); 1504 if (tak == NULL) { 1505 fprintf(stderr, "no such public key: '%s'\n", 1506 tta->key_name); 1507 exit(EXIT_FAILURE); 1508 } 1509 anchors[u].dn.data = tta->dn; 1510 anchors[u].dn.len = tta->dn_len; 1511 anchors[u].flags = tta->flags; 1512 anchors[u].pkey = *tak; 1513 } 1514 1515 /* 1516 * Read all relevant certificates. 1517 */ 1518 for (num_certs = 0; tc->cert_names[num_certs]; num_certs ++); 1519 certs = xmalloc(num_certs * sizeof *certs); 1520 for (u = 0; u < num_certs; u ++) { 1521 certs[u].data = read_file(tc->cert_names[u], &certs[u].len); 1522 } 1523 1524 /* 1525 * Get expected EE public key (if any). 1526 */ 1527 if (tc->ee_key_name == NULL) { 1528 ee_pkey_ref = NULL; 1529 } else { 1530 ee_pkey_ref = HT_get(keys, tc->ee_key_name); 1531 if (ee_pkey_ref == NULL) { 1532 fprintf(stderr, "no such public key: '%s'\n", 1533 tc->ee_key_name); 1534 exit(EXIT_FAILURE); 1535 } 1536 } 1537 1538 /* 1539 * We do the test twice, to exercise distinct API functions. 1540 */ 1541 for (j = 0; j < 2; j ++) { 1542 /* 1543 * Initialise the engine. 1544 */ 1545 br_x509_minimal_init(&ctx, dnhash, anchors, num_anchors); 1546 for (u = 0; hash_impls[u].id; u ++) { 1547 int id; 1548 1549 id = hash_impls[u].id; 1550 if ((tc->hashes & ((unsigned)1 << id)) != 0) { 1551 br_x509_minimal_set_hash(&ctx, 1552 id, hash_impls[u].impl); 1553 } 1554 } 1555 br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default()); 1556 br_x509_minimal_set_ecdsa(&ctx, 1557 br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default()); 1558 1559 /* 1560 * Set the validation date. 1561 */ 1562 if (j == 0) { 1563 br_x509_minimal_set_time(&ctx, tc->days, tc->seconds); 1564 } else { 1565 br_x509_minimal_set_time_callback(&ctx, 1566 tc, &check_time); 1567 } 1568 1569 /* 1570 * Put "canaries" to detect actual stack usage. 1571 */ 1572 for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t); 1573 u ++) 1574 { 1575 ctx.dp_stack[u] = 0xA7C083FE; 1576 } 1577 for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t); 1578 u ++) 1579 { 1580 ctx.rp_stack[u] = 0xA7C083FE; 1581 } 1582 1583 /* 1584 * Run the engine. We inject certificates by chunks of 100 1585 * bytes in order to exercise the coroutine API. 1586 */ 1587 ctx.vtable->start_chain(&ctx.vtable, tc->servername); 1588 for (u = 0; u < num_certs; u ++) { 1589 size_t v; 1590 1591 ctx.vtable->start_cert(&ctx.vtable, certs[u].len); 1592 v = 0; 1593 while (v < certs[u].len) { 1594 size_t w; 1595 1596 w = certs[u].len - v; 1597 if (w > 100) { 1598 w = 100; 1599 } 1600 ctx.vtable->append(&ctx.vtable, 1601 certs[u].data + v, w); 1602 v += w; 1603 } 1604 ctx.vtable->end_cert(&ctx.vtable); 1605 } 1606 status = ctx.vtable->end_chain(&ctx.vtable); 1607 ee_pkey = ctx.vtable->get_pkey(&ctx.vtable, &usages); 1608 1609 /* 1610 * Check key type and usage. 1611 */ 1612 if (ee_pkey != NULL) { 1613 unsigned ktu; 1614 1615 ktu = ee_pkey->key_type | usages; 1616 if (tc->key_type_usage != (ktu & tc->key_type_usage)) { 1617 fprintf(stderr, "wrong key type + usage" 1618 " (expected 0x%02X, got 0x%02X)\n", 1619 tc->key_type_usage, ktu); 1620 exit(EXIT_FAILURE); 1621 } 1622 } 1623 1624 /* 1625 * Check results. Note that we may still get a public key if 1626 * the path is "not trusted" (but otherwise fine). 1627 */ 1628 if (status != tc->status) { 1629 fprintf(stderr, "wrong status (got %d, expected %d)\n", 1630 status, tc->status); 1631 exit(EXIT_FAILURE); 1632 } 1633 if (status == BR_ERR_X509_NOT_TRUSTED) { 1634 ee_pkey = NULL; 1635 } 1636 if (!eqpkey(ee_pkey, ee_pkey_ref)) { 1637 fprintf(stderr, "wrong EE public key\n"); 1638 exit(EXIT_FAILURE); 1639 } 1640 1641 /* 1642 * Check stack usage. 1643 */ 1644 for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t); 1645 u > 0; u --) 1646 { 1647 if (ctx.dp_stack[u - 1] != 0xA7C083FE) { 1648 if (max_dp_usage < u) { 1649 max_dp_usage = u; 1650 } 1651 break; 1652 } 1653 } 1654 for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t); 1655 u > 0; u --) 1656 { 1657 if (ctx.rp_stack[u - 1] != 0xA7C083FE) { 1658 if (max_rp_usage < u) { 1659 max_rp_usage = u; 1660 } 1661 break; 1662 } 1663 } 1664 } 1665 1666 /* 1667 * Release everything. 1668 */ 1669 for (u = 0; u < num_certs; u ++) { 1670 xfree(certs[u].data); 1671 } 1672 xfree(certs); 1673 xfree(anchors); 1674 printf("OK\n"); 1675 } 1676 1677 /* 1678 * A custom structure for tests, synchronised with the test certificate 1679 * names.crt. 1680 * 1681 * If num is 1 or more, then this is a DN element with OID '1.1.1.1.num'. 1682 * If num is -1 or less, then this is a SAN element of type -num. 1683 * If num is 0, then this is a SAN element of type OtherName with 1684 * OID 1.3.6.1.4.1.311.20.2.3 (Microsoft UPN). 1685 */ 1686 typedef struct { 1687 int num; 1688 int status; 1689 const char *expected; 1690 } name_element_test; 1691 1692 static name_element_test names_ref[] = { 1693 /* === DN tests === */ 1694 { 1695 /* [12] 66:6f:6f */ 1696 1, 1, "foo" 1697 }, 1698 { 1699 /* [12] 62:61:72 */ 1700 1, 1, "bar" 1701 }, 1702 { 1703 /* [18] 31:32:33:34 */ 1704 2, 1, "1234" 1705 }, 1706 { 1707 /* [19] 66:6f:6f */ 1708 3, 1, "foo" 1709 }, 1710 { 1711 /* [20] 66:6f:6f */ 1712 4, 1, "foo" 1713 }, 1714 { 1715 /* [22] 66:6f:6f */ 1716 5, 1, "foo" 1717 }, 1718 { 1719 /* [30] 00:66:00:6f:00:6f */ 1720 6, 1, "foo" 1721 }, 1722 { 1723 /* [30] fe:ff:00:66:00:6f:00:6f */ 1724 7, 1, "foo" 1725 }, 1726 { 1727 /* [30] ff:fe:66:00:6f:00:6f:00 */ 1728 8, 1, "foo" 1729 }, 1730 { 1731 /* [20] 63:61:66:e9 */ 1732 9, 1, "caf\xC3\xA9" 1733 }, 1734 { 1735 /* [12] 63:61:66:c3:a9 */ 1736 10, 1, "caf\xC3\xA9" 1737 }, 1738 { 1739 /* [12] 63:61:66:e0:83:a9 */ 1740 11, -1, NULL 1741 }, 1742 { 1743 /* [12] 63:61:66:e3:90:8c */ 1744 12, 1, "caf\xE3\x90\x8C" 1745 }, 1746 { 1747 /* [30] 00:63:00:61:00:66:34:0c */ 1748 13, 1, "caf\xE3\x90\x8C" 1749 }, 1750 { 1751 /* [12] 63:61:66:c3 */ 1752 14, -1, NULL 1753 }, 1754 { 1755 /* [30] d8:42:df:f4:00:67:00:6f */ 1756 15, 1, "\xF0\xA0\xAF\xB4go" 1757 }, 1758 { 1759 /* [30] 00:66:d8:42 */ 1760 16, -1, NULL 1761 }, 1762 { 1763 /* [30] d8:42:00:66 */ 1764 17, -1, NULL 1765 }, 1766 { 1767 /* [30] df:f4:00:66 */ 1768 18, -1, NULL 1769 }, 1770 { 1771 /* [12] 66:00:6f */ 1772 19, -1, NULL 1773 }, 1774 { 1775 /* [30] 00:00:34:0c */ 1776 20, -1, NULL 1777 }, 1778 { 1779 /* [30] 34:0c:00:00:00:66 */ 1780 21, -1, NULL 1781 }, 1782 { 1783 /* [12] ef:bb:bf:66:6f:6f */ 1784 22, 1, "foo" 1785 }, 1786 { 1787 /* [30] 00:66:ff:fe:00:6f */ 1788 23, -1, NULL 1789 }, 1790 { 1791 /* [30] 00:66:ff:fd:00:6f */ 1792 24, 1, "f\xEF\xBF\xBDo" 1793 }, 1794 1795 /* === Value not found in the DN === */ 1796 { 1797 127, 0, NULL 1798 }, 1799 1800 /* === SAN tests === */ 1801 { 1802 /* SAN OtherName (Microsoft UPN) */ 1803 0, 1, "foo@bar.com" 1804 }, 1805 { 1806 /* SAN rfc822Name */ 1807 -1, 1, "bar@foo.com" 1808 }, 1809 { 1810 /* SAN dNSName */ 1811 -2, 1, "example.com" 1812 }, 1813 { 1814 /* SAN dNSName */ 1815 -2, 1, "www.example.com" 1816 }, 1817 { 1818 /* uniformResourceIdentifier */ 1819 -6, 1, "http://www.example.com/" 1820 } 1821 }; 1822 1823 static void 1824 free_name_elements(br_name_element *elts, size_t num) 1825 { 1826 size_t u; 1827 1828 for (u = 0; u < num; u ++) { 1829 xfree((void *)elts[u].oid); 1830 xfree(elts[u].buf); 1831 } 1832 xfree(elts); 1833 } 1834 1835 static void 1836 test_name_extraction(void) 1837 { 1838 unsigned char *data; 1839 size_t len; 1840 br_x509_minimal_context ctx; 1841 uint32_t days, seconds; 1842 size_t u; 1843 unsigned status; 1844 br_name_element *names; 1845 size_t num_names; 1846 int good; 1847 1848 printf("Name extraction: "); 1849 fflush(stdout); 1850 data = read_file("names.crt", &len); 1851 br_x509_minimal_init(&ctx, &br_sha256_vtable, NULL, 0); 1852 for (u = 0; hash_impls[u].id; u ++) { 1853 int id; 1854 1855 id = hash_impls[u].id; 1856 br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl); 1857 } 1858 br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default()); 1859 br_x509_minimal_set_ecdsa(&ctx, 1860 br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default()); 1861 string_to_time(DEFAULT_TIME, &days, &seconds); 1862 br_x509_minimal_set_time(&ctx, days, seconds); 1863 1864 num_names = (sizeof names_ref) / (sizeof names_ref[0]); 1865 names = xmalloc(num_names * sizeof *names); 1866 for (u = 0; u < num_names; u ++) { 1867 int num; 1868 unsigned char *oid; 1869 1870 num = names_ref[u].num; 1871 if (num > 0) { 1872 oid = xmalloc(5); 1873 oid[0] = 4; 1874 oid[1] = 0x29; 1875 oid[2] = 0x01; 1876 oid[3] = 0x01; 1877 oid[4] = num; 1878 } else if (num == 0) { 1879 oid = xmalloc(13); 1880 oid[0] = 0x00; 1881 oid[1] = 0x00; 1882 oid[2] = 0x0A; 1883 oid[3] = 0x2B; 1884 oid[4] = 0x06; 1885 oid[5] = 0x01; 1886 oid[6] = 0x04; 1887 oid[7] = 0x01; 1888 oid[8] = 0x82; 1889 oid[9] = 0x37; 1890 oid[10] = 0x14; 1891 oid[11] = 0x02; 1892 oid[12] = 0x03; 1893 } else { 1894 oid = xmalloc(2); 1895 oid[0] = 0x00; 1896 oid[1] = -num; 1897 } 1898 names[u].oid = oid; 1899 names[u].buf = xmalloc(256); 1900 names[u].len = 256; 1901 } 1902 br_x509_minimal_set_name_elements(&ctx, names, num_names); 1903 1904 /* 1905 * Put "canaries" to detect actual stack usage. 1906 */ 1907 for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t); u ++) { 1908 ctx.dp_stack[u] = 0xA7C083FE; 1909 } 1910 for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t); u ++) { 1911 ctx.rp_stack[u] = 0xA7C083FE; 1912 } 1913 1914 /* 1915 * Run the engine. Since we set no trust anchor, we expect a status 1916 * of "not trusted". 1917 */ 1918 ctx.vtable->start_chain(&ctx.vtable, NULL); 1919 ctx.vtable->start_cert(&ctx.vtable, len); 1920 ctx.vtable->append(&ctx.vtable, data, len); 1921 ctx.vtable->end_cert(&ctx.vtable); 1922 status = ctx.vtable->end_chain(&ctx.vtable); 1923 if (status != BR_ERR_X509_NOT_TRUSTED) { 1924 fprintf(stderr, "wrong status: %u\n", status); 1925 exit(EXIT_FAILURE); 1926 } 1927 1928 /* 1929 * Check stack usage. 1930 */ 1931 for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t); u > 0; u --) { 1932 if (ctx.dp_stack[u - 1] != 0xA7C083FE) { 1933 if (max_dp_usage < u) { 1934 max_dp_usage = u; 1935 } 1936 break; 1937 } 1938 } 1939 for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t); u > 0; u --) { 1940 if (ctx.rp_stack[u - 1] != 0xA7C083FE) { 1941 if (max_rp_usage < u) { 1942 max_rp_usage = u; 1943 } 1944 break; 1945 } 1946 } 1947 1948 good = 1; 1949 for (u = 0; u < num_names; u ++) { 1950 if (names[u].status != names_ref[u].status) { 1951 printf("ERR: name %u (id=%d): status=%d, expected=%d\n", 1952 (unsigned)u, names_ref[u].num, 1953 names[u].status, names_ref[u].status); 1954 if (names[u].status > 0) { 1955 unsigned char *p; 1956 1957 printf(" obtained:"); 1958 p = (unsigned char *)names[u].buf; 1959 while (*p) { 1960 printf(" %02X", *p ++); 1961 } 1962 printf("\n"); 1963 } 1964 good = 0; 1965 continue; 1966 } 1967 if (names_ref[u].expected == NULL) { 1968 if (names[u].buf[0] != 0) { 1969 printf("ERR: name %u not zero-terminated\n", 1970 (unsigned)u); 1971 good = 0; 1972 continue; 1973 } 1974 } else { 1975 if (strcmp(names[u].buf, names_ref[u].expected) != 0) { 1976 unsigned char *p; 1977 1978 printf("ERR: name %u (id=%d): wrong value\n", 1979 (unsigned)u, names_ref[u].num); 1980 printf(" expected:"); 1981 p = (unsigned char *)names_ref[u].expected; 1982 while (*p) { 1983 printf(" %02X", *p ++); 1984 } 1985 printf("\n"); 1986 printf(" obtained:"); 1987 p = (unsigned char *)names[u].buf; 1988 while (*p) { 1989 printf(" %02X", *p ++); 1990 } 1991 printf("\n"); 1992 good = 0; 1993 continue; 1994 } 1995 } 1996 } 1997 if (!good) { 1998 exit(EXIT_FAILURE); 1999 } 2000 2001 /* 2002 for (u = 0; u < num_names; u ++) { 2003 printf("%u: (%d)", (unsigned)u, names[u].status); 2004 if (names[u].status > 0) { 2005 size_t v; 2006 2007 for (v = 0; names[u].buf[v]; v ++) { 2008 printf(" %02x", names[u].buf[v]); 2009 } 2010 } 2011 printf("\n"); 2012 } 2013 */ 2014 2015 xfree(data); 2016 free_name_elements(names, num_names); 2017 printf("OK\n"); 2018 } 2019 2020 int 2021 main(int argc, const char *argv[]) 2022 { 2023 size_t u; 2024 2025 #ifdef SRCDIRNAME 2026 /* 2027 * We want to change the current directory to that of the 2028 * executable, so that test files are reliably located. We 2029 * do that only if SRCDIRNAME is defined (old Makefile would 2030 * not do that). 2031 */ 2032 if (argc >= 1) { 2033 const char *arg, *c; 2034 2035 arg = argv[0]; 2036 for (c = arg + strlen(arg);; c --) { 2037 int sep, r; 2038 2039 #ifdef _WIN32 2040 sep = (*c == '/') || (*c == '\\'); 2041 #else 2042 sep = (*c == '/'); 2043 #endif 2044 if (sep) { 2045 size_t len; 2046 char *dn; 2047 2048 len = 1 + (c - arg); 2049 dn = xmalloc(len + 1); 2050 memcpy(dn, arg, len); 2051 dn[len] = 0; 2052 #ifdef _WIN32 2053 r = _chdir(dn); 2054 #else 2055 r = chdir(dn); 2056 #endif 2057 if (r != 0) { 2058 fprintf(stderr, "warning: could not" 2059 " set directory to '%s'\n", dn); 2060 } 2061 xfree(dn); 2062 break; 2063 } 2064 if (c == arg) { 2065 break; 2066 } 2067 } 2068 } 2069 #else 2070 (void)argc; 2071 (void)argv; 2072 #endif 2073 2074 process_conf_file(CONFFILE); 2075 2076 max_dp_usage = 0; 2077 max_rp_usage = 0; 2078 for (u = 0; u < all_chains_ptr; u ++) { 2079 run_test_case(&all_chains[u]); 2080 } 2081 test_name_extraction(); 2082 2083 printf("Maximum data stack usage: %u\n", (unsigned)max_dp_usage); 2084 printf("Maximum return stack usage: %u\n", (unsigned)max_rp_usage); 2085 2086 HT_free(keys, free_key); 2087 HT_free(trust_anchors, free_trust_anchor); 2088 for (u = 0; u < all_chains_ptr; u ++) { 2089 free_test_case_contents(&all_chains[u]); 2090 } 2091 xfree(all_chains); 2092 2093 return 0; 2094 } 2095