[systemd-devel] PCR signing / enrolling on UKI and validation by systemd-cryptenroll
Hi everybody, For some time now I have been using UKIs, with SB enabled and tying FDE decryption on PCRs 7+11+14, with the PCR 11 being measured during UKI creation. Then, I use systemd-cryptenroll to update the secret: PCR11=$(/usr/lib/systemd/ukify -c /etc/kernel/uki.conf --measure --output=/tmp/arch-linux.efi build | grep 11:sha256) systemd-cryptenroll --unlock-key-file=/root/creds/fdepassword.txt --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=7+11:sha256=d05ee4...+14 /dev/nvme0n1p5 This works, flawlessly. Now, I am exploring the possibility to not bind to the value of those PCRS but to their signature, given that I am also embedding that in the UKI (the correspondent .pcrsig section is in place). However, I am a bit lost: * in .pcrsig there is only the signature for pcr11, and there seems to be no way to embed the signatures for other PCR values. * when used in cryptenroll, how should I use this? So far, seems should be a call like systemd-cryptenroll --unlock-key-file=/root/creds/fdepassword.txt --wipe-slot=tpm2 --tpm2-device=auto --tpm2-public-key=/root/creds/tpm2-pcr-public.pem --tpm2-public-key-pcrs= ... but then I do not see what should be provided in tpm2-public-key-pcrs. The same values I am currently giving to --tpm2-pcrs? the signatures that I get from the .pcrsig for 11 + the calculated signatures for the current values of the PCRs 7 and 14? Thank you very much for your time, -- Felix Rubio
[systemd-devel] unlocking LUKS volume using PCRs and UKI
Hi everybody, Some months ago I tried to learn about systemd cryptenroll, ukify, etc., and I managed to get a UKI that gets updated every time the kernel / modules change by running: ## /usr/lib/systemd/ukify --linux /boot/vmlinuz-linux --initrd /boot/amd-ucode.img --initrd /boot/initramfs-linux.img \ --os-release=@$OSRELEASE \ --cmdline="$CMDLINE" \ --secureboot-certificate=/root/SecureBoot/MOK.crt --secureboot-private-key=/root/SecureBoot/MOK.key \ --output=$OUTPUTPATH/$UKIFILE build ## To set up the unlock of the disk, I ran the following command (only once, as pcrs 7 and 14 have not changed since then): systemd-cryptenroll --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=7+14 /dev/nvme0n1p5 Since then, systemd-cryptenroll has been extended so that literal values can be provided, meaning that (*I think*) I can upgrade my previous process to: ## PCR11=$(/usr/lib/systemd/ukify --linux /boot/vmlinuz-linux --initrd /boot/amd-ucode.img --initrd /boot/initramfs-linux.img \ --os-release=@$OSRELEASE \ --cmdline="$CMDLINE" \ --secureboot-certificate=/root/SecureBoot/MOK.crt --secureboot-private-key=/root/SecureBoot/MOK.key \ --measure \ --phases="enter-initrd" \ --pcr-private-key=/root/SecureBoot/PCRsigning/tpm2-pcr-private.pem \ --pcr-public-key=/root/SecureBoot/PCRsigning/tpm2-pcr-public.pem \ --output=$OUTPUTPATH/$UKIFILE build | grep 11:sha256) systemd-cryptenroll --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=7+$PCR11+14 /dev/nvme0n1p5 ## Do you guys think this is a sensible approach? As I want to bind the unlock of the disk to PCR11, I think I only need to get the measurement of that PCR register in the "enter-initrd" phase, right? What are the implications of providing as well the pcr-private-key parameter? I have gone through the documentation of systemd-cryptenroll, systemd-measure and systemd's ukify, but is not clear to me if this set of flags will (besides providing the measurement I am interested on) also let the kernel continue booting only if the signed policy that gets calculated out of that register is fulfilled. Should that be the case, this additional control will not harm but I guess is a bit redundant for my use case? Thank you very much for your time, -- Felix Rubio "Don't believe what you're told. Double check."
[systemd-devel] Help debugging the access to a hashmap object
Hi everybody, I am kind of lost, and after some hours giving a look at the issue... maybe somebody can give me a hand? I am working on the PR https://github.com/systemd/systemd/pull/28339, to provide a way to specify literals for the PCRs. As part of this PR I am creating a hashmap of hashmaps, in which keys are strings (for the container hashmap, the banks: e.g., "sha256", and for the contained hashmap the pcr index: e.g., "11"). My problem is that in my test I populate PCR idx 11 and I get the following debugging output from hashmap_get (which I call right after storing it): HM: 0x55b0b5524c88 11 1 1 In which 0x55bc13fc0c88 is the pointer to the bank, 11 is the pcr_idx, and 1 and 1 are respectively the hash and idx as found by _hashmap_get in hashmap.c:1359 in my branch. Should I use either a parameter pointer for "11" or a constant, there is no difference: it works as expected. So far so good. Now, should I call it from another method (in this case, a method I use to generate the mask out of all the keys in the map), what I get is quite different: HM: 0x55b0b5524c88 11 1 4294967295 in which the idx is 4294967295 ==> IDX_NIL. In both cases, I am calling hashmap_get like this: TPM2B_DIGEST *v2 = hashmap_get(bank, "11"); First I thought that somehow the value was being deleted, so then I decided to print all the keys for that hashmap (expecting to find none, as I only set one entry). In this case, what I run, right after setting the element and on the other function, is: int *k; TPM2B_DIGEST *v; HASHMAP_FOREACH_KEY(v, k, bank) { _cleanup_free_ char *hex = NULL; hex = hexmem(v->buffer, v->size); fprintf(stderr, "%p %d %s\n", bank, *k, hex); } and what I obtained is: IN : 0x55b0b5524c88 1526739249 3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969 OUT: 0x55b0b5524c88 892625971 3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969 So: I am getting the same pointer for the bank, the hex value for the PCR is correct, but the key is different: the entry is not lost, just seems to be relocated? How is this possible? Thank you in advance, if anybody can point out what am I doing wrong... :-/.
Re: [systemd-devel] Systemd-cryptsetup triggers a black screen after upgrading to 6.4.1
Nope: AMD Ryzen 7 6800H, But thank you for the suggestion! Felix On 2023-07-07 09:07, Christian Hesse wrote: Felix Rubio on Thu, 2023/07/06 18:07: Using arch linux, I have had my kernel upgraded from 6.3.9 to 6.4.1. After regenerating the UKI, that works, I get just a black screen when systemd-cryptsetup should be either using the TPM to unlock the drive or to ask me the rescue password. Possibly running on a Framework laptop with Intel 12th gen or later? https://bugs.archlinux.org/task/78961 https://bugzilla.kernel.org/show_bug.cgi?id=217631
[systemd-devel] Systemd-cryptsetup triggers a black screen after upgrading to 6.4.1
Using arch linux, I have had my kernel upgraded from 6.3.9 to 6.4.1. After regenerating the UKI, that works, I get just a black screen when systemd-cryptsetup should be either using the TPM to unlock the drive or to ask me the rescue password. Luckily I have an old UKI with 6.3.9 (also the correspondent /lib/modules) so that I can boot with the old one, but the question is: any idea on how to debug this issue? I had the same problem previously, which I could trace back to the upgrade of linux-firmware and that got fixed two days later when the same package got updated, but now I have checked and there's been no update about that. Is there any way to set systemd in verbose mode, so that I get more information before the black screen? Thank you, Felix
Re: [systemd-devel] Enrolling PCR11 does not work as expected
In order to achieve the check of a number of PCRs, what do you guys think of this approach? 1. When running ukify, add the "measure" flag so that the expected value of the PCR11 is printed. 2. Then, script the reset of an unused PCR (in my case, 23), and the extend it with the current value of PCRs 7 and 14, and the expected value of PCR 11 3. Run systemd-cryptenroll against PCR 23 4. add a configuration drop to /etc/systemd/system/systemd-cryptsetup@.service.d, so that at ExecPre a similar script of that in 2 is run, but in this case resetting PCR 23 and extending it with the actual values of PCRs 7, 14 and 11. Do you guys this approach is sound? Thank you, Felix On 2023-07-05 14:26, Lennart Poettering wrote: On Mi, 05.07.23 13:11, Felix Rubio (fe...@kngnt.org) wrote: For what is explained on the the systemd-pcrphase.service(8) and comparing it to what I see in the log of the systemd services, there are three events in relation to this question: systemd-pcrphase-initrd.service [...] [systemd-ask-password-console.service] [...] systemd-pcrphase-sysinit systemd-pcrphase This means that, indeed, running cryptenroll after the new kernel has booted will never provide the correct PCR registry for 11. But then... what options do I have? Do I need to choose between having PCRs 7 and 14, so that I make sure that SB is up and running and all the certs from shim have not changed, or to have only PCR 11 so that I know that the UKI has not changed although SB can potentially be even disabled (please, correct me if wrong)? The idea is that with systemd-measure you sign the pre-calculated PCRs for all phases you care about with a key, and then you use enroll the public key that matches that signature in the disk encryption, rather than literal PCR values. Using signed PCR policies enables you to do multiple things at once: 1. You can easily enroll one public key, and have it cover multiple phases of the boot, simply by providing multiple signatures for the PCR values expected in the various boot phases. 2. You can easily enroll one public key, and then update the UKI and still boot up correctly, by providing a new set of signatures for the new expected PCR values for the various boot phases. Hence, the PCR 11 logic we have in place is *not* designed with TPM policies that bind to explicit PCR values in mind. Instead it is designed in mind with policies that bind to public keys that match signatures of those PCR values. Lennart -- Lennart Poettering, Berlin
Re: [systemd-devel] Enrolling PCR11 does not work as expected
I understand that, but systemd-measure is only about PCR 11. Is there any way to provide a list of PCRs, so that additionally can be embedded on the UKI? Thank you, Felix On 2023-07-05 14:26, Lennart Poettering wrote: On Mi, 05.07.23 13:11, Felix Rubio (fe...@kngnt.org) wrote: For what is explained on the the systemd-pcrphase.service(8) and comparing it to what I see in the log of the systemd services, there are three events in relation to this question: systemd-pcrphase-initrd.service [...] [systemd-ask-password-console.service] [...] systemd-pcrphase-sysinit systemd-pcrphase This means that, indeed, running cryptenroll after the new kernel has booted will never provide the correct PCR registry for 11. But then... what options do I have? Do I need to choose between having PCRs 7 and 14, so that I make sure that SB is up and running and all the certs from shim have not changed, or to have only PCR 11 so that I know that the UKI has not changed although SB can potentially be even disabled (please, correct me if wrong)? The idea is that with systemd-measure you sign the pre-calculated PCRs for all phases you care about with a key, and then you use enroll the public key that matches that signature in the disk encryption, rather than literal PCR values. Using signed PCR policies enables you to do multiple things at once: 1. You can easily enroll one public key, and have it cover multiple phases of the boot, simply by providing multiple signatures for the PCR values expected in the various boot phases. 2. You can easily enroll one public key, and then update the UKI and still boot up correctly, by providing a new set of signatures for the new expected PCR values for the various boot phases. Hence, the PCR 11 logic we have in place is *not* designed with TPM policies that bind to explicit PCR values in mind. Instead it is designed in mind with policies that bind to public keys that match signatures of those PCR values. Lennart -- Lennart Poettering, Berlin
Re: [systemd-devel] Enrolling PCR11 does not work as expected
For what is explained on the the systemd-pcrphase.service(8) and comparing it to what I see in the log of the systemd services, there are three events in relation to this question: systemd-pcrphase-initrd.service [...] [systemd-ask-password-console.service] [...] systemd-pcrphase-sysinit systemd-pcrphase This means that, indeed, running cryptenroll after the new kernel has booted will never provide the correct PCR registry for 11. But then... what options do I have? Do I need to choose between having PCRs 7 and 14, so that I make sure that SB is up and running and all the certs from shim have not changed, or to have only PCR 11 so that I know that the UKI has not changed although SB can potentially be even disabled (please, correct me if wrong)? Thank you! Felix On 2023-07-05 10:36, Lennart Poettering wrote: On Mi, 05.07.23 08:30, Felix Rubio (fe...@kngnt.org) wrote: Hi everybody, In my setup (sd-boot+UKI+LUKS) I am using PCRs 7+11+14 to unlock the LUKS drive. Should I use only PCRs 7+14 everything works, but when I add 11 I need to provide the rescue password every single time I boot. I have extracted the values of those PCRs using tpm2_pcrread in two consecutive boots, and they are equal, so at least the issue is reproducible. To enroll the PCRs, after a new kernel (and, therefore, the UKI) has been generated, I run the following command: systemd-cryptenroll --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=7+11+14 After reading the documentation on systemd-measure (that I am not using at the moment): could it be that there are events added to PCR 11 after the unlocking has happened, so that I am enrolling the wrong PCR value? Otherwise... what am I doing wrong? We mesaure the "boot phase" into PCR 11 too. See systemd-pcrphase.service(8) for details. Generally the assumption is that PCR 11 is used for signed PCR policies, i.e. under vendor control. Lennart -- Lennart Poettering, Berlin
[systemd-devel] Enrolling PCR11 does not work as expected
Hi everybody, In my setup (sd-boot+UKI+LUKS) I am using PCRs 7+11+14 to unlock the LUKS drive. Should I use only PCRs 7+14 everything works, but when I add 11 I need to provide the rescue password every single time I boot. I have extracted the values of those PCRs using tpm2_pcrread in two consecutive boots, and they are equal, so at least the issue is reproducible. To enroll the PCRs, after a new kernel (and, therefore, the UKI) has been generated, I run the following command: systemd-cryptenroll --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=7+11+14 After reading the documentation on systemd-measure (that I am not using at the moment): could it be that there are events added to PCR 11 after the unlocking has happened, so that I am enrolling the wrong PCR value? Otherwise... what am I doing wrong? Felix
[systemd-devel] How to tie the unlocking of a LUKS device to multiple PCRs, when one of them is calculated?
Hi everybody, systemd-cryptenroll can seal/unseal the LUKS key in the TPM predicted to the state of some registers, e.g.: systemd-cryptenroll --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=7+11+14 The problem is that this requires, when there are kernel / bootloader / ... updates, to restart the system, unlock manually and run the command again to enroll the new pcr values. As discussed in this mailing list, the way to go to ensure that both the kernel and initramfs are checked is to use UKI, whose expected PCR 11 state can be calculated by systemd-measure (examples from https://www.freedesktop.org/software/systemd/man/systemd-measure.html): * To generate the signature: systemd-measure sign --linux=vmlinux --osrel=os-release.txt --cmdline=cmdline.txt \ --initrd=initrd.cpio --splash=splash.bmp --dtb=devicetree.dtb --pcrpkey=tpm2-pcr-public.pem \ --bank=sha1 --bank=sha256 --private-key=tpm2-pcr-private.pem \ --public-key=tpm2-pcr-public.pem >tpm2-pcr-signature.json.tmp * To embed the signature on the image: ukify --output foo.efi --os-release @os-release.txt --cmdline @cmdline.txt --splash splash.bmp \ --devicetree devicetree.dtb --pcr-private-key tpm2-pcr-private.pem \ --pcr-public-key tpm2-pcr-public.pem --pcr-banks sha1,sha256 vmlinux initrd.cpio * To enroll the PCR policy: systemd-cryptenroll --tpm2-device=auto --tpm2-public-key=tpm2-pcr-public.pem --tpm2-signature=tpm2-pcr-signature.json This process binds the unsealing of the LUKS decryption key to the PCR 11, but is not clear how (or even if it is possible) to add other PCRs to the mix (those being 7 and 14, in my case). To compare, this is what I was doing when dealing directly with the TPM (so, before switching to systemd), creating two policies and combining them with a policyor: # session for auth based on pcr tpm2_startauthsession -S session.ctx tpm2_policypcr -S session.ctx -L regular.policy -l sha256:0,1,7,9 tpm2_policypassword -S session.ctx -L regular.policy tpm2_flushcontext session.ctx # session for auth based on rescue password tpm2_startauthsession -S session.ctx tpm2_policysecret -S session.ctx -L rescue.policy -c o '' tpm2_flushcontext session.ctx # compound both policies using OR tpm2_startauthsession -S session.ctx tpm2_policyor -S session.ctx -L compound.policy sha256:rescue.policy,regular.policy tpm2_flushcontext session.ctx # create the seal object tpm2_create -C prim.ctx -c key.ctx -u key.pub -r key.priv -L compound.policy -i- -p '' -a 'fixedtpm|fixedparent' Is there any way to do something similar with systemd-cryptenroll? Regards! -- Felix
Re: [systemd-devel] sd-boot setup and PCRs
Hi Lennart, Andrei, Adrian Understood, and thank you very much :-) then 7+11+14 it is. Regards! --- Felix Rubio "Don't believe what you're told. Double check." On 2023-06-19 17:21, Lennart Poettering wrote: On So, 18.06.23 20:56, Felix Rubio (fe...@kngnt.org) wrote: Hi everybody, After some days offline, today I have gone through the emails exchanged a couple of weeks ago and agreed: UKI is the way to go. Last time I checked about it I read about possible problems related to when some modules would be loaded and so, but I see that my knowledge was outdated. This said, right now my setup looks like: SecureBoot is enabled, I am using Shim, Systemd-Boot as shim's second stage, and a UKI. As the disk is encrypted, for now I am making the decryption predicated to PCRs 7 and 14, so that the decryption will only fail when either SB state changes, or when shim certificates/hashes change. So far so good. Out of curiosity now, I am wondering: what would happen in case somebody boots the system from, e.g., a USB drive that contains a signed image? Even if the shim is the same version, I assume it will fail to unlock because the MOK will not contain my certificate? Should that certificate had been stolen and present, be enough to then unlock the disk? MOK is persisted in an EFI var, hence it doesn't matter what you boot from, the MOK db will be the same. Hence if that UKI on the usb drive is signed by some key that is in your MOK then this will just be accepted and get access to your keys. I am trying to assess if I should put in the mix PCR 4, so that I can keep track of the UKI image that gets loaded. Do you guys think this would be needed, or is overkill? If you use UKIs, bind to the signature for PCR 11. Lennart -- Lennart Poettering, Berlin
Re: [systemd-devel] sd-boot setup and PCRs
Hi Andrei, In that case, could happen that a malicious actor that has had in the past access to the systemd-boot, shim, and the UKI, comes back with those 3 on a USB stick and boots the machine? Then it would indeed make sense to bind the LUKS key to PCR 4, this making it 4+7+14, so that the use of outdated UKI is not possible. Thank you! Felix On 2023-06-19 14:04, Andrei Borzenkov wrote: On 19.06.2023 10:19, Felix Rubio wrote: "Signed by whom?" - Signed by an actor trusted by Secure Boot, either at the platform level, or by any of the Shim contributors (I have not checked yet if it comes with a list of certificates, or only contains the one I enrolled) "What is \"your certificate\"?" - The one I generated and enrolled into MOK. In this case PCR 14 will not change. PCR 4 will include measurement of the binary loaded by shim. So if you place the same version of systemd-boot binary on USB it is up to the systemd-boot. The shim readme states that PCR 4 will be extended with "the hash of any binary for which Verify is called through the shim_lock protocol". So as long as systemd-boot calls shim to verify UKI you need the same UKI binary to unlock encrypted device. Which is not much different from simply booting from hard disk. I am not familiar with details of UKI implementation, but if it is possible to override kernel command line, you can trivially boot into /bin/sh unless you also bind LUKS key to the PCR 12 (or whatever is used to measure kernel parameters). Regards! Felix On 2023-06-19 06:26, Andrei Borzenkov wrote: On 18.06.2023 21:56, Felix Rubio wrote: Hi everybody, After some days offline, today I have gone through the emails exchanged a couple of weeks ago and agreed: UKI is the way to go. Last time I checked about it I read about possible problems related to when some modules would be loaded and so, but I see that my knowledge was outdated. This said, right now my setup looks like: SecureBoot is enabled, I am using Shim, Systemd-Boot as shim's second stage, and a UKI. As the disk is encrypted, for now I am making the decryption predicated to PCRs 7 and 14, so that the decryption will only fail when either SB state changes, or when shim certificates/hashes change. So far so good. Out of curiosity now, I am wondering: what would happen in case somebody boots the system from, e.g., a USB drive that contains a signed image? Signed by whom? Even if the shim is the same version, I assume it will fail to unlock because the MOK will not contain my certificate? What is "your certificate"? Should that certificate had been stolen and present, be enough to then unlock the disk? I am trying to assess if I should put in the mix PCR 4, so that I can keep track of the UKI image that gets loaded. Do you guys think this would be needed, or is overkill? Regards, Felix
Re: [systemd-devel] sd-boot setup and PCRs
"Signed by whom?" - Signed by an actor trusted by Secure Boot, either at the platform level, or by any of the Shim contributors (I have not checked yet if it comes with a list of certificates, or only contains the one I enrolled) "What is \"your certificate\"?" - The one I generated and enrolled into MOK. Regards! Felix On 2023-06-19 06:26, Andrei Borzenkov wrote: On 18.06.2023 21:56, Felix Rubio wrote: Hi everybody, After some days offline, today I have gone through the emails exchanged a couple of weeks ago and agreed: UKI is the way to go. Last time I checked about it I read about possible problems related to when some modules would be loaded and so, but I see that my knowledge was outdated. This said, right now my setup looks like: SecureBoot is enabled, I am using Shim, Systemd-Boot as shim's second stage, and a UKI. As the disk is encrypted, for now I am making the decryption predicated to PCRs 7 and 14, so that the decryption will only fail when either SB state changes, or when shim certificates/hashes change. So far so good. Out of curiosity now, I am wondering: what would happen in case somebody boots the system from, e.g., a USB drive that contains a signed image? Signed by whom? Even if the shim is the same version, I assume it will fail to unlock because the MOK will not contain my certificate? What is "your certificate"? Should that certificate had been stolen and present, be enough to then unlock the disk? I am trying to assess if I should put in the mix PCR 4, so that I can keep track of the UKI image that gets loaded. Do you guys think this would be needed, or is overkill? Regards, Felix
[systemd-devel] sd-boot setup and PCRs
Hi everybody, After some days offline, today I have gone through the emails exchanged a couple of weeks ago and agreed: UKI is the way to go. Last time I checked about it I read about possible problems related to when some modules would be loaded and so, but I see that my knowledge was outdated. This said, right now my setup looks like: SecureBoot is enabled, I am using Shim, Systemd-Boot as shim's second stage, and a UKI. As the disk is encrypted, for now I am making the decryption predicated to PCRs 7 and 14, so that the decryption will only fail when either SB state changes, or when shim certificates/hashes change. So far so good. Out of curiosity now, I am wondering: what would happen in case somebody boots the system from, e.g., a USB drive that contains a signed image? Even if the shim is the same version, I assume it will fail to unlock because the MOK will not contain my certificate? Should that certificate had been stolen and present, be enough to then unlock the disk? I am trying to assess if I should put in the mix PCR 4, so that I can keep track of the UKI image that gets loaded. Do you guys think this would be needed, or is overkill? Regards, Felix
Re: [systemd-devel] why systemd-boot (seems as everyone else) does not check the signatures of initramfs?
Just to close this off, because you guys have spend time in helping me navigate through this: Finally I decided to go for FDE based on the TPM. Then, most of my concerns where addressed by using PCRs 0,1,7 and 9, so that initramfs gets also measured. This allows me to keep a separate boot partition, and to not get involved yet with UKI. Now I am trying to work out a way to smooth the case when after a kernel / modules update the TPM state changes and will not unlock automatically... but this for another day, I guess :-) Thank you very much for you help! -- Felix Rubio "Don't believe what you're told. Double check." On 2023-05-27 08:31, Felix Rubio wrote: Hi Lennart, I remember having read some time ago that UKI could pose problems with early-boot modules provided by vendors and so. But... let's give it a try! Then, the process should be: 1. Install a version of shim signed with MS keys. 2. Generate the UKI 3. rename the UKI image to grubx64.efi so that it gets picked up by shim As a side: the ESP partition is bit small. Do you think if I introduce systemd-boot I could load the UKI being stored from /boot? In that case this would be like 1. Install a version of shim signed with MS keys. 2. Install systemd-boot as grubx64.efi so that it gets picked up by shim 3. Generate the UKI to /boot/ I will give it a try... and see how it goes. Regards! -- Felix Rubio "Don't believe what you're told. Double check." On 2023-05-25 10:26, Lennart Poettering wrote: On Mi, 24.05.23 19:01, Felix Rubio (fe...@kngnt.org) wrote: Hi Lennart, "Sorry, but GPG is a no-go. Not in 2023." Yes, I understand that. What I am trying to get is a simple way to verify that the initramfs has not been tampered with. UKI comes with its own challenges, using encryption tied to a measured boot looks overkill, and I fully agree in which adding an authentication layer is not desirable. I am not sure what "challenges" you specifically have in mind, but a UKI with an initrd in a PE envelope (i.e. the "add-on" concept I mentioned), then you should be pretty close to current behaviour, no? Then... what alternatives are available for just performing verification of the initramfs? I was giving a look at IMA now, so this could be sorted with a policy... but I think this is not supported in sd-boot. IMA verifies files after the kernel is up, not before. It's not suitable for validating initrds. Anway, you should really ask yourself what cryptographic key you want to authenticate against. Local or vendor one, and where shall it be stored. That dictates your choices more than anything else. In the case I wrap the initramfs on a PE envelope, as you suggested, when then its signature be validated automatically? when it gets loaded? Because, if so... this would work enough for this use case. In the "add-on" module for UKIs I mentioned the validation of both the UKI and the add-ons are done via regular UEFI SecureBoot or via shim. Both UKIs and add-ons are just PE files after all that thus can be verified that way. Because the files can be authenticated via shim you get MOK and so on. Lennart -- Lennart Poettering, Berlin
Re: [systemd-devel] why systemd-boot (seems as everyone else) does not check the signatures of initramfs?
Hi everybody, Continuing the work/learning path I started last week, I have had a development: Still with shim loading systemd-boot, which can read the kernel and initramfs from XBOOTLDR partition, I have introduced LUKS to encrypt the root partition (XBOOTLDR is not encrypted). Originally I was planning to move from this to UKI so that I can make sure that both kernel and initramfs are checked before booting, but today I have considered a different course of action: Should I use the TPM to store a key to decrypt the disk like this: systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+1+7+9 Then, by using PCR9 the initrd would be checked before allowing the boot sequence to continue. By doing this, then, I do not have to switch to UKI until I have learned more about it. Do you guys think this reasoning is flawed? Thank you, --- Felix Rubio "Don't believe what you're told. Double check." On 2023-05-25 10:26, Lennart Poettering wrote: On Mi, 24.05.23 19:01, Felix Rubio (fe...@kngnt.org) wrote: Hi Lennart, "Sorry, but GPG is a no-go. Not in 2023." Yes, I understand that. What I am trying to get is a simple way to verify that the initramfs has not been tampered with. UKI comes with its own challenges, using encryption tied to a measured boot looks overkill, and I fully agree in which adding an authentication layer is not desirable. I am not sure what "challenges" you specifically have in mind, but a UKI with an initrd in a PE envelope (i.e. the "add-on" concept I mentioned), then you should be pretty close to current behaviour, no? Then... what alternatives are available for just performing verification of the initramfs? I was giving a look at IMA now, so this could be sorted with a policy... but I think this is not supported in sd-boot. IMA verifies files after the kernel is up, not before. It's not suitable for validating initrds. Anway, you should really ask yourself what cryptographic key you want to authenticate against. Local or vendor one, and where shall it be stored. That dictates your choices more than anything else. In the case I wrap the initramfs on a PE envelope, as you suggested, when then its signature be validated automatically? when it gets loaded? Because, if so... this would work enough for this use case. In the "add-on" module for UKIs I mentioned the validation of both the UKI and the add-ons are done via regular UEFI SecureBoot or via shim. Both UKIs and add-ons are just PE files after all that thus can be verified that way. Because the files can be authenticated via shim you get MOK and so on. Lennart -- Lennart Poettering, Berlin
Re: [systemd-devel] why systemd-boot (seems as everyone else) does not check the signatures of initramfs?
Hi Lennart, I remember having read some time ago that UKI could pose problems with early-boot modules provided by vendors and so. But... let's give it a try! Then, the process should be: 1. Install a version of shim signed with MS keys. 2. Generate the UKI 3. rename the UKI image to grubx64.efi so that it gets picked up by shim As a side: the ESP partition is bit small. Do you think if I introduce systemd-boot I could load the UKI being stored from /boot? In that case this would be like 1. Install a version of shim signed with MS keys. 2. Install systemd-boot as grubx64.efi so that it gets picked up by shim 3. Generate the UKI to /boot/ I will give it a try... and see how it goes. Regards! -- Felix Rubio "Don't believe what you're told. Double check." On 2023-05-25 10:26, Lennart Poettering wrote: On Mi, 24.05.23 19:01, Felix Rubio (fe...@kngnt.org) wrote: Hi Lennart, "Sorry, but GPG is a no-go. Not in 2023." Yes, I understand that. What I am trying to get is a simple way to verify that the initramfs has not been tampered with. UKI comes with its own challenges, using encryption tied to a measured boot looks overkill, and I fully agree in which adding an authentication layer is not desirable. I am not sure what "challenges" you specifically have in mind, but a UKI with an initrd in a PE envelope (i.e. the "add-on" concept I mentioned), then you should be pretty close to current behaviour, no? Then... what alternatives are available for just performing verification of the initramfs? I was giving a look at IMA now, so this could be sorted with a policy... but I think this is not supported in sd-boot. IMA verifies files after the kernel is up, not before. It's not suitable for validating initrds. Anway, you should really ask yourself what cryptographic key you want to authenticate against. Local or vendor one, and where shall it be stored. That dictates your choices more than anything else. In the case I wrap the initramfs on a PE envelope, as you suggested, when then its signature be validated automatically? when it gets loaded? Because, if so... this would work enough for this use case. In the "add-on" module for UKIs I mentioned the validation of both the UKI and the add-ons are done via regular UEFI SecureBoot or via shim. Both UKIs and add-ons are just PE files after all that thus can be verified that way. Because the files can be authenticated via shim you get MOK and so on. Lennart -- Lennart Poettering, Berlin
Re: [systemd-devel] why systemd-boot (seems as everyone else) does not check the signatures of initramfs?
Hi Lennart, "Sorry, but GPG is a no-go. Not in 2023." Yes, I understand that. What I am trying to get is a simple way to verify that the initramfs has not been tampered with. UKI comes with its own challenges, using encryption tied to a measured boot looks overkill, and I fully agree in which adding an authentication layer is not desirable. Then... what alternatives are available for just performing verification of the initramfs? I was giving a look at IMA now, so this could be sorted with a policy... but I think this is not supported in sd-boot. In the case I wrap the initramfs on a PE envelope, as you suggested, when then its signature be validated automatically? when it gets loaded? Because, if so... this would work enough for this use case. Thank you --- Felix Rubio "Don't believe what you're told. Double check." On 2023-05-24 18:11, Lennart Poettering wrote: On Mi, 24.05.23 16:20, Felix Rubio (fe...@kngnt.org) wrote: Hi Andrei, Lennart @Andrei: Do you think, then, that the same private key used for SecureBoot could be used for GPG signing the initramfs? That would be cool, as the whole boot signing infrastructure would still depend on a single entity. @Lennart: I was thinking in using a private key for which I'd enroll the certificate in MOK (I mean, just following the standard use case for MOK). Without having much idea about the code base of systemd-boot, I am willing to give it a try (to a GPG with private key from SB) provided you think is something the community might benefit from. What are your thoughts? Sorry, but GPG is a no-go. Not in 2023. But also I am not sure I understand what are you trying to do? Note that shim only authenticates PE binaries, hence you'd have to wrap your initrd in a PE binary anyway to validate an initrd against MOK. And we really don#t want to add another layer of authentication in sd-boot, let's leave that in uefi sb firmware + shim. i.e. we expressly don#t want to embedd a crypto stack like grub. And even if we could we don't get access to MOK iirc, shim makes that impossible for later boot components. If you wrap your initrd in a PE envelope this is pretty much exactly what UKIs are. – Also note that there's currently a PR pending that allows wrapping kernel command lines in separate PE files which can be read by a UKI, a concept we call "add-on", which would we could extend to initrds too i guess, see https://github.com/systemd/systemd/pull/27358 Lennart -- Lennart Poettering, Berlin
Re: [systemd-devel] why systemd-boot (seems as everyone else) does not check the signatures of initramfs?
Hi Andrei, Lennart @Andrei: Do you think, then, that the same private key used for SecureBoot could be used for GPG signing the initramfs? That would be cool, as the whole boot signing infrastructure would still depend on a single entity. @Lennart: I was thinking in using a private key for which I'd enroll the certificate in MOK (I mean, just following the standard use case for MOK). Without having much idea about the code base of systemd-boot, I am willing to give it a try (to a GPG with private key from SB) provided you think is something the community might benefit from. What are your thoughts? Regards, -- Felix Rubio "Don't believe what you're told. Double check." On 2023-05-24 14:35, Lennart Poettering wrote: On Mi, 24.05.23 12:22, Felix Rubio (fe...@kngnt.org) wrote: I agree that having a measured boot, that decrypts the system is a better solution... but this is, correct me if wrong, still very green: There are some approaches supported, but none of them seems to be structural: they rely on the existence of a TPM, introduce additional dependencies on the update process (when the kernel/initramfs changes the previous measurement will not be correct anymore and needs to be updated), etc. On the other hand UKI comes with its own challenges, and also forces the admin to rebuild the UKI any time there is an update. I feel there should be some middle point in which we do not have to rely on a TPM and a fully measured system, but we can still make sure that the initramfs is trusted. The question, then, is: Is this something that could be supported in systemd-boot, or this is something that is considered to be just out of scope? As in the other mail: Which key do you intend to use for validation? Note that in systemd git main there's already support for generating UKIs dynamically when a kernel RPM/DEB is installed (as long as the "kernel-install" infra is in use). It can be signed with a local key, that can be enrolled with MOK. With that we make it reasonably easy to run a setup with a locally signed initrd – but it means that you'll get a MOK prompt during at least one boot. Lennart -- Lennart Poettering, Berlin
Re: [systemd-devel] why systemd-boot (seems as everyone else) does not check the signatures of initramfs?
Hi Andrei, Thank you for correcting my statement about Grub2, I did not know that. I agree that having a measured boot, that decrypts the system is a better solution... but this is, correct me if wrong, still very green: There are some approaches supported, but none of them seems to be structural: they rely on the existence of a TPM, introduce additional dependencies on the update process (when the kernel/initramfs changes the previous measurement will not be correct anymore and needs to be updated), etc. On the other hand UKI comes with its own challenges, and also forces the admin to rebuild the UKI any time there is an update. I feel there should be some middle point in which we do not have to rely on a TPM and a fully measured system, but we can still make sure that the initramfs is trusted. The question, then, is: Is this something that could be supported in systemd-boot, or this is something that is considered to be just out of scope? Thank you --- Felix Rubio "Don't believe what you're told. Double check." On 2023-05-23 21:32, Andrei Borzenkov wrote: On 23.05.2023 21:54, Felix Rubio wrote: Hi everybody, I am trying to understand something, and after looking around I have not found any explicit answer. Maybe somebody in this list can shed some light on the matter? I have a laptop in which I am setting up the boot process through systemd-boot, and this works. Now, I'd like to give a try to enable Secure Boot so that the whole boot sequence is protected against tampering. As I am still learning about the technology, I prefer to land on the use of shim/MOK. For what I have read, the sequence should be: 1. Install a version of shim signed with MS keys. 2. On that same folder copy systemd-bootx64.efi, renamed to grubx64.efi (as shim seems to work only with Grub as 2nd stage loader). 3. Sign the kernel with the key for which the certificate has been enrolled in MOK. 4. Reboot, enroll the keys and... voila. So far, so good... until we hit the initramfs wall: the efi's and kernel signatures are verified, but not that of the initramfs. I have seen that grub2 does not do it (it relies in GPG signatures, in which seems to be a workaround), and I have not found any place stating that systemd-boot GPG is independent alternative method of verifying files and most certainly not a workaround (it was implemented in grub2 long before Secure Boot support). does it. I have seen however, some steering towards the use of UKI... but this comes with its own problems about out-of-tree kernel modules and so. So, the question is: why the kernel image gets verified but not the initramfs? Is this mandated by some standard, or is an engineering decision? Kernel image has verifiable origin (it is signed by the same entity that provides your distribution). It is static and does not change on end user system which makes it possible to sign by maintainers of distribution by a secret key that is hopefully kept secret. initrd is volatile, it is usually generated on the same system where it should be verified which means the key to sign it must be kept on the same system as well. Which makes it more probable that secret key will be leaked if system is compromised. And leaked secret key allows installing an arbitrary malware as part of initrd. Measured boot does not have this problem. If you encrypt your root and only allow decrypting if initrd (and kernel and any other data used during boot) has known content then initrd will be implicitly verified and if it is changed system simply fails to boot. This does not require any key management or storing any persistent secret on end system. Downside is that it requires TPM (or some other tamper resistant way to store hashes) so not universally applicable. Thank you very much!
[systemd-devel] why systemd-boot (seems as everyone else) does not check the signatures of initramfs?
Hi everybody, I am trying to understand something, and after looking around I have not found any explicit answer. Maybe somebody in this list can shed some light on the matter? I have a laptop in which I am setting up the boot process through systemd-boot, and this works. Now, I'd like to give a try to enable Secure Boot so that the whole boot sequence is protected against tampering. As I am still learning about the technology, I prefer to land on the use of shim/MOK. For what I have read, the sequence should be: 1. Install a version of shim signed with MS keys. 2. On that same folder copy systemd-bootx64.efi, renamed to grubx64.efi (as shim seems to work only with Grub as 2nd stage loader). 3. Sign the kernel with the key for which the certificate has been enrolled in MOK. 4. Reboot, enroll the keys and... voila. So far, so good... until we hit the initramfs wall: the efi's and kernel signatures are verified, but not that of the initramfs. I have seen that grub2 does not do it (it relies in GPG signatures, in which seems to be a workaround), and I have not found any place stating that systemd-boot does it. I have seen however, some steering towards the use of UKI... but this comes with its own problems about out-of-tree kernel modules and so. So, the question is: why the kernel image gets verified but not the initramfs? Is this mandated by some standard, or is an engineering decision? Thank you very much! -- Felix Rubio "Don't believe what you're told. Double check."
Re: [systemd-devel] setting up systemd-boot with separate EFI and boot partitions
Thank you Lennart. When I separated the /boot from /boot/efi I formatted /boot partition with ext2. After reading your answer I reformatted it to FAT and... all works. Regards! --- Felix Rubio "Don't believe what you're told. Double check." On 2023-05-23 10:51, Lennart Poettering wrote: On Mo, 22.05.23 14:26, Felix Rubio (fe...@kngnt.org) wrote: I have installed arch linux recently, with systemd-boot as boot manager and the EFI partition mounted on /boot. I am wondering how can I mount the EFI partition on /boot/efi, while vmlinuz-linux and initramf remain in /boot? Currently in my /boot/loader/entries/arch.conf I have the following: title Arch Linux linux /vmlinuz-linux initrd /amd-ucode.img initrd /initramfs-linux.img options root=PARTUUID= rw On this setup, I guess amd-ucode.img must remain in /boot/efi, but how can I specify that vmlinuz-linux and initramfs-linux.img are in another partition, if possible at all? sd-boot is an EFI program that uses EFI APIs to access file systems, hence it only generally supports FAT. It will look in the ESP as well as in XBOOTLDR. Thus is you mark your /boot/ partition as XBOOTLDR and format it is vfat it should just work. Lennart -- Lennart Poettering, Berlin
[systemd-devel] setting up systemd-boot with separate EFI and boot partitions
I have installed arch linux recently, with systemd-boot as boot manager and the EFI partition mounted on /boot. I am wondering how can I mount the EFI partition on /boot/efi, while vmlinuz-linux and initramf remain in /boot? Currently in my /boot/loader/entries/arch.conf I have the following: title Arch Linux linux /vmlinuz-linux initrd /amd-ucode.img initrd /initramfs-linux.img options root=PARTUUID= rw On this setup, I guess amd-ucode.img must remain in /boot/efi, but how can I specify that vmlinuz-linux and initramfs-linux.img are in another partition, if possible at all? Regards, -- Felix Rubio "Don't believe what you're told. Double check."