2 * Copyright (c) 2017-2018, Juniper Networks, Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
25 #include <sys/cdefs.h>
26 __FBSDID("$FreeBSD$");
29 * @file vets.c - trust store
30 * @brief verify signatures
32 * We leverage code from BearSSL www.bearssl.org
38 #include "libsecureboot-priv.h"
42 #ifndef TRUST_ANCHOR_STR
43 # define TRUST_ANCHOR_STR ta_PEM
46 #define SECONDS_PER_DAY 86400
47 #define X509_DAYS_TO_UTC0 719528
51 typedef VECTOR(br_x509_certificate) cert_list;
52 typedef VECTOR(hash_data) digest_list;
54 static anchor_list trust_anchors = VEC_INIT;
55 static anchor_list forbidden_anchors = VEC_INIT;
56 static digest_list forbidden_digests = VEC_INIT;
58 static int anchor_verbose = 0;
61 ve_anchor_verbose_set(int n)
67 ve_anchor_verbose_get(void)
69 return (anchor_verbose);
78 static char ebuf[512];
87 ve_error_set(const char *fmt, ...)
97 vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */
98 ebuf[sizeof(ebuf) - 1] = '\0';
101 rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap);
108 /* this is the time we use for verifying certs */
109 static time_t ve_utc = 0;
113 * set ve_utc used for certificate verification
116 * time - ignored unless greater than current value.
119 ve_utc_set(time_t utc)
122 DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc));
128 free_cert_contents(br_x509_certificate *xc)
134 * a bit of a dance to get commonName from a certificate
137 x509_cn_get(br_x509_certificate *xc, char *buf, size_t len)
139 br_x509_minimal_context mc;
141 unsigned char cn_oid[4];
147 * We want the commonName field
148 * the OID we want is 2,5,4,3 - but DER encoded
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);
174 /* ASN parsing related defines */
175 #define ASN1_PRIMITIVE_TAG 0x1F
176 #define ASN1_INF_LENGTH 0x80
177 #define ASN1_LENGTH_MASK 0x7F
180 * Get TBS part of certificate.
181 * Since BearSSL doesn't provide any API to do this,
182 * it has to be implemented here.
185 X509_to_tbs(unsigned char* cert, size_t* output_size)
187 unsigned char *result;
194 /* Strip two sequences to get to the TBS section */
195 for (i = 0; i < 2; i++) {
197 * XXX: We don't need to support extended tags since
198 * they should not be present in certificates.
200 if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG)
205 if (*cert == ASN1_INF_LENGTH)
208 size = *cert & ASN1_LENGTH_MASK;
211 /* Size can either be stored on a single or multiple bytes */
212 if (*cert & (ASN1_LENGTH_MASK + 1)) {
214 while (*cert == 0 && size > 0) {
220 tbs_size |= *(cert++);
226 tbs_size += (cert - result);
228 if (output_size != NULL)
229 *output_size = tbs_size;
235 ve_forbidden_digest_add(hash_data *digest, size_t num)
238 VEC_ADD(forbidden_digests, digest[num]);
242 ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors,
243 const char *anchors_name)
245 br_x509_trust_anchor ta;
248 for (u = 0; u < num; u++) {
249 if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
252 VEC_ADD(*anchors, ta);
253 if (anchor_verbose && anchors_name) {
257 cp = x509_cn_get(&xcs[u], buf, sizeof(buf));
259 printf("x509_anchor(%s) %s\n", cp, anchors_name);
268 * add certs to our trust store
271 ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
273 return (ve_anchors_add(xcs, num, &trust_anchors, "trusted"));
277 ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num)
279 return (ve_anchors_add(xcs, num, &forbidden_anchors, "forbidden"));
284 * @brief add trust anchors in buf
286 * Assume buf contains x509 certificates, but if not and
287 * we support OpenPGP try adding as that.
289 * @return number of anchors added
292 ve_trust_anchors_add_buf(unsigned char *buf, size_t len)
294 br_x509_certificate *xcs;
298 xcs = parse_certificates(buf, len, &num);
300 num = ve_trust_anchors_add(xcs, num);
301 #ifdef VE_OPENPGP_SUPPORT
303 num = openpgp_trust_add_buf(buf, len);
310 * @brief revoke trust anchors in buf
312 * Assume buf contains x509 certificates, but if not and
313 * we support OpenPGP try revoking keyId
315 * @return number of anchors revoked
318 ve_trust_anchors_revoke(unsigned char *buf, size_t len)
320 br_x509_certificate *xcs;
324 xcs = parse_certificates(buf, len, &num);
326 num = ve_forbidden_anchors_add(xcs, num);
327 #ifdef VE_OPENPGP_SUPPORT
329 if (buf[len - 1] == '\n')
331 num = openpgp_trust_revoke((char *)buf);
339 * initialize our trust_anchors from ta_PEM
344 static int once = -1;
348 once = 0; /* to be sure */
349 ve_utc_set(time(NULL));
351 ve_utc_set(BUILD_UTC); /* just in case */
353 ve_error_set(NULL); /* make sure it is empty */
354 #ifdef VE_PCR_SUPPORT
358 #ifdef TRUST_ANCHOR_STR
359 ve_trust_anchors_add_buf(__DECONST(unsigned char *, TRUST_ANCHOR_STR),
360 sizeof(TRUST_ANCHOR_STR));
362 once = (int) VEC_LEN(trust_anchors);
363 #ifdef VE_OPENPGP_SUPPORT
364 once += openpgp_trust_init();
370 * if we can verify the certificate chain in "certs",
371 * return the public key and if "xcp" is !NULL the associated
374 static br_x509_pkey *
375 verify_signer_xcs(br_x509_certificate *xcs,
377 br_name_element *elts, size_t num_elts,
378 anchor_list *anchors)
380 br_x509_minimal_context mc;
381 br_x509_certificate *xc;
383 cert_list chain = VEC_INIT;
384 const br_x509_pkey *tpk;
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");
396 DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n",
399 br_x509_minimal_init(&mc, &br_sha256_vtable,
400 &VEC_ELT(*anchors, 0),
402 #ifdef VE_ECDSA_SUPPORT
403 br_x509_minimal_set_ecdsa(&mc,
404 &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
406 #ifdef VE_RSA_SUPPORT
407 br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
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);
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);
417 #ifdef VE_SHA512_SUPPORT
418 br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable);
420 br_x509_minimal_set_name_elements(&mc, elts, num_elts);
424 * Clock is probably bogus so we use ve_utc.
426 mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0;
427 mc.seconds = (ve_utc % SECONDS_PER_DAY);
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);
439 case BR_ERR_X509_EXPIRED:
442 printf("u=%zu mc.err=%d\n", u, mc.err);
446 err = mc.vtable->end_chain(&mc.vtable);
449 ve_error_set("Validation failed, err = %d", err);
451 tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
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.
467 check_forbidden_digests(br_x509_certificate *xcs, size_t num)
469 unsigned char sha256_digest[br_sha256_SIZE];
470 unsigned char sha384_digest[br_sha384_SIZE];
471 unsigned char sha512_digest[br_sha512_SIZE];
474 br_hash_compat_context ctx;
475 const br_hash_class *md;
477 int have_sha256, have_sha384, have_sha512;
479 if (VEC_LEN(forbidden_digests) == 0)
483 * Iterate through certificates, extract their To-Be-Signed section,
484 * and compare its digest against the ones in the forbidden database.
487 tbs = X509_to_tbs(xcs[num].data, &tbs_len);
489 printf("Failed to obtain TBS part of certificate\n");
492 have_sha256 = have_sha384 = have_sha512 = 0;
494 for (i = 0; i < VEC_LEN(forbidden_digests); i++) {
495 digest = &VEC_ELT(forbidden_digests, i);
496 switch (digest->hash_size) {
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);
505 if (!memcmp(sha256_digest,
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);
519 if (!memcmp(sha384_digest,
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);
533 if (!memcmp(sha512_digest,
546 static br_x509_pkey *
547 verify_signer(const char *certs,
548 br_name_element *elts, size_t num_elts)
550 br_x509_certificate *xcs;
557 xcs = read_certificates(certs, &num);
559 ve_error_set("cannot read certificates\n");
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.
569 if (VEC_LEN(forbidden_anchors) > 0)
570 pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors);
572 ve_error_set("Certificate is on forbidden list\n");
578 pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors);
583 * Check if hash of tbs part of any certificate in chain
584 * is on the forbidden list.
586 if (check_forbidden_digests(xcs, num)) {
587 ve_error_set("Certificate hash is on forbidden list\n");
592 free_certificates(xcs, num);
597 * we need a hex digest including trailing newline below
600 hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len)
602 char const hex2ascii[] = "0123456789abcdef";
605 /* every binary byte is 2 chars in hex + newline + null */
606 if (bufsz < (2 * foo_len) + 2)
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];
614 buf[i * 2] = 0x0A; /* we also want a newline */
615 buf[i * 2 + 1] = '\0';
622 * verify file against sigfile using pk
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.
628 * To verify we need to replicate that result.
634 * file to be verified
637 * signature (PEM encoded)
639 * @return NULL on error, otherwise content of file.
641 #ifdef VE_ECDSA_SUPPORT
642 static unsigned char *
643 verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile)
645 #ifdef VE_ECDSA_HASH_AGAIN
646 char *hex, hexbuf[br_sha512_SIZE * 2 + 2];
648 unsigned char rhbuf[br_sha512_SIZE];
649 br_sha256_context ctx;
650 unsigned char *fcp, *scp;
651 size_t flen, slen, plen;
653 const br_ec_impl *ec;
656 if ((fcp = read_file(file, &flen)) == NULL)
658 if ((scp = read_file(sigfile, &slen)) == NULL) {
662 if ((po = decode_pem(scp, slen, &plen)) == NULL) {
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);
674 br_sha256_init(&ctx);
675 br_sha256_update(&ctx, hex, strlen(hex));
676 br_sha256_out(&ctx, rhbuf);
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,
691 #if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT)
693 * @brief verify an rsa digest
695 * @return 0 on failure
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)
703 br_rsa_pkcs1_vrfy vrfy;
704 unsigned char vhbuf[br_sha512_SIZE];
706 vrfy = br_rsa_pkcs1_vrfy_get_default();
708 if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) ||
709 memcmp(vhbuf, mdata, mlen) != 0) {
710 return (0); /* fail */
718 * verify file against sigfile using pk
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.
724 * Or (deprecated) we simply used sha1 hash directly.
726 * To verify we need to replicate that result.
732 * file to be verified
735 * signature (PEM encoded)
737 * @return NULL on error, otherwise content of file.
739 #ifdef VE_RSA_SUPPORT
740 static unsigned char *
741 verify_rsa(br_x509_pkey *pk, const char *file, const char *sigfile)
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;
751 if ((fcp = read_file(file, &flen)) == NULL)
753 if ((scp = read_file(sigfile, &slen)) == NULL) {
757 if ((po = decode_pem(scp, slen, &plen)) == NULL) {
763 switch (po->data_len) {
764 #if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
766 // this is our old deprecated sig method
767 md = &br_sha1_vtable;
769 hash_oid = BR_HASH_OID_SHA1;
773 md = &br_sha256_vtable;
774 hlen = br_sha256_SIZE;
775 hash_oid = BR_HASH_OID_SHA256;
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)) {
793 * verify a signature and return content of signed file
796 * file containing signature
797 * we derrive path of signed file and certificate change from
801 * only bit 1 significant so far
803 * @return NULL on error otherwise content of signed file
806 verify_sig(const char *sigfile, int flags)
811 unsigned char cn_oid[4];
812 char pbuf[MAXPATHLEN];
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)
821 cp = strcpy(&pbuf[n - 3], "certs");
823 * We want the commonName field
824 * the OID we want is 2,5,4,3 - but DER encoded
832 cn.len = sizeof(cn_buf);
834 pk = verify_signer(pbuf, &cn, 1);
836 printf("cannot verify: %s: %s\n", pbuf, ve_error_get());
839 for (; cp > pbuf; cp--) {
845 switch (pk->key_type) {
846 #ifdef VE_ECDSA_SUPPORT
848 ucp = verify_ec(pk, pbuf, sigfile);
851 #ifdef VE_RSA_SUPPORT
853 ucp = verify_rsa(pk, pbuf, sigfile);
857 ucp = NULL; /* not supported */
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");
872 * @brief verify hash matches
874 * We have finished hashing a file,
875 * see if we got the desired result.
878 * pointer to hash context
881 * pointer to hash class
884 * name of the file we are checking
887 * the expected result
890 * size of hash output
892 * @return 0 on success
895 ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md,
896 const char *path, const char *want, size_t hlen)
898 char hexbuf[br_sha512_SIZE * 2 + 2];
899 unsigned char hbuf[br_sha512_SIZE];
904 md->out(&ctx->vtable, hbuf);
905 #ifdef VE_PCR_SUPPORT
906 ve_pcr_update(hbuf, hlen);
908 hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
910 return (VE_FINGERPRINT_WRONG);
912 if ((rc = strncmp(hex, want, n))) {
913 ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want);
914 rc = VE_FINGERPRINT_WRONG;
916 return (rc ? rc : VE_FINGERPRINT_OK);
919 #ifdef VE_HASH_KAT_STR
921 test_hash(const br_hash_class *md, size_t hlen,
922 const char *hname, const char *s, size_t slen, const char *want)
924 br_hash_compat_context mctx;
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);
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")
941 * run self tests on hash and signature verification
943 * Test that the hash methods (SHA1 and SHA256) work.
944 * Test that we can verify a certificate for each supported
947 * @return cached result.
952 static int once = -1;
953 #ifdef VERIFY_CERTS_STR
954 br_x509_certificate *xcs;
958 unsigned char cn_oid[4];
967 DEBUG_PRINTF(5, ("Self tests...\n"));
968 #ifdef VE_HASH_KAT_STR
969 #ifdef VE_SHA1_SUPPORT
970 ve_test_hash(sha1, SHA1);
972 #ifdef VE_SHA256_SUPPORT
973 ve_test_hash(sha256, SHA256);
975 #ifdef VE_SHA384_SUPPORT
976 ve_test_hash(sha384, SHA384);
978 #ifdef VE_SHA512_SUPPORT
979 ve_test_hash(sha512, SHA512);
982 #ifdef VERIFY_CERTS_STR
983 xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
984 sizeof(VERIFY_CERTS_STR), &num);
987 * We want the commonName field
988 * the OID we want is 2,5,4,3 - but DER encoded
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]);
1002 printf("Testing verify certificate: %s\tPassed\n",
1003 cn.status ? cn_buf : "");
1008 printf("Testing verify certificate:\t\t\tFailed\n");
1011 #endif /* VERIFY_CERTS_STR */
1012 #ifdef VE_OPENPGP_SUPPORT
1013 if (!openpgp_self_tests())