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 STR(x) STR_(x)
35 #define DIRNAME STR(SRCDIRNAME) "/test/x509"
37 #define DIRNAME "test/x509"
39 #define CONFFILE DIRNAME "/alltests.txt"
40 #define DEFAULT_TIME "2016-08-30T18:00:00Z"
52 fprintf(stderr
, "error: cannot allocate %lu byte(s)\n",
68 xstrdup(const char *name
)
87 static string_builder
*
92 sb
= xmalloc(sizeof *sb
);
94 sb
->buf
= xmalloc(sb
->len
);
100 SB_expand(string_builder
*sb
, size_t extra_len
)
105 if (extra_len
< (sb
->len
- sb
->ptr
)) {
109 if (extra_len
> (nlen
- sb
->ptr
)) {
110 nlen
= sb
->ptr
+ extra_len
;
112 nbuf
= xmalloc(nlen
);
113 memcpy(nbuf
, sb
->buf
, sb
->ptr
);
120 SB_append_char(string_builder
*sb
, int c
)
123 sb
->buf
[sb
->ptr
++] = c
;
128 SB_append_string(string_builder *sb, const char *s)
134 memcpy(sb->buf + sb->ptr, s, n);
141 SB_to_string(string_builder *sb)
145 s = xmalloc(sb->ptr + 1);
146 memcpy(s, sb->buf, sb->ptr);
153 SB_contents(string_builder
*sb
)
159 SB_length(string_builder
*sb
)
165 SB_set_length(string_builder
*sb
, size_t len
)
168 SB_expand(sb
, len
- sb
->ptr
);
169 memset(sb
->buf
+ sb
->ptr
, ' ', len
- sb
->ptr
);
175 SB_reset(string_builder
*sb
)
177 SB_set_length(sb
, 0);
181 SB_free(string_builder
*sb
)
187 typedef struct ht_elt_
{
190 struct ht_elt_
*next
;
205 ht
= xmalloc(sizeof *ht
);
208 ht
->buckets
= xmalloc(ht
->num_buckets
* sizeof(ht_elt
*));
209 for (u
= 0; u
< ht
->num_buckets
; u
++) {
210 ht
->buckets
[u
] = NULL
;
216 hash_string(const char *name
)
225 x
= *(const unsigned char *)name
;
226 if (x
>= 'A' && x
<= 'Z') {
236 eqstring(const char *s1
, const char *s2
)
241 x1
= *(const unsigned char *)s1
;
242 x2
= *(const unsigned char *)s2
;
243 if (x1
>= 'A' && x1
<= 'Z') {
246 if (x2
>= 'A' && x2
<= 'Z') {
255 return !(*s1
|| *s2
);
262 ht_elt
**new_buckets
;
266 new_buckets
= xmalloc(n2
* sizeof *new_buckets
);
267 for (u
= 0; u
< n2
; u
++) {
268 new_buckets
[u
] = NULL
;
270 for (u
= 0; u
< n
; u
++) {
274 for (e
= ht
->buckets
[u
]; e
!= NULL
; e
= f
) {
278 hc
= hash_string(e
->name
);
279 v
= (size_t)(hc
& ((uint32_t)n2
- 1));
281 e
->next
= new_buckets
[v
];
286 ht
->buckets
= new_buckets
;
287 ht
->num_buckets
= n2
;
291 HT_put(HT
*ht
, const char *name
, void *value
)
297 hc
= hash_string(name
);
298 k
= (size_t)(hc
& ((uint32_t)ht
->num_buckets
- 1));
299 prev
= &ht
->buckets
[k
];
302 if (eqstring(name
, e
->name
)) {
305 old_value
= e
->value
;
320 e
= xmalloc(sizeof *e
);
321 e
->name
= xstrdup(name
);
323 e
->next
= ht
->buckets
[k
];
326 if (ht
->size
> ht
->num_buckets
) {
335 HT_remove(HT *ht, const char *name)
337 return HT_put(ht, name, NULL);
342 HT_get(const HT
*ht
, const char *name
)
348 hc
= hash_string(name
);
349 k
= (size_t)(hc
& ((uint32_t)ht
->num_buckets
- 1));
350 for (e
= ht
->buckets
[k
]; e
!= NULL
; e
= e
->next
) {
351 if (eqstring(name
, e
->name
)) {
359 HT_clear(HT
*ht
, void (*free_value
)(void *value
))
363 for (u
= 0; u
< ht
->num_buckets
; u
++) {
367 for (e
= ht
->buckets
[u
]; e
!= NULL
; e
= f
) {
370 if (free_value
!= 0) {
371 free_value(e
->value
);
375 ht
->buckets
[u
] = NULL
;
381 HT_free(HT
*ht
, void (*free_value
)(void *value
))
383 HT_clear(ht
, free_value
);
396 static unsigned char *
397 read_all(FILE *f
, size_t *len
)
412 buf2
= xmalloc(blen
);
413 memcpy(buf2
, buf
, ptr
);
417 rlen
= fread(buf
+ ptr
, 1, blen
- ptr
, f
);
422 memcpy(buf3
, buf
, ptr
);
431 static unsigned char *
432 read_file(const char *name
, size_t *len
)
440 dname
= xmalloc(strlen(DIRNAME
) + strlen(name
) + 2);
441 sprintf(dname
, "%s/%s", DIRNAME
, name
);
444 f
= fopen(name
, "rb");
446 fprintf(stderr
, "could not open file '%s'\n", name
);
449 buf
= read_all(f
, len
);
451 fprintf(stderr
, "read error on file '%s'\n", name
);
462 parse_dec(const char *s
, unsigned len
, int *val
)
471 if (c
>= '0' && c
<= '9') {
472 acc
= (acc
* 10) + (c
- '0');
482 parse_choice(const char *s
, const char *acceptable
)
487 while (*acceptable
) {
488 if (c
== *acceptable
++) {
496 month_length(int year
, int month
)
498 static const int base_month_length
[] = {
499 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
504 x
= base_month_length
[month
- 1];
505 if (month
== 2 && year
% 4 == 0
506 && (year
% 100 != 0 || year
% 400 == 0))
514 * Convert a time string to a days+seconds count. Returned value is 0
515 * on success, -1 on error.
518 string_to_time(const char *s
, uint32_t *days
, uint32_t *seconds
)
520 int year
, month
, day
, hour
, minute
, second
;
521 int day_of_year
, leaps
, i
;
523 if (parse_dec(s
, 4, &year
) < 0) {
527 if (parse_choice(s
++, "-:/ ") < 0) {
530 if (parse_dec(s
, 2, &month
) < 0) {
534 if (parse_choice(s
++, "-:/ ") < 0) {
537 if (parse_dec(s
, 2, &day
) < 0) {
541 if (parse_choice(s
++, " T") < 0) {
544 if (parse_dec(s
, 2, &hour
) < 0) {
548 if (parse_choice(s
++, "-:/ ") < 0) {
551 if (parse_dec(s
, 2, &minute
) < 0) {
555 if (parse_choice(s
++, "-:/ ") < 0) {
558 if (parse_dec(s
, 2, &second
) < 0) {
563 while (*s
&& *s
>= '0' && *s
<= '9') {
576 if (month
< 1 || month
> 12) {
580 for (i
= 1; i
< month
; i
++) {
581 day_of_year
+= month_length(year
, i
);
583 if (day
< 1 || day
> month_length(year
, month
)) {
586 day_of_year
+= (day
- 1);
587 leaps
= (year
+ 3) / 4 - (year
+ 99) / 100 + (year
+ 399) / 400;
589 if (hour
> 23 || minute
> 59 || second
> 60) {
592 *days
= (uint32_t)year
* 365 + (uint32_t)leaps
+ day_of_year
;
593 *seconds
= (uint32_t)hour
* 3600 + minute
* 60 + second
;
598 static int conf_delayed_char
;
599 static long conf_linenum
;
600 static string_builder
*line_builder
;
601 static long current_linenum
;
604 conf_init(const char *fname
)
606 conf
= fopen(fname
, "r");
608 fprintf(stderr
, "could not open file '%s'\n", fname
);
611 conf_delayed_char
= -1;
613 line_builder
= SB_new();
621 fprintf(stderr
, "read error on configuration file\n");
627 if (line_builder
!= NULL
) {
628 SB_free(line_builder
);
634 * Get next character from the config file.
641 x
= conf_delayed_char
;
643 conf_delayed_char
= -1;
656 conf_delayed_char
= x
;
675 return (c
>= 'A' && c
<= 'Z')
676 || (c
>= 'a' && c
<= 'z')
677 || (c
>= '0' && c
<= '9')
678 || (c
== '_' || c
== '-' || c
== '.');
682 * Read a complete line. This handles line continuation; empty lines and
683 * comment lines are skipped; leading and trailing whitespace is removed.
684 * Returned value is 0 (line read) or -1 (no line, EOF reached). The line
685 * contents are accumulated in the line_builder.
694 SB_reset(line_builder
);
697 * Get first non-whitespace character. This skips empty
698 * lines. Comment lines (first non-whitespace character
699 * is a semicolon) are also skipped.
725 * Read up the remaining of the line. The line continuation
726 * sequence (final backslash) is detected and processed.
728 current_linenum
= conf_linenum
;
730 SB_append_char(line_builder
, c
);
738 SB_set_length(line_builder
,
739 SB_length(line_builder
) - 1);
746 } else if (c
== '\\') {
749 SB_append_char(line_builder
, c
);
753 * Remove trailing whitespace (if any).
758 u
= SB_length(line_builder
);
759 if (u
== 0 || !is_ws(
760 SB_contents(line_builder
)[u
- 1]))
764 SB_set_length(line_builder
, u
- 1);
768 * We might end up with a totally empty line (in case there
769 * was a line continuation but nothing else), in which case
772 if (SB_length(line_builder
) > 0) {
779 * Test whether the current line is a section header. If yes, then the
780 * header name is extracted, and returned as a newly allocated string.
781 * Otherwise, NULL is returned.
784 parse_header_name(void)
789 buf
= SB_contents(line_builder
);
790 len
= SB_length(line_builder
);
791 if (len
< 2 || buf
[0] != '[' || buf
[len
- 1] != ']') {
796 while (u
< v
&& is_ws(buf
[u
])) {
799 while (u
< v
&& is_ws(buf
[v
- 1])) {
805 for (w
= u
; w
< v
; w
++) {
806 if (!is_name_char(buf
[w
])) {
811 name
= xmalloc(len
+ 1);
812 memcpy(name
, buf
+ u
, len
);
818 * Parse the current line as a 'name = value' pair. The pair is pushed into
819 * the provided hash table. On error (including a duplicate key name),
820 * this function returns -1; otherwise, it returns 0.
823 parse_keyvalue(HT
*d
)
825 char *buf
, *name
, *value
;
828 buf
= SB_contents(line_builder
);
829 len
= SB_length(line_builder
);
830 for (u
= 0; u
< len
; u
++) {
831 if (!is_name_char(buf
[u
])) {
838 name
= xmalloc(u
+ 1);
839 memcpy(name
, buf
, u
);
841 if (HT_get(d
, name
) != NULL
) {
845 while (u
< len
&& is_ws(buf
[u
])) {
848 if (u
>= len
|| buf
[u
] != '=') {
853 while (u
< len
&& is_ws(buf
[u
])) {
856 value
= xmalloc(len
- u
+ 1);
857 memcpy(value
, buf
+ u
, len
- u
);
859 HT_put(d
, name
, value
);
865 * Public keys, indexed by name. Elements are pointers to br_x509_pkey
871 * Trust anchors, indexed by name. Elements are pointers to
872 * test_trust_anchor structures.
874 static HT
*trust_anchors
;
884 * Test case: trust anchors, certificates (file names), key type and
885 * usage, expected status and EE public key.
892 unsigned key_type_usage
;
896 uint32_t days
, seconds
;
899 static test_case
*all_chains
;
900 static size_t all_chains_ptr
, all_chains_len
;
903 free_key(void *value
)
908 switch (pk
->key_type
) {
910 xfree((void *)pk
->key
.rsa
.n
);
911 xfree((void *)pk
->key
.rsa
.e
);
914 xfree((void *)pk
->key
.ec
.q
);
917 fprintf(stderr
, "unknown key type: %d\n", pk
->key_type
);
925 free_trust_anchor(void *value
)
927 test_trust_anchor
*ttc
;
931 xfree(ttc
->key_name
);
936 free_test_case_contents(test_case
*tc
)
941 for (u
= 0; tc
->ta_names
[u
]; u
++) {
942 xfree(tc
->ta_names
[u
]);
945 for (u
= 0; tc
->cert_names
[u
]; u
++) {
946 xfree(tc
->cert_names
[u
]);
948 xfree(tc
->cert_names
);
949 xfree(tc
->servername
);
950 xfree(tc
->ee_key_name
);
954 get_value(char *objtype
, HT
*objdata
, long linenum
, char *name
)
958 value
= HT_get(objdata
, name
);
961 "missing property '%s' in section '%s' (line %ld)\n",
962 name
, objtype
, linenum
);
968 static unsigned char *
969 parse_hex(const char *name
, long linenum
, const char *value
, size_t *len
)
981 for (u
= 0; value
[u
]; u
++) {
985 if (c
>= '0' && c
<= '9') {
987 } else if (c
>= 'A' && c
<= 'F') {
989 } else if (c
>= 'a' && c
<= 'f') {
991 } else if (c
== ' ' || c
== ':') {
994 fprintf(stderr
, "invalid hexadecimal character"
995 " in '%s' (line %ld)\n",
1001 buf
[ptr
] = (acc
<< 4) + c
;
1010 fprintf(stderr
, "invalid hexadecimal value (partial"
1011 " byte) in '%s' (line %ld)\n",
1025 split_names(const char *value
)
1031 len
= strlen(value
);
1040 while (u
< len
&& is_ws(value
[u
])) {
1044 while (v
< len
&& !is_ws(value
[v
])) {
1048 if (names
!= NULL
) {
1051 name
= xmalloc(v
- u
+ 1);
1052 memcpy(name
, value
+ u
, v
- u
);
1060 if (names
== NULL
) {
1061 names
= xmalloc((ptr
+ 1) * sizeof *names
);
1070 string_to_hash(const char *name
)
1075 for (u
= 0, v
= 0; name
[u
]; u
++) {
1079 if ((c
>= '0' && c
<= '9')
1080 || (c
>= 'A' && c
<= 'Z')
1081 || (c
>= 'a' && c
<= 'z'))
1084 if (v
== sizeof tmp
) {
1090 if (eqstring(tmp
, "md5")) {
1092 } else if (eqstring(tmp
, "sha1")) {
1094 } else if (eqstring(tmp
, "sha224")) {
1095 return br_sha224_ID
;
1096 } else if (eqstring(tmp
, "sha256")) {
1097 return br_sha256_ID
;
1098 } else if (eqstring(tmp
, "sha384")) {
1099 return br_sha384_ID
;
1100 } else if (eqstring(tmp
, "sha512")) {
1101 return br_sha512_ID
;
1108 string_to_curve(const char *name
)
1113 for (u
= 0, v
= 0; name
[u
]; u
++) {
1117 if ((c
>= '0' && c
<= '9')
1118 || (c
>= 'A' && c
<= 'Z')
1119 || (c
>= 'a' && c
<= 'z'))
1122 if (v
== sizeof tmp
) {
1128 if (eqstring(tmp
, "p256") || eqstring(tmp
, "secp256r1")) {
1129 return BR_EC_secp256r1
;
1130 } else if (eqstring(tmp
, "p384") || eqstring(tmp
, "secp384r1")) {
1131 return BR_EC_secp384r1
;
1132 } else if (eqstring(tmp
, "p521") || eqstring(tmp
, "secp521r1")) {
1133 return BR_EC_secp521r1
;
1140 parse_object(char *objtype
, HT
*objdata
, long linenum
)
1144 name
= get_value(objtype
, objdata
, linenum
, "name");
1145 if (eqstring(objtype
, "key")) {
1149 stype
= get_value(objtype
, objdata
, linenum
, "type");
1150 pk
= xmalloc(sizeof *pk
);
1151 if (eqstring(stype
, "RSA")) {
1154 sn
= get_value(objtype
, objdata
, linenum
, "n");
1155 se
= get_value(objtype
, objdata
, linenum
, "e");
1156 pk
->key_type
= BR_KEYTYPE_RSA
;
1157 pk
->key
.rsa
.n
= parse_hex("modulus", linenum
,
1158 sn
, &pk
->key
.rsa
.nlen
);
1159 pk
->key
.rsa
.e
= parse_hex("exponent", linenum
,
1160 se
, &pk
->key
.rsa
.elen
);
1161 } else if (eqstring(stype
, "EC")) {
1165 sc
= get_value(objtype
, objdata
, linenum
, "curve");
1166 sq
= get_value(objtype
, objdata
, linenum
, "q");
1167 curve
= string_to_curve(sc
);
1169 fprintf(stderr
, "unknown curve name: '%s'"
1170 " (line %ld)\n", sc
, linenum
);
1173 pk
->key_type
= BR_KEYTYPE_EC
;
1174 pk
->key
.ec
.curve
= curve
;
1175 pk
->key
.ec
.q
= parse_hex("public point", linenum
,
1176 sq
, &pk
->key
.ec
.qlen
);
1178 fprintf(stderr
, "unknown key type '%s' (line %ld)\n",
1182 if (HT_put(keys
, name
, pk
) != NULL
) {
1183 fprintf(stderr
, "duplicate key: '%s' (line %ld)\n",
1187 } else if (eqstring(objtype
, "anchor")) {
1188 char *dnfile
, *kname
, *tatype
;
1189 test_trust_anchor
*tta
;
1191 dnfile
= get_value(objtype
, objdata
, linenum
, "DN_file");
1192 kname
= get_value(objtype
, objdata
, linenum
, "key");
1193 tatype
= get_value(objtype
, objdata
, linenum
, "type");
1194 tta
= xmalloc(sizeof *tta
);
1195 tta
->dn
= read_file(dnfile
, &tta
->dn_len
);
1196 tta
->key_name
= xstrdup(kname
);
1197 if (eqstring(tatype
, "CA")) {
1198 tta
->flags
= BR_X509_TA_CA
;
1199 } else if (eqstring(tatype
, "EE")) {
1203 "unknown trust anchor type: '%s' (line %ld)\n",
1206 if (HT_put(trust_anchors
, name
, tta
) != NULL
) {
1208 "duplicate trust anchor: '%s' (line %ld)\n",
1212 } else if (eqstring(objtype
, "chain")) {
1214 char *ktype
, *kusage
, *sstatus
, *shashes
, *stime
;
1216 ktype
= get_value(objtype
, objdata
, linenum
, "keytype");
1217 kusage
= get_value(objtype
, objdata
, linenum
, "keyusage");
1218 sstatus
= get_value(objtype
, objdata
, linenum
, "status");
1219 tc
.name
= xstrdup(name
);
1220 tc
.ta_names
= split_names(
1221 get_value(objtype
, objdata
, linenum
, "anchors"));
1222 tc
.cert_names
= split_names(
1223 get_value(objtype
, objdata
, linenum
, "chain"));
1224 tc
.servername
= xstrdup(HT_get(objdata
, "servername"));
1225 if (eqstring(ktype
, "RSA")) {
1226 tc
.key_type_usage
= BR_KEYTYPE_RSA
;
1227 } else if (eqstring(ktype
, "EC")) {
1228 tc
.key_type_usage
= BR_KEYTYPE_EC
;
1231 "unknown key type: '%s' (line %ld)\n",
1235 if (eqstring(kusage
, "KEYX")) {
1236 tc
.key_type_usage
|= BR_KEYTYPE_KEYX
;
1237 } else if (eqstring(kusage
, "SIGN")) {
1238 tc
.key_type_usage
|= BR_KEYTYPE_SIGN
;
1241 "unknown key usage: '%s' (line %ld)\n",
1245 tc
.status
= (unsigned)atoi(sstatus
);
1246 if (tc
.status
== 0) {
1247 tc
.ee_key_name
= xstrdup(
1248 get_value(objtype
, objdata
, linenum
, "eekey"));
1250 tc
.ee_key_name
= NULL
;
1252 shashes
= HT_get(objdata
, "hashes");
1253 if (shashes
== NULL
) {
1254 tc
.hashes
= (unsigned)-1;
1260 hns
= split_names(shashes
);
1261 for (u
= 0;; u
++) {
1269 id
= string_to_hash(hn
);
1272 "unknown hash function '%s'"
1273 " (line %ld)\n", hn
, linenum
);
1276 tc
.hashes
|= (unsigned)1 << id
;
1281 stime
= HT_get(objdata
, "time");
1282 if (stime
== NULL
) {
1283 stime
= DEFAULT_TIME
;
1285 if (string_to_time(stime
, &tc
.days
, &tc
.seconds
) < 0) {
1286 fprintf(stderr
, "invalid time string '%s' (line %ld)\n",
1290 if (all_chains_ptr
== all_chains_len
) {
1291 if (all_chains_len
== 0) {
1293 all_chains
= xmalloc(
1294 all_chains_len
* sizeof *all_chains
);
1299 nlen
= all_chains_len
<< 1;
1300 ntc
= xmalloc(nlen
* sizeof *ntc
);
1301 memcpy(ntc
, all_chains
,
1302 all_chains_len
* sizeof *all_chains
);
1305 all_chains_len
= nlen
;
1308 all_chains
[all_chains_ptr
++] = tc
;
1310 fprintf(stderr
, "unknown section type '%s' (line %ld)\n",
1317 process_conf_file(const char *fname
)
1324 trust_anchors
= HT_new();
1335 if (conf_next_line() < 0) {
1338 hname
= parse_header_name();
1339 if (hname
!= NULL
) {
1340 if (objtype
!= NULL
) {
1341 parse_object(objtype
, objdata
, objlinenum
);
1342 HT_clear(objdata
, xfree
);
1346 objlinenum
= current_linenum
;
1349 if (objtype
== NULL
) {
1350 fprintf(stderr
, "no current section (line %ld)\n",
1354 if (parse_keyvalue(objdata
) < 0) {
1355 fprintf(stderr
, "wrong configuration, line %ld\n",
1360 if (objtype
!= NULL
) {
1361 parse_object(objtype
, objdata
, objlinenum
);
1364 HT_free(objdata
, xfree
);
1368 static const struct {
1370 const br_hash_class
*impl
;
1372 { br_md5_ID
, &br_md5_vtable
},
1373 { br_sha1_ID
, &br_sha1_vtable
},
1374 { br_sha224_ID
, &br_sha224_vtable
},
1375 { br_sha256_ID
, &br_sha256_vtable
},
1376 { br_sha384_ID
, &br_sha384_vtable
},
1377 { br_sha512_ID
, &br_sha512_vtable
},
1382 unsigned char *data
;
1387 eqbigint(const unsigned char *b1
, size_t b1_len
,
1388 const unsigned char *b2
, size_t b2_len
)
1390 while (b1_len
> 0 && *b1
== 0) {
1394 while (b2_len
> 0 && *b2
== 0) {
1398 return b1_len
== b2_len
&& memcmp(b1
, b2
, b1_len
) == 0;
1402 eqpkey(const br_x509_pkey
*pk1
, const br_x509_pkey
*pk2
)
1407 if (pk1
== NULL
|| pk2
== NULL
) {
1410 if (pk1
->key_type
!= pk2
->key_type
) {
1413 switch (pk1
->key_type
) {
1414 case BR_KEYTYPE_RSA
:
1415 return eqbigint(pk1
->key
.rsa
.n
, pk1
->key
.rsa
.nlen
,
1416 pk2
->key
.rsa
.n
, pk2
->key
.rsa
.nlen
)
1417 && eqbigint(pk1
->key
.rsa
.e
, pk1
->key
.rsa
.elen
,
1418 pk2
->key
.rsa
.e
, pk2
->key
.rsa
.elen
);
1420 return pk1
->key
.ec
.curve
== pk2
->key
.ec
.curve
1421 && pk1
->key
.ec
.qlen
== pk2
->key
.ec
.qlen
1422 && memcmp(pk1
->key
.ec
.q
,
1423 pk2
->key
.ec
.q
, pk1
->key
.ec
.qlen
) == 0;
1425 fprintf(stderr
, "unknown key type: %d\n", pk1
->key_type
);
1432 static size_t max_dp_usage
;
1433 static size_t max_rp_usage
;
1436 run_test_case(test_case
*tc
)
1438 br_x509_minimal_context ctx
;
1439 br_x509_trust_anchor
*anchors
;
1442 const br_hash_class
*dnhash
;
1445 br_x509_pkey
*ee_pkey_ref
;
1446 const br_x509_pkey
*ee_pkey
;
1450 printf("%s: ", tc
->name
);
1454 * Get the hash function to use for hashing DN. We can use just
1455 * any supported hash function, but for the elegance of things,
1456 * we will use one of the hash function implementations
1457 * supported for this test case (with SHA-1 as fallback).
1459 dnhash
= &br_sha1_vtable
;
1460 for (u
= 0; hash_impls
[u
].id
; u
++) {
1461 if ((tc
->hashes
& ((unsigned)1 << (hash_impls
[u
].id
))) != 0) {
1462 dnhash
= hash_impls
[u
].impl
;
1467 * Get trust anchors.
1469 for (num_anchors
= 0; tc
->ta_names
[num_anchors
]; num_anchors
++);
1470 anchors
= xmalloc(num_anchors
* sizeof *anchors
);
1471 for (u
= 0; tc
->ta_names
[u
]; u
++) {
1472 test_trust_anchor
*tta
;
1475 tta
= HT_get(trust_anchors
, tc
->ta_names
[u
]);
1477 fprintf(stderr
, "no such trust anchor: '%s'\n",
1481 tak
= HT_get(keys
, tta
->key_name
);
1483 fprintf(stderr
, "no such public key: '%s'\n",
1487 anchors
[u
].dn
.data
= tta
->dn
;
1488 anchors
[u
].dn
.len
= tta
->dn_len
;
1489 anchors
[u
].flags
= tta
->flags
;
1490 anchors
[u
].pkey
= *tak
;
1494 * Read all relevant certificates.
1496 for (num_certs
= 0; tc
->cert_names
[num_certs
]; num_certs
++);
1497 certs
= xmalloc(num_certs
* sizeof *certs
);
1498 for (u
= 0; u
< num_certs
; u
++) {
1499 certs
[u
].data
= read_file(tc
->cert_names
[u
], &certs
[u
].len
);
1503 * Get expected EE public key (if any).
1505 if (tc
->ee_key_name
== NULL
) {
1508 ee_pkey_ref
= HT_get(keys
, tc
->ee_key_name
);
1509 if (ee_pkey_ref
== NULL
) {
1510 fprintf(stderr
, "no such public key: '%s'\n",
1517 * Initialise the engine.
1519 br_x509_minimal_init(&ctx
, dnhash
, anchors
, num_anchors
);
1520 for (u
= 0; hash_impls
[u
].id
; u
++) {
1523 id
= hash_impls
[u
].id
;
1524 if ((tc
->hashes
& ((unsigned)1 << id
)) != 0) {
1525 br_x509_minimal_set_hash(&ctx
, id
, hash_impls
[u
].impl
);
1528 br_x509_minimal_set_rsa(&ctx
, br_rsa_i31_pkcs1_vrfy
);
1529 br_x509_minimal_set_ecdsa(&ctx
,
1530 &br_ec_prime_i31
, br_ecdsa_i31_vrfy_asn1
);
1533 * Set the validation date.
1535 br_x509_minimal_set_time(&ctx
, tc
->days
, tc
->seconds
);
1538 * Put "canaries" to detect actual stack usage.
1540 for (u
= 0; u
< (sizeof ctx
.dp_stack
) / sizeof(uint32_t); u
++) {
1541 ctx
.dp_stack
[u
] = 0xA7C083FE;
1543 for (u
= 0; u
< (sizeof ctx
.rp_stack
) / sizeof(uint32_t); u
++) {
1544 ctx
.rp_stack
[u
] = 0xA7C083FE;
1548 * Run the engine. We inject certificates by chunks of 100 bytes
1549 * in order to exercise the coroutine API.
1551 ctx
.vtable
->start_chain(&ctx
.vtable
, tc
->servername
);
1552 for (u
= 0; u
< num_certs
; u
++) {
1555 ctx
.vtable
->start_cert(&ctx
.vtable
, certs
[u
].len
);
1557 while (v
< certs
[u
].len
) {
1560 w
= certs
[u
].len
- v
;
1564 ctx
.vtable
->append(&ctx
.vtable
, certs
[u
].data
+ v
, w
);
1567 ctx
.vtable
->end_cert(&ctx
.vtable
);
1569 status
= ctx
.vtable
->end_chain(&ctx
.vtable
);
1570 ee_pkey
= ctx
.vtable
->get_pkey(&ctx
.vtable
, &usages
);
1573 * Check key type and usage.
1575 if (ee_pkey
!= NULL
) {
1578 ktu
= ee_pkey
->key_type
| usages
;
1579 if (tc
->key_type_usage
!= (ktu
& tc
->key_type_usage
)) {
1580 fprintf(stderr
, "wrong key type + usage"
1581 " (expected 0x%02X, got 0x%02X)\n",
1582 tc
->key_type_usage
, ktu
);
1588 * Check results. Note that we may still get a public key if
1589 * the path is "not trusted" (but otherwise fine).
1591 if (status
!= tc
->status
) {
1592 fprintf(stderr
, "wrong status (got %d, expected %d)\n",
1593 status
, tc
->status
);
1596 if (status
== BR_ERR_X509_NOT_TRUSTED
) {
1599 if (!eqpkey(ee_pkey
, ee_pkey_ref
)) {
1600 fprintf(stderr
, "wrong EE public key\n");
1605 * Check stack usage.
1607 for (u
= (sizeof ctx
.dp_stack
) / sizeof(uint32_t); u
> 0; u
--) {
1608 if (ctx
.dp_stack
[u
- 1] != 0xA7C083FE) {
1609 if (max_dp_usage
< u
) {
1615 for (u
= (sizeof ctx
.rp_stack
) / sizeof(uint32_t); u
> 0; u
--) {
1616 if (ctx
.rp_stack
[u
- 1] != 0xA7C083FE) {
1617 if (max_rp_usage
< u
) {
1625 * Release everything.
1627 for (u
= 0; u
< num_certs
; u
++) {
1628 xfree(certs
[u
].data
);
1636 * A custom structure for tests, synchronised with the test certificate
1639 * If num is 1 or more, then this is a DN element with OID '1.1.1.1.num'.
1640 * If num is -1 or less, then this is a SAN element of type -num.
1641 * If num is 0, then this is a SAN element of type OtherName with
1642 * OID 1.3.6.1.4.1.311.20.2.3 (Microsoft UPN).
1647 const char *expected
;
1648 } name_element_test
;
1650 static name_element_test names_ref
[] = {
1651 /* === DN tests === */
1661 /* [18] 31:32:33:34 */
1677 /* [30] 00:66:00:6f:00:6f */
1681 /* [30] fe:ff:00:66:00:6f:00:6f */
1685 /* [30] ff:fe:66:00:6f:00:6f:00 */
1689 /* [20] 63:61:66:e9 */
1693 /* [12] 63:61:66:c3:a9 */
1694 10, 1, "caf\xC3\xA9"
1697 /* [12] 63:61:66:e0:83:a9 */
1701 /* [12] 63:61:66:e3:90:8c */
1702 12, 1, "caf\xE3\x90\x8C"
1705 /* [30] 00:63:00:61:00:66:34:0c */
1706 13, 1, "caf\xE3\x90\x8C"
1709 /* [12] 63:61:66:c3 */
1713 /* [30] d8:42:df:f4:00:67:00:6f */
1714 15, 1, "\xF0\xA0\xAF\xB4go"
1717 /* [30] 00:66:d8:42 */
1721 /* [30] d8:42:00:66 */
1725 /* [30] df:f4:00:66 */
1733 /* [30] 00:00:34:0c */
1737 /* [30] 34:0c:00:00:00:66 */
1741 /* [12] ef:bb:bf:66:6f:6f */
1745 /* [30] 00:66:ff:fe:00:6f */
1749 /* [30] 00:66:ff:fd:00:6f */
1750 24, 1, "f\xEF\xBF\xBDo"
1753 /* === Value not found in the DN === */
1758 /* === SAN tests === */
1760 /* SAN OtherName (Microsoft UPN) */
1764 /* SAN rfc822Name */
1765 -1, 1, "bar@foo.com"
1769 -2, 1, "example.com"
1773 -2, 1, "www.example.com"
1776 /* uniformResourceIdentifier */
1777 -6, 1, "http://www.example.com/"
1782 free_name_elements(br_name_element
*elts
, size_t num
)
1786 for (u
= 0; u
< num
; u
++) {
1787 xfree((void *)elts
[u
].oid
);
1794 test_name_extraction(void)
1796 unsigned char *data
;
1798 br_x509_minimal_context ctx
;
1799 uint32_t days
, seconds
;
1802 br_name_element
*names
;
1806 printf("Name extraction: ");
1808 data
= read_file("names.crt", &len
);
1809 br_x509_minimal_init(&ctx
, &br_sha256_vtable
, NULL
, 0);
1810 for (u
= 0; hash_impls
[u
].id
; u
++) {
1813 id
= hash_impls
[u
].id
;
1814 br_x509_minimal_set_hash(&ctx
, id
, hash_impls
[u
].impl
);
1816 br_x509_minimal_set_rsa(&ctx
, br_rsa_i31_pkcs1_vrfy
);
1817 br_x509_minimal_set_ecdsa(&ctx
,
1818 &br_ec_prime_i31
, br_ecdsa_i31_vrfy_asn1
);
1819 string_to_time(DEFAULT_TIME
, &days
, &seconds
);
1820 br_x509_minimal_set_time(&ctx
, days
, seconds
);
1822 num_names
= (sizeof names_ref
) / (sizeof names_ref
[0]);
1823 names
= xmalloc(num_names
* sizeof *names
);
1824 for (u
= 0; u
< num_names
; u
++) {
1828 num
= names_ref
[u
].num
;
1836 } else if (num
== 0) {
1857 names
[u
].buf
= xmalloc(256);
1860 br_x509_minimal_set_name_elements(&ctx
, names
, num_names
);
1863 * Put "canaries" to detect actual stack usage.
1865 for (u
= 0; u
< (sizeof ctx
.dp_stack
) / sizeof(uint32_t); u
++) {
1866 ctx
.dp_stack
[u
] = 0xA7C083FE;
1868 for (u
= 0; u
< (sizeof ctx
.rp_stack
) / sizeof(uint32_t); u
++) {
1869 ctx
.rp_stack
[u
] = 0xA7C083FE;
1873 * Run the engine. Since we set no trust anchor, we expect a status
1876 ctx
.vtable
->start_chain(&ctx
.vtable
, NULL
);
1877 ctx
.vtable
->start_cert(&ctx
.vtable
, len
);
1878 ctx
.vtable
->append(&ctx
.vtable
, data
, len
);
1879 ctx
.vtable
->end_cert(&ctx
.vtable
);
1880 status
= ctx
.vtable
->end_chain(&ctx
.vtable
);
1881 if (status
!= BR_ERR_X509_NOT_TRUSTED
) {
1882 fprintf(stderr
, "wrong status: %u\n", status
);
1887 * Check stack usage.
1889 for (u
= (sizeof ctx
.dp_stack
) / sizeof(uint32_t); u
> 0; u
--) {
1890 if (ctx
.dp_stack
[u
- 1] != 0xA7C083FE) {
1891 if (max_dp_usage
< u
) {
1897 for (u
= (sizeof ctx
.rp_stack
) / sizeof(uint32_t); u
> 0; u
--) {
1898 if (ctx
.rp_stack
[u
- 1] != 0xA7C083FE) {
1899 if (max_rp_usage
< u
) {
1907 for (u
= 0; u
< num_names
; u
++) {
1908 if (names
[u
].status
!= names_ref
[u
].status
) {
1909 printf("ERR: name %u (id=%d): status=%d, expected=%d\n",
1910 (unsigned)u
, names_ref
[u
].num
,
1911 names
[u
].status
, names_ref
[u
].status
);
1912 if (names
[u
].status
> 0) {
1915 printf(" obtained:");
1916 p
= (unsigned char *)names
[u
].buf
;
1918 printf(" %02X", *p
++);
1925 if (names_ref
[u
].expected
== NULL
) {
1926 if (names
[u
].buf
[0] != 0) {
1927 printf("ERR: name %u not zero-terminated\n",
1933 if (strcmp(names
[u
].buf
, names_ref
[u
].expected
) != 0) {
1936 printf("ERR: name %u (id=%d): wrong value\n",
1937 (unsigned)u
, names_ref
[u
].num
);
1938 printf(" expected:");
1939 p
= (unsigned char *)names_ref
[u
].expected
;
1941 printf(" %02X", *p
++);
1944 printf(" obtained:");
1945 p
= (unsigned char *)names
[u
].buf
;
1947 printf(" %02X", *p
++);
1960 for (u = 0; u < num_names; u ++) {
1961 printf("%u: (%d)", (unsigned)u, names[u].status);
1962 if (names[u].status > 0) {
1965 for (v = 0; names[u].buf[v]; v ++) {
1966 printf(" %02x", names[u].buf[v]);
1974 free_name_elements(names
, num_names
);
1983 process_conf_file(CONFFILE
);
1987 for (u
= 0; u
< all_chains_ptr
; u
++) {
1988 run_test_case(&all_chains
[u
]);
1990 test_name_extraction();
1992 printf("Maximum data stack usage: %u\n", (unsigned)max_dp_usage
);
1993 printf("Maximum return stack usage: %u\n", (unsigned)max_rp_usage
);
1995 HT_free(keys
, free_key
);
1996 HT_free(trust_anchors
, free_trust_anchor
);
1997 for (u
= 0; u
< all_chains_ptr
; u
++) {
1998 free_test_case_contents(&all_chains
[u
]);