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