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