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
48static void *
49xmalloc(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
65static void
66xfree(void *buf)
67{
68	if (buf != NULL) {
69		free(buf);
70	}
71}
72
73static char *
74xstrdup(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
88typedef struct {
89	char *buf;
90	size_t ptr, len;
91} string_builder;
92
93static string_builder *
94SB_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
105static void
106SB_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
125static void
126SB_append_char(string_builder *sb, int c)
127{
128	SB_expand(sb, 1);
129	sb->buf[sb->ptr ++] = c;
130}
131
132/* unused
133static void
134SB_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
146static char *
147SB_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
158static char *
159SB_contents(string_builder *sb)
160{
161	return sb->buf;
162}
163
164static size_t
165SB_length(string_builder *sb)
166{
167	return sb->ptr;
168}
169
170static void
171SB_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
180static void
181SB_reset(string_builder *sb)
182{
183	SB_set_length(sb, 0);
184}
185
186static void
187SB_free(string_builder *sb)
188{
189	xfree(sb->buf);
190	xfree(sb);
191}
192
193typedef struct ht_elt_ {
194	char *name;
195	void *value;
196	struct ht_elt_ *next;
197} ht_elt;
198
199typedef struct {
200	size_t size;
201	ht_elt **buckets;
202	size_t num_buckets;
203} HT;
204
205static HT *
206HT_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
221static uint32_t
222hash_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
241static int
242eqstring(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
264static void
265HT_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
296static void *
297HT_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
340static void *
341HT_remove(HT *ht, const char *name)
342{
343	return HT_put(ht, name, NULL);
344}
345*/
346
347static void *
348HT_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
364static void
365HT_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
386static void
387HT_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
395static size_t
396HT_size(HT *ht)
397{
398	return ht->size;
399}
400*/
401
402static unsigned char *
403read_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
437static unsigned char *
438read_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
467static int
468parse_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
487static int
488parse_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
501static int
502month_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 */
523static int
524string_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
603static FILE *conf;
604static int conf_delayed_char;
605static long conf_linenum;
606static string_builder *line_builder;
607static long current_linenum;
608
609static void
610conf_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
622static void
623conf_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 */
642static int
643conf_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
672static int
673is_ws(int x)
674{
675	return x <= 32;
676}
677
678static int
679is_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 */
693static int
694conf_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 */
789static char *
790parse_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 */
828static int
829parse_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 */
874static HT *keys;
875
876/*
877 * Trust anchors, indexed by name. Elements are pointers to
878 * test_trust_anchor structures.
879 */
880static HT *trust_anchors;
881
882typedef 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 */
893typedef 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
905static test_case *all_chains;
906static size_t all_chains_ptr, all_chains_len;
907
908static void
909free_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
930static void
931free_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
941static void
942free_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
959static char *
960get_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
974static unsigned char *
975parse_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
1030static char **
1031split_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
1075static int
1076string_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
1113static int
1114string_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
1145static void
1146parse_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
1322static void
1323process_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
1374static 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
1387typedef struct {
1388	unsigned char *data;
1389	size_t len;
1390} blob;
1391
1392static int
1393eqbigint(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
1407static int
1408eqpkey(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
1438static size_t max_dp_usage;
1439static size_t max_rp_usage;
1440
1441static int
1442check_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
1456static void
1457run_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 */
1686typedef struct {
1687	int num;
1688	int status;
1689	const char *expected;
1690} name_element_test;
1691
1692static 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
1823static void
1824free_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
1835static void
1836test_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
2020int
2021main(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}
2095