xref: /freebsd/lib/libsecureboot/vets.c (revision 4b9d605768acabc460aa6dcfe8a1f8db35b16794)
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 /**
275fff9558SSimon J. Gerraty  * @file vets.c - trust store
285fff9558SSimon J. Gerraty  * @brief verify signatures
295fff9558SSimon J. Gerraty  *
305fff9558SSimon J. Gerraty  * We leverage code from BearSSL www.bearssl.org
315fff9558SSimon J. Gerraty  */
325fff9558SSimon J. Gerraty 
335fff9558SSimon J. Gerraty #include <sys/time.h>
345fff9558SSimon J. Gerraty #include <stdarg.h>
355fff9558SSimon J. Gerraty #define NEED_BRSSL_H
365fff9558SSimon J. Gerraty #include "libsecureboot-priv.h"
375fff9558SSimon J. Gerraty #include <brssl.h>
385fff9558SSimon J. Gerraty #include <ta.h>
395fff9558SSimon J. Gerraty 
405fff9558SSimon J. Gerraty #ifndef TRUST_ANCHOR_STR
415fff9558SSimon J. Gerraty # define TRUST_ANCHOR_STR ta_PEM
425fff9558SSimon J. Gerraty #endif
435fff9558SSimon J. Gerraty 
4466655411SSimon J. Gerraty #define EPOCH_YEAR		1970
4566655411SSimon J. Gerraty #define AVG_SECONDS_PER_YEAR	31556952L
465fff9558SSimon J. Gerraty #define SECONDS_PER_DAY		86400
4753f151f9SSimon J. Gerraty #define SECONDS_PER_YEAR	365 * SECONDS_PER_DAY
4853f151f9SSimon J. Gerraty #ifndef VE_UTC_MAX_JUMP
4953f151f9SSimon J. Gerraty # define VE_UTC_MAX_JUMP	20 * SECONDS_PER_YEAR
5053f151f9SSimon J. Gerraty #endif
515fff9558SSimon J. Gerraty #define X509_DAYS_TO_UTC0	719528
525fff9558SSimon J. Gerraty 
535fff9558SSimon J. Gerraty int DebugVe = 0;
545fff9558SSimon J. Gerraty 
5566655411SSimon J. Gerraty #ifndef VE_VERIFY_FLAGS
5666655411SSimon J. Gerraty # define VE_VERIFY_FLAGS VEF_VERBOSE
5766655411SSimon J. Gerraty #endif
5866655411SSimon J. Gerraty int VerifyFlags = VE_VERIFY_FLAGS;
5966655411SSimon J. Gerraty 
605fff9558SSimon J. Gerraty typedef VECTOR(br_x509_certificate) cert_list;
6113ea0450SMarcin Wojtas typedef VECTOR(hash_data) digest_list;
625fff9558SSimon J. Gerraty 
635fff9558SSimon J. Gerraty static anchor_list trust_anchors = VEC_INIT;
6413ea0450SMarcin Wojtas static anchor_list forbidden_anchors = VEC_INIT;
6513ea0450SMarcin Wojtas static digest_list forbidden_digests = VEC_INIT;
665fff9558SSimon J. Gerraty 
67f9510887SSimon J. Gerraty static int anchor_verbose = 0;
68f9510887SSimon J. Gerraty 
69f9510887SSimon J. Gerraty void
70f9510887SSimon J. Gerraty ve_anchor_verbose_set(int n)
71f9510887SSimon J. Gerraty {
72f9510887SSimon J. Gerraty 	anchor_verbose = n;
73f9510887SSimon J. Gerraty }
74f9510887SSimon J. Gerraty 
75f9510887SSimon J. Gerraty int
76f9510887SSimon J. Gerraty ve_anchor_verbose_get(void)
77f9510887SSimon J. Gerraty {
78f9510887SSimon J. Gerraty 	return (anchor_verbose);
79f9510887SSimon J. Gerraty }
80f9510887SSimon J. Gerraty 
815fff9558SSimon J. Gerraty void
825fff9558SSimon J. Gerraty ve_debug_set(int n)
835fff9558SSimon J. Gerraty {
845fff9558SSimon J. Gerraty 	DebugVe = n;
855fff9558SSimon J. Gerraty }
865fff9558SSimon J. Gerraty 
87ab4f0a15SSimon J. Gerraty /*
88ab4f0a15SSimon J. Gerraty  * For embedded systems (and boot loaders)
89ab4f0a15SSimon J. Gerraty  * we do not want to enforce certificate validity post install.
90ab4f0a15SSimon J. Gerraty  * It is generally unacceptible for infrastructure to stop working
91ab4f0a15SSimon J. Gerraty  * just because it has not been updated recently.
92ab4f0a15SSimon J. Gerraty  */
93ab4f0a15SSimon J. Gerraty static int enforce_validity = 0;
94ab4f0a15SSimon J. Gerraty 
95ab4f0a15SSimon J. Gerraty void
96ab4f0a15SSimon J. Gerraty ve_enforce_validity_set(int i)
97ab4f0a15SSimon J. Gerraty {
98ab4f0a15SSimon J. Gerraty     enforce_validity = i;
99ab4f0a15SSimon J. Gerraty }
100ab4f0a15SSimon J. Gerraty 
1015fff9558SSimon J. Gerraty static char ebuf[512];
1025fff9558SSimon J. Gerraty 
1035fff9558SSimon J. Gerraty char *
1045fff9558SSimon J. Gerraty ve_error_get(void)
1055fff9558SSimon J. Gerraty {
1065fff9558SSimon J. Gerraty 	return (ebuf);
1075fff9558SSimon J. Gerraty }
1085fff9558SSimon J. Gerraty 
1095fff9558SSimon J. Gerraty int
1105fff9558SSimon J. Gerraty ve_error_set(const char *fmt, ...)
1115fff9558SSimon J. Gerraty {
1125fff9558SSimon J. Gerraty 	int rc;
1135fff9558SSimon J. Gerraty 	va_list ap;
1145fff9558SSimon J. Gerraty 
1155fff9558SSimon J. Gerraty 	va_start(ap, fmt);
1165fff9558SSimon J. Gerraty 	ebuf[0] = '\0';
1175fff9558SSimon J. Gerraty 	rc = 0;
1185fff9558SSimon J. Gerraty 	if (fmt) {
1195fff9558SSimon J. Gerraty #ifdef STAND_H
1205fff9558SSimon J. Gerraty 		vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */
1215fff9558SSimon J. Gerraty 		ebuf[sizeof(ebuf) - 1] = '\0';
1225fff9558SSimon J. Gerraty 		rc = strlen(ebuf);
1235fff9558SSimon J. Gerraty #else
1245fff9558SSimon J. Gerraty 		rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap);
1255fff9558SSimon J. Gerraty #endif
1265fff9558SSimon J. Gerraty 	}
1275fff9558SSimon J. Gerraty 	va_end(ap);
1285fff9558SSimon J. Gerraty 	return (rc);
1295fff9558SSimon J. Gerraty }
1305fff9558SSimon J. Gerraty 
13166655411SSimon J. Gerraty #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
13266655411SSimon J. Gerraty 
13366655411SSimon J. Gerraty /*
13466655411SSimon J. Gerraty  * The *approximate* date.
13566655411SSimon J. Gerraty  *
13666655411SSimon J. Gerraty  * When certificate verification fails for being
13766655411SSimon J. Gerraty  * expired or not yet valid, it helps to indicate
13866655411SSimon J. Gerraty  * our current date.
13966655411SSimon J. Gerraty  * Since libsa lacks strftime and gmtime,
14066655411SSimon J. Gerraty  * this simple implementation suffices.
14166655411SSimon J. Gerraty  */
14266655411SSimon J. Gerraty static const char *
14366655411SSimon J. Gerraty gdate(char *buf, size_t bufsz, time_t clock)
14466655411SSimon J. Gerraty {
14566655411SSimon J. Gerraty 	int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
14666655411SSimon J. Gerraty 	int year, y, m, d;
14766655411SSimon J. Gerraty 
14866655411SSimon J. Gerraty 	y = clock / AVG_SECONDS_PER_YEAR;
14966655411SSimon J. Gerraty 	year = EPOCH_YEAR + y;
15066655411SSimon J. Gerraty 	for (y = EPOCH_YEAR; y < year; y++) {
15166655411SSimon J. Gerraty 		clock -= SECONDS_PER_YEAR;
15266655411SSimon J. Gerraty 		if (isleap(y))
15366655411SSimon J. Gerraty 			clock -= SECONDS_PER_DAY;
15466655411SSimon J. Gerraty 	}
15566655411SSimon J. Gerraty 	d = clock / SECONDS_PER_DAY;
15666655411SSimon J. Gerraty 	for (m = 0; d > 1 && m < 12; m++) {
15766655411SSimon J. Gerraty 		if (d > days[m]) {
15866655411SSimon J. Gerraty 			d -= days[m];
15966655411SSimon J. Gerraty 			if (m == 1 && d > 0 && isleap(year))
16066655411SSimon J. Gerraty 				d--;
16166655411SSimon J. Gerraty 		} else
16266655411SSimon J. Gerraty 			break;
16366655411SSimon J. Gerraty 	}
16466655411SSimon J. Gerraty 	d++;
16566655411SSimon J. Gerraty 	if (d > days[m]) {
16666655411SSimon J. Gerraty 	    d = 1;
16766655411SSimon J. Gerraty 	    m++;
16866655411SSimon J. Gerraty 	    if (m >= 12) {
16966655411SSimon J. Gerraty 		year++;
17066655411SSimon J. Gerraty 		m = 0;
17166655411SSimon J. Gerraty 	    }
17266655411SSimon J. Gerraty 	}
17366655411SSimon J. Gerraty 	(void)snprintf(buf, bufsz, "%04d-%02d-%02d", year, m+1, d);
17466655411SSimon J. Gerraty 	return(buf);
17566655411SSimon J. Gerraty }
17666655411SSimon J. Gerraty 
1775fff9558SSimon J. Gerraty /* this is the time we use for verifying certs */
17866655411SSimon J. Gerraty #ifdef UNIT_TEST
17966655411SSimon J. Gerraty extern time_t ve_utc;
18066655411SSimon J. Gerraty time_t ve_utc = 0;
18166655411SSimon J. Gerraty #else
1825fff9558SSimon J. Gerraty static time_t ve_utc = 0;
18366655411SSimon J. Gerraty #endif
1845fff9558SSimon J. Gerraty 
1855fff9558SSimon J. Gerraty /**
1865fff9558SSimon J. Gerraty  * @brief
1875fff9558SSimon J. Gerraty  * set ve_utc used for certificate verification
1885fff9558SSimon J. Gerraty  *
1895fff9558SSimon J. Gerraty  * @param[in] utc
19053f151f9SSimon J. Gerraty  *	time - ignored unless greater than current value
19153f151f9SSimon J. Gerraty  *	and not a leap of 20 years or more.
1925fff9558SSimon J. Gerraty  */
1935fff9558SSimon J. Gerraty void
1945fff9558SSimon J. Gerraty ve_utc_set(time_t utc)
1955fff9558SSimon J. Gerraty {
19653f151f9SSimon J. Gerraty 	if (utc > ve_utc &&
19753f151f9SSimon J. Gerraty 	    (ve_utc == 0 || (utc - ve_utc) < VE_UTC_MAX_JUMP)) {
1985fff9558SSimon J. Gerraty 		DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc));
1995fff9558SSimon J. Gerraty 		ve_utc = utc;
2005fff9558SSimon J. Gerraty 	}
2015fff9558SSimon J. Gerraty }
2025fff9558SSimon J. Gerraty 
2035fff9558SSimon J. Gerraty static void
2045fff9558SSimon J. Gerraty free_cert_contents(br_x509_certificate *xc)
2055fff9558SSimon J. Gerraty {
2065fff9558SSimon J. Gerraty 	xfree(xc->data);
2075fff9558SSimon J. Gerraty }
2085fff9558SSimon J. Gerraty 
209f9510887SSimon J. Gerraty /*
210f9510887SSimon J. Gerraty  * a bit of a dance to get commonName from a certificate
211f9510887SSimon J. Gerraty  */
212f9510887SSimon J. Gerraty static char *
213f9510887SSimon J. Gerraty x509_cn_get(br_x509_certificate *xc, char *buf, size_t len)
214f9510887SSimon J. Gerraty {
215f9510887SSimon J. Gerraty 	br_x509_minimal_context mc;
216f9510887SSimon J. Gerraty 	br_name_element cn;
217f9510887SSimon J. Gerraty 	unsigned char cn_oid[4];
218f9510887SSimon J. Gerraty 	int err;
219f9510887SSimon J. Gerraty 
220f9510887SSimon J. Gerraty 	if (buf == NULL)
221f9510887SSimon J. Gerraty 		return (buf);
222f9510887SSimon J. Gerraty 	/*
223f9510887SSimon J. Gerraty 	 * We want the commonName field
224f9510887SSimon J. Gerraty 	 * the OID we want is 2,5,4,3 - but DER encoded
225f9510887SSimon J. Gerraty 	 */
226f9510887SSimon J. Gerraty 	cn_oid[0] = 3;
227f9510887SSimon J. Gerraty 	cn_oid[1] = 0x55;
228f9510887SSimon J. Gerraty 	cn_oid[2] = 4;
229f9510887SSimon J. Gerraty 	cn_oid[3] = 3;
230f9510887SSimon J. Gerraty 	cn.oid = cn_oid;
231f9510887SSimon J. Gerraty 	cn.buf = buf;
232f9510887SSimon J. Gerraty 	cn.len = len;
233f9510887SSimon J. Gerraty 	cn.buf[0] = '\0';
234f9510887SSimon J. Gerraty 
235f9510887SSimon J. Gerraty 	br_x509_minimal_init(&mc, &br_sha256_vtable, NULL, 0);
236f9510887SSimon J. Gerraty 	br_x509_minimal_set_name_elements(&mc, &cn, 1);
237f9510887SSimon J. Gerraty 	/* the below actually does the work - updates cn.status */
238f9510887SSimon J. Gerraty 	mc.vtable->start_chain(&mc.vtable, NULL);
239f9510887SSimon J. Gerraty 	mc.vtable->start_cert(&mc.vtable, xc->data_len);
240f9510887SSimon J. Gerraty 	mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
241f9510887SSimon J. Gerraty 	mc.vtable->end_cert(&mc.vtable);
24256f3f2d2SSimon J. Gerraty 	/* we don't actually care about cert status - just its name */
243f9510887SSimon J. Gerraty 	err = mc.vtable->end_chain(&mc.vtable);
2449c3478cbSSimon J. Gerraty 	(void)err;			/* keep compiler quiet */
245f9510887SSimon J. Gerraty 
2469c3478cbSSimon J. Gerraty 	if (cn.status <= 0)
247f9510887SSimon J. Gerraty 		buf = NULL;
248f9510887SSimon J. Gerraty 	return (buf);
249f9510887SSimon J. Gerraty }
250f9510887SSimon J. Gerraty 
25113ea0450SMarcin Wojtas /* ASN parsing related defines */
25213ea0450SMarcin Wojtas #define ASN1_PRIMITIVE_TAG 0x1F
25313ea0450SMarcin Wojtas #define ASN1_INF_LENGTH    0x80
25413ea0450SMarcin Wojtas #define ASN1_LENGTH_MASK   0x7F
25513ea0450SMarcin Wojtas 
25613ea0450SMarcin Wojtas /*
25713ea0450SMarcin Wojtas  * Get TBS part of certificate.
25813ea0450SMarcin Wojtas  * Since BearSSL doesn't provide any API to do this,
25913ea0450SMarcin Wojtas  * it has to be implemented here.
2605fff9558SSimon J. Gerraty  */
26113ea0450SMarcin Wojtas static void*
26213ea0450SMarcin Wojtas X509_to_tbs(unsigned char* cert, size_t* output_size)
26313ea0450SMarcin Wojtas {
26413ea0450SMarcin Wojtas 	unsigned char *result;
26513ea0450SMarcin Wojtas 	size_t tbs_size;
26613ea0450SMarcin Wojtas 	int size, i;
26713ea0450SMarcin Wojtas 
26813ea0450SMarcin Wojtas 	if (cert == NULL)
26913ea0450SMarcin Wojtas 		return (NULL);
27013ea0450SMarcin Wojtas 
27113ea0450SMarcin Wojtas 	/* Strip two sequences to get to the TBS section */
27213ea0450SMarcin Wojtas 	for (i = 0; i < 2; i++) {
27313ea0450SMarcin Wojtas 		/*
27413ea0450SMarcin Wojtas 		 * XXX: We don't need to support extended tags since
27513ea0450SMarcin Wojtas 		 * they should not be present in certificates.
27613ea0450SMarcin Wojtas 		 */
27713ea0450SMarcin Wojtas 		if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG)
27813ea0450SMarcin Wojtas 			return (NULL);
27913ea0450SMarcin Wojtas 
28013ea0450SMarcin Wojtas 		cert++;
28113ea0450SMarcin Wojtas 
28213ea0450SMarcin Wojtas 		if (*cert == ASN1_INF_LENGTH)
28313ea0450SMarcin Wojtas 			return (NULL);
28413ea0450SMarcin Wojtas 
28513ea0450SMarcin Wojtas 		size = *cert & ASN1_LENGTH_MASK;
28613ea0450SMarcin Wojtas 		tbs_size = 0;
28713ea0450SMarcin Wojtas 
28813ea0450SMarcin Wojtas 		/* Size can either be stored on a single or multiple bytes */
28913ea0450SMarcin Wojtas 		if (*cert & (ASN1_LENGTH_MASK + 1)) {
29013ea0450SMarcin Wojtas 			cert++;
29113ea0450SMarcin Wojtas 			while (*cert == 0 && size > 0) {
29213ea0450SMarcin Wojtas 				cert++;
29313ea0450SMarcin Wojtas 				size--;
29413ea0450SMarcin Wojtas 			}
29513ea0450SMarcin Wojtas 			while (size-- > 0) {
29613ea0450SMarcin Wojtas 				tbs_size <<= 8;
29713ea0450SMarcin Wojtas 				tbs_size |= *(cert++);
29813ea0450SMarcin Wojtas 			}
29913ea0450SMarcin Wojtas 		}
30013ea0450SMarcin Wojtas 		if (i == 0)
30113ea0450SMarcin Wojtas 			result = cert;
30213ea0450SMarcin Wojtas 	}
30313ea0450SMarcin Wojtas 	tbs_size += (cert - result);
30413ea0450SMarcin Wojtas 
30513ea0450SMarcin Wojtas 	if (output_size != NULL)
30613ea0450SMarcin Wojtas 		*output_size = tbs_size;
30713ea0450SMarcin Wojtas 
30813ea0450SMarcin Wojtas 	return (result);
30913ea0450SMarcin Wojtas }
31013ea0450SMarcin Wojtas 
31113ea0450SMarcin Wojtas void
31213ea0450SMarcin Wojtas ve_forbidden_digest_add(hash_data *digest, size_t num)
31313ea0450SMarcin Wojtas {
31413ea0450SMarcin Wojtas 	while (num--)
31513ea0450SMarcin Wojtas 		VEC_ADD(forbidden_digests, digest[num]);
31613ea0450SMarcin Wojtas }
31713ea0450SMarcin Wojtas 
31813ea0450SMarcin Wojtas static size_t
319f9510887SSimon J. Gerraty ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors,
32018e2fbc0SSimon J. Gerraty     const char *anchors_name)
3215fff9558SSimon J. Gerraty {
3225fff9558SSimon J. Gerraty 	br_x509_trust_anchor ta;
3235fff9558SSimon J. Gerraty 	size_t u;
3245fff9558SSimon J. Gerraty 
3255fff9558SSimon J. Gerraty 	for (u = 0; u < num; u++) {
3265fff9558SSimon J. Gerraty 		if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
3275fff9558SSimon J. Gerraty 			break;
3285fff9558SSimon J. Gerraty 		}
32913ea0450SMarcin Wojtas 		VEC_ADD(*anchors, ta);
330f9510887SSimon J. Gerraty 		if (anchor_verbose && anchors_name) {
331f9510887SSimon J. Gerraty 			char buf[64];
332f9510887SSimon J. Gerraty 			char *cp;
333f9510887SSimon J. Gerraty 
334f9510887SSimon J. Gerraty 			cp = x509_cn_get(&xcs[u], buf, sizeof(buf));
335f9510887SSimon J. Gerraty 			if (cp) {
336f9510887SSimon J. Gerraty 				printf("x509_anchor(%s) %s\n", cp, anchors_name);
337f9510887SSimon J. Gerraty 			}
338f9510887SSimon J. Gerraty 		}
3395fff9558SSimon J. Gerraty 	}
3405fff9558SSimon J. Gerraty 	return (u);
3415fff9558SSimon J. Gerraty }
3425fff9558SSimon J. Gerraty 
3435fff9558SSimon J. Gerraty /**
3445fff9558SSimon J. Gerraty  * @brief
34513ea0450SMarcin Wojtas  * add certs to our trust store
34613ea0450SMarcin Wojtas  */
34713ea0450SMarcin Wojtas size_t
34813ea0450SMarcin Wojtas ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
34913ea0450SMarcin Wojtas {
350f9510887SSimon J. Gerraty 	return (ve_anchors_add(xcs, num, &trust_anchors, "trusted"));
35113ea0450SMarcin Wojtas }
35213ea0450SMarcin Wojtas 
35313ea0450SMarcin Wojtas size_t
35413ea0450SMarcin Wojtas ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num)
35513ea0450SMarcin Wojtas {
356f9510887SSimon J. Gerraty 	return (ve_anchors_add(xcs, num, &forbidden_anchors, "forbidden"));
357f9510887SSimon J. Gerraty }
358f9510887SSimon J. Gerraty 
359f9510887SSimon J. Gerraty 
360f9510887SSimon J. Gerraty /**
361f9510887SSimon J. Gerraty  * @brief add trust anchors in buf
362f9510887SSimon J. Gerraty  *
363f9510887SSimon J. Gerraty  * Assume buf contains x509 certificates, but if not and
364f9510887SSimon J. Gerraty  * we support OpenPGP try adding as that.
365f9510887SSimon J. Gerraty  *
366f9510887SSimon J. Gerraty  * @return number of anchors added
367f9510887SSimon J. Gerraty  */
368f9510887SSimon J. Gerraty size_t
369f9510887SSimon J. Gerraty ve_trust_anchors_add_buf(unsigned char *buf, size_t len)
370f9510887SSimon J. Gerraty {
371f9510887SSimon J. Gerraty 	br_x509_certificate *xcs;
372f9510887SSimon J. Gerraty 	size_t num;
373f9510887SSimon J. Gerraty 
374f9510887SSimon J. Gerraty 	num = 0;
375f9510887SSimon J. Gerraty 	xcs = parse_certificates(buf, len, &num);
376f9510887SSimon J. Gerraty 	if (xcs != NULL) {
377f9510887SSimon J. Gerraty 		num = ve_trust_anchors_add(xcs, num);
378f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
379f9510887SSimon J. Gerraty 	} else {
380f9510887SSimon J. Gerraty 		num = openpgp_trust_add_buf(buf, len);
381f9510887SSimon J. Gerraty #endif
382f9510887SSimon J. Gerraty 	}
383f9510887SSimon J. Gerraty 	return (num);
384f9510887SSimon J. Gerraty }
385f9510887SSimon J. Gerraty 
386f9510887SSimon J. Gerraty /**
387f9510887SSimon J. Gerraty  * @brief revoke trust anchors in buf
388f9510887SSimon J. Gerraty  *
389f9510887SSimon J. Gerraty  * Assume buf contains x509 certificates, but if not and
390f9510887SSimon J. Gerraty  * we support OpenPGP try revoking keyId
391f9510887SSimon J. Gerraty  *
392f9510887SSimon J. Gerraty  * @return number of anchors revoked
393f9510887SSimon J. Gerraty  */
394f9510887SSimon J. Gerraty size_t
395f9510887SSimon J. Gerraty ve_trust_anchors_revoke(unsigned char *buf, size_t len)
396f9510887SSimon J. Gerraty {
397f9510887SSimon J. Gerraty 	br_x509_certificate *xcs;
398f9510887SSimon J. Gerraty 	size_t num;
399f9510887SSimon J. Gerraty 
400f9510887SSimon J. Gerraty 	num = 0;
401f9510887SSimon J. Gerraty 	xcs = parse_certificates(buf, len, &num);
402f9510887SSimon J. Gerraty 	if (xcs != NULL) {
403f9510887SSimon J. Gerraty 		num = ve_forbidden_anchors_add(xcs, num);
404f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
405f9510887SSimon J. Gerraty 	} else {
406f9510887SSimon J. Gerraty 		if (buf[len - 1] == '\n')
407f9510887SSimon J. Gerraty 			buf[len - 1] = '\0';
408f9510887SSimon J. Gerraty 		num = openpgp_trust_revoke((char *)buf);
409f9510887SSimon J. Gerraty #endif
410f9510887SSimon J. Gerraty 	}
411f9510887SSimon J. Gerraty 	return (num);
41213ea0450SMarcin Wojtas }
41313ea0450SMarcin Wojtas 
41413ea0450SMarcin Wojtas /**
41513ea0450SMarcin Wojtas  * @brief
4165fff9558SSimon J. Gerraty  * initialize our trust_anchors from ta_PEM
4175fff9558SSimon J. Gerraty  */
4185fff9558SSimon J. Gerraty int
4195fff9558SSimon J. Gerraty ve_trust_init(void)
4205fff9558SSimon J. Gerraty {
4215fff9558SSimon J. Gerraty 	static int once = -1;
4225fff9558SSimon J. Gerraty 
4235fff9558SSimon J. Gerraty 	if (once >= 0)
4245fff9558SSimon J. Gerraty 		return (once);
4253ae2a848SSimon J. Gerraty 	once = 0;			/* to be sure */
4265fff9558SSimon J. Gerraty #ifdef BUILD_UTC
42753f151f9SSimon J. Gerraty 	ve_utc_set(BUILD_UTC);		/* ensure sanity */
4285fff9558SSimon J. Gerraty #endif
42953f151f9SSimon J. Gerraty 	ve_utc_set(time(NULL));
4305fff9558SSimon J. Gerraty 	ve_error_set(NULL);		/* make sure it is empty */
4315fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT
4325fff9558SSimon J. Gerraty 	ve_pcr_init();
4335fff9558SSimon J. Gerraty #endif
4345fff9558SSimon J. Gerraty 
4355fff9558SSimon J. Gerraty #ifdef TRUST_ANCHOR_STR
436e6ef5042SWojciech Macek 	if (TRUST_ANCHOR_STR != NULL && strlen(TRUST_ANCHOR_STR) != 0ul)
437e6ef5042SWojciech Macek 		ve_trust_anchors_add_buf(__DECONST(unsigned char *,
438e6ef5042SWojciech Macek 		    TRUST_ANCHOR_STR), sizeof(TRUST_ANCHOR_STR));
4395fff9558SSimon J. Gerraty #endif
44013ea0450SMarcin Wojtas 	once = (int) VEC_LEN(trust_anchors);
4419bee6a60SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
4429bee6a60SSimon J. Gerraty 	once += openpgp_trust_init();
4439bee6a60SSimon J. Gerraty #endif
44413ea0450SMarcin Wojtas 	return (once);
4455fff9558SSimon J. Gerraty }
4465fff9558SSimon J. Gerraty 
44766655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK
44866655411SSimon J. Gerraty static int
449cc9e6590SSimon J. Gerraty verify_time_cb(void *tctx __unused,
45066655411SSimon J. Gerraty     uint32_t not_before_days, uint32_t not_before_seconds,
45166655411SSimon J. Gerraty     uint32_t not_after_days, uint32_t not_after_seconds)
45266655411SSimon J. Gerraty {
45366655411SSimon J. Gerraty 	time_t not_before;
45466655411SSimon J. Gerraty 	time_t not_after;
45566655411SSimon J. Gerraty 	int rc;
45666655411SSimon J. Gerraty #ifdef UNIT_TEST
45766655411SSimon J. Gerraty 	char date[12], nb_date[12], na_date[12];
45866655411SSimon J. Gerraty #endif
45966655411SSimon J. Gerraty 
460ab4f0a15SSimon J. Gerraty 	if (enforce_validity) {
46166655411SSimon J. Gerraty 		not_before = ((not_before_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_before_seconds;
46266655411SSimon J. Gerraty 		not_after =  ((not_after_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_after_seconds;
46366655411SSimon J. Gerraty 		if (ve_utc < not_before)
46466655411SSimon J. Gerraty 			rc = -1;
46566655411SSimon J. Gerraty 		else if (ve_utc > not_after)
46666655411SSimon J. Gerraty 			rc = 1;
46766655411SSimon J. Gerraty 		else
46866655411SSimon J. Gerraty 			rc = 0;
46966655411SSimon J. Gerraty #ifdef UNIT_TEST
47066655411SSimon J. Gerraty 		printf("notBefore %s notAfter %s date %s rc %d\n",
47166655411SSimon J. Gerraty 		    gdate(nb_date, sizeof(nb_date), not_before),
47266655411SSimon J. Gerraty 		    gdate(na_date, sizeof(na_date), not_after),
47366655411SSimon J. Gerraty 		    gdate(date, sizeof(date), ve_utc), rc);
47466655411SSimon J. Gerraty #endif
475ab4f0a15SSimon J. Gerraty 	} else
47666655411SSimon J. Gerraty 		rc = 0;			/* don't fail */
47766655411SSimon J. Gerraty 	return rc;
47866655411SSimon J. Gerraty }
47966655411SSimon J. Gerraty #endif
48066655411SSimon J. Gerraty 
4815fff9558SSimon J. Gerraty /**
4825fff9558SSimon J. Gerraty  * if we can verify the certificate chain in "certs",
4835fff9558SSimon J. Gerraty  * return the public key and if "xcp" is !NULL the associated
4845fff9558SSimon J. Gerraty  * certificate
4855fff9558SSimon J. Gerraty  */
4865fff9558SSimon J. Gerraty static br_x509_pkey *
4875fff9558SSimon J. Gerraty verify_signer_xcs(br_x509_certificate *xcs,
4885fff9558SSimon J. Gerraty     size_t num,
48913ea0450SMarcin Wojtas     br_name_element *elts, size_t num_elts,
49013ea0450SMarcin Wojtas     anchor_list *anchors)
4915fff9558SSimon J. Gerraty {
4925fff9558SSimon J. Gerraty 	br_x509_minimal_context mc;
4935fff9558SSimon J. Gerraty 	br_x509_certificate *xc;
4945fff9558SSimon J. Gerraty 	size_t u;
4955fff9558SSimon J. Gerraty 	cert_list chain = VEC_INIT;
4965fff9558SSimon J. Gerraty 	const br_x509_pkey *tpk;
4975fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
4985fff9558SSimon J. Gerraty 	unsigned int usages;
4995fff9558SSimon J. Gerraty 	int err;
5005fff9558SSimon J. Gerraty 
5015fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num));
5025fff9558SSimon J. Gerraty 	VEC_ADDMANY(chain, xcs, num);
5035fff9558SSimon J. Gerraty 	if (VEC_LEN(chain) == 0) {
5045fff9558SSimon J. Gerraty 		ve_error_set("ERROR: no/invalid certificate chain\n");
5055fff9558SSimon J. Gerraty 		return (NULL);
5065fff9558SSimon J. Gerraty 	}
5075fff9558SSimon J. Gerraty 
5085fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n",
50913ea0450SMarcin Wojtas 		VEC_LEN(*anchors)));
5105fff9558SSimon J. Gerraty 
5115fff9558SSimon J. Gerraty 	br_x509_minimal_init(&mc, &br_sha256_vtable,
51213ea0450SMarcin Wojtas 	    &VEC_ELT(*anchors, 0),
51313ea0450SMarcin Wojtas 	    VEC_LEN(*anchors));
5145fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
5155fff9558SSimon J. Gerraty 	br_x509_minimal_set_ecdsa(&mc,
5165fff9558SSimon J. Gerraty 	    &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
5175fff9558SSimon J. Gerraty #endif
5185fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
5195fff9558SSimon J. Gerraty 	br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
5205fff9558SSimon J. Gerraty #endif
5215fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
522cb25444cSElyes HAOUAS 	/* This is deprecated! do not enable unless you absolutely have to */
5235fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable);
5245fff9558SSimon J. Gerraty #endif
5255fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable);
5265fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT
5275fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable);
5285fff9558SSimon J. Gerraty #endif
5295fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT
5305fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable);
5315fff9558SSimon J. Gerraty #endif
5325fff9558SSimon J. Gerraty 	br_x509_minimal_set_name_elements(&mc, elts, num_elts);
5335fff9558SSimon J. Gerraty 
53466655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK
53566655411SSimon J. Gerraty 	br_x509_minimal_set_time_callback(&mc, NULL, verify_time_cb);
53666655411SSimon J. Gerraty #else
53766655411SSimon J. Gerraty #if defined(_STANDALONE) || defined(UNIT_TEST)
5385fff9558SSimon J. Gerraty 	/*
5395fff9558SSimon J. Gerraty 	 * Clock is probably bogus so we use ve_utc.
5405fff9558SSimon J. Gerraty 	 */
5415fff9558SSimon J. Gerraty 	mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0;
5425fff9558SSimon J. Gerraty 	mc.seconds = (ve_utc % SECONDS_PER_DAY);
5435fff9558SSimon J. Gerraty #endif
54466655411SSimon J. Gerraty #endif
5455fff9558SSimon J. Gerraty 	mc.vtable->start_chain(&mc.vtable, NULL);
5465fff9558SSimon J. Gerraty 	for (u = 0; u < VEC_LEN(chain); u ++) {
5475fff9558SSimon J. Gerraty 		xc = &VEC_ELT(chain, u);
5485fff9558SSimon J. Gerraty 		mc.vtable->start_cert(&mc.vtable, xc->data_len);
5495fff9558SSimon J. Gerraty 		mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
5505fff9558SSimon J. Gerraty 		mc.vtable->end_cert(&mc.vtable);
5515fff9558SSimon J. Gerraty 		switch (mc.err) {
5525fff9558SSimon J. Gerraty 		case 0:
5535fff9558SSimon J. Gerraty 		case BR_ERR_X509_OK:
5545fff9558SSimon J. Gerraty 		case BR_ERR_X509_EXPIRED:
5555fff9558SSimon J. Gerraty 			break;
5565fff9558SSimon J. Gerraty 		default:
5575fff9558SSimon J. Gerraty 			printf("u=%zu mc.err=%d\n", u, mc.err);
5585fff9558SSimon J. Gerraty 			break;
5595fff9558SSimon J. Gerraty 		}
5605fff9558SSimon J. Gerraty 	}
5615fff9558SSimon J. Gerraty 	err = mc.vtable->end_chain(&mc.vtable);
5625fff9558SSimon J. Gerraty 	pk = NULL;
5635fff9558SSimon J. Gerraty 	if (err) {
56466655411SSimon J. Gerraty 		char date[12];
56566655411SSimon J. Gerraty 
56666655411SSimon J. Gerraty 		switch (err) {
56766655411SSimon J. Gerraty 		case 54:
56866655411SSimon J. Gerraty 			ve_error_set("Validation failed, certificate not valid as of %s",
56966655411SSimon J. Gerraty 			    gdate(date, sizeof(date), ve_utc));
57066655411SSimon J. Gerraty 			break;
571*4b9d6057SStéphane Rochoy 		default: {
572*4b9d6057SStéphane Rochoy 			const char *err_desc = NULL;
573*4b9d6057SStéphane Rochoy 			const char *err_name = find_error_name(err, &err_desc);
574*4b9d6057SStéphane Rochoy 
575*4b9d6057SStéphane Rochoy 			if (err_name == NULL)
576*4b9d6057SStéphane Rochoy 				ve_error_set("Validation failed, err = %d",
577*4b9d6057SStéphane Rochoy 				    err);
578*4b9d6057SStéphane Rochoy 			else
579*4b9d6057SStéphane Rochoy 				ve_error_set("Validation failed, %s (%s)",
580*4b9d6057SStéphane Rochoy 				    err_desc, err_name);
581*4b9d6057SStéphane Rochoy 			break; }
58266655411SSimon J. Gerraty 		}
5835fff9558SSimon J. Gerraty 	} else {
5845fff9558SSimon J. Gerraty 		tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
5855fff9558SSimon J. Gerraty 		if (tpk != NULL) {
5865fff9558SSimon J. Gerraty 			pk = xpkeydup(tpk);
5875fff9558SSimon J. Gerraty 		}
5885fff9558SSimon J. Gerraty 	}
58913ea0450SMarcin Wojtas 	VEC_CLEAR(chain);
5905fff9558SSimon J. Gerraty 	return (pk);
5915fff9558SSimon J. Gerraty }
5925fff9558SSimon J. Gerraty 
59313ea0450SMarcin Wojtas /*
59413ea0450SMarcin Wojtas  * Check if digest of one of the certificates from verified chain
59513ea0450SMarcin Wojtas  * is present in the forbidden database.
59613ea0450SMarcin Wojtas  * Since UEFI allows to store three types of digests
59713ea0450SMarcin Wojtas  * all of them have to be checked separately.
59813ea0450SMarcin Wojtas  */
59913ea0450SMarcin Wojtas static int
60013ea0450SMarcin Wojtas check_forbidden_digests(br_x509_certificate *xcs, size_t num)
60113ea0450SMarcin Wojtas {
60213ea0450SMarcin Wojtas 	unsigned char sha256_digest[br_sha256_SIZE];
60313ea0450SMarcin Wojtas 	unsigned char sha384_digest[br_sha384_SIZE];
60413ea0450SMarcin Wojtas 	unsigned char sha512_digest[br_sha512_SIZE];
60513ea0450SMarcin Wojtas 	void *tbs;
60613ea0450SMarcin Wojtas 	hash_data *digest;
60713ea0450SMarcin Wojtas 	br_hash_compat_context ctx;
60813ea0450SMarcin Wojtas 	const br_hash_class *md;
60913ea0450SMarcin Wojtas 	size_t tbs_len, i;
61013ea0450SMarcin Wojtas 	int have_sha256, have_sha384, have_sha512;
61113ea0450SMarcin Wojtas 
61213ea0450SMarcin Wojtas 	if (VEC_LEN(forbidden_digests) == 0)
61313ea0450SMarcin Wojtas 		return (0);
61413ea0450SMarcin Wojtas 
61513ea0450SMarcin Wojtas 	/*
61613ea0450SMarcin Wojtas 	 * Iterate through certificates, extract their To-Be-Signed section,
61713ea0450SMarcin Wojtas 	 * and compare its digest against the ones in the forbidden database.
61813ea0450SMarcin Wojtas 	 */
61913ea0450SMarcin Wojtas 	while (num--) {
62013ea0450SMarcin Wojtas 		tbs = X509_to_tbs(xcs[num].data, &tbs_len);
62113ea0450SMarcin Wojtas 		if (tbs == NULL) {
62213ea0450SMarcin Wojtas 			printf("Failed to obtain TBS part of certificate\n");
62313ea0450SMarcin Wojtas 			return (1);
62413ea0450SMarcin Wojtas 		}
62513ea0450SMarcin Wojtas 		have_sha256 = have_sha384 = have_sha512 = 0;
62613ea0450SMarcin Wojtas 
62713ea0450SMarcin Wojtas 		for (i = 0; i < VEC_LEN(forbidden_digests); i++) {
62813ea0450SMarcin Wojtas 			digest = &VEC_ELT(forbidden_digests, i);
62913ea0450SMarcin Wojtas 			switch (digest->hash_size) {
63013ea0450SMarcin Wojtas 			case br_sha256_SIZE:
63113ea0450SMarcin Wojtas 				if (!have_sha256) {
63213ea0450SMarcin Wojtas 					have_sha256 = 1;
63313ea0450SMarcin Wojtas 					md = &br_sha256_vtable;
63413ea0450SMarcin Wojtas 					md->init(&ctx.vtable);
63513ea0450SMarcin Wojtas 					md->update(&ctx.vtable, tbs, tbs_len);
63613ea0450SMarcin Wojtas 					md->out(&ctx.vtable, sha256_digest);
63713ea0450SMarcin Wojtas 				}
63813ea0450SMarcin Wojtas 				if (!memcmp(sha256_digest,
63913ea0450SMarcin Wojtas 					digest->data,
64013ea0450SMarcin Wojtas 					br_sha256_SIZE))
64113ea0450SMarcin Wojtas 					return (1);
64213ea0450SMarcin Wojtas 
64313ea0450SMarcin Wojtas 				break;
64413ea0450SMarcin Wojtas 			case br_sha384_SIZE:
64513ea0450SMarcin Wojtas 				if (!have_sha384) {
64613ea0450SMarcin Wojtas 					have_sha384 = 1;
64713ea0450SMarcin Wojtas 					md = &br_sha384_vtable;
64813ea0450SMarcin Wojtas 					md->init(&ctx.vtable);
64913ea0450SMarcin Wojtas 					md->update(&ctx.vtable, tbs, tbs_len);
65013ea0450SMarcin Wojtas 					md->out(&ctx.vtable, sha384_digest);
65113ea0450SMarcin Wojtas 				}
65213ea0450SMarcin Wojtas 				if (!memcmp(sha384_digest,
65313ea0450SMarcin Wojtas 					digest->data,
65413ea0450SMarcin Wojtas 					br_sha384_SIZE))
65513ea0450SMarcin Wojtas 					return (1);
65613ea0450SMarcin Wojtas 
65713ea0450SMarcin Wojtas 				break;
65813ea0450SMarcin Wojtas 			case br_sha512_SIZE:
65913ea0450SMarcin Wojtas 				if (!have_sha512) {
66013ea0450SMarcin Wojtas 					have_sha512 = 1;
66113ea0450SMarcin Wojtas 					md = &br_sha512_vtable;
66213ea0450SMarcin Wojtas 					md->init(&ctx.vtable);
66313ea0450SMarcin Wojtas 					md->update(&ctx.vtable, tbs, tbs_len);
66413ea0450SMarcin Wojtas 					md->out(&ctx.vtable, sha512_digest);
66513ea0450SMarcin Wojtas 				}
66613ea0450SMarcin Wojtas 				if (!memcmp(sha512_digest,
66713ea0450SMarcin Wojtas 					digest->data,
66813ea0450SMarcin Wojtas 					br_sha512_SIZE))
66913ea0450SMarcin Wojtas 					return (1);
67013ea0450SMarcin Wojtas 
67113ea0450SMarcin Wojtas 				break;
67213ea0450SMarcin Wojtas 			}
67313ea0450SMarcin Wojtas 		}
67413ea0450SMarcin Wojtas 	}
67513ea0450SMarcin Wojtas 
67613ea0450SMarcin Wojtas 	return (0);
67713ea0450SMarcin Wojtas }
67813ea0450SMarcin Wojtas 
6795fff9558SSimon J. Gerraty static br_x509_pkey *
6805fff9558SSimon J. Gerraty verify_signer(const char *certs,
6815fff9558SSimon J. Gerraty     br_name_element *elts, size_t num_elts)
6825fff9558SSimon J. Gerraty {
6835fff9558SSimon J. Gerraty 	br_x509_certificate *xcs;
6845fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
6855fff9558SSimon J. Gerraty 	size_t num;
6865fff9558SSimon J. Gerraty 
68713ea0450SMarcin Wojtas 	pk = NULL;
68813ea0450SMarcin Wojtas 
6895fff9558SSimon J. Gerraty 	ve_trust_init();
6905fff9558SSimon J. Gerraty 	xcs = read_certificates(certs, &num);
6915fff9558SSimon J. Gerraty 	if (xcs == NULL) {
6925fff9558SSimon J. Gerraty 		ve_error_set("cannot read certificates\n");
6935fff9558SSimon J. Gerraty 		return (NULL);
6945fff9558SSimon J. Gerraty 	}
69513ea0450SMarcin Wojtas 
69613ea0450SMarcin Wojtas 	/*
69713ea0450SMarcin Wojtas 	 * Check if either
69813ea0450SMarcin Wojtas 	 * 1. There is a direct match between cert from forbidden_anchors
69913ea0450SMarcin Wojtas 	 * and a cert from chain.
70013ea0450SMarcin Wojtas 	 * 2. CA that signed the chain is found in forbidden_anchors.
70113ea0450SMarcin Wojtas 	 */
70213ea0450SMarcin Wojtas 	if (VEC_LEN(forbidden_anchors) > 0)
70313ea0450SMarcin Wojtas 		pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors);
70413ea0450SMarcin Wojtas 	if (pk != NULL) {
70513ea0450SMarcin Wojtas 		ve_error_set("Certificate is on forbidden list\n");
70613ea0450SMarcin Wojtas 		xfreepkey(pk);
70713ea0450SMarcin Wojtas 		pk = NULL;
70813ea0450SMarcin Wojtas 		goto out;
70913ea0450SMarcin Wojtas 	}
71013ea0450SMarcin Wojtas 
71113ea0450SMarcin Wojtas 	pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors);
71213ea0450SMarcin Wojtas 	if (pk == NULL)
71313ea0450SMarcin Wojtas 		goto out;
71413ea0450SMarcin Wojtas 
71513ea0450SMarcin Wojtas 	/*
71613ea0450SMarcin Wojtas 	 * Check if hash of tbs part of any certificate in chain
71713ea0450SMarcin Wojtas 	 * is on the forbidden list.
71813ea0450SMarcin Wojtas 	 */
71913ea0450SMarcin Wojtas 	if (check_forbidden_digests(xcs, num)) {
72013ea0450SMarcin Wojtas 		ve_error_set("Certificate hash is on forbidden list\n");
72113ea0450SMarcin Wojtas 		xfreepkey(pk);
72213ea0450SMarcin Wojtas 		pk = NULL;
72313ea0450SMarcin Wojtas 	}
72413ea0450SMarcin Wojtas out:
72513ea0450SMarcin Wojtas 	free_certificates(xcs, num);
7265fff9558SSimon J. Gerraty 	return (pk);
7275fff9558SSimon J. Gerraty }
7285fff9558SSimon J. Gerraty 
7295fff9558SSimon J. Gerraty /**
7305fff9558SSimon J. Gerraty  * we need a hex digest including trailing newline below
7315fff9558SSimon J. Gerraty  */
7325fff9558SSimon J. Gerraty char *
7335fff9558SSimon J. Gerraty hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len)
7345fff9558SSimon J. Gerraty {
7355fff9558SSimon J. Gerraty 	char const hex2ascii[] = "0123456789abcdef";
7365fff9558SSimon J. Gerraty 	size_t i;
7375fff9558SSimon J. Gerraty 
7385fff9558SSimon J. Gerraty 	/* every binary byte is 2 chars in hex + newline + null  */
7395fff9558SSimon J. Gerraty 	if (bufsz < (2 * foo_len) + 2)
7405fff9558SSimon J. Gerraty 		return (NULL);
7415fff9558SSimon J. Gerraty 
7425fff9558SSimon J. Gerraty 	for (i = 0; i < foo_len; i++) {
7435fff9558SSimon J. Gerraty 		buf[i * 2] = hex2ascii[foo[i] >> 4];
7445fff9558SSimon J. Gerraty 		buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f];
7455fff9558SSimon J. Gerraty 	}
7465fff9558SSimon J. Gerraty 
7475fff9558SSimon J. Gerraty 	buf[i * 2] = 0x0A; /* we also want a newline */
7485fff9558SSimon J. Gerraty 	buf[i * 2 + 1] = '\0';
7495fff9558SSimon J. Gerraty 
7505fff9558SSimon J. Gerraty 	return (buf);
7515fff9558SSimon J. Gerraty }
7525fff9558SSimon J. Gerraty 
7535fff9558SSimon J. Gerraty /**
7545fff9558SSimon J. Gerraty  * @brief
7555fff9558SSimon J. Gerraty  * verify file against sigfile using pk
7565fff9558SSimon J. Gerraty  *
7575fff9558SSimon J. Gerraty  * When we generated the signature in sigfile,
7585fff9558SSimon J. Gerraty  * we hashed (sha256) file, and sent that to signing server
7595fff9558SSimon J. Gerraty  * which hashed (sha256) that hash.
7605fff9558SSimon J. Gerraty  *
7615fff9558SSimon J. Gerraty  * To verify we need to replicate that result.
7625fff9558SSimon J. Gerraty  *
7635fff9558SSimon J. Gerraty  * @param[in] pk
7645fff9558SSimon J. Gerraty  *	br_x509_pkey
7655fff9558SSimon J. Gerraty  *
7665fff9558SSimon J. Gerraty  * @paramp[in] file
7675fff9558SSimon J. Gerraty  *	file to be verified
7685fff9558SSimon J. Gerraty  *
7695fff9558SSimon J. Gerraty  * @param[in] sigfile
7705fff9558SSimon J. Gerraty  * 	signature (PEM encoded)
7715fff9558SSimon J. Gerraty  *
7725fff9558SSimon J. Gerraty  * @return NULL on error, otherwise content of file.
7735fff9558SSimon J. Gerraty  */
7745fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
7755fff9558SSimon J. Gerraty static unsigned char *
7765fff9558SSimon J. Gerraty verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile)
7775fff9558SSimon J. Gerraty {
7780e47020fSSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN
7790e47020fSSimon J. Gerraty 	char *hex, hexbuf[br_sha512_SIZE * 2 + 2];
7800e47020fSSimon J. Gerraty #endif
7815fff9558SSimon J. Gerraty 	unsigned char rhbuf[br_sha512_SIZE];
7825fff9558SSimon J. Gerraty 	br_sha256_context ctx;
7835fff9558SSimon J. Gerraty 	unsigned char *fcp, *scp;
7845fff9558SSimon J. Gerraty 	size_t flen, slen, plen;
7855fff9558SSimon J. Gerraty 	pem_object *po;
7865fff9558SSimon J. Gerraty 	const br_ec_impl *ec;
7875fff9558SSimon J. Gerraty 	br_ecdsa_vrfy vrfy;
7885fff9558SSimon J. Gerraty 
7895fff9558SSimon J. Gerraty 	if ((fcp = read_file(file, &flen)) == NULL)
7905fff9558SSimon J. Gerraty 		return (NULL);
7915fff9558SSimon J. Gerraty 	if ((scp = read_file(sigfile, &slen)) == NULL) {
7925fff9558SSimon J. Gerraty 		free(fcp);
7935fff9558SSimon J. Gerraty 		return (NULL);
7945fff9558SSimon J. Gerraty 	}
7955fff9558SSimon J. Gerraty 	if ((po = decode_pem(scp, slen, &plen)) == NULL) {
7965fff9558SSimon J. Gerraty 		free(fcp);
7975fff9558SSimon J. Gerraty 		free(scp);
7985fff9558SSimon J. Gerraty 		return (NULL);
7995fff9558SSimon J. Gerraty 	}
8005fff9558SSimon J. Gerraty 	br_sha256_init(&ctx);
8015fff9558SSimon J. Gerraty 	br_sha256_update(&ctx, fcp, flen);
8025fff9558SSimon J. Gerraty 	br_sha256_out(&ctx, rhbuf);
803f9510887SSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN
8045fff9558SSimon J. Gerraty 	hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE);
8055fff9558SSimon J. Gerraty 	/* now hash that */
8065fff9558SSimon J. Gerraty 	if (hex) {
8075fff9558SSimon J. Gerraty 		br_sha256_init(&ctx);
8085fff9558SSimon J. Gerraty 		br_sha256_update(&ctx, hex, strlen(hex));
8095fff9558SSimon J. Gerraty 		br_sha256_out(&ctx, rhbuf);
8105fff9558SSimon J. Gerraty 	}
811f9510887SSimon J. Gerraty #endif
8125fff9558SSimon J. Gerraty 	ec = br_ec_get_default();
8135fff9558SSimon J. Gerraty 	vrfy = br_ecdsa_vrfy_asn1_get_default();
8145fff9558SSimon J. Gerraty 	if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data,
8155fff9558SSimon J. Gerraty 		po->data_len)) {
8165fff9558SSimon J. Gerraty 		free(fcp);
8175fff9558SSimon J. Gerraty 		fcp = NULL;
8185fff9558SSimon J. Gerraty 	}
8195fff9558SSimon J. Gerraty 	free(scp);
8205fff9558SSimon J. Gerraty 	return (fcp);
8215fff9558SSimon J. Gerraty }
8225fff9558SSimon J. Gerraty #endif
8235fff9558SSimon J. Gerraty 
8245fff9558SSimon J. Gerraty #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT)
8255fff9558SSimon J. Gerraty /**
8265fff9558SSimon J. Gerraty  * @brief verify an rsa digest
8275fff9558SSimon J. Gerraty  *
8285fff9558SSimon J. Gerraty  * @return 0 on failure
8295fff9558SSimon J. Gerraty  */
8305fff9558SSimon J. Gerraty int
8315fff9558SSimon J. Gerraty verify_rsa_digest (br_rsa_public_key *pkey,
8325fff9558SSimon J. Gerraty     const unsigned char *hash_oid,
8335fff9558SSimon J. Gerraty     unsigned char *mdata, size_t mlen,
8345fff9558SSimon J. Gerraty     unsigned char *sdata, size_t slen)
8355fff9558SSimon J. Gerraty {
8365fff9558SSimon J. Gerraty 	br_rsa_pkcs1_vrfy vrfy;
8375fff9558SSimon J. Gerraty 	unsigned char vhbuf[br_sha512_SIZE];
8385fff9558SSimon J. Gerraty 
8395fff9558SSimon J. Gerraty 	vrfy = br_rsa_pkcs1_vrfy_get_default();
8405fff9558SSimon J. Gerraty 
8415fff9558SSimon J. Gerraty 	if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) ||
8425fff9558SSimon J. Gerraty 	    memcmp(vhbuf, mdata, mlen) != 0) {
8435fff9558SSimon J. Gerraty 		return (0);		/* fail */
8445fff9558SSimon J. Gerraty 	}
8455fff9558SSimon J. Gerraty 	return (1);			/* ok */
8465fff9558SSimon J. Gerraty }
8475fff9558SSimon J. Gerraty #endif
8485fff9558SSimon J. Gerraty 
8495fff9558SSimon J. Gerraty /**
8505fff9558SSimon J. Gerraty  * @brief
8515fff9558SSimon J. Gerraty  * verify file against sigfile using pk
8525fff9558SSimon J. Gerraty  *
8535fff9558SSimon J. Gerraty  * When we generated the signature in sigfile,
8545fff9558SSimon J. Gerraty  * we hashed (sha256) file, and sent that to signing server
8555fff9558SSimon J. Gerraty  * which hashed (sha256) that hash.
8565fff9558SSimon J. Gerraty  *
8575fff9558SSimon J. Gerraty  * Or (deprecated) we simply used sha1 hash directly.
8585fff9558SSimon J. Gerraty  *
8595fff9558SSimon J. Gerraty  * To verify we need to replicate that result.
8605fff9558SSimon J. Gerraty  *
8615fff9558SSimon J. Gerraty  * @param[in] pk
8625fff9558SSimon J. Gerraty  *	br_x509_pkey
8635fff9558SSimon J. Gerraty  *
8645fff9558SSimon J. Gerraty  * @paramp[in] file
8655fff9558SSimon J. Gerraty  *	file to be verified
8665fff9558SSimon J. Gerraty  *
8675fff9558SSimon J. Gerraty  * @param[in] sigfile
8685fff9558SSimon J. Gerraty  * 	signature (PEM encoded)
8695fff9558SSimon J. Gerraty  *
8705fff9558SSimon J. Gerraty  * @return NULL on error, otherwise content of file.
8715fff9558SSimon J. Gerraty  */
8725fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
8735fff9558SSimon J. Gerraty static unsigned char *
8745fff9558SSimon J. Gerraty verify_rsa(br_x509_pkey *pk,  const char *file, const char *sigfile)
8755fff9558SSimon J. Gerraty {
8765fff9558SSimon J. Gerraty 	unsigned char rhbuf[br_sha512_SIZE];
8775fff9558SSimon J. Gerraty 	const unsigned char *hash_oid;
8785fff9558SSimon J. Gerraty 	const br_hash_class *md;
8795fff9558SSimon J. Gerraty 	br_hash_compat_context mctx;
8805fff9558SSimon J. Gerraty 	unsigned char *fcp, *scp;
8815fff9558SSimon J. Gerraty 	size_t flen, slen, plen, hlen;
8825fff9558SSimon J. Gerraty 	pem_object *po;
8835fff9558SSimon J. Gerraty 
8845fff9558SSimon J. Gerraty 	if ((fcp = read_file(file, &flen)) == NULL)
8855fff9558SSimon J. Gerraty 		return (NULL);
8865fff9558SSimon J. Gerraty 	if ((scp = read_file(sigfile, &slen)) == NULL) {
8875fff9558SSimon J. Gerraty 		free(fcp);
8885fff9558SSimon J. Gerraty 		return (NULL);
8895fff9558SSimon J. Gerraty 	}
8905fff9558SSimon J. Gerraty 	if ((po = decode_pem(scp, slen, &plen)) == NULL) {
8915fff9558SSimon J. Gerraty 		free(fcp);
8925fff9558SSimon J. Gerraty 		free(scp);
8935fff9558SSimon J. Gerraty 		return (NULL);
8945fff9558SSimon J. Gerraty 	}
8955fff9558SSimon J. Gerraty 
8965fff9558SSimon J. Gerraty 	switch (po->data_len) {
8975fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
8985fff9558SSimon J. Gerraty 	case 256:
8995fff9558SSimon J. Gerraty 		// this is our old deprecated sig method
9005fff9558SSimon J. Gerraty 		md = &br_sha1_vtable;
9015fff9558SSimon J. Gerraty 		hlen = br_sha1_SIZE;
9025fff9558SSimon J. Gerraty 		hash_oid = BR_HASH_OID_SHA1;
9035fff9558SSimon J. Gerraty 		break;
9045fff9558SSimon J. Gerraty #endif
9055fff9558SSimon J. Gerraty 	default:
9065fff9558SSimon J. Gerraty 		md = &br_sha256_vtable;
9075fff9558SSimon J. Gerraty 		hlen = br_sha256_SIZE;
9085fff9558SSimon J. Gerraty 		hash_oid = BR_HASH_OID_SHA256;
9095fff9558SSimon J. Gerraty 		break;
9105fff9558SSimon J. Gerraty 	}
9115fff9558SSimon J. Gerraty 	md->init(&mctx.vtable);
9125fff9558SSimon J. Gerraty 	md->update(&mctx.vtable, fcp, flen);
9135fff9558SSimon J. Gerraty 	md->out(&mctx.vtable, rhbuf);
9145fff9558SSimon J. Gerraty 	if (!verify_rsa_digest(&pk->key.rsa, hash_oid,
9155fff9558SSimon J. Gerraty 		rhbuf, hlen, po->data, po->data_len)) {
9165fff9558SSimon J. Gerraty 		free(fcp);
9175fff9558SSimon J. Gerraty 		fcp = NULL;
9185fff9558SSimon J. Gerraty 	}
9195fff9558SSimon J. Gerraty 	free(scp);
9205fff9558SSimon J. Gerraty 	return (fcp);
9215fff9558SSimon J. Gerraty }
9225fff9558SSimon J. Gerraty #endif
9235fff9558SSimon J. Gerraty 
9245fff9558SSimon J. Gerraty /**
9255fff9558SSimon J. Gerraty  * @brief
9265fff9558SSimon J. Gerraty  * verify a signature and return content of signed file
9275fff9558SSimon J. Gerraty  *
9285fff9558SSimon J. Gerraty  * @param[in] sigfile
9295fff9558SSimon J. Gerraty  * 	file containing signature
9305fff9558SSimon J. Gerraty  * 	we derrive path of signed file and certificate change from
9315fff9558SSimon J. Gerraty  * 	this.
9325fff9558SSimon J. Gerraty  *
9335fff9558SSimon J. Gerraty  * @param[in] flags
9345fff9558SSimon J. Gerraty  * 	only bit 1 significant so far
9355fff9558SSimon J. Gerraty  *
9365fff9558SSimon J. Gerraty  * @return NULL on error otherwise content of signed file
9375fff9558SSimon J. Gerraty  */
9385fff9558SSimon J. Gerraty unsigned char *
9395fff9558SSimon J. Gerraty verify_sig(const char *sigfile, int flags)
9405fff9558SSimon J. Gerraty {
9415fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
9425fff9558SSimon J. Gerraty 	br_name_element cn;
9435fff9558SSimon J. Gerraty 	char cn_buf[80];
9445fff9558SSimon J. Gerraty 	unsigned char cn_oid[4];
9455fff9558SSimon J. Gerraty 	char pbuf[MAXPATHLEN];
9465fff9558SSimon J. Gerraty 	char *cp;
9475fff9558SSimon J. Gerraty 	unsigned char *ucp;
9485fff9558SSimon J. Gerraty 	size_t n;
9495fff9558SSimon J. Gerraty 
9505fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile));
9515fff9558SSimon J. Gerraty 	n = strlcpy(pbuf, sigfile, sizeof(pbuf));
9525fff9558SSimon J. Gerraty 	if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0)
9535fff9558SSimon J. Gerraty 		return (NULL);
9545fff9558SSimon J. Gerraty 	cp = strcpy(&pbuf[n - 3], "certs");
9555fff9558SSimon J. Gerraty 	/*
9565fff9558SSimon J. Gerraty 	 * We want the commonName field
9575fff9558SSimon J. Gerraty 	 * the OID we want is 2,5,4,3 - but DER encoded
9585fff9558SSimon J. Gerraty 	 */
9595fff9558SSimon J. Gerraty 	cn_oid[0] = 3;
9605fff9558SSimon J. Gerraty 	cn_oid[1] = 0x55;
9615fff9558SSimon J. Gerraty 	cn_oid[2] = 4;
9625fff9558SSimon J. Gerraty 	cn_oid[3] = 3;
9635fff9558SSimon J. Gerraty 	cn.oid = cn_oid;
9645fff9558SSimon J. Gerraty 	cn.buf = cn_buf;
9655fff9558SSimon J. Gerraty 	cn.len = sizeof(cn_buf);
9665fff9558SSimon J. Gerraty 
9675fff9558SSimon J. Gerraty 	pk = verify_signer(pbuf, &cn, 1);
9685fff9558SSimon J. Gerraty 	if (!pk) {
9695fff9558SSimon J. Gerraty 		printf("cannot verify: %s: %s\n", pbuf, ve_error_get());
9705fff9558SSimon J. Gerraty 		return (NULL);
9715fff9558SSimon J. Gerraty 	}
9725fff9558SSimon J. Gerraty 	for (; cp > pbuf; cp--) {
9735fff9558SSimon J. Gerraty 		if (*cp == '.') {
9745fff9558SSimon J. Gerraty 			*cp = '\0';
9755fff9558SSimon J. Gerraty 			break;
9765fff9558SSimon J. Gerraty 		}
9775fff9558SSimon J. Gerraty 	}
9785fff9558SSimon J. Gerraty 	switch (pk->key_type) {
9795fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
9805fff9558SSimon J. Gerraty 	case BR_KEYTYPE_EC:
9815fff9558SSimon J. Gerraty 		ucp = verify_ec(pk, pbuf, sigfile);
9825fff9558SSimon J. Gerraty 		break;
9835fff9558SSimon J. Gerraty #endif
9845fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
9855fff9558SSimon J. Gerraty 	case BR_KEYTYPE_RSA:
9865fff9558SSimon J. Gerraty 		ucp = verify_rsa(pk, pbuf, sigfile);
9875fff9558SSimon J. Gerraty 		break;
9885fff9558SSimon J. Gerraty #endif
9895fff9558SSimon J. Gerraty 	default:
9905fff9558SSimon J. Gerraty 		ucp = NULL;		/* not supported */
9915fff9558SSimon J. Gerraty 	}
9925fff9558SSimon J. Gerraty 	xfreepkey(pk);
9935fff9558SSimon J. Gerraty 	if (!ucp) {
9945fff9558SSimon J. Gerraty 		printf("Unverified %s (%s)\n", pbuf,
9955fff9558SSimon J. Gerraty 		    cn.status ? cn_buf : "unknown");
99666655411SSimon J. Gerraty 	} else if ((flags & VEF_VERBOSE) != 0) {
9975fff9558SSimon J. Gerraty 		printf("Verified %s signed by %s\n", pbuf,
9985fff9558SSimon J. Gerraty 		    cn.status ? cn_buf : "someone we trust");
9995fff9558SSimon J. Gerraty 	}
10005fff9558SSimon J. Gerraty 	return (ucp);
10015fff9558SSimon J. Gerraty }
10025fff9558SSimon J. Gerraty 
10035fff9558SSimon J. Gerraty 
10045fff9558SSimon J. Gerraty /**
10055fff9558SSimon J. Gerraty  * @brief verify hash matches
10065fff9558SSimon J. Gerraty  *
10075fff9558SSimon J. Gerraty  * We have finished hashing a file,
10085fff9558SSimon J. Gerraty  * see if we got the desired result.
10095fff9558SSimon J. Gerraty  *
10105fff9558SSimon J. Gerraty  * @param[in] ctx
10115fff9558SSimon J. Gerraty  *	pointer to hash context
10125fff9558SSimon J. Gerraty  *
10135fff9558SSimon J. Gerraty  * @param[in] md
10145fff9558SSimon J. Gerraty  *	pointer to hash class
10155fff9558SSimon J. Gerraty  *
10165fff9558SSimon J. Gerraty  * @param[in] path
10175fff9558SSimon J. Gerraty  *	name of the file we are checking
10185fff9558SSimon J. Gerraty  *
10195fff9558SSimon J. Gerraty  * @param[in] want
10205fff9558SSimon J. Gerraty  *	the expected result
10215fff9558SSimon J. Gerraty  *
10225fff9558SSimon J. Gerraty  * @param[in] hlen
10235fff9558SSimon J. Gerraty  *	size of hash output
10245fff9558SSimon J. Gerraty  *
10255fff9558SSimon J. Gerraty  * @return 0 on success
10265fff9558SSimon J. Gerraty  */
10275fff9558SSimon J. Gerraty int
10285fff9558SSimon J. Gerraty ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md,
10295fff9558SSimon J. Gerraty     const char *path, const char *want, size_t hlen)
10305fff9558SSimon J. Gerraty {
10315fff9558SSimon J. Gerraty 	char hexbuf[br_sha512_SIZE * 2 + 2];
10325fff9558SSimon J. Gerraty 	unsigned char hbuf[br_sha512_SIZE];
10335fff9558SSimon J. Gerraty 	char *hex;
10345fff9558SSimon J. Gerraty 	int rc;
10355fff9558SSimon J. Gerraty 	int n;
10365fff9558SSimon J. Gerraty 
10375fff9558SSimon J. Gerraty 	md->out(&ctx->vtable, hbuf);
10385fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT
103953f151f9SSimon J. Gerraty 	ve_pcr_update(path, hbuf, hlen);
10405fff9558SSimon J. Gerraty #endif
10415fff9558SSimon J. Gerraty 	hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
10425fff9558SSimon J. Gerraty 	if (!hex)
10435fff9558SSimon J. Gerraty 		return (VE_FINGERPRINT_WRONG);
10445fff9558SSimon J. Gerraty 	n = 2*hlen;
10455fff9558SSimon J. Gerraty 	if ((rc = strncmp(hex, want, n))) {
10465fff9558SSimon J. Gerraty 		ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want);
10475fff9558SSimon J. Gerraty 		rc = VE_FINGERPRINT_WRONG;
10485fff9558SSimon J. Gerraty 	}
10495fff9558SSimon J. Gerraty 	return (rc ? rc : VE_FINGERPRINT_OK);
10505fff9558SSimon J. Gerraty }
10515fff9558SSimon J. Gerraty 
10525fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR
10535fff9558SSimon J. Gerraty static int
10545fff9558SSimon J. Gerraty test_hash(const br_hash_class *md, size_t hlen,
10555fff9558SSimon J. Gerraty     const char *hname, const char *s, size_t slen, const char *want)
10565fff9558SSimon J. Gerraty {
10575fff9558SSimon J. Gerraty 	br_hash_compat_context mctx;
10585fff9558SSimon J. Gerraty 
10595fff9558SSimon J. Gerraty 	md->init(&mctx.vtable);
10605fff9558SSimon J. Gerraty 	md->update(&mctx.vtable, s, slen);
10615fff9558SSimon J. Gerraty 	return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK);
10625fff9558SSimon J. Gerraty }
10635fff9558SSimon J. Gerraty 
10645fff9558SSimon J. Gerraty #endif
10655fff9558SSimon J. Gerraty 
10665fff9558SSimon J. Gerraty #define ve_test_hash(n, N) \
10675fff9558SSimon J. Gerraty 	printf("Testing hash: " #n "\t\t\t\t%s\n", \
10685fff9558SSimon J. Gerraty 	    test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \
10699bee6a60SSimon J. Gerraty 	    VE_HASH_KAT_STR, VE_HASH_KAT_STRLEN(VE_HASH_KAT_STR), \
10705fff9558SSimon J. Gerraty 	    vh_ ## N) ? "Failed" : "Passed")
10715fff9558SSimon J. Gerraty 
10725fff9558SSimon J. Gerraty /**
10735fff9558SSimon J. Gerraty  * @brief
10745fff9558SSimon J. Gerraty  * run self tests on hash and signature verification
10755fff9558SSimon J. Gerraty  *
10765fff9558SSimon J. Gerraty  * Test that the hash methods (SHA1 and SHA256) work.
10775fff9558SSimon J. Gerraty  * Test that we can verify a certificate for each supported
10785fff9558SSimon J. Gerraty  * Root CA.
10795fff9558SSimon J. Gerraty  *
10805fff9558SSimon J. Gerraty  * @return cached result.
10815fff9558SSimon J. Gerraty  */
10825fff9558SSimon J. Gerraty int
10835fff9558SSimon J. Gerraty ve_self_tests(void)
10845fff9558SSimon J. Gerraty {
10855fff9558SSimon J. Gerraty 	static int once = -1;
10865fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR
10875fff9558SSimon J. Gerraty 	br_x509_certificate *xcs;
10885fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
10895fff9558SSimon J. Gerraty 	br_name_element cn;
10905fff9558SSimon J. Gerraty 	char cn_buf[80];
10915fff9558SSimon J. Gerraty 	unsigned char cn_oid[4];
10925fff9558SSimon J. Gerraty 	size_t num;
10935fff9558SSimon J. Gerraty 	size_t u;
10945fff9558SSimon J. Gerraty #endif
10955fff9558SSimon J. Gerraty 
10965fff9558SSimon J. Gerraty 	if (once >= 0)
10975fff9558SSimon J. Gerraty 		return (once);
10985fff9558SSimon J. Gerraty 	once = 0;
10995fff9558SSimon J. Gerraty 
11005fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("Self tests...\n"));
11015fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR
11025fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT
11035fff9558SSimon J. Gerraty 	ve_test_hash(sha1, SHA1);
11045fff9558SSimon J. Gerraty #endif
11055fff9558SSimon J. Gerraty #ifdef VE_SHA256_SUPPORT
11065fff9558SSimon J. Gerraty 	ve_test_hash(sha256, SHA256);
11075fff9558SSimon J. Gerraty #endif
11085fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT
11095fff9558SSimon J. Gerraty 	ve_test_hash(sha384, SHA384);
11105fff9558SSimon J. Gerraty #endif
11115fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT
11125fff9558SSimon J. Gerraty 	ve_test_hash(sha512, SHA512);
11135fff9558SSimon J. Gerraty #endif
11145fff9558SSimon J. Gerraty #endif
11155fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR
11165fff9558SSimon J. Gerraty 	xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
11175fff9558SSimon J. Gerraty 	    sizeof(VERIFY_CERTS_STR), &num);
11189bee6a60SSimon J. Gerraty 	if (xcs != NULL) {
11195fff9558SSimon J. Gerraty 		/*
11205fff9558SSimon J. Gerraty 		 * We want the commonName field
11215fff9558SSimon J. Gerraty 		 * the OID we want is 2,5,4,3 - but DER encoded
11225fff9558SSimon J. Gerraty 		 */
11235fff9558SSimon J. Gerraty 		cn_oid[0] = 3;
11245fff9558SSimon J. Gerraty 		cn_oid[1] = 0x55;
11255fff9558SSimon J. Gerraty 		cn_oid[2] = 4;
11265fff9558SSimon J. Gerraty 		cn_oid[3] = 3;
11275fff9558SSimon J. Gerraty 		cn.oid = cn_oid;
11285fff9558SSimon J. Gerraty 		cn.buf = cn_buf;
11295fff9558SSimon J. Gerraty 
11305fff9558SSimon J. Gerraty 		for (u = 0; u < num; u ++) {
11315fff9558SSimon J. Gerraty 			cn.len = sizeof(cn_buf);
113213ea0450SMarcin Wojtas 			if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
113313ea0450SMarcin Wojtas 				free_cert_contents(&xcs[u]);
11345fff9558SSimon J. Gerraty 				once++;
11355fff9558SSimon J. Gerraty 				printf("Testing verify certificate: %s\tPassed\n",
11365fff9558SSimon J. Gerraty 				    cn.status ? cn_buf : "");
11375fff9558SSimon J. Gerraty 				xfreepkey(pk);
11385fff9558SSimon J. Gerraty 			}
11395fff9558SSimon J. Gerraty 		}
11405fff9558SSimon J. Gerraty 		if (!once)
11415fff9558SSimon J. Gerraty 			printf("Testing verify certificate:\t\t\tFailed\n");
11425fff9558SSimon J. Gerraty 		xfree(xcs);
11439bee6a60SSimon J. Gerraty 	}
11445fff9558SSimon J. Gerraty #endif	/* VERIFY_CERTS_STR */
11455fff9558SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
11465fff9558SSimon J. Gerraty 	if (!openpgp_self_tests())
11475fff9558SSimon J. Gerraty 		once++;
11485fff9558SSimon J. Gerraty #endif
11495fff9558SSimon J. Gerraty 	return (once);
11505fff9558SSimon J. Gerraty }
1151