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
32 #define DIRNAME "test/x509"
33 #define CONFFILE (DIRNAME "/alltests.txt")
34 #define DEFAULT_TIME "2016-08-30T18:00:00Z"
46 fprintf(stderr
, "error: cannot allocate %lu byte(s)\n",
62 xstrdup(const char *name
)
81 static string_builder
*
86 sb
= xmalloc(sizeof *sb
);
88 sb
->buf
= xmalloc(sb
->len
);
94 SB_expand(string_builder
*sb
, size_t extra_len
)
99 if (extra_len
< (sb
->len
- sb
->ptr
)) {
103 if (extra_len
> (nlen
- sb
->ptr
)) {
104 nlen
= sb
->ptr
+ extra_len
;
106 nbuf
= xmalloc(nlen
);
107 memcpy(nbuf
, sb
->buf
, sb
->ptr
);
114 SB_append_char(string_builder
*sb
, int c
)
117 sb
->buf
[sb
->ptr
++] = c
;
122 SB_append_string(string_builder *sb, const char *s)
128 memcpy(sb->buf + sb->ptr, s, n);
135 SB_to_string(string_builder *sb)
139 s = xmalloc(sb->ptr + 1);
140 memcpy(s, sb->buf, sb->ptr);
147 SB_contents(string_builder
*sb
)
153 SB_length(string_builder
*sb
)
159 SB_set_length(string_builder
*sb
, size_t len
)
162 SB_expand(sb
, len
- sb
->ptr
);
163 memset(sb
->buf
+ sb
->ptr
, ' ', len
- sb
->ptr
);
169 SB_reset(string_builder
*sb
)
171 SB_set_length(sb
, 0);
175 SB_free(string_builder
*sb
)
181 typedef struct ht_elt_
{
184 struct ht_elt_
*next
;
199 ht
= xmalloc(sizeof *ht
);
202 ht
->buckets
= xmalloc(ht
->num_buckets
* sizeof(ht_elt
*));
203 for (u
= 0; u
< ht
->num_buckets
; u
++) {
204 ht
->buckets
[u
] = NULL
;
210 hash_string(const char *name
)
219 x
= *(const unsigned char *)name
;
220 if (x
>= 'A' && x
<= 'Z') {
230 eqstring(const char *s1
, const char *s2
)
235 x1
= *(const unsigned char *)s1
;
236 x2
= *(const unsigned char *)s2
;
237 if (x1
>= 'A' && x1
<= 'Z') {
240 if (x2
>= 'A' && x2
<= 'Z') {
249 return !(*s1
|| *s2
);
256 ht_elt
**new_buckets
;
260 new_buckets
= xmalloc(n2
* sizeof *new_buckets
);
261 for (u
= 0; u
< n2
; u
++) {
262 new_buckets
[u
] = NULL
;
264 for (u
= 0; u
< n
; u
++) {
268 for (e
= ht
->buckets
[u
]; e
!= NULL
; e
= f
) {
272 hc
= hash_string(e
->name
);
273 v
= (size_t)(hc
& ((uint32_t)n2
- 1));
275 e
->next
= new_buckets
[v
];
280 ht
->buckets
= new_buckets
;
281 ht
->num_buckets
= n2
;
285 HT_put(HT
*ht
, const char *name
, void *value
)
291 hc
= hash_string(name
);
292 k
= (size_t)(hc
& ((uint32_t)ht
->num_buckets
- 1));
293 prev
= &ht
->buckets
[k
];
296 if (eqstring(name
, e
->name
)) {
299 old_value
= e
->value
;
314 e
= xmalloc(sizeof *e
);
315 e
->name
= xstrdup(name
);
317 e
->next
= ht
->buckets
[k
];
320 if (ht
->size
> ht
->num_buckets
) {
329 HT_remove(HT *ht, const char *name)
331 return HT_put(ht, name, NULL);
336 HT_get(const HT
*ht
, const char *name
)
342 hc
= hash_string(name
);
343 k
= (size_t)(hc
& ((uint32_t)ht
->num_buckets
- 1));
344 for (e
= ht
->buckets
[k
]; e
!= NULL
; e
= e
->next
) {
345 if (eqstring(name
, e
->name
)) {
353 HT_clear(HT
*ht
, void (*free_value
)(void *value
))
357 for (u
= 0; u
< ht
->num_buckets
; u
++) {
361 for (e
= ht
->buckets
[u
]; e
!= NULL
; e
= f
) {
364 if (free_value
!= 0) {
365 free_value(e
->value
);
369 ht
->buckets
[u
] = NULL
;
375 HT_free(HT
*ht
, void (*free_value
)(void *value
))
377 HT_clear(ht
, free_value
);
390 static unsigned char *
391 read_all(FILE *f
, size_t *len
)
406 buf2
= xmalloc(blen
);
407 memcpy(buf2
, buf
, ptr
);
411 rlen
= fread(buf
+ ptr
, 1, blen
- ptr
, f
);
416 memcpy(buf3
, buf
, ptr
);
425 static unsigned char *
426 read_file(const char *name
, size_t *len
)
434 dname
= xmalloc(strlen(DIRNAME
) + strlen(name
) + 2);
435 sprintf(dname
, "%s/%s", DIRNAME
, name
);
438 f
= fopen(name
, "rb");
440 fprintf(stderr
, "could not open file '%s'\n", name
);
443 buf
= read_all(f
, len
);
445 fprintf(stderr
, "read error on file '%s'\n", name
);
456 parse_dec(const char *s
, unsigned len
, int *val
)
465 if (c
>= '0' && c
<= '9') {
466 acc
= (acc
* 10) + (c
- '0');
476 parse_choice(const char *s
, const char *acceptable
)
481 while (*acceptable
) {
482 if (c
== *acceptable
++) {
490 month_length(int year
, int month
)
492 static const int base_month_length
[] = {
493 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
498 x
= base_month_length
[month
- 1];
499 if (month
== 2 && year
% 4 == 0
500 && (year
% 100 != 0 || year
% 400 == 0))
508 * Convert a time string to a days+seconds count. Returned value is 0
509 * on success, -1 on error.
512 string_to_time(const char *s
, uint32_t *days
, uint32_t *seconds
)
514 int year
, month
, day
, hour
, minute
, second
;
515 int day_of_year
, leaps
, i
;
517 if (parse_dec(s
, 4, &year
) < 0) {
521 if (parse_choice(s
++, "-:/ ") < 0) {
524 if (parse_dec(s
, 2, &month
) < 0) {
528 if (parse_choice(s
++, "-:/ ") < 0) {
531 if (parse_dec(s
, 2, &day
) < 0) {
535 if (parse_choice(s
++, " T") < 0) {
538 if (parse_dec(s
, 2, &hour
) < 0) {
542 if (parse_choice(s
++, "-:/ ") < 0) {
545 if (parse_dec(s
, 2, &minute
) < 0) {
549 if (parse_choice(s
++, "-:/ ") < 0) {
552 if (parse_dec(s
, 2, &second
) < 0) {
557 while (*s
&& *s
>= '0' && *s
<= '9') {
570 if (month
< 1 || month
> 12) {
574 for (i
= 1; i
< month
; i
++) {
575 day_of_year
+= month_length(year
, i
);
577 if (day
< 1 || day
> month_length(year
, month
)) {
580 day_of_year
+= (day
- 1);
581 leaps
= (year
+ 3) / 4 - (year
+ 99) / 100 + (year
+ 399) / 400;
583 if (hour
> 23 || minute
> 59 || second
> 60) {
586 *days
= (uint32_t)year
* 365 + (uint32_t)leaps
+ day_of_year
;
587 *seconds
= (uint32_t)hour
* 3600 + minute
* 60 + second
;
592 static int conf_delayed_char
;
593 static long conf_linenum
;
594 static string_builder
*line_builder
;
595 static long current_linenum
;
598 conf_init(const char *fname
)
600 conf
= fopen(fname
, "r");
602 fprintf(stderr
, "could not open file '%s'\n", fname
);
605 conf_delayed_char
= -1;
607 line_builder
= SB_new();
615 fprintf(stderr
, "read error on configuration file\n");
621 if (line_builder
!= NULL
) {
622 SB_free(line_builder
);
628 * Get next character from the config file.
635 x
= conf_delayed_char
;
637 conf_delayed_char
= -1;
650 conf_delayed_char
= x
;
669 return (c
>= 'A' && c
<= 'Z')
670 || (c
>= 'a' && c
<= 'z')
671 || (c
>= '0' && c
<= '9')
672 || (c
== '_' || c
== '-' || c
== '.');
676 * Read a complete line. This handles line continuation; empty lines and
677 * comment lines are skipped; leading and trailing whitespace is removed.
678 * Returned value is 0 (line read) or -1 (no line, EOF reached). The line
679 * contents are accumulated in the line_builder.
688 SB_reset(line_builder
);
691 * Get first non-whitespace character. This skips empty
692 * lines. Comment lines (first non-whitespace character
693 * is a semicolon) are also skipped.
719 * Read up the remaining of the line. The line continuation
720 * sequence (final backslash) is detected and processed.
722 current_linenum
= conf_linenum
;
724 SB_append_char(line_builder
, c
);
732 SB_set_length(line_builder
,
733 SB_length(line_builder
) - 1);
740 } else if (c
== '\\') {
743 SB_append_char(line_builder
, c
);
747 * Remove trailing whitespace (if any).
752 u
= SB_length(line_builder
);
753 if (u
== 0 || !is_ws(
754 SB_contents(line_builder
)[u
- 1]))
758 SB_set_length(line_builder
, u
- 1);
762 * We might end up with a totally empty line (in case there
763 * was a line continuation but nothing else), in which case
766 if (SB_length(line_builder
) > 0) {
773 * Test whether the current line is a section header. If yes, then the
774 * header name is extracted, and returned as a newly allocated string.
775 * Otherwise, NULL is returned.
778 parse_header_name(void)
783 buf
= SB_contents(line_builder
);
784 len
= SB_length(line_builder
);
785 if (len
< 2 || buf
[0] != '[' || buf
[len
- 1] != ']') {
790 while (u
< v
&& is_ws(buf
[u
])) {
793 while (u
< v
&& is_ws(buf
[v
- 1])) {
799 for (w
= u
; w
< v
; w
++) {
800 if (!is_name_char(buf
[w
])) {
805 name
= xmalloc(len
+ 1);
806 memcpy(name
, buf
+ u
, len
);
812 * Parse the current line as a 'name = value' pair. The pair is pushed into
813 * the provided hash table. On error (including a duplicate key name),
814 * this function returns -1; otherwise, it returns 0.
817 parse_keyvalue(HT
*d
)
819 char *buf
, *name
, *value
;
822 buf
= SB_contents(line_builder
);
823 len
= SB_length(line_builder
);
824 for (u
= 0; u
< len
; u
++) {
825 if (!is_name_char(buf
[u
])) {
832 name
= xmalloc(u
+ 1);
833 memcpy(name
, buf
, u
);
835 if (HT_get(d
, name
) != NULL
) {
839 while (u
< len
&& is_ws(buf
[u
])) {
842 if (u
>= len
|| buf
[u
] != '=') {
847 while (u
< len
&& is_ws(buf
[u
])) {
850 value
= xmalloc(len
- u
+ 1);
851 memcpy(value
, buf
+ u
, len
- u
);
853 HT_put(d
, name
, value
);
859 * Public keys, indexed by name. Elements are pointers to br_x509_pkey
865 * Trust anchors, indexed by name. Elements are pointers to
866 * test_trust_anchor structures.
868 static HT
*trust_anchors
;
878 * Test case: trust anchors, certificates (file names), key type and
879 * usage, expected status and EE public key.
886 unsigned key_type_usage
;
890 uint32_t days
, seconds
;
893 static test_case
*all_chains
;
894 static size_t all_chains_ptr
, all_chains_len
;
897 free_key(void *value
)
902 switch (pk
->key_type
) {
904 xfree((void *)pk
->key
.rsa
.n
);
905 xfree((void *)pk
->key
.rsa
.e
);
908 xfree((void *)pk
->key
.ec
.q
);
911 fprintf(stderr
, "unknown key type: %d\n", pk
->key_type
);
919 free_trust_anchor(void *value
)
921 test_trust_anchor
*ttc
;
925 xfree(ttc
->key_name
);
930 free_test_case_contents(test_case
*tc
)
935 for (u
= 0; tc
->ta_names
[u
]; u
++) {
936 xfree(tc
->ta_names
[u
]);
939 for (u
= 0; tc
->cert_names
[u
]; u
++) {
940 xfree(tc
->cert_names
[u
]);
942 xfree(tc
->cert_names
);
943 xfree(tc
->servername
);
944 xfree(tc
->ee_key_name
);
948 get_value(char *objtype
, HT
*objdata
, long linenum
, char *name
)
952 value
= HT_get(objdata
, name
);
955 "missing property '%s' in section '%s' (line %ld)\n",
956 name
, objtype
, linenum
);
962 static unsigned char *
963 parse_hex(const char *name
, long linenum
, const char *value
, size_t *len
)
975 for (u
= 0; value
[u
]; u
++) {
979 if (c
>= '0' && c
<= '9') {
981 } else if (c
>= 'A' && c
<= 'F') {
983 } else if (c
>= 'a' && c
<= 'f') {
985 } else if (c
== ' ' || c
== ':') {
988 fprintf(stderr
, "invalid hexadecimal character"
989 " in '%s' (line %ld)\n",
995 buf
[ptr
] = (acc
<< 4) + c
;
1004 fprintf(stderr
, "invalid hexadecimal value (partial"
1005 " byte) in '%s' (line %ld)\n",
1019 split_names(const char *value
)
1025 len
= strlen(value
);
1034 while (u
< len
&& is_ws(value
[u
])) {
1038 while (v
< len
&& !is_ws(value
[v
])) {
1042 if (names
!= NULL
) {
1045 name
= xmalloc(v
- u
+ 1);
1046 memcpy(name
, value
+ u
, v
- u
);
1054 if (names
== NULL
) {
1055 names
= xmalloc((ptr
+ 1) * sizeof *names
);
1064 string_to_hash(const char *name
)
1069 for (u
= 0, v
= 0; name
[u
]; u
++) {
1073 if ((c
>= '0' && c
<= '9')
1074 || (c
>= 'A' && c
<= 'Z')
1075 || (c
>= 'a' && c
<= 'z'))
1078 if (v
== sizeof tmp
) {
1084 if (eqstring(tmp
, "md5")) {
1086 } else if (eqstring(tmp
, "sha1")) {
1088 } else if (eqstring(tmp
, "sha224")) {
1089 return br_sha224_ID
;
1090 } else if (eqstring(tmp
, "sha256")) {
1091 return br_sha256_ID
;
1092 } else if (eqstring(tmp
, "sha384")) {
1093 return br_sha384_ID
;
1094 } else if (eqstring(tmp
, "sha512")) {
1095 return br_sha512_ID
;
1102 string_to_curve(const char *name
)
1107 for (u
= 0, v
= 0; name
[u
]; u
++) {
1111 if ((c
>= '0' && c
<= '9')
1112 || (c
>= 'A' && c
<= 'Z')
1113 || (c
>= 'a' && c
<= 'z'))
1116 if (v
== sizeof tmp
) {
1122 if (eqstring(tmp
, "p256") || eqstring(tmp
, "secp256r1")) {
1123 return BR_EC_secp256r1
;
1124 } else if (eqstring(tmp
, "p384") || eqstring(tmp
, "secp384r1")) {
1125 return BR_EC_secp384r1
;
1126 } else if (eqstring(tmp
, "p521") || eqstring(tmp
, "secp521r1")) {
1127 return BR_EC_secp521r1
;
1134 parse_object(char *objtype
, HT
*objdata
, long linenum
)
1138 name
= get_value(objtype
, objdata
, linenum
, "name");
1139 if (eqstring(objtype
, "key")) {
1143 stype
= get_value(objtype
, objdata
, linenum
, "type");
1144 pk
= xmalloc(sizeof *pk
);
1145 if (eqstring(stype
, "RSA")) {
1148 sn
= get_value(objtype
, objdata
, linenum
, "n");
1149 se
= get_value(objtype
, objdata
, linenum
, "e");
1150 pk
->key_type
= BR_KEYTYPE_RSA
;
1151 pk
->key
.rsa
.n
= parse_hex("modulus", linenum
,
1152 sn
, &pk
->key
.rsa
.nlen
);
1153 pk
->key
.rsa
.e
= parse_hex("exponent", linenum
,
1154 se
, &pk
->key
.rsa
.elen
);
1155 } else if (eqstring(stype
, "EC")) {
1159 sc
= get_value(objtype
, objdata
, linenum
, "curve");
1160 sq
= get_value(objtype
, objdata
, linenum
, "q");
1161 curve
= string_to_curve(sc
);
1163 fprintf(stderr
, "unknown curve name: '%s'"
1164 " (line %ld)\n", sc
, linenum
);
1167 pk
->key_type
= BR_KEYTYPE_EC
;
1168 pk
->key
.ec
.curve
= curve
;
1169 pk
->key
.ec
.q
= parse_hex("public point", linenum
,
1170 sq
, &pk
->key
.ec
.qlen
);
1172 fprintf(stderr
, "unknown key type '%s' (line %ld)\n",
1176 if (HT_put(keys
, name
, pk
) != NULL
) {
1177 fprintf(stderr
, "duplicate key: '%s' (line %ld)\n",
1181 } else if (eqstring(objtype
, "anchor")) {
1182 char *dnfile
, *kname
, *tatype
;
1183 test_trust_anchor
*tta
;
1185 dnfile
= get_value(objtype
, objdata
, linenum
, "DN_file");
1186 kname
= get_value(objtype
, objdata
, linenum
, "key");
1187 tatype
= get_value(objtype
, objdata
, linenum
, "type");
1188 tta
= xmalloc(sizeof *tta
);
1189 tta
->dn
= read_file(dnfile
, &tta
->dn_len
);
1190 tta
->key_name
= xstrdup(kname
);
1191 if (eqstring(tatype
, "CA")) {
1192 tta
->flags
= BR_X509_TA_CA
;
1193 } else if (eqstring(tatype
, "EE")) {
1197 "unknown trust anchor type: '%s' (line %ld)\n",
1200 if (HT_put(trust_anchors
, name
, tta
) != NULL
) {
1202 "duplicate trust anchor: '%s' (line %ld)\n",
1206 } else if (eqstring(objtype
, "chain")) {
1208 char *ktype
, *kusage
, *sstatus
, *shashes
, *stime
;
1210 ktype
= get_value(objtype
, objdata
, linenum
, "keytype");
1211 kusage
= get_value(objtype
, objdata
, linenum
, "keyusage");
1212 sstatus
= get_value(objtype
, objdata
, linenum
, "status");
1213 tc
.name
= xstrdup(name
);
1214 tc
.ta_names
= split_names(
1215 get_value(objtype
, objdata
, linenum
, "anchors"));
1216 tc
.cert_names
= split_names(
1217 get_value(objtype
, objdata
, linenum
, "chain"));
1218 tc
.servername
= xstrdup(HT_get(objdata
, "servername"));
1219 if (eqstring(ktype
, "RSA")) {
1220 tc
.key_type_usage
= BR_KEYTYPE_RSA
;
1221 } else if (eqstring(ktype
, "EC")) {
1222 tc
.key_type_usage
= BR_KEYTYPE_EC
;
1225 "unknown key type: '%s' (line %ld)\n",
1229 if (eqstring(kusage
, "KEYX")) {
1230 tc
.key_type_usage
|= BR_KEYTYPE_KEYX
;
1231 } else if (eqstring(kusage
, "SIGN")) {
1232 tc
.key_type_usage
|= BR_KEYTYPE_SIGN
;
1235 "unknown key usage: '%s' (line %ld)\n",
1239 tc
.status
= (unsigned)atoi(sstatus
);
1240 if (tc
.status
== 0) {
1241 tc
.ee_key_name
= xstrdup(
1242 get_value(objtype
, objdata
, linenum
, "eekey"));
1244 tc
.ee_key_name
= NULL
;
1246 shashes
= HT_get(objdata
, "hashes");
1247 if (shashes
== NULL
) {
1248 tc
.hashes
= (unsigned)-1;
1254 hns
= split_names(shashes
);
1255 for (u
= 0;; u
++) {
1263 id
= string_to_hash(hn
);
1266 "unknown hash function '%s'"
1267 " (line %ld)\n", hn
, linenum
);
1270 tc
.hashes
|= (unsigned)1 << id
;
1275 stime
= HT_get(objdata
, "time");
1276 if (stime
== NULL
) {
1277 stime
= DEFAULT_TIME
;
1279 if (string_to_time(stime
, &tc
.days
, &tc
.seconds
) < 0) {
1280 fprintf(stderr
, "invalid time string '%s' (line %ld)\n",
1284 if (all_chains_ptr
== all_chains_len
) {
1285 if (all_chains_len
== 0) {
1287 all_chains
= xmalloc(
1288 all_chains_len
* sizeof *all_chains
);
1293 nlen
= all_chains_len
<< 1;
1294 ntc
= xmalloc(nlen
* sizeof *ntc
);
1295 memcpy(ntc
, all_chains
,
1296 all_chains_len
* sizeof *all_chains
);
1299 all_chains_len
= nlen
;
1302 all_chains
[all_chains_ptr
++] = tc
;
1304 fprintf(stderr
, "unknown section type '%s' (line %ld)\n",
1311 process_conf_file(const char *fname
)
1318 trust_anchors
= HT_new();
1329 if (conf_next_line() < 0) {
1332 hname
= parse_header_name();
1333 if (hname
!= NULL
) {
1334 if (objtype
!= NULL
) {
1335 parse_object(objtype
, objdata
, objlinenum
);
1336 HT_clear(objdata
, xfree
);
1340 objlinenum
= current_linenum
;
1343 if (objtype
== NULL
) {
1344 fprintf(stderr
, "no current section (line %ld)\n",
1348 if (parse_keyvalue(objdata
) < 0) {
1349 fprintf(stderr
, "wrong configuration, line %ld\n",
1354 if (objtype
!= NULL
) {
1355 parse_object(objtype
, objdata
, objlinenum
);
1358 HT_free(objdata
, xfree
);
1362 static const struct {
1364 const br_hash_class
*impl
;
1366 { br_md5_ID
, &br_md5_vtable
},
1367 { br_sha1_ID
, &br_sha1_vtable
},
1368 { br_sha224_ID
, &br_sha224_vtable
},
1369 { br_sha256_ID
, &br_sha256_vtable
},
1370 { br_sha384_ID
, &br_sha384_vtable
},
1371 { br_sha512_ID
, &br_sha512_vtable
},
1376 unsigned char *data
;
1381 eqbigint(const unsigned char *b1
, size_t b1_len
,
1382 const unsigned char *b2
, size_t b2_len
)
1384 while (b1_len
> 0 && *b1
== 0) {
1388 while (b2_len
> 0 && *b2
== 0) {
1392 return b1_len
== b2_len
&& memcmp(b1
, b2
, b1_len
) == 0;
1396 eqpkey(const br_x509_pkey
*pk1
, const br_x509_pkey
*pk2
)
1401 if (pk1
== NULL
|| pk2
== NULL
) {
1404 if (pk1
->key_type
!= pk2
->key_type
) {
1407 switch (pk1
->key_type
) {
1408 case BR_KEYTYPE_RSA
:
1409 return eqbigint(pk1
->key
.rsa
.n
, pk1
->key
.rsa
.nlen
,
1410 pk2
->key
.rsa
.n
, pk2
->key
.rsa
.nlen
)
1411 && eqbigint(pk1
->key
.rsa
.e
, pk1
->key
.rsa
.elen
,
1412 pk2
->key
.rsa
.e
, pk2
->key
.rsa
.elen
);
1414 return pk1
->key
.ec
.curve
== pk2
->key
.ec
.curve
1415 && pk1
->key
.ec
.qlen
== pk2
->key
.ec
.qlen
1416 && memcmp(pk1
->key
.ec
.q
,
1417 pk2
->key
.ec
.q
, pk1
->key
.ec
.qlen
) == 0;
1419 fprintf(stderr
, "unknown key type: %d\n", pk1
->key_type
);
1426 static size_t max_dp_usage
;
1427 static size_t max_rp_usage
;
1430 run_test_case(test_case
*tc
)
1432 br_x509_minimal_context ctx
;
1433 br_x509_trust_anchor
*anchors
;
1436 const br_hash_class
*dnhash
;
1439 br_x509_pkey
*ee_pkey_ref
;
1440 const br_x509_pkey
*ee_pkey
;
1444 printf("%s: ", tc
->name
);
1448 * Get the hash function to use for hashing DN. We can use just
1449 * any supported hash function, but for the elegance of things,
1450 * we will use one of the hash function implementations
1451 * supported for this test case (with SHA-1 as fallback).
1453 dnhash
= &br_sha1_vtable
;
1454 for (u
= 0; hash_impls
[u
].id
; u
++) {
1455 if ((tc
->hashes
& ((unsigned)1 << (hash_impls
[u
].id
))) != 0) {
1456 dnhash
= hash_impls
[u
].impl
;
1461 * Get trust anchors.
1463 for (num_anchors
= 0; tc
->ta_names
[num_anchors
]; num_anchors
++);
1464 anchors
= xmalloc(num_anchors
* sizeof *anchors
);
1465 for (u
= 0; tc
->ta_names
[u
]; u
++) {
1466 test_trust_anchor
*tta
;
1469 tta
= HT_get(trust_anchors
, tc
->ta_names
[u
]);
1471 fprintf(stderr
, "no such trust anchor: '%s'\n",
1475 tak
= HT_get(keys
, tta
->key_name
);
1477 fprintf(stderr
, "no such public key: '%s'\n",
1481 anchors
[u
].dn
.data
= tta
->dn
;
1482 anchors
[u
].dn
.len
= tta
->dn_len
;
1483 anchors
[u
].flags
= tta
->flags
;
1484 anchors
[u
].pkey
= *tak
;
1488 * Read all relevant certificates.
1490 for (num_certs
= 0; tc
->cert_names
[num_certs
]; num_certs
++);
1491 certs
= xmalloc(num_certs
* sizeof *certs
);
1492 for (u
= 0; u
< num_certs
; u
++) {
1493 certs
[u
].data
= read_file(tc
->cert_names
[u
], &certs
[u
].len
);
1497 * Get expected EE public key (if any).
1499 if (tc
->ee_key_name
== NULL
) {
1502 ee_pkey_ref
= HT_get(keys
, tc
->ee_key_name
);
1503 if (ee_pkey_ref
== NULL
) {
1504 fprintf(stderr
, "no such public key: '%s'\n",
1511 * Initialise the engine.
1513 br_x509_minimal_init(&ctx
, dnhash
, anchors
, num_anchors
);
1514 for (u
= 0; hash_impls
[u
].id
; u
++) {
1517 id
= hash_impls
[u
].id
;
1518 if ((tc
->hashes
& ((unsigned)1 << id
)) != 0) {
1519 br_x509_minimal_set_hash(&ctx
, id
, hash_impls
[u
].impl
);
1522 br_x509_minimal_set_rsa(&ctx
, br_rsa_i31_pkcs1_vrfy
);
1523 br_x509_minimal_set_ecdsa(&ctx
,
1524 &br_ec_prime_i31
, br_ecdsa_i31_vrfy_asn1
);
1527 * Set the validation date.
1529 br_x509_minimal_set_time(&ctx
, tc
->days
, tc
->seconds
);
1532 * Put "canaries" to detect actual stack usage.
1534 for (u
= 0; u
< (sizeof ctx
.dp_stack
) / sizeof(uint32_t); u
++) {
1535 ctx
.dp_stack
[u
] = 0xA7C083FE;
1537 for (u
= 0; u
< (sizeof ctx
.rp_stack
) / sizeof(uint32_t); u
++) {
1538 ctx
.rp_stack
[u
] = 0xA7C083FE;
1542 * Run the engine. We inject certificates by chunks of 100 bytes
1543 * in order to exercise the coroutine API.
1545 ctx
.vtable
->start_chain(&ctx
.vtable
, tc
->servername
);
1546 for (u
= 0; u
< num_certs
; u
++) {
1549 ctx
.vtable
->start_cert(&ctx
.vtable
, certs
[u
].len
);
1551 while (v
< certs
[u
].len
) {
1554 w
= certs
[u
].len
- v
;
1558 ctx
.vtable
->append(&ctx
.vtable
, certs
[u
].data
+ v
, w
);
1561 ctx
.vtable
->end_cert(&ctx
.vtable
);
1563 status
= ctx
.vtable
->end_chain(&ctx
.vtable
);
1564 ee_pkey
= ctx
.vtable
->get_pkey(&ctx
.vtable
, &usages
);
1567 * Check key type and usage.
1569 if (ee_pkey
!= NULL
) {
1572 ktu
= ee_pkey
->key_type
| usages
;
1573 if (tc
->key_type_usage
!= (ktu
& tc
->key_type_usage
)) {
1574 fprintf(stderr
, "wrong key type + usage"
1575 " (expected 0x%02X, got 0x%02X)\n",
1576 tc
->key_type_usage
, ktu
);
1582 * Check results. Note that we may still get a public key if
1583 * the path is "not trusted" (but otherwise fine).
1585 if (status
!= tc
->status
) {
1586 fprintf(stderr
, "wrong status (got %d, expected %d)\n",
1587 status
, tc
->status
);
1590 if (status
== BR_ERR_X509_NOT_TRUSTED
) {
1593 if (!eqpkey(ee_pkey
, ee_pkey_ref
)) {
1594 fprintf(stderr
, "wrong EE public key\n");
1599 * Check stack usage.
1601 for (u
= (sizeof ctx
.dp_stack
) / sizeof(uint32_t); u
> 0; u
--) {
1602 if (ctx
.dp_stack
[u
- 1] != 0xA7C083FE) {
1603 if (max_dp_usage
< u
) {
1609 for (u
= (sizeof ctx
.rp_stack
) / sizeof(uint32_t); u
> 0; u
--) {
1610 if (ctx
.rp_stack
[u
- 1] != 0xA7C083FE) {
1611 if (max_rp_usage
< u
) {
1619 * Release everything.
1621 for (u
= 0; u
< num_certs
; u
++) {
1622 xfree(certs
[u
].data
);
1630 * A custom structure for tests, synchronised with the test certificate
1633 * If num is 1 or more, then this is a DN element with OID '1.1.1.1.num'.
1634 * If num is -1 or less, then this is a SAN element of type -num.
1635 * If num is 0, then this is a SAN element of type OtherName with
1636 * OID 1.3.6.1.4.1.311.20.2.3 (Microsoft UPN).
1641 const char *expected
;
1642 } name_element_test
;
1644 static name_element_test names_ref
[] = {
1645 /* === DN tests === */
1655 /* [18] 31:32:33:34 */
1671 /* [30] 00:66:00:6f:00:6f */
1675 /* [30] fe:ff:00:66:00:6f:00:6f */
1679 /* [30] ff:fe:66:00:6f:00:6f:00 */
1683 /* [20] 63:61:66:e9 */
1687 /* [12] 63:61:66:c3:a9 */
1688 10, 1, "caf\xC3\xA9"
1691 /* [12] 63:61:66:e0:83:a9 */
1695 /* [12] 63:61:66:e3:90:8c */
1696 12, 1, "caf\xE3\x90\x8C"
1699 /* [30] 00:63:00:61:00:66:34:0c */
1700 13, 1, "caf\xE3\x90\x8C"
1703 /* [12] 63:61:66:c3 */
1707 /* [30] d8:42:df:f4:00:67:00:6f */
1708 15, 1, "\xF0\xA0\xAF\xB4go"
1711 /* [30] 00:66:d8:42 */
1715 /* [30] d8:42:00:66 */
1719 /* [30] df:f4:00:66 */
1727 /* [30] 00:00:34:0c */
1731 /* [30] 34:0c:00:00:00:66 */
1735 /* [12] ef:bb:bf:66:6f:6f */
1739 /* [30] 00:66:ff:fe:00:6f */
1743 /* [30] 00:66:ff:fd:00:6f */
1744 24, 1, "f\xEF\xBF\xBDo"
1747 /* === Value not found in the DN === */
1752 /* === SAN tests === */
1754 /* SAN OtherName (Microsoft UPN) */
1758 /* SAN rfc822Name */
1759 -1, 1, "bar@foo.com"
1763 -2, 1, "example.com"
1767 -2, 1, "www.example.com"
1770 /* uniformResourceIdentifier */
1771 -6, 1, "http://www.example.com/"
1776 free_name_elements(br_name_element
*elts
, size_t num
)
1780 for (u
= 0; u
< num
; u
++) {
1781 xfree((void *)elts
[u
].oid
);
1788 test_name_extraction(void)
1790 unsigned char *data
;
1792 br_x509_minimal_context ctx
;
1793 uint32_t days
, seconds
;
1796 br_name_element
*names
;
1800 printf("Name extraction: ");
1802 data
= read_file("names.crt", &len
);
1803 br_x509_minimal_init(&ctx
, &br_sha256_vtable
, NULL
, 0);
1804 for (u
= 0; hash_impls
[u
].id
; u
++) {
1807 id
= hash_impls
[u
].id
;
1808 br_x509_minimal_set_hash(&ctx
, id
, hash_impls
[u
].impl
);
1810 br_x509_minimal_set_rsa(&ctx
, br_rsa_i31_pkcs1_vrfy
);
1811 br_x509_minimal_set_ecdsa(&ctx
,
1812 &br_ec_prime_i31
, br_ecdsa_i31_vrfy_asn1
);
1813 string_to_time(DEFAULT_TIME
, &days
, &seconds
);
1814 br_x509_minimal_set_time(&ctx
, days
, seconds
);
1816 num_names
= (sizeof names_ref
) / (sizeof names_ref
[0]);
1817 names
= xmalloc(num_names
* sizeof *names
);
1818 for (u
= 0; u
< num_names
; u
++) {
1822 num
= names_ref
[u
].num
;
1830 } else if (num
== 0) {
1851 names
[u
].buf
= xmalloc(256);
1854 br_x509_minimal_set_name_elements(&ctx
, names
, num_names
);
1857 * Put "canaries" to detect actual stack usage.
1859 for (u
= 0; u
< (sizeof ctx
.dp_stack
) / sizeof(uint32_t); u
++) {
1860 ctx
.dp_stack
[u
] = 0xA7C083FE;
1862 for (u
= 0; u
< (sizeof ctx
.rp_stack
) / sizeof(uint32_t); u
++) {
1863 ctx
.rp_stack
[u
] = 0xA7C083FE;
1867 * Run the engine. Since we set no trust anchor, we expect a status
1870 ctx
.vtable
->start_chain(&ctx
.vtable
, NULL
);
1871 ctx
.vtable
->start_cert(&ctx
.vtable
, len
);
1872 ctx
.vtable
->append(&ctx
.vtable
, data
, len
);
1873 ctx
.vtable
->end_cert(&ctx
.vtable
);
1874 status
= ctx
.vtable
->end_chain(&ctx
.vtable
);
1875 if (status
!= BR_ERR_X509_NOT_TRUSTED
) {
1876 fprintf(stderr
, "wrong status: %u\n", status
);
1881 * Check stack usage.
1883 for (u
= (sizeof ctx
.dp_stack
) / sizeof(uint32_t); u
> 0; u
--) {
1884 if (ctx
.dp_stack
[u
- 1] != 0xA7C083FE) {
1885 if (max_dp_usage
< u
) {
1891 for (u
= (sizeof ctx
.rp_stack
) / sizeof(uint32_t); u
> 0; u
--) {
1892 if (ctx
.rp_stack
[u
- 1] != 0xA7C083FE) {
1893 if (max_rp_usage
< u
) {
1901 for (u
= 0; u
< num_names
; u
++) {
1902 if (names
[u
].status
!= names_ref
[u
].status
) {
1903 printf("ERR: name %u (id=%d): status=%d, expected=%d\n",
1904 (unsigned)u
, names_ref
[u
].num
,
1905 names
[u
].status
, names_ref
[u
].status
);
1906 if (names
[u
].status
> 0) {
1909 printf(" obtained:");
1910 p
= (unsigned char *)names
[u
].buf
;
1912 printf(" %02X", *p
++);
1919 if (names_ref
[u
].expected
== NULL
) {
1920 if (names
[u
].buf
[0] != 0) {
1921 printf("ERR: name %u not zero-terminated\n",
1927 if (strcmp(names
[u
].buf
, names_ref
[u
].expected
) != 0) {
1930 printf("ERR: name %u (id=%d): wrong value\n",
1931 (unsigned)u
, names_ref
[u
].num
);
1932 printf(" expected:");
1933 p
= (unsigned char *)names_ref
[u
].expected
;
1935 printf(" %02X", *p
++);
1938 printf(" obtained:");
1939 p
= (unsigned char *)names
[u
].buf
;
1941 printf(" %02X", *p
++);
1954 for (u = 0; u < num_names; u ++) {
1955 printf("%u: (%d)", (unsigned)u, names[u].status);
1956 if (names[u].status > 0) {
1959 for (v = 0; names[u].buf[v]; v ++) {
1960 printf(" %02x", names[u].buf[v]);
1968 free_name_elements(names
, num_names
);
1977 process_conf_file(CONFFILE
);
1981 for (u
= 0; u
< all_chains_ptr
; u
++) {
1982 run_test_case(&all_chains
[u
]);
1984 test_name_extraction();
1986 printf("Maximum data stack usage: %u\n", (unsigned)max_dp_usage
);
1987 printf("Maximum return stack usage: %u\n", (unsigned)max_rp_usage
);
1989 HT_free(keys
, free_key
);
1990 HT_free(trust_anchors
, free_trust_anchor
);
1991 for (u
= 0; u
< all_chains_ptr
; u
++) {
1992 free_test_case_contents(&all_chains
[u
]);