summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mkosi.conf3
-rw-r--r--mkosi.uki-profiles/profile1.conf7
-rw-r--r--mkosi.uki-profiles/profile2.conf7
-rw-r--r--src/boot/measure.c33
-rw-r--r--src/cryptenroll/cryptenroll-tpm2.c2
-rw-r--r--src/pcrlock/pehash.c16
-rw-r--r--test/TEST-86-MULTI-PROFILE-UKI/meson.build1
-rwxr-xr-xtest/units/TEST-70-TPM2.pcrlock.sh4
-rwxr-xr-xtest/units/TEST-86-MULTI-PROFILE-UKI.sh65
9 files changed, 90 insertions, 48 deletions
diff --git a/mkosi.conf b/mkosi.conf
index b76cefe0df..f2389b7f01 100644
--- a/mkosi.conf
+++ b/mkosi.conf
@@ -33,9 +33,8 @@ CacheDirectory=build/mkosi.cache
BuildSourcesEphemeral=yes
Incremental=yes
-# TODO: Remove when TEST-70-TPM doesn't fail in an image with signed PCRs anymore.
[Validation]
-SignExpectedPcr=no
+SignExpectedPcr=yes
[Content]
ExtraTrees=
diff --git a/mkosi.uki-profiles/profile1.conf b/mkosi.uki-profiles/profile1.conf
new file mode 100644
index 0000000000..3dc39d2534
--- /dev/null
+++ b/mkosi.uki-profiles/profile1.conf
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[UKIProfile]
+Profile=
+ ID=profile1
+ TITLE=Profile Two
+Cmdline=testprofile1=1
diff --git a/mkosi.uki-profiles/profile2.conf b/mkosi.uki-profiles/profile2.conf
new file mode 100644
index 0000000000..d5bd4b6b6a
--- /dev/null
+++ b/mkosi.uki-profiles/profile2.conf
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[UKIProfile]
+Profile=
+ ID=profile2
+ TITLE=Profile Two
+Cmdline=testprofile2=1
diff --git a/src/boot/measure.c b/src/boot/measure.c
index 36d42147a1..f2d644ff03 100644
--- a/src/boot/measure.c
+++ b/src/boot/measure.c
@@ -16,6 +16,7 @@
#include "openssl-util.h"
#include "parse-argument.h"
#include "parse-util.h"
+#include "pe-binary.h"
#include "pretty-print.h"
#include "sha256.h"
#include "strv.h"
@@ -517,6 +518,38 @@ static int measure_kernel(PcrState *pcr_states, size_t n) {
m += sz;
}
+ if (c == UNIFIED_SECTION_LINUX) {
+ _cleanup_free_ PeHeader *pe_header = NULL;
+
+ r = pe_load_headers(fd, /*ret_dos_header=*/ NULL, &pe_header);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse kernel image file '%s', ignoring: %m", arg_sections[c]);
+ else if (m < pe_header->optional.SizeOfImage) {
+ memzero(buffer, BUFFER_SIZE);
+
+ /* Our EFI stub measures VirtualSize bytes of the .linux section into PCR 11.
+ * Notably, VirtualSize can be larger than the section's size on disk. In
+ * that case the extra space is initialized with zeros, so the stub ends up
+ * measuring a bunch of zeros. To accomodate this, we have to measure the
+ * same number of zeros here. We opt to measure extra zeros here instead of
+ * modifying the stub to only measure the number of bytes on disk as we want
+ * newer ukify + systemd-measure to work with older versions of the stub and
+ * as of 6.12 the kernel image's VirtualSize won't be larger than its size on
+ * disk anymore (see https://github.com/systemd/systemd/issues/34578#issuecomment-2382459515).
+ */
+
+ while (m < pe_header->optional.SizeOfImage) {
+ uint64_t sz = MIN(BUFFER_SIZE, pe_header->optional.SizeOfImage - m);
+
+ for (size_t i = 0; i < n; i++)
+ if (EVP_DigestUpdate(mdctx[i], buffer, sz) != 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to run digest.");
+
+ m += sz;
+ }
+ }
+ }
+
fd = safe_close(fd);
if (m == 0) /* We skip over empty files, the stub does so too */
diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c
index d58194fb85..ca163ef3c2 100644
--- a/src/cryptenroll/cryptenroll-tpm2.c
+++ b/src/cryptenroll/cryptenroll-tpm2.c
@@ -78,8 +78,6 @@ static int search_policy_hash(
j++;
}
- assert(j == n_policy_hash);
-
if (match) /* Found entry with the exact same set of hashes */
return keyslot;
}
diff --git a/src/pcrlock/pehash.c b/src/pcrlock/pehash.c
index 06d1f6afc7..7e9dade1f7 100644
--- a/src/pcrlock/pehash.c
+++ b/src/pcrlock/pehash.c
@@ -216,10 +216,24 @@ int uki_hash(int fd,
if (EVP_DigestInit_ex(mdctx, md, NULL) != 1)
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to allocate message digest.");
- r = hash_file(fd, mdctx, section->PointerToRawData, section->VirtualSize);
+ r = hash_file(fd, mdctx, section->PointerToRawData, MIN(section->VirtualSize, section->SizeOfRawData));
if (r < 0)
return r;
+ if (section->SizeOfRawData < section->VirtualSize) {
+ uint8_t zeroes[1024] = {};
+ size_t remaining = section->VirtualSize - section->SizeOfRawData;
+
+ while (remaining > 0) {
+ size_t sz = MIN(sizeof(zeroes), remaining);
+
+ if (EVP_DigestUpdate(mdctx, zeroes, sz) != 1)
+ return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to hash data.");
+
+ remaining -= sz;
+ }
+ }
+
hashes[i] = malloc(hsz);
if (!hashes[i])
return log_oom_debug();
diff --git a/test/TEST-86-MULTI-PROFILE-UKI/meson.build b/test/TEST-86-MULTI-PROFILE-UKI/meson.build
index 10d5957d8f..53042884cc 100644
--- a/test/TEST-86-MULTI-PROFILE-UKI/meson.build
+++ b/test/TEST-86-MULTI-PROFILE-UKI/meson.build
@@ -6,6 +6,5 @@ integration_tests += [
'storage' : 'persistent',
'vm' : true,
'firmware' : 'auto',
- 'enabled' : false,
},
]
diff --git a/test/units/TEST-70-TPM2.pcrlock.sh b/test/units/TEST-70-TPM2.pcrlock.sh
index 0bf32e2eac..19af3a774d 100755
--- a/test/units/TEST-70-TPM2.pcrlock.sh
+++ b/test/units/TEST-70-TPM2.pcrlock.sh
@@ -86,7 +86,7 @@ echo -n hoho >/tmp/pcrlockpwd
chmod 0600 /tmp/pcrlockpwd
cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom "$img" /tmp/pcrlockpwd
-systemd-cryptenroll --unlock-key-file=/tmp/pcrlockpwd --tpm2-device=auto --tpm2-pcrlock=/var/lib/systemd/pcrlock.json --wipe-slot=tpm2 "$img"
+systemd-cryptenroll --unlock-key-file=/tmp/pcrlockpwd --tpm2-device=auto --tpm2-pcrlock=/var/lib/systemd/pcrlock.json --tpm2-public-key= --wipe-slot=tpm2 "$img"
systemd-cryptsetup attach pcrlock "$img" - tpm2-device=auto,tpm2-pcrlock=/var/lib/systemd/pcrlock.json,headless
systemd-cryptsetup detach pcrlock
@@ -136,7 +136,7 @@ systemd-cryptenroll --unlock-tpm2-device=auto --tpm2-device=auto --tpm2-pcrlock=
"$SD_MEASURE" sign --current --bank=sha256 --private-key="$img".private.pem --public-key="$img".public.pem --phase=: | tee "$img".pcrsign
SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach pcrlock "$img" - "tpm2-device=auto,tpm2-pcrlock=/var/lib/systemd/pcrlock.json,tpm2-signature=$img.pcrsign,headless"
systemd-cryptsetup detach pcrlock
-systemd-cryptenroll --unlock-key-file=/tmp/pcrlockpwd --tpm2-device=auto --tpm2-pcrlock=/var/lib/systemd/pcrlock.json --wipe-slot=tpm2 "$img"
+systemd-cryptenroll --unlock-key-file=/tmp/pcrlockpwd --tpm2-device=auto --tpm2-pcrlock=/var/lib/systemd/pcrlock.json --tpm2-public-key= --wipe-slot=tpm2 "$img"
rm "$img".public.pem "$img".private.pem "$img".pcrsign
# Now use the root fs support, i.e. make the tool write a copy of the pcrlock
diff --git a/test/units/TEST-86-MULTI-PROFILE-UKI.sh b/test/units/TEST-86-MULTI-PROFILE-UKI.sh
index 042cc59419..1af0788d5e 100755
--- a/test/units/TEST-86-MULTI-PROFILE-UKI.sh
+++ b/test/units/TEST-86-MULTI-PROFILE-UKI.sh
@@ -25,57 +25,42 @@ fi
echo "CURRENT EVENT LOG + PCRS:"
/usr/lib/systemd/systemd-pcrlock
-if test ! -f /run/systemd/stub/profile; then
- openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out /root/pcrsign.private.pem
- openssl rsa -pubout -in /root/pcrsign.private.pem -out /root/pcrsign.public.pem
+test -f /run/systemd/stub/profile
- ukify build --extend="$CURRENT_UKI" --output=/tmp/extended0.efi --profile='ID=profile0
-TITLE="Profile Zero"' --measure-base="$CURRENT_UKI" --pcr-private-key=/root/pcrsign.private.pem --pcr-public-key=/root/pcrsign.public.pem --pcr-banks=sha256,sha384,sha512
+# shellcheck source=/dev/null
+. /run/systemd/stub/profile
- ukify build --extend=/tmp/extended0.efi --output=/tmp/extended1.efi --profile='ID=profile1
-TITLE="Profile One"' --measure-base=/tmp/extended0.efi --cmdline="testprofile1=1 $(cat /proc/cmdline)" --pcr-private-key=/root/pcrsign.private.pem --pcr-public-key=/root/pcrsign.public.pem --pcr-banks=sha256,sha384,sha512
-
- ukify build --extend=/tmp/extended1.efi --output=/tmp/extended2.efi --profile='ID=profile2
-TITLE="Profile Two"' --measure-base=/tmp/extended1.efi --cmdline="testprofile2=1 $(cat /proc/cmdline)" --pcr-private-key=/root/pcrsign.private.pem --pcr-public-key=/root/pcrsign.public.pem --pcr-banks=sha256,sha384,sha512
-
- echo "EXTENDED UKI:"
- ukify inspect /tmp/extended2.efi
- rm /tmp/extended0.efi /tmp/extended1.efi
- mv /tmp/extended2.efi "$CURRENT_UKI"
+if [[ "$ID" == "main" ]]; then
+ if [[ -f /root/encrypted.raw ]]; then
+ exit 1
+ fi
- # Prepare a disk image, locked to the PCR measurements of the UKI we just generated
+ # Prepare a disk image, locked to the PCR measurements of the current UKI
truncate -s 32M /root/encrypted.raw
echo -n "geheim" >/root/encrypted.secret
cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom /root/encrypted.raw --key-file=/root/encrypted.secret
- systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs= --tpm2-public-key=/root/pcrsign.public.pem --unlock-key-file=/root/encrypted.secret /root/encrypted.raw
+ systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs= --unlock-key-file=/root/encrypted.secret /root/encrypted.raw
rm -f /root/encrypted.secret
+fi
+
+# Validate that with the current profile we can fulfill the PCR 11 policy
+systemd-cryptsetup attach multiprof /root/encrypted.raw - tpm2-device=auto,headless=1
+systemd-cryptsetup detach multiprof
+if [[ "$ID" == "main" ]]; then
+ bootctl set-default "$(basename "$CURRENT_UKI")@profile1"
reboot
exit 0
+elif [[ "$ID" == "profile1" ]]; then
+ grep testprofile1=1 /proc/cmdline
+ bootctl set-default "$(basename "$CURRENT_UKI")@profile2"
+ reboot
+ exit 0
+elif [[ "$ID" == "profile2" ]]; then
+ grep testprofile2=1 /proc/cmdline
+ rm /root/encrypted.raw
else
- # shellcheck source=/dev/null
- . /run/systemd/stub/profile
-
- # Validate that with the current profile we can fulfill the PCR 11 policy
- systemd-cryptsetup attach multiprof /root/encrypted.raw - tpm2-device=auto,headless=1
- systemd-cryptsetup detach multiprof
-
- if [ "$ID" = "profile0" ]; then
- grep -v testprofile /proc/cmdline
- echo "default $(basename "$CURRENT_UKI")@profile1" >"$(bootctl -p)/loader/loader.conf"
- reboot
- exit 0
- elif [ "$ID" = "profile1" ]; then
- grep testprofile1=1 /proc/cmdline
- echo "default $(basename "$CURRENT_UKI")@profile2" >"$(bootctl -p)/loader/loader.conf"
- reboot
- exit 0
- elif [ "$ID" = "profile2" ]; then
- grep testprofile2=1 /proc/cmdline
- rm /root/encrypted.raw
- else
- exit 1
- fi
+ exit 1
fi
touch /testok