10957b409SSimon J. Gerraty /*
20957b409SSimon J. Gerraty * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
30957b409SSimon J. Gerraty *
40957b409SSimon J. Gerraty * Permission is hereby granted, free of charge, to any person obtaining
50957b409SSimon J. Gerraty * a copy of this software and associated documentation files (the
60957b409SSimon J. Gerraty * "Software"), to deal in the Software without restriction, including
70957b409SSimon J. Gerraty * without limitation the rights to use, copy, modify, merge, publish,
80957b409SSimon J. Gerraty * distribute, sublicense, and/or sell copies of the Software, and to
90957b409SSimon J. Gerraty * permit persons to whom the Software is furnished to do so, subject to
100957b409SSimon J. Gerraty * the following conditions:
110957b409SSimon J. Gerraty *
120957b409SSimon J. Gerraty * The above copyright notice and this permission notice shall be
130957b409SSimon J. Gerraty * included in all copies or substantial portions of the Software.
140957b409SSimon J. Gerraty *
150957b409SSimon J. Gerraty * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
160957b409SSimon J. Gerraty * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
170957b409SSimon J. Gerraty * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
180957b409SSimon J. Gerraty * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
190957b409SSimon J. Gerraty * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
200957b409SSimon J. Gerraty * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
210957b409SSimon J. Gerraty * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
220957b409SSimon J. Gerraty * SOFTWARE.
230957b409SSimon J. Gerraty */
240957b409SSimon J. Gerraty
250957b409SSimon J. Gerraty #include <stdio.h>
260957b409SSimon J. Gerraty #include <stdlib.h>
270957b409SSimon J. Gerraty #include <string.h>
280957b409SSimon J. Gerraty #include <stdint.h>
290957b409SSimon J. Gerraty
300957b409SSimon J. Gerraty #ifdef _WIN32
310957b409SSimon J. Gerraty #include <windows.h>
320957b409SSimon J. Gerraty #else
330957b409SSimon J. Gerraty #include <unistd.h>
340957b409SSimon J. Gerraty #endif
350957b409SSimon J. Gerraty
360957b409SSimon J. Gerraty #include "bearssl.h"
370957b409SSimon J. Gerraty
380957b409SSimon J. Gerraty #define STR(x) STR_(x)
390957b409SSimon J. Gerraty #define STR_(x) #x
400957b409SSimon J. Gerraty #ifdef SRCDIRNAME
410957b409SSimon J. Gerraty #define DIRNAME STR(SRCDIRNAME) "/test/x509"
420957b409SSimon J. Gerraty #else
430957b409SSimon J. Gerraty #define DIRNAME "test/x509"
440957b409SSimon J. Gerraty #endif
450957b409SSimon J. Gerraty #define CONFFILE DIRNAME "/alltests.txt"
460957b409SSimon J. Gerraty #define DEFAULT_TIME "2016-08-30T18:00:00Z"
470957b409SSimon J. Gerraty
480957b409SSimon J. Gerraty static void *
xmalloc(size_t len)490957b409SSimon J. Gerraty xmalloc(size_t len)
500957b409SSimon J. Gerraty {
510957b409SSimon J. Gerraty void *buf;
520957b409SSimon J. Gerraty
530957b409SSimon J. Gerraty if (len == 0) {
540957b409SSimon J. Gerraty return NULL;
550957b409SSimon J. Gerraty }
560957b409SSimon J. Gerraty buf = malloc(len);
570957b409SSimon J. Gerraty if (buf == NULL) {
580957b409SSimon J. Gerraty fprintf(stderr, "error: cannot allocate %lu byte(s)\n",
590957b409SSimon J. Gerraty (unsigned long)len);
600957b409SSimon J. Gerraty exit(EXIT_FAILURE);
610957b409SSimon J. Gerraty }
620957b409SSimon J. Gerraty return buf;
630957b409SSimon J. Gerraty }
640957b409SSimon J. Gerraty
650957b409SSimon J. Gerraty static void
xfree(void * buf)660957b409SSimon J. Gerraty xfree(void *buf)
670957b409SSimon J. Gerraty {
680957b409SSimon J. Gerraty if (buf != NULL) {
690957b409SSimon J. Gerraty free(buf);
700957b409SSimon J. Gerraty }
710957b409SSimon J. Gerraty }
720957b409SSimon J. Gerraty
730957b409SSimon J. Gerraty static char *
xstrdup(const char * name)740957b409SSimon J. Gerraty xstrdup(const char *name)
750957b409SSimon J. Gerraty {
760957b409SSimon J. Gerraty size_t n;
770957b409SSimon J. Gerraty char *s;
780957b409SSimon J. Gerraty
790957b409SSimon J. Gerraty if (name == NULL) {
800957b409SSimon J. Gerraty return NULL;
810957b409SSimon J. Gerraty }
820957b409SSimon J. Gerraty n = strlen(name) + 1;
830957b409SSimon J. Gerraty s = xmalloc(n);
840957b409SSimon J. Gerraty memcpy(s, name, n);
850957b409SSimon J. Gerraty return s;
860957b409SSimon J. Gerraty }
870957b409SSimon J. Gerraty
880957b409SSimon J. Gerraty typedef struct {
890957b409SSimon J. Gerraty char *buf;
900957b409SSimon J. Gerraty size_t ptr, len;
910957b409SSimon J. Gerraty } string_builder;
920957b409SSimon J. Gerraty
930957b409SSimon J. Gerraty static string_builder *
SB_new(void)940957b409SSimon J. Gerraty SB_new(void)
950957b409SSimon J. Gerraty {
960957b409SSimon J. Gerraty string_builder *sb;
970957b409SSimon J. Gerraty
980957b409SSimon J. Gerraty sb = xmalloc(sizeof *sb);
990957b409SSimon J. Gerraty sb->len = 8;
1000957b409SSimon J. Gerraty sb->buf = xmalloc(sb->len);
1010957b409SSimon J. Gerraty sb->ptr = 0;
1020957b409SSimon J. Gerraty return sb;
1030957b409SSimon J. Gerraty }
1040957b409SSimon J. Gerraty
1050957b409SSimon J. Gerraty static void
SB_expand(string_builder * sb,size_t extra_len)1060957b409SSimon J. Gerraty SB_expand(string_builder *sb, size_t extra_len)
1070957b409SSimon J. Gerraty {
1080957b409SSimon J. Gerraty size_t nlen;
1090957b409SSimon J. Gerraty char *nbuf;
1100957b409SSimon J. Gerraty
1110957b409SSimon J. Gerraty if (extra_len < (sb->len - sb->ptr)) {
1120957b409SSimon J. Gerraty return;
1130957b409SSimon J. Gerraty }
1140957b409SSimon J. Gerraty nlen = sb->len << 1;
1150957b409SSimon J. Gerraty if (extra_len > (nlen - sb->ptr)) {
1160957b409SSimon J. Gerraty nlen = sb->ptr + extra_len;
1170957b409SSimon J. Gerraty }
1180957b409SSimon J. Gerraty nbuf = xmalloc(nlen);
1190957b409SSimon J. Gerraty memcpy(nbuf, sb->buf, sb->ptr);
1200957b409SSimon J. Gerraty xfree(sb->buf);
1210957b409SSimon J. Gerraty sb->buf = nbuf;
1220957b409SSimon J. Gerraty sb->len = nlen;
1230957b409SSimon J. Gerraty }
1240957b409SSimon J. Gerraty
1250957b409SSimon J. Gerraty static void
SB_append_char(string_builder * sb,int c)1260957b409SSimon J. Gerraty SB_append_char(string_builder *sb, int c)
1270957b409SSimon J. Gerraty {
1280957b409SSimon J. Gerraty SB_expand(sb, 1);
1290957b409SSimon J. Gerraty sb->buf[sb->ptr ++] = c;
1300957b409SSimon J. Gerraty }
1310957b409SSimon J. Gerraty
1320957b409SSimon J. Gerraty /* unused
1330957b409SSimon J. Gerraty static void
1340957b409SSimon J. Gerraty SB_append_string(string_builder *sb, const char *s)
1350957b409SSimon J. Gerraty {
1360957b409SSimon J. Gerraty size_t n;
1370957b409SSimon J. Gerraty
1380957b409SSimon J. Gerraty n = strlen(s);
1390957b409SSimon J. Gerraty SB_expand(sb, n);
1400957b409SSimon J. Gerraty memcpy(sb->buf + sb->ptr, s, n);
1410957b409SSimon J. Gerraty sb->ptr += n;
1420957b409SSimon J. Gerraty }
1430957b409SSimon J. Gerraty */
1440957b409SSimon J. Gerraty
1450957b409SSimon J. Gerraty /* unused
1460957b409SSimon J. Gerraty static char *
1470957b409SSimon J. Gerraty SB_to_string(string_builder *sb)
1480957b409SSimon J. Gerraty {
1490957b409SSimon J. Gerraty char *s;
1500957b409SSimon J. Gerraty
1510957b409SSimon J. Gerraty s = xmalloc(sb->ptr + 1);
1520957b409SSimon J. Gerraty memcpy(s, sb->buf, sb->ptr);
1530957b409SSimon J. Gerraty s[sb->ptr] = 0;
1540957b409SSimon J. Gerraty return s;
1550957b409SSimon J. Gerraty }
1560957b409SSimon J. Gerraty */
1570957b409SSimon J. Gerraty
1580957b409SSimon J. Gerraty static char *
SB_contents(string_builder * sb)1590957b409SSimon J. Gerraty SB_contents(string_builder *sb)
1600957b409SSimon J. Gerraty {
1610957b409SSimon J. Gerraty return sb->buf;
1620957b409SSimon J. Gerraty }
1630957b409SSimon J. Gerraty
1640957b409SSimon J. Gerraty static size_t
SB_length(string_builder * sb)1650957b409SSimon J. Gerraty SB_length(string_builder *sb)
1660957b409SSimon J. Gerraty {
1670957b409SSimon J. Gerraty return sb->ptr;
1680957b409SSimon J. Gerraty }
1690957b409SSimon J. Gerraty
1700957b409SSimon J. Gerraty static void
SB_set_length(string_builder * sb,size_t len)1710957b409SSimon J. Gerraty SB_set_length(string_builder *sb, size_t len)
1720957b409SSimon J. Gerraty {
1730957b409SSimon J. Gerraty if (sb->ptr < len) {
1740957b409SSimon J. Gerraty SB_expand(sb, len - sb->ptr);
1750957b409SSimon J. Gerraty memset(sb->buf + sb->ptr, ' ', len - sb->ptr);
1760957b409SSimon J. Gerraty }
1770957b409SSimon J. Gerraty sb->ptr = len;
1780957b409SSimon J. Gerraty }
1790957b409SSimon J. Gerraty
1800957b409SSimon J. Gerraty static void
SB_reset(string_builder * sb)1810957b409SSimon J. Gerraty SB_reset(string_builder *sb)
1820957b409SSimon J. Gerraty {
1830957b409SSimon J. Gerraty SB_set_length(sb, 0);
1840957b409SSimon J. Gerraty }
1850957b409SSimon J. Gerraty
1860957b409SSimon J. Gerraty static void
SB_free(string_builder * sb)1870957b409SSimon J. Gerraty SB_free(string_builder *sb)
1880957b409SSimon J. Gerraty {
1890957b409SSimon J. Gerraty xfree(sb->buf);
1900957b409SSimon J. Gerraty xfree(sb);
1910957b409SSimon J. Gerraty }
1920957b409SSimon J. Gerraty
1930957b409SSimon J. Gerraty typedef struct ht_elt_ {
1940957b409SSimon J. Gerraty char *name;
1950957b409SSimon J. Gerraty void *value;
1960957b409SSimon J. Gerraty struct ht_elt_ *next;
1970957b409SSimon J. Gerraty } ht_elt;
1980957b409SSimon J. Gerraty
1990957b409SSimon J. Gerraty typedef struct {
2000957b409SSimon J. Gerraty size_t size;
2010957b409SSimon J. Gerraty ht_elt **buckets;
2020957b409SSimon J. Gerraty size_t num_buckets;
2030957b409SSimon J. Gerraty } HT;
2040957b409SSimon J. Gerraty
2050957b409SSimon J. Gerraty static HT *
HT_new(void)2060957b409SSimon J. Gerraty HT_new(void)
2070957b409SSimon J. Gerraty {
2080957b409SSimon J. Gerraty HT *ht;
2090957b409SSimon J. Gerraty size_t u;
2100957b409SSimon J. Gerraty
2110957b409SSimon J. Gerraty ht = xmalloc(sizeof *ht);
2120957b409SSimon J. Gerraty ht->size = 0;
2130957b409SSimon J. Gerraty ht->num_buckets = 8;
2140957b409SSimon J. Gerraty ht->buckets = xmalloc(ht->num_buckets * sizeof(ht_elt *));
2150957b409SSimon J. Gerraty for (u = 0; u < ht->num_buckets; u ++) {
2160957b409SSimon J. Gerraty ht->buckets[u] = NULL;
2170957b409SSimon J. Gerraty }
2180957b409SSimon J. Gerraty return ht;
2190957b409SSimon J. Gerraty }
2200957b409SSimon J. Gerraty
2210957b409SSimon J. Gerraty static uint32_t
hash_string(const char * name)2220957b409SSimon J. Gerraty hash_string(const char *name)
2230957b409SSimon J. Gerraty {
2240957b409SSimon J. Gerraty uint32_t hc;
2250957b409SSimon J. Gerraty
2260957b409SSimon J. Gerraty hc = 0;
2270957b409SSimon J. Gerraty while (*name) {
2280957b409SSimon J. Gerraty int x;
2290957b409SSimon J. Gerraty
2300957b409SSimon J. Gerraty hc = (hc << 5) - hc;
2310957b409SSimon J. Gerraty x = *(const unsigned char *)name;
2320957b409SSimon J. Gerraty if (x >= 'A' && x <= 'Z') {
2330957b409SSimon J. Gerraty x += 'a' - 'A';
2340957b409SSimon J. Gerraty }
2350957b409SSimon J. Gerraty hc += (uint32_t)x;
2360957b409SSimon J. Gerraty name ++;
2370957b409SSimon J. Gerraty }
2380957b409SSimon J. Gerraty return hc;
2390957b409SSimon J. Gerraty }
2400957b409SSimon J. Gerraty
2410957b409SSimon J. Gerraty static int
eqstring(const char * s1,const char * s2)2420957b409SSimon J. Gerraty eqstring(const char *s1, const char *s2)
2430957b409SSimon J. Gerraty {
2440957b409SSimon J. Gerraty while (*s1 && *s2) {
2450957b409SSimon J. Gerraty int x1, x2;
2460957b409SSimon J. Gerraty
2470957b409SSimon J. Gerraty x1 = *(const unsigned char *)s1;
2480957b409SSimon J. Gerraty x2 = *(const unsigned char *)s2;
2490957b409SSimon J. Gerraty if (x1 >= 'A' && x1 <= 'Z') {
2500957b409SSimon J. Gerraty x1 += 'a' - 'A';
2510957b409SSimon J. Gerraty }
2520957b409SSimon J. Gerraty if (x2 >= 'A' && x2 <= 'Z') {
2530957b409SSimon J. Gerraty x2 += 'a' - 'A';
2540957b409SSimon J. Gerraty }
2550957b409SSimon J. Gerraty if (x1 != x2) {
2560957b409SSimon J. Gerraty return 0;
2570957b409SSimon J. Gerraty }
2580957b409SSimon J. Gerraty s1 ++;
2590957b409SSimon J. Gerraty s2 ++;
2600957b409SSimon J. Gerraty }
2610957b409SSimon J. Gerraty return !(*s1 || *s2);
2620957b409SSimon J. Gerraty }
2630957b409SSimon J. Gerraty
2640957b409SSimon J. Gerraty static void
HT_expand(HT * ht)2650957b409SSimon J. Gerraty HT_expand(HT *ht)
2660957b409SSimon J. Gerraty {
2670957b409SSimon J. Gerraty size_t n, n2, u;
2680957b409SSimon J. Gerraty ht_elt **new_buckets;
2690957b409SSimon J. Gerraty
2700957b409SSimon J. Gerraty n = ht->num_buckets;
2710957b409SSimon J. Gerraty n2 = n << 1;
2720957b409SSimon J. Gerraty new_buckets = xmalloc(n2 * sizeof *new_buckets);
2730957b409SSimon J. Gerraty for (u = 0; u < n2; u ++) {
2740957b409SSimon J. Gerraty new_buckets[u] = NULL;
2750957b409SSimon J. Gerraty }
2760957b409SSimon J. Gerraty for (u = 0; u < n; u ++) {
2770957b409SSimon J. Gerraty ht_elt *e, *f;
2780957b409SSimon J. Gerraty
2790957b409SSimon J. Gerraty f = NULL;
2800957b409SSimon J. Gerraty for (e = ht->buckets[u]; e != NULL; e = f) {
2810957b409SSimon J. Gerraty uint32_t hc;
2820957b409SSimon J. Gerraty size_t v;
2830957b409SSimon J. Gerraty
2840957b409SSimon J. Gerraty hc = hash_string(e->name);
2850957b409SSimon J. Gerraty v = (size_t)(hc & ((uint32_t)n2 - 1));
2860957b409SSimon J. Gerraty f = e->next;
2870957b409SSimon J. Gerraty e->next = new_buckets[v];
2880957b409SSimon J. Gerraty new_buckets[v] = e;
2890957b409SSimon J. Gerraty }
2900957b409SSimon J. Gerraty }
2910957b409SSimon J. Gerraty xfree(ht->buckets);
2920957b409SSimon J. Gerraty ht->buckets = new_buckets;
2930957b409SSimon J. Gerraty ht->num_buckets = n2;
2940957b409SSimon J. Gerraty }
2950957b409SSimon J. Gerraty
2960957b409SSimon J. Gerraty static void *
HT_put(HT * ht,const char * name,void * value)2970957b409SSimon J. Gerraty HT_put(HT *ht, const char *name, void *value)
2980957b409SSimon J. Gerraty {
2990957b409SSimon J. Gerraty uint32_t hc;
3000957b409SSimon J. Gerraty size_t k;
3010957b409SSimon J. Gerraty ht_elt *e, **prev;
3020957b409SSimon J. Gerraty
3030957b409SSimon J. Gerraty hc = hash_string(name);
3040957b409SSimon J. Gerraty k = (size_t)(hc & ((uint32_t)ht->num_buckets - 1));
3050957b409SSimon J. Gerraty prev = &ht->buckets[k];
3060957b409SSimon J. Gerraty e = *prev;
3070957b409SSimon J. Gerraty while (e != NULL) {
3080957b409SSimon J. Gerraty if (eqstring(name, e->name)) {
3090957b409SSimon J. Gerraty void *old_value;
3100957b409SSimon J. Gerraty
3110957b409SSimon J. Gerraty old_value = e->value;
3120957b409SSimon J. Gerraty if (value == NULL) {
3130957b409SSimon J. Gerraty *prev = e->next;
3140957b409SSimon J. Gerraty xfree(e->name);
3150957b409SSimon J. Gerraty xfree(e);
3160957b409SSimon J. Gerraty ht->size --;
3170957b409SSimon J. Gerraty } else {
3180957b409SSimon J. Gerraty e->value = value;
3190957b409SSimon J. Gerraty }
3200957b409SSimon J. Gerraty return old_value;
3210957b409SSimon J. Gerraty }
3220957b409SSimon J. Gerraty prev = &e->next;
3230957b409SSimon J. Gerraty e = *prev;
3240957b409SSimon J. Gerraty }
3250957b409SSimon J. Gerraty if (value != NULL) {
3260957b409SSimon J. Gerraty e = xmalloc(sizeof *e);
3270957b409SSimon J. Gerraty e->name = xstrdup(name);
3280957b409SSimon J. Gerraty e->value = value;
3290957b409SSimon J. Gerraty e->next = ht->buckets[k];
3300957b409SSimon J. Gerraty ht->buckets[k] = e;
3310957b409SSimon J. Gerraty ht->size ++;
3320957b409SSimon J. Gerraty if (ht->size > ht->num_buckets) {
3330957b409SSimon J. Gerraty HT_expand(ht);
3340957b409SSimon J. Gerraty }
3350957b409SSimon J. Gerraty }
3360957b409SSimon J. Gerraty return NULL;
3370957b409SSimon J. Gerraty }
3380957b409SSimon J. Gerraty
3390957b409SSimon J. Gerraty /* unused
3400957b409SSimon J. Gerraty static void *
3410957b409SSimon J. Gerraty HT_remove(HT *ht, const char *name)
3420957b409SSimon J. Gerraty {
3430957b409SSimon J. Gerraty return HT_put(ht, name, NULL);
3440957b409SSimon J. Gerraty }
3450957b409SSimon J. Gerraty */
3460957b409SSimon J. Gerraty
3470957b409SSimon J. Gerraty static void *
HT_get(const HT * ht,const char * name)3480957b409SSimon J. Gerraty HT_get(const HT *ht, const char *name)
3490957b409SSimon J. Gerraty {
3500957b409SSimon J. Gerraty uint32_t hc;
3510957b409SSimon J. Gerraty size_t k;
3520957b409SSimon J. Gerraty ht_elt *e;
3530957b409SSimon J. Gerraty
3540957b409SSimon J. Gerraty hc = hash_string(name);
3550957b409SSimon J. Gerraty k = (size_t)(hc & ((uint32_t)ht->num_buckets - 1));
3560957b409SSimon J. Gerraty for (e = ht->buckets[k]; e != NULL; e = e->next) {
3570957b409SSimon J. Gerraty if (eqstring(name, e->name)) {
3580957b409SSimon J. Gerraty return e->value;
3590957b409SSimon J. Gerraty }
3600957b409SSimon J. Gerraty }
3610957b409SSimon J. Gerraty return NULL;
3620957b409SSimon J. Gerraty }
3630957b409SSimon J. Gerraty
3640957b409SSimon J. Gerraty static void
HT_clear(HT * ht,void (* free_value)(void * value))3650957b409SSimon J. Gerraty HT_clear(HT *ht, void (*free_value)(void *value))
3660957b409SSimon J. Gerraty {
3670957b409SSimon J. Gerraty size_t u;
3680957b409SSimon J. Gerraty
3690957b409SSimon J. Gerraty for (u = 0; u < ht->num_buckets; u ++) {
3700957b409SSimon J. Gerraty ht_elt *e, *f;
3710957b409SSimon J. Gerraty
3720957b409SSimon J. Gerraty f = NULL;
3730957b409SSimon J. Gerraty for (e = ht->buckets[u]; e != NULL; e = f) {
3740957b409SSimon J. Gerraty f = e->next;
3750957b409SSimon J. Gerraty xfree(e->name);
3760957b409SSimon J. Gerraty if (free_value != 0) {
3770957b409SSimon J. Gerraty free_value(e->value);
3780957b409SSimon J. Gerraty }
3790957b409SSimon J. Gerraty xfree(e);
3800957b409SSimon J. Gerraty }
3810957b409SSimon J. Gerraty ht->buckets[u] = NULL;
3820957b409SSimon J. Gerraty }
3830957b409SSimon J. Gerraty ht->size = 0;
3840957b409SSimon J. Gerraty }
3850957b409SSimon J. Gerraty
3860957b409SSimon J. Gerraty static void
HT_free(HT * ht,void (* free_value)(void * value))3870957b409SSimon J. Gerraty HT_free(HT *ht, void (*free_value)(void *value))
3880957b409SSimon J. Gerraty {
3890957b409SSimon J. Gerraty HT_clear(ht, free_value);
3900957b409SSimon J. Gerraty xfree(ht->buckets);
3910957b409SSimon J. Gerraty xfree(ht);
3920957b409SSimon J. Gerraty }
3930957b409SSimon J. Gerraty
3940957b409SSimon J. Gerraty /* unused
3950957b409SSimon J. Gerraty static size_t
3960957b409SSimon J. Gerraty HT_size(HT *ht)
3970957b409SSimon J. Gerraty {
3980957b409SSimon J. Gerraty return ht->size;
3990957b409SSimon J. Gerraty }
4000957b409SSimon J. Gerraty */
4010957b409SSimon J. Gerraty
4020957b409SSimon J. Gerraty static unsigned char *
read_all(FILE * f,size_t * len)4030957b409SSimon J. Gerraty read_all(FILE *f, size_t *len)
4040957b409SSimon J. Gerraty {
4050957b409SSimon J. Gerraty unsigned char *buf;
4060957b409SSimon J. Gerraty size_t ptr, blen;
4070957b409SSimon J. Gerraty
4080957b409SSimon J. Gerraty blen = 1024;
4090957b409SSimon J. Gerraty buf = xmalloc(blen);
4100957b409SSimon J. Gerraty ptr = 0;
4110957b409SSimon J. Gerraty for (;;) {
4120957b409SSimon J. Gerraty size_t rlen;
4130957b409SSimon J. Gerraty
4140957b409SSimon J. Gerraty if (ptr == blen) {
4150957b409SSimon J. Gerraty unsigned char *buf2;
4160957b409SSimon J. Gerraty
4170957b409SSimon J. Gerraty blen <<= 1;
4180957b409SSimon J. Gerraty buf2 = xmalloc(blen);
4190957b409SSimon J. Gerraty memcpy(buf2, buf, ptr);
4200957b409SSimon J. Gerraty xfree(buf);
4210957b409SSimon J. Gerraty buf = buf2;
4220957b409SSimon J. Gerraty }
4230957b409SSimon J. Gerraty rlen = fread(buf + ptr, 1, blen - ptr, f);
4240957b409SSimon J. Gerraty if (rlen == 0) {
4250957b409SSimon J. Gerraty unsigned char *buf3;
4260957b409SSimon J. Gerraty
4270957b409SSimon J. Gerraty buf3 = xmalloc(ptr);
4280957b409SSimon J. Gerraty memcpy(buf3, buf, ptr);
4290957b409SSimon J. Gerraty xfree(buf);
4300957b409SSimon J. Gerraty *len = ptr;
4310957b409SSimon J. Gerraty return buf3;
4320957b409SSimon J. Gerraty }
4330957b409SSimon J. Gerraty ptr += rlen;
4340957b409SSimon J. Gerraty }
4350957b409SSimon J. Gerraty }
4360957b409SSimon J. Gerraty
4370957b409SSimon J. Gerraty static unsigned char *
read_file(const char * name,size_t * len)4380957b409SSimon J. Gerraty read_file(const char *name, size_t *len)
4390957b409SSimon J. Gerraty {
4400957b409SSimon J. Gerraty FILE *f;
4410957b409SSimon J. Gerraty unsigned char *buf;
4420957b409SSimon J. Gerraty
4430957b409SSimon J. Gerraty #ifdef DIRNAME
4440957b409SSimon J. Gerraty char *dname;
4450957b409SSimon J. Gerraty
4460957b409SSimon J. Gerraty dname = xmalloc(strlen(DIRNAME) + strlen(name) + 2);
4470957b409SSimon J. Gerraty sprintf(dname, "%s/%s", DIRNAME, name);
4480957b409SSimon J. Gerraty name = dname;
4490957b409SSimon J. Gerraty #endif
4500957b409SSimon J. Gerraty f = fopen(name, "rb");
4510957b409SSimon J. Gerraty if (f == NULL) {
4520957b409SSimon J. Gerraty fprintf(stderr, "could not open file '%s'\n", name);
4530957b409SSimon J. Gerraty exit(EXIT_FAILURE);
4540957b409SSimon J. Gerraty }
4550957b409SSimon J. Gerraty buf = read_all(f, len);
4560957b409SSimon J. Gerraty if (ferror(f)) {
4570957b409SSimon J. Gerraty fprintf(stderr, "read error on file '%s'\n", name);
4580957b409SSimon J. Gerraty exit(EXIT_FAILURE);
4590957b409SSimon J. Gerraty }
4600957b409SSimon J. Gerraty fclose(f);
4610957b409SSimon J. Gerraty #ifdef DIRNAME
4620957b409SSimon J. Gerraty xfree(dname);
4630957b409SSimon J. Gerraty #endif
4640957b409SSimon J. Gerraty return buf;
4650957b409SSimon J. Gerraty }
4660957b409SSimon J. Gerraty
4670957b409SSimon J. Gerraty static int
parse_dec(const char * s,unsigned len,int * val)4680957b409SSimon J. Gerraty parse_dec(const char *s, unsigned len, int *val)
4690957b409SSimon J. Gerraty {
4700957b409SSimon J. Gerraty int acc;
4710957b409SSimon J. Gerraty
4720957b409SSimon J. Gerraty acc = 0;
4730957b409SSimon J. Gerraty while (len -- > 0) {
4740957b409SSimon J. Gerraty int c;
4750957b409SSimon J. Gerraty
4760957b409SSimon J. Gerraty c = *s ++;
4770957b409SSimon J. Gerraty if (c >= '0' && c <= '9') {
4780957b409SSimon J. Gerraty acc = (acc * 10) + (c - '0');
4790957b409SSimon J. Gerraty } else {
4800957b409SSimon J. Gerraty return -1;
4810957b409SSimon J. Gerraty }
4820957b409SSimon J. Gerraty }
4830957b409SSimon J. Gerraty *val = acc;
4840957b409SSimon J. Gerraty return 0;
4850957b409SSimon J. Gerraty }
4860957b409SSimon J. Gerraty
4870957b409SSimon J. Gerraty static int
parse_choice(const char * s,const char * acceptable)4880957b409SSimon J. Gerraty parse_choice(const char *s, const char *acceptable)
4890957b409SSimon J. Gerraty {
4900957b409SSimon J. Gerraty int c;
4910957b409SSimon J. Gerraty
4920957b409SSimon J. Gerraty c = *s;
4930957b409SSimon J. Gerraty while (*acceptable) {
4940957b409SSimon J. Gerraty if (c == *acceptable ++) {
4950957b409SSimon J. Gerraty return 0;
4960957b409SSimon J. Gerraty }
4970957b409SSimon J. Gerraty }
4980957b409SSimon J. Gerraty return -1;
4990957b409SSimon J. Gerraty }
5000957b409SSimon J. Gerraty
5010957b409SSimon J. Gerraty static int
month_length(int year,int month)5020957b409SSimon J. Gerraty month_length(int year, int month)
5030957b409SSimon J. Gerraty {
5040957b409SSimon J. Gerraty static const int base_month_length[] = {
5050957b409SSimon J. Gerraty 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
5060957b409SSimon J. Gerraty };
5070957b409SSimon J. Gerraty
5080957b409SSimon J. Gerraty int x;
5090957b409SSimon J. Gerraty
5100957b409SSimon J. Gerraty x = base_month_length[month - 1];
5110957b409SSimon J. Gerraty if (month == 2 && year % 4 == 0
5120957b409SSimon J. Gerraty && (year % 100 != 0 || year % 400 == 0))
5130957b409SSimon J. Gerraty {
5140957b409SSimon J. Gerraty x ++;
5150957b409SSimon J. Gerraty }
5160957b409SSimon J. Gerraty return x;
5170957b409SSimon J. Gerraty }
5180957b409SSimon J. Gerraty
5190957b409SSimon J. Gerraty /*
5200957b409SSimon J. Gerraty * Convert a time string to a days+seconds count. Returned value is 0
5210957b409SSimon J. Gerraty * on success, -1 on error.
5220957b409SSimon J. Gerraty */
5230957b409SSimon J. Gerraty static int
string_to_time(const char * s,uint32_t * days,uint32_t * seconds)5240957b409SSimon J. Gerraty string_to_time(const char *s, uint32_t *days, uint32_t *seconds)
5250957b409SSimon J. Gerraty {
5260957b409SSimon J. Gerraty int year, month, day, hour, minute, second;
5270957b409SSimon J. Gerraty int day_of_year, leaps, i;
5280957b409SSimon J. Gerraty
5290957b409SSimon J. Gerraty if (parse_dec(s, 4, &year) < 0) {
5300957b409SSimon J. Gerraty return -1;
5310957b409SSimon J. Gerraty }
5320957b409SSimon J. Gerraty s += 4;
5330957b409SSimon J. Gerraty if (parse_choice(s ++, "-:/ ") < 0) {
5340957b409SSimon J. Gerraty return -1;
5350957b409SSimon J. Gerraty }
5360957b409SSimon J. Gerraty if (parse_dec(s, 2, &month) < 0) {
5370957b409SSimon J. Gerraty return -1;
5380957b409SSimon J. Gerraty }
5390957b409SSimon J. Gerraty s += 2;
5400957b409SSimon J. Gerraty if (parse_choice(s ++, "-:/ ") < 0) {
5410957b409SSimon J. Gerraty return -1;
5420957b409SSimon J. Gerraty }
5430957b409SSimon J. Gerraty if (parse_dec(s, 2, &day) < 0) {
5440957b409SSimon J. Gerraty return -1;
5450957b409SSimon J. Gerraty }
5460957b409SSimon J. Gerraty s += 2;
5470957b409SSimon J. Gerraty if (parse_choice(s ++, " T") < 0) {
5480957b409SSimon J. Gerraty return -1;
5490957b409SSimon J. Gerraty }
5500957b409SSimon J. Gerraty if (parse_dec(s, 2, &hour) < 0) {
5510957b409SSimon J. Gerraty return -1;
5520957b409SSimon J. Gerraty }
5530957b409SSimon J. Gerraty s += 2;
5540957b409SSimon J. Gerraty if (parse_choice(s ++, "-:/ ") < 0) {
5550957b409SSimon J. Gerraty return -1;
5560957b409SSimon J. Gerraty }
5570957b409SSimon J. Gerraty if (parse_dec(s, 2, &minute) < 0) {
5580957b409SSimon J. Gerraty return -1;
5590957b409SSimon J. Gerraty }
5600957b409SSimon J. Gerraty s += 2;
5610957b409SSimon J. Gerraty if (parse_choice(s ++, "-:/ ") < 0) {
5620957b409SSimon J. Gerraty return -1;
5630957b409SSimon J. Gerraty }
5640957b409SSimon J. Gerraty if (parse_dec(s, 2, &second) < 0) {
5650957b409SSimon J. Gerraty return -1;
5660957b409SSimon J. Gerraty }
5670957b409SSimon J. Gerraty s += 2;
5680957b409SSimon J. Gerraty if (*s == '.') {
5690957b409SSimon J. Gerraty while (*s && *s >= '0' && *s <= '9') {
5700957b409SSimon J. Gerraty s ++;
5710957b409SSimon J. Gerraty }
5720957b409SSimon J. Gerraty }
5730957b409SSimon J. Gerraty if (*s) {
5740957b409SSimon J. Gerraty if (*s ++ != 'Z') {
5750957b409SSimon J. Gerraty return -1;
5760957b409SSimon J. Gerraty }
5770957b409SSimon J. Gerraty if (*s) {
5780957b409SSimon J. Gerraty return -1;
5790957b409SSimon J. Gerraty }
5800957b409SSimon J. Gerraty }
5810957b409SSimon J. Gerraty
5820957b409SSimon J. Gerraty if (month < 1 || month > 12) {
5830957b409SSimon J. Gerraty return -1;
5840957b409SSimon J. Gerraty }
5850957b409SSimon J. Gerraty day_of_year = 0;
5860957b409SSimon J. Gerraty for (i = 1; i < month; i ++) {
5870957b409SSimon J. Gerraty day_of_year += month_length(year, i);
5880957b409SSimon J. Gerraty }
5890957b409SSimon J. Gerraty if (day < 1 || day > month_length(year, month)) {
5900957b409SSimon J. Gerraty return -1;
5910957b409SSimon J. Gerraty }
5920957b409SSimon J. Gerraty day_of_year += (day - 1);
5930957b409SSimon J. Gerraty leaps = (year + 3) / 4 - (year + 99) / 100 + (year + 399) / 400;
5940957b409SSimon J. Gerraty
5950957b409SSimon J. Gerraty if (hour > 23 || minute > 59 || second > 60) {
5960957b409SSimon J. Gerraty return -1;
5970957b409SSimon J. Gerraty }
5980957b409SSimon J. Gerraty *days = (uint32_t)year * 365 + (uint32_t)leaps + day_of_year;
5990957b409SSimon J. Gerraty *seconds = (uint32_t)hour * 3600 + minute * 60 + second;
6000957b409SSimon J. Gerraty return 0;
6010957b409SSimon J. Gerraty }
6020957b409SSimon J. Gerraty
6030957b409SSimon J. Gerraty static FILE *conf;
6040957b409SSimon J. Gerraty static int conf_delayed_char;
6050957b409SSimon J. Gerraty static long conf_linenum;
6060957b409SSimon J. Gerraty static string_builder *line_builder;
6070957b409SSimon J. Gerraty static long current_linenum;
6080957b409SSimon J. Gerraty
6090957b409SSimon J. Gerraty static void
conf_init(const char * fname)6100957b409SSimon J. Gerraty conf_init(const char *fname)
6110957b409SSimon J. Gerraty {
6120957b409SSimon J. Gerraty conf = fopen(fname, "r");
6130957b409SSimon J. Gerraty if (conf == NULL) {
6140957b409SSimon J. Gerraty fprintf(stderr, "could not open file '%s'\n", fname);
6150957b409SSimon J. Gerraty exit(EXIT_FAILURE);
6160957b409SSimon J. Gerraty }
6170957b409SSimon J. Gerraty conf_delayed_char = -1;
6180957b409SSimon J. Gerraty conf_linenum = 1;
6190957b409SSimon J. Gerraty line_builder = SB_new();
6200957b409SSimon J. Gerraty }
6210957b409SSimon J. Gerraty
6220957b409SSimon J. Gerraty static void
conf_close(void)6230957b409SSimon J. Gerraty conf_close(void)
6240957b409SSimon J. Gerraty {
6250957b409SSimon J. Gerraty if (conf != NULL) {
6260957b409SSimon J. Gerraty if (ferror(conf)) {
6270957b409SSimon J. Gerraty fprintf(stderr, "read error on configuration file\n");
6280957b409SSimon J. Gerraty exit(EXIT_FAILURE);
6290957b409SSimon J. Gerraty }
6300957b409SSimon J. Gerraty fclose(conf);
6310957b409SSimon J. Gerraty conf = NULL;
6320957b409SSimon J. Gerraty }
6330957b409SSimon J. Gerraty if (line_builder != NULL) {
6340957b409SSimon J. Gerraty SB_free(line_builder);
6350957b409SSimon J. Gerraty line_builder = NULL;
6360957b409SSimon J. Gerraty }
6370957b409SSimon J. Gerraty }
6380957b409SSimon J. Gerraty
6390957b409SSimon J. Gerraty /*
6400957b409SSimon J. Gerraty * Get next character from the config file.
6410957b409SSimon J. Gerraty */
6420957b409SSimon J. Gerraty static int
conf_next_low(void)6430957b409SSimon J. Gerraty conf_next_low(void)
6440957b409SSimon J. Gerraty {
6450957b409SSimon J. Gerraty int x;
6460957b409SSimon J. Gerraty
6470957b409SSimon J. Gerraty x = conf_delayed_char;
6480957b409SSimon J. Gerraty if (x >= 0) {
6490957b409SSimon J. Gerraty conf_delayed_char = -1;
6500957b409SSimon J. Gerraty } else {
6510957b409SSimon J. Gerraty x = fgetc(conf);
6520957b409SSimon J. Gerraty if (x == EOF) {
6530957b409SSimon J. Gerraty x = -1;
6540957b409SSimon J. Gerraty }
6550957b409SSimon J. Gerraty }
6560957b409SSimon J. Gerraty if (x == '\r') {
6570957b409SSimon J. Gerraty x = fgetc(conf);
6580957b409SSimon J. Gerraty if (x == EOF) {
6590957b409SSimon J. Gerraty x = -1;
6600957b409SSimon J. Gerraty }
6610957b409SSimon J. Gerraty if (x != '\n') {
6620957b409SSimon J. Gerraty conf_delayed_char = x;
6630957b409SSimon J. Gerraty x = '\n';
6640957b409SSimon J. Gerraty }
6650957b409SSimon J. Gerraty }
6660957b409SSimon J. Gerraty if (x == '\n') {
6670957b409SSimon J. Gerraty conf_linenum ++;
6680957b409SSimon J. Gerraty }
6690957b409SSimon J. Gerraty return x;
6700957b409SSimon J. Gerraty }
6710957b409SSimon J. Gerraty
6720957b409SSimon J. Gerraty static int
is_ws(int x)6730957b409SSimon J. Gerraty is_ws(int x)
6740957b409SSimon J. Gerraty {
6750957b409SSimon J. Gerraty return x <= 32;
6760957b409SSimon J. Gerraty }
6770957b409SSimon J. Gerraty
6780957b409SSimon J. Gerraty static int
is_name_char(int c)6790957b409SSimon J. Gerraty is_name_char(int c)
6800957b409SSimon J. Gerraty {
6810957b409SSimon J. Gerraty return (c >= 'A' && c <= 'Z')
6820957b409SSimon J. Gerraty || (c >= 'a' && c <= 'z')
6830957b409SSimon J. Gerraty || (c >= '0' && c <= '9')
6840957b409SSimon J. Gerraty || (c == '_' || c == '-' || c == '.');
6850957b409SSimon J. Gerraty }
6860957b409SSimon J. Gerraty
6870957b409SSimon J. Gerraty /*
6880957b409SSimon J. Gerraty * Read a complete line. This handles line continuation; empty lines and
6890957b409SSimon J. Gerraty * comment lines are skipped; leading and trailing whitespace is removed.
6900957b409SSimon J. Gerraty * Returned value is 0 (line read) or -1 (no line, EOF reached). The line
6910957b409SSimon J. Gerraty * contents are accumulated in the line_builder.
6920957b409SSimon J. Gerraty */
6930957b409SSimon J. Gerraty static int
conf_next_line(void)6940957b409SSimon J. Gerraty conf_next_line(void)
6950957b409SSimon J. Gerraty {
6960957b409SSimon J. Gerraty for (;;) {
6970957b409SSimon J. Gerraty int c;
6980957b409SSimon J. Gerraty int lcwb;
6990957b409SSimon J. Gerraty
7000957b409SSimon J. Gerraty SB_reset(line_builder);
7010957b409SSimon J. Gerraty
7020957b409SSimon J. Gerraty /*
7030957b409SSimon J. Gerraty * Get first non-whitespace character. This skips empty
7040957b409SSimon J. Gerraty * lines. Comment lines (first non-whitespace character
7050957b409SSimon J. Gerraty * is a semicolon) are also skipped.
7060957b409SSimon J. Gerraty */
7070957b409SSimon J. Gerraty for (;;) {
7080957b409SSimon J. Gerraty c = conf_next_low();
7090957b409SSimon J. Gerraty if (c < 0) {
7100957b409SSimon J. Gerraty return -1;
7110957b409SSimon J. Gerraty }
7120957b409SSimon J. Gerraty if (is_ws(c)) {
7130957b409SSimon J. Gerraty continue;
7140957b409SSimon J. Gerraty }
7150957b409SSimon J. Gerraty if (c == ';') {
7160957b409SSimon J. Gerraty for (;;) {
7170957b409SSimon J. Gerraty c = conf_next_low();
7180957b409SSimon J. Gerraty if (c < 0) {
7190957b409SSimon J. Gerraty return -1;
7200957b409SSimon J. Gerraty }
7210957b409SSimon J. Gerraty if (c == '\n') {
7220957b409SSimon J. Gerraty break;
7230957b409SSimon J. Gerraty }
7240957b409SSimon J. Gerraty }
7250957b409SSimon J. Gerraty continue;
7260957b409SSimon J. Gerraty }
7270957b409SSimon J. Gerraty break;
7280957b409SSimon J. Gerraty }
7290957b409SSimon J. Gerraty
7300957b409SSimon J. Gerraty /*
7310957b409SSimon J. Gerraty * Read up the remaining of the line. The line continuation
7320957b409SSimon J. Gerraty * sequence (final backslash) is detected and processed.
7330957b409SSimon J. Gerraty */
7340957b409SSimon J. Gerraty current_linenum = conf_linenum;
7350957b409SSimon J. Gerraty lcwb = (c == '\\');
7360957b409SSimon J. Gerraty SB_append_char(line_builder, c);
7370957b409SSimon J. Gerraty for (;;) {
7380957b409SSimon J. Gerraty c = conf_next_low();
7390957b409SSimon J. Gerraty if (c < 0) {
7400957b409SSimon J. Gerraty break;
7410957b409SSimon J. Gerraty }
7420957b409SSimon J. Gerraty if (lcwb) {
7430957b409SSimon J. Gerraty if (c == '\n') {
7440957b409SSimon J. Gerraty SB_set_length(line_builder,
7450957b409SSimon J. Gerraty SB_length(line_builder) - 1);
7460957b409SSimon J. Gerraty }
7470957b409SSimon J. Gerraty lcwb = 0;
7480957b409SSimon J. Gerraty continue;
7490957b409SSimon J. Gerraty }
7500957b409SSimon J. Gerraty if (c == '\n') {
7510957b409SSimon J. Gerraty break;
7520957b409SSimon J. Gerraty } else if (c == '\\') {
7530957b409SSimon J. Gerraty lcwb = 1;
7540957b409SSimon J. Gerraty }
7550957b409SSimon J. Gerraty SB_append_char(line_builder, c);
7560957b409SSimon J. Gerraty }
7570957b409SSimon J. Gerraty
7580957b409SSimon J. Gerraty /*
7590957b409SSimon J. Gerraty * Remove trailing whitespace (if any).
7600957b409SSimon J. Gerraty */
7610957b409SSimon J. Gerraty for (;;) {
7620957b409SSimon J. Gerraty size_t u;
7630957b409SSimon J. Gerraty
7640957b409SSimon J. Gerraty u = SB_length(line_builder);
7650957b409SSimon J. Gerraty if (u == 0 || !is_ws(
7660957b409SSimon J. Gerraty SB_contents(line_builder)[u - 1]))
7670957b409SSimon J. Gerraty {
7680957b409SSimon J. Gerraty break;
7690957b409SSimon J. Gerraty }
7700957b409SSimon J. Gerraty SB_set_length(line_builder, u - 1);
7710957b409SSimon J. Gerraty }
7720957b409SSimon J. Gerraty
7730957b409SSimon J. Gerraty /*
7740957b409SSimon J. Gerraty * We might end up with a totally empty line (in case there
7750957b409SSimon J. Gerraty * was a line continuation but nothing else), in which case
7760957b409SSimon J. Gerraty * we must loop.
7770957b409SSimon J. Gerraty */
7780957b409SSimon J. Gerraty if (SB_length(line_builder) > 0) {
7790957b409SSimon J. Gerraty return 0;
7800957b409SSimon J. Gerraty }
7810957b409SSimon J. Gerraty }
7820957b409SSimon J. Gerraty }
7830957b409SSimon J. Gerraty
7840957b409SSimon J. Gerraty /*
7850957b409SSimon J. Gerraty * Test whether the current line is a section header. If yes, then the
7860957b409SSimon J. Gerraty * header name is extracted, and returned as a newly allocated string.
7870957b409SSimon J. Gerraty * Otherwise, NULL is returned.
7880957b409SSimon J. Gerraty */
7890957b409SSimon J. Gerraty static char *
parse_header_name(void)7900957b409SSimon J. Gerraty parse_header_name(void)
7910957b409SSimon J. Gerraty {
7920957b409SSimon J. Gerraty char *buf, *name;
7930957b409SSimon J. Gerraty size_t u, v, w, len;
7940957b409SSimon J. Gerraty
7950957b409SSimon J. Gerraty buf = SB_contents(line_builder);
7960957b409SSimon J. Gerraty len = SB_length(line_builder);
7970957b409SSimon J. Gerraty if (len < 2 || buf[0] != '[' || buf[len - 1] != ']') {
7980957b409SSimon J. Gerraty return NULL;
7990957b409SSimon J. Gerraty }
8000957b409SSimon J. Gerraty u = 1;
8010957b409SSimon J. Gerraty v = len - 1;
8020957b409SSimon J. Gerraty while (u < v && is_ws(buf[u])) {
8030957b409SSimon J. Gerraty u ++;
8040957b409SSimon J. Gerraty }
8050957b409SSimon J. Gerraty while (u < v && is_ws(buf[v - 1])) {
8060957b409SSimon J. Gerraty v --;
8070957b409SSimon J. Gerraty }
8080957b409SSimon J. Gerraty if (u == v) {
8090957b409SSimon J. Gerraty return NULL;
8100957b409SSimon J. Gerraty }
8110957b409SSimon J. Gerraty for (w = u; w < v; w ++) {
8120957b409SSimon J. Gerraty if (!is_name_char(buf[w])) {
8130957b409SSimon J. Gerraty return NULL;
8140957b409SSimon J. Gerraty }
8150957b409SSimon J. Gerraty }
8160957b409SSimon J. Gerraty len = v - u;
8170957b409SSimon J. Gerraty name = xmalloc(len + 1);
8180957b409SSimon J. Gerraty memcpy(name, buf + u, len);
8190957b409SSimon J. Gerraty name[len] = 0;
8200957b409SSimon J. Gerraty return name;
8210957b409SSimon J. Gerraty }
8220957b409SSimon J. Gerraty
8230957b409SSimon J. Gerraty /*
8240957b409SSimon J. Gerraty * Parse the current line as a 'name = value' pair. The pair is pushed into
8250957b409SSimon J. Gerraty * the provided hash table. On error (including a duplicate key name),
8260957b409SSimon J. Gerraty * this function returns -1; otherwise, it returns 0.
8270957b409SSimon J. Gerraty */
8280957b409SSimon J. Gerraty static int
parse_keyvalue(HT * d)8290957b409SSimon J. Gerraty parse_keyvalue(HT *d)
8300957b409SSimon J. Gerraty {
8310957b409SSimon J. Gerraty char *buf, *name, *value;
8320957b409SSimon J. Gerraty size_t u, len;
8330957b409SSimon J. Gerraty
8340957b409SSimon J. Gerraty buf = SB_contents(line_builder);
8350957b409SSimon J. Gerraty len = SB_length(line_builder);
8360957b409SSimon J. Gerraty for (u = 0; u < len; u ++) {
8370957b409SSimon J. Gerraty if (!is_name_char(buf[u])) {
8380957b409SSimon J. Gerraty break;
8390957b409SSimon J. Gerraty }
8400957b409SSimon J. Gerraty }
8410957b409SSimon J. Gerraty if (u == 0) {
8420957b409SSimon J. Gerraty return -1;
8430957b409SSimon J. Gerraty }
8440957b409SSimon J. Gerraty name = xmalloc(u + 1);
8450957b409SSimon J. Gerraty memcpy(name, buf, u);
8460957b409SSimon J. Gerraty name[u] = 0;
8470957b409SSimon J. Gerraty if (HT_get(d, name) != NULL) {
8480957b409SSimon J. Gerraty xfree(name);
8490957b409SSimon J. Gerraty return -1;
8500957b409SSimon J. Gerraty }
8510957b409SSimon J. Gerraty while (u < len && is_ws(buf[u])) {
8520957b409SSimon J. Gerraty u ++;
8530957b409SSimon J. Gerraty }
8540957b409SSimon J. Gerraty if (u >= len || buf[u] != '=') {
8550957b409SSimon J. Gerraty xfree(name);
8560957b409SSimon J. Gerraty return -1;
8570957b409SSimon J. Gerraty }
8580957b409SSimon J. Gerraty u ++;
8590957b409SSimon J. Gerraty while (u < len && is_ws(buf[u])) {
8600957b409SSimon J. Gerraty u ++;
8610957b409SSimon J. Gerraty }
8620957b409SSimon J. Gerraty value = xmalloc(len - u + 1);
8630957b409SSimon J. Gerraty memcpy(value, buf + u, len - u);
8640957b409SSimon J. Gerraty value[len - u] = 0;
8650957b409SSimon J. Gerraty HT_put(d, name, value);
8660957b409SSimon J. Gerraty xfree(name);
8670957b409SSimon J. Gerraty return 0;
8680957b409SSimon J. Gerraty }
8690957b409SSimon J. Gerraty
8700957b409SSimon J. Gerraty /*
8710957b409SSimon J. Gerraty * Public keys, indexed by name. Elements are pointers to br_x509_pkey
8720957b409SSimon J. Gerraty * structures.
8730957b409SSimon J. Gerraty */
8740957b409SSimon J. Gerraty static HT *keys;
8750957b409SSimon J. Gerraty
8760957b409SSimon J. Gerraty /*
8770957b409SSimon J. Gerraty * Trust anchors, indexed by name. Elements are pointers to
8780957b409SSimon J. Gerraty * test_trust_anchor structures.
8790957b409SSimon J. Gerraty */
8800957b409SSimon J. Gerraty static HT *trust_anchors;
8810957b409SSimon J. Gerraty
8820957b409SSimon J. Gerraty typedef struct {
8830957b409SSimon J. Gerraty unsigned char *dn;
8840957b409SSimon J. Gerraty size_t dn_len;
8850957b409SSimon J. Gerraty unsigned flags;
8860957b409SSimon J. Gerraty char *key_name;
8870957b409SSimon J. Gerraty } test_trust_anchor;
8880957b409SSimon J. Gerraty
8890957b409SSimon J. Gerraty /*
8900957b409SSimon J. Gerraty * Test case: trust anchors, certificates (file names), key type and
8910957b409SSimon J. Gerraty * usage, expected status and EE public key.
8920957b409SSimon J. Gerraty */
8930957b409SSimon J. Gerraty typedef struct {
8940957b409SSimon J. Gerraty char *name;
8950957b409SSimon J. Gerraty char **ta_names;
8960957b409SSimon J. Gerraty char **cert_names;
8970957b409SSimon J. Gerraty char *servername;
8980957b409SSimon J. Gerraty unsigned key_type_usage;
8990957b409SSimon J. Gerraty unsigned status;
9000957b409SSimon J. Gerraty char *ee_key_name;
9010957b409SSimon J. Gerraty unsigned hashes;
9020957b409SSimon J. Gerraty uint32_t days, seconds;
9030957b409SSimon J. Gerraty } test_case;
9040957b409SSimon J. Gerraty
9050957b409SSimon J. Gerraty static test_case *all_chains;
9060957b409SSimon J. Gerraty static size_t all_chains_ptr, all_chains_len;
9070957b409SSimon J. Gerraty
9080957b409SSimon J. Gerraty static void
free_key(void * value)9090957b409SSimon J. Gerraty free_key(void *value)
9100957b409SSimon J. Gerraty {
9110957b409SSimon J. Gerraty br_x509_pkey *pk;
9120957b409SSimon J. Gerraty
9130957b409SSimon J. Gerraty pk = value;
9140957b409SSimon J. Gerraty switch (pk->key_type) {
9150957b409SSimon J. Gerraty case BR_KEYTYPE_RSA:
9160957b409SSimon J. Gerraty xfree((void *)pk->key.rsa.n);
9170957b409SSimon J. Gerraty xfree((void *)pk->key.rsa.e);
9180957b409SSimon J. Gerraty break;
9190957b409SSimon J. Gerraty case BR_KEYTYPE_EC:
9200957b409SSimon J. Gerraty xfree((void *)pk->key.ec.q);
9210957b409SSimon J. Gerraty break;
9220957b409SSimon J. Gerraty default:
9230957b409SSimon J. Gerraty fprintf(stderr, "unknown key type: %d\n", pk->key_type);
9240957b409SSimon J. Gerraty exit(EXIT_FAILURE);
9250957b409SSimon J. Gerraty break;
9260957b409SSimon J. Gerraty }
9270957b409SSimon J. Gerraty xfree(pk);
9280957b409SSimon J. Gerraty }
9290957b409SSimon J. Gerraty
9300957b409SSimon J. Gerraty static void
free_trust_anchor(void * value)9310957b409SSimon J. Gerraty free_trust_anchor(void *value)
9320957b409SSimon J. Gerraty {
9330957b409SSimon J. Gerraty test_trust_anchor *ttc;
9340957b409SSimon J. Gerraty
9350957b409SSimon J. Gerraty ttc = value;
9360957b409SSimon J. Gerraty xfree(ttc->dn);
9370957b409SSimon J. Gerraty xfree(ttc->key_name);
9380957b409SSimon J. Gerraty xfree(ttc);
9390957b409SSimon J. Gerraty }
9400957b409SSimon J. Gerraty
9410957b409SSimon J. Gerraty static void
free_test_case_contents(test_case * tc)9420957b409SSimon J. Gerraty free_test_case_contents(test_case *tc)
9430957b409SSimon J. Gerraty {
9440957b409SSimon J. Gerraty size_t u;
9450957b409SSimon J. Gerraty
9460957b409SSimon J. Gerraty xfree(tc->name);
9470957b409SSimon J. Gerraty for (u = 0; tc->ta_names[u]; u ++) {
9480957b409SSimon J. Gerraty xfree(tc->ta_names[u]);
9490957b409SSimon J. Gerraty }
9500957b409SSimon J. Gerraty xfree(tc->ta_names);
9510957b409SSimon J. Gerraty for (u = 0; tc->cert_names[u]; u ++) {
9520957b409SSimon J. Gerraty xfree(tc->cert_names[u]);
9530957b409SSimon J. Gerraty }
9540957b409SSimon J. Gerraty xfree(tc->cert_names);
9550957b409SSimon J. Gerraty xfree(tc->servername);
9560957b409SSimon J. Gerraty xfree(tc->ee_key_name);
9570957b409SSimon J. Gerraty }
9580957b409SSimon J. Gerraty
9590957b409SSimon J. Gerraty static char *
get_value(char * objtype,HT * objdata,long linenum,char * name)9600957b409SSimon J. Gerraty get_value(char *objtype, HT *objdata, long linenum, char *name)
9610957b409SSimon J. Gerraty {
9620957b409SSimon J. Gerraty char *value;
9630957b409SSimon J. Gerraty
9640957b409SSimon J. Gerraty value = HT_get(objdata, name);
9650957b409SSimon J. Gerraty if (value == NULL) {
9660957b409SSimon J. Gerraty fprintf(stderr,
9670957b409SSimon J. Gerraty "missing property '%s' in section '%s' (line %ld)\n",
9680957b409SSimon J. Gerraty name, objtype, linenum);
9690957b409SSimon J. Gerraty exit(EXIT_FAILURE);
9700957b409SSimon J. Gerraty }
9710957b409SSimon J. Gerraty return value;
9720957b409SSimon J. Gerraty }
9730957b409SSimon J. Gerraty
9740957b409SSimon J. Gerraty static unsigned char *
parse_hex(const char * name,long linenum,const char * value,size_t * len)9750957b409SSimon J. Gerraty parse_hex(const char *name, long linenum, const char *value, size_t *len)
9760957b409SSimon J. Gerraty {
9770957b409SSimon J. Gerraty unsigned char *buf;
9780957b409SSimon J. Gerraty
9790957b409SSimon J. Gerraty buf = NULL;
9800957b409SSimon J. Gerraty for (;;) {
9810957b409SSimon J. Gerraty size_t u, ptr;
9820957b409SSimon J. Gerraty int acc, z;
9830957b409SSimon J. Gerraty
9840957b409SSimon J. Gerraty ptr = 0;
9850957b409SSimon J. Gerraty acc = 0;
9860957b409SSimon J. Gerraty z = 0;
9870957b409SSimon J. Gerraty for (u = 0; value[u]; u ++) {
9880957b409SSimon J. Gerraty int c;
9890957b409SSimon J. Gerraty
9900957b409SSimon J. Gerraty c = value[u];
9910957b409SSimon J. Gerraty if (c >= '0' && c <= '9') {
9920957b409SSimon J. Gerraty c -= '0';
9930957b409SSimon J. Gerraty } else if (c >= 'A' && c <= 'F') {
9940957b409SSimon J. Gerraty c -= 'A' - 10;
9950957b409SSimon J. Gerraty } else if (c >= 'a' && c <= 'f') {
9960957b409SSimon J. Gerraty c -= 'a' - 10;
9970957b409SSimon J. Gerraty } else if (c == ' ' || c == ':') {
9980957b409SSimon J. Gerraty continue;
9990957b409SSimon J. Gerraty } else {
10000957b409SSimon J. Gerraty fprintf(stderr, "invalid hexadecimal character"
10010957b409SSimon J. Gerraty " in '%s' (line %ld)\n",
10020957b409SSimon J. Gerraty name, linenum);
10030957b409SSimon J. Gerraty exit(EXIT_FAILURE);
10040957b409SSimon J. Gerraty }
10050957b409SSimon J. Gerraty if (z) {
10060957b409SSimon J. Gerraty if (buf != NULL) {
10070957b409SSimon J. Gerraty buf[ptr] = (acc << 4) + c;
10080957b409SSimon J. Gerraty }
10090957b409SSimon J. Gerraty ptr ++;
10100957b409SSimon J. Gerraty } else {
10110957b409SSimon J. Gerraty acc = c;
10120957b409SSimon J. Gerraty }
10130957b409SSimon J. Gerraty z = !z;
10140957b409SSimon J. Gerraty }
10150957b409SSimon J. Gerraty if (z) {
10160957b409SSimon J. Gerraty fprintf(stderr, "invalid hexadecimal value (partial"
10170957b409SSimon J. Gerraty " byte) in '%s' (line %ld)\n",
10180957b409SSimon J. Gerraty name, linenum);
10190957b409SSimon J. Gerraty exit(EXIT_FAILURE);
10200957b409SSimon J. Gerraty }
10210957b409SSimon J. Gerraty if (buf == NULL) {
10220957b409SSimon J. Gerraty buf = xmalloc(ptr);
10230957b409SSimon J. Gerraty } else {
10240957b409SSimon J. Gerraty *len = ptr;
10250957b409SSimon J. Gerraty return buf;
10260957b409SSimon J. Gerraty }
10270957b409SSimon J. Gerraty }
10280957b409SSimon J. Gerraty }
10290957b409SSimon J. Gerraty
10300957b409SSimon J. Gerraty static char **
split_names(const char * value)10310957b409SSimon J. Gerraty split_names(const char *value)
10320957b409SSimon J. Gerraty {
10330957b409SSimon J. Gerraty char **names;
10340957b409SSimon J. Gerraty size_t len;
10350957b409SSimon J. Gerraty
10360957b409SSimon J. Gerraty names = NULL;
10370957b409SSimon J. Gerraty len = strlen(value);
10380957b409SSimon J. Gerraty for (;;) {
10390957b409SSimon J. Gerraty size_t u, ptr;
10400957b409SSimon J. Gerraty
10410957b409SSimon J. Gerraty ptr = 0;
10420957b409SSimon J. Gerraty u = 0;
10430957b409SSimon J. Gerraty while (u < len) {
10440957b409SSimon J. Gerraty size_t v;
10450957b409SSimon J. Gerraty
10460957b409SSimon J. Gerraty while (u < len && is_ws(value[u])) {
10470957b409SSimon J. Gerraty u ++;
10480957b409SSimon J. Gerraty }
10490957b409SSimon J. Gerraty v = u;
10500957b409SSimon J. Gerraty while (v < len && !is_ws(value[v])) {
10510957b409SSimon J. Gerraty v ++;
10520957b409SSimon J. Gerraty }
10530957b409SSimon J. Gerraty if (v > u) {
10540957b409SSimon J. Gerraty if (names != NULL) {
10550957b409SSimon J. Gerraty char *name;
10560957b409SSimon J. Gerraty
10570957b409SSimon J. Gerraty name = xmalloc(v - u + 1);
10580957b409SSimon J. Gerraty memcpy(name, value + u, v - u);
10590957b409SSimon J. Gerraty name[v - u] = 0;
10600957b409SSimon J. Gerraty names[ptr] = name;
10610957b409SSimon J. Gerraty }
10620957b409SSimon J. Gerraty ptr ++;
10630957b409SSimon J. Gerraty }
10640957b409SSimon J. Gerraty u = v;
10650957b409SSimon J. Gerraty }
10660957b409SSimon J. Gerraty if (names == NULL) {
10670957b409SSimon J. Gerraty names = xmalloc((ptr + 1) * sizeof *names);
10680957b409SSimon J. Gerraty } else {
10690957b409SSimon J. Gerraty names[ptr] = NULL;
10700957b409SSimon J. Gerraty return names;
10710957b409SSimon J. Gerraty }
10720957b409SSimon J. Gerraty }
10730957b409SSimon J. Gerraty }
10740957b409SSimon J. Gerraty
10750957b409SSimon J. Gerraty static int
string_to_hash(const char * name)10760957b409SSimon J. Gerraty string_to_hash(const char *name)
10770957b409SSimon J. Gerraty {
10780957b409SSimon J. Gerraty char tmp[20];
10790957b409SSimon J. Gerraty size_t u, v;
10800957b409SSimon J. Gerraty
10810957b409SSimon J. Gerraty for (u = 0, v = 0; name[u]; u ++) {
10820957b409SSimon J. Gerraty int c;
10830957b409SSimon J. Gerraty
10840957b409SSimon J. Gerraty c = name[u];
10850957b409SSimon J. Gerraty if ((c >= '0' && c <= '9')
10860957b409SSimon J. Gerraty || (c >= 'A' && c <= 'Z')
10870957b409SSimon J. Gerraty || (c >= 'a' && c <= 'z'))
10880957b409SSimon J. Gerraty {
10890957b409SSimon J. Gerraty tmp[v ++] = c;
10900957b409SSimon J. Gerraty if (v == sizeof tmp) {
10910957b409SSimon J. Gerraty return -1;
10920957b409SSimon J. Gerraty }
10930957b409SSimon J. Gerraty }
10940957b409SSimon J. Gerraty }
10950957b409SSimon J. Gerraty tmp[v] = 0;
10960957b409SSimon J. Gerraty if (eqstring(tmp, "md5")) {
10970957b409SSimon J. Gerraty return br_md5_ID;
10980957b409SSimon J. Gerraty } else if (eqstring(tmp, "sha1")) {
10990957b409SSimon J. Gerraty return br_sha1_ID;
11000957b409SSimon J. Gerraty } else if (eqstring(tmp, "sha224")) {
11010957b409SSimon J. Gerraty return br_sha224_ID;
11020957b409SSimon J. Gerraty } else if (eqstring(tmp, "sha256")) {
11030957b409SSimon J. Gerraty return br_sha256_ID;
11040957b409SSimon J. Gerraty } else if (eqstring(tmp, "sha384")) {
11050957b409SSimon J. Gerraty return br_sha384_ID;
11060957b409SSimon J. Gerraty } else if (eqstring(tmp, "sha512")) {
11070957b409SSimon J. Gerraty return br_sha512_ID;
11080957b409SSimon J. Gerraty } else {
11090957b409SSimon J. Gerraty return -1;
11100957b409SSimon J. Gerraty }
11110957b409SSimon J. Gerraty }
11120957b409SSimon J. Gerraty
11130957b409SSimon J. Gerraty static int
string_to_curve(const char * name)11140957b409SSimon J. Gerraty string_to_curve(const char *name)
11150957b409SSimon J. Gerraty {
11160957b409SSimon J. Gerraty char tmp[20];
11170957b409SSimon J. Gerraty size_t u, v;
11180957b409SSimon J. Gerraty
11190957b409SSimon J. Gerraty for (u = 0, v = 0; name[u]; u ++) {
11200957b409SSimon J. Gerraty int c;
11210957b409SSimon J. Gerraty
11220957b409SSimon J. Gerraty c = name[u];
11230957b409SSimon J. Gerraty if ((c >= '0' && c <= '9')
11240957b409SSimon J. Gerraty || (c >= 'A' && c <= 'Z')
11250957b409SSimon J. Gerraty || (c >= 'a' && c <= 'z'))
11260957b409SSimon J. Gerraty {
11270957b409SSimon J. Gerraty tmp[v ++] = c;
11280957b409SSimon J. Gerraty if (v == sizeof tmp) {
11290957b409SSimon J. Gerraty return -1;
11300957b409SSimon J. Gerraty }
11310957b409SSimon J. Gerraty }
11320957b409SSimon J. Gerraty }
11330957b409SSimon J. Gerraty tmp[v] = 0;
11340957b409SSimon J. Gerraty if (eqstring(tmp, "p256") || eqstring(tmp, "secp256r1")) {
11350957b409SSimon J. Gerraty return BR_EC_secp256r1;
11360957b409SSimon J. Gerraty } else if (eqstring(tmp, "p384") || eqstring(tmp, "secp384r1")) {
11370957b409SSimon J. Gerraty return BR_EC_secp384r1;
11380957b409SSimon J. Gerraty } else if (eqstring(tmp, "p521") || eqstring(tmp, "secp521r1")) {
11390957b409SSimon J. Gerraty return BR_EC_secp521r1;
11400957b409SSimon J. Gerraty } else {
11410957b409SSimon J. Gerraty return -1;
11420957b409SSimon J. Gerraty }
11430957b409SSimon J. Gerraty }
11440957b409SSimon J. Gerraty
11450957b409SSimon J. Gerraty static void
parse_object(char * objtype,HT * objdata,long linenum)11460957b409SSimon J. Gerraty parse_object(char *objtype, HT *objdata, long linenum)
11470957b409SSimon J. Gerraty {
11480957b409SSimon J. Gerraty char *name;
11490957b409SSimon J. Gerraty
11500957b409SSimon J. Gerraty name = get_value(objtype, objdata, linenum, "name");
11510957b409SSimon J. Gerraty if (eqstring(objtype, "key")) {
11520957b409SSimon J. Gerraty char *stype;
11530957b409SSimon J. Gerraty br_x509_pkey *pk;
11540957b409SSimon J. Gerraty
11550957b409SSimon J. Gerraty stype = get_value(objtype, objdata, linenum, "type");
11560957b409SSimon J. Gerraty pk = xmalloc(sizeof *pk);
11570957b409SSimon J. Gerraty if (eqstring(stype, "RSA")) {
11580957b409SSimon J. Gerraty char *sn, *se;
11590957b409SSimon J. Gerraty
11600957b409SSimon J. Gerraty sn = get_value(objtype, objdata, linenum, "n");
11610957b409SSimon J. Gerraty se = get_value(objtype, objdata, linenum, "e");
11620957b409SSimon J. Gerraty pk->key_type = BR_KEYTYPE_RSA;
11630957b409SSimon J. Gerraty pk->key.rsa.n = parse_hex("modulus", linenum,
11640957b409SSimon J. Gerraty sn, &pk->key.rsa.nlen);
11650957b409SSimon J. Gerraty pk->key.rsa.e = parse_hex("exponent", linenum,
11660957b409SSimon J. Gerraty se, &pk->key.rsa.elen);
11670957b409SSimon J. Gerraty } else if (eqstring(stype, "EC")) {
11680957b409SSimon J. Gerraty char *sc, *sq;
11690957b409SSimon J. Gerraty int curve;
11700957b409SSimon J. Gerraty
11710957b409SSimon J. Gerraty sc = get_value(objtype, objdata, linenum, "curve");
11720957b409SSimon J. Gerraty sq = get_value(objtype, objdata, linenum, "q");
11730957b409SSimon J. Gerraty curve = string_to_curve(sc);
11740957b409SSimon J. Gerraty if (curve < 0) {
11750957b409SSimon J. Gerraty fprintf(stderr, "unknown curve name: '%s'"
11760957b409SSimon J. Gerraty " (line %ld)\n", sc, linenum);
11770957b409SSimon J. Gerraty exit(EXIT_FAILURE);
11780957b409SSimon J. Gerraty }
11790957b409SSimon J. Gerraty pk->key_type = BR_KEYTYPE_EC;
11800957b409SSimon J. Gerraty pk->key.ec.curve = curve;
11810957b409SSimon J. Gerraty pk->key.ec.q = parse_hex("public point", linenum,
11820957b409SSimon J. Gerraty sq, &pk->key.ec.qlen);
11830957b409SSimon J. Gerraty } else {
11840957b409SSimon J. Gerraty fprintf(stderr, "unknown key type '%s' (line %ld)\n",
11850957b409SSimon J. Gerraty stype, linenum);
11860957b409SSimon J. Gerraty exit(EXIT_FAILURE);
11870957b409SSimon J. Gerraty }
11880957b409SSimon J. Gerraty if (HT_put(keys, name, pk) != NULL) {
11890957b409SSimon J. Gerraty fprintf(stderr, "duplicate key: '%s' (line %ld)\n",
11900957b409SSimon J. Gerraty name, linenum);
11910957b409SSimon J. Gerraty exit(EXIT_FAILURE);
11920957b409SSimon J. Gerraty }
11930957b409SSimon J. Gerraty } else if (eqstring(objtype, "anchor")) {
11940957b409SSimon J. Gerraty char *dnfile, *kname, *tatype;
11950957b409SSimon J. Gerraty test_trust_anchor *tta;
11960957b409SSimon J. Gerraty
11970957b409SSimon J. Gerraty dnfile = get_value(objtype, objdata, linenum, "DN_file");
11980957b409SSimon J. Gerraty kname = get_value(objtype, objdata, linenum, "key");
11990957b409SSimon J. Gerraty tatype = get_value(objtype, objdata, linenum, "type");
12000957b409SSimon J. Gerraty tta = xmalloc(sizeof *tta);
12010957b409SSimon J. Gerraty tta->dn = read_file(dnfile, &tta->dn_len);
12020957b409SSimon J. Gerraty tta->key_name = xstrdup(kname);
12030957b409SSimon J. Gerraty if (eqstring(tatype, "CA")) {
12040957b409SSimon J. Gerraty tta->flags = BR_X509_TA_CA;
12050957b409SSimon J. Gerraty } else if (eqstring(tatype, "EE")) {
12060957b409SSimon J. Gerraty tta->flags = 0;
12070957b409SSimon J. Gerraty } else {
12080957b409SSimon J. Gerraty fprintf(stderr,
12090957b409SSimon J. Gerraty "unknown trust anchor type: '%s' (line %ld)\n",
12100957b409SSimon J. Gerraty tatype, linenum);
12110957b409SSimon J. Gerraty }
12120957b409SSimon J. Gerraty if (HT_put(trust_anchors, name, tta) != NULL) {
12130957b409SSimon J. Gerraty fprintf(stderr,
12140957b409SSimon J. Gerraty "duplicate trust anchor: '%s' (line %ld)\n",
12150957b409SSimon J. Gerraty name, linenum);
12160957b409SSimon J. Gerraty exit(EXIT_FAILURE);
12170957b409SSimon J. Gerraty }
12180957b409SSimon J. Gerraty } else if (eqstring(objtype, "chain")) {
12190957b409SSimon J. Gerraty test_case tc;
12200957b409SSimon J. Gerraty char *ktype, *kusage, *sstatus, *shashes, *stime;
12210957b409SSimon J. Gerraty
12220957b409SSimon J. Gerraty ktype = get_value(objtype, objdata, linenum, "keytype");
12230957b409SSimon J. Gerraty kusage = get_value(objtype, objdata, linenum, "keyusage");
12240957b409SSimon J. Gerraty sstatus = get_value(objtype, objdata, linenum, "status");
12250957b409SSimon J. Gerraty tc.name = xstrdup(name);
12260957b409SSimon J. Gerraty tc.ta_names = split_names(
12270957b409SSimon J. Gerraty get_value(objtype, objdata, linenum, "anchors"));
12280957b409SSimon J. Gerraty tc.cert_names = split_names(
12290957b409SSimon J. Gerraty get_value(objtype, objdata, linenum, "chain"));
12300957b409SSimon J. Gerraty tc.servername = xstrdup(HT_get(objdata, "servername"));
12310957b409SSimon J. Gerraty if (eqstring(ktype, "RSA")) {
12320957b409SSimon J. Gerraty tc.key_type_usage = BR_KEYTYPE_RSA;
12330957b409SSimon J. Gerraty } else if (eqstring(ktype, "EC")) {
12340957b409SSimon J. Gerraty tc.key_type_usage = BR_KEYTYPE_EC;
12350957b409SSimon J. Gerraty } else {
12360957b409SSimon J. Gerraty fprintf(stderr,
12370957b409SSimon J. Gerraty "unknown key type: '%s' (line %ld)\n",
12380957b409SSimon J. Gerraty ktype, linenum);
12390957b409SSimon J. Gerraty exit(EXIT_FAILURE);
12400957b409SSimon J. Gerraty }
12410957b409SSimon J. Gerraty if (eqstring(kusage, "KEYX")) {
12420957b409SSimon J. Gerraty tc.key_type_usage |= BR_KEYTYPE_KEYX;
12430957b409SSimon J. Gerraty } else if (eqstring(kusage, "SIGN")) {
12440957b409SSimon J. Gerraty tc.key_type_usage |= BR_KEYTYPE_SIGN;
12450957b409SSimon J. Gerraty } else {
12460957b409SSimon J. Gerraty fprintf(stderr,
12470957b409SSimon J. Gerraty "unknown key usage: '%s' (line %ld)\n",
12480957b409SSimon J. Gerraty kusage, linenum);
12490957b409SSimon J. Gerraty exit(EXIT_FAILURE);
12500957b409SSimon J. Gerraty }
12510957b409SSimon J. Gerraty tc.status = (unsigned)atoi(sstatus);
12520957b409SSimon J. Gerraty if (tc.status == 0) {
12530957b409SSimon J. Gerraty tc.ee_key_name = xstrdup(
12540957b409SSimon J. Gerraty get_value(objtype, objdata, linenum, "eekey"));
12550957b409SSimon J. Gerraty } else {
12560957b409SSimon J. Gerraty tc.ee_key_name = NULL;
12570957b409SSimon J. Gerraty }
12580957b409SSimon J. Gerraty shashes = HT_get(objdata, "hashes");
12590957b409SSimon J. Gerraty if (shashes == NULL) {
12600957b409SSimon J. Gerraty tc.hashes = (unsigned)-1;
12610957b409SSimon J. Gerraty } else {
12620957b409SSimon J. Gerraty char **hns;
12630957b409SSimon J. Gerraty size_t u;
12640957b409SSimon J. Gerraty
12650957b409SSimon J. Gerraty tc.hashes = 0;
12660957b409SSimon J. Gerraty hns = split_names(shashes);
12670957b409SSimon J. Gerraty for (u = 0;; u ++) {
12680957b409SSimon J. Gerraty char *hn;
12690957b409SSimon J. Gerraty int id;
12700957b409SSimon J. Gerraty
12710957b409SSimon J. Gerraty hn = hns[u];
12720957b409SSimon J. Gerraty if (hn == NULL) {
12730957b409SSimon J. Gerraty break;
12740957b409SSimon J. Gerraty }
12750957b409SSimon J. Gerraty id = string_to_hash(hn);
12760957b409SSimon J. Gerraty if (id < 0) {
12770957b409SSimon J. Gerraty fprintf(stderr,
12780957b409SSimon J. Gerraty "unknown hash function '%s'"
12790957b409SSimon J. Gerraty " (line %ld)\n", hn, linenum);
12800957b409SSimon J. Gerraty exit(EXIT_FAILURE);
12810957b409SSimon J. Gerraty }
12820957b409SSimon J. Gerraty tc.hashes |= (unsigned)1 << id;
12830957b409SSimon J. Gerraty xfree(hn);
12840957b409SSimon J. Gerraty }
12850957b409SSimon J. Gerraty xfree(hns);
12860957b409SSimon J. Gerraty }
12870957b409SSimon J. Gerraty stime = HT_get(objdata, "time");
12880957b409SSimon J. Gerraty if (stime == NULL) {
12890957b409SSimon J. Gerraty stime = DEFAULT_TIME;
12900957b409SSimon J. Gerraty }
12910957b409SSimon J. Gerraty if (string_to_time(stime, &tc.days, &tc.seconds) < 0) {
12920957b409SSimon J. Gerraty fprintf(stderr, "invalid time string '%s' (line %ld)\n",
12930957b409SSimon J. Gerraty stime, linenum);
12940957b409SSimon J. Gerraty exit(EXIT_FAILURE);
12950957b409SSimon J. Gerraty }
12960957b409SSimon J. Gerraty if (all_chains_ptr == all_chains_len) {
12970957b409SSimon J. Gerraty if (all_chains_len == 0) {
12980957b409SSimon J. Gerraty all_chains_len = 8;
12990957b409SSimon J. Gerraty all_chains = xmalloc(
13000957b409SSimon J. Gerraty all_chains_len * sizeof *all_chains);
13010957b409SSimon J. Gerraty } else {
13020957b409SSimon J. Gerraty test_case *ntc;
13030957b409SSimon J. Gerraty size_t nlen;
13040957b409SSimon J. Gerraty
13050957b409SSimon J. Gerraty nlen = all_chains_len << 1;
13060957b409SSimon J. Gerraty ntc = xmalloc(nlen * sizeof *ntc);
13070957b409SSimon J. Gerraty memcpy(ntc, all_chains,
13080957b409SSimon J. Gerraty all_chains_len * sizeof *all_chains);
13090957b409SSimon J. Gerraty xfree(all_chains);
13100957b409SSimon J. Gerraty all_chains = ntc;
13110957b409SSimon J. Gerraty all_chains_len = nlen;
13120957b409SSimon J. Gerraty }
13130957b409SSimon J. Gerraty }
13140957b409SSimon J. Gerraty all_chains[all_chains_ptr ++] = tc;
13150957b409SSimon J. Gerraty } else {
13160957b409SSimon J. Gerraty fprintf(stderr, "unknown section type '%s' (line %ld)\n",
13170957b409SSimon J. Gerraty objtype, linenum);
13180957b409SSimon J. Gerraty exit(EXIT_FAILURE);
13190957b409SSimon J. Gerraty }
13200957b409SSimon J. Gerraty }
13210957b409SSimon J. Gerraty
13220957b409SSimon J. Gerraty static void
process_conf_file(const char * fname)13230957b409SSimon J. Gerraty process_conf_file(const char *fname)
13240957b409SSimon J. Gerraty {
13250957b409SSimon J. Gerraty char *objtype;
13260957b409SSimon J. Gerraty HT *objdata;
13270957b409SSimon J. Gerraty long objlinenum;
13280957b409SSimon J. Gerraty
13290957b409SSimon J. Gerraty keys = HT_new();
13300957b409SSimon J. Gerraty trust_anchors = HT_new();
13310957b409SSimon J. Gerraty all_chains = NULL;
13320957b409SSimon J. Gerraty all_chains_ptr = 0;
13330957b409SSimon J. Gerraty all_chains_len = 0;
13340957b409SSimon J. Gerraty conf_init(fname);
13350957b409SSimon J. Gerraty objtype = NULL;
13360957b409SSimon J. Gerraty objdata = HT_new();
13370957b409SSimon J. Gerraty objlinenum = 0;
13380957b409SSimon J. Gerraty for (;;) {
13390957b409SSimon J. Gerraty char *hname;
13400957b409SSimon J. Gerraty
13410957b409SSimon J. Gerraty if (conf_next_line() < 0) {
13420957b409SSimon J. Gerraty break;
13430957b409SSimon J. Gerraty }
13440957b409SSimon J. Gerraty hname = parse_header_name();
13450957b409SSimon J. Gerraty if (hname != NULL) {
13460957b409SSimon J. Gerraty if (objtype != NULL) {
13470957b409SSimon J. Gerraty parse_object(objtype, objdata, objlinenum);
13480957b409SSimon J. Gerraty HT_clear(objdata, xfree);
13490957b409SSimon J. Gerraty xfree(objtype);
13500957b409SSimon J. Gerraty }
13510957b409SSimon J. Gerraty objtype = hname;
13520957b409SSimon J. Gerraty objlinenum = current_linenum;
13530957b409SSimon J. Gerraty continue;
13540957b409SSimon J. Gerraty }
13550957b409SSimon J. Gerraty if (objtype == NULL) {
13560957b409SSimon J. Gerraty fprintf(stderr, "no current section (line %ld)\n",
13570957b409SSimon J. Gerraty current_linenum);
13580957b409SSimon J. Gerraty exit(EXIT_FAILURE);
13590957b409SSimon J. Gerraty }
13600957b409SSimon J. Gerraty if (parse_keyvalue(objdata) < 0) {
13610957b409SSimon J. Gerraty fprintf(stderr, "wrong configuration, line %ld\n",
13620957b409SSimon J. Gerraty current_linenum);
13630957b409SSimon J. Gerraty exit(EXIT_FAILURE);
13640957b409SSimon J. Gerraty }
13650957b409SSimon J. Gerraty }
13660957b409SSimon J. Gerraty if (objtype != NULL) {
13670957b409SSimon J. Gerraty parse_object(objtype, objdata, objlinenum);
13680957b409SSimon J. Gerraty xfree(objtype);
13690957b409SSimon J. Gerraty }
13700957b409SSimon J. Gerraty HT_free(objdata, xfree);
13710957b409SSimon J. Gerraty conf_close();
13720957b409SSimon J. Gerraty }
13730957b409SSimon J. Gerraty
13740957b409SSimon J. Gerraty static const struct {
13750957b409SSimon J. Gerraty int id;
13760957b409SSimon J. Gerraty const br_hash_class *impl;
13770957b409SSimon J. Gerraty } hash_impls[] = {
13780957b409SSimon J. Gerraty { br_md5_ID, &br_md5_vtable },
13790957b409SSimon J. Gerraty { br_sha1_ID, &br_sha1_vtable },
13800957b409SSimon J. Gerraty { br_sha224_ID, &br_sha224_vtable },
13810957b409SSimon J. Gerraty { br_sha256_ID, &br_sha256_vtable },
13820957b409SSimon J. Gerraty { br_sha384_ID, &br_sha384_vtable },
13830957b409SSimon J. Gerraty { br_sha512_ID, &br_sha512_vtable },
13840957b409SSimon J. Gerraty { 0, NULL }
13850957b409SSimon J. Gerraty };
13860957b409SSimon J. Gerraty
13870957b409SSimon J. Gerraty typedef struct {
13880957b409SSimon J. Gerraty unsigned char *data;
13890957b409SSimon J. Gerraty size_t len;
13900957b409SSimon J. Gerraty } blob;
13910957b409SSimon J. Gerraty
13920957b409SSimon J. Gerraty static int
eqbigint(const unsigned char * b1,size_t b1_len,const unsigned char * b2,size_t b2_len)13930957b409SSimon J. Gerraty eqbigint(const unsigned char *b1, size_t b1_len,
13940957b409SSimon J. Gerraty const unsigned char *b2, size_t b2_len)
13950957b409SSimon J. Gerraty {
13960957b409SSimon J. Gerraty while (b1_len > 0 && *b1 == 0) {
13970957b409SSimon J. Gerraty b1 ++;
13980957b409SSimon J. Gerraty b1_len --;
13990957b409SSimon J. Gerraty }
14000957b409SSimon J. Gerraty while (b2_len > 0 && *b2 == 0) {
14010957b409SSimon J. Gerraty b2 ++;
14020957b409SSimon J. Gerraty b2_len --;
14030957b409SSimon J. Gerraty }
14040957b409SSimon J. Gerraty return b1_len == b2_len && memcmp(b1, b2, b1_len) == 0;
14050957b409SSimon J. Gerraty }
14060957b409SSimon J. Gerraty
14070957b409SSimon J. Gerraty static int
eqpkey(const br_x509_pkey * pk1,const br_x509_pkey * pk2)14080957b409SSimon J. Gerraty eqpkey(const br_x509_pkey *pk1, const br_x509_pkey *pk2)
14090957b409SSimon J. Gerraty {
14100957b409SSimon J. Gerraty if (pk1 == pk2) {
14110957b409SSimon J. Gerraty return 1;
14120957b409SSimon J. Gerraty }
14130957b409SSimon J. Gerraty if (pk1 == NULL || pk2 == NULL) {
14140957b409SSimon J. Gerraty return 0;
14150957b409SSimon J. Gerraty }
14160957b409SSimon J. Gerraty if (pk1->key_type != pk2->key_type) {
14170957b409SSimon J. Gerraty return 0;
14180957b409SSimon J. Gerraty }
14190957b409SSimon J. Gerraty switch (pk1->key_type) {
14200957b409SSimon J. Gerraty case BR_KEYTYPE_RSA:
14210957b409SSimon J. Gerraty return eqbigint(pk1->key.rsa.n, pk1->key.rsa.nlen,
14220957b409SSimon J. Gerraty pk2->key.rsa.n, pk2->key.rsa.nlen)
14230957b409SSimon J. Gerraty && eqbigint(pk1->key.rsa.e, pk1->key.rsa.elen,
14240957b409SSimon J. Gerraty pk2->key.rsa.e, pk2->key.rsa.elen);
14250957b409SSimon J. Gerraty case BR_KEYTYPE_EC:
14260957b409SSimon J. Gerraty return pk1->key.ec.curve == pk2->key.ec.curve
14270957b409SSimon J. Gerraty && pk1->key.ec.qlen == pk2->key.ec.qlen
14280957b409SSimon J. Gerraty && memcmp(pk1->key.ec.q,
14290957b409SSimon J. Gerraty pk2->key.ec.q, pk1->key.ec.qlen) == 0;
14300957b409SSimon J. Gerraty default:
14310957b409SSimon J. Gerraty fprintf(stderr, "unknown key type: %d\n", pk1->key_type);
14320957b409SSimon J. Gerraty exit(EXIT_FAILURE);
14330957b409SSimon J. Gerraty break;
14340957b409SSimon J. Gerraty }
14350957b409SSimon J. Gerraty return 0;
14360957b409SSimon J. Gerraty }
14370957b409SSimon J. Gerraty
14380957b409SSimon J. Gerraty static size_t max_dp_usage;
14390957b409SSimon J. Gerraty static size_t max_rp_usage;
14400957b409SSimon J. Gerraty
1441*cc9e6590SSimon J. Gerraty static int
check_time(void * ctx,uint32_t nbd,uint32_t nbs,uint32_t nad,uint32_t nas)1442*cc9e6590SSimon J. Gerraty check_time(void *ctx, uint32_t nbd, uint32_t nbs, uint32_t nad, uint32_t nas)
1443*cc9e6590SSimon J. Gerraty {
1444*cc9e6590SSimon J. Gerraty test_case *tc;
1445*cc9e6590SSimon J. Gerraty
1446*cc9e6590SSimon J. Gerraty tc = ctx;
1447*cc9e6590SSimon J. Gerraty if (tc->days < nbd || (tc->days == nbd && tc->seconds < nbs)) {
1448*cc9e6590SSimon J. Gerraty return -1;
1449*cc9e6590SSimon J. Gerraty }
1450*cc9e6590SSimon J. Gerraty if (tc->days > nad || (tc->days == nad && tc->seconds > nas)) {
1451*cc9e6590SSimon J. Gerraty return 1;
1452*cc9e6590SSimon J. Gerraty }
1453*cc9e6590SSimon J. Gerraty return 0;
1454*cc9e6590SSimon J. Gerraty }
1455*cc9e6590SSimon J. Gerraty
14560957b409SSimon J. Gerraty static void
run_test_case(test_case * tc)14570957b409SSimon J. Gerraty run_test_case(test_case *tc)
14580957b409SSimon J. Gerraty {
14590957b409SSimon J. Gerraty br_x509_minimal_context ctx;
14600957b409SSimon J. Gerraty br_x509_trust_anchor *anchors;
14610957b409SSimon J. Gerraty size_t num_anchors;
14620957b409SSimon J. Gerraty size_t u;
14630957b409SSimon J. Gerraty const br_hash_class *dnhash;
14640957b409SSimon J. Gerraty size_t num_certs;
14650957b409SSimon J. Gerraty blob *certs;
14660957b409SSimon J. Gerraty br_x509_pkey *ee_pkey_ref;
14670957b409SSimon J. Gerraty const br_x509_pkey *ee_pkey;
14680957b409SSimon J. Gerraty unsigned usages;
14690957b409SSimon J. Gerraty unsigned status;
1470*cc9e6590SSimon J. Gerraty int j;
14710957b409SSimon J. Gerraty
14720957b409SSimon J. Gerraty printf("%s: ", tc->name);
14730957b409SSimon J. Gerraty fflush(stdout);
14740957b409SSimon J. Gerraty
14750957b409SSimon J. Gerraty /*
14760957b409SSimon J. Gerraty * Get the hash function to use for hashing DN. We can use just
14770957b409SSimon J. Gerraty * any supported hash function, but for the elegance of things,
14780957b409SSimon J. Gerraty * we will use one of the hash function implementations
14790957b409SSimon J. Gerraty * supported for this test case (with SHA-1 as fallback).
14800957b409SSimon J. Gerraty */
14810957b409SSimon J. Gerraty dnhash = &br_sha1_vtable;
14820957b409SSimon J. Gerraty for (u = 0; hash_impls[u].id; u ++) {
14830957b409SSimon J. Gerraty if ((tc->hashes & ((unsigned)1 << (hash_impls[u].id))) != 0) {
14840957b409SSimon J. Gerraty dnhash = hash_impls[u].impl;
14850957b409SSimon J. Gerraty }
14860957b409SSimon J. Gerraty }
14870957b409SSimon J. Gerraty
14880957b409SSimon J. Gerraty /*
14890957b409SSimon J. Gerraty * Get trust anchors.
14900957b409SSimon J. Gerraty */
14910957b409SSimon J. Gerraty for (num_anchors = 0; tc->ta_names[num_anchors]; num_anchors ++);
14920957b409SSimon J. Gerraty anchors = xmalloc(num_anchors * sizeof *anchors);
14930957b409SSimon J. Gerraty for (u = 0; tc->ta_names[u]; u ++) {
14940957b409SSimon J. Gerraty test_trust_anchor *tta;
14950957b409SSimon J. Gerraty br_x509_pkey *tak;
14960957b409SSimon J. Gerraty
14970957b409SSimon J. Gerraty tta = HT_get(trust_anchors, tc->ta_names[u]);
14980957b409SSimon J. Gerraty if (tta == NULL) {
14990957b409SSimon J. Gerraty fprintf(stderr, "no such trust anchor: '%s'\n",
15000957b409SSimon J. Gerraty tc->ta_names[u]);
15010957b409SSimon J. Gerraty exit(EXIT_FAILURE);
15020957b409SSimon J. Gerraty }
15030957b409SSimon J. Gerraty tak = HT_get(keys, tta->key_name);
15040957b409SSimon J. Gerraty if (tak == NULL) {
15050957b409SSimon J. Gerraty fprintf(stderr, "no such public key: '%s'\n",
15060957b409SSimon J. Gerraty tta->key_name);
15070957b409SSimon J. Gerraty exit(EXIT_FAILURE);
15080957b409SSimon J. Gerraty }
15090957b409SSimon J. Gerraty anchors[u].dn.data = tta->dn;
15100957b409SSimon J. Gerraty anchors[u].dn.len = tta->dn_len;
15110957b409SSimon J. Gerraty anchors[u].flags = tta->flags;
15120957b409SSimon J. Gerraty anchors[u].pkey = *tak;
15130957b409SSimon J. Gerraty }
15140957b409SSimon J. Gerraty
15150957b409SSimon J. Gerraty /*
15160957b409SSimon J. Gerraty * Read all relevant certificates.
15170957b409SSimon J. Gerraty */
15180957b409SSimon J. Gerraty for (num_certs = 0; tc->cert_names[num_certs]; num_certs ++);
15190957b409SSimon J. Gerraty certs = xmalloc(num_certs * sizeof *certs);
15200957b409SSimon J. Gerraty for (u = 0; u < num_certs; u ++) {
15210957b409SSimon J. Gerraty certs[u].data = read_file(tc->cert_names[u], &certs[u].len);
15220957b409SSimon J. Gerraty }
15230957b409SSimon J. Gerraty
15240957b409SSimon J. Gerraty /*
15250957b409SSimon J. Gerraty * Get expected EE public key (if any).
15260957b409SSimon J. Gerraty */
15270957b409SSimon J. Gerraty if (tc->ee_key_name == NULL) {
15280957b409SSimon J. Gerraty ee_pkey_ref = NULL;
15290957b409SSimon J. Gerraty } else {
15300957b409SSimon J. Gerraty ee_pkey_ref = HT_get(keys, tc->ee_key_name);
15310957b409SSimon J. Gerraty if (ee_pkey_ref == NULL) {
15320957b409SSimon J. Gerraty fprintf(stderr, "no such public key: '%s'\n",
15330957b409SSimon J. Gerraty tc->ee_key_name);
15340957b409SSimon J. Gerraty exit(EXIT_FAILURE);
15350957b409SSimon J. Gerraty }
15360957b409SSimon J. Gerraty }
15370957b409SSimon J. Gerraty
15380957b409SSimon J. Gerraty /*
1539*cc9e6590SSimon J. Gerraty * We do the test twice, to exercise distinct API functions.
1540*cc9e6590SSimon J. Gerraty */
1541*cc9e6590SSimon J. Gerraty for (j = 0; j < 2; j ++) {
1542*cc9e6590SSimon J. Gerraty /*
15430957b409SSimon J. Gerraty * Initialise the engine.
15440957b409SSimon J. Gerraty */
15450957b409SSimon J. Gerraty br_x509_minimal_init(&ctx, dnhash, anchors, num_anchors);
15460957b409SSimon J. Gerraty for (u = 0; hash_impls[u].id; u ++) {
15470957b409SSimon J. Gerraty int id;
15480957b409SSimon J. Gerraty
15490957b409SSimon J. Gerraty id = hash_impls[u].id;
15500957b409SSimon J. Gerraty if ((tc->hashes & ((unsigned)1 << id)) != 0) {
1551*cc9e6590SSimon J. Gerraty br_x509_minimal_set_hash(&ctx,
1552*cc9e6590SSimon J. Gerraty id, hash_impls[u].impl);
15530957b409SSimon J. Gerraty }
15540957b409SSimon J. Gerraty }
15550957b409SSimon J. Gerraty br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default());
15560957b409SSimon J. Gerraty br_x509_minimal_set_ecdsa(&ctx,
15570957b409SSimon J. Gerraty br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
15580957b409SSimon J. Gerraty
15590957b409SSimon J. Gerraty /*
15600957b409SSimon J. Gerraty * Set the validation date.
15610957b409SSimon J. Gerraty */
1562*cc9e6590SSimon J. Gerraty if (j == 0) {
15630957b409SSimon J. Gerraty br_x509_minimal_set_time(&ctx, tc->days, tc->seconds);
1564*cc9e6590SSimon J. Gerraty } else {
1565*cc9e6590SSimon J. Gerraty br_x509_minimal_set_time_callback(&ctx,
1566*cc9e6590SSimon J. Gerraty tc, &check_time);
1567*cc9e6590SSimon J. Gerraty }
15680957b409SSimon J. Gerraty
15690957b409SSimon J. Gerraty /*
15700957b409SSimon J. Gerraty * Put "canaries" to detect actual stack usage.
15710957b409SSimon J. Gerraty */
1572*cc9e6590SSimon J. Gerraty for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t);
1573*cc9e6590SSimon J. Gerraty u ++)
1574*cc9e6590SSimon J. Gerraty {
15750957b409SSimon J. Gerraty ctx.dp_stack[u] = 0xA7C083FE;
15760957b409SSimon J. Gerraty }
1577*cc9e6590SSimon J. Gerraty for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t);
1578*cc9e6590SSimon J. Gerraty u ++)
1579*cc9e6590SSimon J. Gerraty {
15800957b409SSimon J. Gerraty ctx.rp_stack[u] = 0xA7C083FE;
15810957b409SSimon J. Gerraty }
15820957b409SSimon J. Gerraty
15830957b409SSimon J. Gerraty /*
1584*cc9e6590SSimon J. Gerraty * Run the engine. We inject certificates by chunks of 100
1585*cc9e6590SSimon J. Gerraty * bytes in order to exercise the coroutine API.
15860957b409SSimon J. Gerraty */
15870957b409SSimon J. Gerraty ctx.vtable->start_chain(&ctx.vtable, tc->servername);
15880957b409SSimon J. Gerraty for (u = 0; u < num_certs; u ++) {
15890957b409SSimon J. Gerraty size_t v;
15900957b409SSimon J. Gerraty
15910957b409SSimon J. Gerraty ctx.vtable->start_cert(&ctx.vtable, certs[u].len);
15920957b409SSimon J. Gerraty v = 0;
15930957b409SSimon J. Gerraty while (v < certs[u].len) {
15940957b409SSimon J. Gerraty size_t w;
15950957b409SSimon J. Gerraty
15960957b409SSimon J. Gerraty w = certs[u].len - v;
15970957b409SSimon J. Gerraty if (w > 100) {
15980957b409SSimon J. Gerraty w = 100;
15990957b409SSimon J. Gerraty }
1600*cc9e6590SSimon J. Gerraty ctx.vtable->append(&ctx.vtable,
1601*cc9e6590SSimon J. Gerraty certs[u].data + v, w);
16020957b409SSimon J. Gerraty v += w;
16030957b409SSimon J. Gerraty }
16040957b409SSimon J. Gerraty ctx.vtable->end_cert(&ctx.vtable);
16050957b409SSimon J. Gerraty }
16060957b409SSimon J. Gerraty status = ctx.vtable->end_chain(&ctx.vtable);
16070957b409SSimon J. Gerraty ee_pkey = ctx.vtable->get_pkey(&ctx.vtable, &usages);
16080957b409SSimon J. Gerraty
16090957b409SSimon J. Gerraty /*
16100957b409SSimon J. Gerraty * Check key type and usage.
16110957b409SSimon J. Gerraty */
16120957b409SSimon J. Gerraty if (ee_pkey != NULL) {
16130957b409SSimon J. Gerraty unsigned ktu;
16140957b409SSimon J. Gerraty
16150957b409SSimon J. Gerraty ktu = ee_pkey->key_type | usages;
16160957b409SSimon J. Gerraty if (tc->key_type_usage != (ktu & tc->key_type_usage)) {
16170957b409SSimon J. Gerraty fprintf(stderr, "wrong key type + usage"
16180957b409SSimon J. Gerraty " (expected 0x%02X, got 0x%02X)\n",
16190957b409SSimon J. Gerraty tc->key_type_usage, ktu);
16200957b409SSimon J. Gerraty exit(EXIT_FAILURE);
16210957b409SSimon J. Gerraty }
16220957b409SSimon J. Gerraty }
16230957b409SSimon J. Gerraty
16240957b409SSimon J. Gerraty /*
16250957b409SSimon J. Gerraty * Check results. Note that we may still get a public key if
16260957b409SSimon J. Gerraty * the path is "not trusted" (but otherwise fine).
16270957b409SSimon J. Gerraty */
16280957b409SSimon J. Gerraty if (status != tc->status) {
16290957b409SSimon J. Gerraty fprintf(stderr, "wrong status (got %d, expected %d)\n",
16300957b409SSimon J. Gerraty status, tc->status);
16310957b409SSimon J. Gerraty exit(EXIT_FAILURE);
16320957b409SSimon J. Gerraty }
16330957b409SSimon J. Gerraty if (status == BR_ERR_X509_NOT_TRUSTED) {
16340957b409SSimon J. Gerraty ee_pkey = NULL;
16350957b409SSimon J. Gerraty }
16360957b409SSimon J. Gerraty if (!eqpkey(ee_pkey, ee_pkey_ref)) {
16370957b409SSimon J. Gerraty fprintf(stderr, "wrong EE public key\n");
16380957b409SSimon J. Gerraty exit(EXIT_FAILURE);
16390957b409SSimon J. Gerraty }
16400957b409SSimon J. Gerraty
16410957b409SSimon J. Gerraty /*
16420957b409SSimon J. Gerraty * Check stack usage.
16430957b409SSimon J. Gerraty */
1644*cc9e6590SSimon J. Gerraty for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t);
1645*cc9e6590SSimon J. Gerraty u > 0; u --)
1646*cc9e6590SSimon J. Gerraty {
16470957b409SSimon J. Gerraty if (ctx.dp_stack[u - 1] != 0xA7C083FE) {
16480957b409SSimon J. Gerraty if (max_dp_usage < u) {
16490957b409SSimon J. Gerraty max_dp_usage = u;
16500957b409SSimon J. Gerraty }
16510957b409SSimon J. Gerraty break;
16520957b409SSimon J. Gerraty }
16530957b409SSimon J. Gerraty }
1654*cc9e6590SSimon J. Gerraty for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t);
1655*cc9e6590SSimon J. Gerraty u > 0; u --)
1656*cc9e6590SSimon J. Gerraty {
16570957b409SSimon J. Gerraty if (ctx.rp_stack[u - 1] != 0xA7C083FE) {
16580957b409SSimon J. Gerraty if (max_rp_usage < u) {
16590957b409SSimon J. Gerraty max_rp_usage = u;
16600957b409SSimon J. Gerraty }
16610957b409SSimon J. Gerraty break;
16620957b409SSimon J. Gerraty }
16630957b409SSimon J. Gerraty }
1664*cc9e6590SSimon J. Gerraty }
16650957b409SSimon J. Gerraty
16660957b409SSimon J. Gerraty /*
16670957b409SSimon J. Gerraty * Release everything.
16680957b409SSimon J. Gerraty */
16690957b409SSimon J. Gerraty for (u = 0; u < num_certs; u ++) {
16700957b409SSimon J. Gerraty xfree(certs[u].data);
16710957b409SSimon J. Gerraty }
16720957b409SSimon J. Gerraty xfree(certs);
16730957b409SSimon J. Gerraty xfree(anchors);
16740957b409SSimon J. Gerraty printf("OK\n");
16750957b409SSimon J. Gerraty }
16760957b409SSimon J. Gerraty
16770957b409SSimon J. Gerraty /*
16780957b409SSimon J. Gerraty * A custom structure for tests, synchronised with the test certificate
16790957b409SSimon J. Gerraty * names.crt.
16800957b409SSimon J. Gerraty *
16810957b409SSimon J. Gerraty * If num is 1 or more, then this is a DN element with OID '1.1.1.1.num'.
16820957b409SSimon J. Gerraty * If num is -1 or less, then this is a SAN element of type -num.
16830957b409SSimon J. Gerraty * If num is 0, then this is a SAN element of type OtherName with
16840957b409SSimon J. Gerraty * OID 1.3.6.1.4.1.311.20.2.3 (Microsoft UPN).
16850957b409SSimon J. Gerraty */
16860957b409SSimon J. Gerraty typedef struct {
16870957b409SSimon J. Gerraty int num;
16880957b409SSimon J. Gerraty int status;
16890957b409SSimon J. Gerraty const char *expected;
16900957b409SSimon J. Gerraty } name_element_test;
16910957b409SSimon J. Gerraty
16920957b409SSimon J. Gerraty static name_element_test names_ref[] = {
16930957b409SSimon J. Gerraty /* === DN tests === */
16940957b409SSimon J. Gerraty {
16950957b409SSimon J. Gerraty /* [12] 66:6f:6f */
16960957b409SSimon J. Gerraty 1, 1, "foo"
16970957b409SSimon J. Gerraty },
16980957b409SSimon J. Gerraty {
16990957b409SSimon J. Gerraty /* [12] 62:61:72 */
17000957b409SSimon J. Gerraty 1, 1, "bar"
17010957b409SSimon J. Gerraty },
17020957b409SSimon J. Gerraty {
17030957b409SSimon J. Gerraty /* [18] 31:32:33:34 */
17040957b409SSimon J. Gerraty 2, 1, "1234"
17050957b409SSimon J. Gerraty },
17060957b409SSimon J. Gerraty {
17070957b409SSimon J. Gerraty /* [19] 66:6f:6f */
17080957b409SSimon J. Gerraty 3, 1, "foo"
17090957b409SSimon J. Gerraty },
17100957b409SSimon J. Gerraty {
17110957b409SSimon J. Gerraty /* [20] 66:6f:6f */
17120957b409SSimon J. Gerraty 4, 1, "foo"
17130957b409SSimon J. Gerraty },
17140957b409SSimon J. Gerraty {
17150957b409SSimon J. Gerraty /* [22] 66:6f:6f */
17160957b409SSimon J. Gerraty 5, 1, "foo"
17170957b409SSimon J. Gerraty },
17180957b409SSimon J. Gerraty {
17190957b409SSimon J. Gerraty /* [30] 00:66:00:6f:00:6f */
17200957b409SSimon J. Gerraty 6, 1, "foo"
17210957b409SSimon J. Gerraty },
17220957b409SSimon J. Gerraty {
17230957b409SSimon J. Gerraty /* [30] fe:ff:00:66:00:6f:00:6f */
17240957b409SSimon J. Gerraty 7, 1, "foo"
17250957b409SSimon J. Gerraty },
17260957b409SSimon J. Gerraty {
17270957b409SSimon J. Gerraty /* [30] ff:fe:66:00:6f:00:6f:00 */
17280957b409SSimon J. Gerraty 8, 1, "foo"
17290957b409SSimon J. Gerraty },
17300957b409SSimon J. Gerraty {
17310957b409SSimon J. Gerraty /* [20] 63:61:66:e9 */
17320957b409SSimon J. Gerraty 9, 1, "caf\xC3\xA9"
17330957b409SSimon J. Gerraty },
17340957b409SSimon J. Gerraty {
17350957b409SSimon J. Gerraty /* [12] 63:61:66:c3:a9 */
17360957b409SSimon J. Gerraty 10, 1, "caf\xC3\xA9"
17370957b409SSimon J. Gerraty },
17380957b409SSimon J. Gerraty {
17390957b409SSimon J. Gerraty /* [12] 63:61:66:e0:83:a9 */
17400957b409SSimon J. Gerraty 11, -1, NULL
17410957b409SSimon J. Gerraty },
17420957b409SSimon J. Gerraty {
17430957b409SSimon J. Gerraty /* [12] 63:61:66:e3:90:8c */
17440957b409SSimon J. Gerraty 12, 1, "caf\xE3\x90\x8C"
17450957b409SSimon J. Gerraty },
17460957b409SSimon J. Gerraty {
17470957b409SSimon J. Gerraty /* [30] 00:63:00:61:00:66:34:0c */
17480957b409SSimon J. Gerraty 13, 1, "caf\xE3\x90\x8C"
17490957b409SSimon J. Gerraty },
17500957b409SSimon J. Gerraty {
17510957b409SSimon J. Gerraty /* [12] 63:61:66:c3 */
17520957b409SSimon J. Gerraty 14, -1, NULL
17530957b409SSimon J. Gerraty },
17540957b409SSimon J. Gerraty {
17550957b409SSimon J. Gerraty /* [30] d8:42:df:f4:00:67:00:6f */
17560957b409SSimon J. Gerraty 15, 1, "\xF0\xA0\xAF\xB4go"
17570957b409SSimon J. Gerraty },
17580957b409SSimon J. Gerraty {
17590957b409SSimon J. Gerraty /* [30] 00:66:d8:42 */
17600957b409SSimon J. Gerraty 16, -1, NULL
17610957b409SSimon J. Gerraty },
17620957b409SSimon J. Gerraty {
17630957b409SSimon J. Gerraty /* [30] d8:42:00:66 */
17640957b409SSimon J. Gerraty 17, -1, NULL
17650957b409SSimon J. Gerraty },
17660957b409SSimon J. Gerraty {
17670957b409SSimon J. Gerraty /* [30] df:f4:00:66 */
17680957b409SSimon J. Gerraty 18, -1, NULL
17690957b409SSimon J. Gerraty },
17700957b409SSimon J. Gerraty {
17710957b409SSimon J. Gerraty /* [12] 66:00:6f */
17720957b409SSimon J. Gerraty 19, -1, NULL
17730957b409SSimon J. Gerraty },
17740957b409SSimon J. Gerraty {
17750957b409SSimon J. Gerraty /* [30] 00:00:34:0c */
17760957b409SSimon J. Gerraty 20, -1, NULL
17770957b409SSimon J. Gerraty },
17780957b409SSimon J. Gerraty {
17790957b409SSimon J. Gerraty /* [30] 34:0c:00:00:00:66 */
17800957b409SSimon J. Gerraty 21, -1, NULL
17810957b409SSimon J. Gerraty },
17820957b409SSimon J. Gerraty {
17830957b409SSimon J. Gerraty /* [12] ef:bb:bf:66:6f:6f */
17840957b409SSimon J. Gerraty 22, 1, "foo"
17850957b409SSimon J. Gerraty },
17860957b409SSimon J. Gerraty {
17870957b409SSimon J. Gerraty /* [30] 00:66:ff:fe:00:6f */
17880957b409SSimon J. Gerraty 23, -1, NULL
17890957b409SSimon J. Gerraty },
17900957b409SSimon J. Gerraty {
17910957b409SSimon J. Gerraty /* [30] 00:66:ff:fd:00:6f */
17920957b409SSimon J. Gerraty 24, 1, "f\xEF\xBF\xBDo"
17930957b409SSimon J. Gerraty },
17940957b409SSimon J. Gerraty
17950957b409SSimon J. Gerraty /* === Value not found in the DN === */
17960957b409SSimon J. Gerraty {
17970957b409SSimon J. Gerraty 127, 0, NULL
17980957b409SSimon J. Gerraty },
17990957b409SSimon J. Gerraty
18000957b409SSimon J. Gerraty /* === SAN tests === */
18010957b409SSimon J. Gerraty {
18020957b409SSimon J. Gerraty /* SAN OtherName (Microsoft UPN) */
18030957b409SSimon J. Gerraty 0, 1, "foo@bar.com"
18040957b409SSimon J. Gerraty },
18050957b409SSimon J. Gerraty {
18060957b409SSimon J. Gerraty /* SAN rfc822Name */
18070957b409SSimon J. Gerraty -1, 1, "bar@foo.com"
18080957b409SSimon J. Gerraty },
18090957b409SSimon J. Gerraty {
18100957b409SSimon J. Gerraty /* SAN dNSName */
18110957b409SSimon J. Gerraty -2, 1, "example.com"
18120957b409SSimon J. Gerraty },
18130957b409SSimon J. Gerraty {
18140957b409SSimon J. Gerraty /* SAN dNSName */
18150957b409SSimon J. Gerraty -2, 1, "www.example.com"
18160957b409SSimon J. Gerraty },
18170957b409SSimon J. Gerraty {
18180957b409SSimon J. Gerraty /* uniformResourceIdentifier */
18190957b409SSimon J. Gerraty -6, 1, "http://www.example.com/"
18200957b409SSimon J. Gerraty }
18210957b409SSimon J. Gerraty };
18220957b409SSimon J. Gerraty
18230957b409SSimon J. Gerraty static void
free_name_elements(br_name_element * elts,size_t num)18240957b409SSimon J. Gerraty free_name_elements(br_name_element *elts, size_t num)
18250957b409SSimon J. Gerraty {
18260957b409SSimon J. Gerraty size_t u;
18270957b409SSimon J. Gerraty
18280957b409SSimon J. Gerraty for (u = 0; u < num; u ++) {
18290957b409SSimon J. Gerraty xfree((void *)elts[u].oid);
18300957b409SSimon J. Gerraty xfree(elts[u].buf);
18310957b409SSimon J. Gerraty }
18320957b409SSimon J. Gerraty xfree(elts);
18330957b409SSimon J. Gerraty }
18340957b409SSimon J. Gerraty
18350957b409SSimon J. Gerraty static void
test_name_extraction(void)18360957b409SSimon J. Gerraty test_name_extraction(void)
18370957b409SSimon J. Gerraty {
18380957b409SSimon J. Gerraty unsigned char *data;
18390957b409SSimon J. Gerraty size_t len;
18400957b409SSimon J. Gerraty br_x509_minimal_context ctx;
18410957b409SSimon J. Gerraty uint32_t days, seconds;
18420957b409SSimon J. Gerraty size_t u;
18430957b409SSimon J. Gerraty unsigned status;
18440957b409SSimon J. Gerraty br_name_element *names;
18450957b409SSimon J. Gerraty size_t num_names;
18460957b409SSimon J. Gerraty int good;
18470957b409SSimon J. Gerraty
18480957b409SSimon J. Gerraty printf("Name extraction: ");
18490957b409SSimon J. Gerraty fflush(stdout);
18500957b409SSimon J. Gerraty data = read_file("names.crt", &len);
18510957b409SSimon J. Gerraty br_x509_minimal_init(&ctx, &br_sha256_vtable, NULL, 0);
18520957b409SSimon J. Gerraty for (u = 0; hash_impls[u].id; u ++) {
18530957b409SSimon J. Gerraty int id;
18540957b409SSimon J. Gerraty
18550957b409SSimon J. Gerraty id = hash_impls[u].id;
18560957b409SSimon J. Gerraty br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl);
18570957b409SSimon J. Gerraty }
18580957b409SSimon J. Gerraty br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default());
18590957b409SSimon J. Gerraty br_x509_minimal_set_ecdsa(&ctx,
18600957b409SSimon J. Gerraty br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
18610957b409SSimon J. Gerraty string_to_time(DEFAULT_TIME, &days, &seconds);
18620957b409SSimon J. Gerraty br_x509_minimal_set_time(&ctx, days, seconds);
18630957b409SSimon J. Gerraty
18640957b409SSimon J. Gerraty num_names = (sizeof names_ref) / (sizeof names_ref[0]);
18650957b409SSimon J. Gerraty names = xmalloc(num_names * sizeof *names);
18660957b409SSimon J. Gerraty for (u = 0; u < num_names; u ++) {
18670957b409SSimon J. Gerraty int num;
18680957b409SSimon J. Gerraty unsigned char *oid;
18690957b409SSimon J. Gerraty
18700957b409SSimon J. Gerraty num = names_ref[u].num;
18710957b409SSimon J. Gerraty if (num > 0) {
18720957b409SSimon J. Gerraty oid = xmalloc(5);
18730957b409SSimon J. Gerraty oid[0] = 4;
18740957b409SSimon J. Gerraty oid[1] = 0x29;
18750957b409SSimon J. Gerraty oid[2] = 0x01;
18760957b409SSimon J. Gerraty oid[3] = 0x01;
18770957b409SSimon J. Gerraty oid[4] = num;
18780957b409SSimon J. Gerraty } else if (num == 0) {
18790957b409SSimon J. Gerraty oid = xmalloc(13);
18800957b409SSimon J. Gerraty oid[0] = 0x00;
18810957b409SSimon J. Gerraty oid[1] = 0x00;
18820957b409SSimon J. Gerraty oid[2] = 0x0A;
18830957b409SSimon J. Gerraty oid[3] = 0x2B;
18840957b409SSimon J. Gerraty oid[4] = 0x06;
18850957b409SSimon J. Gerraty oid[5] = 0x01;
18860957b409SSimon J. Gerraty oid[6] = 0x04;
18870957b409SSimon J. Gerraty oid[7] = 0x01;
18880957b409SSimon J. Gerraty oid[8] = 0x82;
18890957b409SSimon J. Gerraty oid[9] = 0x37;
18900957b409SSimon J. Gerraty oid[10] = 0x14;
18910957b409SSimon J. Gerraty oid[11] = 0x02;
18920957b409SSimon J. Gerraty oid[12] = 0x03;
18930957b409SSimon J. Gerraty } else {
18940957b409SSimon J. Gerraty oid = xmalloc(2);
18950957b409SSimon J. Gerraty oid[0] = 0x00;
18960957b409SSimon J. Gerraty oid[1] = -num;
18970957b409SSimon J. Gerraty }
18980957b409SSimon J. Gerraty names[u].oid = oid;
18990957b409SSimon J. Gerraty names[u].buf = xmalloc(256);
19000957b409SSimon J. Gerraty names[u].len = 256;
19010957b409SSimon J. Gerraty }
19020957b409SSimon J. Gerraty br_x509_minimal_set_name_elements(&ctx, names, num_names);
19030957b409SSimon J. Gerraty
19040957b409SSimon J. Gerraty /*
19050957b409SSimon J. Gerraty * Put "canaries" to detect actual stack usage.
19060957b409SSimon J. Gerraty */
19070957b409SSimon J. Gerraty for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t); u ++) {
19080957b409SSimon J. Gerraty ctx.dp_stack[u] = 0xA7C083FE;
19090957b409SSimon J. Gerraty }
19100957b409SSimon J. Gerraty for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t); u ++) {
19110957b409SSimon J. Gerraty ctx.rp_stack[u] = 0xA7C083FE;
19120957b409SSimon J. Gerraty }
19130957b409SSimon J. Gerraty
19140957b409SSimon J. Gerraty /*
19150957b409SSimon J. Gerraty * Run the engine. Since we set no trust anchor, we expect a status
19160957b409SSimon J. Gerraty * of "not trusted".
19170957b409SSimon J. Gerraty */
19180957b409SSimon J. Gerraty ctx.vtable->start_chain(&ctx.vtable, NULL);
19190957b409SSimon J. Gerraty ctx.vtable->start_cert(&ctx.vtable, len);
19200957b409SSimon J. Gerraty ctx.vtable->append(&ctx.vtable, data, len);
19210957b409SSimon J. Gerraty ctx.vtable->end_cert(&ctx.vtable);
19220957b409SSimon J. Gerraty status = ctx.vtable->end_chain(&ctx.vtable);
19230957b409SSimon J. Gerraty if (status != BR_ERR_X509_NOT_TRUSTED) {
19240957b409SSimon J. Gerraty fprintf(stderr, "wrong status: %u\n", status);
19250957b409SSimon J. Gerraty exit(EXIT_FAILURE);
19260957b409SSimon J. Gerraty }
19270957b409SSimon J. Gerraty
19280957b409SSimon J. Gerraty /*
19290957b409SSimon J. Gerraty * Check stack usage.
19300957b409SSimon J. Gerraty */
19310957b409SSimon J. Gerraty for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t); u > 0; u --) {
19320957b409SSimon J. Gerraty if (ctx.dp_stack[u - 1] != 0xA7C083FE) {
19330957b409SSimon J. Gerraty if (max_dp_usage < u) {
19340957b409SSimon J. Gerraty max_dp_usage = u;
19350957b409SSimon J. Gerraty }
19360957b409SSimon J. Gerraty break;
19370957b409SSimon J. Gerraty }
19380957b409SSimon J. Gerraty }
19390957b409SSimon J. Gerraty for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t); u > 0; u --) {
19400957b409SSimon J. Gerraty if (ctx.rp_stack[u - 1] != 0xA7C083FE) {
19410957b409SSimon J. Gerraty if (max_rp_usage < u) {
19420957b409SSimon J. Gerraty max_rp_usage = u;
19430957b409SSimon J. Gerraty }
19440957b409SSimon J. Gerraty break;
19450957b409SSimon J. Gerraty }
19460957b409SSimon J. Gerraty }
19470957b409SSimon J. Gerraty
19480957b409SSimon J. Gerraty good = 1;
19490957b409SSimon J. Gerraty for (u = 0; u < num_names; u ++) {
19500957b409SSimon J. Gerraty if (names[u].status != names_ref[u].status) {
19510957b409SSimon J. Gerraty printf("ERR: name %u (id=%d): status=%d, expected=%d\n",
19520957b409SSimon J. Gerraty (unsigned)u, names_ref[u].num,
19530957b409SSimon J. Gerraty names[u].status, names_ref[u].status);
19540957b409SSimon J. Gerraty if (names[u].status > 0) {
19550957b409SSimon J. Gerraty unsigned char *p;
19560957b409SSimon J. Gerraty
19570957b409SSimon J. Gerraty printf(" obtained:");
19580957b409SSimon J. Gerraty p = (unsigned char *)names[u].buf;
19590957b409SSimon J. Gerraty while (*p) {
19600957b409SSimon J. Gerraty printf(" %02X", *p ++);
19610957b409SSimon J. Gerraty }
19620957b409SSimon J. Gerraty printf("\n");
19630957b409SSimon J. Gerraty }
19640957b409SSimon J. Gerraty good = 0;
19650957b409SSimon J. Gerraty continue;
19660957b409SSimon J. Gerraty }
19670957b409SSimon J. Gerraty if (names_ref[u].expected == NULL) {
19680957b409SSimon J. Gerraty if (names[u].buf[0] != 0) {
19690957b409SSimon J. Gerraty printf("ERR: name %u not zero-terminated\n",
19700957b409SSimon J. Gerraty (unsigned)u);
19710957b409SSimon J. Gerraty good = 0;
19720957b409SSimon J. Gerraty continue;
19730957b409SSimon J. Gerraty }
19740957b409SSimon J. Gerraty } else {
19750957b409SSimon J. Gerraty if (strcmp(names[u].buf, names_ref[u].expected) != 0) {
19760957b409SSimon J. Gerraty unsigned char *p;
19770957b409SSimon J. Gerraty
19780957b409SSimon J. Gerraty printf("ERR: name %u (id=%d): wrong value\n",
19790957b409SSimon J. Gerraty (unsigned)u, names_ref[u].num);
19800957b409SSimon J. Gerraty printf(" expected:");
19810957b409SSimon J. Gerraty p = (unsigned char *)names_ref[u].expected;
19820957b409SSimon J. Gerraty while (*p) {
19830957b409SSimon J. Gerraty printf(" %02X", *p ++);
19840957b409SSimon J. Gerraty }
19850957b409SSimon J. Gerraty printf("\n");
19860957b409SSimon J. Gerraty printf(" obtained:");
19870957b409SSimon J. Gerraty p = (unsigned char *)names[u].buf;
19880957b409SSimon J. Gerraty while (*p) {
19890957b409SSimon J. Gerraty printf(" %02X", *p ++);
19900957b409SSimon J. Gerraty }
19910957b409SSimon J. Gerraty printf("\n");
19920957b409SSimon J. Gerraty good = 0;
19930957b409SSimon J. Gerraty continue;
19940957b409SSimon J. Gerraty }
19950957b409SSimon J. Gerraty }
19960957b409SSimon J. Gerraty }
19970957b409SSimon J. Gerraty if (!good) {
19980957b409SSimon J. Gerraty exit(EXIT_FAILURE);
19990957b409SSimon J. Gerraty }
20000957b409SSimon J. Gerraty
20010957b409SSimon J. Gerraty /*
20020957b409SSimon J. Gerraty for (u = 0; u < num_names; u ++) {
20030957b409SSimon J. Gerraty printf("%u: (%d)", (unsigned)u, names[u].status);
20040957b409SSimon J. Gerraty if (names[u].status > 0) {
20050957b409SSimon J. Gerraty size_t v;
20060957b409SSimon J. Gerraty
20070957b409SSimon J. Gerraty for (v = 0; names[u].buf[v]; v ++) {
20080957b409SSimon J. Gerraty printf(" %02x", names[u].buf[v]);
20090957b409SSimon J. Gerraty }
20100957b409SSimon J. Gerraty }
20110957b409SSimon J. Gerraty printf("\n");
20120957b409SSimon J. Gerraty }
20130957b409SSimon J. Gerraty */
20140957b409SSimon J. Gerraty
20150957b409SSimon J. Gerraty xfree(data);
20160957b409SSimon J. Gerraty free_name_elements(names, num_names);
20170957b409SSimon J. Gerraty printf("OK\n");
20180957b409SSimon J. Gerraty }
20190957b409SSimon J. Gerraty
20200957b409SSimon J. Gerraty int
main(int argc,const char * argv[])20210957b409SSimon J. Gerraty main(int argc, const char *argv[])
20220957b409SSimon J. Gerraty {
20230957b409SSimon J. Gerraty size_t u;
20240957b409SSimon J. Gerraty
20250957b409SSimon J. Gerraty #ifdef SRCDIRNAME
20260957b409SSimon J. Gerraty /*
20270957b409SSimon J. Gerraty * We want to change the current directory to that of the
20280957b409SSimon J. Gerraty * executable, so that test files are reliably located. We
20290957b409SSimon J. Gerraty * do that only if SRCDIRNAME is defined (old Makefile would
20300957b409SSimon J. Gerraty * not do that).
20310957b409SSimon J. Gerraty */
20320957b409SSimon J. Gerraty if (argc >= 1) {
20330957b409SSimon J. Gerraty const char *arg, *c;
20340957b409SSimon J. Gerraty
20350957b409SSimon J. Gerraty arg = argv[0];
20360957b409SSimon J. Gerraty for (c = arg + strlen(arg);; c --) {
20370957b409SSimon J. Gerraty int sep, r;
20380957b409SSimon J. Gerraty
20390957b409SSimon J. Gerraty #ifdef _WIN32
20400957b409SSimon J. Gerraty sep = (*c == '/') || (*c == '\\');
20410957b409SSimon J. Gerraty #else
20420957b409SSimon J. Gerraty sep = (*c == '/');
20430957b409SSimon J. Gerraty #endif
20440957b409SSimon J. Gerraty if (sep) {
20450957b409SSimon J. Gerraty size_t len;
20460957b409SSimon J. Gerraty char *dn;
20470957b409SSimon J. Gerraty
20480957b409SSimon J. Gerraty len = 1 + (c - arg);
20490957b409SSimon J. Gerraty dn = xmalloc(len + 1);
20500957b409SSimon J. Gerraty memcpy(dn, arg, len);
20510957b409SSimon J. Gerraty dn[len] = 0;
20520957b409SSimon J. Gerraty #ifdef _WIN32
20530957b409SSimon J. Gerraty r = _chdir(dn);
20540957b409SSimon J. Gerraty #else
20550957b409SSimon J. Gerraty r = chdir(dn);
20560957b409SSimon J. Gerraty #endif
20570957b409SSimon J. Gerraty if (r != 0) {
20580957b409SSimon J. Gerraty fprintf(stderr, "warning: could not"
20590957b409SSimon J. Gerraty " set directory to '%s'\n", dn);
20600957b409SSimon J. Gerraty }
20610957b409SSimon J. Gerraty xfree(dn);
20620957b409SSimon J. Gerraty break;
20630957b409SSimon J. Gerraty }
20640957b409SSimon J. Gerraty if (c == arg) {
20650957b409SSimon J. Gerraty break;
20660957b409SSimon J. Gerraty }
20670957b409SSimon J. Gerraty }
20680957b409SSimon J. Gerraty }
20690957b409SSimon J. Gerraty #else
20700957b409SSimon J. Gerraty (void)argc;
20710957b409SSimon J. Gerraty (void)argv;
20720957b409SSimon J. Gerraty #endif
20730957b409SSimon J. Gerraty
20740957b409SSimon J. Gerraty process_conf_file(CONFFILE);
20750957b409SSimon J. Gerraty
20760957b409SSimon J. Gerraty max_dp_usage = 0;
20770957b409SSimon J. Gerraty max_rp_usage = 0;
20780957b409SSimon J. Gerraty for (u = 0; u < all_chains_ptr; u ++) {
20790957b409SSimon J. Gerraty run_test_case(&all_chains[u]);
20800957b409SSimon J. Gerraty }
20810957b409SSimon J. Gerraty test_name_extraction();
20820957b409SSimon J. Gerraty
20830957b409SSimon J. Gerraty printf("Maximum data stack usage: %u\n", (unsigned)max_dp_usage);
20840957b409SSimon J. Gerraty printf("Maximum return stack usage: %u\n", (unsigned)max_rp_usage);
20850957b409SSimon J. Gerraty
20860957b409SSimon J. Gerraty HT_free(keys, free_key);
20870957b409SSimon J. Gerraty HT_free(trust_anchors, free_trust_anchor);
20880957b409SSimon J. Gerraty for (u = 0; u < all_chains_ptr; u ++) {
20890957b409SSimon J. Gerraty free_test_case_contents(&all_chains[u]);
20900957b409SSimon J. Gerraty }
20910957b409SSimon J. Gerraty xfree(all_chains);
20920957b409SSimon J. Gerraty
20930957b409SSimon J. Gerraty return 0;
20940957b409SSimon J. Gerraty }
2095