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
@ -98,10 +98,20 @@ CFLAGS+= ${VE_HASH_LIST:@H@-DVE_$H_SUPPORT@} \
|
||||
|
||||
.if ${VE_SELF_TESTS} != "no"
|
||||
# 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_INPUT= cat
|
||||
VE_HASH_KAT_STRLEN= sizeof
|
||||
XCFLAGS.vets+= -DVE_HASH_KAT_STR=${VE_HASH_KAT_STR}
|
||||
.endif
|
||||
XCFLAGS.vets+= -DVE_HASH_KAT_STRLEN=${VE_HASH_KAT_STRLEN}
|
||||
.endif
|
||||
|
||||
# this should be updated occassionally this is 2019-01-01Z
|
||||
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
|
||||
# containing certificates that we can verify for each trust anchor.
|
||||
# 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)
|
||||
#
|
||||
TA_PEM_LIST ?= ${.ALLSRC:N*crl*:Mt*.pem}
|
||||
VC_PEM_LIST ?= ${.ALLSRC:N*crl*:Mv*.pem}
|
||||
vets.o vets.po vets.pico: ta.h
|
||||
ta.h: ${.ALLTARGETS:M[tv]*pem:O:u}
|
||||
ta.h:
|
||||
@( 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[] = {' '};'; \
|
||||
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"
|
||||
( 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}
|
||||
.endif
|
||||
echo '#define BUILD_UTC ${BUILD_UTC}' >> ${.TARGET} ${.OODATE:MNOMETA_CMP}
|
||||
@ -141,7 +154,7 @@ vesigned.o vesigned.po vesigned.pico: vse.h
|
||||
vse.h:
|
||||
@( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
|
||||
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}
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ int verify_rsa_digest(br_rsa_public_key *pkey,
|
||||
int is_verified(struct stat *stp);
|
||||
void add_verify_status(struct stat *stp, int status);
|
||||
|
||||
int openpgp_trust_init(void);
|
||||
int openpgp_self_tests(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:
|
||||
${SIGN_OPENPGP} -C ${.TARGET}
|
||||
|
||||
ta.h: ta_openpgp.asc
|
||||
ta_asc.h: ta_openpgp.asc
|
||||
|
||||
.if ${VE_SELF_TESTS} != "no"
|
||||
# for self test
|
||||
@ -59,7 +59,7 @@ vc_openpgp.asc: ta_openpgp.asc
|
||||
${SIGN_OPENPGP} ${.ALLSRC:M*.asc}
|
||||
mv ta_openpgp.asc.asc ${.TARGET}
|
||||
|
||||
ta.h: vc_openpgp.asc
|
||||
ta_asc.h: vc_openpgp.asc
|
||||
.endif
|
||||
.endif
|
||||
|
||||
@ -72,17 +72,20 @@ ecerts.pem:
|
||||
.if ${VE_SIGNATURE_LIST:tu:MECDSA} != ""
|
||||
# the last cert in the chain is the one we want
|
||||
ta_ec.pem: ecerts.pem _LAST_PEM_USE
|
||||
|
||||
ta.h: ta_ec.pem
|
||||
.if ${VE_SELF_TESTS} != "no"
|
||||
# these are for verification self test
|
||||
vc_ec.pem: ecerts.pem _2ndLAST_PEM_USE
|
||||
ta.h: vc_ec.pem
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.if ${VE_SIGNATURE_LIST:tu:MRSA} != ""
|
||||
ta_rsa.pem: rcerts.pem _LAST_PEM_USE
|
||||
ta.h: ta_rsa.pem
|
||||
.if ${VE_SELF_TESTS} != "no"
|
||||
vc_rsa.pem: rcerts.pem _2ndLAST_PEM_USE
|
||||
ta.h: vc_rsa.pem
|
||||
.endif
|
||||
.endif
|
||||
|
||||
|
@ -23,26 +23,29 @@ opgp_key.o opgp_key.po opgp_key.pico: ta_asc.h
|
||||
# It is assumed that these v*.asc files are named similarly to
|
||||
# the appropriate t*.asc so that the relative order of vc_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} != ""
|
||||
@( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
|
||||
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 \
|
||||
file2c -sx "static const char $$2[] = {" ', 0x00 };' < $$1; \
|
||||
shift 2; \
|
||||
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}
|
||||
.if ${VE_SELF_TESTS} != "no"
|
||||
@( 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 \
|
||||
file2c -sx "static const char $$2[] = {" ', 0x00 };' < $$1; \
|
||||
shift 2; \
|
||||
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}
|
||||
.endif
|
||||
.endif
|
||||
|
@ -289,26 +289,8 @@ load_trusted_key_id(const char *keyID)
|
||||
OpenPGP_key *
|
||||
load_key_id(const char *keyID)
|
||||
{
|
||||
static int once = 0;
|
||||
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);
|
||||
#ifndef _STANDALONE
|
||||
if (!key)
|
||||
@ -317,6 +299,39 @@ load_key_id(const char *keyID)
|
||||
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
|
||||
*
|
||||
@ -333,19 +348,21 @@ openpgp_self_tests(void)
|
||||
char *fdata, *sdata = NULL;
|
||||
size_t fbytes, sbytes;
|
||||
|
||||
for (tp = ta_ASC, vp = vc_ASC; *tp && *vp && rc; tp++, vp++) {
|
||||
if ((fdata = strdup(*tp)) &&
|
||||
(sdata = strdup(*vp))) {
|
||||
fbytes = strlen(fdata);
|
||||
sbytes = strlen(sdata);
|
||||
rc = openpgp_verify("ta_ASC",
|
||||
(unsigned char *)fdata, fbytes,
|
||||
(unsigned char *)sdata, sbytes, 0);
|
||||
printf("Testing verify OpenPGP signature:\t\t%s\n",
|
||||
rc ? "Failed" : "Passed");
|
||||
if (openpgp_trust_init() > 0) {
|
||||
for (tp = ta_ASC, vp = vc_ASC; *tp && *vp && rc; tp++, vp++) {
|
||||
if ((fdata = strdup(*tp)) &&
|
||||
(sdata = strdup(*vp))) {
|
||||
fbytes = strlen(fdata);
|
||||
sbytes = strlen(sdata);
|
||||
rc = openpgp_verify("ta_ASC",
|
||||
(unsigned char *)fdata, fbytes,
|
||||
(unsigned char *)sdata, sbytes, 0);
|
||||
printf("Testing verify OpenPGP signature:\t\t%s\n",
|
||||
rc ? "Failed" : "Passed");
|
||||
}
|
||||
free(fdata);
|
||||
free(sdata);
|
||||
}
|
||||
free(fdata);
|
||||
free(sdata);
|
||||
}
|
||||
#endif
|
||||
return (rc);
|
||||
|
@ -13,6 +13,7 @@ NO_SHARED=
|
||||
|
||||
# we want to test verify_file api too
|
||||
# which requires a kludge or two
|
||||
MK_LOADER_EFI_SECUREBOOT= no
|
||||
.include "../Makefile.libsa.inc"
|
||||
BRSSL_CFLAGS := ${BRSSL_CFLAGS:N-DNO_STDIO}
|
||||
XCFLAGS.verify_file += -DSOPEN_MAX=64
|
||||
|
@ -246,7 +246,9 @@ ve_trust_init(void)
|
||||
num = ve_trust_anchors_add(xcs, num);
|
||||
#endif
|
||||
once = (int) VEC_LEN(trust_anchors);
|
||||
|
||||
#ifdef VE_OPENPGP_SUPPORT
|
||||
once += openpgp_trust_init();
|
||||
#endif
|
||||
return (once);
|
||||
}
|
||||
|
||||
@ -814,7 +816,7 @@ test_hash(const br_hash_class *md, size_t hlen,
|
||||
#define ve_test_hash(n, N) \
|
||||
printf("Testing hash: " #n "\t\t\t\t%s\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")
|
||||
|
||||
/**
|
||||
@ -863,34 +865,32 @@ ve_self_tests(void)
|
||||
#ifdef VERIFY_CERTS_STR
|
||||
xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
|
||||
sizeof(VERIFY_CERTS_STR), &num);
|
||||
if (xcs == NULL)
|
||||
return (0);
|
||||
/*
|
||||
* We want the commonName field
|
||||
* the OID we want is 2,5,4,3 - but DER encoded
|
||||
*/
|
||||
cn_oid[0] = 3;
|
||||
cn_oid[1] = 0x55;
|
||||
cn_oid[2] = 4;
|
||||
cn_oid[3] = 3;
|
||||
cn.oid = cn_oid;
|
||||
cn.buf = cn_buf;
|
||||
if (xcs != NULL) {
|
||||
/*
|
||||
* We want the commonName field
|
||||
* the OID we want is 2,5,4,3 - but DER encoded
|
||||
*/
|
||||
cn_oid[0] = 3;
|
||||
cn_oid[1] = 0x55;
|
||||
cn_oid[2] = 4;
|
||||
cn_oid[3] = 3;
|
||||
cn.oid = cn_oid;
|
||||
cn.buf = cn_buf;
|
||||
|
||||
for (u = 0; u < num; u ++) {
|
||||
cn.len = sizeof(cn_buf);
|
||||
if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
|
||||
free_cert_contents(&xcs[u]);
|
||||
once++;
|
||||
printf("Testing verify certificate: %s\tPassed\n",
|
||||
cn.status ? cn_buf : "");
|
||||
xfreepkey(pk);
|
||||
for (u = 0; u < num; u ++) {
|
||||
cn.len = sizeof(cn_buf);
|
||||
if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
|
||||
free_cert_contents(&xcs[u]);
|
||||
once++;
|
||||
printf("Testing verify certificate: %s\tPassed\n",
|
||||
cn.status ? cn_buf : "");
|
||||
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 */
|
||||
#ifdef VE_OPENPGP_SUPPORT
|
||||
if (!openpgp_self_tests())
|
||||
|
Loading…
Reference in New Issue
Block a user