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