libsecureboot: make it easier to customize trust anchors
Avoid making hash self-tests depend on X.509 certs. Include OpenPGP keys in trust store count. Reviewed by: stevek MFC after: 1 week Sponsored by: Juniper Networks Differential Revision: https://reviews.freebsd.org/D20208
This commit is contained in:
parent
b5a154d8e3
commit
9bee6a6083
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=347408
@ -98,10 +98,20 @@ CFLAGS+= ${VE_HASH_LIST:@H@-DVE_$H_SUPPORT@} \
|
|||||||
|
|
||||||
.if ${VE_SELF_TESTS} != "no"
|
.if ${VE_SELF_TESTS} != "no"
|
||||||
# The input used for hash KATs
|
# The input used for hash KATs
|
||||||
|
# we use a string by default so it is independent of any other test
|
||||||
|
VE_HASH_KAT_STRLEN?= strlen
|
||||||
|
.if ${VE_HASH_KAT_STRLEN} == "strlen"
|
||||||
|
VE_HASH_KAT_STR?= self-tests-are-good
|
||||||
|
VE_HASH_KAT_STR_INPUT= echo -n
|
||||||
|
XCFLAGS.vets+= -DVE_HASH_KAT_STR=\"${VE_HASH_KAT_STR}\"
|
||||||
|
.else
|
||||||
VE_HASH_KAT_STR?= vc_PEM
|
VE_HASH_KAT_STR?= vc_PEM
|
||||||
|
VE_HASH_KAT_STR_INPUT= cat
|
||||||
|
VE_HASH_KAT_STRLEN= sizeof
|
||||||
XCFLAGS.vets+= -DVE_HASH_KAT_STR=${VE_HASH_KAT_STR}
|
XCFLAGS.vets+= -DVE_HASH_KAT_STR=${VE_HASH_KAT_STR}
|
||||||
.endif
|
.endif
|
||||||
|
XCFLAGS.vets+= -DVE_HASH_KAT_STRLEN=${VE_HASH_KAT_STRLEN}
|
||||||
|
.endif
|
||||||
|
|
||||||
# this should be updated occassionally this is 2019-01-01Z
|
# this should be updated occassionally this is 2019-01-01Z
|
||||||
SOURCE_DATE_EPOCH?= 1546329600
|
SOURCE_DATE_EPOCH?= 1546329600
|
||||||
@ -121,17 +131,20 @@ BUILD_UTC?= ${${STAT:Ustat} -f %m ${BUILD_UTC_FILE}:L:sh}
|
|||||||
# If we are doing self-tests, we define another arrary vc_PEM
|
# If we are doing self-tests, we define another arrary vc_PEM
|
||||||
# containing certificates that we can verify for each trust anchor.
|
# containing certificates that we can verify for each trust anchor.
|
||||||
# This is typically a subordinate CA cert.
|
# This is typically a subordinate CA cert.
|
||||||
# Finally we generate a hash of vc_PEM using each supported hash method
|
# Finally we generate a hash of VE_HASH_KAT_STR
|
||||||
|
# using each supported hash method
|
||||||
# to use as a Known Answer Test (needed for FIPS 140-2)
|
# to use as a Known Answer Test (needed for FIPS 140-2)
|
||||||
#
|
#
|
||||||
|
TA_PEM_LIST ?= ${.ALLSRC:N*crl*:Mt*.pem}
|
||||||
|
VC_PEM_LIST ?= ${.ALLSRC:N*crl*:Mv*.pem}
|
||||||
vets.o vets.po vets.pico: ta.h
|
vets.o vets.po vets.pico: ta.h
|
||||||
ta.h: ${.ALLTARGETS:M[tv]*pem:O:u}
|
ta.h:
|
||||||
@( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
|
@( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
|
||||||
cat ${.ALLSRC:N*crl*:Mt*.pem} /dev/null | \
|
cat ${TA_PEM_LIST:O:u} /dev/null | \
|
||||||
file2c -sx 'static const char ta_PEM[] = {' '};'; \
|
file2c -sx 'static const char ta_PEM[] = {' '};'; \
|
||||||
echo "${.newline}${VE_HASH_LIST:@H@static char vh_$H[] = \"`cat ${.ALLSRC:N*crl*:Mv*.pem} | ${$H:U${H:tl}}`\";${.newline}@}"; ) > ${.TARGET}
|
echo "${.newline}${VE_HASH_LIST:O:u:@H@static char vh_$H[] = \"`${VE_HASH_KAT_STR_INPUT} ${VE_HASH_KAT_STR} | ${$H:U${H:tl}}`\";${.newline}@}"; ) > ${.TARGET}
|
||||||
.if ${VE_SELF_TESTS} != "no"
|
.if ${VE_SELF_TESTS} != "no"
|
||||||
( cat ${.ALLSRC:N*crl*:Mv*.pem} /dev/null | \
|
( cat ${VC_PEM_LIST:O:u} /dev/null | \
|
||||||
file2c -sx 'static const char vc_PEM[] = {' '};'; echo ) >> ${.TARGET}
|
file2c -sx 'static const char vc_PEM[] = {' '};'; echo ) >> ${.TARGET}
|
||||||
.endif
|
.endif
|
||||||
echo '#define BUILD_UTC ${BUILD_UTC}' >> ${.TARGET} ${.OODATE:MNOMETA_CMP}
|
echo '#define BUILD_UTC ${BUILD_UTC}' >> ${.TARGET} ${.OODATE:MNOMETA_CMP}
|
||||||
@ -141,7 +154,7 @@ vesigned.o vesigned.po vesigned.pico: vse.h
|
|||||||
vse.h:
|
vse.h:
|
||||||
@( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
|
@( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
|
||||||
echo "static const char *signature_exts[] = {"; \
|
echo "static const char *signature_exts[] = {"; \
|
||||||
echo '${VE_SIGNATURE_EXT_LIST:@e@"$e",${.newline}@}'; \
|
echo '${VE_SIGNATURE_EXT_LIST:O:u:@e@"$e",${.newline}@}'; \
|
||||||
echo 'NULL };' ) > ${.TARGET}
|
echo 'NULL };' ) > ${.TARGET}
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ int verify_rsa_digest(br_rsa_public_key *pkey,
|
|||||||
int is_verified(struct stat *stp);
|
int is_verified(struct stat *stp);
|
||||||
void add_verify_status(struct stat *stp, int status);
|
void add_verify_status(struct stat *stp, int status);
|
||||||
|
|
||||||
|
int openpgp_trust_init(void);
|
||||||
int openpgp_self_tests(void);
|
int openpgp_self_tests(void);
|
||||||
|
|
||||||
int efi_secure_boot_enabled(void);
|
int efi_secure_boot_enabled(void);
|
||||||
|
@ -51,7 +51,7 @@ SIGN_OPENPGP= ${PYTHON} ${SIGNER:H}/openpgp-sign.py -a -u ${OPENPGP_SIGN_URL}
|
|||||||
ta_openpgp.asc:
|
ta_openpgp.asc:
|
||||||
${SIGN_OPENPGP} -C ${.TARGET}
|
${SIGN_OPENPGP} -C ${.TARGET}
|
||||||
|
|
||||||
ta.h: ta_openpgp.asc
|
ta_asc.h: ta_openpgp.asc
|
||||||
|
|
||||||
.if ${VE_SELF_TESTS} != "no"
|
.if ${VE_SELF_TESTS} != "no"
|
||||||
# for self test
|
# for self test
|
||||||
@ -59,7 +59,7 @@ vc_openpgp.asc: ta_openpgp.asc
|
|||||||
${SIGN_OPENPGP} ${.ALLSRC:M*.asc}
|
${SIGN_OPENPGP} ${.ALLSRC:M*.asc}
|
||||||
mv ta_openpgp.asc.asc ${.TARGET}
|
mv ta_openpgp.asc.asc ${.TARGET}
|
||||||
|
|
||||||
ta.h: vc_openpgp.asc
|
ta_asc.h: vc_openpgp.asc
|
||||||
.endif
|
.endif
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
@ -72,17 +72,20 @@ ecerts.pem:
|
|||||||
.if ${VE_SIGNATURE_LIST:tu:MECDSA} != ""
|
.if ${VE_SIGNATURE_LIST:tu:MECDSA} != ""
|
||||||
# the last cert in the chain is the one we want
|
# the last cert in the chain is the one we want
|
||||||
ta_ec.pem: ecerts.pem _LAST_PEM_USE
|
ta_ec.pem: ecerts.pem _LAST_PEM_USE
|
||||||
|
ta.h: ta_ec.pem
|
||||||
.if ${VE_SELF_TESTS} != "no"
|
.if ${VE_SELF_TESTS} != "no"
|
||||||
# these are for verification self test
|
# these are for verification self test
|
||||||
vc_ec.pem: ecerts.pem _2ndLAST_PEM_USE
|
vc_ec.pem: ecerts.pem _2ndLAST_PEM_USE
|
||||||
|
ta.h: vc_ec.pem
|
||||||
.endif
|
.endif
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
.if ${VE_SIGNATURE_LIST:tu:MRSA} != ""
|
.if ${VE_SIGNATURE_LIST:tu:MRSA} != ""
|
||||||
ta_rsa.pem: rcerts.pem _LAST_PEM_USE
|
ta_rsa.pem: rcerts.pem _LAST_PEM_USE
|
||||||
|
ta.h: ta_rsa.pem
|
||||||
.if ${VE_SELF_TESTS} != "no"
|
.if ${VE_SELF_TESTS} != "no"
|
||||||
vc_rsa.pem: rcerts.pem _2ndLAST_PEM_USE
|
vc_rsa.pem: rcerts.pem _2ndLAST_PEM_USE
|
||||||
|
ta.h: vc_rsa.pem
|
||||||
.endif
|
.endif
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
@ -24,25 +24,28 @@ opgp_key.o opgp_key.po opgp_key.pico: ta_asc.h
|
|||||||
# the appropriate t*.asc so that the relative order of vc_ASC
|
# the appropriate t*.asc so that the relative order of vc_ASC
|
||||||
# entries matches ta_ASC.
|
# entries matches ta_ASC.
|
||||||
#
|
#
|
||||||
ta_asc.h: ${.ALLTARGETS:M[tv]*.asc:O:u}
|
TA_ASC_LIST ?= ${.ALLSRC:Mt*.asc}
|
||||||
|
VC_ASC_LIST ?= ${.ALLSRC:Mv*.asc}
|
||||||
|
|
||||||
|
ta_asc.h:
|
||||||
.if ${VE_SIGNATURE_LIST:MOPENPGP} != ""
|
.if ${VE_SIGNATURE_LIST:MOPENPGP} != ""
|
||||||
@( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
|
@( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
|
||||||
echo "#define HAVE_TA_ASC 1"; \
|
echo "#define HAVE_TA_ASC 1"; \
|
||||||
set -- ${.ALLSRC:Mt*.asc:@f@$f ${f:T:R}@}; \
|
set -- ${TA_ASC_LIST:@f@$f ${f:T:R}@}; \
|
||||||
while test $$# -ge 2; do \
|
while test $$# -ge 2; do \
|
||||||
file2c -sx "static const char $$2[] = {" ', 0x00 };' < $$1; \
|
file2c -sx "static const char $$2[] = {" ', 0x00 };' < $$1; \
|
||||||
shift 2; \
|
shift 2; \
|
||||||
done; \
|
done; \
|
||||||
echo 'static const char *ta_ASC[] = { ${.ALLSRC:Mt*.asc:T:R:ts,}, NULL };'; \
|
echo 'static const char *ta_ASC[] = { ${TA_ASC_LIST:T:R:ts,}, NULL };'; \
|
||||||
echo; ) > ${.TARGET}
|
echo; ) > ${.TARGET}
|
||||||
.if ${VE_SELF_TESTS} != "no"
|
.if ${VE_SELF_TESTS} != "no"
|
||||||
@( echo "#define HAVE_VC_ASC 1"; \
|
@( echo "#define HAVE_VC_ASC 1"; \
|
||||||
set -- ${.ALLSRC:Mv*.asc:@f@$f ${f:T:R}@}; \
|
set -- ${VC_ASC_LIST:@f@$f ${f:T:R}@}; \
|
||||||
while test $$# -ge 2; do \
|
while test $$# -ge 2; do \
|
||||||
file2c -sx "static const char $$2[] = {" ', 0x00 };' < $$1; \
|
file2c -sx "static const char $$2[] = {" ', 0x00 };' < $$1; \
|
||||||
shift 2; \
|
shift 2; \
|
||||||
done; \
|
done; \
|
||||||
echo 'static const char *vc_ASC[] = { ${.ALLSRC:Mv*.asc:T:R:ts,}, NULL };'; \
|
echo 'static const char *vc_ASC[] = { ${VC_ASC_LIST:T:R:ts,}, NULL };'; \
|
||||||
echo; ) >> ${.TARGET}
|
echo; ) >> ${.TARGET}
|
||||||
.endif
|
.endif
|
||||||
.endif
|
.endif
|
||||||
|
@ -289,26 +289,8 @@ load_trusted_key_id(const char *keyID)
|
|||||||
OpenPGP_key *
|
OpenPGP_key *
|
||||||
load_key_id(const char *keyID)
|
load_key_id(const char *keyID)
|
||||||
{
|
{
|
||||||
static int once = 0;
|
|
||||||
OpenPGP_key *key;
|
OpenPGP_key *key;
|
||||||
|
|
||||||
if (!once) {
|
|
||||||
#ifdef HAVE_TA_ASC
|
|
||||||
const char **tp;
|
|
||||||
char *cp;
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
for (tp = ta_ASC; *tp; tp++) {
|
|
||||||
if ((cp = strdup(*tp))) {
|
|
||||||
n = strlen(cp);
|
|
||||||
key = load_key_buf((unsigned char *)cp, n);
|
|
||||||
free(cp);
|
|
||||||
openpgp_trust_add(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
once = 1;
|
|
||||||
}
|
|
||||||
key = openpgp_trust_get(keyID);
|
key = openpgp_trust_get(keyID);
|
||||||
#ifndef _STANDALONE
|
#ifndef _STANDALONE
|
||||||
if (!key)
|
if (!key)
|
||||||
@ -317,6 +299,39 @@ load_key_id(const char *keyID)
|
|||||||
return (key);
|
return (key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief initialize our internal trust store if any
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
openpgp_trust_init(void)
|
||||||
|
{
|
||||||
|
static int once = -1;
|
||||||
|
#ifdef HAVE_TA_ASC
|
||||||
|
OpenPGP_key *key;
|
||||||
|
const char **tp;
|
||||||
|
char *cp;
|
||||||
|
size_t n;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (once < 0) {
|
||||||
|
once = 0;
|
||||||
|
#ifdef HAVE_TA_ASC
|
||||||
|
for (tp = ta_ASC; *tp; tp++) {
|
||||||
|
if ((cp = strdup(*tp))) {
|
||||||
|
n = strlen(cp);
|
||||||
|
key = load_key_buf((unsigned char *)cp, n);
|
||||||
|
free(cp);
|
||||||
|
if (key) {
|
||||||
|
openpgp_trust_add(key);
|
||||||
|
once++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return (once);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief test that we can verify a signature
|
* @brief test that we can verify a signature
|
||||||
*
|
*
|
||||||
@ -333,19 +348,21 @@ openpgp_self_tests(void)
|
|||||||
char *fdata, *sdata = NULL;
|
char *fdata, *sdata = NULL;
|
||||||
size_t fbytes, sbytes;
|
size_t fbytes, sbytes;
|
||||||
|
|
||||||
for (tp = ta_ASC, vp = vc_ASC; *tp && *vp && rc; tp++, vp++) {
|
if (openpgp_trust_init() > 0) {
|
||||||
if ((fdata = strdup(*tp)) &&
|
for (tp = ta_ASC, vp = vc_ASC; *tp && *vp && rc; tp++, vp++) {
|
||||||
(sdata = strdup(*vp))) {
|
if ((fdata = strdup(*tp)) &&
|
||||||
fbytes = strlen(fdata);
|
(sdata = strdup(*vp))) {
|
||||||
sbytes = strlen(sdata);
|
fbytes = strlen(fdata);
|
||||||
rc = openpgp_verify("ta_ASC",
|
sbytes = strlen(sdata);
|
||||||
(unsigned char *)fdata, fbytes,
|
rc = openpgp_verify("ta_ASC",
|
||||||
(unsigned char *)sdata, sbytes, 0);
|
(unsigned char *)fdata, fbytes,
|
||||||
printf("Testing verify OpenPGP signature:\t\t%s\n",
|
(unsigned char *)sdata, sbytes, 0);
|
||||||
rc ? "Failed" : "Passed");
|
printf("Testing verify OpenPGP signature:\t\t%s\n",
|
||||||
|
rc ? "Failed" : "Passed");
|
||||||
|
}
|
||||||
|
free(fdata);
|
||||||
|
free(sdata);
|
||||||
}
|
}
|
||||||
free(fdata);
|
|
||||||
free(sdata);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return (rc);
|
return (rc);
|
||||||
|
@ -13,6 +13,7 @@ NO_SHARED=
|
|||||||
|
|
||||||
# we want to test verify_file api too
|
# we want to test verify_file api too
|
||||||
# which requires a kludge or two
|
# which requires a kludge or two
|
||||||
|
MK_LOADER_EFI_SECUREBOOT= no
|
||||||
.include "../Makefile.libsa.inc"
|
.include "../Makefile.libsa.inc"
|
||||||
BRSSL_CFLAGS := ${BRSSL_CFLAGS:N-DNO_STDIO}
|
BRSSL_CFLAGS := ${BRSSL_CFLAGS:N-DNO_STDIO}
|
||||||
XCFLAGS.verify_file += -DSOPEN_MAX=64
|
XCFLAGS.verify_file += -DSOPEN_MAX=64
|
||||||
|
@ -246,7 +246,9 @@ ve_trust_init(void)
|
|||||||
num = ve_trust_anchors_add(xcs, num);
|
num = ve_trust_anchors_add(xcs, num);
|
||||||
#endif
|
#endif
|
||||||
once = (int) VEC_LEN(trust_anchors);
|
once = (int) VEC_LEN(trust_anchors);
|
||||||
|
#ifdef VE_OPENPGP_SUPPORT
|
||||||
|
once += openpgp_trust_init();
|
||||||
|
#endif
|
||||||
return (once);
|
return (once);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,7 +816,7 @@ test_hash(const br_hash_class *md, size_t hlen,
|
|||||||
#define ve_test_hash(n, N) \
|
#define ve_test_hash(n, N) \
|
||||||
printf("Testing hash: " #n "\t\t\t\t%s\n", \
|
printf("Testing hash: " #n "\t\t\t\t%s\n", \
|
||||||
test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \
|
test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \
|
||||||
VE_HASH_KAT_STR, sizeof(VE_HASH_KAT_STR), \
|
VE_HASH_KAT_STR, VE_HASH_KAT_STRLEN(VE_HASH_KAT_STR), \
|
||||||
vh_ ## N) ? "Failed" : "Passed")
|
vh_ ## N) ? "Failed" : "Passed")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -863,34 +865,32 @@ ve_self_tests(void)
|
|||||||
#ifdef VERIFY_CERTS_STR
|
#ifdef VERIFY_CERTS_STR
|
||||||
xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
|
xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
|
||||||
sizeof(VERIFY_CERTS_STR), &num);
|
sizeof(VERIFY_CERTS_STR), &num);
|
||||||
if (xcs == NULL)
|
if (xcs != NULL) {
|
||||||
return (0);
|
/*
|
||||||
/*
|
* We want the commonName field
|
||||||
* We want the commonName field
|
* the OID we want is 2,5,4,3 - but DER encoded
|
||||||
* the OID we want is 2,5,4,3 - but DER encoded
|
*/
|
||||||
*/
|
cn_oid[0] = 3;
|
||||||
cn_oid[0] = 3;
|
cn_oid[1] = 0x55;
|
||||||
cn_oid[1] = 0x55;
|
cn_oid[2] = 4;
|
||||||
cn_oid[2] = 4;
|
cn_oid[3] = 3;
|
||||||
cn_oid[3] = 3;
|
cn.oid = cn_oid;
|
||||||
cn.oid = cn_oid;
|
cn.buf = cn_buf;
|
||||||
cn.buf = cn_buf;
|
|
||||||
|
|
||||||
for (u = 0; u < num; u ++) {
|
for (u = 0; u < num; u ++) {
|
||||||
cn.len = sizeof(cn_buf);
|
cn.len = sizeof(cn_buf);
|
||||||
if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
|
if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
|
||||||
free_cert_contents(&xcs[u]);
|
free_cert_contents(&xcs[u]);
|
||||||
once++;
|
once++;
|
||||||
printf("Testing verify certificate: %s\tPassed\n",
|
printf("Testing verify certificate: %s\tPassed\n",
|
||||||
cn.status ? cn_buf : "");
|
cn.status ? cn_buf : "");
|
||||||
xfreepkey(pk);
|
xfreepkey(pk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (!once)
|
||||||
|
printf("Testing verify certificate:\t\t\tFailed\n");
|
||||||
|
xfree(xcs);
|
||||||
}
|
}
|
||||||
if (!once)
|
|
||||||
printf("Testing verify certificate:\t\t\tFailed\n");
|
|
||||||
xfree(xcs);
|
|
||||||
#else
|
|
||||||
printf("No X.509 self tests\n");
|
|
||||||
#endif /* VERIFY_CERTS_STR */
|
#endif /* VERIFY_CERTS_STR */
|
||||||
#ifdef VE_OPENPGP_SUPPORT
|
#ifdef VE_OPENPGP_SUPPORT
|
||||||
if (!openpgp_self_tests())
|
if (!openpgp_self_tests())
|
||||||
|
Loading…
Reference in New Issue
Block a user