Files
Simon J. Gerraty 9ca2cfeb4e libsecureboot: add support for more signatures
For 2027 we need to support new, stronger signatures and hashes.

Re-work Makefile.inc and local.trust.mk to define
VE_SIGN_URL_LIST or VE_SIGNATURE_LIST (can be derrived from
VE_SIGN_URL_LIST) containing tuples of sig/method/hash/flags and
for VE_SIGN_URL_LIST the same plus /url.

From VE_SIGNATURE_LIST we derrive VE_SIGNATURE_EXT_LIST used to populate
signature_ext_list which defines the order in which we look for
signatures for a manifest.

We also populate signature_info_list which maps a signature ext to the
needed hash and flags to indicate whether that hash needs to be repeated.

verify_sig will lookup signature_info_list, no match means not
supported.  For asc we just call verify_asc() otherwise we call
verify_ec() or verify_rsa() depending on the key type found in the
certificate chain, we pass the signature_info entry to these so they
know which hash to use and whether to repeat it.

The need to repeat the hash is a consequence of sending a hash to a
server using signature methods that insiste on hashing their input.
To-date only our original ECDSA signatures use this.
A FakeHash class added in 2012 avoids that wrinkle.

This is a much more flexible arrangement and should be more
readily usable by others.

Sponsored by:	Hewlett Packard Enterprise Development LP.

Reviewed by:	imp
Differential Revision:	https://reviews.freebsd.org/D61007
2026-11-04 15:07:09 -08:00

209 lines
6.2 KiB
Makefile

