xref: /freebsd/contrib/bearssl/test/test_x509.c (revision 0a36787e4c1fa0cf77dcf83be0867178476e372b)
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 void
1442 run_test_case(test_case *tc)
1443 {
1444 	br_x509_minimal_context ctx;
1445 	br_x509_trust_anchor *anchors;
1446 	size_t num_anchors;
1447 	size_t u;
1448 	const br_hash_class *dnhash;
1449 	size_t num_certs;
1450 	blob *certs;
1451 	br_x509_pkey *ee_pkey_ref;
1452 	const br_x509_pkey *ee_pkey;
1453 	unsigned usages;
1454 	unsigned status;
1455 
1456 	printf("%s: ", tc->name);
1457 	fflush(stdout);
1458 
1459 	/*
1460 	 * Get the hash function to use for hashing DN. We can use just
1461 	 * any supported hash function, but for the elegance of things,
1462 	 * we will use one of the hash function implementations
1463 	 * supported for this test case (with SHA-1 as fallback).
1464 	 */
1465 	dnhash = &br_sha1_vtable;
1466 	for (u = 0; hash_impls[u].id; u ++) {
1467 		if ((tc->hashes & ((unsigned)1 << (hash_impls[u].id))) != 0) {
1468 			dnhash = hash_impls[u].impl;
1469 		}
1470 	}
1471 
1472 	/*
1473 	 * Get trust anchors.
1474 	 */
1475 	for (num_anchors = 0; tc->ta_names[num_anchors]; num_anchors ++);
1476 	anchors = xmalloc(num_anchors * sizeof *anchors);
1477 	for (u = 0; tc->ta_names[u]; u ++) {
1478 		test_trust_anchor *tta;
1479 		br_x509_pkey *tak;
1480 
1481 		tta = HT_get(trust_anchors, tc->ta_names[u]);
1482 		if (tta == NULL) {
1483 			fprintf(stderr, "no such trust anchor: '%s'\n",
1484 				tc->ta_names[u]);
1485 			exit(EXIT_FAILURE);
1486 		}
1487 		tak = HT_get(keys, tta->key_name);
1488 		if (tak == NULL) {
1489 			fprintf(stderr, "no such public key: '%s'\n",
1490 				tta->key_name);
1491 			exit(EXIT_FAILURE);
1492 		}
1493 		anchors[u].dn.data = tta->dn;
1494 		anchors[u].dn.len = tta->dn_len;
1495 		anchors[u].flags = tta->flags;
1496 		anchors[u].pkey = *tak;
1497 	}
1498 
1499 	/*
1500 	 * Read all relevant certificates.
1501 	 */
1502 	for (num_certs = 0; tc->cert_names[num_certs]; num_certs ++);
1503 	certs = xmalloc(num_certs * sizeof *certs);
1504 	for (u = 0; u < num_certs; u ++) {
1505 		certs[u].data = read_file(tc->cert_names[u], &certs[u].len);
1506 	}
1507 
1508 	/*
1509 	 * Get expected EE public key (if any).
1510 	 */
1511 	if (tc->ee_key_name == NULL) {
1512 		ee_pkey_ref = NULL;
1513 	} else {
1514 		ee_pkey_ref = HT_get(keys, tc->ee_key_name);
1515 		if (ee_pkey_ref == NULL) {
1516 			fprintf(stderr, "no such public key: '%s'\n",
1517 				tc->ee_key_name);
1518 			exit(EXIT_FAILURE);
1519 		}
1520 	}
1521 
1522 	/*
1523 	 * Initialise the engine.
1524 	 */
1525 	br_x509_minimal_init(&ctx, dnhash, anchors, num_anchors);
1526 	for (u = 0; hash_impls[u].id; u ++) {
1527 		int id;
1528 
1529 		id = hash_impls[u].id;
1530 		if ((tc->hashes & ((unsigned)1 << id)) != 0) {
1531 			br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl);
1532 		}
1533 	}
1534 	br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default());
1535 	br_x509_minimal_set_ecdsa(&ctx,
1536 		br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
1537 
1538 	/*
1539 	 * Set the validation date.
1540 	 */
1541 	br_x509_minimal_set_time(&ctx, tc->days, tc->seconds);
1542 
1543 	/*
1544 	 * Put "canaries" to detect actual stack usage.
1545 	 */
1546 	for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t); u ++) {
1547 		ctx.dp_stack[u] = 0xA7C083FE;
1548 	}
1549 	for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t); u ++) {
1550 		ctx.rp_stack[u] = 0xA7C083FE;
1551 	}
1552 
1553 	/*
1554 	 * Run the engine. We inject certificates by chunks of 100 bytes
1555 	 * in order to exercise the coroutine API.
1556 	 */
1557 	ctx.vtable->start_chain(&ctx.vtable, tc->servername);
1558 	for (u = 0; u < num_certs; u ++) {
1559 		size_t v;
1560 
1561 		ctx.vtable->start_cert(&ctx.vtable, certs[u].len);
1562 		v = 0;
1563 		while (v < certs[u].len) {
1564 			size_t w;
1565 
1566 			w = certs[u].len - v;
1567 			if (w > 100) {
1568 				w = 100;
1569 			}
1570 			ctx.vtable->append(&ctx.vtable, certs[u].data + v, w);
1571 			v += w;
1572 		}
1573 		ctx.vtable->end_cert(&ctx.vtable);
1574 	}
1575 	status = ctx.vtable->end_chain(&ctx.vtable);
1576 	ee_pkey = ctx.vtable->get_pkey(&ctx.vtable, &usages);
1577 
1578 	/*
1579 	 * Check key type and usage.
1580 	 */
1581 	if (ee_pkey != NULL) {
1582 		unsigned ktu;
1583 
1584 		ktu = ee_pkey->key_type | usages;
1585 		if (tc->key_type_usage != (ktu & tc->key_type_usage)) {
1586 			fprintf(stderr, "wrong key type + usage"
1587 				" (expected 0x%02X, got 0x%02X)\n",
1588 				tc->key_type_usage, ktu);
1589 			exit(EXIT_FAILURE);
1590 		}
1591 	}
1592 
1593 	/*
1594 	 * Check results. Note that we may still get a public key if
1595 	 * the path is "not trusted" (but otherwise fine).
1596 	 */
1597 	if (status != tc->status) {
1598 		fprintf(stderr, "wrong status (got %d, expected %d)\n",
1599 			status, tc->status);
1600 		exit(EXIT_FAILURE);
1601 	}
1602 	if (status == BR_ERR_X509_NOT_TRUSTED) {
1603 		ee_pkey = NULL;
1604 	}
1605 	if (!eqpkey(ee_pkey, ee_pkey_ref)) {
1606 		fprintf(stderr, "wrong EE public key\n");
1607 		exit(EXIT_FAILURE);
1608 	}
1609 
1610 	/*
1611 	 * Check stack usage.
1612 	 */
1613 	for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t); u > 0; u --) {
1614 		if (ctx.dp_stack[u - 1] != 0xA7C083FE) {
1615 			if (max_dp_usage < u) {
1616 				max_dp_usage = u;
1617 			}
1618 			break;
1619 		}
1620 	}
1621 	for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t); u > 0; u --) {
1622 		if (ctx.rp_stack[u - 1] != 0xA7C083FE) {
1623 			if (max_rp_usage < u) {
1624 				max_rp_usage = u;
1625 			}
1626 			break;
1627 		}
1628 	}
1629 
1630 	/*
1631 	 * Release everything.
1632 	 */
1633 	for (u = 0; u < num_certs; u ++) {
1634 		xfree(certs[u].data);
1635 	}
1636 	xfree(certs);
1637 	xfree(anchors);
1638 	printf("OK\n");
1639 }
1640 
1641 /*
1642  * A custom structure for tests, synchronised with the test certificate
1643  * names.crt.
1644  *
1645  * If num is 1 or more, then this is a DN element with OID '1.1.1.1.num'.
1646  * If num is -1 or less, then this is a SAN element of type -num.
1647  * If num is 0, then this is a SAN element of type OtherName with
1648  * OID 1.3.6.1.4.1.311.20.2.3 (Microsoft UPN).
1649  */
1650 typedef struct {
1651 	int num;
1652 	int status;
1653 	const char *expected;
1654 } name_element_test;
1655 
1656 static name_element_test names_ref[] = {
1657 	/* === DN tests === */
1658 	{
1659 		/* [12] 66:6f:6f */
1660 		1, 1, "foo"
1661 	},
1662 	{
1663 		/* [12] 62:61:72 */
1664 		1, 1, "bar"
1665 	},
1666 	{
1667 		/* [18] 31:32:33:34 */
1668 		2, 1, "1234"
1669 	},
1670 	{
1671 		/* [19] 66:6f:6f */
1672 		3, 1, "foo"
1673 	},
1674 	{
1675 		/* [20] 66:6f:6f */
1676 		4, 1, "foo"
1677 	},
1678 	{
1679 		/* [22] 66:6f:6f */
1680 		5, 1, "foo"
1681 	},
1682 	{
1683 		/* [30] 00:66:00:6f:00:6f */
1684 		6, 1, "foo"
1685 	},
1686 	{
1687 		/* [30] fe:ff:00:66:00:6f:00:6f */
1688 		7, 1, "foo"
1689 	},
1690 	{
1691 		/* [30] ff:fe:66:00:6f:00:6f:00 */
1692 		8, 1, "foo"
1693 	},
1694 	{
1695 		/* [20] 63:61:66:e9 */
1696 		9, 1, "caf\xC3\xA9"
1697 	},
1698 	{
1699 		/* [12] 63:61:66:c3:a9 */
1700 		10, 1, "caf\xC3\xA9"
1701 	},
1702 	{
1703 		/* [12] 63:61:66:e0:83:a9 */
1704 		11, -1, NULL
1705 	},
1706 	{
1707 		/* [12] 63:61:66:e3:90:8c */
1708 		12, 1, "caf\xE3\x90\x8C"
1709 	},
1710 	{
1711 		/* [30] 00:63:00:61:00:66:34:0c */
1712 		13, 1, "caf\xE3\x90\x8C"
1713 	},
1714 	{
1715 		/* [12] 63:61:66:c3 */
1716 		14, -1, NULL
1717 	},
1718 	{
1719 		/* [30] d8:42:df:f4:00:67:00:6f */
1720 		15, 1, "\xF0\xA0\xAF\xB4go"
1721 	},
1722 	{
1723 		/* [30] 00:66:d8:42 */
1724 		16, -1, NULL
1725 	},
1726 	{
1727 		/* [30] d8:42:00:66 */
1728 		17, -1, NULL
1729 	},
1730 	{
1731 		/* [30] df:f4:00:66 */
1732 		18, -1, NULL
1733 	},
1734 	{
1735 		/* [12] 66:00:6f */
1736 		19, -1, NULL
1737 	},
1738 	{
1739 		/* [30] 00:00:34:0c */
1740 		20, -1, NULL
1741 	},
1742 	{
1743 		/* [30] 34:0c:00:00:00:66 */
1744 		21, -1, NULL
1745 	},
1746 	{
1747 		/* [12] ef:bb:bf:66:6f:6f */
1748 		22, 1, "foo"
1749 	},
1750 	{
1751 		/* [30] 00:66:ff:fe:00:6f */
1752 		23, -1, NULL
1753 	},
1754 	{
1755 		/* [30] 00:66:ff:fd:00:6f */
1756 		24, 1, "f\xEF\xBF\xBDo"
1757 	},
1758 
1759 	/* === Value not found in the DN === */
1760 	{
1761 		127, 0, NULL
1762 	},
1763 
1764 	/* === SAN tests === */
1765 	{
1766 		/* SAN OtherName (Microsoft UPN) */
1767 		0, 1, "foo@bar.com"
1768 	},
1769 	{
1770 		/* SAN rfc822Name */
1771 		-1, 1, "bar@foo.com"
1772 	},
1773 	{
1774 		/* SAN dNSName */
1775 		-2, 1, "example.com"
1776 	},
1777 	{
1778 		/* SAN dNSName */
1779 		-2, 1, "www.example.com"
1780 	},
1781 	{
1782 		/* uniformResourceIdentifier */
1783 		-6, 1, "http://www.example.com/"
1784 	}
1785 };
1786 
1787 static void
1788 free_name_elements(br_name_element *elts, size_t num)
1789 {
1790 	size_t u;
1791 
1792 	for (u = 0; u < num; u ++) {
1793 		xfree((void *)elts[u].oid);
1794 		xfree(elts[u].buf);
1795 	}
1796 	xfree(elts);
1797 }
1798 
1799 static void
1800 test_name_extraction(void)
1801 {
1802 	unsigned char *data;
1803 	size_t len;
1804 	br_x509_minimal_context ctx;
1805 	uint32_t days, seconds;
1806 	size_t u;
1807 	unsigned status;
1808 	br_name_element *names;
1809 	size_t num_names;
1810 	int good;
1811 
1812 	printf("Name extraction: ");
1813 	fflush(stdout);
1814 	data = read_file("names.crt", &len);
1815 	br_x509_minimal_init(&ctx, &br_sha256_vtable, NULL, 0);
1816 	for (u = 0; hash_impls[u].id; u ++) {
1817 		int id;
1818 
1819 		id = hash_impls[u].id;
1820 		br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl);
1821 	}
1822 	br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default());
1823 	br_x509_minimal_set_ecdsa(&ctx,
1824 		br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
1825 	string_to_time(DEFAULT_TIME, &days, &seconds);
1826 	br_x509_minimal_set_time(&ctx, days, seconds);
1827 
1828 	num_names = (sizeof names_ref) / (sizeof names_ref[0]);
1829 	names = xmalloc(num_names * sizeof *names);
1830 	for (u = 0; u < num_names; u ++) {
1831 		int num;
1832 		unsigned char *oid;
1833 
1834 		num = names_ref[u].num;
1835 		if (num > 0) {
1836 			oid = xmalloc(5);
1837 			oid[0] = 4;
1838 			oid[1] = 0x29;
1839 			oid[2] = 0x01;
1840 			oid[3] = 0x01;
1841 			oid[4] = num;
1842 		} else if (num == 0) {
1843 			oid = xmalloc(13);
1844 			oid[0] = 0x00;
1845 			oid[1] = 0x00;
1846 			oid[2] = 0x0A;
1847 			oid[3] = 0x2B;
1848 			oid[4] = 0x06;
1849 			oid[5] = 0x01;
1850 			oid[6] = 0x04;
1851 			oid[7] = 0x01;
1852 			oid[8] = 0x82;
1853 			oid[9] = 0x37;
1854 			oid[10] = 0x14;
1855 			oid[11] = 0x02;
1856 			oid[12] = 0x03;
1857 		} else {
1858 			oid = xmalloc(2);
1859 			oid[0] = 0x00;
1860 			oid[1] = -num;
1861 		}
1862 		names[u].oid = oid;
1863 		names[u].buf = xmalloc(256);
1864 		names[u].len = 256;
1865 	}
1866 	br_x509_minimal_set_name_elements(&ctx, names, num_names);
1867 
1868 	/*
1869 	 * Put "canaries" to detect actual stack usage.
1870 	 */
1871 	for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t); u ++) {
1872 		ctx.dp_stack[u] = 0xA7C083FE;
1873 	}
1874 	for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t); u ++) {
1875 		ctx.rp_stack[u] = 0xA7C083FE;
1876 	}
1877 
1878 	/*
1879 	 * Run the engine. Since we set no trust anchor, we expect a status
1880 	 * of "not trusted".
1881 	 */
1882 	ctx.vtable->start_chain(&ctx.vtable, NULL);
1883 	ctx.vtable->start_cert(&ctx.vtable, len);
1884 	ctx.vtable->append(&ctx.vtable, data, len);
1885 	ctx.vtable->end_cert(&ctx.vtable);
1886 	status = ctx.vtable->end_chain(&ctx.vtable);
1887 	if (status != BR_ERR_X509_NOT_TRUSTED) {
1888 		fprintf(stderr, "wrong status: %u\n", status);
1889 		exit(EXIT_FAILURE);
1890 	}
1891 
1892 	/*
1893 	 * Check stack usage.
1894 	 */
1895 	for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t); u > 0; u --) {
1896 		if (ctx.dp_stack[u - 1] != 0xA7C083FE) {
1897 			if (max_dp_usage < u) {
1898 				max_dp_usage = u;
1899 			}
1900 			break;
1901 		}
1902 	}
1903 	for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t); u > 0; u --) {
1904 		if (ctx.rp_stack[u - 1] != 0xA7C083FE) {
1905 			if (max_rp_usage < u) {
1906 				max_rp_usage = u;
1907 			}
1908 			break;
1909 		}
1910 	}
1911 
1912 	good = 1;
1913 	for (u = 0; u < num_names; u ++) {
1914 		if (names[u].status != names_ref[u].status) {
1915 			printf("ERR: name %u (id=%d): status=%d, expected=%d\n",
1916 				(unsigned)u, names_ref[u].num,
1917 				names[u].status, names_ref[u].status);
1918 			if (names[u].status > 0) {
1919 				unsigned char *p;
1920 
1921 				printf("  obtained:");
1922 				p = (unsigned char *)names[u].buf;
1923 				while (*p) {
1924 					printf(" %02X", *p ++);
1925 				}
1926 				printf("\n");
1927 			}
1928 			good = 0;
1929 			continue;
1930 		}
1931 		if (names_ref[u].expected == NULL) {
1932 			if (names[u].buf[0] != 0) {
1933 				printf("ERR: name %u not zero-terminated\n",
1934 					(unsigned)u);
1935 				good = 0;
1936 				continue;
1937 			}
1938 		} else {
1939 			if (strcmp(names[u].buf, names_ref[u].expected) != 0) {
1940 				unsigned char *p;
1941 
1942 				printf("ERR: name %u (id=%d): wrong value\n",
1943 					(unsigned)u, names_ref[u].num);
1944 				printf("  expected:");
1945 				p = (unsigned char *)names_ref[u].expected;
1946 				while (*p) {
1947 					printf(" %02X", *p ++);
1948 				}
1949 				printf("\n");
1950 				printf("  obtained:");
1951 				p = (unsigned char *)names[u].buf;
1952 				while (*p) {
1953 					printf(" %02X", *p ++);
1954 				}
1955 				printf("\n");
1956 				good = 0;
1957 				continue;
1958 			}
1959 		}
1960 	}
1961 	if (!good) {
1962 		exit(EXIT_FAILURE);
1963 	}
1964 
1965 	/*
1966 	for (u = 0; u < num_names; u ++) {
1967 		printf("%u: (%d)", (unsigned)u, names[u].status);
1968 		if (names[u].status > 0) {
1969 			size_t v;
1970 
1971 			for (v = 0; names[u].buf[v]; v ++) {
1972 				printf(" %02x", names[u].buf[v]);
1973 			}
1974 		}
1975 		printf("\n");
1976 	}
1977 	*/
1978 
1979 	xfree(data);
1980 	free_name_elements(names, num_names);
1981 	printf("OK\n");
1982 }
1983 
1984 int
1985 main(int argc, const char *argv[])
1986 {
1987 	size_t u;
1988 
1989 #ifdef SRCDIRNAME
1990 	/*
1991 	 * We want to change the current directory to that of the
1992 	 * executable, so that test files are reliably located. We
1993 	 * do that only if SRCDIRNAME is defined (old Makefile would
1994 	 * not do that).
1995 	 */
1996 	if (argc >= 1) {
1997 		const char *arg, *c;
1998 
1999 		arg = argv[0];
2000 		for (c = arg + strlen(arg);; c --) {
2001 			int sep, r;
2002 
2003 #ifdef _WIN32
2004 			sep = (*c == '/') || (*c == '\\');
2005 #else
2006 			sep = (*c == '/');
2007 #endif
2008 			if (sep) {
2009 				size_t len;
2010 				char *dn;
2011 
2012 				len = 1 + (c - arg);
2013 				dn = xmalloc(len + 1);
2014 				memcpy(dn, arg, len);
2015 				dn[len] = 0;
2016 #ifdef _WIN32
2017 				r = _chdir(dn);
2018 #else
2019 				r = chdir(dn);
2020 #endif
2021 				if (r != 0) {
2022 					fprintf(stderr, "warning: could not"
2023 						" set directory to '%s'\n", dn);
2024 				}
2025 				xfree(dn);
2026 				break;
2027 			}
2028 			if (c == arg) {
2029 				break;
2030 			}
2031 		}
2032 	}
2033 #else
2034 	(void)argc;
2035 	(void)argv;
2036 #endif
2037 
2038 	process_conf_file(CONFFILE);
2039 
2040 	max_dp_usage = 0;
2041 	max_rp_usage = 0;
2042 	for (u = 0; u < all_chains_ptr; u ++) {
2043 		run_test_case(&all_chains[u]);
2044 	}
2045 	test_name_extraction();
2046 
2047 	printf("Maximum data stack usage:    %u\n", (unsigned)max_dp_usage);
2048 	printf("Maximum return stack usage:  %u\n", (unsigned)max_rp_usage);
2049 
2050 	HT_free(keys, free_key);
2051 	HT_free(trust_anchors, free_trust_anchor);
2052 	for (u = 0; u < all_chains_ptr; u ++) {
2053 		free_test_case_contents(&all_chains[u]);
2054 	}
2055 	xfree(all_chains);
2056 
2057 	return 0;
2058 }
2059