Inject CA cert into kernel during tools/publish, not during build
Summary
Currently, we insert the leaf code-signing cert during the kernel build and sign the modules with the private portion in tools/publish. However, instead we should do the following:
- DON'T insert any certs into the kernel at build time
- Generate a one-time modules signing key in
tools/publish - Sign the modules with it
- Inject the certificate into the prebuilt kernel
- Throw away the signing key
- ukify the whole thing and sign for secure boot
Reasoning
- We match other distros behavior, where they sign their modules w/ a one-off key
- This allows our kernel build to be reproducible
- Avoids using any data specific to a secret from within BuildStream
- Completely prevents modules from one kernel build from being used in another kernel build, even if we mess up version numbers
- The kernel won't automatically trust everything signed with our leaf codesigning key
- Instead trusting this key comes from the UEFI/MOK
- This allows a user to sign carbonOS with their own keys and the kernel won't trust our keys anymore
- This allows a user who's using their own keys to prevent sysexts/kexec/etc signed by us from loading, but still let kmods work as intended
Prior Art
- No other distro is doing such a thing
- They generate a throw-away key during the kernel build and sign built-in modules with it
- They don't have the same reproducibility and artifact-cache-uploading-private-key concerns that we have
- The kernel has limited support for this in the form of
scripts/insert-sys-cert. HOWEVER it doesn't work with abzImage- Abandoned patch series from 2018 to make it work on x86: "Certificate insertion support for x86 bzImages"
- TODO: Investigate how Pop_OS! handles this (they're the only distro I know that ships the NVIDIA driver OOTB. Maybe they just don't do secureboot?)
How to implement
Ideas:
- Revive the abandoned patch, possibly port to aarch64 too (is that even possible?), upstream it
- An in-tree kernel module that just loads some certs into the builtin keyring. The hash of this bundle can be provided on the kernel cmdline (which allows it to bypass lockdown). Then in
tools/publishwe can take the ko file (which is just an elf, soinject-sys-certwill work on it), inject the certs into it, compress, and append its hash to the kernel cmdline - Certs can already be inserted into the builtin keyring IF they are signed by key already in the ring. If the keyring is empty, permit the very first cert loaded in and then ensure everything else is signed by that. Treat it as built-in. Then add section to sd-stub that contains the cert. sd-stub can then synthesize a file in the initrd and systemd can load it into the keyring before any modules are loaded.
- Like 3, but instead of accepting any cert the cmdline would have to have a hash of the cert. This prevents certs from being uploaded into the kernel during on systems that are protected by traditional secure-boot
- Perhaps cert can be inserted somewhere into the EFI stub PE binary?
- Maybe some other interface can exist between sd-stub and the embedded kernel?