# See README.rst for details on what we are doing here
.if empty(BEARSSL)
.include "../libbearssl/Makefile.inc"
.endif
.if !target(_${__this}_)
_${__this}_:
libsecureboot_src:= ${.PARSEDIR}
.PATH: ${.PARSEDIR}
CFLAGS+= -I. \
-I${libsecureboot_src}/h \
-DHAVE_BR_X509_TIME_CHECK \
${XCFLAGS.${.TARGET:T:R}:U}
SRCS+= \
readfile.c \
brf.c \
vesigned.c \
vets.c
.if ${.CURDIR:M*libsecureboot*} != ""
SRCS+= veta.c
.endif
# we use a couple of files from ${BEARSSL}/tools
BRSSL_CFLAGS+= -I${BEARSSL}/tools
BRSSL_SRCS+= \
${BEARSSL}/tools/xmem.c \
${BEARSSL}/tools/vector.c
BRSSL_DEPS= \
brf.c \
vets.c \
veta.c
.if ${MK_LOADER_EFI_SECUREBOOT} != "no"
BRSSL_DEPS+= \
efi_init.c \
efi_variables.c
.endif
# we do not need/want nested objdirs
OBJS_SRCS_FILTER = T R
SRCS+= ${BRSSL_SRCS}
# extract the last cert from a chain (should be rootCA)
_LAST_PEM_USE: .USE
sed "1,`grep -n .-END ${.ALLSRC:M*.pem} | tail -2 | head -1 | sed 's,:.*,,'`d" ${.ALLSRC:M*.pem} > ${.TARGET}
# extract 2nd last cert from chain - we use this for self-test
_2ndLAST_PEM_USE: .USE
sed -n "`grep -n .-BEGIN ${.ALLSRC:M*.pem} | tail -2 | \
sed 's,:.*,,' | xargs | (read a b; echo $$a,$$(($$b - 1)))`p" ${.ALLSRC:M*.pem} > ${.TARGET}
# Suppress duplicate entries in a list
# without changing the order
M_unique ?= @x@$${"${.$$x}":?:$$x${.$$x::=1}}@
# rules to populate the [tv]*.pem files we use to generate ta.h
# and VE_*_LIST as desired.
# At minimum we expect this to populate VE_SIGNATURE_LIST with tuples of
# sig/method/hash/flags in order of preference.
# The / separator makes it easy to use combinations of :H and :T to
# extract elements.
# XXXX change the format of VE_SIGNATURE_LIST and *lots* of :H
# expressions below need to change.
.-include "local.trust.mk"
# list of signatures we support
# Each entry defines an sig/method/hash/flags
# this list controls our search for signatures so will not be sorted
# note: for X509 signatures we assume we can replace the trailing
# "sig" with "certs" to find the certificate chain
# eg. for manifest.esig we use manifest.ecerts
VE_SIGNATURE_LIST?= sig/RSA/sha256/0
.if ${VE_SIGNATURE_LIST:M*OPENPGP*} != ""
.include "openpgp/Makefile.inc"
.endif
VE_SIGNATURE_LIST:= ${VE_SIGNATURE_LIST:${M_unique}}
# list of hashes we support (2nd last element of each tuple)
VE_HASH_LIST+= ${VE_SIGNATURE_LIST:H:T}
VE_HASH_LIST:= ${VE_HASH_LIST:tu:O:u}
# sig(ext) is first (4th last) element of each tuple
VE_SIGNATURE_EXT_LIST?= ${VE_SIGNATURE_LIST:H:H:H}
# needs to be yes for FIPS 140-2 compliance
VE_SELF_TESTS?= no
.if ${VE_SIGNATURE_EXT_LIST:M*sig} != ""
# this is what we use as our trust anchor
CFLAGS+= -DTRUST_ANCHOR_STR=ta_PEM
.if ${VE_SELF_TESTS} != "no"
XCFLAGS.vets+= -DVERIFY_CERTS_STR=vc_PEM
.endif
.endif
# method is 3rd last element of each tuple
VE_SUPPORT_LIST+= ${VE_HASH_LIST} ${VE_SIGNATURE_LIST:H:H:T}
# make sure we have the canonical names for the signature methods
# we support. eg. VE_SIGNATURE_LIST might have RSA3K etc,
# and we need RSA.
.for x in ECDSA RSA OPENPGP
.if ${VE_SUPPORT_LIST:tu:M*$x*} != ""
VE_SUPPORT_LIST+= $x
.endif
.endfor
# clean that up
VE_SUPPORT_LIST:= ${VE_SUPPORT_LIST:tu:O:u}
# define what we are supporting
CFLAGS+= ${VE_SUPPORT_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 2026-04-01Z
SOURCE_DATE_EPOCH?= 1775001600
.if ${MK_REPRODUCIBLE_BUILD} == "yes"
BUILD_UTC?= ${SOURCE_DATE_EPOCH}
.endif
# BUILD_UTC provides a basis for the loader's notion of time
# By default we use the mtime of BUILD_UTC_FILE
.if empty(BUILD_UTC_FILE)
BUILD_UTC_FILE:= ${.PARSEDIR:tA}/${.PARSEFILE}
.endif
# you can of course set BUILD_UTC to any value you like
.if ${MAKE_VERSION} > 20230509
BUILD_UTC?= ${BUILD_UTC_FILE:mtime}
.else
BUILD_UTC?= ${${STAT:Ustat} -L -f %m ${BUILD_UTC_FILE}:L:sh}
.endif
# Generate ta.h containing one or more PEM encoded trust anchors in ta_PEM.
#
# 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 VE_HASH_KAT_STR
# using each supported hash method
# to use as a Known Answer Test (needed for FIPS 140-2)
#
# We also populate signature_info_list describing the signatures
# we support.
#
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:
@( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
cat ${TA_PEM_LIST:O:u} /dev/null | \
file2c -sx 'static const char ta_PEM[] = {' '};'; \
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 ${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}
# This header contains signature info needed by verify_sig et al
${.SUFFIXES:M*o:S,^,vets,}: vsi.h
vsi.h:
@( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
echo 'static signature_info signature_info_list[] = {'; \
echo -e '${VE_SIGNATURE_LIST:@x@\t{ "${x:H:H:H}", "${x:H:H:T}", br_${x:H:T:tl}_ID, ${x:T} },${.newline}@}'; \
echo -e '\t{ NULL, NULL, 0, 0 },'; \
echo '};'; ) > ${.TARGET}
# This header records our preference for signature extensions.
${.SUFFIXES:M*o:S,^,vesigned,}: vse.h
vse.h:
@( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
echo "static const char *signature_ext_list[] = {"; \
echo '${VE_SIGNATURE_EXT_LIST:@e@"$e",${.newline}@}'; \
echo 'NULL };' ) > ${.TARGET}
.for s in ${BRSSL_SRCS} ${BRSSL_DEPS}
.ifdef BRSSL_SED
$s: brssl.h
.endif
XCFLAGS.${s:R}+= ${BRSSL_CFLAGS}
.endfor
.endif