nethsm-gateway runs a daemon provided by
pkcs11-proxy.
This daemon is listening on tls port 2345, accessible through the nebula tunnel from the hetzner CI. A library provided by the same project can be used as the pkcs11 module, which will proxy the requests to the correct place (configured through environment variables).
The requests are encrypted with a PKS key which comes from the host secrets.
Signing operations can be done from Hetzner CI, with configured pkcs11-proxy. The keys used will be the ones stored on the NetHSM.
The HSM infrastructure serves two independent signing purposes — SLSA signing (supply chain integrity for disk images and provenance) and UEFI Secure Boot signing (EFI binary authentication on target hardware). Both use the same PKCS#11 proxy but different keys and tools.
SLSA provenance documents are generated by
sbomnix on the Jenkins controllers, then
signed with openssl using keys stored in the NetHSM. Test agents verify these
signatures with policy-checker / verify-signature before flashing images.
Signing of blobs is done through openssl with the keys stored in the NetHSM.
GhafInfraSignECP256: ECDSA, Used for signing binariesGhafInfraSignProv: EDDSA, Used for signing provenance filesGhafInfraSignBin: EDDSA, Ideally would be used for signing binaries (TODO)
Normally signing would be done with the openssl dgst commands, but since it
does not support ED25519 keys, pkeyutl has to be used instead.
Create signature:
openssl pkeyutl -sign \
-inkey "pkcs11:token=NetHSM;object=GhafInfraSignProv" \
-in provenance.json -rawin \
-out provenance.json.sigVerify signature:
openssl pkeyutl -verify \
-inkey "pkcs11:token=NetHSM;object=GhafInfraSignProv" -pubin \
-in provenance.json -rawin \
-sigfile provenance.json.sigpkeyutl will not hash the file, but uses the raw file as the input for the
signature. Since disk images are so large, the operation performed by pkeyutl
with EDDSA keys will fail. We have to use ECDSA key for signing the images (for
now).
Create signature:
openssl dgst -sha256 -sign \
"pkcs11:token=NetHSM;object=GhafInfraSignECP256" \
-out disk1.raw.zst.sig \
disk1.raw.zstVerify signature:
openssl dgst -verify \
"pkcs11:token=NetHSM;object=GhafInfraSignECP256" \
-signature disk1.raw.zst.sig \
disk1.raw.zstUEFI Secure Boot signing ensures that EFI binaries and boot images are authenticated by the target hardware's firmware before execution. This is separate from SLSA signing — SLSA provides supply chain provenance, while Secure Boot provides runtime boot integrity enforced by the UEFI firmware.
The Secure Boot key hierarchy (PK, KEK, DB) is stored on the HSM. The
get-secureboot-keys command on nethsm-gateway fetches the certificates
and generates the signed auth files needed for enrollment:
get-secureboot-keys /path/to/outputThe public certificates used for build-time signing are distributed via the
ghaf-infra-pki flake input (yubi-uefi-pki package) and deployed to
/etc/jenkins/keys/secboot/ on Jenkins controllers.
Jenkins controllers have the following UEFI signing tools available
(from the ci-yubi flake input and hosts/hetzci/signing.nix):
uefisign— sign individual EFI binariesuefisigniso— sign EFI binaries within ISO imagesuefisign-simple— simplified wrapper for common signing operationssystemd-sbsign— systemd's built-in sbsign tool for PE binary signing
These tools use the same PKCS#11 proxy connection as SLSA signing to access the HSM keys.
