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. -k Optional RSA private key.
RSA signing RSA signing
If a private key in PEM format is supplied then the RSA signature of the If a private key in PEM format or a pkcs#11 URI is supplied then the
sha256 digest is included in the .sig file. Currently, the bootloader only RSA signature of the sha256 digest is included in the .sig
supports sha256 digests signed with a 2048bit RSA key. file. Currently, the bootloader only supports sha256 digests signed
The bootloader only verifies RSA signatures in signed boot mode with a 2048bit RSA key. The bootloader only verifies RSA signatures
and only for the EEPROM config file and the signed image. in signed boot mode and only for the EEPROM config file and the signed
image.
Examples: 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 # As used by update-pieeprom.sh in usbboot/secure-boot-recovery
rpi-eeprom-digest -k private.pem -i bootconf.txt -o bootconf.sig 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. # 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. # 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 rpi-eeprom-digest -k public.pem -i boot.bin -v boot.sig
@@ -99,8 +103,7 @@ writeSig() {
fi fi
if [ -n "${KEY}" ]; then if [ -n "${KEY}" ]; then
[ -f "${KEY}" ] || die "RSA private \"${KEY}\" not found" "${OPENSSL}" dgst ${ENGINE_OPTS} -sign "${KEY}" -sha256 -out "${SIG_TMP}" "${IMAGE}"
"${OPENSSL}" dgst -sign "${KEY}" -keyform PEM -sha256 -out "${SIG_TMP}" "${IMAGE}"
echo "rsa2048: $(xxd -c 4096 -p < "${SIG_TMP}")" >> "${OUTPUT}" echo "rsa2048: $(xxd -c 4096 -p < "${SIG_TMP}")" >> "${OUTPUT}"
fi fi
} }
@@ -113,7 +116,7 @@ verifySig() {
[ -n "${sig_hex}" ] || die "No RSA signature in ${sig_file}" [ -n "${sig_hex}" ] || die "No RSA signature in ${sig_file}"
echo ${sig_hex} | xxd -c 4096 -p -r > "${TMP_DIR}/sig.bin" 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="" OUTPUT=""
@@ -142,6 +145,18 @@ checkDependencies
[ -n "${IMAGE}" ] || usage [ -n "${IMAGE}" ] || usage
[ -f "${IMAGE}" ] || die "Source image \"${IMAGE}\" not found" [ -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 if [ "${VERIFY}" = 1 ]; then
verifySig "${SIGNATURE}" verifySig "${SIGNATURE}"
else else