rpi-eeprom-digest: support specifying keys via PKCS#11 URI

In production setups, it is quite normal that the private key does not
exist as a file in the file system, but is kept inside some HSM,
remote signing service or similar, and only accessed via some pkcs#11
interface; moreover, by design, the private key _cannot_ be extracted
from the HSM or signing service.

In such a case, the user will have set OPENSSL_CONF to some
configuration file setting up the appropriate engine, and the "key" is
simply the pkcs#11 URI, e.g. "pkcs11:model=foo;object=bar".

In order to support this use case, automatically infer the appropriate
options to pass to openssl-dgst if "${KEY}" begins with
"pkcs11:". Doing this at the top level avoids duplicating the logic in
both writeSig and verifySig. While here, this also adds a sanity check
that -v can only be used while also providing a (public) key to check
against.

This drops the -keyform argument in the non-pkcs#11 case, as openssl
automatically infers the type, and this then in fact allows one to use
a private key in e.g. DER format.

Signed-off-by: Rasmus Villemoes <ravi@prevas.dk>
This commit is contained in:
Rasmus Villemoes
2025-02-24 11:48:15 +01:00
committed by timg236
parent 28a2c0242c
commit 3a16bd016f

View File

@@ -59,11 +59,12 @@ Options:
-k Optional RSA private key.
RSA signing
If a private key in PEM format is supplied then the RSA signature of the
sha256 digest is included in the .sig file. Currently, the bootloader only
supports sha256 digests signed with a 2048bit RSA key.
The bootloader only verifies RSA signatures in signed boot mode
and only for the EEPROM config file and the signed image.
If a private key in PEM format or a pkcs#11 URI is supplied then the
RSA signature of the sha256 digest is included in the .sig
file. Currently, the bootloader only supports sha256 digests signed
with a 2048bit RSA key. The bootloader only verifies RSA signatures
in signed boot mode and only for the EEPROM config file and the signed
image.
Examples:
@@ -78,6 +79,9 @@ rpi-eeprom-digest -k private.pem -i boot.img -o boot.sig
# As used by update-pieeprom.sh in usbboot/secure-boot-recovery
rpi-eeprom-digest -k private.pem -i bootconf.txt -o bootconf.sig
# Similarly, but specifying the key with a PKCS#11 URI
rpi-eeprom-digest -k pkcs11:token=deadbeef;object=bl-key;type=private;pin-value=1234 -i bootconf.txt -o bootconf.sig
# To verify the signature of an existing .sig file using the public key.
# N.B The key file must be the PUBLIC key in PEM format.
rpi-eeprom-digest -k public.pem -i boot.bin -v boot.sig
@@ -99,8 +103,7 @@ writeSig() {
fi
if [ -n "${KEY}" ]; then
[ -f "${KEY}" ] || die "RSA private \"${KEY}\" not found"
"${OPENSSL}" dgst -sign "${KEY}" -keyform PEM -sha256 -out "${SIG_TMP}" "${IMAGE}"
"${OPENSSL}" dgst ${ENGINE_OPTS} -sign "${KEY}" -sha256 -out "${SIG_TMP}" "${IMAGE}"
echo "rsa2048: $(xxd -c 4096 -p < "${SIG_TMP}")" >> "${OUTPUT}"
fi
}
@@ -113,7 +116,7 @@ verifySig() {
[ -n "${sig_hex}" ] || die "No RSA signature in ${sig_file}"
echo ${sig_hex} | xxd -c 4096 -p -r > "${TMP_DIR}/sig.bin"
"${OPENSSL}" dgst -verify "${KEY}" -signature "${TMP_DIR}/sig.bin" "${IMAGE}" || die "${IMAGE} not verified"
"${OPENSSL}" dgst ${ENGINE_OPTS} -verify "${KEY}" -signature "${TMP_DIR}/sig.bin" "${IMAGE}" || die "${IMAGE} not verified"
}
OUTPUT=""
@@ -142,6 +145,18 @@ checkDependencies
[ -n "${IMAGE}" ] || usage
[ -f "${IMAGE}" ] || die "Source image \"${IMAGE}\" not found"
[ "${VERIFY}" != 1 ] || [ -n "${KEY}" ] || die "Option -v also requires passing public key via -k"
if [ -n "${KEY}" ] ; then
if [ -f "${KEY}" ] ; then
ENGINE_OPTS=
elif echo "${KEY}" | grep -q "^pkcs11:" ; then
ENGINE_OPTS="-engine pkcs11 -keyform engine"
else
die "RSA key \"${KEY}\" not found"
fi
fi
if [ "${VERIFY}" = 1 ]; then
verifySig "${SIGNATURE}"
else