2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
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:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
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
38 #define STR(x) STR_(x)
41 #define DIRNAME STR(SRCDIRNAME) "/test/x509"
43 #define DIRNAME "test/x509"
45 #define CONFFILE DIRNAME "/alltests.txt"
46 #define DEFAULT_TIME "2016-08-30T18:00:00Z"
58 fprintf(stderr, "error: cannot allocate %lu byte(s)\n",
74 xstrdup(const char *name)
93 static string_builder *
98 sb = xmalloc(sizeof *sb);
100 sb->buf = xmalloc(sb->len);
106 SB_expand(string_builder *sb, size_t extra_len)
111 if (extra_len < (sb->len - sb->ptr)) {
115 if (extra_len > (nlen - sb->ptr)) {
116 nlen = sb->ptr + extra_len;
118 nbuf = xmalloc(nlen);
119 memcpy(nbuf, sb->buf, sb->ptr);
126 SB_append_char(string_builder *sb, int c)
129 sb->buf[sb->ptr ++] = c;
134 SB_append_string(string_builder *sb, const char *s)
140 memcpy(sb->buf + sb->ptr, s, n);
147 SB_to_string(string_builder *sb)
151 s = xmalloc(sb->ptr + 1);
152 memcpy(s, sb->buf, sb->ptr);
159 SB_contents(string_builder *sb)
165 SB_length(string_builder *sb)
171 SB_set_length(string_builder *sb, size_t len)
174 SB_expand(sb, len - sb->ptr);
175 memset(sb->buf + sb->ptr, ' ', len - sb->ptr);
181 SB_reset(string_builder *sb)
183 SB_set_length(sb, 0);
187 SB_free(string_builder *sb)
193 typedef struct ht_elt_ {
196 struct ht_elt_ *next;
211 ht = xmalloc(sizeof *ht);
214 ht->buckets = xmalloc(ht->num_buckets * sizeof(ht_elt *));
215 for (u = 0; u < ht->num_buckets; u ++) {
216 ht->buckets[u] = NULL;
222 hash_string(const char *name)
231 x = *(const unsigned char *)name;
232 if (x >= 'A' && x <= 'Z') {
242 eqstring(const char *s1, const char *s2)
247 x1 = *(const unsigned char *)s1;
248 x2 = *(const unsigned char *)s2;
249 if (x1 >= 'A' && x1 <= 'Z') {
252 if (x2 >= 'A' && x2 <= 'Z') {
261 return !(*s1 || *s2);
268 ht_elt **new_buckets;
272 new_buckets = xmalloc(n2 * sizeof *new_buckets);
273 for (u = 0; u < n2; u ++) {
274 new_buckets[u] = NULL;
276 for (u = 0; u < n; u ++) {
280 for (e = ht->buckets[u]; e != NULL; e = f) {
284 hc = hash_string(e->name);
285 v = (size_t)(hc & ((uint32_t)n2 - 1));
287 e->next = new_buckets[v];
292 ht->buckets = new_buckets;
293 ht->num_buckets = n2;
297 HT_put(HT *ht, const char *name, void *value)
303 hc = hash_string(name);
304 k = (size_t)(hc & ((uint32_t)ht->num_buckets - 1));
305 prev = &ht->buckets[k];
308 if (eqstring(name, e->name)) {
311 old_value = e->value;
326 e = xmalloc(sizeof *e);
327 e->name = xstrdup(name);
329 e->next = ht->buckets[k];
332 if (ht->size > ht->num_buckets) {
341 HT_remove(HT *ht, const char *name)
343 return HT_put(ht, name, NULL);
348 HT_get(const HT *ht, const char *name)
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)) {
365 HT_clear(HT *ht, void (*free_value)(void *value))
369 for (u = 0; u < ht->num_buckets; u ++) {
373 for (e = ht->buckets[u]; e != NULL; e = f) {
376 if (free_value != 0) {
377 free_value(e->value);
381 ht->buckets[u] = NULL;
387 HT_free(HT *ht, void (*free_value)(void *value))
389 HT_clear(ht, free_value);
402 static unsigned char *
403 read_all(FILE *f, size_t *len)
418 buf2 = xmalloc(blen);
419 memcpy(buf2, buf, ptr);
423 rlen = fread(buf + ptr, 1, blen - ptr, f);
428 memcpy(buf3, buf, ptr);
437 static unsigned char *
438 read_file(const char *name, size_t *len)
446 dname = xmalloc(strlen(DIRNAME) + strlen(name) + 2);
447 sprintf(dname, "%s/%s", DIRNAME, name);
450 f = fopen(name, "rb");
452 fprintf(stderr, "could not open file '%s'\n", name);
455 buf = read_all(f, len);
457 fprintf(stderr, "read error on file '%s'\n", name);
468 parse_dec(const char *s, unsigned len, int *val)
477 if (c >= '0' && c <= '9') {
478 acc = (acc * 10) + (c - '0');
488 parse_choice(const char *s, const char *acceptable)
493 while (*acceptable) {
494 if (c == *acceptable ++) {
502 month_length(int year, int month)
504 static const int base_month_length[] = {
505 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
510 x = base_month_length[month - 1];
511 if (month == 2 && year % 4 == 0
512 && (year % 100 != 0 || year % 400 == 0))
520 * Convert a time string to a days+seconds count. Returned value is 0
521 * on success, -1 on error.
524 string_to_time(const char *s, uint32_t *days, uint32_t *seconds)
526 int year, month, day, hour, minute, second;
527 int day_of_year, leaps, i;
529 if (parse_dec(s, 4, &year) < 0) {
533 if (parse_choice(s ++, "-:/ ") < 0) {
536 if (parse_dec(s, 2, &month) < 0) {
540 if (parse_choice(s ++, "-:/ ") < 0) {
543 if (parse_dec(s, 2, &day) < 0) {
547 if (parse_choice(s ++, " T") < 0) {
550 if (parse_dec(s, 2, &hour) < 0) {
554 if (parse_choice(s ++, "-:/ ") < 0) {
557 if (parse_dec(s, 2, &minute) < 0) {
561 if (parse_choice(s ++, "-:/ ") < 0) {
564 if (parse_dec(s, 2, &second) < 0) {
569 while (*s && *s >= '0' && *s <= '9') {
582 if (month < 1 || month > 12) {
586 for (i = 1; i < month; i ++) {
587 day_of_year += month_length(year, i);
589 if (day < 1 || day > month_length(year, month)) {
592 day_of_year += (day - 1);
593 leaps = (year + 3) / 4 - (year + 99) / 100 + (year + 399) / 400;
595 if (hour > 23 || minute > 59 || second > 60) {
598 *days = (uint32_t)year * 365 + (uint32_t)leaps + day_of_year;
599 *seconds = (uint32_t)hour * 3600 + minute * 60 + second;
604 static int conf_delayed_char;
605 static long conf_linenum;
606 static string_builder *line_builder;
607 static long current_linenum;
610 conf_init(const char *fname)
612 conf = fopen(fname, "r");
614 fprintf(stderr, "could not open file '%s'\n", fname);
617 conf_delayed_char = -1;
619 line_builder = SB_new();
627 fprintf(stderr, "read error on configuration file\n");
633 if (line_builder != NULL) {
634 SB_free(line_builder);
640 * Get next character from the config file.
647 x = conf_delayed_char;
649 conf_delayed_char = -1;
662 conf_delayed_char = x;
681 return (c >= 'A' && c <= 'Z')
682 || (c >= 'a' && c <= 'z')
683 || (c >= '0' && c <= '9')
684 || (c == '_' || c == '-' || c == '.');
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.
700 SB_reset(line_builder);
703 * Get first non-whitespace character. This skips empty
704 * lines. Comment lines (first non-whitespace character
705 * is a semicolon) are also skipped.
731 * Read up the remaining of the line. The line continuation
732 * sequence (final backslash) is detected and processed.
734 current_linenum = conf_linenum;
736 SB_append_char(line_builder, c);
744 SB_set_length(line_builder,
745 SB_length(line_builder) - 1);
752 } else if (c == '\\') {
755 SB_append_char(line_builder, c);
759 * Remove trailing whitespace (if any).
764 u = SB_length(line_builder);
765 if (u == 0 || !is_ws(
766 SB_contents(line_builder)[u - 1]))
770 SB_set_length(line_builder, u - 1);
774 * We might end up with a totally empty line (in case there
775 * was a line continuation but nothing else), in which case
778 if (SB_length(line_builder) > 0) {
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.
790 parse_header_name(void)
795 buf = SB_contents(line_builder);
796 len = SB_length(line_builder);
797 if (len < 2 || buf[0] != '[' || buf[len - 1] != ']') {
802 while (u < v && is_ws(buf[u])) {
805 while (u < v && is_ws(buf[v - 1])) {
811 for (w = u; w < v; w ++) {
812 if (!is_name_char(buf[w])) {
817 name = xmalloc(len + 1);
818 memcpy(name, buf + u, len);
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.
829 parse_keyvalue(HT *d)
831 char *buf, *name, *value;
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])) {
844 name = xmalloc(u + 1);
845 memcpy(name, buf, u);
847 if (HT_get(d, name) != NULL) {
851 while (u < len && is_ws(buf[u])) {
854 if (u >= len || buf[u] != '=') {
859 while (u < len && is_ws(buf[u])) {
862 value = xmalloc(len - u + 1);
863 memcpy(value, buf + u, len - u);
865 HT_put(d, name, value);
871 * Public keys, indexed by name. Elements are pointers to br_x509_pkey
877 * Trust anchors, indexed by name. Elements are pointers to
878 * test_trust_anchor structures.
880 static HT *trust_anchors;
890 * Test case: trust anchors, certificates (file names), key type and
891 * usage, expected status and EE public key.
898 unsigned key_type_usage;
902 uint32_t days, seconds;
905 static test_case *all_chains;
906 static size_t all_chains_ptr, all_chains_len;
909 free_key(void *value)
914 switch (pk->key_type) {
916 xfree((void *)pk->key.rsa.n);
917 xfree((void *)pk->key.rsa.e);
920 xfree((void *)pk->key.ec.q);
923 fprintf(stderr, "unknown key type: %d\n", pk->key_type);
931 free_trust_anchor(void *value)
933 test_trust_anchor *ttc;
937 xfree(ttc->key_name);
942 free_test_case_contents(test_case *tc)
947 for (u = 0; tc->ta_names[u]; u ++) {
948 xfree(tc->ta_names[u]);
951 for (u = 0; tc->cert_names[u]; u ++) {
952 xfree(tc->cert_names[u]);
954 xfree(tc->cert_names);
955 xfree(tc->servername);
956 xfree(tc->ee_key_name);
960 get_value(char *objtype, HT *objdata, long linenum, char *name)
964 value = HT_get(objdata, name);
967 "missing property '%s' in section '%s' (line %ld)\n",
968 name, objtype, linenum);
974 static unsigned char *
975 parse_hex(const char *name, long linenum, const char *value, size_t *len)
987 for (u = 0; value[u]; u ++) {
991 if (c >= '0' && c <= '9') {
993 } else if (c >= 'A' && c <= 'F') {
995 } else if (c >= 'a' && c <= 'f') {
997 } else if (c == ' ' || c == ':') {
1000 fprintf(stderr, "invalid hexadecimal character"
1001 " in '%s' (line %ld)\n",
1007 buf[ptr] = (acc << 4) + c;
1016 fprintf(stderr, "invalid hexadecimal value (partial"
1017 " byte) in '%s' (line %ld)\n",
1031 split_names(const char *value)
1037 len = strlen(value);
1046 while (u < len && is_ws(value[u])) {
1050 while (v < len && !is_ws(value[v])) {
1054 if (names != NULL) {
1057 name = xmalloc(v - u + 1);
1058 memcpy(name, value + u, v - u);
1066 if (names == NULL) {
1067 names = xmalloc((ptr + 1) * sizeof *names);
1076 string_to_hash(const char *name)
1081 for (u = 0, v = 0; name[u]; u ++) {
1085 if ((c >= '0' && c <= '9')
1086 || (c >= 'A' && c <= 'Z')
1087 || (c >= 'a' && c <= 'z'))
1090 if (v == sizeof tmp) {
1096 if (eqstring(tmp, "md5")) {
1098 } else if (eqstring(tmp, "sha1")) {
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;
1114 string_to_curve(const char *name)
1119 for (u = 0, v = 0; name[u]; u ++) {
1123 if ((c >= '0' && c <= '9')
1124 || (c >= 'A' && c <= 'Z')
1125 || (c >= 'a' && c <= 'z'))
1128 if (v == sizeof tmp) {
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;
1146 parse_object(char *objtype, HT *objdata, long linenum)
1150 name = get_value(objtype, objdata, linenum, "name");
1151 if (eqstring(objtype, "key")) {
1155 stype = get_value(objtype, objdata, linenum, "type");
1156 pk = xmalloc(sizeof *pk);
1157 if (eqstring(stype, "RSA")) {
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")) {
1171 sc = get_value(objtype, objdata, linenum, "curve");
1172 sq = get_value(objtype, objdata, linenum, "q");
1173 curve = string_to_curve(sc);
1175 fprintf(stderr, "unknown curve name: '%s'"
1176 " (line %ld)\n", sc, linenum);
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);
1184 fprintf(stderr, "unknown key type '%s' (line %ld)\n",
1188 if (HT_put(keys, name, pk) != NULL) {
1189 fprintf(stderr, "duplicate key: '%s' (line %ld)\n",
1193 } else if (eqstring(objtype, "anchor")) {
1194 char *dnfile, *kname, *tatype;
1195 test_trust_anchor *tta;
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")) {
1209 "unknown trust anchor type: '%s' (line %ld)\n",
1212 if (HT_put(trust_anchors, name, tta) != NULL) {
1214 "duplicate trust anchor: '%s' (line %ld)\n",
1218 } else if (eqstring(objtype, "chain")) {
1220 char *ktype, *kusage, *sstatus, *shashes, *stime;
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;
1237 "unknown key type: '%s' (line %ld)\n",
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;
1247 "unknown key usage: '%s' (line %ld)\n",
1251 tc.status = (unsigned)atoi(sstatus);
1252 if (tc.status == 0) {
1253 tc.ee_key_name = xstrdup(
1254 get_value(objtype, objdata, linenum, "eekey"));
1256 tc.ee_key_name = NULL;
1258 shashes = HT_get(objdata, "hashes");
1259 if (shashes == NULL) {
1260 tc.hashes = (unsigned)-1;
1266 hns = split_names(shashes);
1267 for (u = 0;; u ++) {
1275 id = string_to_hash(hn);
1278 "unknown hash function '%s'"
1279 " (line %ld)\n", hn, linenum);
1282 tc.hashes |= (unsigned)1 << id;
1287 stime = HT_get(objdata, "time");
1288 if (stime == NULL) {
1289 stime = DEFAULT_TIME;
1291 if (string_to_time(stime, &tc.days, &tc.seconds) < 0) {
1292 fprintf(stderr, "invalid time string '%s' (line %ld)\n",
1296 if (all_chains_ptr == all_chains_len) {
1297 if (all_chains_len == 0) {
1299 all_chains = xmalloc(
1300 all_chains_len * sizeof *all_chains);
1305 nlen = all_chains_len << 1;
1306 ntc = xmalloc(nlen * sizeof *ntc);
1307 memcpy(ntc, all_chains,
1308 all_chains_len * sizeof *all_chains);
1311 all_chains_len = nlen;
1314 all_chains[all_chains_ptr ++] = tc;
1316 fprintf(stderr, "unknown section type '%s' (line %ld)\n",
1323 process_conf_file(const char *fname)
1330 trust_anchors = HT_new();
1341 if (conf_next_line() < 0) {
1344 hname = parse_header_name();
1345 if (hname != NULL) {
1346 if (objtype != NULL) {
1347 parse_object(objtype, objdata, objlinenum);
1348 HT_clear(objdata, xfree);
1352 objlinenum = current_linenum;
1355 if (objtype == NULL) {
1356 fprintf(stderr, "no current section (line %ld)\n",
1360 if (parse_keyvalue(objdata) < 0) {
1361 fprintf(stderr, "wrong configuration, line %ld\n",
1366 if (objtype != NULL) {
1367 parse_object(objtype, objdata, objlinenum);
1370 HT_free(objdata, xfree);
1374 static const struct {
1376 const br_hash_class *impl;
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 },
1388 unsigned char *data;
1393 eqbigint(const unsigned char *b1, size_t b1_len,
1394 const unsigned char *b2, size_t b2_len)
1396 while (b1_len > 0 && *b1 == 0) {
1400 while (b2_len > 0 && *b2 == 0) {
1404 return b1_len == b2_len && memcmp(b1, b2, b1_len) == 0;
1408 eqpkey(const br_x509_pkey *pk1, const br_x509_pkey *pk2)
1413 if (pk1 == NULL || pk2 == NULL) {
1416 if (pk1->key_type != pk2->key_type) {
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);
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;
1431 fprintf(stderr, "unknown key type: %d\n", pk1->key_type);
1438 static size_t max_dp_usage;
1439 static size_t max_rp_usage;
1442 run_test_case(test_case *tc)
1444 br_x509_minimal_context ctx;
1445 br_x509_trust_anchor *anchors;
1448 const br_hash_class *dnhash;
1451 br_x509_pkey *ee_pkey_ref;
1452 const br_x509_pkey *ee_pkey;
1456 printf("%s: ", tc->name);
1460 * Get the hash function to use for hashing DN. We can use just
1461 * any supported hash function, but for the elegance of things,
1462 * we will use one of the hash function implementations
1463 * supported for this test case (with SHA-1 as fallback).
1465 dnhash = &br_sha1_vtable;
1466 for (u = 0; hash_impls[u].id; u ++) {
1467 if ((tc->hashes & ((unsigned)1 << (hash_impls[u].id))) != 0) {
1468 dnhash = hash_impls[u].impl;
1473 * Get trust anchors.
1475 for (num_anchors = 0; tc->ta_names[num_anchors]; num_anchors ++);
1476 anchors = xmalloc(num_anchors * sizeof *anchors);
1477 for (u = 0; tc->ta_names[u]; u ++) {
1478 test_trust_anchor *tta;
1481 tta = HT_get(trust_anchors, tc->ta_names[u]);
1483 fprintf(stderr, "no such trust anchor: '%s'\n",
1487 tak = HT_get(keys, tta->key_name);
1489 fprintf(stderr, "no such public key: '%s'\n",
1493 anchors[u].dn.data = tta->dn;
1494 anchors[u].dn.len = tta->dn_len;
1495 anchors[u].flags = tta->flags;
1496 anchors[u].pkey = *tak;
1500 * Read all relevant certificates.
1502 for (num_certs = 0; tc->cert_names[num_certs]; num_certs ++);
1503 certs = xmalloc(num_certs * sizeof *certs);
1504 for (u = 0; u < num_certs; u ++) {
1505 certs[u].data = read_file(tc->cert_names[u], &certs[u].len);
1509 * Get expected EE public key (if any).
1511 if (tc->ee_key_name == NULL) {
1514 ee_pkey_ref = HT_get(keys, tc->ee_key_name);
1515 if (ee_pkey_ref == NULL) {
1516 fprintf(stderr, "no such public key: '%s'\n",
1523 * Initialise the engine.
1525 br_x509_minimal_init(&ctx, dnhash, anchors, num_anchors);
1526 for (u = 0; hash_impls[u].id; u ++) {
1529 id = hash_impls[u].id;
1530 if ((tc->hashes & ((unsigned)1 << id)) != 0) {
1531 br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl);
1534 br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default());
1535 br_x509_minimal_set_ecdsa(&ctx,
1536 br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
1539 * Set the validation date.
1541 br_x509_minimal_set_time(&ctx, tc->days, tc->seconds);
1544 * Put "canaries" to detect actual stack usage.
1546 for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t); u ++) {
1547 ctx.dp_stack[u] = 0xA7C083FE;
1549 for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t); u ++) {
1550 ctx.rp_stack[u] = 0xA7C083FE;
1554 * Run the engine. We inject certificates by chunks of 100 bytes
1555 * in order to exercise the coroutine API.
1557 ctx.vtable->start_chain(&ctx.vtable, tc->servername);
1558 for (u = 0; u < num_certs; u ++) {
1561 ctx.vtable->start_cert(&ctx.vtable, certs[u].len);
1563 while (v < certs[u].len) {
1566 w = certs[u].len - v;
1570 ctx.vtable->append(&ctx.vtable, certs[u].data + v, w);
1573 ctx.vtable->end_cert(&ctx.vtable);
1575 status = ctx.vtable->end_chain(&ctx.vtable);
1576 ee_pkey = ctx.vtable->get_pkey(&ctx.vtable, &usages);
1579 * Check key type and usage.
1581 if (ee_pkey != NULL) {
1584 ktu = ee_pkey->key_type | usages;
1585 if (tc->key_type_usage != (ktu & tc->key_type_usage)) {
1586 fprintf(stderr, "wrong key type + usage"
1587 " (expected 0x%02X, got 0x%02X)\n",
1588 tc->key_type_usage, ktu);
1594 * Check results. Note that we may still get a public key if
1595 * the path is "not trusted" (but otherwise fine).
1597 if (status != tc->status) {
1598 fprintf(stderr, "wrong status (got %d, expected %d)\n",
1599 status, tc->status);
1602 if (status == BR_ERR_X509_NOT_TRUSTED) {
1605 if (!eqpkey(ee_pkey, ee_pkey_ref)) {
1606 fprintf(stderr, "wrong EE public key\n");
1611 * Check stack usage.
1613 for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t); u > 0; u --) {
1614 if (ctx.dp_stack[u - 1] != 0xA7C083FE) {
1615 if (max_dp_usage < u) {
1621 for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t); u > 0; u --) {
1622 if (ctx.rp_stack[u - 1] != 0xA7C083FE) {
1623 if (max_rp_usage < u) {
1631 * Release everything.
1633 for (u = 0; u < num_certs; u ++) {
1634 xfree(certs[u].data);
1642 * A custom structure for tests, synchronised with the test certificate
1645 * If num is 1 or more, then this is a DN element with OID '1.1.1.1.num'.
1646 * If num is -1 or less, then this is a SAN element of type -num.
1647 * If num is 0, then this is a SAN element of type OtherName with
1648 * OID 1.3.6.1.4.1.311.20.2.3 (Microsoft UPN).
1653 const char *expected;
1654 } name_element_test;
1656 static name_element_test names_ref[] = {
1657 /* === DN tests === */
1667 /* [18] 31:32:33:34 */
1683 /* [30] 00:66:00:6f:00:6f */
1687 /* [30] fe:ff:00:66:00:6f:00:6f */
1691 /* [30] ff:fe:66:00:6f:00:6f:00 */
1695 /* [20] 63:61:66:e9 */
1699 /* [12] 63:61:66:c3:a9 */
1700 10, 1, "caf\xC3\xA9"
1703 /* [12] 63:61:66:e0:83:a9 */
1707 /* [12] 63:61:66:e3:90:8c */
1708 12, 1, "caf\xE3\x90\x8C"
1711 /* [30] 00:63:00:61:00:66:34:0c */
1712 13, 1, "caf\xE3\x90\x8C"
1715 /* [12] 63:61:66:c3 */
1719 /* [30] d8:42:df:f4:00:67:00:6f */
1720 15, 1, "\xF0\xA0\xAF\xB4go"
1723 /* [30] 00:66:d8:42 */
1727 /* [30] d8:42:00:66 */
1731 /* [30] df:f4:00:66 */
1739 /* [30] 00:00:34:0c */
1743 /* [30] 34:0c:00:00:00:66 */
1747 /* [12] ef:bb:bf:66:6f:6f */
1751 /* [30] 00:66:ff:fe:00:6f */
1755 /* [30] 00:66:ff:fd:00:6f */
1756 24, 1, "f\xEF\xBF\xBDo"
1759 /* === Value not found in the DN === */
1764 /* === SAN tests === */
1766 /* SAN OtherName (Microsoft UPN) */
1770 /* SAN rfc822Name */
1771 -1, 1, "bar@foo.com"
1775 -2, 1, "example.com"
1779 -2, 1, "www.example.com"
1782 /* uniformResourceIdentifier */
1783 -6, 1, "http://www.example.com/"
1788 free_name_elements(br_name_element *elts, size_t num)
1792 for (u = 0; u < num; u ++) {
1793 xfree((void *)elts[u].oid);
1800 test_name_extraction(void)
1802 unsigned char *data;
1804 br_x509_minimal_context ctx;
1805 uint32_t days, seconds;
1808 br_name_element *names;
1812 printf("Name extraction: ");
1814 data = read_file("names.crt", &len);
1815 br_x509_minimal_init(&ctx, &br_sha256_vtable, NULL, 0);
1816 for (u = 0; hash_impls[u].id; u ++) {
1819 id = hash_impls[u].id;
1820 br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl);
1822 br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default());
1823 br_x509_minimal_set_ecdsa(&ctx,
1824 br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
1825 string_to_time(DEFAULT_TIME, &days, &seconds);
1826 br_x509_minimal_set_time(&ctx, days, seconds);
1828 num_names = (sizeof names_ref) / (sizeof names_ref[0]);
1829 names = xmalloc(num_names * sizeof *names);
1830 for (u = 0; u < num_names; u ++) {
1834 num = names_ref[u].num;
1842 } else if (num == 0) {
1863 names[u].buf = xmalloc(256);
1866 br_x509_minimal_set_name_elements(&ctx, names, num_names);
1869 * Put "canaries" to detect actual stack usage.
1871 for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t); u ++) {
1872 ctx.dp_stack[u] = 0xA7C083FE;
1874 for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t); u ++) {
1875 ctx.rp_stack[u] = 0xA7C083FE;
1879 * Run the engine. Since we set no trust anchor, we expect a status
1882 ctx.vtable->start_chain(&ctx.vtable, NULL);
1883 ctx.vtable->start_cert(&ctx.vtable, len);
1884 ctx.vtable->append(&ctx.vtable, data, len);
1885 ctx.vtable->end_cert(&ctx.vtable);
1886 status = ctx.vtable->end_chain(&ctx.vtable);
1887 if (status != BR_ERR_X509_NOT_TRUSTED) {
1888 fprintf(stderr, "wrong status: %u\n", status);
1893 * Check stack usage.
1895 for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t); u > 0; u --) {
1896 if (ctx.dp_stack[u - 1] != 0xA7C083FE) {
1897 if (max_dp_usage < u) {
1903 for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t); u > 0; u --) {
1904 if (ctx.rp_stack[u - 1] != 0xA7C083FE) {
1905 if (max_rp_usage < u) {
1913 for (u = 0; u < num_names; u ++) {
1914 if (names[u].status != names_ref[u].status) {
1915 printf("ERR: name %u (id=%d): status=%d, expected=%d\n",
1916 (unsigned)u, names_ref[u].num,
1917 names[u].status, names_ref[u].status);
1918 if (names[u].status > 0) {
1921 printf(" obtained:");
1922 p = (unsigned char *)names[u].buf;
1924 printf(" %02X", *p ++);
1931 if (names_ref[u].expected == NULL) {
1932 if (names[u].buf[0] != 0) {
1933 printf("ERR: name %u not zero-terminated\n",
1939 if (strcmp(names[u].buf, names_ref[u].expected) != 0) {
1942 printf("ERR: name %u (id=%d): wrong value\n",
1943 (unsigned)u, names_ref[u].num);
1944 printf(" expected:");
1945 p = (unsigned char *)names_ref[u].expected;
1947 printf(" %02X", *p ++);
1950 printf(" obtained:");
1951 p = (unsigned char *)names[u].buf;
1953 printf(" %02X", *p ++);
1966 for (u = 0; u < num_names; u ++) {
1967 printf("%u: (%d)", (unsigned)u, names[u].status);
1968 if (names[u].status > 0) {
1971 for (v = 0; names[u].buf[v]; v ++) {
1972 printf(" %02x", names[u].buf[v]);
1980 free_name_elements(names, num_names);
1985 main(int argc, const char *argv[])
1991 * We want to change the current directory to that of the
1992 * executable, so that test files are reliably located. We
1993 * do that only if SRCDIRNAME is defined (old Makefile would
1997 const char *arg, *c;
2000 for (c = arg + strlen(arg);; c --) {
2004 sep = (*c == '/') || (*c == '\\');
2012 len = 1 + (c - arg);
2013 dn = xmalloc(len + 1);
2014 memcpy(dn, arg, len);
2022 fprintf(stderr, "warning: could not"
2023 " set directory to '%s'\n", dn);
2038 process_conf_file(CONFFILE);
2042 for (u = 0; u < all_chains_ptr; u ++) {
2043 run_test_case(&all_chains[u]);
2045 test_name_extraction();
2047 printf("Maximum data stack usage: %u\n", (unsigned)max_dp_usage);
2048 printf("Maximum return stack usage: %u\n", (unsigned)max_rp_usage);
2050 HT_free(keys, free_key);
2051 HT_free(trust_anchors, free_trust_anchor);
2052 for (u = 0; u < all_chains_ptr; u ++) {
2053 free_test_case_contents(&all_chains[u]);