xref: /freebsd/lib/libsecureboot/vets.c (revision 666554111a7e6b4c1a9a6ff2e73f12cd582573bb)
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 
46*66655411SSimon J. Gerraty #define EPOCH_YEAR		1970
47*66655411SSimon 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 
57*66655411SSimon J. Gerraty #ifndef VE_VERIFY_FLAGS
58*66655411SSimon J. Gerraty # define VE_VERIFY_FLAGS VEF_VERBOSE
59*66655411SSimon J. Gerraty #endif
60*66655411SSimon J. Gerraty int VerifyFlags = VE_VERIFY_FLAGS;
61*66655411SSimon 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 
895fff9558SSimon J. Gerraty static char ebuf[512];
905fff9558SSimon J. Gerraty 
915fff9558SSimon J. Gerraty char *
925fff9558SSimon J. Gerraty ve_error_get(void)
935fff9558SSimon J. Gerraty {
945fff9558SSimon J. Gerraty 	return (ebuf);
955fff9558SSimon J. Gerraty }
965fff9558SSimon J. Gerraty 
975fff9558SSimon J. Gerraty int
985fff9558SSimon J. Gerraty ve_error_set(const char *fmt, ...)
995fff9558SSimon J. Gerraty {
1005fff9558SSimon J. Gerraty 	int rc;
1015fff9558SSimon J. Gerraty 	va_list ap;
1025fff9558SSimon J. Gerraty 
1035fff9558SSimon J. Gerraty 	va_start(ap, fmt);
1045fff9558SSimon J. Gerraty 	ebuf[0] = '\0';
1055fff9558SSimon J. Gerraty 	rc = 0;
1065fff9558SSimon J. Gerraty 	if (fmt) {
1075fff9558SSimon J. Gerraty #ifdef STAND_H
1085fff9558SSimon J. Gerraty 		vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */
1095fff9558SSimon J. Gerraty 		ebuf[sizeof(ebuf) - 1] = '\0';
1105fff9558SSimon J. Gerraty 		rc = strlen(ebuf);
1115fff9558SSimon J. Gerraty #else
1125fff9558SSimon J. Gerraty 		rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap);
1135fff9558SSimon J. Gerraty #endif
1145fff9558SSimon J. Gerraty 	}
1155fff9558SSimon J. Gerraty 	va_end(ap);
1165fff9558SSimon J. Gerraty 	return (rc);
1175fff9558SSimon J. Gerraty }
1185fff9558SSimon J. Gerraty 
119*66655411SSimon J. Gerraty #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
120*66655411SSimon J. Gerraty 
121*66655411SSimon J. Gerraty /*
122*66655411SSimon J. Gerraty  * The *approximate* date.
123*66655411SSimon J. Gerraty  *
124*66655411SSimon J. Gerraty  * When certificate verification fails for being
125*66655411SSimon J. Gerraty  * expired or not yet valid, it helps to indicate
126*66655411SSimon J. Gerraty  * our current date.
127*66655411SSimon J. Gerraty  * Since libsa lacks strftime and gmtime,
128*66655411SSimon J. Gerraty  * this simple implementation suffices.
129*66655411SSimon J. Gerraty  */
130*66655411SSimon J. Gerraty static const char *
131*66655411SSimon J. Gerraty gdate(char *buf, size_t bufsz, time_t clock)
132*66655411SSimon J. Gerraty {
133*66655411SSimon J. Gerraty 	int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
134*66655411SSimon J. Gerraty 	int year, y, m, d;
135*66655411SSimon J. Gerraty 
136*66655411SSimon J. Gerraty 	y = clock / AVG_SECONDS_PER_YEAR;
137*66655411SSimon J. Gerraty 	year = EPOCH_YEAR + y;
138*66655411SSimon J. Gerraty 	for (y = EPOCH_YEAR; y < year; y++) {
139*66655411SSimon J. Gerraty 		clock -= SECONDS_PER_YEAR;
140*66655411SSimon J. Gerraty 		if (isleap(y))
141*66655411SSimon J. Gerraty 			clock -= SECONDS_PER_DAY;
142*66655411SSimon J. Gerraty 	}
143*66655411SSimon J. Gerraty 	d = clock / SECONDS_PER_DAY;
144*66655411SSimon J. Gerraty 	for (m = 0; d > 1 && m < 12; m++) {
145*66655411SSimon J. Gerraty 		if (d > days[m]) {
146*66655411SSimon J. Gerraty 			d -= days[m];
147*66655411SSimon J. Gerraty 			if (m == 1 && d > 0 && isleap(year))
148*66655411SSimon J. Gerraty 				d--;
149*66655411SSimon J. Gerraty 		} else
150*66655411SSimon J. Gerraty 			break;
151*66655411SSimon J. Gerraty 	}
152*66655411SSimon J. Gerraty 	d++;
153*66655411SSimon J. Gerraty 	if (d > days[m]) {
154*66655411SSimon J. Gerraty 	    d = 1;
155*66655411SSimon J. Gerraty 	    m++;
156*66655411SSimon J. Gerraty 	    if (m >= 12) {
157*66655411SSimon J. Gerraty 		year++;
158*66655411SSimon J. Gerraty 		m = 0;
159*66655411SSimon J. Gerraty 	    }
160*66655411SSimon J. Gerraty 	}
161*66655411SSimon J. Gerraty 	(void)snprintf(buf, bufsz, "%04d-%02d-%02d", year, m+1, d);
162*66655411SSimon J. Gerraty 	return(buf);
163*66655411SSimon J. Gerraty }
164*66655411SSimon J. Gerraty 
1655fff9558SSimon J. Gerraty /* this is the time we use for verifying certs */
166*66655411SSimon J. Gerraty #ifdef UNIT_TEST
167*66655411SSimon J. Gerraty extern time_t ve_utc;
168*66655411SSimon J. Gerraty time_t ve_utc = 0;
169*66655411SSimon J. Gerraty #else
1705fff9558SSimon J. Gerraty static time_t ve_utc = 0;
171*66655411SSimon J. Gerraty #endif
1725fff9558SSimon J. Gerraty 
1735fff9558SSimon J. Gerraty /**
1745fff9558SSimon J. Gerraty  * @brief
1755fff9558SSimon J. Gerraty  * set ve_utc used for certificate verification
1765fff9558SSimon J. Gerraty  *
1775fff9558SSimon J. Gerraty  * @param[in] utc
17853f151f9SSimon J. Gerraty  *	time - ignored unless greater than current value
17953f151f9SSimon J. Gerraty  *	and not a leap of 20 years or more.
1805fff9558SSimon J. Gerraty  */
1815fff9558SSimon J. Gerraty void
1825fff9558SSimon J. Gerraty ve_utc_set(time_t utc)
1835fff9558SSimon J. Gerraty {
18453f151f9SSimon J. Gerraty 	if (utc > ve_utc &&
18553f151f9SSimon J. Gerraty 	    (ve_utc == 0 || (utc - ve_utc) < VE_UTC_MAX_JUMP)) {
1865fff9558SSimon J. Gerraty 		DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc));
1875fff9558SSimon J. Gerraty 		ve_utc = utc;
1885fff9558SSimon J. Gerraty 	}
1895fff9558SSimon J. Gerraty }
1905fff9558SSimon J. Gerraty 
1915fff9558SSimon J. Gerraty static void
1925fff9558SSimon J. Gerraty free_cert_contents(br_x509_certificate *xc)
1935fff9558SSimon J. Gerraty {
1945fff9558SSimon J. Gerraty 	xfree(xc->data);
1955fff9558SSimon J. Gerraty }
1965fff9558SSimon J. Gerraty 
197f9510887SSimon J. Gerraty /*
198f9510887SSimon J. Gerraty  * a bit of a dance to get commonName from a certificate
199f9510887SSimon J. Gerraty  */
200f9510887SSimon J. Gerraty static char *
201f9510887SSimon J. Gerraty x509_cn_get(br_x509_certificate *xc, char *buf, size_t len)
202f9510887SSimon J. Gerraty {
203f9510887SSimon J. Gerraty 	br_x509_minimal_context mc;
204f9510887SSimon J. Gerraty 	br_name_element cn;
205f9510887SSimon J. Gerraty 	unsigned char cn_oid[4];
206f9510887SSimon J. Gerraty 	int err;
207f9510887SSimon J. Gerraty 
208f9510887SSimon J. Gerraty 	if (buf == NULL)
209f9510887SSimon J. Gerraty 		return (buf);
210f9510887SSimon J. Gerraty 	/*
211f9510887SSimon J. Gerraty 	 * We want the commonName field
212f9510887SSimon J. Gerraty 	 * the OID we want is 2,5,4,3 - but DER encoded
213f9510887SSimon J. Gerraty 	 */
214f9510887SSimon J. Gerraty 	cn_oid[0] = 3;
215f9510887SSimon J. Gerraty 	cn_oid[1] = 0x55;
216f9510887SSimon J. Gerraty 	cn_oid[2] = 4;
217f9510887SSimon J. Gerraty 	cn_oid[3] = 3;
218f9510887SSimon J. Gerraty 	cn.oid = cn_oid;
219f9510887SSimon J. Gerraty 	cn.buf = buf;
220f9510887SSimon J. Gerraty 	cn.len = len;
221f9510887SSimon J. Gerraty 	cn.buf[0] = '\0';
222f9510887SSimon J. Gerraty 
223f9510887SSimon J. Gerraty 	br_x509_minimal_init(&mc, &br_sha256_vtable, NULL, 0);
224f9510887SSimon J. Gerraty 	br_x509_minimal_set_name_elements(&mc, &cn, 1);
225f9510887SSimon J. Gerraty 	/* the below actually does the work - updates cn.status */
226f9510887SSimon J. Gerraty 	mc.vtable->start_chain(&mc.vtable, NULL);
227f9510887SSimon J. Gerraty 	mc.vtable->start_cert(&mc.vtable, xc->data_len);
228f9510887SSimon J. Gerraty 	mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
229f9510887SSimon J. Gerraty 	mc.vtable->end_cert(&mc.vtable);
230f9510887SSimon J. Gerraty 	/* we don' actually care about cert status - just its name */
231f9510887SSimon J. Gerraty 	err = mc.vtable->end_chain(&mc.vtable);
232f9510887SSimon J. Gerraty 
233f9510887SSimon J. Gerraty 	if (!cn.status)
234f9510887SSimon J. Gerraty 		buf = NULL;
235f9510887SSimon J. Gerraty 	return (buf);
236f9510887SSimon J. Gerraty }
237f9510887SSimon J. Gerraty 
23813ea0450SMarcin Wojtas /* ASN parsing related defines */
23913ea0450SMarcin Wojtas #define ASN1_PRIMITIVE_TAG 0x1F
24013ea0450SMarcin Wojtas #define ASN1_INF_LENGTH    0x80
24113ea0450SMarcin Wojtas #define ASN1_LENGTH_MASK   0x7F
24213ea0450SMarcin Wojtas 
24313ea0450SMarcin Wojtas /*
24413ea0450SMarcin Wojtas  * Get TBS part of certificate.
24513ea0450SMarcin Wojtas  * Since BearSSL doesn't provide any API to do this,
24613ea0450SMarcin Wojtas  * it has to be implemented here.
2475fff9558SSimon J. Gerraty  */
24813ea0450SMarcin Wojtas static void*
24913ea0450SMarcin Wojtas X509_to_tbs(unsigned char* cert, size_t* output_size)
25013ea0450SMarcin Wojtas {
25113ea0450SMarcin Wojtas 	unsigned char *result;
25213ea0450SMarcin Wojtas 	size_t tbs_size;
25313ea0450SMarcin Wojtas 	int size, i;
25413ea0450SMarcin Wojtas 
25513ea0450SMarcin Wojtas 	if (cert == NULL)
25613ea0450SMarcin Wojtas 		return (NULL);
25713ea0450SMarcin Wojtas 
25813ea0450SMarcin Wojtas 	/* Strip two sequences to get to the TBS section */
25913ea0450SMarcin Wojtas 	for (i = 0; i < 2; i++) {
26013ea0450SMarcin Wojtas 		/*
26113ea0450SMarcin Wojtas 		 * XXX: We don't need to support extended tags since
26213ea0450SMarcin Wojtas 		 * they should not be present in certificates.
26313ea0450SMarcin Wojtas 		 */
26413ea0450SMarcin Wojtas 		if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG)
26513ea0450SMarcin Wojtas 			return (NULL);
26613ea0450SMarcin Wojtas 
26713ea0450SMarcin Wojtas 		cert++;
26813ea0450SMarcin Wojtas 
26913ea0450SMarcin Wojtas 		if (*cert == ASN1_INF_LENGTH)
27013ea0450SMarcin Wojtas 			return (NULL);
27113ea0450SMarcin Wojtas 
27213ea0450SMarcin Wojtas 		size = *cert & ASN1_LENGTH_MASK;
27313ea0450SMarcin Wojtas 		tbs_size = 0;
27413ea0450SMarcin Wojtas 
27513ea0450SMarcin Wojtas 		/* Size can either be stored on a single or multiple bytes */
27613ea0450SMarcin Wojtas 		if (*cert & (ASN1_LENGTH_MASK + 1)) {
27713ea0450SMarcin Wojtas 			cert++;
27813ea0450SMarcin Wojtas 			while (*cert == 0 && size > 0) {
27913ea0450SMarcin Wojtas 				cert++;
28013ea0450SMarcin Wojtas 				size--;
28113ea0450SMarcin Wojtas 			}
28213ea0450SMarcin Wojtas 			while (size-- > 0) {
28313ea0450SMarcin Wojtas 				tbs_size <<= 8;
28413ea0450SMarcin Wojtas 				tbs_size |= *(cert++);
28513ea0450SMarcin Wojtas 			}
28613ea0450SMarcin Wojtas 		}
28713ea0450SMarcin Wojtas 		if (i == 0)
28813ea0450SMarcin Wojtas 			result = cert;
28913ea0450SMarcin Wojtas 	}
29013ea0450SMarcin Wojtas 	tbs_size += (cert - result);
29113ea0450SMarcin Wojtas 
29213ea0450SMarcin Wojtas 	if (output_size != NULL)
29313ea0450SMarcin Wojtas 		*output_size = tbs_size;
29413ea0450SMarcin Wojtas 
29513ea0450SMarcin Wojtas 	return (result);
29613ea0450SMarcin Wojtas }
29713ea0450SMarcin Wojtas 
29813ea0450SMarcin Wojtas void
29913ea0450SMarcin Wojtas ve_forbidden_digest_add(hash_data *digest, size_t num)
30013ea0450SMarcin Wojtas {
30113ea0450SMarcin Wojtas 	while (num--)
30213ea0450SMarcin Wojtas 		VEC_ADD(forbidden_digests, digest[num]);
30313ea0450SMarcin Wojtas }
30413ea0450SMarcin Wojtas 
30513ea0450SMarcin Wojtas static size_t
306f9510887SSimon J. Gerraty ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors,
30718e2fbc0SSimon J. Gerraty     const char *anchors_name)
3085fff9558SSimon J. Gerraty {
3095fff9558SSimon J. Gerraty 	br_x509_trust_anchor ta;
3105fff9558SSimon J. Gerraty 	size_t u;
3115fff9558SSimon J. Gerraty 
3125fff9558SSimon J. Gerraty 	for (u = 0; u < num; u++) {
3135fff9558SSimon J. Gerraty 		if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
3145fff9558SSimon J. Gerraty 			break;
3155fff9558SSimon J. Gerraty 		}
31613ea0450SMarcin Wojtas 		VEC_ADD(*anchors, ta);
317f9510887SSimon J. Gerraty 		if (anchor_verbose && anchors_name) {
318f9510887SSimon J. Gerraty 			char buf[64];
319f9510887SSimon J. Gerraty 			char *cp;
320f9510887SSimon J. Gerraty 
321f9510887SSimon J. Gerraty 			cp = x509_cn_get(&xcs[u], buf, sizeof(buf));
322f9510887SSimon J. Gerraty 			if (cp) {
323f9510887SSimon J. Gerraty 				printf("x509_anchor(%s) %s\n", cp, anchors_name);
324f9510887SSimon J. Gerraty 			}
325f9510887SSimon J. Gerraty 		}
3265fff9558SSimon J. Gerraty 	}
3275fff9558SSimon J. Gerraty 	return (u);
3285fff9558SSimon J. Gerraty }
3295fff9558SSimon J. Gerraty 
3305fff9558SSimon J. Gerraty /**
3315fff9558SSimon J. Gerraty  * @brief
33213ea0450SMarcin Wojtas  * add certs to our trust store
33313ea0450SMarcin Wojtas  */
33413ea0450SMarcin Wojtas size_t
33513ea0450SMarcin Wojtas ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
33613ea0450SMarcin Wojtas {
337f9510887SSimon J. Gerraty 	return (ve_anchors_add(xcs, num, &trust_anchors, "trusted"));
33813ea0450SMarcin Wojtas }
33913ea0450SMarcin Wojtas 
34013ea0450SMarcin Wojtas size_t
34113ea0450SMarcin Wojtas ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num)
34213ea0450SMarcin Wojtas {
343f9510887SSimon J. Gerraty 	return (ve_anchors_add(xcs, num, &forbidden_anchors, "forbidden"));
344f9510887SSimon J. Gerraty }
345f9510887SSimon J. Gerraty 
346f9510887SSimon J. Gerraty 
347f9510887SSimon J. Gerraty /**
348f9510887SSimon J. Gerraty  * @brief add trust anchors in buf
349f9510887SSimon J. Gerraty  *
350f9510887SSimon J. Gerraty  * Assume buf contains x509 certificates, but if not and
351f9510887SSimon J. Gerraty  * we support OpenPGP try adding as that.
352f9510887SSimon J. Gerraty  *
353f9510887SSimon J. Gerraty  * @return number of anchors added
354f9510887SSimon J. Gerraty  */
355f9510887SSimon J. Gerraty size_t
356f9510887SSimon J. Gerraty ve_trust_anchors_add_buf(unsigned char *buf, size_t len)
357f9510887SSimon J. Gerraty {
358f9510887SSimon J. Gerraty 	br_x509_certificate *xcs;
359f9510887SSimon J. Gerraty 	size_t num;
360f9510887SSimon J. Gerraty 
361f9510887SSimon J. Gerraty 	num = 0;
362f9510887SSimon J. Gerraty 	xcs = parse_certificates(buf, len, &num);
363f9510887SSimon J. Gerraty 	if (xcs != NULL) {
364f9510887SSimon J. Gerraty 		num = ve_trust_anchors_add(xcs, num);
365f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
366f9510887SSimon J. Gerraty 	} else {
367f9510887SSimon J. Gerraty 		num = openpgp_trust_add_buf(buf, len);
368f9510887SSimon J. Gerraty #endif
369f9510887SSimon J. Gerraty 	}
370f9510887SSimon J. Gerraty 	return (num);
371f9510887SSimon J. Gerraty }
372f9510887SSimon J. Gerraty 
373f9510887SSimon J. Gerraty /**
374f9510887SSimon J. Gerraty  * @brief revoke trust anchors in buf
375f9510887SSimon J. Gerraty  *
376f9510887SSimon J. Gerraty  * Assume buf contains x509 certificates, but if not and
377f9510887SSimon J. Gerraty  * we support OpenPGP try revoking keyId
378f9510887SSimon J. Gerraty  *
379f9510887SSimon J. Gerraty  * @return number of anchors revoked
380f9510887SSimon J. Gerraty  */
381f9510887SSimon J. Gerraty size_t
382f9510887SSimon J. Gerraty ve_trust_anchors_revoke(unsigned char *buf, size_t len)
383f9510887SSimon J. Gerraty {
384f9510887SSimon J. Gerraty 	br_x509_certificate *xcs;
385f9510887SSimon J. Gerraty 	size_t num;
386f9510887SSimon J. Gerraty 
387f9510887SSimon J. Gerraty 	num = 0;
388f9510887SSimon J. Gerraty 	xcs = parse_certificates(buf, len, &num);
389f9510887SSimon J. Gerraty 	if (xcs != NULL) {
390f9510887SSimon J. Gerraty 		num = ve_forbidden_anchors_add(xcs, num);
391f9510887SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
392f9510887SSimon J. Gerraty 	} else {
393f9510887SSimon J. Gerraty 		if (buf[len - 1] == '\n')
394f9510887SSimon J. Gerraty 			buf[len - 1] = '\0';
395f9510887SSimon J. Gerraty 		num = openpgp_trust_revoke((char *)buf);
396f9510887SSimon J. Gerraty #endif
397f9510887SSimon J. Gerraty 	}
398f9510887SSimon J. Gerraty 	return (num);
39913ea0450SMarcin Wojtas }
40013ea0450SMarcin Wojtas 
40113ea0450SMarcin Wojtas /**
40213ea0450SMarcin Wojtas  * @brief
4035fff9558SSimon J. Gerraty  * initialize our trust_anchors from ta_PEM
4045fff9558SSimon J. Gerraty  */
4055fff9558SSimon J. Gerraty int
4065fff9558SSimon J. Gerraty ve_trust_init(void)
4075fff9558SSimon J. Gerraty {
4085fff9558SSimon J. Gerraty 	static int once = -1;
4095fff9558SSimon J. Gerraty 
4105fff9558SSimon J. Gerraty 	if (once >= 0)
4115fff9558SSimon J. Gerraty 		return (once);
4123ae2a848SSimon J. Gerraty 	once = 0;			/* to be sure */
4135fff9558SSimon J. Gerraty #ifdef BUILD_UTC
41453f151f9SSimon J. Gerraty 	ve_utc_set(BUILD_UTC);		/* ensure sanity */
4155fff9558SSimon J. Gerraty #endif
41653f151f9SSimon J. Gerraty 	ve_utc_set(time(NULL));
4175fff9558SSimon J. Gerraty 	ve_error_set(NULL);		/* make sure it is empty */
4185fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT
4195fff9558SSimon J. Gerraty 	ve_pcr_init();
4205fff9558SSimon J. Gerraty #endif
4215fff9558SSimon J. Gerraty 
4225fff9558SSimon J. Gerraty #ifdef TRUST_ANCHOR_STR
423f9510887SSimon J. Gerraty 	ve_trust_anchors_add_buf(__DECONST(unsigned char *, TRUST_ANCHOR_STR),
424f9510887SSimon J. Gerraty 	    sizeof(TRUST_ANCHOR_STR));
4255fff9558SSimon J. Gerraty #endif
42613ea0450SMarcin Wojtas 	once = (int) VEC_LEN(trust_anchors);
4279bee6a60SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
4289bee6a60SSimon J. Gerraty 	once += openpgp_trust_init();
4299bee6a60SSimon J. Gerraty #endif
43013ea0450SMarcin Wojtas 	return (once);
4315fff9558SSimon J. Gerraty }
4325fff9558SSimon J. Gerraty 
433*66655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK
434*66655411SSimon J. Gerraty static int
435*66655411SSimon J. Gerraty verify_time_cb(void *tctx,
436*66655411SSimon J. Gerraty     uint32_t not_before_days, uint32_t not_before_seconds,
437*66655411SSimon J. Gerraty     uint32_t not_after_days, uint32_t not_after_seconds)
438*66655411SSimon J. Gerraty {
439*66655411SSimon J. Gerraty 	time_t not_before;
440*66655411SSimon J. Gerraty 	time_t not_after;
441*66655411SSimon J. Gerraty 	int rc;
442*66655411SSimon J. Gerraty #ifdef UNIT_TEST
443*66655411SSimon J. Gerraty 	char date[12], nb_date[12], na_date[12];
444*66655411SSimon J. Gerraty #endif
445*66655411SSimon J. Gerraty 
446*66655411SSimon J. Gerraty 	not_before = ((not_before_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_before_seconds;
447*66655411SSimon J. Gerraty 	not_after =  ((not_after_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_after_seconds;
448*66655411SSimon J. Gerraty 	if (ve_utc < not_before)
449*66655411SSimon J. Gerraty 		rc = -1;
450*66655411SSimon J. Gerraty 	else if (ve_utc > not_after)
451*66655411SSimon J. Gerraty 		rc = 1;
452*66655411SSimon J. Gerraty 	else
453*66655411SSimon J. Gerraty 		rc = 0;
454*66655411SSimon J. Gerraty #ifdef UNIT_TEST
455*66655411SSimon J. Gerraty 	printf("notBefore %s notAfter %s date %s rc %d\n",
456*66655411SSimon J. Gerraty 	    gdate(nb_date, sizeof(nb_date), not_before),
457*66655411SSimon J. Gerraty 	    gdate(na_date, sizeof(na_date), not_after),
458*66655411SSimon J. Gerraty 	    gdate(date, sizeof(date), ve_utc), rc);
459*66655411SSimon J. Gerraty #endif
460*66655411SSimon J. Gerraty #if defined(_STANDALONE)
461*66655411SSimon J. Gerraty 	rc = 0;				/* don't fail */
462*66655411SSimon J. Gerraty #endif
463*66655411SSimon J. Gerraty 	return rc;
464*66655411SSimon J. Gerraty }
465*66655411SSimon J. Gerraty #endif
466*66655411SSimon J. Gerraty 
4675fff9558SSimon J. Gerraty /**
4685fff9558SSimon J. Gerraty  * if we can verify the certificate chain in "certs",
4695fff9558SSimon J. Gerraty  * return the public key and if "xcp" is !NULL the associated
4705fff9558SSimon J. Gerraty  * certificate
4715fff9558SSimon J. Gerraty  */
4725fff9558SSimon J. Gerraty static br_x509_pkey *
4735fff9558SSimon J. Gerraty verify_signer_xcs(br_x509_certificate *xcs,
4745fff9558SSimon J. Gerraty     size_t num,
47513ea0450SMarcin Wojtas     br_name_element *elts, size_t num_elts,
47613ea0450SMarcin Wojtas     anchor_list *anchors)
4775fff9558SSimon J. Gerraty {
4785fff9558SSimon J. Gerraty 	br_x509_minimal_context mc;
4795fff9558SSimon J. Gerraty 	br_x509_certificate *xc;
4805fff9558SSimon J. Gerraty 	size_t u;
4815fff9558SSimon J. Gerraty 	cert_list chain = VEC_INIT;
4825fff9558SSimon J. Gerraty 	const br_x509_pkey *tpk;
4835fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
4845fff9558SSimon J. Gerraty 	unsigned int usages;
4855fff9558SSimon J. Gerraty 	int err;
4865fff9558SSimon J. Gerraty 
4875fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num));
4885fff9558SSimon J. Gerraty 	VEC_ADDMANY(chain, xcs, num);
4895fff9558SSimon J. Gerraty 	if (VEC_LEN(chain) == 0) {
4905fff9558SSimon J. Gerraty 		ve_error_set("ERROR: no/invalid certificate chain\n");
4915fff9558SSimon J. Gerraty 		return (NULL);
4925fff9558SSimon J. Gerraty 	}
4935fff9558SSimon J. Gerraty 
4945fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n",
49513ea0450SMarcin Wojtas 		VEC_LEN(*anchors)));
4965fff9558SSimon J. Gerraty 
4975fff9558SSimon J. Gerraty 	br_x509_minimal_init(&mc, &br_sha256_vtable,
49813ea0450SMarcin Wojtas 	    &VEC_ELT(*anchors, 0),
49913ea0450SMarcin Wojtas 	    VEC_LEN(*anchors));
5005fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
5015fff9558SSimon J. Gerraty 	br_x509_minimal_set_ecdsa(&mc,
5025fff9558SSimon J. Gerraty 	    &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
5035fff9558SSimon J. Gerraty #endif
5045fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
5055fff9558SSimon J. Gerraty 	br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
5065fff9558SSimon J. Gerraty #endif
5075fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
5085fff9558SSimon J. Gerraty 	/* This is deprecated! do not enable unless you absoultely have to */
5095fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable);
5105fff9558SSimon J. Gerraty #endif
5115fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable);
5125fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT
5135fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable);
5145fff9558SSimon J. Gerraty #endif
5155fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT
5165fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable);
5175fff9558SSimon J. Gerraty #endif
5185fff9558SSimon J. Gerraty 	br_x509_minimal_set_name_elements(&mc, elts, num_elts);
5195fff9558SSimon J. Gerraty 
520*66655411SSimon J. Gerraty #ifdef HAVE_BR_X509_TIME_CHECK
521*66655411SSimon J. Gerraty 	br_x509_minimal_set_time_callback(&mc, NULL, verify_time_cb);
522*66655411SSimon J. Gerraty #else
523*66655411SSimon J. Gerraty #if defined(_STANDALONE) || defined(UNIT_TEST)
5245fff9558SSimon J. Gerraty 	/*
5255fff9558SSimon J. Gerraty 	 * Clock is probably bogus so we use ve_utc.
5265fff9558SSimon J. Gerraty 	 */
5275fff9558SSimon J. Gerraty 	mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0;
5285fff9558SSimon J. Gerraty 	mc.seconds = (ve_utc % SECONDS_PER_DAY);
5295fff9558SSimon J. Gerraty #endif
530*66655411SSimon J. Gerraty #endif
5315fff9558SSimon J. Gerraty 	mc.vtable->start_chain(&mc.vtable, NULL);
5325fff9558SSimon J. Gerraty 	for (u = 0; u < VEC_LEN(chain); u ++) {
5335fff9558SSimon J. Gerraty 		xc = &VEC_ELT(chain, u);
5345fff9558SSimon J. Gerraty 		mc.vtable->start_cert(&mc.vtable, xc->data_len);
5355fff9558SSimon J. Gerraty 		mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
5365fff9558SSimon J. Gerraty 		mc.vtable->end_cert(&mc.vtable);
5375fff9558SSimon J. Gerraty 		switch (mc.err) {
5385fff9558SSimon J. Gerraty 		case 0:
5395fff9558SSimon J. Gerraty 		case BR_ERR_X509_OK:
5405fff9558SSimon J. Gerraty 		case BR_ERR_X509_EXPIRED:
5415fff9558SSimon J. Gerraty 			break;
5425fff9558SSimon J. Gerraty 		default:
5435fff9558SSimon J. Gerraty 			printf("u=%zu mc.err=%d\n", u, mc.err);
5445fff9558SSimon J. Gerraty 			break;
5455fff9558SSimon J. Gerraty 		}
5465fff9558SSimon J. Gerraty 	}
5475fff9558SSimon J. Gerraty 	err = mc.vtable->end_chain(&mc.vtable);
5485fff9558SSimon J. Gerraty 	pk = NULL;
5495fff9558SSimon J. Gerraty 	if (err) {
550*66655411SSimon J. Gerraty 		char date[12];
551*66655411SSimon J. Gerraty 
552*66655411SSimon J. Gerraty 		switch (err) {
553*66655411SSimon J. Gerraty 		case 54:
554*66655411SSimon J. Gerraty 			ve_error_set("Validation failed, certificate not valid as of %s",
555*66655411SSimon J. Gerraty 			    gdate(date, sizeof(date), ve_utc));
556*66655411SSimon J. Gerraty 			break;
557*66655411SSimon J. Gerraty 		default:
5585fff9558SSimon J. Gerraty 			ve_error_set("Validation failed, err = %d", err);
559*66655411SSimon J. Gerraty 			break;
560*66655411SSimon J. Gerraty 		}
5615fff9558SSimon J. Gerraty 	} else {
5625fff9558SSimon J. Gerraty 		tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
5635fff9558SSimon J. Gerraty 		if (tpk != NULL) {
5645fff9558SSimon J. Gerraty 			pk = xpkeydup(tpk);
5655fff9558SSimon J. Gerraty 		}
5665fff9558SSimon J. Gerraty 	}
56713ea0450SMarcin Wojtas 	VEC_CLEAR(chain);
5685fff9558SSimon J. Gerraty 	return (pk);
5695fff9558SSimon J. Gerraty }
5705fff9558SSimon J. Gerraty 
57113ea0450SMarcin Wojtas /*
57213ea0450SMarcin Wojtas  * Check if digest of one of the certificates from verified chain
57313ea0450SMarcin Wojtas  * is present in the forbidden database.
57413ea0450SMarcin Wojtas  * Since UEFI allows to store three types of digests
57513ea0450SMarcin Wojtas  * all of them have to be checked separately.
57613ea0450SMarcin Wojtas  */
57713ea0450SMarcin Wojtas static int
57813ea0450SMarcin Wojtas check_forbidden_digests(br_x509_certificate *xcs, size_t num)
57913ea0450SMarcin Wojtas {
58013ea0450SMarcin Wojtas 	unsigned char sha256_digest[br_sha256_SIZE];
58113ea0450SMarcin Wojtas 	unsigned char sha384_digest[br_sha384_SIZE];
58213ea0450SMarcin Wojtas 	unsigned char sha512_digest[br_sha512_SIZE];
58313ea0450SMarcin Wojtas 	void *tbs;
58413ea0450SMarcin Wojtas 	hash_data *digest;
58513ea0450SMarcin Wojtas 	br_hash_compat_context ctx;
58613ea0450SMarcin Wojtas 	const br_hash_class *md;
58713ea0450SMarcin Wojtas 	size_t tbs_len, i;
58813ea0450SMarcin Wojtas 	int have_sha256, have_sha384, have_sha512;
58913ea0450SMarcin Wojtas 
59013ea0450SMarcin Wojtas 	if (VEC_LEN(forbidden_digests) == 0)
59113ea0450SMarcin Wojtas 		return (0);
59213ea0450SMarcin Wojtas 
59313ea0450SMarcin Wojtas 	/*
59413ea0450SMarcin Wojtas 	 * Iterate through certificates, extract their To-Be-Signed section,
59513ea0450SMarcin Wojtas 	 * and compare its digest against the ones in the forbidden database.
59613ea0450SMarcin Wojtas 	 */
59713ea0450SMarcin Wojtas 	while (num--) {
59813ea0450SMarcin Wojtas 		tbs = X509_to_tbs(xcs[num].data, &tbs_len);
59913ea0450SMarcin Wojtas 		if (tbs == NULL) {
60013ea0450SMarcin Wojtas 			printf("Failed to obtain TBS part of certificate\n");
60113ea0450SMarcin Wojtas 			return (1);
60213ea0450SMarcin Wojtas 		}
60313ea0450SMarcin Wojtas 		have_sha256 = have_sha384 = have_sha512 = 0;
60413ea0450SMarcin Wojtas 
60513ea0450SMarcin Wojtas 		for (i = 0; i < VEC_LEN(forbidden_digests); i++) {
60613ea0450SMarcin Wojtas 			digest = &VEC_ELT(forbidden_digests, i);
60713ea0450SMarcin Wojtas 			switch (digest->hash_size) {
60813ea0450SMarcin Wojtas 			case br_sha256_SIZE:
60913ea0450SMarcin Wojtas 				if (!have_sha256) {
61013ea0450SMarcin Wojtas 					have_sha256 = 1;
61113ea0450SMarcin Wojtas 					md = &br_sha256_vtable;
61213ea0450SMarcin Wojtas 					md->init(&ctx.vtable);
61313ea0450SMarcin Wojtas 					md->update(&ctx.vtable, tbs, tbs_len);
61413ea0450SMarcin Wojtas 					md->out(&ctx.vtable, sha256_digest);
61513ea0450SMarcin Wojtas 				}
61613ea0450SMarcin Wojtas 				if (!memcmp(sha256_digest,
61713ea0450SMarcin Wojtas 					digest->data,
61813ea0450SMarcin Wojtas 					br_sha256_SIZE))
61913ea0450SMarcin Wojtas 					return (1);
62013ea0450SMarcin Wojtas 
62113ea0450SMarcin Wojtas 				break;
62213ea0450SMarcin Wojtas 			case br_sha384_SIZE:
62313ea0450SMarcin Wojtas 				if (!have_sha384) {
62413ea0450SMarcin Wojtas 					have_sha384 = 1;
62513ea0450SMarcin Wojtas 					md = &br_sha384_vtable;
62613ea0450SMarcin Wojtas 					md->init(&ctx.vtable);
62713ea0450SMarcin Wojtas 					md->update(&ctx.vtable, tbs, tbs_len);
62813ea0450SMarcin Wojtas 					md->out(&ctx.vtable, sha384_digest);
62913ea0450SMarcin Wojtas 				}
63013ea0450SMarcin Wojtas 				if (!memcmp(sha384_digest,
63113ea0450SMarcin Wojtas 					digest->data,
63213ea0450SMarcin Wojtas 					br_sha384_SIZE))
63313ea0450SMarcin Wojtas 					return (1);
63413ea0450SMarcin Wojtas 
63513ea0450SMarcin Wojtas 				break;
63613ea0450SMarcin Wojtas 			case br_sha512_SIZE:
63713ea0450SMarcin Wojtas 				if (!have_sha512) {
63813ea0450SMarcin Wojtas 					have_sha512 = 1;
63913ea0450SMarcin Wojtas 					md = &br_sha512_vtable;
64013ea0450SMarcin Wojtas 					md->init(&ctx.vtable);
64113ea0450SMarcin Wojtas 					md->update(&ctx.vtable, tbs, tbs_len);
64213ea0450SMarcin Wojtas 					md->out(&ctx.vtable, sha512_digest);
64313ea0450SMarcin Wojtas 				}
64413ea0450SMarcin Wojtas 				if (!memcmp(sha512_digest,
64513ea0450SMarcin Wojtas 					digest->data,
64613ea0450SMarcin Wojtas 					br_sha512_SIZE))
64713ea0450SMarcin Wojtas 					return (1);
64813ea0450SMarcin Wojtas 
64913ea0450SMarcin Wojtas 				break;
65013ea0450SMarcin Wojtas 			}
65113ea0450SMarcin Wojtas 		}
65213ea0450SMarcin Wojtas 	}
65313ea0450SMarcin Wojtas 
65413ea0450SMarcin Wojtas 	return (0);
65513ea0450SMarcin Wojtas }
65613ea0450SMarcin Wojtas 
6575fff9558SSimon J. Gerraty static br_x509_pkey *
6585fff9558SSimon J. Gerraty verify_signer(const char *certs,
6595fff9558SSimon J. Gerraty     br_name_element *elts, size_t num_elts)
6605fff9558SSimon J. Gerraty {
6615fff9558SSimon J. Gerraty 	br_x509_certificate *xcs;
6625fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
6635fff9558SSimon J. Gerraty 	size_t num;
6645fff9558SSimon J. Gerraty 
66513ea0450SMarcin Wojtas 	pk = NULL;
66613ea0450SMarcin Wojtas 
6675fff9558SSimon J. Gerraty 	ve_trust_init();
6685fff9558SSimon J. Gerraty 	xcs = read_certificates(certs, &num);
6695fff9558SSimon J. Gerraty 	if (xcs == NULL) {
6705fff9558SSimon J. Gerraty 		ve_error_set("cannot read certificates\n");
6715fff9558SSimon J. Gerraty 		return (NULL);
6725fff9558SSimon J. Gerraty 	}
67313ea0450SMarcin Wojtas 
67413ea0450SMarcin Wojtas 	/*
67513ea0450SMarcin Wojtas 	 * Check if either
67613ea0450SMarcin Wojtas 	 * 1. There is a direct match between cert from forbidden_anchors
67713ea0450SMarcin Wojtas 	 * and a cert from chain.
67813ea0450SMarcin Wojtas 	 * 2. CA that signed the chain is found in forbidden_anchors.
67913ea0450SMarcin Wojtas 	 */
68013ea0450SMarcin Wojtas 	if (VEC_LEN(forbidden_anchors) > 0)
68113ea0450SMarcin Wojtas 		pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors);
68213ea0450SMarcin Wojtas 	if (pk != NULL) {
68313ea0450SMarcin Wojtas 		ve_error_set("Certificate is on forbidden list\n");
68413ea0450SMarcin Wojtas 		xfreepkey(pk);
68513ea0450SMarcin Wojtas 		pk = NULL;
68613ea0450SMarcin Wojtas 		goto out;
68713ea0450SMarcin Wojtas 	}
68813ea0450SMarcin Wojtas 
68913ea0450SMarcin Wojtas 	pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors);
69013ea0450SMarcin Wojtas 	if (pk == NULL)
69113ea0450SMarcin Wojtas 		goto out;
69213ea0450SMarcin Wojtas 
69313ea0450SMarcin Wojtas 	/*
69413ea0450SMarcin Wojtas 	 * Check if hash of tbs part of any certificate in chain
69513ea0450SMarcin Wojtas 	 * is on the forbidden list.
69613ea0450SMarcin Wojtas 	 */
69713ea0450SMarcin Wojtas 	if (check_forbidden_digests(xcs, num)) {
69813ea0450SMarcin Wojtas 		ve_error_set("Certificate hash is on forbidden list\n");
69913ea0450SMarcin Wojtas 		xfreepkey(pk);
70013ea0450SMarcin Wojtas 		pk = NULL;
70113ea0450SMarcin Wojtas 	}
70213ea0450SMarcin Wojtas out:
70313ea0450SMarcin Wojtas 	free_certificates(xcs, num);
7045fff9558SSimon J. Gerraty 	return (pk);
7055fff9558SSimon J. Gerraty }
7065fff9558SSimon J. Gerraty 
7075fff9558SSimon J. Gerraty /**
7085fff9558SSimon J. Gerraty  * we need a hex digest including trailing newline below
7095fff9558SSimon J. Gerraty  */
7105fff9558SSimon J. Gerraty char *
7115fff9558SSimon J. Gerraty hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len)
7125fff9558SSimon J. Gerraty {
7135fff9558SSimon J. Gerraty 	char const hex2ascii[] = "0123456789abcdef";
7145fff9558SSimon J. Gerraty 	size_t i;
7155fff9558SSimon J. Gerraty 
7165fff9558SSimon J. Gerraty 	/* every binary byte is 2 chars in hex + newline + null  */
7175fff9558SSimon J. Gerraty 	if (bufsz < (2 * foo_len) + 2)
7185fff9558SSimon J. Gerraty 		return (NULL);
7195fff9558SSimon J. Gerraty 
7205fff9558SSimon J. Gerraty 	for (i = 0; i < foo_len; i++) {
7215fff9558SSimon J. Gerraty 		buf[i * 2] = hex2ascii[foo[i] >> 4];
7225fff9558SSimon J. Gerraty 		buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f];
7235fff9558SSimon J. Gerraty 	}
7245fff9558SSimon J. Gerraty 
7255fff9558SSimon J. Gerraty 	buf[i * 2] = 0x0A; /* we also want a newline */
7265fff9558SSimon J. Gerraty 	buf[i * 2 + 1] = '\0';
7275fff9558SSimon J. Gerraty 
7285fff9558SSimon J. Gerraty 	return (buf);
7295fff9558SSimon J. Gerraty }
7305fff9558SSimon J. Gerraty 
7315fff9558SSimon J. Gerraty /**
7325fff9558SSimon J. Gerraty  * @brief
7335fff9558SSimon J. Gerraty  * verify file against sigfile using pk
7345fff9558SSimon J. Gerraty  *
7355fff9558SSimon J. Gerraty  * When we generated the signature in sigfile,
7365fff9558SSimon J. Gerraty  * we hashed (sha256) file, and sent that to signing server
7375fff9558SSimon J. Gerraty  * which hashed (sha256) that hash.
7385fff9558SSimon J. Gerraty  *
7395fff9558SSimon J. Gerraty  * To verify we need to replicate that result.
7405fff9558SSimon J. Gerraty  *
7415fff9558SSimon J. Gerraty  * @param[in] pk
7425fff9558SSimon J. Gerraty  *	br_x509_pkey
7435fff9558SSimon J. Gerraty  *
7445fff9558SSimon J. Gerraty  * @paramp[in] file
7455fff9558SSimon J. Gerraty  *	file to be verified
7465fff9558SSimon J. Gerraty  *
7475fff9558SSimon J. Gerraty  * @param[in] sigfile
7485fff9558SSimon J. Gerraty  * 	signature (PEM encoded)
7495fff9558SSimon J. Gerraty  *
7505fff9558SSimon J. Gerraty  * @return NULL on error, otherwise content of file.
7515fff9558SSimon J. Gerraty  */
7525fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
7535fff9558SSimon J. Gerraty static unsigned char *
7545fff9558SSimon J. Gerraty verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile)
7555fff9558SSimon J. Gerraty {
7560e47020fSSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN
7570e47020fSSimon J. Gerraty 	char *hex, hexbuf[br_sha512_SIZE * 2 + 2];
7580e47020fSSimon J. Gerraty #endif
7595fff9558SSimon J. Gerraty 	unsigned char rhbuf[br_sha512_SIZE];
7605fff9558SSimon J. Gerraty 	br_sha256_context ctx;
7615fff9558SSimon J. Gerraty 	unsigned char *fcp, *scp;
7625fff9558SSimon J. Gerraty 	size_t flen, slen, plen;
7635fff9558SSimon J. Gerraty 	pem_object *po;
7645fff9558SSimon J. Gerraty 	const br_ec_impl *ec;
7655fff9558SSimon J. Gerraty 	br_ecdsa_vrfy vrfy;
7665fff9558SSimon J. Gerraty 
7675fff9558SSimon J. Gerraty 	if ((fcp = read_file(file, &flen)) == NULL)
7685fff9558SSimon J. Gerraty 		return (NULL);
7695fff9558SSimon J. Gerraty 	if ((scp = read_file(sigfile, &slen)) == NULL) {
7705fff9558SSimon J. Gerraty 		free(fcp);
7715fff9558SSimon J. Gerraty 		return (NULL);
7725fff9558SSimon J. Gerraty 	}
7735fff9558SSimon J. Gerraty 	if ((po = decode_pem(scp, slen, &plen)) == NULL) {
7745fff9558SSimon J. Gerraty 		free(fcp);
7755fff9558SSimon J. Gerraty 		free(scp);
7765fff9558SSimon J. Gerraty 		return (NULL);
7775fff9558SSimon J. Gerraty 	}
7785fff9558SSimon J. Gerraty 	br_sha256_init(&ctx);
7795fff9558SSimon J. Gerraty 	br_sha256_update(&ctx, fcp, flen);
7805fff9558SSimon J. Gerraty 	br_sha256_out(&ctx, rhbuf);
781f9510887SSimon J. Gerraty #ifdef VE_ECDSA_HASH_AGAIN
7825fff9558SSimon J. Gerraty 	hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE);
7835fff9558SSimon J. Gerraty 	/* now hash that */
7845fff9558SSimon J. Gerraty 	if (hex) {
7855fff9558SSimon J. Gerraty 		br_sha256_init(&ctx);
7865fff9558SSimon J. Gerraty 		br_sha256_update(&ctx, hex, strlen(hex));
7875fff9558SSimon J. Gerraty 		br_sha256_out(&ctx, rhbuf);
7885fff9558SSimon J. Gerraty 	}
789f9510887SSimon J. Gerraty #endif
7905fff9558SSimon J. Gerraty 	ec = br_ec_get_default();
7915fff9558SSimon J. Gerraty 	vrfy = br_ecdsa_vrfy_asn1_get_default();
7925fff9558SSimon J. Gerraty 	if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data,
7935fff9558SSimon J. Gerraty 		po->data_len)) {
7945fff9558SSimon J. Gerraty 		free(fcp);
7955fff9558SSimon J. Gerraty 		fcp = NULL;
7965fff9558SSimon J. Gerraty 	}
7975fff9558SSimon J. Gerraty 	free(scp);
7985fff9558SSimon J. Gerraty 	return (fcp);
7995fff9558SSimon J. Gerraty }
8005fff9558SSimon J. Gerraty #endif
8015fff9558SSimon J. Gerraty 
8025fff9558SSimon J. Gerraty #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT)
8035fff9558SSimon J. Gerraty /**
8045fff9558SSimon J. Gerraty  * @brief verify an rsa digest
8055fff9558SSimon J. Gerraty  *
8065fff9558SSimon J. Gerraty  * @return 0 on failure
8075fff9558SSimon J. Gerraty  */
8085fff9558SSimon J. Gerraty int
8095fff9558SSimon J. Gerraty verify_rsa_digest (br_rsa_public_key *pkey,
8105fff9558SSimon J. Gerraty     const unsigned char *hash_oid,
8115fff9558SSimon J. Gerraty     unsigned char *mdata, size_t mlen,
8125fff9558SSimon J. Gerraty     unsigned char *sdata, size_t slen)
8135fff9558SSimon J. Gerraty {
8145fff9558SSimon J. Gerraty 	br_rsa_pkcs1_vrfy vrfy;
8155fff9558SSimon J. Gerraty 	unsigned char vhbuf[br_sha512_SIZE];
8165fff9558SSimon J. Gerraty 
8175fff9558SSimon J. Gerraty 	vrfy = br_rsa_pkcs1_vrfy_get_default();
8185fff9558SSimon J. Gerraty 
8195fff9558SSimon J. Gerraty 	if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) ||
8205fff9558SSimon J. Gerraty 	    memcmp(vhbuf, mdata, mlen) != 0) {
8215fff9558SSimon J. Gerraty 		return (0);		/* fail */
8225fff9558SSimon J. Gerraty 	}
8235fff9558SSimon J. Gerraty 	return (1);			/* ok */
8245fff9558SSimon J. Gerraty }
8255fff9558SSimon J. Gerraty #endif
8265fff9558SSimon J. Gerraty 
8275fff9558SSimon J. Gerraty /**
8285fff9558SSimon J. Gerraty  * @brief
8295fff9558SSimon J. Gerraty  * verify file against sigfile using pk
8305fff9558SSimon J. Gerraty  *
8315fff9558SSimon J. Gerraty  * When we generated the signature in sigfile,
8325fff9558SSimon J. Gerraty  * we hashed (sha256) file, and sent that to signing server
8335fff9558SSimon J. Gerraty  * which hashed (sha256) that hash.
8345fff9558SSimon J. Gerraty  *
8355fff9558SSimon J. Gerraty  * Or (deprecated) we simply used sha1 hash directly.
8365fff9558SSimon J. Gerraty  *
8375fff9558SSimon J. Gerraty  * To verify we need to replicate that result.
8385fff9558SSimon J. Gerraty  *
8395fff9558SSimon J. Gerraty  * @param[in] pk
8405fff9558SSimon J. Gerraty  *	br_x509_pkey
8415fff9558SSimon J. Gerraty  *
8425fff9558SSimon J. Gerraty  * @paramp[in] file
8435fff9558SSimon J. Gerraty  *	file to be verified
8445fff9558SSimon J. Gerraty  *
8455fff9558SSimon J. Gerraty  * @param[in] sigfile
8465fff9558SSimon J. Gerraty  * 	signature (PEM encoded)
8475fff9558SSimon J. Gerraty  *
8485fff9558SSimon J. Gerraty  * @return NULL on error, otherwise content of file.
8495fff9558SSimon J. Gerraty  */
8505fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
8515fff9558SSimon J. Gerraty static unsigned char *
8525fff9558SSimon J. Gerraty verify_rsa(br_x509_pkey *pk,  const char *file, const char *sigfile)
8535fff9558SSimon J. Gerraty {
8545fff9558SSimon J. Gerraty 	unsigned char rhbuf[br_sha512_SIZE];
8555fff9558SSimon J. Gerraty 	const unsigned char *hash_oid;
8565fff9558SSimon J. Gerraty 	const br_hash_class *md;
8575fff9558SSimon J. Gerraty 	br_hash_compat_context mctx;
8585fff9558SSimon J. Gerraty 	unsigned char *fcp, *scp;
8595fff9558SSimon J. Gerraty 	size_t flen, slen, plen, hlen;
8605fff9558SSimon J. Gerraty 	pem_object *po;
8615fff9558SSimon J. Gerraty 
8625fff9558SSimon J. Gerraty 	if ((fcp = read_file(file, &flen)) == NULL)
8635fff9558SSimon J. Gerraty 		return (NULL);
8645fff9558SSimon J. Gerraty 	if ((scp = read_file(sigfile, &slen)) == NULL) {
8655fff9558SSimon J. Gerraty 		free(fcp);
8665fff9558SSimon J. Gerraty 		return (NULL);
8675fff9558SSimon J. Gerraty 	}
8685fff9558SSimon J. Gerraty 	if ((po = decode_pem(scp, slen, &plen)) == NULL) {
8695fff9558SSimon J. Gerraty 		free(fcp);
8705fff9558SSimon J. Gerraty 		free(scp);
8715fff9558SSimon J. Gerraty 		return (NULL);
8725fff9558SSimon J. Gerraty 	}
8735fff9558SSimon J. Gerraty 
8745fff9558SSimon J. Gerraty 	switch (po->data_len) {
8755fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
8765fff9558SSimon J. Gerraty 	case 256:
8775fff9558SSimon J. Gerraty 		// this is our old deprecated sig method
8785fff9558SSimon J. Gerraty 		md = &br_sha1_vtable;
8795fff9558SSimon J. Gerraty 		hlen = br_sha1_SIZE;
8805fff9558SSimon J. Gerraty 		hash_oid = BR_HASH_OID_SHA1;
8815fff9558SSimon J. Gerraty 		break;
8825fff9558SSimon J. Gerraty #endif
8835fff9558SSimon J. Gerraty 	default:
8845fff9558SSimon J. Gerraty 		md = &br_sha256_vtable;
8855fff9558SSimon J. Gerraty 		hlen = br_sha256_SIZE;
8865fff9558SSimon J. Gerraty 		hash_oid = BR_HASH_OID_SHA256;
8875fff9558SSimon J. Gerraty 		break;
8885fff9558SSimon J. Gerraty 	}
8895fff9558SSimon J. Gerraty 	md->init(&mctx.vtable);
8905fff9558SSimon J. Gerraty 	md->update(&mctx.vtable, fcp, flen);
8915fff9558SSimon J. Gerraty 	md->out(&mctx.vtable, rhbuf);
8925fff9558SSimon J. Gerraty 	if (!verify_rsa_digest(&pk->key.rsa, hash_oid,
8935fff9558SSimon J. Gerraty 		rhbuf, hlen, po->data, po->data_len)) {
8945fff9558SSimon J. Gerraty 		free(fcp);
8955fff9558SSimon J. Gerraty 		fcp = NULL;
8965fff9558SSimon J. Gerraty 	}
8975fff9558SSimon J. Gerraty 	free(scp);
8985fff9558SSimon J. Gerraty 	return (fcp);
8995fff9558SSimon J. Gerraty }
9005fff9558SSimon J. Gerraty #endif
9015fff9558SSimon J. Gerraty 
9025fff9558SSimon J. Gerraty /**
9035fff9558SSimon J. Gerraty  * @brief
9045fff9558SSimon J. Gerraty  * verify a signature and return content of signed file
9055fff9558SSimon J. Gerraty  *
9065fff9558SSimon J. Gerraty  * @param[in] sigfile
9075fff9558SSimon J. Gerraty  * 	file containing signature
9085fff9558SSimon J. Gerraty  * 	we derrive path of signed file and certificate change from
9095fff9558SSimon J. Gerraty  * 	this.
9105fff9558SSimon J. Gerraty  *
9115fff9558SSimon J. Gerraty  * @param[in] flags
9125fff9558SSimon J. Gerraty  * 	only bit 1 significant so far
9135fff9558SSimon J. Gerraty  *
9145fff9558SSimon J. Gerraty  * @return NULL on error otherwise content of signed file
9155fff9558SSimon J. Gerraty  */
9165fff9558SSimon J. Gerraty unsigned char *
9175fff9558SSimon J. Gerraty verify_sig(const char *sigfile, int flags)
9185fff9558SSimon J. Gerraty {
9195fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
9205fff9558SSimon J. Gerraty 	br_name_element cn;
9215fff9558SSimon J. Gerraty 	char cn_buf[80];
9225fff9558SSimon J. Gerraty 	unsigned char cn_oid[4];
9235fff9558SSimon J. Gerraty 	char pbuf[MAXPATHLEN];
9245fff9558SSimon J. Gerraty 	char *cp;
9255fff9558SSimon J. Gerraty 	unsigned char *ucp;
9265fff9558SSimon J. Gerraty 	size_t n;
9275fff9558SSimon J. Gerraty 
9285fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile));
9295fff9558SSimon J. Gerraty 	n = strlcpy(pbuf, sigfile, sizeof(pbuf));
9305fff9558SSimon J. Gerraty 	if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0)
9315fff9558SSimon J. Gerraty 		return (NULL);
9325fff9558SSimon J. Gerraty 	cp = strcpy(&pbuf[n - 3], "certs");
9335fff9558SSimon J. Gerraty 	/*
9345fff9558SSimon J. Gerraty 	 * We want the commonName field
9355fff9558SSimon J. Gerraty 	 * the OID we want is 2,5,4,3 - but DER encoded
9365fff9558SSimon J. Gerraty 	 */
9375fff9558SSimon J. Gerraty 	cn_oid[0] = 3;
9385fff9558SSimon J. Gerraty 	cn_oid[1] = 0x55;
9395fff9558SSimon J. Gerraty 	cn_oid[2] = 4;
9405fff9558SSimon J. Gerraty 	cn_oid[3] = 3;
9415fff9558SSimon J. Gerraty 	cn.oid = cn_oid;
9425fff9558SSimon J. Gerraty 	cn.buf = cn_buf;
9435fff9558SSimon J. Gerraty 	cn.len = sizeof(cn_buf);
9445fff9558SSimon J. Gerraty 
9455fff9558SSimon J. Gerraty 	pk = verify_signer(pbuf, &cn, 1);
9465fff9558SSimon J. Gerraty 	if (!pk) {
9475fff9558SSimon J. Gerraty 		printf("cannot verify: %s: %s\n", pbuf, ve_error_get());
9485fff9558SSimon J. Gerraty 		return (NULL);
9495fff9558SSimon J. Gerraty 	}
9505fff9558SSimon J. Gerraty 	for (; cp > pbuf; cp--) {
9515fff9558SSimon J. Gerraty 		if (*cp == '.') {
9525fff9558SSimon J. Gerraty 			*cp = '\0';
9535fff9558SSimon J. Gerraty 			break;
9545fff9558SSimon J. Gerraty 		}
9555fff9558SSimon J. Gerraty 	}
9565fff9558SSimon J. Gerraty 	switch (pk->key_type) {
9575fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
9585fff9558SSimon J. Gerraty 	case BR_KEYTYPE_EC:
9595fff9558SSimon J. Gerraty 		ucp = verify_ec(pk, pbuf, sigfile);
9605fff9558SSimon J. Gerraty 		break;
9615fff9558SSimon J. Gerraty #endif
9625fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
9635fff9558SSimon J. Gerraty 	case BR_KEYTYPE_RSA:
9645fff9558SSimon J. Gerraty 		ucp = verify_rsa(pk, pbuf, sigfile);
9655fff9558SSimon J. Gerraty 		break;
9665fff9558SSimon J. Gerraty #endif
9675fff9558SSimon J. Gerraty 	default:
9685fff9558SSimon J. Gerraty 		ucp = NULL;		/* not supported */
9695fff9558SSimon J. Gerraty 	}
9705fff9558SSimon J. Gerraty 	xfreepkey(pk);
9715fff9558SSimon J. Gerraty 	if (!ucp) {
9725fff9558SSimon J. Gerraty 		printf("Unverified %s (%s)\n", pbuf,
9735fff9558SSimon J. Gerraty 		    cn.status ? cn_buf : "unknown");
974*66655411SSimon J. Gerraty 	} else if ((flags & VEF_VERBOSE) != 0) {
9755fff9558SSimon J. Gerraty 		printf("Verified %s signed by %s\n", pbuf,
9765fff9558SSimon J. Gerraty 		    cn.status ? cn_buf : "someone we trust");
9775fff9558SSimon J. Gerraty 	}
9785fff9558SSimon J. Gerraty 	return (ucp);
9795fff9558SSimon J. Gerraty }
9805fff9558SSimon J. Gerraty 
9815fff9558SSimon J. Gerraty 
9825fff9558SSimon J. Gerraty /**
9835fff9558SSimon J. Gerraty  * @brief verify hash matches
9845fff9558SSimon J. Gerraty  *
9855fff9558SSimon J. Gerraty  * We have finished hashing a file,
9865fff9558SSimon J. Gerraty  * see if we got the desired result.
9875fff9558SSimon J. Gerraty  *
9885fff9558SSimon J. Gerraty  * @param[in] ctx
9895fff9558SSimon J. Gerraty  *	pointer to hash context
9905fff9558SSimon J. Gerraty  *
9915fff9558SSimon J. Gerraty  * @param[in] md
9925fff9558SSimon J. Gerraty  *	pointer to hash class
9935fff9558SSimon J. Gerraty  *
9945fff9558SSimon J. Gerraty  * @param[in] path
9955fff9558SSimon J. Gerraty  *	name of the file we are checking
9965fff9558SSimon J. Gerraty  *
9975fff9558SSimon J. Gerraty  * @param[in] want
9985fff9558SSimon J. Gerraty  *	the expected result
9995fff9558SSimon J. Gerraty  *
10005fff9558SSimon J. Gerraty  * @param[in] hlen
10015fff9558SSimon J. Gerraty  *	size of hash output
10025fff9558SSimon J. Gerraty  *
10035fff9558SSimon J. Gerraty  * @return 0 on success
10045fff9558SSimon J. Gerraty  */
10055fff9558SSimon J. Gerraty int
10065fff9558SSimon J. Gerraty ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md,
10075fff9558SSimon J. Gerraty     const char *path, const char *want, size_t hlen)
10085fff9558SSimon J. Gerraty {
10095fff9558SSimon J. Gerraty 	char hexbuf[br_sha512_SIZE * 2 + 2];
10105fff9558SSimon J. Gerraty 	unsigned char hbuf[br_sha512_SIZE];
10115fff9558SSimon J. Gerraty 	char *hex;
10125fff9558SSimon J. Gerraty 	int rc;
10135fff9558SSimon J. Gerraty 	int n;
10145fff9558SSimon J. Gerraty 
10155fff9558SSimon J. Gerraty 	md->out(&ctx->vtable, hbuf);
10165fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT
101753f151f9SSimon J. Gerraty 	ve_pcr_update(path, hbuf, hlen);
10185fff9558SSimon J. Gerraty #endif
10195fff9558SSimon J. Gerraty 	hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
10205fff9558SSimon J. Gerraty 	if (!hex)
10215fff9558SSimon J. Gerraty 		return (VE_FINGERPRINT_WRONG);
10225fff9558SSimon J. Gerraty 	n = 2*hlen;
10235fff9558SSimon J. Gerraty 	if ((rc = strncmp(hex, want, n))) {
10245fff9558SSimon J. Gerraty 		ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want);
10255fff9558SSimon J. Gerraty 		rc = VE_FINGERPRINT_WRONG;
10265fff9558SSimon J. Gerraty 	}
10275fff9558SSimon J. Gerraty 	return (rc ? rc : VE_FINGERPRINT_OK);
10285fff9558SSimon J. Gerraty }
10295fff9558SSimon J. Gerraty 
10305fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR
10315fff9558SSimon J. Gerraty static int
10325fff9558SSimon J. Gerraty test_hash(const br_hash_class *md, size_t hlen,
10335fff9558SSimon J. Gerraty     const char *hname, const char *s, size_t slen, const char *want)
10345fff9558SSimon J. Gerraty {
10355fff9558SSimon J. Gerraty 	br_hash_compat_context mctx;
10365fff9558SSimon J. Gerraty 
10375fff9558SSimon J. Gerraty 	md->init(&mctx.vtable);
10385fff9558SSimon J. Gerraty 	md->update(&mctx.vtable, s, slen);
10395fff9558SSimon J. Gerraty 	return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK);
10405fff9558SSimon J. Gerraty }
10415fff9558SSimon J. Gerraty 
10425fff9558SSimon J. Gerraty #endif
10435fff9558SSimon J. Gerraty 
10445fff9558SSimon J. Gerraty #define ve_test_hash(n, N) \
10455fff9558SSimon J. Gerraty 	printf("Testing hash: " #n "\t\t\t\t%s\n", \
10465fff9558SSimon J. Gerraty 	    test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \
10479bee6a60SSimon J. Gerraty 	    VE_HASH_KAT_STR, VE_HASH_KAT_STRLEN(VE_HASH_KAT_STR), \
10485fff9558SSimon J. Gerraty 	    vh_ ## N) ? "Failed" : "Passed")
10495fff9558SSimon J. Gerraty 
10505fff9558SSimon J. Gerraty /**
10515fff9558SSimon J. Gerraty  * @brief
10525fff9558SSimon J. Gerraty  * run self tests on hash and signature verification
10535fff9558SSimon J. Gerraty  *
10545fff9558SSimon J. Gerraty  * Test that the hash methods (SHA1 and SHA256) work.
10555fff9558SSimon J. Gerraty  * Test that we can verify a certificate for each supported
10565fff9558SSimon J. Gerraty  * Root CA.
10575fff9558SSimon J. Gerraty  *
10585fff9558SSimon J. Gerraty  * @return cached result.
10595fff9558SSimon J. Gerraty  */
10605fff9558SSimon J. Gerraty int
10615fff9558SSimon J. Gerraty ve_self_tests(void)
10625fff9558SSimon J. Gerraty {
10635fff9558SSimon J. Gerraty 	static int once = -1;
10645fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR
10655fff9558SSimon J. Gerraty 	br_x509_certificate *xcs;
10665fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
10675fff9558SSimon J. Gerraty 	br_name_element cn;
10685fff9558SSimon J. Gerraty 	char cn_buf[80];
10695fff9558SSimon J. Gerraty 	unsigned char cn_oid[4];
10705fff9558SSimon J. Gerraty 	size_t num;
10715fff9558SSimon J. Gerraty 	size_t u;
10725fff9558SSimon J. Gerraty #endif
10735fff9558SSimon J. Gerraty 
10745fff9558SSimon J. Gerraty 	if (once >= 0)
10755fff9558SSimon J. Gerraty 		return (once);
10765fff9558SSimon J. Gerraty 	once = 0;
10775fff9558SSimon J. Gerraty 
10785fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("Self tests...\n"));
10795fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR
10805fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT
10815fff9558SSimon J. Gerraty 	ve_test_hash(sha1, SHA1);
10825fff9558SSimon J. Gerraty #endif
10835fff9558SSimon J. Gerraty #ifdef VE_SHA256_SUPPORT
10845fff9558SSimon J. Gerraty 	ve_test_hash(sha256, SHA256);
10855fff9558SSimon J. Gerraty #endif
10865fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT
10875fff9558SSimon J. Gerraty 	ve_test_hash(sha384, SHA384);
10885fff9558SSimon J. Gerraty #endif
10895fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT
10905fff9558SSimon J. Gerraty 	ve_test_hash(sha512, SHA512);
10915fff9558SSimon J. Gerraty #endif
10925fff9558SSimon J. Gerraty #endif
10935fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR
10945fff9558SSimon J. Gerraty 	xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
10955fff9558SSimon J. Gerraty 	    sizeof(VERIFY_CERTS_STR), &num);
10969bee6a60SSimon J. Gerraty 	if (xcs != NULL) {
10975fff9558SSimon J. Gerraty 		/*
10985fff9558SSimon J. Gerraty 		 * We want the commonName field
10995fff9558SSimon J. Gerraty 		 * the OID we want is 2,5,4,3 - but DER encoded
11005fff9558SSimon J. Gerraty 		 */
11015fff9558SSimon J. Gerraty 		cn_oid[0] = 3;
11025fff9558SSimon J. Gerraty 		cn_oid[1] = 0x55;
11035fff9558SSimon J. Gerraty 		cn_oid[2] = 4;
11045fff9558SSimon J. Gerraty 		cn_oid[3] = 3;
11055fff9558SSimon J. Gerraty 		cn.oid = cn_oid;
11065fff9558SSimon J. Gerraty 		cn.buf = cn_buf;
11075fff9558SSimon J. Gerraty 
11085fff9558SSimon J. Gerraty 		for (u = 0; u < num; u ++) {
11095fff9558SSimon J. Gerraty 			cn.len = sizeof(cn_buf);
111013ea0450SMarcin Wojtas 			if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
111113ea0450SMarcin Wojtas 				free_cert_contents(&xcs[u]);
11125fff9558SSimon J. Gerraty 				once++;
11135fff9558SSimon J. Gerraty 				printf("Testing verify certificate: %s\tPassed\n",
11145fff9558SSimon J. Gerraty 				    cn.status ? cn_buf : "");
11155fff9558SSimon J. Gerraty 				xfreepkey(pk);
11165fff9558SSimon J. Gerraty 			}
11175fff9558SSimon J. Gerraty 		}
11185fff9558SSimon J. Gerraty 		if (!once)
11195fff9558SSimon J. Gerraty 			printf("Testing verify certificate:\t\t\tFailed\n");
11205fff9558SSimon J. Gerraty 		xfree(xcs);
11219bee6a60SSimon J. Gerraty 	}
11225fff9558SSimon J. Gerraty #endif	/* VERIFY_CERTS_STR */
11235fff9558SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
11245fff9558SSimon J. Gerraty 	if (!openpgp_self_tests())
11255fff9558SSimon J. Gerraty 		once++;
11265fff9558SSimon J. Gerraty #endif
11275fff9558SSimon J. Gerraty 	return (once);
11285fff9558SSimon J. Gerraty }
1129