Compare commits

...

7 Commits

Author SHA1 Message Date
Lennart Poettering e754ca25fc
Merge 8fd917a74d into 7ac1ad90d0 2024-09-17 22:41:38 -07:00
Yu Watanabe 7ac1ad90d0
Merge pull request #34460 from yuwata/test-86-follow-ups
test: follow-ups for TEST-86
2024-09-18 09:31:17 +09:00
Daan De Meyer 099b16c3e7 tmpfiles.d: Remove purge flag from lines that don't support it
Fixes db15657dfb
2024-09-17 23:02:01 +02:00
Yu Watanabe d265b8afb7 test: drop unused test.sh for TEST-86-MULTI-PROFILE-UKI
The test cannot run with the bash test runner, as it requires python.
Hence, test.sh is not necessary.

Follow-up for a37640653c.
2024-09-18 04:00:05 +09:00
Yu Watanabe 1aab0a5b10 test: minor coding style fixlets
Follow-up for a37640653c.
2024-09-18 03:50:46 +09:00
Lennart Poettering 8fd917a74d tpm2-util: allocate pcrlock NV indexes from our newly assigned range 2024-07-04 16:32:03 +02:00
Lennart Poettering 6cda26f3d6 doc: add document stating how we assign NV indexes
The Trusted Computing Group has assigned the systemd project an NV index
range, let's document properly which one that is, and how we use it.

Thank you so much, TCG!
2024-07-04 16:32:03 +02:00
7 changed files with 97 additions and 29 deletions

View File

