xref: /freebsd/lib/libsecureboot/vets.c (revision ab4f0a15188087e407426aac2a720035fd2a3b0a)
15fff9558SSimon J. Gerraty /*-
25fff9558SSimon J. Gerraty  * Copyright (c) 2017-2018, Juniper Networks, Inc.
35fff9558SSimon J. Gerraty  *
45fff9558SSimon J. Gerraty  * Redistribution and use in source and binary forms, with or without
55fff9558SSimon J. Gerraty  * modification, are permitted provided that the following conditions
65fff9558SSimon J. Gerraty  * are met:
75fff9558SSimon J. Gerraty  * 1. Redistributions of source code must retain the above copyright
85fff9558SSimon J. Gerraty  *    notice, this list of conditions and the following disclaimer.
95fff9558SSimon J. Gerraty  * 2. Redistributions in binary form must reproduce the above copyright
105fff9558SSimon J. Gerraty  *    notice, this list of conditions and the following disclaimer in the
115fff9558SSimon J. Gerraty  *    documentation and/or other materials provided with the distribution.
125fff9558SSimon J. Gerraty  *
135fff9558SSimon J. Gerraty  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
145fff9558SSimon J. Gerraty  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
155fff9558SSimon J. Gerraty  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
165fff9558SSimon J. Gerraty  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
175fff9558SSimon J. Gerraty  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
185fff9558SSimon J. Gerraty  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
195fff9558SSimon J. Gerraty  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
205fff9558SSimon J. Gerraty  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
215fff9558SSimon J. Gerraty  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225fff9558SSimon J. Gerraty  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
235fff9558SSimon J. Gerraty  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245fff9558SSimon J. Gerraty  */
255fff9558SSimon J. Gerraty #include <sys/cdefs.h>
265fff9558SSimon J. Gerraty __FBSDID("$FreeBSD$");
275fff9558SSimon J. Gerraty 
285fff9558SSimon J. Gerraty /**
295fff9558SSimon J. Gerraty  * @file vets.c - trust store
305fff9558SSimon J. Gerraty  * @brief verify signatures
315fff9558SSimon J. Gerraty  *
325fff9558SSimon J. Gerraty  * We leverage code from BearSSL www.bearssl.org
335fff9558SSimon J. Gerraty  */
345fff9558SSimon J. Gerraty 
355fff9558SSimon J. Gerraty #include <sys/time.h>
365fff9558SSimon J. Gerraty #include <stdarg.h>
375fff9558SSimon J. Gerraty #define NEED_BRSSL_H
385fff9558SSimon J. Gerraty #include "libsecureboot-priv.h"
395fff9558SSimon J. Gerraty #include <brssl.h>
405fff9558SSimon J. Gerraty #include <ta.h>
415fff9558SSimon J. Gerraty 
425fff9558SSimon J. Gerraty #ifndef TRUST_ANCHOR_STR
435fff9558SSimon J. Gerraty # define TRUST_ANCHOR_STR ta_PEM
445fff9558SSimon J. Gerraty #endif
455fff9558SSimon J. Gerraty 
4666655411SSimon J. Gerraty #define EPOCH_YEAR		1970
4766655411SSimon J. Gerraty #define AVG_SECONDS_PER_YEAR	31556952L
485fff9558SSimon J. Gerraty #define SECONDS_PER_DAY		86400
4953f151f9SSimon J. Gerraty #define SECONDS_PER_YEAR	365 * SECONDS_PER_DAY
5053f151f9SSimon J. Gerraty #ifndef VE_UTC_MAX_JUMP
5153f151f9SSimon J. Gerraty # define VE_UTC_MAX_JUMP	20 * SECONDS_PER_YEAR
5253f151f9SSimon J. Gerraty #endif
535fff9558SSimon J. Gerraty #define X509_DAYS_TO_UTC0	719528
545fff9558SSimon J. Gerraty 
555fff9558SSimon J. Gerraty int DebugVe = 0;
565fff9558SSimon J. Gerraty 
5766655411SSimon J. Gerraty #ifndef VE_VERIFY_FLAGS
5866655411SSimon J. Gerraty # define VE_VERIFY_FLAGS VEF_VERBOSE
5966655411SSimon J. Gerraty #endif
6066655411SSimon J. Gerraty int VerifyFlags = VE_VERIFY_FLAGS;
6166655411SSimon J. Gerraty 
625fff9558SSimon J. Gerraty typedef VECTOR(br_x509_certificate) cert_list;
6313ea0450SMarcin Wojtas typedef VECTOR(hash_data) digest_list;
645fff9558SSimon J. Gerraty 
655fff9558SSimon J. Gerraty static anchor_list trust_anchors = VEC_INIT;
6613ea0450SMarcin Wojtas static anchor_list forbidden_anchors = VEC_INIT;
6713ea0450SMarcin Wojtas static digest_list forbidden_digests = VEC_INIT;
685fff9558SSimon J. Gerraty 
69f9510887SSimon J. Gerraty static int anchor_verbose = 0;
70f9510887SSimon J. Gerraty 
71f9510887SSimon J. Gerraty void
72f9510887SSimon J. Gerraty ve_anchor_verbose_set(int n)
73f9510887SSimon J. Gerraty {
74f9510887SSimon J. Gerraty 	anchor_verbose = n;
75f9510887SSimon J. Gerraty }
76f9510887SSimon J. Gerraty 
77f9510887SSimon J. Gerraty int
78f9510887SSimon J. Gerraty ve_anchor_verbose_get(void)
79f9510887SSimon J. Gerraty {
80f9510887SSimon J. Gerraty 	return (anchor_verbose);
81f9510887SSimon J. Gerraty }
82f9510887SSimon J. Gerraty 
835fff9558SSimon J. Gerraty void
845fff9558SSimon J. Gerraty ve_debug_set(int n)
855fff9558SSimon J. Gerraty {
865fff9558SSimon J. Gerraty 	DebugVe = n;
875fff9558SSimon J. Gerraty }
885fff9558SSimon J. Gerraty 
89*ab4f0a15SSimon J. Gerraty /*
90*ab4f0a15SSimon J. Gerraty  * For embedded systems (and boot loaders)
91*ab4f0a15SSimon J. Gerraty  * we do not want to enforce certificate validity post install.
92*ab4f0a15SSimon J. Gerraty  * It is generally unacceptible for infrastructure to stop working
93*ab4f0a15SSimon J. Gerraty  * just because it has not been updated recently.
94*ab4f0a15SSimon J. Gerraty  */
95*ab4f0a15SSimon J. Gerraty static int enforce_validity = 0;
96*ab4f0a15SSimon J. Gerraty 
97*ab4f0a15SSimon J. Gerraty void
98*ab4f0a15SSimon J. Gerraty ve_enforce_validity_set(int i)
99*ab4f0a15SSimon J. Gerraty {
100*ab4f0a15SSimon J. Gerraty     enforce_validity = i;
101*ab4f0a15SSimon J. Gerraty }
102*ab4f0a15SSimon J. Gerraty 
1035fff9558SSimon J. Gerraty static char ebuf[512];
1045fff9558SSimon J. Gerraty 
1055fff9558SSimon J. Gerraty char *
1065fff9558SSimon J. Gerraty ve_error_get(void)
1075fff9558SSimon J. Gerraty {
1085fff9558SSimon J. Gerraty 	return (ebuf);
1095fff9558SSimon J. Gerraty }
1105fff9558SSimon J. Gerraty 
1115fff9558SSimon J. Gerraty int
1125fff9558SSimon J. Gerraty ve_error_set(const char *fmt, ...)
1135fff9558SSimon J. Gerraty {
1145fff9558SSimon J. Gerraty 	int rc;
1155fff9558SSimon J. Gerraty 	va_list ap;
1165fff9558SSimon J. Gerraty 
1175fff9558SSimon J. Gerraty 	va_start(ap, fmt);
1185fff9558SSimon J. Gerraty 	ebuf[0] = '\0';
1195fff9558SSimon J. Gerraty 	rc = 0;
1205fff9558SSimon J. Gerraty 	if (fmt) {
1215fff9558SSimon J. Gerraty #ifdef STAND_H
1225fff9558SSimon J. Gerraty 		vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */
1235fff9558SSimon J. Gerraty 		ebuf[sizeof(ebuf) - 1] = '\0';
1245fff9558SSimon J. Gerraty 		rc = strlen(ebuf);
1255fff9558SSimon J. Gerraty #else
1265fff9558SSimon J. Gerraty 		rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap);
1275fff9558SSimon J. Gerraty #endif
1285fff9558SSimon J. Gerraty 	}
1295fff9558SSimon J. Gerraty 	va_end(ap);
1305fff9558SSimon J. Gerraty 	return (rc);
1315fff9558SSimon J. Gerraty }
1325fff9558SSimon J. Gerraty 
13366655411SSimon J. Gerraty #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
13466655411SSimon J. Gerraty 
13566655411SSimon J. Gerraty /*
13666655411SSimon J. Gerraty  * The *approximate* date.
13766655411SSimon J. Gerraty  *
13866655411SSimon J. Gerraty  * When certificate verification fails for being
13966655411SSimon J. Gerraty  * expired or not yet valid, it helps to indicate
14066655411SSimon J. Gerraty  * our current date.
14166655411SSimon J. Gerraty  * Since libsa lacks strftime and gmtime,
14266655411SSimon J. Gerraty  * this simple implementation suffices.
14366655411SSimon J. Gerraty  */
14466655411SSimon J. Gerraty static const char *
14566655411SSimon J. Gerraty gdate(char *buf, size_t bufsz, time_t clock)
14666655411SSimon J. Gerraty {
14766655411SSimon J. Gerraty 	int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
14866655411SSimon J. Gerraty 	int year, y, m, d;
14966655411SSimon J. Gerraty 
15066655411SSimon J. Gerraty 	y = clock / AVG_SECONDS_PER_YEAR;
15166655411SSimon J. Gerraty 	year = EPOCH_YEAR + y;
15266655411SSimon J. Gerraty 	for (y = EPOCH_YEAR; y < year; y++) {
15366655411SSimon J. Gerraty 		clock -= SECONDS_PER_YEAR;
15466655411SSimon J. Gerraty 		if (isleap(y))
15566655411SSimon J. Gerraty 			clock -= SECONDS_PER_DAY;
15666655411SSimon J. Gerraty 	}
15766655411SSimon J. Gerraty 	d = clock / SECONDS_PER_DAY;
15866655411SSimon J. Gerraty 	for (m = 0; d > 1 && m < 12; m++) {
15966655411SSimon J. Gerraty 		if (d > days[m]) {
16066655411SSimon J. Gerraty 			d -= days[m];
16166655411SSimon J. Gerraty 			if (m == 1 && d > 0 && isleap(year))
16266655411SSimon J. Gerraty 				d--;
16366655411SSimon J. Gerraty 		} else
16466655411SSimon J. Gerraty 			break;
16566655411SSimon J. Gerraty 	}
16666655411SSimon J. Gerraty 	d++;
16766655411SSimon J. Gerraty 	if (d > days[m]) {
16866655411SSimon J. Gerraty 	    d = 1;
16966655411SSimon J. Gerraty 	    m++;
17066655411SSimon J. Gerraty 	    if (m >= 12) {
17166655411SSimon J. Gerraty 		year++;
17266655411SSimon J. Gerraty 		m = 0;
17366655411SSimon J. Gerraty 	    }
17466655411SSimon J. Gerraty 	}
17566655411SSimon J. Gerraty 	(void)snprintf(buf, bufsz, "%04d-%02d-%02d", year, m+1, d);
17666655411SSimon J. Gerraty 	return(buf);
17766655411SSimon J. Gerraty }
17866655411SSimon J. Gerraty 
1795fff9558SSimon J. Gerraty /* this is the time we use for verifying certs */
18066655411SSimon J. Gerraty #ifdef UNIT_TEST
18166655411SSimon J. Gerraty extern time_t ve_utc;
18266655411SSimon J. Gerraty time_t ve_utc = 0;
18366655411SSimon J. Gerraty #else
1845fff9558SSimon J. Gerraty static time_t ve_utc = 0;
18566655411SSimon J. Gerraty #endif
1865fff9558SSimon J. Gerraty 
1875fff9558SSimon J. Gerraty /**
1885fff9558SSimon J. Gerraty  * @brief
1895fff9558SSimon J. Gerraty  * set ve_utc used for certificate verification
1905fff9558SSimon J. Gerraty  *
1915fff9558SSimon J. Gerraty  * @param[in] utc
19253f151f9SSimon J. Gerraty  *	time - ignored unless greater than current value
19353f151f9SSimon J. Gerraty  *	and not a leap of 20 years or more.
1945fff9558SSimon J. Gerraty  */
1955fff9558SSimon J. Gerraty void
1965fff9558SSimon J. Gerraty ve_utc_set(time_t utc)
1975fff9558SSimon J. Gerraty {
19853f151f9SSimon J. Gerraty 	if (utc > ve_utc &&
19953f151f9SSimon J. Gerraty 	    (ve_utc == 0 || (utc - ve_utc) < VE_UTC_MAX_JUMP)) {
2005fff9558SSimon J. Gerraty 		DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc));
2015fff9558SSimon J. Gerraty 		ve_utc = utc;
2025fff9558SSimon J. Gerraty 	}
2035fff9558SSimon J. Gerraty }
2045fff9558SSimon J. Gerraty 
2055fff9558SSimon J. Gerraty static void
2065fff9558SSimon J. Gerraty free_cert_contents(br_x509_certificate *xc)
2075fff9558SSimon J. Gerraty {
2085fff9558SSimon J. Gerraty 	xfree(xc->data);
2095fff9558SSimon J. Gerraty }
2105fff9558SSimon J. Gerraty 
211f9510887SSimon J. Gerraty /*
212f9510887SSimon J. Gerraty  * a bit of a dance to get commonName from a certificate
213f9510887SSimon J. Gerraty  */
214f9510887SSimon J. Gerraty static char *
215f9510887SSimon J. Gerraty x509_cn_get(br_x509_certificate *xc, char *buf, size_t len)
216f9510887SSimon J. Gerraty {
217f9510887SSimon J. Gerraty 	br_x509_minimal_context mc;
218f9510887SSimon J. Gerraty 	br_name_element cn;
219f9510887SSimon J. Gerraty 	unsigned char cn_oid[4];
220f9510887SSimon J. Gerraty 	int err;
221f9510887SSimon J. Gerraty 
222f9510887SSimon J. Gerraty 	if (buf == NULL)
223f9510887SSimon J. Gerraty 		return (buf);
224f9510887SSimon J. Gerraty 	/*
225f9510887SSimon J. Gerraty 	 * We want the commonName field
226f9510887SSimon J. Gerraty 	 * the OID we want is 2,5,4,3 - but DER encoded
227f9510887SSimon J. Gerraty 	 */
228f9510887SSimon J. Gerraty 	cn_oid[0] = 3;
229f9510887SSimon J. Gerraty 	cn_oid[1] = 0x55;
230f9510887SSimon J. Gerraty 	cn_oid[2] = 4;
231f9510887SSimon J. Gerraty 	cn_oid[3] = 3;
232f9510887SSimon J. Gerraty 	cn.oid = cn_oid;
233f9510887SSimon J. Gerraty 	cn.buf = buf;
234f9510887SSimon J. Gerraty 	cn.len = len;
235f9510887SSimon J. Gerraty 	cn.buf[0] = '\0';
236f9510887SSimon J. Gerraty 
237f9510887SSimon J. Gerraty 	br_x509_minimal_init(&mc, &br_sha256_vtable, NULL, 0);
238f9510887SSimon J. Gerraty 	br_x509_minimal_set_name_elements(&mc, &cn, 1);
239f9510887SSimon J. Gerraty 	/* the below actually does the work - updates cn.status */
240f9510887SSimon J. Gerraty 	mc.vtable->start_chain(&mc.vtable, NULL);
241f9510887SSimon J. Gerraty 	mc.vtable->start_cert(&mc.vtable, xc->data_len);
242f9510887SSimon J. Gerraty 	mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
243f9510887SSimon J. Gerraty 	mc.vtable->end_cert(&mc.vtable);
244f9510887SSimon J. Gerraty 	/* we don' actually care about cert status - just its name */
245f9510887SSimon J. Gerraty 	err = mc.vtable->end_chain(&mc.vtable);
246f9510887SSimon J. Gerraty 
247f9510887SSimon J. Gerraty 	if (!cn.status)
248f9510887SSimon J. Gerraty 		buf = NULL;
249f9510887SSimon J. Gerraty 	return (buf);
250f9510887SSimon J. Gerraty }
251f9510887SSimon J. Gerraty 
25213ea0450SMarcin Wojtas /* ASN parsing related defines */
25313ea0450SMarcin Wojtas #define ASN1_PRIMITIVE_TAG 0x1F
25413ea0450SMarcin Wojtas #define ASN1_INF_LENGTH    0x80
25513ea0450SMarcin Wojtas #define ASN1_LENGTH_MASK   0x7F
25613ea0450SMarcin Wojtas 
25713ea0450SMarcin Wojtas /*
25813ea0450SMarcin Wojtas  * Get TBS part of certificate.
25913ea0450SMarcin Wojtas  * Since BearSSL doesn't provide any API to do this,
26013ea0450SMarcin Wojtas  * it has to be implemented here.
2615fff9558SSimon J. Gerraty  */
26213ea0450SMarcin Wojtas static void*
26313ea0450SMarcin Wojtas X509_to_tbs(unsigned char* cert, size_t* output_size)
26413ea0450SMarcin Wojtas {
26513ea0450SMarcin Wojtas 	unsigned char *result;
26613ea0450SMarcin Wojtas 	size_t tbs_size;
26713ea0450SMarcin Wojtas 	int size, i;
26813ea0450SMarcin Wojtas 
26913ea0450SMarcin Wojtas 	if (cert == NULL)
27013ea0450SMarcin Wojtas 		return (NULL);
27113ea0450SMarcin Wojtas 
27213ea0450SMarcin Wojtas 	/* Strip two sequences to get to the TBS section */
27313ea0450SMarcin Wojtas 	for (i = 0; i < 2; i++) {
27413ea0450SMarcin Wojtas 		/*
27513ea0450SMarcin Wojtas 		 * XXX: We don't need to support extended tags since
27613ea0450SMarcin Wojtas 		 * they should not be present in certificates.
27713ea0450SMarcin Wojtas 		 */
27813ea0450SMarcin Wojtas 		if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG)
27913ea0450SMarcin Wojtas 			return (NULL);
28013ea0450SMarcin Wojtas 
28113ea0450SMarcin Wojtas 		cert++;
28213ea0450SMarcin Wojtas 
28313ea0450SMarcin Wojtas 		if (*cert == ASN1_INF_LENGTH)
28413ea0450SMarcin Wojtas 			return (NULL);
28513ea0450SMarcin Wojtas 
28613ea0450SMarcin Wojtas 		size = *cert & ASN1_LENGTH_MASK;
28713ea0450SMarcin Wojtas 		tbs_size = 0;
28813ea0450SMarcin Wojtas 
28913ea0450SMarcin Wojtas 		/* Size can either be stored on a single or multiple bytes */
29013ea0450SMarcin Wojtas 		if (*cert & (ASN1_LENGTH_MASK + 1)) {
29113ea0450SMarcin Wojtas 			cert++;
29213ea0450SMarcin Wojtas 			while (*cert == 0 && size > 0) {
29313ea0450SMarcin Wojtas 				cert++;
29413ea0450SMarcin Wojtas 				size--;
29513ea0450SMarcin Wojtas 			}
29613ea0450SMarcin Wojtas 			while (size-- > 0) {
29713ea0450SMarcin Wojtas 				tbs_size <<= 8;
29813ea0450SMarcin Wojtas 				tbs_size |= *(cert++);
29913ea0450SMarcin Wojtas 			}
30013ea0450SMarcin Wojtas 		}
30113ea0450SMarcin Wojtas 		if (i == 0)
30213ea0450SMarcin Wojtas 			result = cert;
30313ea0450SMarcin Wojtas 	}
30413ea0450SMarcin Wojtas 	tbs_size += (cert - result);
30513ea0450SMarcin Wojtas 
30613ea0450SMarcin Wojtas 	if (output_size != NULL)
30713ea0450SMarcin Wojtas 		*output_size = tbs_size;
30813ea0450SMarcin Wojtas 
30913ea0450SMarcin Wojtas 	return (result);
31013ea0450SMarcin Wojtas }
31113ea0450SMarcin Wojtas 
31213ea0450SMarcin Wojtas void
31313ea0450SMarcin Wojtas ve_forbidden_digest_add(hash_data *digest, size_t num)
31413ea0450SMarcin Wojtas {
31513ea0450SMarcin Wojtas 	while (num--)
31613ea0450SMarcin Wojtas 		VEC_ADD(forbidden_digests, digest[num]);
31713ea0450SMarcin Wojtas }
31813ea0450SMarcin Wojtas 
31913ea0450SMarcin Wojtas static size_t
320f9510887SSimon J. Gerraty ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors,
32118e2fbc0SSimon J. Gerraty     const char *anchors_name)
3225fff9558SSimon J. Gerraty {
3235fff9558SSimon J. Gerraty 	br_x509_trust_anchor ta;
3245fff9558SSimon J. Gerraty 	size_t u;
3255fff9558SSimon J. Gerraty 
3265fff9558SSimon J. Gerraty 	for (u = 0; u < num; u++) {
3275fff9558SSimon J. Gerraty 		if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
3285fff9558SSimon J. Gerraty 			break;
3295fff9558SSimon J. Gerraty 		}
33013ea0450SMarcin Wojtas 		VEC_ADD(*anchors, ta);
331f9510887SSimon J. Gerraty 		if (anchor_verbose && anchors_name) {
332f9510887SSimon J. Gerraty 			char buf[64];
333f9510887SSimon J. Gerraty 			char *cp;
334f9510887SSimon J. Gerraty 
335f9510887SSimon J. Gerraty 			cp = x509_cn_get(&xcs[u], buf, sizeof(buf));
336f9510887SSimon J. Gerraty 			if (cp) {
337f9510887SSimon J. Gerraty 				printf("x509_anchor(%s) %s\n", cp, anchors_name);
338f9510887SSimon J. Gerraty 			}
339f9510887SSimon J. Gerraty 		}
3405fff9558SSimon J. Gerraty 	}
3415fff9558SSimon J. Gerraty 	return (u);
3425fff9558SSimon J. Gerraty }
3435fff9558SSimon J. Gerraty 
3445fff9558SSimon J. Gerraty /**
3455fff9558SSimon J. Gerraty  * @brief
34613ea0450SMarcin Wojtas  * add certs to our trust store
34713ea0450SMarcin Wojtas  */
34813ea0450SMarcin Wojtas size_t
34913ea0450SMarcin Wojtas ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
35013ea0450SMarcin Wojtas {
351f9510887SSimon J. Gerraty 	return (ve_anchors_add(xcs, num, &trust_anchors, "trusted"));
35213ea0450SMarcin Wojtas }
35313ea0450SMarcin Wojtas 
35413ea0450SMarcin Wojtas size_t
35513ea0450SMarcin Wojtas ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num)
35613ea0450SMarcin Wojtas {
357f9510887SSimon J. Gerraty 	return (ve_anchors_add(xcs, num, &forbidden_anchors, "forbidden"));
358f9510887SSimon J. Gerraty }
359f9510887SSimon J. Gerraty 
360f9510887SSimon J. Gerraty 
361f9510887SSimon J. Gerraty /**
362f9510887SSimon J. Gerraty  * @brief add trust anchors in buf
363f9510887SSimon J. Gerraty  *
364f9510887SSimon J. Gerraty  * Assume buf contains x509 certificates, but if not and
365f9510887SSimon J. Gerraty  * we support OpenPGP try adding as that.
366f9510887SSimon J. Gerraty  *
367f9510887SSimon J. Gerraty  * @return number of anchors added
368f9510887SSimon J. Gerraty  */
369f9510887SSimon J. Gerraty size_t
370f9510887SSimon J. Gerraty ve_trust_anchors_add_buf(unsigned char *buf, size_t len)
371f9510887SSimon J. Gerraty {
372f9510887SSimon J. Gerraty 	br_x509_certificate *xcs;
373f9510887SSimon J. Gerraty 	size_t num;
374f9510887SSimon J. Gerraty 
375f9510887SSimon J. Gerraty 	num = 0;
376f9510887SSimon J. Gerraty 	xcs = parse_certificates(buf, len, &num);
377f9510887SSimon J. Gerraty 	if (xcs != NULL) {
378f9510887SSimon J. Gerraty 		num = ve_trust_anchors_add(xcs, num);
379f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
380f9510887SSimon J. Gerraty 	} else {
381f9510887SSimon J. Gerraty 		num = openpgp_trust_add_buf(buf, len);
382f9510887SSimon J. Gerraty #endif
383f9510887SSimon J. Gerraty 	}
384f9510887SSimon J. Gerraty 	return (num);
385f9510887SSimon J. Gerraty }
386f9510887SSimon J. Gerraty 
387f9510887SSimon J. Gerraty /**
388f9510887SSimon J. Gerraty  * @brief revoke trust anchors in buf
389f9510887SSimon J. Gerraty  *
390f9510887SSimon J. Gerraty  * Assume buf contains x509 certificates, but if not and
391f9510887SSimon J. Gerraty  * we support OpenPGP try revoking keyId
392f9510887SSimon J. Gerraty  *
393f9510887SSimon J. Gerraty  * @return number of anchors revoked
394f9510887SSimon J. Gerraty  */
395f9510887SSimon J. Gerraty size_t
396f9510887SSimon J. Gerraty ve_trust_anchors_revoke(unsigned char *buf, size_t len)
397f9510887SSimon J. Gerraty {
398f9510887SSimon J. Gerraty 	br_x509_certificate *xcs;
399f9510887SSimon J. Gerraty 	size_t num;
400f9510887SSimon J. Gerraty 
401f9510887SSimon J. Gerraty 	num = 0;
402f9510887SSimon J. Gerraty 	xcs = parse_certificates(buf, len, &num);
403f9510887SSimon J. Gerraty 	if (xcs != NULL) {
404f9510887SSimon J. Gerraty 		num = ve_forbidden_anchors_add(xcs, num);
405f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
406f9510887SSimon J. Gerraty 	} else {
407f9510887SSimon J. Gerraty 		if (buf[len - 1] == '\n')
408f9510887SSimon J. Gerraty 			buf[len - 1] = '\0';
409f9510887SSimon J. Gerraty 		num = openpgp_trust_revoke((char *)buf);
410f9510887SSimon J. Gerraty #endif
411f9510887SSimon J. Gerraty 	}
412f9510887SSimon J. Gerraty 	return (num);
41313ea0450SMarcin Wojtas }
41413ea0450SMarcin Wojtas 
41513ea0450SMarcin Wojtas /**
41613ea0450SMarcin Wojtas  * @brief
4175fff9558SSimon J. Gerraty  * initialize our trust_anchors from ta_PEM
4185fff9558SSimon J. Gerraty  */
4195fff9558SSimon J. Gerraty int
4205fff9558SSimon J. Gerraty ve_trust_init(void)
4215fff9558SSimon J. Gerraty {
4225fff9558SSimon J. Gerraty 	static int once = -1;
4235fff9558SSimon J. Gerraty 
4245fff9558SSimon J. Gerraty 	if (once >= 0)
4255fff9558SSimon J. Gerraty 		return (once);
4263ae2a848SSimon J. Gerraty 	once = 0;			/* to be sure */
4275fff9558SSimon J. Gerraty #ifdef BUILD_UTC
42853f151f9SSimon J. Gerraty 	ve_utc_set(BUILD_UTC);		/* ensure sanity */
4295fff9558SSimon J. Gerraty #endif
43053f151f9SSimon J. Gerraty 	ve_utc_set(time(NULL));
4315fff9558SSimon J. Gerraty 	ve_error_set(NULL);		/* make sure it is empty */
4325fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT
4335fff9558SSimon J. Gerraty 	ve_pcr_init();
4345fff9558SSimon J. Gerraty #endif
4355fff9558SSimon J. Gerraty 
4365fff9558SSimon J. Gerraty #ifdef TRUST_ANCHOR_STR
437e6ef5042SWojciech Macek 	if (TRUST_ANCHOR_STR != NULL && strlen(TRUST_ANCHOR_STR) != 0ul)
438e6ef5042SWojciech Macek 		ve_trust_anchors_add_buf(__DECONST(unsigned char *,
439e6ef5042SWojciech Macek 		    TRUST_ANCHOR_STR), sizeof(TRUST_ANCHOR_STR));
4405fff9558SSimon J. Gerraty #endif
44113ea0450SMarcin Wojtas 	once = (int) VEC_LEN(trust_anchors);
4429bee6a60SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
4439bee6a60SSimon J. Gerraty 	once += openpgp_trust_init();
4449bee6a60SSimon J. Gerraty #endif
44513ea0450SMarcin Wojtas 	return (once);
4465fff9558SSimon J. Gerraty }
4475fff9558SSimon J. Gerraty 
44866655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK
44966655411SSimon J. Gerraty static int
450cc9e6590SSimon J. Gerraty verify_time_cb(void *tctx __unused,
45166655411SSimon J. Gerraty     uint32_t not_before_days, uint32_t not_before_seconds,
45266655411SSimon J. Gerraty     uint32_t not_after_days, uint32_t not_after_seconds)
45366655411SSimon J. Gerraty {
45466655411SSimon J. Gerraty 	time_t not_before;
45566655411SSimon J. Gerraty 	time_t not_after;
45666655411SSimon J. Gerraty 	int rc;
45766655411SSimon J. Gerraty #ifdef UNIT_TEST
45866655411SSimon J. Gerraty 	char date[12], nb_date[12], na_date[12];
45966655411SSimon J. Gerraty #endif
46066655411SSimon J. Gerraty 
461*ab4f0a15SSimon J. Gerraty 	if (enforce_validity) {
46266655411SSimon J. Gerraty 		not_before = ((not_before_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_before_seconds;
46366655411SSimon J. Gerraty 		not_after =  ((not_after_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_after_seconds;
46466655411SSimon J. Gerraty 		if (ve_utc < not_before)
46566655411SSimon J. Gerraty 			rc = -1;
46666655411SSimon J. Gerraty 		else if (ve_utc > not_after)
46766655411SSimon J. Gerraty 			rc = 1;
46866655411SSimon J. Gerraty 		else
46966655411SSimon J. Gerraty 			rc = 0;
47066655411SSimon J. Gerraty #ifdef UNIT_TEST
47166655411SSimon J. Gerraty 		printf("notBefore %s notAfter %s date %s rc %d\n",
47266655411SSimon J. Gerraty 		    gdate(nb_date, sizeof(nb_date), not_before),
47366655411SSimon J. Gerraty 		    gdate(na_date, sizeof(na_date), not_after),
47466655411SSimon J. Gerraty 		    gdate(date, sizeof(date), ve_utc), rc);
47566655411SSimon J. Gerraty #endif
476*ab4f0a15SSimon J. Gerraty 	} else
47766655411SSimon J. Gerraty 		rc = 0;			/* don't fail */
47866655411SSimon J. Gerraty 	return rc;
47966655411SSimon J. Gerraty }
48066655411SSimon J. Gerraty #endif
48166655411SSimon J. Gerraty 
4825fff9558SSimon J. Gerraty /**
4835fff9558SSimon J. Gerraty  * if we can verify the certificate chain in "certs",
4845fff9558SSimon J. Gerraty  * return the public key and if "xcp" is !NULL the associated
4855fff9558SSimon J. Gerraty  * certificate
4865fff9558SSimon J. Gerraty  */
4875fff9558SSimon J. Gerraty static br_x509_pkey *
4885fff9558SSimon J. Gerraty verify_signer_xcs(br_x509_certificate *xcs,
4895fff9558SSimon J. Gerraty     size_t num,
49013ea0450SMarcin Wojtas     br_name_element *elts, size_t num_elts,
49113ea0450SMarcin Wojtas     anchor_list *anchors)
4925fff9558SSimon J. Gerraty {
4935fff9558SSimon J. Gerraty 	br_x509_minimal_context mc;
4945fff9558SSimon J. Gerraty 	br_x509_certificate *xc;
4955fff9558SSimon J. Gerraty 	size_t u;
4965fff9558SSimon J. Gerraty 	cert_list chain = VEC_INIT;
4975fff9558SSimon J. Gerraty 	const br_x509_pkey *tpk;
4985fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
4995fff9558SSimon J. Gerraty 	unsigned int usages;
5005fff9558SSimon J. Gerraty 	int err;
5015fff9558SSimon J. Gerraty 
5025fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num));
5035fff9558SSimon J. Gerraty 	VEC_ADDMANY(chain, xcs, num);
5045fff9558SSimon J. Gerraty 	if (VEC_LEN(chain) == 0) {
5055fff9558SSimon J. Gerraty 		ve_error_set("ERROR: no/invalid certificate chain\n");
5065fff9558SSimon J. Gerraty 		return (NULL);
5075fff9558SSimon J. Gerraty 	}
5085fff9558SSimon J. Gerraty 
5095fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n",
51013ea0450SMarcin Wojtas 		VEC_LEN(*anchors)));
5115fff9558SSimon J. Gerraty 
5125fff9558SSimon J. Gerraty 	br_x509_minimal_init(&mc, &br_sha256_vtable,
51313ea0450SMarcin Wojtas 	    &VEC_ELT(*anchors, 0),
51413ea0450SMarcin Wojtas 	    VEC_LEN(*anchors));
5155fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
5165fff9558SSimon J. Gerraty 	br_x509_minimal_set_ecdsa(&mc,
5175fff9558SSimon J. Gerraty 	    &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
5185fff9558SSimon J. Gerraty #endif
5195fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
5205fff9558SSimon J. Gerraty 	br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
5215fff9558SSimon J. Gerraty #endif
5225fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
5235fff9558SSimon J. Gerraty 	/* This is deprecated! do not enable unless you absoultely have to */
5245fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable);
5255fff9558SSimon J. Gerraty #endif
5265fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable);
5275fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT
5285fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable);
5295fff9558SSimon J. Gerraty #endif
5305fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT
5315fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable);
5325fff9558SSimon J. Gerraty #endif
5335fff9558SSimon J. Gerraty 	br_x509_minimal_set_name_elements(&mc, elts, num_elts);
5345fff9558SSimon J. Gerraty 
53566655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK
53666655411SSimon J. Gerraty 	br_x509_minimal_set_time_callback(&mc, NULL, verify_time_cb);
53766655411SSimon J. Gerraty #else
53866655411SSimon J. Gerraty #if defined(_STANDALONE) || defined(UNIT_TEST)
5395fff9558SSimon J. Gerraty 	/*
5405fff9558SSimon J. Gerraty 	 * Clock is probably bogus so we use ve_utc.
5415fff9558SSimon J. Gerraty 	 */
5425fff9558SSimon J. Gerraty 	mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0;
5435fff9558SSimon J. Gerraty 	mc.seconds = (ve_utc % SECONDS_PER_DAY);
5445fff9558SSimon J. Gerraty #endif
54566655411SSimon J. Gerraty #endif
5465fff9558SSimon J. Gerraty 	mc.vtable->start_chain(&mc.vtable, NULL);
5475fff9558SSimon J. Gerraty 	for (u = 0; u < VEC_LEN(chain); u ++) {
5485fff9558SSimon J. Gerraty 		xc = &VEC_ELT(chain, u);
5495fff9558SSimon J. Gerraty 		mc.vtable->start_cert(&mc.vtable, xc->data_len);
5505fff9558SSimon J. Gerraty 		mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
5515fff9558SSimon J. Gerraty 		mc.vtable->end_cert(&mc.vtable);
5525fff9558SSimon J. Gerraty 		switch (mc.err) {
5535fff9558SSimon J. Gerraty 		case 0:
5545fff9558SSimon J. Gerraty 		case BR_ERR_X509_OK:
5555fff9558SSimon J. Gerraty 		case BR_ERR_X509_EXPIRED:
5565fff9558SSimon J. Gerraty 			break;
5575fff9558SSimon J. Gerraty 		default:
5585fff9558SSimon J. Gerraty 			printf("u=%zu mc.err=%d\n", u, mc.err);
5595fff9558SSimon J. Gerraty 			break;
5605fff9558SSimon J. Gerraty 		}
5615fff9558SSimon J. Gerraty 	}
5625fff9558SSimon J. Gerraty 	err = mc.vtable->end_chain(&mc.vtable);
5635fff9558SSimon J. Gerraty 	pk = NULL;
5645fff9558SSimon J. Gerraty 	if (err) {
56566655411SSimon J. Gerraty 		char date[12];
56666655411SSimon J. Gerraty 
56766655411SSimon J. Gerraty 		switch (err) {
56866655411SSimon J. Gerraty 		case 54:
56966655411SSimon J. Gerraty 			ve_error_set("Validation failed, certificate not valid as of %s",
57066655411SSimon J. Gerraty 			    gdate(date, sizeof(date), ve_utc));
57166655411SSimon J. Gerraty 			break;
57266655411SSimon J. Gerraty 		default:
5735fff9558SSimon J. Gerraty 			ve_error_set("Validation failed, err = %d", err);
57466655411SSimon J. Gerraty 			break;
57566655411SSimon J. Gerraty 		}
5765fff9558SSimon J. Gerraty 	} else {
5775fff9558SSimon J. Gerraty 		tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
5785fff9558SSimon J. Gerraty 		if (tpk != NULL) {
5795fff9558SSimon J. Gerraty 			pk = xpkeydup(tpk);
5805fff9558SSimon J. Gerraty 		}
5815fff9558SSimon J. Gerraty 	}
58213ea0450SMarcin Wojtas 	VEC_CLEAR(chain);
5835fff9558SSimon J. Gerraty 	return (pk);
5845fff9558SSimon J. Gerraty }
5855fff9558SSimon J. Gerraty 
58613ea0450SMarcin Wojtas /*
58713ea0450SMarcin Wojtas  * Check if digest of one of the certificates from verified chain
58813ea0450SMarcin Wojtas  * is present in the forbidden database.
58913ea0450SMarcin Wojtas  * Since UEFI allows to store three types of digests
59013ea0450SMarcin Wojtas  * all of them have to be checked separately.
59113ea0450SMarcin Wojtas  */
59213ea0450SMarcin Wojtas static int
59313ea0450SMarcin Wojtas check_forbidden_digests(br_x509_certificate *xcs, size_t num)
59413ea0450SMarcin Wojtas {
59513ea0450SMarcin Wojtas 	unsigned char sha256_digest[br_sha256_SIZE];
59613ea0450SMarcin Wojtas 	unsigned char sha384_digest[br_sha384_SIZE];
59713ea0450SMarcin Wojtas 	unsigned char sha512_digest[br_sha512_SIZE];
59813ea0450SMarcin Wojtas 	void *tbs;
59913ea0450SMarcin Wojtas 	hash_data *digest;
60013ea0450SMarcin Wojtas 	br_hash_compat_context ctx;
60113ea0450SMarcin Wojtas 	const br_hash_class *md;
60213ea0450SMarcin Wojtas 	size_t tbs_len, i;
60313ea0450SMarcin Wojtas 	int have_sha256, have_sha384, have_sha512;
60413ea0450SMarcin Wojtas 
60513ea0450SMarcin Wojtas 	if (VEC_LEN(forbidden_digests) == 0)
60613ea0450SMarcin Wojtas 		return (0);
60713ea0450SMarcin Wojtas 
60813ea0450SMarcin Wojtas 	/*
60913ea0450SMarcin Wojtas 	 * Iterate through certificates, extract their To-Be-Signed section,
61013ea0450SMarcin Wojtas 	 * and compare its digest against the ones in the forbidden database.
61113ea0450SMarcin Wojtas 	 */
61213ea0450SMarcin Wojtas 	while (num--) {
61313ea0450SMarcin Wojtas 		tbs = X509_to_tbs(xcs[num].data, &tbs_len);
61413ea0450SMarcin Wojtas 		if (tbs == NULL) {
61513ea0450SMarcin Wojtas 			printf("Failed to obtain TBS part of certificate\n");
61613ea0450SMarcin Wojtas 			return (1);
61713ea0450SMarcin Wojtas 		}
61813ea0450SMarcin Wojtas 		have_sha256 = have_sha384 = have_sha512 = 0;
61913ea0450SMarcin Wojtas 
62013ea0450SMarcin Wojtas 		for (i = 0; i < VEC_LEN(forbidden_digests); i++) {
62113ea0450SMarcin Wojtas 			digest = &VEC_ELT(forbidden_digests, i);
62213ea0450SMarcin Wojtas 			switch (digest->hash_size) {
62313ea0450SMarcin Wojtas 			case br_sha256_SIZE:
62413ea0450SMarcin Wojtas 				if (!have_sha256) {
62513ea0450SMarcin Wojtas 					have_sha256 = 1;
62613ea0450SMarcin Wojtas 					md = &br_sha256_vtable;
62713ea0450SMarcin Wojtas 					md->init(&ctx.vtable);
62813ea0450SMarcin Wojtas 					md->update(&ctx.vtable, tbs, tbs_len);
62913ea0450SMarcin Wojtas 					md->out(&ctx.vtable, sha256_digest);
63013ea0450SMarcin Wojtas 				}
63113ea0450SMarcin Wojtas 				if (!memcmp(sha256_digest,
63213ea0450SMarcin Wojtas 					digest->data,
63313ea0450SMarcin Wojtas 					br_sha256_SIZE))
63413ea0450SMarcin Wojtas 					return (1);
63513ea0450SMarcin Wojtas 
63613ea0450SMarcin Wojtas 				break;
63713ea0450SMarcin Wojtas 			case br_sha384_SIZE:
63813ea0450SMarcin Wojtas 				if (!have_sha384) {
63913ea0450SMarcin Wojtas 					have_sha384 = 1;
64013ea0450SMarcin Wojtas 					md = &br_sha384_vtable;
64113ea0450SMarcin Wojtas 					md->init(&ctx.vtable);
64213ea0450SMarcin Wojtas 					md->update(&ctx.vtable, tbs, tbs_len);
64313ea0450SMarcin Wojtas 					md->out(&ctx.vtable, sha384_digest);
64413ea0450SMarcin Wojtas 				}
64513ea0450SMarcin Wojtas 				if (!memcmp(sha384_digest,
64613ea0450SMarcin Wojtas 					digest->data,
64713ea0450SMarcin Wojtas 					br_sha384_SIZE))
64813ea0450SMarcin Wojtas 					return (1);
64913ea0450SMarcin Wojtas 
65013ea0450SMarcin Wojtas 				break;
65113ea0450SMarcin Wojtas 			case br_sha512_SIZE:
65213ea0450SMarcin Wojtas 				if (!have_sha512) {
65313ea0450SMarcin Wojtas 					have_sha512 = 1;
65413ea0450SMarcin Wojtas 					md = &br_sha512_vtable;
65513ea0450SMarcin Wojtas 					md->init(&ctx.vtable);
65613ea0450SMarcin Wojtas 					md->update(&ctx.vtable, tbs, tbs_len);
65713ea0450SMarcin Wojtas 					md->out(&ctx.vtable, sha512_digest);
65813ea0450SMarcin Wojtas 				}
65913ea0450SMarcin Wojtas 				if (!memcmp(sha512_digest,
66013ea0450SMarcin Wojtas 					digest->data,
66113ea0450SMarcin Wojtas 					br_sha512_SIZE))
66213ea0450SMarcin Wojtas 					return (1);
66313ea0450SMarcin Wojtas 
66413ea0450SMarcin Wojtas 				break;
66513ea0450SMarcin Wojtas 			}
66613ea0450SMarcin Wojtas 		}
66713ea0450SMarcin Wojtas 	}
66813ea0450SMarcin Wojtas 
66913ea0450SMarcin Wojtas 	return (0);
67013ea0450SMarcin Wojtas }
67113ea0450SMarcin Wojtas 
6725fff9558SSimon J. Gerraty static br_x509_pkey *
6735fff9558SSimon J. Gerraty verify_signer(const char *certs,
6745fff9558SSimon J. Gerraty     br_name_element *elts, size_t num_elts)
6755fff9558SSimon J. Gerraty {
6765fff9558SSimon J. Gerraty 	br_x509_certificate *xcs;
6775fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
6785fff9558SSimon J. Gerraty 	size_t num;
6795fff9558SSimon J. Gerraty 
68013ea0450SMarcin Wojtas 	pk = NULL;
68113ea0450SMarcin Wojtas 
6825fff9558SSimon J. Gerraty 	ve_trust_init();
6835fff9558SSimon J. Gerraty 	xcs = read_certificates(certs, &num);
6845fff9558SSimon J. Gerraty 	if (xcs == NULL) {
6855fff9558SSimon J. Gerraty 		ve_error_set("cannot read certificates\n");
6865fff9558SSimon J. Gerraty 		return (NULL);
6875fff9558SSimon J. Gerraty 	}
68813ea0450SMarcin Wojtas 
68913ea0450SMarcin Wojtas 	/*
69013ea0450SMarcin Wojtas 	 * Check if either
69113ea0450SMarcin Wojtas 	 * 1. There is a direct match between cert from forbidden_anchors
69213ea0450SMarcin Wojtas 	 * and a cert from chain.
69313ea0450SMarcin Wojtas 	 * 2. CA that signed the chain is found in forbidden_anchors.
69413ea0450SMarcin Wojtas 	 */
69513ea0450SMarcin Wojtas 	if (VEC_LEN(forbidden_anchors) > 0)
69613ea0450SMarcin Wojtas 		pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors);
69713ea0450SMarcin Wojtas 	if (pk != NULL) {
69813ea0450SMarcin Wojtas 		ve_error_set("Certificate is on forbidden list\n");
69913ea0450SMarcin Wojtas 		xfreepkey(pk);
70013ea0450SMarcin Wojtas 		pk = NULL;
70113ea0450SMarcin Wojtas 		goto out;
70213ea0450SMarcin Wojtas 	}
70313ea0450SMarcin Wojtas 
70413ea0450SMarcin Wojtas 	pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors);
70513ea0450SMarcin Wojtas 	if (pk == NULL)
70613ea0450SMarcin Wojtas 		goto out;
70713ea0450SMarcin Wojtas 
70813ea0450SMarcin Wojtas 	/*
70913ea0450SMarcin Wojtas 	 * Check if hash of tbs part of any certificate in chain
71013ea0450SMarcin Wojtas 	 * is on the forbidden list.
71113ea0450SMarcin Wojtas 	 */
71213ea0450SMarcin Wojtas 	if (check_forbidden_digests(xcs, num)) {
71313ea0450SMarcin Wojtas 		ve_error_set("Certificate hash is on forbidden list\n");
71413ea0450SMarcin Wojtas 		xfreepkey(pk);
71513ea0450SMarcin Wojtas 		pk = NULL;
71613ea0450SMarcin Wojtas 	}
71713ea0450SMarcin Wojtas out:
71813ea0450SMarcin Wojtas 	free_certificates(xcs, num);
7195fff9558SSimon J. Gerraty 	return (pk);
7205fff9558SSimon J. Gerraty }
7215fff9558SSimon J. Gerraty 
7225fff9558SSimon J. Gerraty /**
7235fff9558SSimon J. Gerraty  * we need a hex digest including trailing newline below
7245fff9558SSimon J. Gerraty  */
7255fff9558SSimon J. Gerraty char *
7265fff9558SSimon J. Gerraty hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len)
7275fff9558SSimon J. Gerraty {
7285fff9558SSimon J. Gerraty 	char const hex2ascii[] = "0123456789abcdef";
7295fff9558SSimon J. Gerraty 	size_t i;
7305fff9558SSimon J. Gerraty 
7315fff9558SSimon J. Gerraty 	/* every binary byte is 2 chars in hex + newline + null  */
7325fff9558SSimon J. Gerraty 	if (bufsz < (2 * foo_len) + 2)
7335fff9558SSimon J. Gerraty 		return (NULL);
7345fff9558SSimon J. Gerraty 
7355fff9558SSimon J. Gerraty 	for (i = 0; i < foo_len; i++) {
7365fff9558SSimon J. Gerraty 		buf[i * 2] = hex2ascii[foo[i] >> 4];
7375fff9558SSimon J. Gerraty 		buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f];
7385fff9558SSimon J. Gerraty 	}
7395fff9558SSimon J. Gerraty 
7405fff9558SSimon J. Gerraty 	buf[i * 2] = 0x0A; /* we also want a newline */
7415fff9558SSimon J. Gerraty 	buf[i * 2 + 1] = '\0';
7425fff9558SSimon J. Gerraty 
7435fff9558SSimon J. Gerraty 	return (buf);
7445fff9558SSimon J. Gerraty }
7455fff9558SSimon J. Gerraty 
7465fff9558SSimon J. Gerraty /**
7475fff9558SSimon J. Gerraty  * @brief
7485fff9558SSimon J. Gerraty  * verify file against sigfile using pk
7495fff9558SSimon J. Gerraty  *
7505fff9558SSimon J. Gerraty  * When we generated the signature in sigfile,
7515fff9558SSimon J. Gerraty  * we hashed (sha256) file, and sent that to signing server
7525fff9558SSimon J. Gerraty  * which hashed (sha256) that hash.
7535fff9558SSimon J. Gerraty  *
7545fff9558SSimon J. Gerraty  * To verify we need to replicate that result.
7555fff9558SSimon J. Gerraty  *
7565fff9558SSimon J. Gerraty  * @param[in] pk
7575fff9558SSimon J. Gerraty  *	br_x509_pkey
7585fff9558SSimon J. Gerraty  *
7595fff9558SSimon J. Gerraty  * @paramp[in] file
7605fff9558SSimon J. Gerraty  *	file to be verified
7615fff9558SSimon J. Gerraty  *
7625fff9558SSimon J. Gerraty  * @param[in] sigfile
7635fff9558SSimon J. Gerraty  * 	signature (PEM encoded)
7645fff9558SSimon J. Gerraty  *
7655fff9558SSimon J. Gerraty  * @return NULL on error, otherwise content of file.
7665fff9558SSimon J. Gerraty  */
7675fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
7685fff9558SSimon J. Gerraty static unsigned char *
7695fff9558SSimon J. Gerraty verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile)
7705fff9558SSimon J. Gerraty {
7710e47020fSSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN
7720e47020fSSimon J. Gerraty 	char *hex, hexbuf[br_sha512_SIZE * 2 + 2];
7730e47020fSSimon J. Gerraty #endif
7745fff9558SSimon J. Gerraty 	unsigned char rhbuf[br_sha512_SIZE];
7755fff9558SSimon J. Gerraty 	br_sha256_context ctx;
7765fff9558SSimon J. Gerraty 	unsigned char *fcp, *scp;
7775fff9558SSimon J. Gerraty 	size_t flen, slen, plen;
7785fff9558SSimon J. Gerraty 	pem_object *po;
7795fff9558SSimon J. Gerraty 	const br_ec_impl *ec;
7805fff9558SSimon J. Gerraty 	br_ecdsa_vrfy vrfy;
7815fff9558SSimon J. Gerraty 
7825fff9558SSimon J. Gerraty 	if ((fcp = read_file(file, &flen)) == NULL)
7835fff9558SSimon J. Gerraty 		return (NULL);
7845fff9558SSimon J. Gerraty 	if ((scp = read_file(sigfile, &slen)) == NULL) {
7855fff9558SSimon J. Gerraty 		free(fcp);
7865fff9558SSimon J. Gerraty 		return (NULL);
7875fff9558SSimon J. Gerraty 	}
7885fff9558SSimon J. Gerraty 	if ((po = decode_pem(scp, slen, &plen)) == NULL) {
7895fff9558SSimon J. Gerraty 		free(fcp);
7905fff9558SSimon J. Gerraty 		free(scp);
7915fff9558SSimon J. Gerraty 		return (NULL);
7925fff9558SSimon J. Gerraty 	}
7935fff9558SSimon J. Gerraty 	br_sha256_init(&ctx);
7945fff9558SSimon J. Gerraty 	br_sha256_update(&ctx, fcp, flen);
7955fff9558SSimon J. Gerraty 	br_sha256_out(&ctx, rhbuf);
796f9510887SSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN
7975fff9558SSimon J. Gerraty 	hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE);
7985fff9558SSimon J. Gerraty 	/* now hash that */
7995fff9558SSimon J. Gerraty 	if (hex) {
8005fff9558SSimon J. Gerraty 		br_sha256_init(&ctx);
8015fff9558SSimon J. Gerraty 		br_sha256_update(&ctx, hex, strlen(hex));
8025fff9558SSimon J. Gerraty 		br_sha256_out(&ctx, rhbuf);
8035fff9558SSimon J. Gerraty 	}
804f9510887SSimon J. Gerraty #endif
8055fff9558SSimon J. Gerraty 	ec = br_ec_get_default();
8065fff9558SSimon J. Gerraty 	vrfy = br_ecdsa_vrfy_asn1_get_default();
8075fff9558SSimon J. Gerraty 	if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data,
8085fff9558SSimon J. Gerraty 		po->data_len)) {
8095fff9558SSimon J. Gerraty 		free(fcp);
8105fff9558SSimon J. Gerraty 		fcp = NULL;
8115fff9558SSimon J. Gerraty 	}
8125fff9558SSimon J. Gerraty 	free(scp);
8135fff9558SSimon J. Gerraty 	return (fcp);
8145fff9558SSimon J. Gerraty }
8155fff9558SSimon J. Gerraty #endif
8165fff9558SSimon J. Gerraty 
8175fff9558SSimon J. Gerraty #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT)
8185fff9558SSimon J. Gerraty /**
8195fff9558SSimon J. Gerraty  * @brief verify an rsa digest
8205fff9558SSimon J. Gerraty  *
8215fff9558SSimon J. Gerraty  * @return 0 on failure
8225fff9558SSimon J. Gerraty  */
8235fff9558SSimon J. Gerraty int
8245fff9558SSimon J. Gerraty verify_rsa_digest (br_rsa_public_key *pkey,
8255fff9558SSimon J. Gerraty     const unsigned char *hash_oid,
8265fff9558SSimon J. Gerraty     unsigned char *mdata, size_t mlen,
8275fff9558SSimon J. Gerraty     unsigned char *sdata, size_t slen)
8285fff9558SSimon J. Gerraty {
8295fff9558SSimon J. Gerraty 	br_rsa_pkcs1_vrfy vrfy;
8305fff9558SSimon J. Gerraty 	unsigned char vhbuf[br_sha512_SIZE];
8315fff9558SSimon J. Gerraty 
8325fff9558SSimon J. Gerraty 	vrfy = br_rsa_pkcs1_vrfy_get_default();
8335fff9558SSimon J. Gerraty 
8345fff9558SSimon J. Gerraty 	if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) ||
8355fff9558SSimon J. Gerraty 	    memcmp(vhbuf, mdata, mlen) != 0) {
8365fff9558SSimon J. Gerraty 		return (0);		/* fail */
8375fff9558SSimon J. Gerraty 	}
8385fff9558SSimon J. Gerraty 	return (1);			/* ok */
8395fff9558SSimon J. Gerraty }
8405fff9558SSimon J. Gerraty #endif
8415fff9558SSimon J. Gerraty 
8425fff9558SSimon J. Gerraty /**
8435fff9558SSimon J. Gerraty  * @brief
8445fff9558SSimon J. Gerraty  * verify file against sigfile using pk
8455fff9558SSimon J. Gerraty  *
8465fff9558SSimon J. Gerraty  * When we generated the signature in sigfile,
8475fff9558SSimon J. Gerraty  * we hashed (sha256) file, and sent that to signing server
8485fff9558SSimon J. Gerraty  * which hashed (sha256) that hash.
8495fff9558SSimon J. Gerraty  *
8505fff9558SSimon J. Gerraty  * Or (deprecated) we simply used sha1 hash directly.
8515fff9558SSimon J. Gerraty  *
8525fff9558SSimon J. Gerraty  * To verify we need to replicate that result.
8535fff9558SSimon J. Gerraty  *
8545fff9558SSimon J. Gerraty  * @param[in] pk
8555fff9558SSimon J. Gerraty  *	br_x509_pkey
8565fff9558SSimon J. Gerraty  *
8575fff9558SSimon J. Gerraty  * @paramp[in] file
8585fff9558SSimon J. Gerraty  *	file to be verified
8595fff9558SSimon J. Gerraty  *
8605fff9558SSimon J. Gerraty  * @param[in] sigfile
8615fff9558SSimon J. Gerraty  * 	signature (PEM encoded)
8625fff9558SSimon J. Gerraty  *
8635fff9558SSimon J. Gerraty  * @return NULL on error, otherwise content of file.
8645fff9558SSimon J. Gerraty  */
8655fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
8665fff9558SSimon J. Gerraty static unsigned char *
8675fff9558SSimon J. Gerraty verify_rsa(br_x509_pkey *pk,  const char *file, const char *sigfile)
8685fff9558SSimon J. Gerraty {
8695fff9558SSimon J. Gerraty 	unsigned char rhbuf[br_sha512_SIZE];
8705fff9558SSimon J. Gerraty 	const unsigned char *hash_oid;
8715fff9558SSimon J. Gerraty 	const br_hash_class *md;
8725fff9558SSimon J. Gerraty 	br_hash_compat_context mctx;
8735fff9558SSimon J. Gerraty 	unsigned char *fcp, *scp;
8745fff9558SSimon J. Gerraty 	size_t flen, slen, plen, hlen;
8755fff9558SSimon J. Gerraty 	pem_object *po;
8765fff9558SSimon J. Gerraty 
8775fff9558SSimon J. Gerraty 	if ((fcp = read_file(file, &flen)) == NULL)
8785fff9558SSimon J. Gerraty 		return (NULL);
8795fff9558SSimon J. Gerraty 	if ((scp = read_file(sigfile, &slen)) == NULL) {
8805fff9558SSimon J. Gerraty 		free(fcp);
8815fff9558SSimon J. Gerraty 		return (NULL);
8825fff9558SSimon J. Gerraty 	}
8835fff9558SSimon J. Gerraty 	if ((po = decode_pem(scp, slen, &plen)) == NULL) {
8845fff9558SSimon J. Gerraty 		free(fcp);
8855fff9558SSimon J. Gerraty 		free(scp);
8865fff9558SSimon J. Gerraty 		return (NULL);
8875fff9558SSimon J. Gerraty 	}
8885fff9558SSimon J. Gerraty 
8895fff9558SSimon J. Gerraty 	switch (po->data_len) {
8905fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
8915fff9558SSimon J. Gerraty 	case 256:
8925fff9558SSimon J. Gerraty 		// this is our old deprecated sig method
8935fff9558SSimon J. Gerraty 		md = &br_sha1_vtable;
8945fff9558SSimon J. Gerraty 		hlen = br_sha1_SIZE;
8955fff9558SSimon J. Gerraty 		hash_oid = BR_HASH_OID_SHA1;
8965fff9558SSimon J. Gerraty 		break;
8975fff9558SSimon J. Gerraty #endif
8985fff9558SSimon J. Gerraty 	default:
8995fff9558SSimon J. Gerraty 		md = &br_sha256_vtable;
9005fff9558SSimon J. Gerraty 		hlen = br_sha256_SIZE;
9015fff9558SSimon J. Gerraty 		hash_oid = BR_HASH_OID_SHA256;
9025fff9558SSimon J. Gerraty 		break;
9035fff9558SSimon J. Gerraty 	}
9045fff9558SSimon J. Gerraty 	md->init(&mctx.vtable);
9055fff9558SSimon J. Gerraty 	md->update(&mctx.vtable, fcp, flen);
9065fff9558SSimon J. Gerraty 	md->out(&mctx.vtable, rhbuf);
9075fff9558SSimon J. Gerraty 	if (!verify_rsa_digest(&pk->key.rsa, hash_oid,
9085fff9558SSimon J. Gerraty 		rhbuf, hlen, po->data, po->data_len)) {
9095fff9558SSimon J. Gerraty 		free(fcp);
9105fff9558SSimon J. Gerraty 		fcp = NULL;
9115fff9558SSimon J. Gerraty 	}
9125fff9558SSimon J. Gerraty 	free(scp);
9135fff9558SSimon J. Gerraty 	return (fcp);
9145fff9558SSimon J. Gerraty }
9155fff9558SSimon J. Gerraty #endif
9165fff9558SSimon J. Gerraty 
9175fff9558SSimon J. Gerraty /**
9185fff9558SSimon J. Gerraty  * @brief
9195fff9558SSimon J. Gerraty  * verify a signature and return content of signed file
9205fff9558SSimon J. Gerraty  *
9215fff9558SSimon J. Gerraty  * @param[in] sigfile
9225fff9558SSimon J. Gerraty  * 	file containing signature
9235fff9558SSimon J. Gerraty  * 	we derrive path of signed file and certificate change from
9245fff9558SSimon J. Gerraty  * 	this.
9255fff9558SSimon J. Gerraty  *
9265fff9558SSimon J. Gerraty  * @param[in] flags
9275fff9558SSimon J. Gerraty  * 	only bit 1 significant so far
9285fff9558SSimon J. Gerraty  *
9295fff9558SSimon J. Gerraty  * @return NULL on error otherwise content of signed file
9305fff9558SSimon J. Gerraty  */
9315fff9558SSimon J. Gerraty unsigned char *
9325fff9558SSimon J. Gerraty verify_sig(const char *sigfile, int flags)
9335fff9558SSimon J. Gerraty {
9345fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
9355fff9558SSimon J. Gerraty 	br_name_element cn;
9365fff9558SSimon J. Gerraty 	char cn_buf[80];
9375fff9558SSimon J. Gerraty 	unsigned char cn_oid[4];
9385fff9558SSimon J. Gerraty 	char pbuf[MAXPATHLEN];
9395fff9558SSimon J. Gerraty 	char *cp;
9405fff9558SSimon J. Gerraty 	unsigned char *ucp;
9415fff9558SSimon J. Gerraty 	size_t n;
9425fff9558SSimon J. Gerraty 
9435fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile));
9445fff9558SSimon J. Gerraty 	n = strlcpy(pbuf, sigfile, sizeof(pbuf));
9455fff9558SSimon J. Gerraty 	if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0)
9465fff9558SSimon J. Gerraty 		return (NULL);
9475fff9558SSimon J. Gerraty 	cp = strcpy(&pbuf[n - 3], "certs");
9485fff9558SSimon J. Gerraty 	/*
9495fff9558SSimon J. Gerraty 	 * We want the commonName field
9505fff9558SSimon J. Gerraty 	 * the OID we want is 2,5,4,3 - but DER encoded
9515fff9558SSimon J. Gerraty 	 */
9525fff9558SSimon J. Gerraty 	cn_oid[0] = 3;
9535fff9558SSimon J. Gerraty 	cn_oid[1] = 0x55;
9545fff9558SSimon J. Gerraty 	cn_oid[2] = 4;
9555fff9558SSimon J. Gerraty 	cn_oid[3] = 3;
9565fff9558SSimon J. Gerraty 	cn.oid = cn_oid;
9575fff9558SSimon J. Gerraty 	cn.buf = cn_buf;
9585fff9558SSimon J. Gerraty 	cn.len = sizeof(cn_buf);
9595fff9558SSimon J. Gerraty 
9605fff9558SSimon J. Gerraty 	pk = verify_signer(pbuf, &cn, 1);
9615fff9558SSimon J. Gerraty 	if (!pk) {
9625fff9558SSimon J. Gerraty 		printf("cannot verify: %s: %s\n", pbuf, ve_error_get());
9635fff9558SSimon J. Gerraty 		return (NULL);
9645fff9558SSimon J. Gerraty 	}
9655fff9558SSimon J. Gerraty 	for (; cp > pbuf; cp--) {
9665fff9558SSimon J. Gerraty 		if (*cp == '.') {
9675fff9558SSimon J. Gerraty 			*cp = '\0';
9685fff9558SSimon J. Gerraty 			break;
9695fff9558SSimon J. Gerraty 		}
9705fff9558SSimon J. Gerraty 	}
9715fff9558SSimon J. Gerraty 	switch (pk->key_type) {
9725fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
9735fff9558SSimon J. Gerraty 	case BR_KEYTYPE_EC:
9745fff9558SSimon J. Gerraty 		ucp = verify_ec(pk, pbuf, sigfile);
9755fff9558SSimon J. Gerraty 		break;
9765fff9558SSimon J. Gerraty #endif
9775fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
9785fff9558SSimon J. Gerraty 	case BR_KEYTYPE_RSA:
9795fff9558SSimon J. Gerraty 		ucp = verify_rsa(pk, pbuf, sigfile);
9805fff9558SSimon J. Gerraty 		break;
9815fff9558SSimon J. Gerraty #endif
9825fff9558SSimon J. Gerraty 	default:
9835fff9558SSimon J. Gerraty 		ucp = NULL;		/* not supported */
9845fff9558SSimon J. Gerraty 	}
9855fff9558SSimon J. Gerraty 	xfreepkey(pk);
9865fff9558SSimon J. Gerraty 	if (!ucp) {
9875fff9558SSimon J. Gerraty 		printf("Unverified %s (%s)\n", pbuf,
9885fff9558SSimon J. Gerraty 		    cn.status ? cn_buf : "unknown");
98966655411SSimon J. Gerraty 	} else if ((flags & VEF_VERBOSE) != 0) {
9905fff9558SSimon J. Gerraty 		printf("Verified %s signed by %s\n", pbuf,
9915fff9558SSimon J. Gerraty 		    cn.status ? cn_buf : "someone we trust");
9925fff9558SSimon J. Gerraty 	}
9935fff9558SSimon J. Gerraty 	return (ucp);
9945fff9558SSimon J. Gerraty }
9955fff9558SSimon J. Gerraty 
9965fff9558SSimon J. Gerraty 
9975fff9558SSimon J. Gerraty /**
9985fff9558SSimon J. Gerraty  * @brief verify hash matches
9995fff9558SSimon J. Gerraty  *
10005fff9558SSimon J. Gerraty  * We have finished hashing a file,
10015fff9558SSimon J. Gerraty  * see if we got the desired result.
10025fff9558SSimon J. Gerraty  *
10035fff9558SSimon J. Gerraty  * @param[in] ctx
10045fff9558SSimon J. Gerraty  *	pointer to hash context
10055fff9558SSimon J. Gerraty  *
10065fff9558SSimon J. Gerraty  * @param[in] md
10075fff9558SSimon J. Gerraty  *	pointer to hash class
10085fff9558SSimon J. Gerraty  *
10095fff9558SSimon J. Gerraty  * @param[in] path
10105fff9558SSimon J. Gerraty  *	name of the file we are checking
10115fff9558SSimon J. Gerraty  *
10125fff9558SSimon J. Gerraty  * @param[in] want
10135fff9558SSimon J. Gerraty  *	the expected result
10145fff9558SSimon J. Gerraty  *
10155fff9558SSimon J. Gerraty  * @param[in] hlen
10165fff9558SSimon J. Gerraty  *	size of hash output
10175fff9558SSimon J. Gerraty  *
10185fff9558SSimon J. Gerraty  * @return 0 on success
10195fff9558SSimon J. Gerraty  */
10205fff9558SSimon J. Gerraty int
10215fff9558SSimon J. Gerraty ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md,
10225fff9558SSimon J. Gerraty     const char *path, const char *want, size_t hlen)
10235fff9558SSimon J. Gerraty {
10245fff9558SSimon J. Gerraty 	char hexbuf[br_sha512_SIZE * 2 + 2];
10255fff9558SSimon J. Gerraty 	unsigned char hbuf[br_sha512_SIZE];
10265fff9558SSimon J. Gerraty 	char *hex;
10275fff9558SSimon J. Gerraty 	int rc;
10285fff9558SSimon J. Gerraty 	int n;
10295fff9558SSimon J. Gerraty 
10305fff9558SSimon J. Gerraty 	md->out(&ctx->vtable, hbuf);
10315fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT
103253f151f9SSimon J. Gerraty 	ve_pcr_update(path, hbuf, hlen);
10335fff9558SSimon J. Gerraty #endif
10345fff9558SSimon J. Gerraty 	hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
10355fff9558SSimon J. Gerraty 	if (!hex)
10365fff9558SSimon J. Gerraty 		return (VE_FINGERPRINT_WRONG);
10375fff9558SSimon J. Gerraty 	n = 2*hlen;
10385fff9558SSimon J. Gerraty 	if ((rc = strncmp(hex, want, n))) {
10395fff9558SSimon J. Gerraty 		ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want);
10405fff9558SSimon J. Gerraty 		rc = VE_FINGERPRINT_WRONG;
10415fff9558SSimon J. Gerraty 	}
10425fff9558SSimon J. Gerraty 	return (rc ? rc : VE_FINGERPRINT_OK);
10435fff9558SSimon J. Gerraty }
10445fff9558SSimon J. Gerraty 
10455fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR
10465fff9558SSimon J. Gerraty static int
10475fff9558SSimon J. Gerraty test_hash(const br_hash_class *md, size_t hlen,
10485fff9558SSimon J. Gerraty     const char *hname, const char *s, size_t slen, const char *want)
10495fff9558SSimon J. Gerraty {
10505fff9558SSimon J. Gerraty 	br_hash_compat_context mctx;
10515fff9558SSimon J. Gerraty 
10525fff9558SSimon J. Gerraty 	md->init(&mctx.vtable);
10535fff9558SSimon J. Gerraty 	md->update(&mctx.vtable, s, slen);
10545fff9558SSimon J. Gerraty 	return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK);
10555fff9558SSimon J. Gerraty }
10565fff9558SSimon J. Gerraty 
10575fff9558SSimon J. Gerraty #endif
10585fff9558SSimon J. Gerraty 
10595fff9558SSimon J. Gerraty #define ve_test_hash(n, N) \
10605fff9558SSimon J. Gerraty 	printf("Testing hash: " #n "\t\t\t\t%s\n", \
10615fff9558SSimon J. Gerraty 	    test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \
10629bee6a60SSimon J. Gerraty 	    VE_HASH_KAT_STR, VE_HASH_KAT_STRLEN(VE_HASH_KAT_STR), \
10635fff9558SSimon J. Gerraty 	    vh_ ## N) ? "Failed" : "Passed")
10645fff9558SSimon J. Gerraty 
10655fff9558SSimon J. Gerraty /**
10665fff9558SSimon J. Gerraty  * @brief
10675fff9558SSimon J. Gerraty  * run self tests on hash and signature verification
10685fff9558SSimon J. Gerraty  *
10695fff9558SSimon J. Gerraty  * Test that the hash methods (SHA1 and SHA256) work.
10705fff9558SSimon J. Gerraty  * Test that we can verify a certificate for each supported
10715fff9558SSimon J. Gerraty  * Root CA.
10725fff9558SSimon J. Gerraty  *
10735fff9558SSimon J. Gerraty  * @return cached result.
10745fff9558SSimon J. Gerraty  */
10755fff9558SSimon J. Gerraty int
10765fff9558SSimon J. Gerraty ve_self_tests(void)
10775fff9558SSimon J. Gerraty {
10785fff9558SSimon J. Gerraty 	static int once = -1;
10795fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR
10805fff9558SSimon J. Gerraty 	br_x509_certificate *xcs;
10815fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
10825fff9558SSimon J. Gerraty 	br_name_element cn;
10835fff9558SSimon J. Gerraty 	char cn_buf[80];
10845fff9558SSimon J. Gerraty 	unsigned char cn_oid[4];
10855fff9558SSimon J. Gerraty 	size_t num;
10865fff9558SSimon J. Gerraty 	size_t u;
10875fff9558SSimon J. Gerraty #endif
10885fff9558SSimon J. Gerraty 
10895fff9558SSimon J. Gerraty 	if (once >= 0)
10905fff9558SSimon J. Gerraty 		return (once);
10915fff9558SSimon J. Gerraty 	once = 0;
10925fff9558SSimon J. Gerraty 
10935fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("Self tests...\n"));
10945fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR
10955fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT
10965fff9558SSimon J. Gerraty 	ve_test_hash(sha1, SHA1);
10975fff9558SSimon J. Gerraty #endif
10985fff9558SSimon J. Gerraty #ifdef VE_SHA256_SUPPORT
10995fff9558SSimon J. Gerraty 	ve_test_hash(sha256, SHA256);
11005fff9558SSimon J. Gerraty #endif
11015fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT
11025fff9558SSimon J. Gerraty 	ve_test_hash(sha384, SHA384);
11035fff9558SSimon J. Gerraty #endif
11045fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT
11055fff9558SSimon J. Gerraty 	ve_test_hash(sha512, SHA512);
11065fff9558SSimon J. Gerraty #endif
11075fff9558SSimon J. Gerraty #endif
11085fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR
11095fff9558SSimon J. Gerraty 	xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
11105fff9558SSimon J. Gerraty 	    sizeof(VERIFY_CERTS_STR), &num);
11119bee6a60SSimon J. Gerraty 	if (xcs != NULL) {
11125fff9558SSimon J. Gerraty 		/*
11135fff9558SSimon J. Gerraty 		 * We want the commonName field
11145fff9558SSimon J. Gerraty 		 * the OID we want is 2,5,4,3 - but DER encoded
11155fff9558SSimon J. Gerraty 		 */
11165fff9558SSimon J. Gerraty 		cn_oid[0] = 3;
11175fff9558SSimon J. Gerraty 		cn_oid[1] = 0x55;
11185fff9558SSimon J. Gerraty 		cn_oid[2] = 4;
11195fff9558SSimon J. Gerraty 		cn_oid[3] = 3;
11205fff9558SSimon J. Gerraty 		cn.oid = cn_oid;
11215fff9558SSimon J. Gerraty 		cn.buf = cn_buf;
11225fff9558SSimon J. Gerraty 
11235fff9558SSimon J. Gerraty 		for (u = 0; u < num; u ++) {
11245fff9558SSimon J. Gerraty 			cn.len = sizeof(cn_buf);
112513ea0450SMarcin Wojtas 			if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
112613ea0450SMarcin Wojtas 				free_cert_contents(&xcs[u]);
11275fff9558SSimon J. Gerraty 				once++;
11285fff9558SSimon J. Gerraty 				printf("Testing verify certificate: %s\tPassed\n",
11295fff9558SSimon J. Gerraty 				    cn.status ? cn_buf : "");
11305fff9558SSimon J. Gerraty 				xfreepkey(pk);
11315fff9558SSimon J. Gerraty 			}
11325fff9558SSimon J. Gerraty 		}
11335fff9558SSimon J. Gerraty 		if (!once)
11345fff9558SSimon J. Gerraty 			printf("Testing verify certificate:\t\t\tFailed\n");
11355fff9558SSimon J. Gerraty 		xfree(xcs);
11369bee6a60SSimon J. Gerraty 	}
11375fff9558SSimon J. Gerraty #endif	/* VERIFY_CERTS_STR */
11385fff9558SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
11395fff9558SSimon J. Gerraty 	if (!openpgp_self_tests())
11405fff9558SSimon J. Gerraty 		once++;
11415fff9558SSimon J. Gerraty #endif
11425fff9558SSimon J. Gerraty 	return (once);
11435fff9558SSimon J. Gerraty }
1144