Added generic API for date range validation (with callbacks).
[BearSSL] / test / test_x509.c
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 }