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