@ -0,0 +1,70 @@
---
title: TPM2 NV Index Assignment by systemd
category: Booting
layout: default
SPDX-License-Identifier: LGPL-2.1-or-later
---
# TPM 2.0 NV Index Assignments
The Trusted Computing Group (TCG) maintains a [Registry of Reserved TPM 2.0
Handles and Localities](https://trustedcomputinggroup.org/resource/registry/)
which assigns TPM 2.0 NV index ranges (among ther things, see section 2.2) to
organizations (by convention only!). It has assigned the NV index range
**0x01800400-0x018005FF** to the systemd project. This NV index range is subdivided
and used by systemd for the following purposes:
## As Storage for a Disk Encryption PolicyAuthorizeNV Policy Hash
*Scope*: Dynamic allocation at OS installation time, one for each installed
Linux/systemd based OS that uses `systemd-pcrlock` based disk encryption policies.
*Subrange*: **0x01800400-0x0180041F**
*Number of NV Indexes*: **32**
*Size*: Stores one policy hash. Under the assumption SHA256 policy hashes are
used, this means **32 byte**.
## As Storage for Additional PCRs Implemented in NV Indexes
*Scope*: Static allocation by the systemd project, one for each additional NV
Indexed based PCR (systemd calls these "NvPCRs"). These can be shared between
multiple Linux/systemd based OSes installed on the same system.
*Subrange*: **0x01800420-0x01800423**
*Number of NV Indexes*: **4**
*Size*: Stores one PCR hash each (`TPMA_NT_EXTEND`). We'd expect that typically
SHA256 PCR hashes are used, hence this means **32 byte**.
*Detailed Assignments*:
| NVIndex | Purpose |
|------------|---------------------------------------------------------------|
| 0x01800420 | Used LUKS unlock mechanism (TPM2, PKCS11, FIDO2, …) |
| 0x01800421 | Product UUID |
| 0x01800422 | System Extension Images (sysexts) applied to the host |
| 0x01800423 | Configuration Extension Images (confexts) applied to the host |
## Currently Unused Range
The following range is currently not used by the systemd project, but might be
allocated later: **0x01800424-0x018005FF**
## Summary:
| NVIndex Range | Number | Purpose |
|-----------------------|--------|------------------------------------------------|
| 0x01800400-0x0180041F | 32 | Assigned to systemd, used for pcrlock policies |
| 0x01800420-0x01800423 | 4 | Assigned to systemd, used as additional PCRs |
| 0x01800424-0x018005FF | 476 | Assigned to systemd, currently unused |
# Relationship with TCG
This document is referenced by the aforementioned registry for details about
assignments of the NV Index range delegated to the systemd project. Hence,
particular care should be taken that this page is not moved, and its URL
remains stable as
[`https://systemd.io/TPM2_NVINDEX_ASSIGNMENTS`](https://systemd.io/TPM2_NVINDEX_ASSIGNMENTS).

View File

@ -5848,9 +5848,9 @@ int tpm2_unseal(Tpm2Context *c,
return 0;
}
static TPM2_HANDLE generate_random_nv_index(void) {
return TPM2_NV_INDEX_UNASSIGNED_FIRST +
(TPM2_HANDLE) random_u64_range(TPM2_NV_INDEX_UNASSIGNED_LAST - TPM2_NV_INDEX_UNASSIGNED_FIRST + 1);
static TPM2_HANDLE generate_random_pcrlock_nv_index(void) {
return TPM2_NV_INDEX_PCRLOCK_FIRST +
(TPM2_HANDLE) random_u64_range(TPM2_NV_INDEX_PCRLOCK_LAST - TPM2_NV_INDEX_PCRLOCK_FIRST + 1);
}
int tpm2_define_policy_nv_index(
@ -5884,7 +5884,7 @@ int tpm2_define_policy_nv_index(
if (requested_nv_index != 0)
nv_index = requested_nv_index;
else
nv_index = generate_random_nv_index();
nv_index = generate_random_pcrlock_nv_index();
TPM2B_NV_PUBLIC public_info = {
.size = sizeof_field(TPM2B_NV_PUBLIC, nvPublic),

View File

@ -487,13 +487,21 @@ enum {
int tpm2_pcr_index_from_string(const char *s) _pure_;
const char* tpm2_pcr_index_to_string(int pcr) _const_;
/* The first and last NV index handle that is not registered to any company, as per TCG's "Registry of
/* The first and last NV index handle that is assigned to the systemd project as per TCG's "Registry of
* Reserved TPM 2.0 Handles and Localities", section 2.2.2. */
#define TPM2_NV_INDEX_UNASSIGNED_FIRST UINT32_C(0x01800000)
#define TPM2_NV_INDEX_UNASSIGNED_LAST UINT32_C(0x01BFFFFF)
#define TPM2_NV_INDEX_SYSTEMD_FIRST UINT32_C(0x01800400)
#define TPM2_NV_INDEX_SYSTEMD_LAST UINT32_C(0x018005FF)
#if HAVE_TPM2
/* Verify that the above is indeed a subset of the general NV Index range */
assert_cc(TPM2_NV_INDEX_UNASSIGNED_FIRST >= TPM2_NV_INDEX_FIRST);
assert_cc(TPM2_NV_INDEX_UNASSIGNED_LAST <= TPM2_NV_INDEX_LAST);
assert_cc(TPM2_NV_INDEX_SYSTEMD_FIRST >= TPM2_NV_INDEX_FIRST);
assert_cc(TPM2_NV_INDEX_SYSTEMD_LAST <= TPM2_NV_INDEX_LAST);
#endif
/* A subrange we use to store pcrlock policies in */
#define TPM2_NV_INDEX_PCRLOCK_FIRST UINT32_C(0x01800400)
#define TPM2_NV_INDEX_PCRLOCK_LAST UINT32_C(0x0180041F)
assert_cc(TPM2_NV_INDEX_PCRLOCK_FIRST >= TPM2_NV_INDEX_SYSTEMD_FIRST);
assert_cc(TPM2_NV_INDEX_PCRLOCK_LAST <= TPM2_NV_INDEX_SYSTEMD_LAST);

View File

@ -1,10 +0,0 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -e
TEST_DESCRIPTION="Test Multi-Profile UKI Boots"
# shellcheck source=test/test-functions
. "${TEST_BASE_DIR:?}/test-functions"
do_test "$@"

View File

@ -17,9 +17,9 @@ if test -f /run/systemd/stub/profile; then
fi
echo "CURRENT MEASUREMENT:"
/usr/lib/systemd/systemd-measure --current
if test -f /run/systemd/tpm2-pcr-signature.json ; then
if test -f /run/systemd/tpm2-pcr-signature.json; then
echo "CURRENT SIGNATURE:"
jq < /run/systemd/tpm2-pcr-signature.json
jq </run/systemd/tpm2-pcr-signature.json
fi
echo "CURRENT EVENT LOG + PCRS:"
@ -45,7 +45,7 @@ TITLE="Profile Two"' --measure-base=/tmp/extended1.efi --cmdline="testprofile2=1
# Prepare a disk image, locked to the PCR measurements of the UKI we just generated
truncate -s 32M /root/encrypted.raw
echo -n "geheim" > /root/encrypted.secret
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
rm -f /root/encrypted.secret
@ -62,12 +62,12 @@ else
if [ "$ID" = "profile0" ]; then
grep -v testprofile /proc/cmdline
echo "default $(basename "$CURRENT_UKI")@profile1" > "$(bootctl -p)/loader/loader.conf"
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"
echo "default $(basename "$CURRENT_UKI")@profile2" >"$(bootctl -p)/loader/loader.conf"
reboot
exit 0
elif [ "$ID" = "profile2" ]; then

View File

@ -19,5 +19,5 @@ Q /var/lib/machines 0700 - - -
# systemd-nspawn --ephemeral places snapshots) we are more strict, to
# avoid removing unrelated temporary files.
R!$ /var/lib/machines/.#*
R!$ /.#machine.*
R! /var/lib/machines/.#*
R! /.#machine.*

View File

@ -14,10 +14,10 @@ x /var/tmp/systemd-private-%b-*
X /var/tmp/systemd-private-%b-*/tmp
# Remove top-level private temporary directories on each boot
R!$ /tmp/systemd-private-*
R!$ /var/tmp/systemd-private-*
R! /tmp/systemd-private-*
R! /var/tmp/systemd-private-*
# Handle lost systemd-coredump temp files. They could be lost on old filesystems,
# for example, after hard reboot.
x /var/lib/systemd/coredump/.#core*.%b*
r!$ /var/lib/systemd/coredump/.#*
r! /var/lib/systemd/coredump/.#*