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