# 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 `trixie` or newer:

    $ 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-key`

- `generate-asymmetric-key`

- `put-asymmetric-key`

- `sign-attestation-certificate`

- `sign-ecdsa`

- `sign-eddsa`

- `sign-pkcs`

- `sign-pss`

- `export-wrapped`

- `import-wrapped`

And a useful set of delegated capabilities is:

- `sign-ecdsa`

- `sign-eddsa`

- `sign-pkcs`

- `sign-pss`

- `exportable-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

1. The `yubihsm-connector` package 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.conf` file (the exact path is not important as long as `debusine-signing` can read it) with the following contents:

       connector = http://127.0.0.1:12345

2. Create the `/etc/systemd/system/debusine-signing.service.d` directory and create `/etc/systemd/system/debusine-signing.service.d/override.conf` with 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

3. 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 `secretpw` would become `0005secretpw`.

4. Encrypt this PIN for use by systemd (this must be run as root). Note the use of the `systemd-ask-password -n` option 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

1. Use `YUBIHSM_PKCS11_CONF=/etc/yubihsm_pkcs11.conf p11-kit list-modules` to find the base PKCS #11 URI for the HSM. This will be in the `uri:` line under `module: yubihsm_pkcs11`. You may drop the `manufacturer` and `token` fields; `model` and `serial` should be sufficient to uniquely identify the device.

2. Append `;pin-source=/run/credentials/debusine-signing.service/yubihsm-pin` so that `debusine-signing` uses the PIN for its authentication key.

3. Append `;id=KEY-ID`, where `KEY-ID` is the ID of the relevant signing key as a four-character hexadecimal string.

4. Ensure that the `/etc/debusine/signing/certificates` directory exists and write the key’s certificate to `/etc/debusine/signing/certificates/KEY-NAME.crt` (for some appropriate identifier `KEY-NAME`),

5. Register the key with `debusine-signing` as follows, where `KEY-URI` is the URI assembled in the previous steps:

       $ sudo debusine-signing register_pkcs11_static_key \
           uefi KEY-URI /etc/debusine/signing/certificates/KEY-NAME.crt \
           'some description of the new key'

6. 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