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