The CryptOS release assets are built unsigned, and they carry no upgrade
anchor. An upgrade anchor is the certificate a node checks an incoming image
against before it writes the image to its ESP. A node installed from an
unsigned asset as-is serves the image upgrade calls (image stage,
image rollback, image activate) as unavailable.
cryptosctl image sign fixes that on your workstation. It needs no rebuild, no
root and no other tools, and it runs on Linux and macOS. With your Secure Boot
key and certificate it:
- adds your certificate to the image as its upgrade anchor;
- Authenticode-signs the image for Secure Boot, the same form
sbsignwrites; - writes the detached release signature that
image stagesends, beside the image as<out>.sig.
A node installed from an image you signed this way takes signed in-place
upgrades: any later image you sign with the same key can be staged onto it
with cryptosctl image stage.
It signs an unsigned ISO the same way, so you can install from a signed ISO without rebuilding it; see Sign an ISO.
- An unsigned CryptOS UKI or ISO, for example a release asset, or
build/out/cryptos-amd64.uki.unsignedorbuild/out/cryptos-amd64-vmware-unsigned-<build>.isofrom a cryptos-appliance build. - Your Secure Boot signing key as an unencrypted RSA PEM file (PKCS#1 or PKCS#8), and its certificate as PEM or DER. This is the certificate enrolled in your machines' Secure Boot db. Keep the key file readable by you only.
- A
cryptosctlbuilt from this repo (task buildwritesbin/cryptosctl).
-
Sign it:
cryptosctl image sign \ --image cryptos-amd64.uki.unsigned \ --key release.key \ --cert release.crt
With no
--out, the signed image goes next to the input without its.unsignedsuffix (cryptos-amd64.uki); an input with any other name gets.signed.uki. The release signature is written as<out>.sig. The command prints both paths, the image's SHA-256, and the anchor certificate's subject and SHA-256 fingerprint. -
Optionally, check the Secure Boot signature on a Linux host that has
sbsigntools:sbverify --cert release.crt cryptos-amd64.uki
-
Install a new node from the signed image, or stage it onto a node that already trusts this key:
cryptosctl --endpoint pki-root.example:443 image stage --image cryptos-amd64.uki
image stagepicks upcryptos-amd64.uki.sigby default.
Give --image an ISO instead of a UKI. The command tells the two apart by
their content, not their names. It needs no root, no xorriso and no rebuild.
-
Sign it:
cryptosctl image sign \ --image cryptos-amd64-vmware-unsigned-v0.1.0.iso \ --key release.key \ --cert release.crt
It signs the UKI inside the ISO exactly as it signs a UKI on its own, then writes the signed UKI back over every copy the ISO carries:
EFI/BOOT/BOOTX64.EFIin the EFI boot image, which the firmware boots;/cryptos.uki, which the installer copies to the disk it installs.
It writes three files. With no
--out, the signed ISO is the input name without-unsigned(cryptos-amd64-vmware-v0.1.0.iso); an input with any other name gets.signed.iso. Beside the ISO it writes the signed UKI, named like the ISO with.ukiin place of.iso(cryptos-amd64-vmware-v0.1.0.uki), and that UKI's release signature (cryptos-amd64-vmware-v0.1.0.uki.sig). The command prints each place in the ISO it signed, the paths and the SHA-256 of the ISO and the UKI.Before it writes anything, it reads the new ISO back, checks that every copy is the signed UKI, and checks the signature and the anchor.
-
Optionally, check the Secure Boot signature on the UKI written beside the ISO, the same bytes as the copies inside it:
sbverify --cert release.crt cryptos-amd64-vmware-v0.1.0.uki
-
Install a node from the signed ISO. Keep the signed
.ukiand.sig: they are what you stage onto a node, and later ISOs or UKIs you sign with the same key upgrade every node installed from this one.
Caution
The EFI boot image inside the ISO keeps its size. A cryptos-appliance build leaves 2 MiB free in it, far more than signing adds, but an ISO built some other way with no free space is refused, and nothing is written.
- The anchor. A small uncompressed cpio archive holding
upgrade-anchor.der(your certificate, DER) is appended to the UKI's.initrd. The kernel unpacks it as/upgrade-anchor.der, and the initramfs hands it to init. Because it is part of.initrd, it is measured into PCR 11 and covered by the Secure Boot signature, the same as the kernel. - The layout. The sections after
.initrdmove up to make room. The systemd-stub sections before it keep their bytes and addresses. - The signature. Any existing Authenticode signature is replaced by yours.
Signing an already signed image again appends a second anchor; the last one wins, so the image then trusts only the new key.
A node takes its anchor from the image it is running. A sign-time anchor (from
image sign) wins over a build-time one (stamped in by a cryptos-appliance
build with SB_CERT set). An image with neither serves the upgrade calls as
unavailable. To move a node onto a different key, reinstall it from an image
signed with the new key.