Configure an HSM for use with Debusine
After setting up a signing worker, you may want to attach a hardware security module (HSM) to provide additional protection for some keys. Debusine supports any HSM that you can interact with using PKCS #11, but we have currently only tested it with YubiHSM 2 devices. The remainder of this document describes how to set up a YubiHSM 2 for use with Debusine; it may be possible to adapt the same ideas for other devices.
Install packages needed to use the YubiHSM 2
These packages can be installed from bookworm-backports or newer
(including trixie):
$ sudo apt install \
libengine-pkcs11-openssl p11-kit-modules \
yubihsm-connector yubihsm-pkcs11 yubihsm-shell
Decide on a key policy
The YubiHSM 2 user guide has some advice on initial provisioning and deployment, which you should consider.
You may wish to have a “management” authentication key with a strong password held offline which you can use to change the key policy later, and as an escape hatch in case you make a mistake. If so, note that the default authentication key shipped with the device has a weak password; either that key must be removed or its password must be changed.
Debusine currently only supports using “static” PKCS #11 signing keys: that is, keys that have been pre-generated on the HSM and that can then be registered for use by Debusine. (In future, we may support dynamic key generation as well.) Debusine-specific keys should be kept within their own domain, to allow using the HSM for other purposes.
Debusine additionally needs an authentication key that it can use to connect
to the HSM and make signatures. This should have a strong password, but the
password will need to be made available to debusine-signing.service.
This key must have enough capabilities
and delegated capabilities
to allow making use of signing keys. A useful set of capabilities is:
delete-asymmetric-keygenerate-asymmetric-keyput-asymmetric-keysign-attestation-certificatesign-ecdsasign-eddsasign-pkcssign-pssexport-wrappedimport-wrapped
And a useful set of delegated capabilities is:
sign-ecdsasign-eddsasign-pkcssign-pssexportable-under-wrap
For backup
purposes, it is wise to use “wrap keys” which allow exporting keys “under
wrap” in such a way that they can be imported into devices possessing the
same wrap key. You should have a management wrap key that allows backing up
and restoring all exportable keys on the device. There should also be a
wrap key that debusine-signing can use to export keys in its own domain:
this is part of our plan for supporting more keys than the HSM supports, so
it will eventually become a requirement.
Although the YubiHSM itself supports passwords from 8 to 64 bytes long, in practice the userspace stack currently imposes a maximum length of 27 bytes.
You can use yubihsm-shell to create the various keys involved. The
put authkey, put wrapkey, generate wrapkey, and put
asymmetric commands are especially useful here. You should keep a record
of the script you followed and the resulting key IDs for later reference.
For each key, you will need its corresponding certificate (public key). If
you imported an externally-generated key into the HSM, then you should
already have its certificate. Otherwise, you can use the attest
asymmetric command in yubihsm-shell to generate one.
Configure debusine-signing to use the HSM
The
yubihsm-connectorpackage provides an HTTP daemon that passes through requests to the USB device. Some tools need to be pointed to the connector’s URL. Create a/etc/yubihsm_pkcs11.conffile (the exact path is not important as long asdebusine-signingcan read it) with the following contents:connector = http://127.0.0.1:12345
Create the
/etc/systemd/system/debusine-signing.service.ddirectory and create/etc/systemd/system/debusine-signing.service.d/override.confwith the following contents, where the path is the same as that of the file you created in the previous step:[Service] Environment=YUBIHSM_PKCS11_CONF=/etc/yubihsm_pkcs11.conf
Assemble the PIN to be used by Debusine. This consists of its authentication key ID as a four-character hexadecimal string, followed by the actual password: for example, key ID 5 with password
secretpwwould become0005secretpw.Encrypt this PIN for use by systemd (this must be run as root). Note the use of the
systemd-ask-password -noption to ensure that the PIN does not end with a newline character:# systemd-ask-password -n | systemd-creds encrypt --name=yubihsm-pin -p - - \ >>/etc/systemd/system/debusine-signing.service.d/override.conf
Register a UEFI signing key stored in the HSM
Use
YUBIHSM_PKCS11_CONF=/etc/yubihsm_pkcs11.conf p11-kit list-modulesto find the base PKCS #11 URI for the HSM. This will be in theuri:line undermodule: yubihsm_pkcs11. You may drop themanufacturerandtokenfields;modelandserialshould be sufficient to uniquely identify the device.Append
;pin-source=/run/credentials/debusine-signing.service/yubihsm-pinso thatdebusine-signinguses the PIN for its authentication key.Append
;id=KEY-ID, whereKEY-IDis the ID of the relevant signing key as a four-character hexadecimal string.Ensure that the
/etc/debusine/signing/certificatesdirectory exists and write the key’s certificate to/etc/debusine/signing/certificates/KEY-NAME.crt(for some appropriate identifierKEY-NAME),Register the key with
debusine-signingas follows, whereKEY-URIis the URI assembled in the previous steps:$ sudo -u debusine-signing debusine-signing register_pkcs11_static_key \ uefi KEY-URI /etc/debusine/signing/certificates/KEY-NAME.crt \ 'some description of the new key'
Create a debusine:signing-key corresponding to the new key:
$ debusine create-asset --workspace System --data - <<END purpose: uefi fingerprint: KEY-FINGERPRINT public_key: BASE64-ENCODED-CERTIFICATE END