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
]);