xref: /freebsd/lib/libsecureboot/vets.c (revision 13ea0450a9c8742119d36f3bf8f47accdce46e54)
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 
465fff9558SSimon J. Gerraty #define SECONDS_PER_DAY		86400
475fff9558SSimon J. Gerraty #define X509_DAYS_TO_UTC0	719528
485fff9558SSimon J. Gerraty 
495fff9558SSimon J. Gerraty int DebugVe = 0;
505fff9558SSimon J. Gerraty 
515fff9558SSimon J. Gerraty typedef VECTOR(br_x509_certificate) cert_list;
52*13ea0450SMarcin Wojtas typedef VECTOR(hash_data) digest_list;
535fff9558SSimon J. Gerraty 
545fff9558SSimon J. Gerraty static anchor_list trust_anchors = VEC_INIT;
55*13ea0450SMarcin Wojtas static anchor_list forbidden_anchors = VEC_INIT;
56*13ea0450SMarcin Wojtas static digest_list forbidden_digests = VEC_INIT;
575fff9558SSimon J. Gerraty 
585fff9558SSimon J. Gerraty void
595fff9558SSimon J. Gerraty ve_debug_set(int n)
605fff9558SSimon J. Gerraty {
615fff9558SSimon J. Gerraty 	DebugVe = n;
625fff9558SSimon J. Gerraty }
635fff9558SSimon J. Gerraty 
645fff9558SSimon J. Gerraty static char ebuf[512];
655fff9558SSimon J. Gerraty 
665fff9558SSimon J. Gerraty char *
675fff9558SSimon J. Gerraty ve_error_get(void)
685fff9558SSimon J. Gerraty {
695fff9558SSimon J. Gerraty 	return (ebuf);
705fff9558SSimon J. Gerraty }
715fff9558SSimon J. Gerraty 
725fff9558SSimon J. Gerraty int
735fff9558SSimon J. Gerraty ve_error_set(const char *fmt, ...)
745fff9558SSimon J. Gerraty {
755fff9558SSimon J. Gerraty 	int rc;
765fff9558SSimon J. Gerraty 	va_list ap;
775fff9558SSimon J. Gerraty 
785fff9558SSimon J. Gerraty 	va_start(ap, fmt);
795fff9558SSimon J. Gerraty 	ebuf[0] = '\0';
805fff9558SSimon J. Gerraty 	rc = 0;
815fff9558SSimon J. Gerraty 	if (fmt) {
825fff9558SSimon J. Gerraty #ifdef STAND_H
835fff9558SSimon J. Gerraty 		vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */
845fff9558SSimon J. Gerraty 		ebuf[sizeof(ebuf) - 1] = '\0';
855fff9558SSimon J. Gerraty 		rc = strlen(ebuf);
865fff9558SSimon J. Gerraty #else
875fff9558SSimon J. Gerraty 		rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap);
885fff9558SSimon J. Gerraty #endif
895fff9558SSimon J. Gerraty 	}
905fff9558SSimon J. Gerraty 	va_end(ap);
915fff9558SSimon J. Gerraty 	return (rc);
925fff9558SSimon J. Gerraty }
935fff9558SSimon J. Gerraty 
945fff9558SSimon J. Gerraty /* this is the time we use for verifying certs */
955fff9558SSimon J. Gerraty static time_t ve_utc = 0;
965fff9558SSimon J. Gerraty 
975fff9558SSimon J. Gerraty /**
985fff9558SSimon J. Gerraty  * @brief
995fff9558SSimon J. Gerraty  * set ve_utc used for certificate verification
1005fff9558SSimon J. Gerraty  *
1015fff9558SSimon J. Gerraty  * @param[in] utc
1025fff9558SSimon J. Gerraty  *	time - ignored unless greater than current value.
1035fff9558SSimon J. Gerraty  */
1045fff9558SSimon J. Gerraty void
1055fff9558SSimon J. Gerraty ve_utc_set(time_t utc)
1065fff9558SSimon J. Gerraty {
1075fff9558SSimon J. Gerraty 	if (utc > ve_utc) {
1085fff9558SSimon J. Gerraty 		DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc));
1095fff9558SSimon J. Gerraty 		ve_utc = utc;
1105fff9558SSimon J. Gerraty 	}
1115fff9558SSimon J. Gerraty }
1125fff9558SSimon J. Gerraty 
1135fff9558SSimon J. Gerraty static void
1145fff9558SSimon J. Gerraty free_cert_contents(br_x509_certificate *xc)
1155fff9558SSimon J. Gerraty {
1165fff9558SSimon J. Gerraty 	xfree(xc->data);
1175fff9558SSimon J. Gerraty }
1185fff9558SSimon J. Gerraty 
119*13ea0450SMarcin Wojtas /* ASN parsing related defines */
120*13ea0450SMarcin Wojtas #define ASN1_PRIMITIVE_TAG 0x1F
121*13ea0450SMarcin Wojtas #define ASN1_INF_LENGTH    0x80
122*13ea0450SMarcin Wojtas #define ASN1_LENGTH_MASK   0x7F
123*13ea0450SMarcin Wojtas 
124*13ea0450SMarcin Wojtas /*
125*13ea0450SMarcin Wojtas  * Get TBS part of certificate.
126*13ea0450SMarcin Wojtas  * Since BearSSL doesn't provide any API to do this,
127*13ea0450SMarcin Wojtas  * it has to be implemented here.
1285fff9558SSimon J. Gerraty  */
129*13ea0450SMarcin Wojtas static void*
130*13ea0450SMarcin Wojtas X509_to_tbs(unsigned char* cert, size_t* output_size)
131*13ea0450SMarcin Wojtas {
132*13ea0450SMarcin Wojtas 	unsigned char *result;
133*13ea0450SMarcin Wojtas 	size_t tbs_size;
134*13ea0450SMarcin Wojtas 	int size, i;
135*13ea0450SMarcin Wojtas 
136*13ea0450SMarcin Wojtas 	if (cert == NULL)
137*13ea0450SMarcin Wojtas 		return (NULL);
138*13ea0450SMarcin Wojtas 
139*13ea0450SMarcin Wojtas 	/* Strip two sequences to get to the TBS section */
140*13ea0450SMarcin Wojtas 	for (i = 0; i < 2; i++) {
141*13ea0450SMarcin Wojtas 		/*
142*13ea0450SMarcin Wojtas 		 * XXX: We don't need to support extended tags since
143*13ea0450SMarcin Wojtas 		 * they should not be present in certificates.
144*13ea0450SMarcin Wojtas 		 */
145*13ea0450SMarcin Wojtas 		if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG)
146*13ea0450SMarcin Wojtas 			return (NULL);
147*13ea0450SMarcin Wojtas 
148*13ea0450SMarcin Wojtas 		cert++;
149*13ea0450SMarcin Wojtas 
150*13ea0450SMarcin Wojtas 		if (*cert == ASN1_INF_LENGTH)
151*13ea0450SMarcin Wojtas 			return (NULL);
152*13ea0450SMarcin Wojtas 
153*13ea0450SMarcin Wojtas 		size = *cert & ASN1_LENGTH_MASK;
154*13ea0450SMarcin Wojtas 		tbs_size = 0;
155*13ea0450SMarcin Wojtas 
156*13ea0450SMarcin Wojtas 		/* Size can either be stored on a single or multiple bytes */
157*13ea0450SMarcin Wojtas 		if (*cert & (ASN1_LENGTH_MASK + 1)) {
158*13ea0450SMarcin Wojtas 			cert++;
159*13ea0450SMarcin Wojtas 			while (*cert == 0 && size > 0) {
160*13ea0450SMarcin Wojtas 				cert++;
161*13ea0450SMarcin Wojtas 				size--;
162*13ea0450SMarcin Wojtas 			}
163*13ea0450SMarcin Wojtas 			while (size-- > 0) {
164*13ea0450SMarcin Wojtas 				tbs_size <<= 8;
165*13ea0450SMarcin Wojtas 				tbs_size |= *(cert++);
166*13ea0450SMarcin Wojtas 			}
167*13ea0450SMarcin Wojtas 		}
168*13ea0450SMarcin Wojtas 		if (i == 0)
169*13ea0450SMarcin Wojtas 			result = cert;
170*13ea0450SMarcin Wojtas 	}
171*13ea0450SMarcin Wojtas 	tbs_size += (cert - result);
172*13ea0450SMarcin Wojtas 
173*13ea0450SMarcin Wojtas 	if (output_size != NULL)
174*13ea0450SMarcin Wojtas 		*output_size = tbs_size;
175*13ea0450SMarcin Wojtas 
176*13ea0450SMarcin Wojtas 	return (result);
177*13ea0450SMarcin Wojtas }
178*13ea0450SMarcin Wojtas 
179*13ea0450SMarcin Wojtas void
180*13ea0450SMarcin Wojtas ve_forbidden_digest_add(hash_data *digest, size_t num)
181*13ea0450SMarcin Wojtas {
182*13ea0450SMarcin Wojtas 	while (num--)
183*13ea0450SMarcin Wojtas 		VEC_ADD(forbidden_digests, digest[num]);
184*13ea0450SMarcin Wojtas }
185*13ea0450SMarcin Wojtas 
186*13ea0450SMarcin Wojtas static size_t
187*13ea0450SMarcin Wojtas ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors)
1885fff9558SSimon J. Gerraty {
1895fff9558SSimon J. Gerraty 	br_x509_trust_anchor ta;
1905fff9558SSimon J. Gerraty 	size_t u;
1915fff9558SSimon J. Gerraty 
1925fff9558SSimon J. Gerraty 	for (u = 0; u < num; u++) {
1935fff9558SSimon J. Gerraty 		if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
1945fff9558SSimon J. Gerraty 			break;
1955fff9558SSimon J. Gerraty 		}
196*13ea0450SMarcin Wojtas 		VEC_ADD(*anchors, ta);
1975fff9558SSimon J. Gerraty 	}
1985fff9558SSimon J. Gerraty 	return (u);
1995fff9558SSimon J. Gerraty }
2005fff9558SSimon J. Gerraty 
2015fff9558SSimon J. Gerraty /**
2025fff9558SSimon J. Gerraty  * @brief
203*13ea0450SMarcin Wojtas  * add certs to our trust store
204*13ea0450SMarcin Wojtas  */
205*13ea0450SMarcin Wojtas size_t
206*13ea0450SMarcin Wojtas ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
207*13ea0450SMarcin Wojtas {
208*13ea0450SMarcin Wojtas 	return (ve_anchors_add(xcs, num, &trust_anchors));
209*13ea0450SMarcin Wojtas }
210*13ea0450SMarcin Wojtas 
211*13ea0450SMarcin Wojtas size_t
212*13ea0450SMarcin Wojtas ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num)
213*13ea0450SMarcin Wojtas {
214*13ea0450SMarcin Wojtas 	return (ve_anchors_add(xcs, num, &forbidden_anchors));
215*13ea0450SMarcin Wojtas }
216*13ea0450SMarcin Wojtas 
217*13ea0450SMarcin Wojtas /**
218*13ea0450SMarcin Wojtas  * @brief
2195fff9558SSimon J. Gerraty  * initialize our trust_anchors from ta_PEM
2205fff9558SSimon J. Gerraty  */
2215fff9558SSimon J. Gerraty int
2225fff9558SSimon J. Gerraty ve_trust_init(void)
2235fff9558SSimon J. Gerraty {
224*13ea0450SMarcin Wojtas #ifdef TRUST_ANCHOR_STR
2255fff9558SSimon J. Gerraty 	br_x509_certificate *xcs;
226*13ea0450SMarcin Wojtas #endif
2275fff9558SSimon J. Gerraty 	static int once = -1;
2285fff9558SSimon J. Gerraty 	size_t num;
2295fff9558SSimon J. Gerraty 
2305fff9558SSimon J. Gerraty 	if (once >= 0)
2315fff9558SSimon J. Gerraty 		return (once);
2325fff9558SSimon J. Gerraty 
2335fff9558SSimon J. Gerraty 	ve_utc_set(time(NULL));
2345fff9558SSimon J. Gerraty #ifdef BUILD_UTC
2355fff9558SSimon J. Gerraty 	ve_utc_set(BUILD_UTC);		/* just in case */
2365fff9558SSimon J. Gerraty #endif
2375fff9558SSimon J. Gerraty 	ve_error_set(NULL);		/* make sure it is empty */
2385fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT
2395fff9558SSimon J. Gerraty 	ve_pcr_init();
2405fff9558SSimon J. Gerraty #endif
2415fff9558SSimon J. Gerraty 
2425fff9558SSimon J. Gerraty #ifdef TRUST_ANCHOR_STR
2435fff9558SSimon J. Gerraty 	xcs = parse_certificates(__DECONST(unsigned char *, TRUST_ANCHOR_STR),
2445fff9558SSimon J. Gerraty 	    sizeof(TRUST_ANCHOR_STR), &num);
245*13ea0450SMarcin Wojtas 	if (xcs != NULL)
2465fff9558SSimon J. Gerraty 		num = ve_trust_anchors_add(xcs, num);
2475fff9558SSimon J. Gerraty #endif
248*13ea0450SMarcin Wojtas 	once = (int) VEC_LEN(trust_anchors);
249*13ea0450SMarcin Wojtas 
250*13ea0450SMarcin Wojtas 	return (once);
2515fff9558SSimon J. Gerraty }
2525fff9558SSimon J. Gerraty 
2535fff9558SSimon J. Gerraty /**
2545fff9558SSimon J. Gerraty  * if we can verify the certificate chain in "certs",
2555fff9558SSimon J. Gerraty  * return the public key and if "xcp" is !NULL the associated
2565fff9558SSimon J. Gerraty  * certificate
2575fff9558SSimon J. Gerraty  */
2585fff9558SSimon J. Gerraty static br_x509_pkey *
2595fff9558SSimon J. Gerraty verify_signer_xcs(br_x509_certificate *xcs,
2605fff9558SSimon J. Gerraty     size_t num,
261*13ea0450SMarcin Wojtas     br_name_element *elts, size_t num_elts,
262*13ea0450SMarcin Wojtas     anchor_list *anchors)
2635fff9558SSimon J. Gerraty {
2645fff9558SSimon J. Gerraty 	br_x509_minimal_context mc;
2655fff9558SSimon J. Gerraty 	br_x509_certificate *xc;
2665fff9558SSimon J. Gerraty 	size_t u;
2675fff9558SSimon J. Gerraty 	cert_list chain = VEC_INIT;
2685fff9558SSimon J. Gerraty 	const br_x509_pkey *tpk;
2695fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
2705fff9558SSimon J. Gerraty 	unsigned int usages;
2715fff9558SSimon J. Gerraty 	int err;
2725fff9558SSimon J. Gerraty 
2735fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num));
2745fff9558SSimon J. Gerraty 	VEC_ADDMANY(chain, xcs, num);
2755fff9558SSimon J. Gerraty 	if (VEC_LEN(chain) == 0) {
2765fff9558SSimon J. Gerraty 		ve_error_set("ERROR: no/invalid certificate chain\n");
2775fff9558SSimon J. Gerraty 		return (NULL);
2785fff9558SSimon J. Gerraty 	}
2795fff9558SSimon J. Gerraty 
2805fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n",
281*13ea0450SMarcin Wojtas 		VEC_LEN(*anchors)));
2825fff9558SSimon J. Gerraty 
2835fff9558SSimon J. Gerraty 	br_x509_minimal_init(&mc, &br_sha256_vtable,
284*13ea0450SMarcin Wojtas 	    &VEC_ELT(*anchors, 0),
285*13ea0450SMarcin Wojtas 	    VEC_LEN(*anchors));
2865fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
2875fff9558SSimon J. Gerraty 	br_x509_minimal_set_ecdsa(&mc,
2885fff9558SSimon J. Gerraty 	    &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
2895fff9558SSimon J. Gerraty #endif
2905fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
2915fff9558SSimon J. Gerraty 	br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
2925fff9558SSimon J. Gerraty #endif
2935fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
2945fff9558SSimon J. Gerraty 	/* This is deprecated! do not enable unless you absoultely have to */
2955fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable);
2965fff9558SSimon J. Gerraty #endif
2975fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable);
2985fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT
2995fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable);
3005fff9558SSimon J. Gerraty #endif
3015fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT
3025fff9558SSimon J. Gerraty 	br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable);
3035fff9558SSimon J. Gerraty #endif
3045fff9558SSimon J. Gerraty 	br_x509_minimal_set_name_elements(&mc, elts, num_elts);
3055fff9558SSimon J. Gerraty 
3065fff9558SSimon J. Gerraty #ifdef _STANDALONE
3075fff9558SSimon J. Gerraty 	/*
3085fff9558SSimon J. Gerraty 	 * Clock is probably bogus so we use ve_utc.
3095fff9558SSimon J. Gerraty 	 */
3105fff9558SSimon J. Gerraty 	mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0;
3115fff9558SSimon J. Gerraty 	mc.seconds = (ve_utc % SECONDS_PER_DAY);
3125fff9558SSimon J. Gerraty #endif
3135fff9558SSimon J. Gerraty 
3145fff9558SSimon J. Gerraty 	mc.vtable->start_chain(&mc.vtable, NULL);
3155fff9558SSimon J. Gerraty 	for (u = 0; u < VEC_LEN(chain); u ++) {
3165fff9558SSimon J. Gerraty 		xc = &VEC_ELT(chain, u);
3175fff9558SSimon J. Gerraty 		mc.vtable->start_cert(&mc.vtable, xc->data_len);
3185fff9558SSimon J. Gerraty 		mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
3195fff9558SSimon J. Gerraty 		mc.vtable->end_cert(&mc.vtable);
3205fff9558SSimon J. Gerraty 		switch (mc.err) {
3215fff9558SSimon J. Gerraty 		case 0:
3225fff9558SSimon J. Gerraty 		case BR_ERR_X509_OK:
3235fff9558SSimon J. Gerraty 		case BR_ERR_X509_EXPIRED:
3245fff9558SSimon J. Gerraty 			break;
3255fff9558SSimon J. Gerraty 		default:
3265fff9558SSimon J. Gerraty 			printf("u=%zu mc.err=%d\n", u, mc.err);
3275fff9558SSimon J. Gerraty 			break;
3285fff9558SSimon J. Gerraty 		}
3295fff9558SSimon J. Gerraty 	}
3305fff9558SSimon J. Gerraty 	err = mc.vtable->end_chain(&mc.vtable);
3315fff9558SSimon J. Gerraty 	pk = NULL;
3325fff9558SSimon J. Gerraty 	if (err) {
3335fff9558SSimon J. Gerraty 		ve_error_set("Validation failed, err = %d", err);
3345fff9558SSimon J. Gerraty 	} else {
3355fff9558SSimon J. Gerraty 		tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
3365fff9558SSimon J. Gerraty 		if (tpk != NULL) {
3375fff9558SSimon J. Gerraty 			pk = xpkeydup(tpk);
3385fff9558SSimon J. Gerraty 		}
3395fff9558SSimon J. Gerraty 	}
340*13ea0450SMarcin Wojtas 	VEC_CLEAR(chain);
3415fff9558SSimon J. Gerraty 	return (pk);
3425fff9558SSimon J. Gerraty }
3435fff9558SSimon J. Gerraty 
344*13ea0450SMarcin Wojtas /*
345*13ea0450SMarcin Wojtas  * Check if digest of one of the certificates from verified chain
346*13ea0450SMarcin Wojtas  * is present in the forbidden database.
347*13ea0450SMarcin Wojtas  * Since UEFI allows to store three types of digests
348*13ea0450SMarcin Wojtas  * all of them have to be checked separately.
349*13ea0450SMarcin Wojtas  */
350*13ea0450SMarcin Wojtas static int
351*13ea0450SMarcin Wojtas check_forbidden_digests(br_x509_certificate *xcs, size_t num)
352*13ea0450SMarcin Wojtas {
353*13ea0450SMarcin Wojtas 	unsigned char sha256_digest[br_sha256_SIZE];
354*13ea0450SMarcin Wojtas 	unsigned char sha384_digest[br_sha384_SIZE];
355*13ea0450SMarcin Wojtas 	unsigned char sha512_digest[br_sha512_SIZE];
356*13ea0450SMarcin Wojtas 	void *tbs;
357*13ea0450SMarcin Wojtas 	hash_data *digest;
358*13ea0450SMarcin Wojtas 	br_hash_compat_context ctx;
359*13ea0450SMarcin Wojtas 	const br_hash_class *md;
360*13ea0450SMarcin Wojtas 	size_t tbs_len, i;
361*13ea0450SMarcin Wojtas 	int have_sha256, have_sha384, have_sha512;
362*13ea0450SMarcin Wojtas 
363*13ea0450SMarcin Wojtas 	if (VEC_LEN(forbidden_digests) == 0)
364*13ea0450SMarcin Wojtas 		return (0);
365*13ea0450SMarcin Wojtas 
366*13ea0450SMarcin Wojtas 	/*
367*13ea0450SMarcin Wojtas 	 * Iterate through certificates, extract their To-Be-Signed section,
368*13ea0450SMarcin Wojtas 	 * and compare its digest against the ones in the forbidden database.
369*13ea0450SMarcin Wojtas 	 */
370*13ea0450SMarcin Wojtas 	while (num--) {
371*13ea0450SMarcin Wojtas 		tbs = X509_to_tbs(xcs[num].data, &tbs_len);
372*13ea0450SMarcin Wojtas 		if (tbs == NULL) {
373*13ea0450SMarcin Wojtas 			printf("Failed to obtain TBS part of certificate\n");
374*13ea0450SMarcin Wojtas 			return (1);
375*13ea0450SMarcin Wojtas 		}
376*13ea0450SMarcin Wojtas 		have_sha256 = have_sha384 = have_sha512 = 0;
377*13ea0450SMarcin Wojtas 
378*13ea0450SMarcin Wojtas 		for (i = 0; i < VEC_LEN(forbidden_digests); i++) {
379*13ea0450SMarcin Wojtas 			digest = &VEC_ELT(forbidden_digests, i);
380*13ea0450SMarcin Wojtas 			switch (digest->hash_size) {
381*13ea0450SMarcin Wojtas 			case br_sha256_SIZE:
382*13ea0450SMarcin Wojtas 				if (!have_sha256) {
383*13ea0450SMarcin Wojtas 					have_sha256 = 1;
384*13ea0450SMarcin Wojtas 					md = &br_sha256_vtable;
385*13ea0450SMarcin Wojtas 					md->init(&ctx.vtable);
386*13ea0450SMarcin Wojtas 					md->update(&ctx.vtable, tbs, tbs_len);
387*13ea0450SMarcin Wojtas 					md->out(&ctx.vtable, sha256_digest);
388*13ea0450SMarcin Wojtas 				}
389*13ea0450SMarcin Wojtas 				if (!memcmp(sha256_digest,
390*13ea0450SMarcin Wojtas 					digest->data,
391*13ea0450SMarcin Wojtas 					br_sha256_SIZE))
392*13ea0450SMarcin Wojtas 					return (1);
393*13ea0450SMarcin Wojtas 
394*13ea0450SMarcin Wojtas 				break;
395*13ea0450SMarcin Wojtas 			case br_sha384_SIZE:
396*13ea0450SMarcin Wojtas 				if (!have_sha384) {
397*13ea0450SMarcin Wojtas 					have_sha384 = 1;
398*13ea0450SMarcin Wojtas 					md = &br_sha384_vtable;
399*13ea0450SMarcin Wojtas 					md->init(&ctx.vtable);
400*13ea0450SMarcin Wojtas 					md->update(&ctx.vtable, tbs, tbs_len);
401*13ea0450SMarcin Wojtas 					md->out(&ctx.vtable, sha384_digest);
402*13ea0450SMarcin Wojtas 				}
403*13ea0450SMarcin Wojtas 				if (!memcmp(sha384_digest,
404*13ea0450SMarcin Wojtas 					digest->data,
405*13ea0450SMarcin Wojtas 					br_sha384_SIZE))
406*13ea0450SMarcin Wojtas 					return (1);
407*13ea0450SMarcin Wojtas 
408*13ea0450SMarcin Wojtas 				break;
409*13ea0450SMarcin Wojtas 			case br_sha512_SIZE:
410*13ea0450SMarcin Wojtas 				if (!have_sha512) {
411*13ea0450SMarcin Wojtas 					have_sha512 = 1;
412*13ea0450SMarcin Wojtas 					md = &br_sha512_vtable;
413*13ea0450SMarcin Wojtas 					md->init(&ctx.vtable);
414*13ea0450SMarcin Wojtas 					md->update(&ctx.vtable, tbs, tbs_len);
415*13ea0450SMarcin Wojtas 					md->out(&ctx.vtable, sha512_digest);
416*13ea0450SMarcin Wojtas 				}
417*13ea0450SMarcin Wojtas 				if (!memcmp(sha512_digest,
418*13ea0450SMarcin Wojtas 					digest->data,
419*13ea0450SMarcin Wojtas 					br_sha512_SIZE))
420*13ea0450SMarcin Wojtas 					return (1);
421*13ea0450SMarcin Wojtas 
422*13ea0450SMarcin Wojtas 				break;
423*13ea0450SMarcin Wojtas 			}
424*13ea0450SMarcin Wojtas 		}
425*13ea0450SMarcin Wojtas 	}
426*13ea0450SMarcin Wojtas 
427*13ea0450SMarcin Wojtas 	return (0);
428*13ea0450SMarcin Wojtas }
429*13ea0450SMarcin Wojtas 
4305fff9558SSimon J. Gerraty static br_x509_pkey *
4315fff9558SSimon J. Gerraty verify_signer(const char *certs,
4325fff9558SSimon J. Gerraty     br_name_element *elts, size_t num_elts)
4335fff9558SSimon J. Gerraty {
4345fff9558SSimon J. Gerraty 	br_x509_certificate *xcs;
4355fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
4365fff9558SSimon J. Gerraty 	size_t num;
4375fff9558SSimon J. Gerraty 
438*13ea0450SMarcin Wojtas 	pk = NULL;
439*13ea0450SMarcin Wojtas 
4405fff9558SSimon J. Gerraty 	ve_trust_init();
4415fff9558SSimon J. Gerraty 	xcs = read_certificates(certs, &num);
4425fff9558SSimon J. Gerraty 	if (xcs == NULL) {
4435fff9558SSimon J. Gerraty 		ve_error_set("cannot read certificates\n");
4445fff9558SSimon J. Gerraty 		return (NULL);
4455fff9558SSimon J. Gerraty 	}
446*13ea0450SMarcin Wojtas 
447*13ea0450SMarcin Wojtas 	/*
448*13ea0450SMarcin Wojtas 	 * Check if either
449*13ea0450SMarcin Wojtas 	 * 1. There is a direct match between cert from forbidden_anchors
450*13ea0450SMarcin Wojtas 	 * and a cert from chain.
451*13ea0450SMarcin Wojtas 	 * 2. CA that signed the chain is found in forbidden_anchors.
452*13ea0450SMarcin Wojtas 	 */
453*13ea0450SMarcin Wojtas 	if (VEC_LEN(forbidden_anchors) > 0)
454*13ea0450SMarcin Wojtas 		pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors);
455*13ea0450SMarcin Wojtas 	if (pk != NULL) {
456*13ea0450SMarcin Wojtas 		ve_error_set("Certificate is on forbidden list\n");
457*13ea0450SMarcin Wojtas 		xfreepkey(pk);
458*13ea0450SMarcin Wojtas 		pk = NULL;
459*13ea0450SMarcin Wojtas 		goto out;
460*13ea0450SMarcin Wojtas 	}
461*13ea0450SMarcin Wojtas 
462*13ea0450SMarcin Wojtas 	pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors);
463*13ea0450SMarcin Wojtas 	if (pk == NULL)
464*13ea0450SMarcin Wojtas 		goto out;
465*13ea0450SMarcin Wojtas 
466*13ea0450SMarcin Wojtas 	/*
467*13ea0450SMarcin Wojtas 	 * Check if hash of tbs part of any certificate in chain
468*13ea0450SMarcin Wojtas 	 * is on the forbidden list.
469*13ea0450SMarcin Wojtas 	 */
470*13ea0450SMarcin Wojtas 	if (check_forbidden_digests(xcs, num)) {
471*13ea0450SMarcin Wojtas 		ve_error_set("Certificate hash is on forbidden list\n");
472*13ea0450SMarcin Wojtas 		xfreepkey(pk);
473*13ea0450SMarcin Wojtas 		pk = NULL;
474*13ea0450SMarcin Wojtas 	}
475*13ea0450SMarcin Wojtas out:
476*13ea0450SMarcin Wojtas 	free_certificates(xcs, num);
4775fff9558SSimon J. Gerraty 	return (pk);
4785fff9558SSimon J. Gerraty }
4795fff9558SSimon J. Gerraty 
4805fff9558SSimon J. Gerraty /**
4815fff9558SSimon J. Gerraty  * we need a hex digest including trailing newline below
4825fff9558SSimon J. Gerraty  */
4835fff9558SSimon J. Gerraty char *
4845fff9558SSimon J. Gerraty hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len)
4855fff9558SSimon J. Gerraty {
4865fff9558SSimon J. Gerraty 	char const hex2ascii[] = "0123456789abcdef";
4875fff9558SSimon J. Gerraty 	size_t i;
4885fff9558SSimon J. Gerraty 
4895fff9558SSimon J. Gerraty 	/* every binary byte is 2 chars in hex + newline + null  */
4905fff9558SSimon J. Gerraty 	if (bufsz < (2 * foo_len) + 2)
4915fff9558SSimon J. Gerraty 		return (NULL);
4925fff9558SSimon J. Gerraty 
4935fff9558SSimon J. Gerraty 	for (i = 0; i < foo_len; i++) {
4945fff9558SSimon J. Gerraty 		buf[i * 2] = hex2ascii[foo[i] >> 4];
4955fff9558SSimon J. Gerraty 		buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f];
4965fff9558SSimon J. Gerraty 	}
4975fff9558SSimon J. Gerraty 
4985fff9558SSimon J. Gerraty 	buf[i * 2] = 0x0A; /* we also want a newline */
4995fff9558SSimon J. Gerraty 	buf[i * 2 + 1] = '\0';
5005fff9558SSimon J. Gerraty 
5015fff9558SSimon J. Gerraty 	return (buf);
5025fff9558SSimon J. Gerraty }
5035fff9558SSimon J. Gerraty 
5045fff9558SSimon J. Gerraty /**
5055fff9558SSimon J. Gerraty  * @brief
5065fff9558SSimon J. Gerraty  * verify file against sigfile using pk
5075fff9558SSimon J. Gerraty  *
5085fff9558SSimon J. Gerraty  * When we generated the signature in sigfile,
5095fff9558SSimon J. Gerraty  * we hashed (sha256) file, and sent that to signing server
5105fff9558SSimon J. Gerraty  * which hashed (sha256) that hash.
5115fff9558SSimon J. Gerraty  *
5125fff9558SSimon J. Gerraty  * To verify we need to replicate that result.
5135fff9558SSimon J. Gerraty  *
5145fff9558SSimon J. Gerraty  * @param[in] pk
5155fff9558SSimon J. Gerraty  *	br_x509_pkey
5165fff9558SSimon J. Gerraty  *
5175fff9558SSimon J. Gerraty  * @paramp[in] file
5185fff9558SSimon J. Gerraty  *	file to be verified
5195fff9558SSimon J. Gerraty  *
5205fff9558SSimon J. Gerraty  * @param[in] sigfile
5215fff9558SSimon J. Gerraty  * 	signature (PEM encoded)
5225fff9558SSimon J. Gerraty  *
5235fff9558SSimon J. Gerraty  * @return NULL on error, otherwise content of file.
5245fff9558SSimon J. Gerraty  */
5255fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
5265fff9558SSimon J. Gerraty static unsigned char *
5275fff9558SSimon J. Gerraty verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile)
5285fff9558SSimon J. Gerraty {
5295fff9558SSimon J. Gerraty 	char hexbuf[br_sha512_SIZE * 2 + 2];
5305fff9558SSimon J. Gerraty 	unsigned char rhbuf[br_sha512_SIZE];
5315fff9558SSimon J. Gerraty 	char *hex;
5325fff9558SSimon J. Gerraty 	br_sha256_context ctx;
5335fff9558SSimon J. Gerraty 	unsigned char *fcp, *scp;
5345fff9558SSimon J. Gerraty 	size_t flen, slen, plen;
5355fff9558SSimon J. Gerraty 	pem_object *po;
5365fff9558SSimon J. Gerraty 	const br_ec_impl *ec;
5375fff9558SSimon J. Gerraty 	br_ecdsa_vrfy vrfy;
5385fff9558SSimon J. Gerraty 
5395fff9558SSimon J. Gerraty 	if ((fcp = read_file(file, &flen)) == NULL)
5405fff9558SSimon J. Gerraty 		return (NULL);
5415fff9558SSimon J. Gerraty 	if ((scp = read_file(sigfile, &slen)) == NULL) {
5425fff9558SSimon J. Gerraty 		free(fcp);
5435fff9558SSimon J. Gerraty 		return (NULL);
5445fff9558SSimon J. Gerraty 	}
5455fff9558SSimon J. Gerraty 	if ((po = decode_pem(scp, slen, &plen)) == NULL) {
5465fff9558SSimon J. Gerraty 		free(fcp);
5475fff9558SSimon J. Gerraty 		free(scp);
5485fff9558SSimon J. Gerraty 		return (NULL);
5495fff9558SSimon J. Gerraty 	}
5505fff9558SSimon J. Gerraty 	br_sha256_init(&ctx);
5515fff9558SSimon J. Gerraty 	br_sha256_update(&ctx, fcp, flen);
5525fff9558SSimon J. Gerraty 	br_sha256_out(&ctx, rhbuf);
5535fff9558SSimon J. Gerraty 	hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE);
5545fff9558SSimon J. Gerraty 	/* now hash that */
5555fff9558SSimon J. Gerraty 	if (hex) {
5565fff9558SSimon J. Gerraty 		br_sha256_init(&ctx);
5575fff9558SSimon J. Gerraty 		br_sha256_update(&ctx, hex, strlen(hex));
5585fff9558SSimon J. Gerraty 		br_sha256_out(&ctx, rhbuf);
5595fff9558SSimon J. Gerraty 	}
5605fff9558SSimon J. Gerraty 	ec = br_ec_get_default();
5615fff9558SSimon J. Gerraty 	vrfy = br_ecdsa_vrfy_asn1_get_default();
5625fff9558SSimon J. Gerraty 	if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data,
5635fff9558SSimon J. Gerraty 		po->data_len)) {
5645fff9558SSimon J. Gerraty 		free(fcp);
5655fff9558SSimon J. Gerraty 		fcp = NULL;
5665fff9558SSimon J. Gerraty 	}
5675fff9558SSimon J. Gerraty 	free(scp);
5685fff9558SSimon J. Gerraty 	return (fcp);
5695fff9558SSimon J. Gerraty }
5705fff9558SSimon J. Gerraty #endif
5715fff9558SSimon J. Gerraty 
5725fff9558SSimon J. Gerraty #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT)
5735fff9558SSimon J. Gerraty /**
5745fff9558SSimon J. Gerraty  * @brief verify an rsa digest
5755fff9558SSimon J. Gerraty  *
5765fff9558SSimon J. Gerraty  * @return 0 on failure
5775fff9558SSimon J. Gerraty  */
5785fff9558SSimon J. Gerraty int
5795fff9558SSimon J. Gerraty verify_rsa_digest (br_rsa_public_key *pkey,
5805fff9558SSimon J. Gerraty     const unsigned char *hash_oid,
5815fff9558SSimon J. Gerraty     unsigned char *mdata, size_t mlen,
5825fff9558SSimon J. Gerraty     unsigned char *sdata, size_t slen)
5835fff9558SSimon J. Gerraty {
5845fff9558SSimon J. Gerraty 	br_rsa_pkcs1_vrfy vrfy;
5855fff9558SSimon J. Gerraty 	unsigned char vhbuf[br_sha512_SIZE];
5865fff9558SSimon J. Gerraty 
5875fff9558SSimon J. Gerraty 	vrfy = br_rsa_pkcs1_vrfy_get_default();
5885fff9558SSimon J. Gerraty 
5895fff9558SSimon J. Gerraty 	if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) ||
5905fff9558SSimon J. Gerraty 	    memcmp(vhbuf, mdata, mlen) != 0) {
5915fff9558SSimon J. Gerraty 		return (0);		/* fail */
5925fff9558SSimon J. Gerraty 	}
5935fff9558SSimon J. Gerraty 	return (1);			/* ok */
5945fff9558SSimon J. Gerraty }
5955fff9558SSimon J. Gerraty #endif
5965fff9558SSimon J. Gerraty 
5975fff9558SSimon J. Gerraty /**
5985fff9558SSimon J. Gerraty  * @brief
5995fff9558SSimon J. Gerraty  * verify file against sigfile using pk
6005fff9558SSimon J. Gerraty  *
6015fff9558SSimon J. Gerraty  * When we generated the signature in sigfile,
6025fff9558SSimon J. Gerraty  * we hashed (sha256) file, and sent that to signing server
6035fff9558SSimon J. Gerraty  * which hashed (sha256) that hash.
6045fff9558SSimon J. Gerraty  *
6055fff9558SSimon J. Gerraty  * Or (deprecated) we simply used sha1 hash directly.
6065fff9558SSimon J. Gerraty  *
6075fff9558SSimon J. Gerraty  * To verify we need to replicate that result.
6085fff9558SSimon J. Gerraty  *
6095fff9558SSimon J. Gerraty  * @param[in] pk
6105fff9558SSimon J. Gerraty  *	br_x509_pkey
6115fff9558SSimon J. Gerraty  *
6125fff9558SSimon J. Gerraty  * @paramp[in] file
6135fff9558SSimon J. Gerraty  *	file to be verified
6145fff9558SSimon J. Gerraty  *
6155fff9558SSimon J. Gerraty  * @param[in] sigfile
6165fff9558SSimon J. Gerraty  * 	signature (PEM encoded)
6175fff9558SSimon J. Gerraty  *
6185fff9558SSimon J. Gerraty  * @return NULL on error, otherwise content of file.
6195fff9558SSimon J. Gerraty  */
6205fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
6215fff9558SSimon J. Gerraty static unsigned char *
6225fff9558SSimon J. Gerraty verify_rsa(br_x509_pkey *pk,  const char *file, const char *sigfile)
6235fff9558SSimon J. Gerraty {
6245fff9558SSimon J. Gerraty 	unsigned char rhbuf[br_sha512_SIZE];
6255fff9558SSimon J. Gerraty 	const unsigned char *hash_oid;
6265fff9558SSimon J. Gerraty 	const br_hash_class *md;
6275fff9558SSimon J. Gerraty 	br_hash_compat_context mctx;
6285fff9558SSimon J. Gerraty 	unsigned char *fcp, *scp;
6295fff9558SSimon J. Gerraty 	size_t flen, slen, plen, hlen;
6305fff9558SSimon J. Gerraty 	pem_object *po;
6315fff9558SSimon J. Gerraty 
6325fff9558SSimon J. Gerraty 	if ((fcp = read_file(file, &flen)) == NULL)
6335fff9558SSimon J. Gerraty 		return (NULL);
6345fff9558SSimon J. Gerraty 	if ((scp = read_file(sigfile, &slen)) == NULL) {
6355fff9558SSimon J. Gerraty 		free(fcp);
6365fff9558SSimon J. Gerraty 		return (NULL);
6375fff9558SSimon J. Gerraty 	}
6385fff9558SSimon J. Gerraty 	if ((po = decode_pem(scp, slen, &plen)) == NULL) {
6395fff9558SSimon J. Gerraty 		free(fcp);
6405fff9558SSimon J. Gerraty 		free(scp);
6415fff9558SSimon J. Gerraty 		return (NULL);
6425fff9558SSimon J. Gerraty 	}
6435fff9558SSimon J. Gerraty 
6445fff9558SSimon J. Gerraty 	switch (po->data_len) {
6455fff9558SSimon J. Gerraty #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
6465fff9558SSimon J. Gerraty 	case 256:
6475fff9558SSimon J. Gerraty 		// this is our old deprecated sig method
6485fff9558SSimon J. Gerraty 		md = &br_sha1_vtable;
6495fff9558SSimon J. Gerraty 		hlen = br_sha1_SIZE;
6505fff9558SSimon J. Gerraty 		hash_oid = BR_HASH_OID_SHA1;
6515fff9558SSimon J. Gerraty 		break;
6525fff9558SSimon J. Gerraty #endif
6535fff9558SSimon J. Gerraty 	default:
6545fff9558SSimon J. Gerraty 		md = &br_sha256_vtable;
6555fff9558SSimon J. Gerraty 		hlen = br_sha256_SIZE;
6565fff9558SSimon J. Gerraty 		hash_oid = BR_HASH_OID_SHA256;
6575fff9558SSimon J. Gerraty 		break;
6585fff9558SSimon J. Gerraty 	}
6595fff9558SSimon J. Gerraty 	md->init(&mctx.vtable);
6605fff9558SSimon J. Gerraty 	md->update(&mctx.vtable, fcp, flen);
6615fff9558SSimon J. Gerraty 	md->out(&mctx.vtable, rhbuf);
6625fff9558SSimon J. Gerraty 	if (!verify_rsa_digest(&pk->key.rsa, hash_oid,
6635fff9558SSimon J. Gerraty 		rhbuf, hlen, po->data, po->data_len)) {
6645fff9558SSimon J. Gerraty 		free(fcp);
6655fff9558SSimon J. Gerraty 		fcp = NULL;
6665fff9558SSimon J. Gerraty 	}
6675fff9558SSimon J. Gerraty 	free(scp);
6685fff9558SSimon J. Gerraty 	return (fcp);
6695fff9558SSimon J. Gerraty }
6705fff9558SSimon J. Gerraty #endif
6715fff9558SSimon J. Gerraty 
6725fff9558SSimon J. Gerraty /**
6735fff9558SSimon J. Gerraty  * @brief
6745fff9558SSimon J. Gerraty  * verify a signature and return content of signed file
6755fff9558SSimon J. Gerraty  *
6765fff9558SSimon J. Gerraty  * @param[in] sigfile
6775fff9558SSimon J. Gerraty  * 	file containing signature
6785fff9558SSimon J. Gerraty  * 	we derrive path of signed file and certificate change from
6795fff9558SSimon J. Gerraty  * 	this.
6805fff9558SSimon J. Gerraty  *
6815fff9558SSimon J. Gerraty  * @param[in] flags
6825fff9558SSimon J. Gerraty  * 	only bit 1 significant so far
6835fff9558SSimon J. Gerraty  *
6845fff9558SSimon J. Gerraty  * @return NULL on error otherwise content of signed file
6855fff9558SSimon J. Gerraty  */
6865fff9558SSimon J. Gerraty unsigned char *
6875fff9558SSimon J. Gerraty verify_sig(const char *sigfile, int flags)
6885fff9558SSimon J. Gerraty {
6895fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
6905fff9558SSimon J. Gerraty 	br_name_element cn;
6915fff9558SSimon J. Gerraty 	char cn_buf[80];
6925fff9558SSimon J. Gerraty 	unsigned char cn_oid[4];
6935fff9558SSimon J. Gerraty 	char pbuf[MAXPATHLEN];
6945fff9558SSimon J. Gerraty 	char *cp;
6955fff9558SSimon J. Gerraty 	unsigned char *ucp;
6965fff9558SSimon J. Gerraty 	size_t n;
6975fff9558SSimon J. Gerraty 
6985fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile));
6995fff9558SSimon J. Gerraty 	n = strlcpy(pbuf, sigfile, sizeof(pbuf));
7005fff9558SSimon J. Gerraty 	if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0)
7015fff9558SSimon J. Gerraty 		return (NULL);
7025fff9558SSimon J. Gerraty 	cp = strcpy(&pbuf[n - 3], "certs");
7035fff9558SSimon J. Gerraty 	/*
7045fff9558SSimon J. Gerraty 	 * We want the commonName field
7055fff9558SSimon J. Gerraty 	 * the OID we want is 2,5,4,3 - but DER encoded
7065fff9558SSimon J. Gerraty 	 */
7075fff9558SSimon J. Gerraty 	cn_oid[0] = 3;
7085fff9558SSimon J. Gerraty 	cn_oid[1] = 0x55;
7095fff9558SSimon J. Gerraty 	cn_oid[2] = 4;
7105fff9558SSimon J. Gerraty 	cn_oid[3] = 3;
7115fff9558SSimon J. Gerraty 	cn.oid = cn_oid;
7125fff9558SSimon J. Gerraty 	cn.buf = cn_buf;
7135fff9558SSimon J. Gerraty 	cn.len = sizeof(cn_buf);
7145fff9558SSimon J. Gerraty 
7155fff9558SSimon J. Gerraty 	pk = verify_signer(pbuf, &cn, 1);
7165fff9558SSimon J. Gerraty 	if (!pk) {
7175fff9558SSimon J. Gerraty 		printf("cannot verify: %s: %s\n", pbuf, ve_error_get());
7185fff9558SSimon J. Gerraty 		return (NULL);
7195fff9558SSimon J. Gerraty 	}
7205fff9558SSimon J. Gerraty 	for (; cp > pbuf; cp--) {
7215fff9558SSimon J. Gerraty 		if (*cp == '.') {
7225fff9558SSimon J. Gerraty 			*cp = '\0';
7235fff9558SSimon J. Gerraty 			break;
7245fff9558SSimon J. Gerraty 		}
7255fff9558SSimon J. Gerraty 	}
7265fff9558SSimon J. Gerraty 	switch (pk->key_type) {
7275fff9558SSimon J. Gerraty #ifdef VE_ECDSA_SUPPORT
7285fff9558SSimon J. Gerraty 	case BR_KEYTYPE_EC:
7295fff9558SSimon J. Gerraty 		ucp = verify_ec(pk, pbuf, sigfile);
7305fff9558SSimon J. Gerraty 		break;
7315fff9558SSimon J. Gerraty #endif
7325fff9558SSimon J. Gerraty #ifdef VE_RSA_SUPPORT
7335fff9558SSimon J. Gerraty 	case BR_KEYTYPE_RSA:
7345fff9558SSimon J. Gerraty 		ucp = verify_rsa(pk, pbuf, sigfile);
7355fff9558SSimon J. Gerraty 		break;
7365fff9558SSimon J. Gerraty #endif
7375fff9558SSimon J. Gerraty 	default:
7385fff9558SSimon J. Gerraty 		ucp = NULL;		/* not supported */
7395fff9558SSimon J. Gerraty 	}
7405fff9558SSimon J. Gerraty 	xfreepkey(pk);
7415fff9558SSimon J. Gerraty 	if (!ucp) {
7425fff9558SSimon J. Gerraty 		printf("Unverified %s (%s)\n", pbuf,
7435fff9558SSimon J. Gerraty 		    cn.status ? cn_buf : "unknown");
7445fff9558SSimon J. Gerraty 	} else if ((flags & 1) != 0) {
7455fff9558SSimon J. Gerraty 		printf("Verified %s signed by %s\n", pbuf,
7465fff9558SSimon J. Gerraty 		    cn.status ? cn_buf : "someone we trust");
7475fff9558SSimon J. Gerraty 	}
7485fff9558SSimon J. Gerraty 	return (ucp);
7495fff9558SSimon J. Gerraty }
7505fff9558SSimon J. Gerraty 
7515fff9558SSimon J. Gerraty 
7525fff9558SSimon J. Gerraty /**
7535fff9558SSimon J. Gerraty  * @brief verify hash matches
7545fff9558SSimon J. Gerraty  *
7555fff9558SSimon J. Gerraty  * We have finished hashing a file,
7565fff9558SSimon J. Gerraty  * see if we got the desired result.
7575fff9558SSimon J. Gerraty  *
7585fff9558SSimon J. Gerraty  * @param[in] ctx
7595fff9558SSimon J. Gerraty  *	pointer to hash context
7605fff9558SSimon J. Gerraty  *
7615fff9558SSimon J. Gerraty  * @param[in] md
7625fff9558SSimon J. Gerraty  *	pointer to hash class
7635fff9558SSimon J. Gerraty  *
7645fff9558SSimon J. Gerraty  * @param[in] path
7655fff9558SSimon J. Gerraty  *	name of the file we are checking
7665fff9558SSimon J. Gerraty  *
7675fff9558SSimon J. Gerraty  * @param[in] want
7685fff9558SSimon J. Gerraty  *	the expected result
7695fff9558SSimon J. Gerraty  *
7705fff9558SSimon J. Gerraty  * @param[in] hlen
7715fff9558SSimon J. Gerraty  *	size of hash output
7725fff9558SSimon J. Gerraty  *
7735fff9558SSimon J. Gerraty  * @return 0 on success
7745fff9558SSimon J. Gerraty  */
7755fff9558SSimon J. Gerraty int
7765fff9558SSimon J. Gerraty ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md,
7775fff9558SSimon J. Gerraty     const char *path, const char *want, size_t hlen)
7785fff9558SSimon J. Gerraty {
7795fff9558SSimon J. Gerraty 	char hexbuf[br_sha512_SIZE * 2 + 2];
7805fff9558SSimon J. Gerraty 	unsigned char hbuf[br_sha512_SIZE];
7815fff9558SSimon J. Gerraty 	char *hex;
7825fff9558SSimon J. Gerraty 	int rc;
7835fff9558SSimon J. Gerraty 	int n;
7845fff9558SSimon J. Gerraty 
7855fff9558SSimon J. Gerraty 	md->out(&ctx->vtable, hbuf);
7865fff9558SSimon J. Gerraty #ifdef VE_PCR_SUPPORT
7875fff9558SSimon J. Gerraty 	ve_pcr_update(hbuf, hlen);
7885fff9558SSimon J. Gerraty #endif
7895fff9558SSimon J. Gerraty 	hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
7905fff9558SSimon J. Gerraty 	if (!hex)
7915fff9558SSimon J. Gerraty 		return (VE_FINGERPRINT_WRONG);
7925fff9558SSimon J. Gerraty 	n = 2*hlen;
7935fff9558SSimon J. Gerraty 	if ((rc = strncmp(hex, want, n))) {
7945fff9558SSimon J. Gerraty 		ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want);
7955fff9558SSimon J. Gerraty 		rc = VE_FINGERPRINT_WRONG;
7965fff9558SSimon J. Gerraty 	}
7975fff9558SSimon J. Gerraty 	return (rc ? rc : VE_FINGERPRINT_OK);
7985fff9558SSimon J. Gerraty }
7995fff9558SSimon J. Gerraty 
8005fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR
8015fff9558SSimon J. Gerraty static int
8025fff9558SSimon J. Gerraty test_hash(const br_hash_class *md, size_t hlen,
8035fff9558SSimon J. Gerraty     const char *hname, const char *s, size_t slen, const char *want)
8045fff9558SSimon J. Gerraty {
8055fff9558SSimon J. Gerraty 	br_hash_compat_context mctx;
8065fff9558SSimon J. Gerraty 
8075fff9558SSimon J. Gerraty 	md->init(&mctx.vtable);
8085fff9558SSimon J. Gerraty 	md->update(&mctx.vtable, s, slen);
8095fff9558SSimon J. Gerraty 	return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK);
8105fff9558SSimon J. Gerraty }
8115fff9558SSimon J. Gerraty 
8125fff9558SSimon J. Gerraty #endif
8135fff9558SSimon J. Gerraty 
8145fff9558SSimon J. Gerraty #define ve_test_hash(n, N) \
8155fff9558SSimon J. Gerraty 	printf("Testing hash: " #n "\t\t\t\t%s\n", \
8165fff9558SSimon J. Gerraty 	    test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \
8175fff9558SSimon J. Gerraty 	    VE_HASH_KAT_STR, sizeof(VE_HASH_KAT_STR), \
8185fff9558SSimon J. Gerraty 	    vh_ ## N) ? "Failed" : "Passed")
8195fff9558SSimon J. Gerraty 
8205fff9558SSimon J. Gerraty /**
8215fff9558SSimon J. Gerraty  * @brief
8225fff9558SSimon J. Gerraty  * run self tests on hash and signature verification
8235fff9558SSimon J. Gerraty  *
8245fff9558SSimon J. Gerraty  * Test that the hash methods (SHA1 and SHA256) work.
8255fff9558SSimon J. Gerraty  * Test that we can verify a certificate for each supported
8265fff9558SSimon J. Gerraty  * Root CA.
8275fff9558SSimon J. Gerraty  *
8285fff9558SSimon J. Gerraty  * @return cached result.
8295fff9558SSimon J. Gerraty  */
8305fff9558SSimon J. Gerraty int
8315fff9558SSimon J. Gerraty ve_self_tests(void)
8325fff9558SSimon J. Gerraty {
8335fff9558SSimon J. Gerraty 	static int once = -1;
8345fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR
8355fff9558SSimon J. Gerraty 	br_x509_certificate *xcs;
8365fff9558SSimon J. Gerraty 	br_x509_pkey *pk;
8375fff9558SSimon J. Gerraty 	br_name_element cn;
8385fff9558SSimon J. Gerraty 	char cn_buf[80];
8395fff9558SSimon J. Gerraty 	unsigned char cn_oid[4];
8405fff9558SSimon J. Gerraty 	size_t num;
8415fff9558SSimon J. Gerraty 	size_t u;
8425fff9558SSimon J. Gerraty #endif
8435fff9558SSimon J. Gerraty 
8445fff9558SSimon J. Gerraty 	if (once >= 0)
8455fff9558SSimon J. Gerraty 		return (once);
8465fff9558SSimon J. Gerraty 	once = 0;
8475fff9558SSimon J. Gerraty 
8485fff9558SSimon J. Gerraty 	DEBUG_PRINTF(5, ("Self tests...\n"));
8495fff9558SSimon J. Gerraty #ifdef VE_HASH_KAT_STR
8505fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT
8515fff9558SSimon J. Gerraty 	ve_test_hash(sha1, SHA1);
8525fff9558SSimon J. Gerraty #endif
8535fff9558SSimon J. Gerraty #ifdef VE_SHA256_SUPPORT
8545fff9558SSimon J. Gerraty 	ve_test_hash(sha256, SHA256);
8555fff9558SSimon J. Gerraty #endif
8565fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT
8575fff9558SSimon J. Gerraty 	ve_test_hash(sha384, SHA384);
8585fff9558SSimon J. Gerraty #endif
8595fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT
8605fff9558SSimon J. Gerraty 	ve_test_hash(sha512, SHA512);
8615fff9558SSimon J. Gerraty #endif
8625fff9558SSimon J. Gerraty #endif
8635fff9558SSimon J. Gerraty #ifdef VERIFY_CERTS_STR
8645fff9558SSimon J. Gerraty 	xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
8655fff9558SSimon J. Gerraty 	    sizeof(VERIFY_CERTS_STR), &num);
8665fff9558SSimon J. Gerraty 	if (xcs == NULL)
8675fff9558SSimon J. Gerraty 		return (0);
8685fff9558SSimon J. Gerraty 	/*
8695fff9558SSimon J. Gerraty 	 * We want the commonName field
8705fff9558SSimon J. Gerraty 	 * the OID we want is 2,5,4,3 - but DER encoded
8715fff9558SSimon J. Gerraty 	 */
8725fff9558SSimon J. Gerraty 	cn_oid[0] = 3;
8735fff9558SSimon J. Gerraty 	cn_oid[1] = 0x55;
8745fff9558SSimon J. Gerraty 	cn_oid[2] = 4;
8755fff9558SSimon J. Gerraty 	cn_oid[3] = 3;
8765fff9558SSimon J. Gerraty 	cn.oid = cn_oid;
8775fff9558SSimon J. Gerraty 	cn.buf = cn_buf;
8785fff9558SSimon J. Gerraty 
8795fff9558SSimon J. Gerraty 	for (u = 0; u < num; u ++) {
8805fff9558SSimon J. Gerraty 		cn.len = sizeof(cn_buf);
881*13ea0450SMarcin Wojtas 		if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
882*13ea0450SMarcin Wojtas 			free_cert_contents(&xcs[u]);
8835fff9558SSimon J. Gerraty 			once++;
8845fff9558SSimon J. Gerraty 			printf("Testing verify certificate: %s\tPassed\n",
8855fff9558SSimon J. Gerraty 			    cn.status ? cn_buf : "");
8865fff9558SSimon J. Gerraty 			xfreepkey(pk);
8875fff9558SSimon J. Gerraty 		}
8885fff9558SSimon J. Gerraty 	}
8895fff9558SSimon J. Gerraty 	if (!once)
8905fff9558SSimon J. Gerraty 		printf("Testing verify certificate:\t\t\tFailed\n");
8915fff9558SSimon J. Gerraty 	xfree(xcs);
8925fff9558SSimon J. Gerraty #else
8935fff9558SSimon J. Gerraty 	printf("No X.509 self tests\n");
8945fff9558SSimon J. Gerraty #endif	/* VERIFY_CERTS_STR */
8955fff9558SSimon J. Gerraty #ifdef VE_OPENPGP_SUPPORT
8965fff9558SSimon J. Gerraty 	if (!openpgp_self_tests())
8975fff9558SSimon J. Gerraty 		once++;
8985fff9558SSimon J. Gerraty #endif
8995fff9558SSimon J. Gerraty 	return (once);
9005fff9558SSimon J. Gerraty }
901