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