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