xref: /freebsd/lib/libsecureboot/vets.c (revision 8881d206f4e68b564c2c5f50fc717086fc3e827a)
1 /*-
2  * Copyright (c) 2017-2018, Juniper Networks, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include <sys/cdefs.h>
26 __FBSDID("$FreeBSD$");
27 
28 /**
29  * @file vets.c - trust store
30  * @brief verify signatures
31  *
32  * We leverage code from BearSSL www.bearssl.org
33  */
34 
35 #include <sys/time.h>
36 #include <stdarg.h>
37 #define NEED_BRSSL_H
38 #include "libsecureboot-priv.h"
39 #include <brssl.h>
40 #include <ta.h>
41 
42 #ifndef TRUST_ANCHOR_STR
43 # define TRUST_ANCHOR_STR ta_PEM
44 #endif
45 
46 #define SECONDS_PER_DAY		86400
47 #define SECONDS_PER_YEAR	365 * SECONDS_PER_DAY
48 #ifndef VE_UTC_MAX_JUMP
49 # define VE_UTC_MAX_JUMP	20 * SECONDS_PER_YEAR
50 #endif
51 #define X509_DAYS_TO_UTC0	719528
52 
53 int DebugVe = 0;
54 
55 typedef VECTOR(br_x509_certificate) cert_list;
56 typedef VECTOR(hash_data) digest_list;
57 
58 static anchor_list trust_anchors = VEC_INIT;
59 static anchor_list forbidden_anchors = VEC_INIT;
60 static digest_list forbidden_digests = VEC_INIT;
61 
62 static int anchor_verbose = 0;
63 
64 void
65 ve_anchor_verbose_set(int n)
66 {
67 	anchor_verbose = n;
68 }
69 
70 int
71 ve_anchor_verbose_get(void)
72 {
73 	return (anchor_verbose);
74 }
75 
76 void
77 ve_debug_set(int n)
78 {
79 	DebugVe = n;
80 }
81 
82 static char ebuf[512];
83 
84 char *
85 ve_error_get(void)
86 {
87 	return (ebuf);
88 }
89 
90 int
91 ve_error_set(const char *fmt, ...)
92 {
93 	int rc;
94 	va_list ap;
95 
96 	va_start(ap, fmt);
97 	ebuf[0] = '\0';
98 	rc = 0;
99 	if (fmt) {
100 #ifdef STAND_H
101 		vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */
102 		ebuf[sizeof(ebuf) - 1] = '\0';
103 		rc = strlen(ebuf);
104 #else
105 		rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap);
106 #endif
107 	}
108 	va_end(ap);
109 	return (rc);
110 }
111 
112 /* this is the time we use for verifying certs */
113 static time_t ve_utc = 0;
114 
115 /**
116  * @brief
117  * set ve_utc used for certificate verification
118  *
119  * @param[in] utc
120  *	time - ignored unless greater than current value
121  *	and not a leap of 20 years or more.
122  */
123 void
124 ve_utc_set(time_t utc)
125 {
126 	if (utc > ve_utc &&
127 	    (ve_utc == 0 || (utc - ve_utc) < VE_UTC_MAX_JUMP)) {
128 		DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc));
129 		ve_utc = utc;
130 	}
131 }
132 
133 static void
134 free_cert_contents(br_x509_certificate *xc)
135 {
136 	xfree(xc->data);
137 }
138 
139 /*
140  * a bit of a dance to get commonName from a certificate
141  */
142 static char *
143 x509_cn_get(br_x509_certificate *xc, char *buf, size_t len)
144 {
145 	br_x509_minimal_context mc;
146 	br_name_element cn;
147 	unsigned char cn_oid[4];
148 	int err;
149 
150 	if (buf == NULL)
151 		return (buf);
152 	/*
153 	 * We want the commonName field
154 	 * the OID we want is 2,5,4,3 - but DER encoded
155 	 */
156 	cn_oid[0] = 3;
157 	cn_oid[1] = 0x55;
158 	cn_oid[2] = 4;
159 	cn_oid[3] = 3;
160 	cn.oid = cn_oid;
161 	cn.buf = buf;
162 	cn.len = len;
163 	cn.buf[0] = '\0';
164 
165 	br_x509_minimal_init(&mc, &br_sha256_vtable, NULL, 0);
166 	br_x509_minimal_set_name_elements(&mc, &cn, 1);
167 	/* the below actually does the work - updates cn.status */
168 	mc.vtable->start_chain(&mc.vtable, NULL);
169 	mc.vtable->start_cert(&mc.vtable, xc->data_len);
170 	mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
171 	mc.vtable->end_cert(&mc.vtable);
172 	/* we don' actually care about cert status - just its name */
173 	err = mc.vtable->end_chain(&mc.vtable);
174 
175 	if (!cn.status)
176 		buf = NULL;
177 	return (buf);
178 }
179 
180 /* ASN parsing related defines */
181 #define ASN1_PRIMITIVE_TAG 0x1F
182 #define ASN1_INF_LENGTH    0x80
183 #define ASN1_LENGTH_MASK   0x7F
184 
185 /*
186  * Get TBS part of certificate.
187  * Since BearSSL doesn't provide any API to do this,
188  * it has to be implemented here.
189  */
190 static void*
191 X509_to_tbs(unsigned char* cert, size_t* output_size)
192 {
193 	unsigned char *result;
194 	size_t tbs_size;
195 	int size, i;
196 
197 	if (cert == NULL)
198 		return (NULL);
199 
200 	/* Strip two sequences to get to the TBS section */
201 	for (i = 0; i < 2; i++) {
202 		/*
203 		 * XXX: We don't need to support extended tags since
204 		 * they should not be present in certificates.
205 		 */
206 		if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG)
207 			return (NULL);
208 
209 		cert++;
210 
211 		if (*cert == ASN1_INF_LENGTH)
212 			return (NULL);
213 
214 		size = *cert & ASN1_LENGTH_MASK;
215 		tbs_size = 0;
216 
217 		/* Size can either be stored on a single or multiple bytes */
218 		if (*cert & (ASN1_LENGTH_MASK + 1)) {
219 			cert++;
220 			while (*cert == 0 && size > 0) {
221 				cert++;
222 				size--;
223 			}
224 			while (size-- > 0) {
225 				tbs_size <<= 8;
226 				tbs_size |= *(cert++);
227 			}
228 		}
229 		if (i == 0)
230 			result = cert;
231 	}
232 	tbs_size += (cert - result);
233 
234 	if (output_size != NULL)
235 		*output_size = tbs_size;
236 
237 	return (result);
238 }
239 
240 void
241 ve_forbidden_digest_add(hash_data *digest, size_t num)
242 {
243 	while (num--)
244 		VEC_ADD(forbidden_digests, digest[num]);
245 }
246 
247 static size_t
248 ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors,
249     const char *anchors_name)
250 {
251 	br_x509_trust_anchor ta;
252 	size_t u;
253 
254 	for (u = 0; u < num; u++) {
255 		if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
256 			break;
257 		}
258 		VEC_ADD(*anchors, ta);
259 		if (anchor_verbose && anchors_name) {
260 			char buf[64];
261 			char *cp;
262 
263 			cp = x509_cn_get(&xcs[u], buf, sizeof(buf));
264 			if (cp) {
265 				printf("x509_anchor(%s) %s\n", cp, anchors_name);
266 			}
267 		}
268 	}
269 	return (u);
270 }
271 
272 /**
273  * @brief
274  * add certs to our trust store
275  */
276 size_t
277 ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
278 {
279 	return (ve_anchors_add(xcs, num, &trust_anchors, "trusted"));
280 }
281 
282 size_t
283 ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num)
284 {
285 	return (ve_anchors_add(xcs, num, &forbidden_anchors, "forbidden"));
286 }
287 
288 
289 /**
290  * @brief add trust anchors in buf
291  *
292  * Assume buf contains x509 certificates, but if not and
293  * we support OpenPGP try adding as that.
294  *
295  * @return number of anchors added
296  */
297 size_t
298 ve_trust_anchors_add_buf(unsigned char *buf, size_t len)
299 {
300 	br_x509_certificate *xcs;
301 	size_t num;
302 
303 	num = 0;
304 	xcs = parse_certificates(buf, len, &num);
305 	if (xcs != NULL) {
306 		num = ve_trust_anchors_add(xcs, num);
307 #ifdef VE_OPENPGP_SUPPORT
308 	} else {
309 		num = openpgp_trust_add_buf(buf, len);
310 #endif
311 	}
312 	return (num);
313 }
314 
315 /**
316  * @brief revoke trust anchors in buf
317  *
318  * Assume buf contains x509 certificates, but if not and
319  * we support OpenPGP try revoking keyId
320  *
321  * @return number of anchors revoked
322  */
323 size_t
324 ve_trust_anchors_revoke(unsigned char *buf, size_t len)
325 {
326 	br_x509_certificate *xcs;
327 	size_t num;
328 
329 	num = 0;
330 	xcs = parse_certificates(buf, len, &num);
331 	if (xcs != NULL) {
332 		num = ve_forbidden_anchors_add(xcs, num);
333 #ifdef VE_OPENPGP_SUPPORT
334 	} else {
335 		if (buf[len - 1] == '\n')
336 			buf[len - 1] = '\0';
337 		num = openpgp_trust_revoke((char *)buf);
338 #endif
339 	}
340 	return (num);
341 }
342 
343 /**
344  * @brief
345  * initialize our trust_anchors from ta_PEM
346  */
347 int
348 ve_trust_init(void)
349 {
350 	static int once = -1;
351 
352 	if (once >= 0)
353 		return (once);
354 	once = 0;			/* to be sure */
355 #ifdef BUILD_UTC
356 	ve_utc_set(BUILD_UTC);		/* ensure sanity */
357 #endif
358 	ve_utc_set(time(NULL));
359 	ve_error_set(NULL);		/* make sure it is empty */
360 #ifdef VE_PCR_SUPPORT
361 	ve_pcr_init();
362 #endif
363 
364 #ifdef TRUST_ANCHOR_STR
365 	ve_trust_anchors_add_buf(__DECONST(unsigned char *, TRUST_ANCHOR_STR),
366 	    sizeof(TRUST_ANCHOR_STR));
367 #endif
368 	once = (int) VEC_LEN(trust_anchors);
369 #ifdef VE_OPENPGP_SUPPORT
370 	once += openpgp_trust_init();
371 #endif
372 	return (once);
373 }
374 
375 /**
376  * if we can verify the certificate chain in "certs",
377  * return the public key and if "xcp" is !NULL the associated
378  * certificate
379  */
380 static br_x509_pkey *
381 verify_signer_xcs(br_x509_certificate *xcs,
382     size_t num,
383     br_name_element *elts, size_t num_elts,
384     anchor_list *anchors)
385 {
386 	br_x509_minimal_context mc;
387 	br_x509_certificate *xc;
388 	size_t u;
389 	cert_list chain = VEC_INIT;
390 	const br_x509_pkey *tpk;
391 	br_x509_pkey *pk;
392 	unsigned int usages;
393 	int err;
394 
395 	DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num));
396 	VEC_ADDMANY(chain, xcs, num);
397 	if (VEC_LEN(chain) == 0) {
398 		ve_error_set("ERROR: no/invalid certificate chain\n");
399 		return (NULL);
400 	}
401 
402 	DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n",
403 		VEC_LEN(*anchors)));
404 
405 	br_x509_minimal_init(&mc, &br_sha256_vtable,
406 	    &VEC_ELT(*anchors, 0),
407 	    VEC_LEN(*anchors));
408 #ifdef VE_ECDSA_SUPPORT
409 	br_x509_minimal_set_ecdsa(&mc,
410 	    &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
411 #endif
412 #ifdef VE_RSA_SUPPORT
413 	br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
414 #endif
415 #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
416 	/* This is deprecated! do not enable unless you absoultely have to */
417 	br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable);
418 #endif
419 	br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable);
420 #ifdef VE_SHA384_SUPPORT
421 	br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable);
422 #endif
423 #ifdef VE_SHA512_SUPPORT
424 	br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable);
425 #endif
426 	br_x509_minimal_set_name_elements(&mc, elts, num_elts);
427 
428 #ifdef _STANDALONE
429 	/*
430 	 * Clock is probably bogus so we use ve_utc.
431 	 */
432 	mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0;
433 	mc.seconds = (ve_utc % SECONDS_PER_DAY);
434 #endif
435 
436 	mc.vtable->start_chain(&mc.vtable, NULL);
437 	for (u = 0; u < VEC_LEN(chain); u ++) {
438 		xc = &VEC_ELT(chain, u);
439 		mc.vtable->start_cert(&mc.vtable, xc->data_len);
440 		mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
441 		mc.vtable->end_cert(&mc.vtable);
442 		switch (mc.err) {
443 		case 0:
444 		case BR_ERR_X509_OK:
445 		case BR_ERR_X509_EXPIRED:
446 			break;
447 		default:
448 			printf("u=%zu mc.err=%d\n", u, mc.err);
449 			break;
450 		}
451 	}
452 	err = mc.vtable->end_chain(&mc.vtable);
453 	pk = NULL;
454 	if (err) {
455 		ve_error_set("Validation failed, err = %d", err);
456 	} else {
457 		tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
458 		if (tpk != NULL) {
459 			pk = xpkeydup(tpk);
460 		}
461 	}
462 	VEC_CLEAR(chain);
463 	return (pk);
464 }
465 
466 /*
467  * Check if digest of one of the certificates from verified chain
468  * is present in the forbidden database.
469  * Since UEFI allows to store three types of digests
470  * all of them have to be checked separately.
471  */
472 static int
473 check_forbidden_digests(br_x509_certificate *xcs, size_t num)
474 {
475 	unsigned char sha256_digest[br_sha256_SIZE];
476 	unsigned char sha384_digest[br_sha384_SIZE];
477 	unsigned char sha512_digest[br_sha512_SIZE];
478 	void *tbs;
479 	hash_data *digest;
480 	br_hash_compat_context ctx;
481 	const br_hash_class *md;
482 	size_t tbs_len, i;
483 	int have_sha256, have_sha384, have_sha512;
484 
485 	if (VEC_LEN(forbidden_digests) == 0)
486 		return (0);
487 
488 	/*
489 	 * Iterate through certificates, extract their To-Be-Signed section,
490 	 * and compare its digest against the ones in the forbidden database.
491 	 */
492 	while (num--) {
493 		tbs = X509_to_tbs(xcs[num].data, &tbs_len);
494 		if (tbs == NULL) {
495 			printf("Failed to obtain TBS part of certificate\n");
496 			return (1);
497 		}
498 		have_sha256 = have_sha384 = have_sha512 = 0;
499 
500 		for (i = 0; i < VEC_LEN(forbidden_digests); i++) {
501 			digest = &VEC_ELT(forbidden_digests, i);
502 			switch (digest->hash_size) {
503 			case br_sha256_SIZE:
504 				if (!have_sha256) {
505 					have_sha256 = 1;
506 					md = &br_sha256_vtable;
507 					md->init(&ctx.vtable);
508 					md->update(&ctx.vtable, tbs, tbs_len);
509 					md->out(&ctx.vtable, sha256_digest);
510 				}
511 				if (!memcmp(sha256_digest,
512 					digest->data,
513 					br_sha256_SIZE))
514 					return (1);
515 
516 				break;
517 			case br_sha384_SIZE:
518 				if (!have_sha384) {
519 					have_sha384 = 1;
520 					md = &br_sha384_vtable;
521 					md->init(&ctx.vtable);
522 					md->update(&ctx.vtable, tbs, tbs_len);
523 					md->out(&ctx.vtable, sha384_digest);
524 				}
525 				if (!memcmp(sha384_digest,
526 					digest->data,
527 					br_sha384_SIZE))
528 					return (1);
529 
530 				break;
531 			case br_sha512_SIZE:
532 				if (!have_sha512) {
533 					have_sha512 = 1;
534 					md = &br_sha512_vtable;
535 					md->init(&ctx.vtable);
536 					md->update(&ctx.vtable, tbs, tbs_len);
537 					md->out(&ctx.vtable, sha512_digest);
538 				}
539 				if (!memcmp(sha512_digest,
540 					digest->data,
541 					br_sha512_SIZE))
542 					return (1);
543 
544 				break;
545 			}
546 		}
547 	}
548 
549 	return (0);
550 }
551 
552 static br_x509_pkey *
553 verify_signer(const char *certs,
554     br_name_element *elts, size_t num_elts)
555 {
556 	br_x509_certificate *xcs;
557 	br_x509_pkey *pk;
558 	size_t num;
559 
560 	pk = NULL;
561 
562 	ve_trust_init();
563 	xcs = read_certificates(certs, &num);
564 	if (xcs == NULL) {
565 		ve_error_set("cannot read certificates\n");
566 		return (NULL);
567 	}
568 
569 	/*
570 	 * Check if either
571 	 * 1. There is a direct match between cert from forbidden_anchors
572 	 * and a cert from chain.
573 	 * 2. CA that signed the chain is found in forbidden_anchors.
574 	 */
575 	if (VEC_LEN(forbidden_anchors) > 0)
576 		pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors);
577 	if (pk != NULL) {
578 		ve_error_set("Certificate is on forbidden list\n");
579 		xfreepkey(pk);
580 		pk = NULL;
581 		goto out;
582 	}
583 
584 	pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors);
585 	if (pk == NULL)
586 		goto out;
587 
588 	/*
589 	 * Check if hash of tbs part of any certificate in chain
590 	 * is on the forbidden list.
591 	 */
592 	if (check_forbidden_digests(xcs, num)) {
593 		ve_error_set("Certificate hash is on forbidden list\n");
594 		xfreepkey(pk);
595 		pk = NULL;
596 	}
597 out:
598 	free_certificates(xcs, num);
599 	return (pk);
600 }
601 
602 /**
603  * we need a hex digest including trailing newline below
604  */
605 char *
606 hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len)
607 {
608 	char const hex2ascii[] = "0123456789abcdef";
609 	size_t i;
610 
611 	/* every binary byte is 2 chars in hex + newline + null  */
612 	if (bufsz < (2 * foo_len) + 2)
613 		return (NULL);
614 
615 	for (i = 0; i < foo_len; i++) {
616 		buf[i * 2] = hex2ascii[foo[i] >> 4];
617 		buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f];
618 	}
619 
620 	buf[i * 2] = 0x0A; /* we also want a newline */
621 	buf[i * 2 + 1] = '\0';
622 
623 	return (buf);
624 }
625 
626 /**
627  * @brief
628  * verify file against sigfile using pk
629  *
630  * When we generated the signature in sigfile,
631  * we hashed (sha256) file, and sent that to signing server
632  * which hashed (sha256) that hash.
633  *
634  * To verify we need to replicate that result.
635  *
636  * @param[in] pk
637  *	br_x509_pkey
638  *
639  * @paramp[in] file
640  *	file to be verified
641  *
642  * @param[in] sigfile
643  * 	signature (PEM encoded)
644  *
645  * @return NULL on error, otherwise content of file.
646  */
647 #ifdef VE_ECDSA_SUPPORT
648 static unsigned char *
649 verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile)
650 {
651 #ifdef VE_ECDSA_HASH_AGAIN
652 	char *hex, hexbuf[br_sha512_SIZE * 2 + 2];
653 #endif
654 	unsigned char rhbuf[br_sha512_SIZE];
655 	br_sha256_context ctx;
656 	unsigned char *fcp, *scp;
657 	size_t flen, slen, plen;
658 	pem_object *po;
659 	const br_ec_impl *ec;
660 	br_ecdsa_vrfy vrfy;
661 
662 	if ((fcp = read_file(file, &flen)) == NULL)
663 		return (NULL);
664 	if ((scp = read_file(sigfile, &slen)) == NULL) {
665 		free(fcp);
666 		return (NULL);
667 	}
668 	if ((po = decode_pem(scp, slen, &plen)) == NULL) {
669 		free(fcp);
670 		free(scp);
671 		return (NULL);
672 	}
673 	br_sha256_init(&ctx);
674 	br_sha256_update(&ctx, fcp, flen);
675 	br_sha256_out(&ctx, rhbuf);
676 #ifdef VE_ECDSA_HASH_AGAIN
677 	hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE);
678 	/* now hash that */
679 	if (hex) {
680 		br_sha256_init(&ctx);
681 		br_sha256_update(&ctx, hex, strlen(hex));
682 		br_sha256_out(&ctx, rhbuf);
683 	}
684 #endif
685 	ec = br_ec_get_default();
686 	vrfy = br_ecdsa_vrfy_asn1_get_default();
687 	if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data,
688 		po->data_len)) {
689 		free(fcp);
690 		fcp = NULL;
691 	}
692 	free(scp);
693 	return (fcp);
694 }
695 #endif
696 
697 #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT)
698 /**
699  * @brief verify an rsa digest
700  *
701  * @return 0 on failure
702  */
703 int
704 verify_rsa_digest (br_rsa_public_key *pkey,
705     const unsigned char *hash_oid,
706     unsigned char *mdata, size_t mlen,
707     unsigned char *sdata, size_t slen)
708 {
709 	br_rsa_pkcs1_vrfy vrfy;
710 	unsigned char vhbuf[br_sha512_SIZE];
711 
712 	vrfy = br_rsa_pkcs1_vrfy_get_default();
713 
714 	if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) ||
715 	    memcmp(vhbuf, mdata, mlen) != 0) {
716 		return (0);		/* fail */
717 	}
718 	return (1);			/* ok */
719 }
720 #endif
721 
722 /**
723  * @brief
724  * verify file against sigfile using pk
725  *
726  * When we generated the signature in sigfile,
727  * we hashed (sha256) file, and sent that to signing server
728  * which hashed (sha256) that hash.
729  *
730  * Or (deprecated) we simply used sha1 hash directly.
731  *
732  * To verify we need to replicate that result.
733  *
734  * @param[in] pk
735  *	br_x509_pkey
736  *
737  * @paramp[in] file
738  *	file to be verified
739  *
740  * @param[in] sigfile
741  * 	signature (PEM encoded)
742  *
743  * @return NULL on error, otherwise content of file.
744  */
745 #ifdef VE_RSA_SUPPORT
746 static unsigned char *
747 verify_rsa(br_x509_pkey *pk,  const char *file, const char *sigfile)
748 {
749 	unsigned char rhbuf[br_sha512_SIZE];
750 	const unsigned char *hash_oid;
751 	const br_hash_class *md;
752 	br_hash_compat_context mctx;
753 	unsigned char *fcp, *scp;
754 	size_t flen, slen, plen, hlen;
755 	pem_object *po;
756 
757 	if ((fcp = read_file(file, &flen)) == NULL)
758 		return (NULL);
759 	if ((scp = read_file(sigfile, &slen)) == NULL) {
760 		free(fcp);
761 		return (NULL);
762 	}
763 	if ((po = decode_pem(scp, slen, &plen)) == NULL) {
764 		free(fcp);
765 		free(scp);
766 		return (NULL);
767 	}
768 
769 	switch (po->data_len) {
770 #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
771 	case 256:
772 		// this is our old deprecated sig method
773 		md = &br_sha1_vtable;
774 		hlen = br_sha1_SIZE;
775 		hash_oid = BR_HASH_OID_SHA1;
776 		break;
777 #endif
778 	default:
779 		md = &br_sha256_vtable;
780 		hlen = br_sha256_SIZE;
781 		hash_oid = BR_HASH_OID_SHA256;
782 		break;
783 	}
784 	md->init(&mctx.vtable);
785 	md->update(&mctx.vtable, fcp, flen);
786 	md->out(&mctx.vtable, rhbuf);
787 	if (!verify_rsa_digest(&pk->key.rsa, hash_oid,
788 		rhbuf, hlen, po->data, po->data_len)) {
789 		free(fcp);
790 		fcp = NULL;
791 	}
792 	free(scp);
793 	return (fcp);
794 }
795 #endif
796 
797 /**
798  * @brief
799  * verify a signature and return content of signed file
800  *
801  * @param[in] sigfile
802  * 	file containing signature
803  * 	we derrive path of signed file and certificate change from
804  * 	this.
805  *
806  * @param[in] flags
807  * 	only bit 1 significant so far
808  *
809  * @return NULL on error otherwise content of signed file
810  */
811 unsigned char *
812 verify_sig(const char *sigfile, int flags)
813 {
814 	br_x509_pkey *pk;
815 	br_name_element cn;
816 	char cn_buf[80];
817 	unsigned char cn_oid[4];
818 	char pbuf[MAXPATHLEN];
819 	char *cp;
820 	unsigned char *ucp;
821 	size_t n;
822 
823 	DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile));
824 	n = strlcpy(pbuf, sigfile, sizeof(pbuf));
825 	if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0)
826 		return (NULL);
827 	cp = strcpy(&pbuf[n - 3], "certs");
828 	/*
829 	 * We want the commonName field
830 	 * the OID we want is 2,5,4,3 - but DER encoded
831 	 */
832 	cn_oid[0] = 3;
833 	cn_oid[1] = 0x55;
834 	cn_oid[2] = 4;
835 	cn_oid[3] = 3;
836 	cn.oid = cn_oid;
837 	cn.buf = cn_buf;
838 	cn.len = sizeof(cn_buf);
839 
840 	pk = verify_signer(pbuf, &cn, 1);
841 	if (!pk) {
842 		printf("cannot verify: %s: %s\n", pbuf, ve_error_get());
843 		return (NULL);
844 	}
845 	for (; cp > pbuf; cp--) {
846 		if (*cp == '.') {
847 			*cp = '\0';
848 			break;
849 		}
850 	}
851 	switch (pk->key_type) {
852 #ifdef VE_ECDSA_SUPPORT
853 	case BR_KEYTYPE_EC:
854 		ucp = verify_ec(pk, pbuf, sigfile);
855 		break;
856 #endif
857 #ifdef VE_RSA_SUPPORT
858 	case BR_KEYTYPE_RSA:
859 		ucp = verify_rsa(pk, pbuf, sigfile);
860 		break;
861 #endif
862 	default:
863 		ucp = NULL;		/* not supported */
864 	}
865 	xfreepkey(pk);
866 	if (!ucp) {
867 		printf("Unverified %s (%s)\n", pbuf,
868 		    cn.status ? cn_buf : "unknown");
869 	} else if ((flags & 1) != 0) {
870 		printf("Verified %s signed by %s\n", pbuf,
871 		    cn.status ? cn_buf : "someone we trust");
872 	}
873 	return (ucp);
874 }
875 
876 
877 /**
878  * @brief verify hash matches
879  *
880  * We have finished hashing a file,
881  * see if we got the desired result.
882  *
883  * @param[in] ctx
884  *	pointer to hash context
885  *
886  * @param[in] md
887  *	pointer to hash class
888  *
889  * @param[in] path
890  *	name of the file we are checking
891  *
892  * @param[in] want
893  *	the expected result
894  *
895  * @param[in] hlen
896  *	size of hash output
897  *
898  * @return 0 on success
899  */
900 int
901 ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md,
902     const char *path, const char *want, size_t hlen)
903 {
904 	char hexbuf[br_sha512_SIZE * 2 + 2];
905 	unsigned char hbuf[br_sha512_SIZE];
906 	char *hex;
907 	int rc;
908 	int n;
909 
910 	md->out(&ctx->vtable, hbuf);
911 #ifdef VE_PCR_SUPPORT
912 	ve_pcr_update(path, hbuf, hlen);
913 #endif
914 	hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
915 	if (!hex)
916 		return (VE_FINGERPRINT_WRONG);
917 	n = 2*hlen;
918 	if ((rc = strncmp(hex, want, n))) {
919 		ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want);
920 		rc = VE_FINGERPRINT_WRONG;
921 	}
922 	return (rc ? rc : VE_FINGERPRINT_OK);
923 }
924 
925 #ifdef VE_HASH_KAT_STR
926 static int
927 test_hash(const br_hash_class *md, size_t hlen,
928     const char *hname, const char *s, size_t slen, const char *want)
929 {
930 	br_hash_compat_context mctx;
931 
932 	md->init(&mctx.vtable);
933 	md->update(&mctx.vtable, s, slen);
934 	return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK);
935 }
936 
937 #endif
938 
939 #define ve_test_hash(n, N) \
940 	printf("Testing hash: " #n "\t\t\t\t%s\n", \
941 	    test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \
942 	    VE_HASH_KAT_STR, VE_HASH_KAT_STRLEN(VE_HASH_KAT_STR), \
943 	    vh_ ## N) ? "Failed" : "Passed")
944 
945 /**
946  * @brief
947  * run self tests on hash and signature verification
948  *
949  * Test that the hash methods (SHA1 and SHA256) work.
950  * Test that we can verify a certificate for each supported
951  * Root CA.
952  *
953  * @return cached result.
954  */
955 int
956 ve_self_tests(void)
957 {
958 	static int once = -1;
959 #ifdef VERIFY_CERTS_STR
960 	br_x509_certificate *xcs;
961 	br_x509_pkey *pk;
962 	br_name_element cn;
963 	char cn_buf[80];
964 	unsigned char cn_oid[4];
965 	size_t num;
966 	size_t u;
967 #endif
968 
969 	if (once >= 0)
970 		return (once);
971 	once = 0;
972 
973 	DEBUG_PRINTF(5, ("Self tests...\n"));
974 #ifdef VE_HASH_KAT_STR
975 #ifdef VE_SHA1_SUPPORT
976 	ve_test_hash(sha1, SHA1);
977 #endif
978 #ifdef VE_SHA256_SUPPORT
979 	ve_test_hash(sha256, SHA256);
980 #endif
981 #ifdef VE_SHA384_SUPPORT
982 	ve_test_hash(sha384, SHA384);
983 #endif
984 #ifdef VE_SHA512_SUPPORT
985 	ve_test_hash(sha512, SHA512);
986 #endif
987 #endif
988 #ifdef VERIFY_CERTS_STR
989 	xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
990 	    sizeof(VERIFY_CERTS_STR), &num);
991 	if (xcs != NULL) {
992 		/*
993 		 * We want the commonName field
994 		 * the OID we want is 2,5,4,3 - but DER encoded
995 		 */
996 		cn_oid[0] = 3;
997 		cn_oid[1] = 0x55;
998 		cn_oid[2] = 4;
999 		cn_oid[3] = 3;
1000 		cn.oid = cn_oid;
1001 		cn.buf = cn_buf;
1002 
1003 		for (u = 0; u < num; u ++) {
1004 			cn.len = sizeof(cn_buf);
1005 			if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
1006 				free_cert_contents(&xcs[u]);
1007 				once++;
1008 				printf("Testing verify certificate: %s\tPassed\n",
1009 				    cn.status ? cn_buf : "");
1010 				xfreepkey(pk);
1011 			}
1012 		}
1013 		if (!once)
1014 			printf("Testing verify certificate:\t\t\tFailed\n");
1015 		xfree(xcs);
1016 	}
1017 #endif	/* VERIFY_CERTS_STR */
1018 #ifdef VE_OPENPGP_SUPPORT
1019 	if (!openpgp_self_tests())
1020 		once++;
1021 #endif
1022 	return (once);
1023 }
1024