-
-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can I automatically run systemd-cryptenroll after bootloader is updated? #61
Comments
Interesting, quick question:
|
systemd-cryptenroll takes some time to enroll keys , I don't want to run it when there is no update to the bootloader. My goal is preventing other OSes on USB sticks from accessing LUKS encryption keys stored in the TPM, while still allowing them to boot. I can still manually unlock my volume with a password when I want. |
I'm not sure exactly when I need to re-run this command. Upgrading the kernel doesn't seem to cause boot failure, which might mean that bootloader configuration doesn't affect calculation of PCR 4 value. |
So basically, some sort of |
What I planned was running a single script with environment variables indicating what are updated, rather than having multiple hooks. |
I was misunderstanding how PCR value calculation works. tpm_futurepcr would allow pre-calculating the value for PCR4, but no longer maintained. I try enabling early SSH instead to type password from main machine. Hooks won't be useful for my use case without a tool like tpm_futurepcr. |
Should this be closed? Is there any way to have working tpm unlocking after a kernel/bootloader/initrd update? Could |
I'm not sure why this was closed. Looks like a pretty useful feature. |
To me this sounds like you want to use something like |
If someone uses |
We discussed it today with @nikstur some of the PR inflight will enable
this, feel free to participate in reviews. :)
Le ven. 12 mai 2023 à 23:58, Cole Mickens ***@***.***> a
écrit :
… If someone uses systemd-measure with lanzaboote, maybe perhaps with
systemd-cryptenroll for automatic TPM-based LUKS unlocking, I'd love to
hear a few hints/details. Unless someone else wants to just do it, I could
add it to the README once I get it figured out.
—
Reply to this email directly, view it on GitHub
<#61 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACMZRACNVQAFXL4IQTZM6TXF2W7ZANCNFSM6AAAAAATZ7BQOY>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
So one thing to keep note of: If you're using self-signed secure boot and just want to avoid re-enrolling your TPM2 based LUKS keys, you can just bind to PCR 7 (and 0 and 2 IMO). No need for all the systemd-measure stuff. The systemd-measure stuff is more about sealing things against specific UKI configurations, but still depends on the previous boot stages to be secure. systemd-measure also confusingly includes the idea of PCR phases in there (which is why I've messed with it), but that's realistically a distinct concept from both PCR sigs and secure boot. |
This is slightly offtopic (because I ended up not using lanzaboote in the end), but here's my config where I pre-measure an UKI, auto-enroll and workaround systemd/systemd#30164: https://github.com/t184256/nix-configs/blob/c48e6583f56fcb9ca1dbcf527fe96ea43b76b79a/hosts/quince/secureboot.nix Hope that'd be of help for the next soul who ends up figuring these bits out. |
fwiw, my auto cryptenroll config: boot.lanzaboote = {
enable = true;
pkiBundle = "/etc/secureboot";
package = lib.mkForce (pkgs.writeShellApplication {
name = "lzbt";
runtimeInputs = with pkgs; [ coreutils binutils vim openssl jq ];
text = let
systemd-pcr-value = pkgs.systemd.overrideAttrs (old: {
patches = old.patches ++ [
(pkgs.fetchpatch {
url = "https://github.com/systemd/systemd/pull/28398.patch";
hash = "sha256-VCDB8tdkBiG0eOlSN5PS4cYkOxl0BtiORxmrfpRKoKo=";
})
(pkgs.fetchpatch {
url = "https://github.com/systemd/systemd/pull/28916.patch";
hash = "sha256-G/cx9RsVhah18rNqtmy2fzkfvBFGLXUCuDIby5vaZZ4=";
})
];
});
in ''
set -o pipefail
"${lanzaboote.packages."${pkgs.system}".tool}/bin/lzbt" "$@"
work_dir="$(mktemp -d)"
pushd "$work_dir" > /dev/null
hash_algo=sha256
hash_len="$(openssl "$hash_algo" -binary /dev/null | wc -c)"
stub_path="$(bootctl list --json pretty | jq -r '.[] | select(.isDefault) | .path')"
section_names=".linux .osrel .cmdline .initrd .splash .dtb .pcrsig .pcrpkey"
head -c "$hash_len" /dev/zero > pcr
for section_name in $section_names; do
objcopy -O binary --dump-section "$section_name=section$section_name" "$stub_path" /dev/null
if [ ! -f "section$section_name" ]; then
continue
fi
cat pcr <(openssl "$hash_algo" -binary "section$section_name") | openssl "$hash_algo" -binary -out pcr_new
echo "pcr old=$(xxd -p -c0 pcr) new=$(xxd -p -c0 pcr_new)"
mv pcr_new pcr
done
"${systemd-pcr-value}/bin/systemd-cryptenroll" \
"${config.boot.initrd.luks.devices."cryptroot".device}" \
--wipe-slot tpm2 --tpm2-device auto --tpm2-pcrs "7+11:$hash_algo=$(xxd -p -c0 pcr)" \
--unlock-key-file /etc/nixos/credentials/luks/root
popd > /dev/null
rm -rf "$work_dir"
'';
});
}; The systemd patches are for specifying pcr values to systemd-cryptenroll --tpm2-pcrs. Once nixpkgs has systemd v255, these patches will no longer be required and we can probably use systemd-pcrlock to avoid keeping a key file on disk or entering recovery key every time upgrading. Note that currently lanzaboote's support for measuring kernel image into pcr 11 is only available in master branch, and it is still wip. It only measures .osrel and .cmdline, not kernel and initrd sections. See #167, #168. Don't use it in production environment. Once support for systemd-stub compatible measurement is complete, I guess systemd-measure can be used to replace manual calculation of pcr values. |
As someone going through the process of migrating from LUKS1 to LUKS2 in order to use the TPM to decrypt my drives instead of manually entering a password, is it secure to simply bind to PCRs 0,2, and 7 and call it a day? If so, why, and if not, why not? |
🙄 define your threat model, put yourself into the attacker's shoes, arrive at the answer. if you want to discuss that, please use some discussions space that's not an issue tracker. |
I fully agree with the stated goal of wanting TPM-based disk locking to "just work" across generation changes/kernel, initrd, and bootloader updates. Having post-installation hooks is probably also useful for many things, but I believe there is a better solution for this particular goal. That said, I'm not an expert on the TPM, so take this with a grain of salt. The setup described above binds a TPM secret to a particular set of PCRs that change on an upgrade. Hence the need to re-enroll the secret any time the PCRs change. Instead, it is possible to bind the secret indirectly. From systemd-cryptenroll docs:
It is my understanding that this can be combined with the My understanding of the flow is as follows:
Having written all of this, I have now also discovered that #169 already exists so work seems to be underway :-) I'll still leave this comment in the hope that it helps someone perusing the issue tracker. |
I should reiterate: In most cases, simply binding to PCR 7 will be sufficient for a securely locked disk that needs no re-enrollment on upgrades. This works because PCR 7 is essentially validating that your secure boot chain was honored. i.e. Only your self-signed OS can unlock it. Even if you've enrolled MS keys, the first time an individual key is used to validate a boot phase, it is measured into PCR 7, so MS-signed OSes won't be able to unlock your disk. I'm not really a fan of the |
Systemd recommends using PCRs 7+11.
|
I want to auto-unlock LUKS encrypted system drive only when the computer boots NixOS installed to an SSD. For that I need to run
systemd-cryptenroll /dev/nvme0n1p1 --tpm2-device=auto --tpm2-pcrs=0+2+4+7
There appears to be no way to run custom commands when lanzaboote bootloader is installed:lanzaboote/nix/modules/lanzaboote.nix
Lines 54 to 67 in 367d367
Can we add custom command option to the module that runs only when bootloader is updated?
The text was updated successfully, but these errors were encountered: