Skip to content
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

[UKI] Cant unlock luks device after adding new certs to EFI #32946

Closed
Itxaka opened this issue May 21, 2024 · 15 comments · Fixed by #32993
Closed

[UKI] Cant unlock luks device after adding new certs to EFI #32946

Itxaka opened this issue May 21, 2024 · 15 comments · Fixed by #32993
Labels
bug 🐛 Programming errors, that need preferential fixing cryptsetup

Comments

@Itxaka
Copy link

Itxaka commented May 21, 2024

systemd version the issue has been seen with

255.4-1ubuntu8

Used distribution

Ubuntu 24.04

Linux kernel version used

6.8.0-31-generic

CPU architectures issue was seen on

x86_64

Component

systemd-cryptsetup

Expected behaviour you didn't see

Installed UKI signed with secureboot custom cert (lets call it itxaka1). Measured with tpm2-signature to default PCRs (11 according to docs). Partitions are correctly unlocked on boot with cryptsetup attach using the measurements on /run/systemd/ (systemd-cryptsetup attach oem /dev/vda2 - tpm2-device=auto)

All fine and dandy and working without issues.

Then we add a new KEK cert to the EFI firmware (lets call it itxaka2) and system boots correctly, so secureboot works, but partitions wont unlock anymore. See logs attached.

If you remove the cert, then it starts working again.

Unexpected behaviour you saw

Expecting it to unlock anyway as measurements and tpm2 policy should not relay on PCR7, which is the one that changed by adding new certs.

Steps to reproduce the problem

  • Boot measured UKI with a set of certs and locked partitions via tpm2-signature
  • Check that it can unlock the partitions
  • Add a new cert to KEK (Or DB)
  • See that it cannot unlock the partitions anymore

Additional program output to the terminal or log subsystem illustrating the issue

root@localhost:/tmp/sbctl# SYSTEMD_LOG_LEVEL=debug /usr/lib/systemd/systemd-cryptsetup attach oem /dev/vda2 - tpm2-device=auto
run oem ← /dev/vda2 type= cipher=
Allocating context for crypt device /dev/vda2.
Trying to open and read device /dev/vda2 with direct-io.
Initialising device-mapper backend library.
dm version   [ opencount flush ]   [16384] (*1)
dm versions   [ opencount flush ]   [16384] (*1)
Detected dm-ioctl version 4.48.0.
Device-mapper backend running with UDEV support enabled.
dm status oem  [ opencount noflush ]   [16384] (*1)
Trying to load any crypt type from device /dev/vda2.
Crypto backend (OpenSSL 3.0.13 30 Jan 2024 [default][legacy] [external libargon2]) initialized in cryptsetup library version 2.7.0.
Detected kernel Linux 6.8.0-31-generic x86_64.
Loading LUKS2 header (repair disabled).
Acquiring read lock for device /dev/vda2.
Opening lock resource file /run/cryptsetup/L_253:2
Verifying lock handle for /dev/vda2.
Device /dev/vda2 READ lock taken.
Trying to read primary LUKS2 header at offset 0x0.
Opening locked device /dev/vda2
Verifying locked device handle (bdev)
LUKS2 header version 2 of size 16384 bytes, checksum sha256.
Checksum:fdbdd1202369e39c383bc9e81e7ac0a1ad3502fe97a09ab92e932d34d4b3dbe3 (on-disk)
Checksum:fdbdd1202369e39c383bc9e81e7ac0a1ad3502fe97a09ab92e932d34d4b3dbe3 (in-memory)
Trying to read secondary LUKS2 header at offset 0x4000.
Reusing open ro fd on device /dev/vda2
LUKS2 header version 2 of size 16384 bytes, checksum sha256.
Checksum:07f34f7f97f8d0507cd07281550768cd473269d207de08e408d7809d9563b83a (on-disk)
Checksum:07f34f7f97f8d0507cd07281550768cd473269d207de08e408d7809d9563b83a (in-memory)
Device size 67108864, offset 16777216.
Device /dev/vda2 READ lock released.
PBKDF argon2id, time_ms 2000 (iterations 0), max_memory_kb 1048576, parallel_threads 4.
Activating volume oem [keyslot -1] using token.
dm versions   [ opencount flush ]   [16384] (*1)
dm status oem  [ opencount noflush ]   [16384] (*1)
Token 0 unusable for segment 0 with desired keyslot priority 2.
Trying to load /lib/x86_64-linux-gnu/cryptsetup/libcryptsetup-token-systemd-tpm2.so.
Loading symbol cryptsetup_token_open@CRYPTSETUP_TOKEN_1.0.
Loading symbol cryptsetup_token_buffer_free@CRYPTSETUP_TOKEN_1.0.
Loading symbol cryptsetup_token_validate@CRYPTSETUP_TOKEN_1.0.
Loading symbol cryptsetup_token_dump@CRYPTSETUP_TOKEN_1.0.
Loading symbol cryptsetup_token_open_pin@CRYPTSETUP_TOKEN_1.0.
Loading symbol cryptsetup_token_version@CRYPTSETUP_TOKEN_1.0.
Token handler systemd-tpm2-1.0 systemd-v255 (255.4-1ubuntu8) loaded successfully.
Requesting JSON for token 0.
Using TPM2 TCTI driver 'device' with device '/dev/tpmrm0'.
Loaded TCTI module 'tcti-device' (TCTI module for communication with Linux kernel interface.) [Version 2]
TPM successfully started up.
Getting TPM2 capability 0x0000 property 0x0001 count 127.
Getting TPM2 capability 0x0002 property 0x011f count 256.
Getting TPM2 capability 0x0008 property 0x0000 count 508.
Getting TPM2 capability 0x0005 property 0x0000 count 1.
Loading HMAC key into TPM.
Loading object into TPM.
Starting HMAC encryption session.
Starting policy session.
Building sealing policy.
Reading PCR selection: [sha256(7+11)]
Read PCR selection: [sha256(7+11)]
PCR value: 7:sha256=b052e441d98f548a44e2b158104ca0d13cc606f6da8323de8efac367987b4495
PCR value: 11:sha256=14ab6091ec232bb7e78872ce7ac216e7c6a940c61dd9e4887a61c5b8e4a06770
Adding PCR signature policy.
Loading external key into TPM.
Object name: 000bad2a981c0eed83d41d9544750be2bc8f80b39f8af1ab3463bd7dbefb6576da3e
Submitting PCR hash policy.
Acquiring policy digest.
Session policy digest: 7c1d391e47b2273e4b21868c62d5363aca0fef88bb6f02ed4edcdbd4593dc326
Acquiring policy digest.
Session policy digest: 513c0686708c06d99dd558564d916e0cfd3ed03040e91cc6de5a8ac89d5b02b6
Submitting PCR hash policy.
Acquiring policy digest.
Session policy digest: d6f159ed795360f93828831e96c2064453ceb16c8c51014b9bbfaa28c36b0a00
Acquiring policy digest.
Session policy digest: d6f159ed795360f93828831e96c2064453ceb16c8c51014b9bbfaa28c36b0a00
Policy hash mismatch, retrying with RSA pubkey exponent set to 0.
Starting policy session.
Building sealing policy.
Reading PCR selection: [sha256(7+11)]
Read PCR selection: [sha256(7+11)]
PCR value: 7:sha256=b052e441d98f548a44e2b158104ca0d13cc606f6da8323de8efac367987b4495
PCR value: 11:sha256=14ab6091ec232bb7e78872ce7ac216e7c6a940c61dd9e4887a61c5b8e4a06770
Adding PCR signature policy.
Loading external key into TPM.
Object name: 000bce2d3f0ac405531b340244aea700e547caee3e900ec97117f10e9588aa15fade
Submitting PCR hash policy.
Acquiring policy digest.
Session policy digest: 7c1d391e47b2273e4b21868c62d5363aca0fef88bb6f02ed4edcdbd4593dc326
Acquiring policy digest.
Session policy digest: 0eeb3077dbb73e6e0b72bc35474fb5d8d5dc49b017a9fe12eabd8bddc117b698
Submitting PCR hash policy.
Acquiring policy digest.
Session policy digest: 01ca98001d9e3a7e8da521171a21833d74462e6127e18c79e39748701fdf99ff
Acquiring policy digest.
Session policy digest: 01ca98001d9e3a7e8da521171a21833d74462e6127e18c79e39748701fdf99ff
Current policy digest does not match stored policy digest, cancelling TPM2 authentication attempt.
Failed to unseal secret using TPM2: Operation not permitted
systemd-tpm2 open failed: Operation not permitted.
systemd-tpm2 token handler returned -1. Changing to -2.
Token 0 (systemd-tpm2) open failed with -2.
Token activation unsuccessful for device /dev/vda2: No such file or directory
Set cipher aes, mode xts-plain64, key size 512 bits for device /dev/vda2.
Activating volume oem [keyslot -1] using token.
dm versions   [ opencount flush ]   [16384] (*1)
dm status oem  [ opencount noflush ]   [16384] (*1)
Token 0 unusable for segment 0 with desired keyslot priority 2.
Requesting JSON for token 0.
Using TPM2 TCTI driver 'device' with device '/dev/tpmrm0'.
Loaded TCTI module 'tcti-device' (TCTI module for communication with Linux kernel interface.) [Version 2]
TPM successfully started up.
Getting TPM2 capability 0x0000 property 0x0001 count 127.
Getting TPM2 capability 0x0002 property 0x011f count 256.
Getting TPM2 capability 0x0008 property 0x0000 count 508.
Getting TPM2 capability 0x0005 property 0x0000 count 1.
Loading HMAC key into TPM.
Loading object into TPM.
Starting HMAC encryption session.
Starting policy session.
Building sealing policy.
Reading PCR selection: [sha256(7+11)]
Read PCR selection: [sha256(7+11)]
PCR value: 7:sha256=b052e441d98f548a44e2b158104ca0d13cc606f6da8323de8efac367987b4495
PCR value: 11:sha256=14ab6091ec232bb7e78872ce7ac216e7c6a940c61dd9e4887a61c5b8e4a06770
Adding PCR signature policy.
Loading external key into TPM.
Object name: 000bad2a981c0eed83d41d9544750be2bc8f80b39f8af1ab3463bd7dbefb6576da3e
Submitting PCR hash policy.
Acquiring policy digest.
Session policy digest: 7c1d391e47b2273e4b21868c62d5363aca0fef88bb6f02ed4edcdbd4593dc326
Acquiring policy digest.
Session policy digest: 513c0686708c06d99dd558564d916e0cfd3ed03040e91cc6de5a8ac89d5b02b6
Submitting PCR hash policy.
Acquiring policy digest.
Session policy digest: d6f159ed795360f93828831e96c2064453ceb16c8c51014b9bbfaa28c36b0a00
Acquiring policy digest.
Session policy digest: d6f159ed795360f93828831e96c2064453ceb16c8c51014b9bbfaa28c36b0a00
Policy hash mismatch, retrying with RSA pubkey exponent set to 0.
Starting policy session.
Building sealing policy.
Reading PCR selection: [sha256(7+11)]
Read PCR selection: [sha256(7+11)]
PCR value: 7:sha256=b052e441d98f548a44e2b158104ca0d13cc606f6da8323de8efac367987b4495
PCR value: 11:sha256=14ab6091ec232bb7e78872ce7ac216e7c6a940c61dd9e4887a61c5b8e4a06770
Adding PCR signature policy.
Loading external key into TPM.
Object name: 000bce2d3f0ac405531b340244aea700e547caee3e900ec97117f10e9588aa15fade
Submitting PCR hash policy.
Acquiring policy digest.
Session policy digest: 7c1d391e47b2273e4b21868c62d5363aca0fef88bb6f02ed4edcdbd4593dc326
Acquiring policy digest.
Session policy digest: 0eeb3077dbb73e6e0b72bc35474fb5d8d5dc49b017a9fe12eabd8bddc117b698
Submitting PCR hash policy.
Acquiring policy digest.
Session policy digest: 01ca98001d9e3a7e8da521171a21833d74462e6127e18c79e39748701fdf99ff
Acquiring policy digest.
Session policy digest: 01ca98001d9e3a7e8da521171a21833d74462e6127e18c79e39748701fdf99ff
Current policy digest does not match stored policy digest, cancelling TPM2 authentication attempt.
Failed to unseal secret using TPM2: Operation not permitted
systemd-tpm2 open failed: Operation not permitted.
systemd-tpm2 token handler returned -1. Changing to -2.
Token 0 (systemd-tpm2) open failed with -2.
No TPM2 metadata enrolled in LUKS2 header or TPM2 support not available, falling back to traditional unlocking.
Requesting JSON for token 0.
Requesting JSON for token 1.
Requesting JSON for token 2.
Requesting JSON for token 3.
Requesting JSON for token 4.
Requesting JSON for token 5.
Requesting JSON for token 6.
Requesting JSON for token 7.
Requesting JSON for token 8.
Requesting JSON for token 9.
Requesting JSON for token 10.
Requesting JSON for token 11.
Requesting JSON for token 12.
Requesting JSON for token 13.
Requesting JSON for token 14.
Requesting JSON for token 15.
Requesting JSON for token 16.
Requesting JSON for token 17.
Requesting JSON for token 18.
Requesting JSON for token 19.
Requesting JSON for token 20.
Requesting JSON for token 21.
Requesting JSON for token 22.
Requesting JSON for token 23.
Requesting JSON for token 24.
Requesting JSON for token 25.
Requesting JSON for token 26.
Requesting JSON for token 27.
Requesting JSON for token 28.
Requesting JSON for token 29.
Requesting JSON for token 30.
Requesting JSON for token 31.
No passphrase or recovery key registered.
Releasing crypt device /dev/vda2 context.
Releasing device-mapper backend.
Closing read only fd for /dev/vda2.
Unloading systemd-tpm2 token handler.
@Itxaka Itxaka added the bug 🐛 Programming errors, that need preferential fixing label May 21, 2024
@Itxaka
Copy link
Author

Itxaka commented May 21, 2024

According to docs, if not specified, when locking via a tpm signature/policy it will bind to PCR11, but this sure looks like its binding to PCR7 as well? Otherwise Im not sure why would adding a new cert in the KEK or DB would break the PCR11 measurements?

@Itxaka
Copy link
Author

Itxaka commented May 21, 2024

We also tried to specify exactly -tpm2-public-key-pcrs=11 when binding and still failing.

@Itxaka
Copy link
Author

Itxaka commented May 21, 2024

oh I just saw it thanks to #30546

decryption is trying PCR7+11 ? Does that make sense if the default is to encrypt with 11 only?

@Itxaka
Copy link
Author

Itxaka commented May 21, 2024

going further down into this, when running cryptsetup its supposed to store the binded PCR slots into the luks JSON header?

When unlocking the encrypted volume, the primary key pair is generated on the TPM2 chip again (which works as long as the chip's seed key is correctly maintained by the TPM2 chip), which is then used to decrypt (on the TPM2 chip) the encrypted key from the LUKS2 volume JSON token header saved there during enrollment. The resulting decrypted key is then used to unlock the volume. When the randomized key is encrypted the current values of the selected PCRs (see below) are included in the operation, so that different PCR state results in different encrypted keys and the decrypted key can only be recovered if the same PCR state is reproduced.

So if we enroll with PCR11 cryptsetup would read that from the header and try to unlock with PCR11 only but we are not seeing this, we are locking with PCR11 and we can clearly see cryptsetup picking up 7+11:

Reading PCR selection: [sha256(7+11)]

@Itxaka
Copy link
Author

Itxaka commented May 21, 2024

I did regenerate the partition and encrolling the key seems to default to 7+11 no matter what we specify in the flag --tpm2-public-key-pcrs

root@localhost:~# SYSTEMD_LOG_LEVEL=debug systemd-cryptenroll --tpm2-public-key=/run/systemd/tpm2-pcr-public-key.pem --tpm2-signature=/run/systemd/tpm2-pcr-signature.json --tpm2-public-key-pcrs=11 --tpm2-device=auto /dev/vda3

BUT, it seems that if we specify --tpm2-pcrs=11 then it binds to PCR11 properly.

So whats the flag to use? Is this a docs issue? did the behavior change?

Docs mention:

Configures a TPM2 signed PCR policy to bind encryption to. The --tpm2-public-key= option accepts a path to a PEM encoded RSA public key, to bind the encryption to. If this is not specified explicitly, but a file tpm2-pcr-public-key.pem exists in one of the directories /etc/systemd/, /run/systemd/, /usr/lib/systemd/ (searched in this order), it is automatically used. The --tpm2-public-key-pcrs= option takes a list of TPM2 PCR indexes to bind to (same syntax as --tpm2-pcrs= described above). If not specified defaults to 11 (i.e. this binds the policy to any unified kernel image for which a PCR signature can be provided).

Note the difference between --tpm2-pcrs= and --tpm2-public-key-pcrs=: the former binds decryption to the current, specific PCR values; the latter binds decryption to any set of PCR values for which a signature by the specified public key can be provided. The latter is hence more useful in scenarios where software updates shell be possible without losing access to all previously encrypted LUKS2 volumes. Like with --tpm2-pcrs=, names defined in the table above can also be used to specify the registers, for instance --tpm2-public-key-pcrs=boot-loader-code+system-identity.

So it makes sense that if we are using a policy in order to be able to update the system, we use --tpm2-public-key-pcrs= but that doesnt seem to match the current behavior? it ignores the PCRs in there and just default to 7+11. And setting --tpm2-pcrs= instead makes it bind to 11 indeed but we dont want that, we want the --tpm2-public-key-pcrs= to allow for updates?

@Itxaka
Copy link
Author

Itxaka commented May 21, 2024

yes, confirmed that setting public key and public pcrs, does not bind only to the public pcrs as one would assume from whats written in the docs, it binds also to the default --tpm-pcrs values which default to 7 in the back without hinting at it.

I think the docs need to be updated to mention that both values would be merged, so if you dont specify anything in the tpm2-pcrs it will automatically add PCR7.

Not only that but docs also hint that if you want to use public pcrs to allow updating you need to use that flag, because tpm2-pcr will lock to a single set of measurements, which made us wary of setting that as we didnt want to bind to just 1 set of measurements.
Is this correct? If we specify --tpm2-public-key=/run/systemd/tpm2-pcr-public-key.pem --tpm2-public-key-pcrs=11 --tpm2-pcrs=11 will it bind to a single set of measurements or to the policy?

@Itxaka
Copy link
Author

Itxaka commented May 21, 2024

going more and more on this, seems that the solution of setting the --tpm2-pcrs=11 is not valid, becuase that will set it to a single measurement:

{
  "type": "systemd-tpm2",
  "keyslots": [
    "2"
  ],
  "tpm2-blob": "AJ4AIOU3ZfAH3z0fvsiJ0aw2I7Pq+Zue8/5qABTjPXcgU5QxABD9zn5TUr1qrEmkg4exJDDPErq23zAyh4zGfDL7DIR5buyw8ukHDX9CPu05Rqqe71LQsQYf56RPP03DSyzZ+Wtr95bwPkaoDexs/Ecw47dZbqL6j75/+e2oTMzv/qmKf2yExISVoi15bqsIofGYc/oe+yR/55IiQVK/DABOAAgACwAAABIAIHsVg0g6toC+AVZjPAXcWbl1jlPVYIMUTGSyiqttBy+pABAAIJvOeakoukYzJt/UpdzCD0fyoXU8T//ND+3nKwf5OVLx",
  "tpm2-pcrs": [
    11
  ],
  "tpm2-pcr-bank": "sha256",
  "tpm2-policy-hash": "7b1583483ab680be0156633c05dc59b9758e53d56083144c64b28aab6d072fa9",
  "tpm2-pin": false,
  "tpm2_pcrlock": false,
  "tpm2_pubkey_pcrs": [
    11
  ],
  "tpm2_pubkey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUExTldTU3RWNDRIQVowdkdGaFBuUAp3eHJZbUhHRU1NeHVzUXRPVnBXNVFiLzN2dHRDMFpieG05MGdMQ2w0UjYzNUl2WGVwb2I1NmZhR2YyL2l5TTJyCnA2MlRHSnpLdFNLODFGNjFLQnlZRjdaS2pWeWFNTmMzSjdoMVBmQjdlT0oyZ1EzUGdybWpLM0lKdUkxT2hGMzcKUi9maWt3cFYvZ2VTU2diUGxqZ3IyUmw1b1d4VFluNXFDaC9CQ3dmbDVZTnp0N0lPOEVFdEUwTThycklvTHpTMQp4UnhmaWdoOTNQaEltdG5tbDN2ZDlnd1FIcnJPN2NzNGVsQVkrOFhSdW5kRVZCYmd1TTd6QzBIUlRocDRZYWh0Cmw4bVREQ1YwaGFZOVVvSWp0ZGJkcG10K3NEMmZyYllEVlk5Zis3VTJSZDdZcDFkaDhNc1BHMkJ5M1RVQ2l3a1EKYVFJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==",
  "tpm2_srk": "gQAAAQAiAAtFmtcOfTaTsqkzrcwxonwYAc9HacRwvfKkGhbjR9uaLAAAAAEAWgAjAAsAAwRyAAAABgCAAEMAEAADABAAICn301ozNM+qA0RKpa/ptgcIYxLjBPYKJvcfxSpaCILlACBkbJ6JNOT36Spcm1s3hFSP+RVLj0JG+/ZQPRDTF+0jmA=="
}

we dont want to have that tpm2-pcrs values in there, we only want to bind to tpm2_pubkey_pcrs. Is that possible?

@Itxaka
Copy link
Author

Itxaka commented May 21, 2024

docs say that passing an empty string will result in tpm2-pcrs not being binded to anything but that fails

SYSTEMD_LOG_LEVEL=debug systemd-cryptenroll --tpm2-public-key=/run/systemd/tpm2-pcr-public-key.pem --tpm2-signature=/run/systemd/tpm2-pcr-signature.json --tpm2-public-key-pcrs=11 --tpm2-pcrs="" --tpm2-device=auto /dev/vda3
Failed to find TPM2 pcrlock policy file 'pcrlock.json': No such file or directory
Allocating context for crypt device /dev/vda3.
Trying to open and read device /dev/vda3 with direct-io.
Initialising device-mapper backend library.
Trying to load LUKS2 crypt type from device /dev/vda3.
Crypto backend (OpenSSL 3.0.13 30 Jan 2024 [default][legacy] [external libargon2]) initialized in cryptsetup library version 2.7.0.
Detected kernel Linux 6.8.0-31-generic x86_64.
Loading LUKS2 header (repair disabled).
Acquiring read lock for device /dev/vda3.
Opening lock resource file /run/cryptsetup/L_253:3
Verifying lock handle for /dev/vda3.
Device /dev/vda3 READ lock taken.
Trying to read primary LUKS2 header at offset 0x0.
Opening locked device /dev/vda3
Verifying locked device handle (bdev)
LUKS2 header version 2 of size 16384 bytes, checksum sha256.
Checksum:75c52ed4e5c10691e6130acacade1e3460f101848bd397332d3b82beabde2fb1 (on-disk)
Checksum:75c52ed4e5c10691e6130acacade1e3460f101848bd397332d3b82beabde2fb1 (in-memory)
Trying to read secondary LUKS2 header at offset 0x4000.
Reusing open ro fd on device /dev/vda3
LUKS2 header version 2 of size 16384 bytes, checksum sha256.
Checksum:00a479f34a6f7250ebb4d23b5e3a6c101319c59aab55aee6bac80581dc9170eb (on-disk)
Checksum:00a479f34a6f7250ebb4d23b5e3a6c101319c59aab55aee6bac80581dc9170eb (in-memory)
Device size 37511757824, offset 16777216.
Device /dev/vda3 READ lock released.
PBKDF argon2id, time_ms 2000 (iterations 0), max_memory_kb 1048576, parallel_threads 4.
Requesting JSON for token 0.
Requesting JSON for token 1.
Requesting JSON for token 2.
Requesting JSON for token 3.
Requesting JSON for token 4.
Requesting JSON for token 5.
Requesting JSON for token 6.
Requesting JSON for token 7.
Requesting JSON for token 8.
Requesting JSON for token 9.
Requesting JSON for token 10.
Requesting JSON for token 11.
Requesting JSON for token 12.
Requesting JSON for token 13.
Requesting JSON for token 14.
Requesting JSON for token 15.
Requesting JSON for token 16.
Requesting JSON for token 17.
Requesting JSON for token 18.
Requesting JSON for token 19.
Requesting JSON for token 20.
Requesting JSON for token 21.
Requesting JSON for token 22.
Requesting JSON for token 23.
Requesting JSON for token 24.
Requesting JSON for token 25.
Requesting JSON for token 26.
Requesting JSON for token 27.
Requesting JSON for token 28.
Requesting JSON for token 29.
Requesting JSON for token 30.
Requesting JSON for token 31.
🔐 Please enter current passphrase for disk /dev/vda3: ••••Failed to adjust kernel keyring key timeout: Permission denied
Added key to kernel keyring as 1072956954.

Keyslot 0 priority 1 != 2 (required), skipped.
Trying to open LUKS2 keyslot 0.
Running keyslot key derivation.
Reading keyslot area [0x8000].
Acquiring read lock for device /dev/vda3.
Opening lock resource file /run/cryptsetup/L_253:3
Verifying lock handle for /dev/vda3.
Device /dev/vda3 READ lock taken.
Reusing open ro fd on device /dev/vda3
Device /dev/vda3 READ lock released.
Verifying key from keyslot 0, digest 0.
Using TPM2 TCTI driver 'device' with device '/dev/tpmrm0'.
Loaded TCTI module 'tcti-device' (TCTI module for communication with Linux kernel interface.) [Version 2]
TPM successfully started up.
Getting TPM2 capability 0x0000 property 0x0001 count 127.
Getting TPM2 capability 0x0002 property 0x011f count 256.
Getting TPM2 capability 0x0008 property 0x0000 count 508.
Getting TPM2 capability 0x0005 property 0x0000 count 1.
Calculated public key name: 000bad2a981c0eed83d41d9544750be2bc8f80b39f8af1ab3463bd7dbefb6576da3e
PolicyAuthorize calculated digest: 513c0686708c06d99dd558564d916e0cfd3ed03040e91cc6de5a8ac89d5b02b6
Not adding TPM2 entropy to the kernel random pool again.
Generating secret key data.
Getting TPM2 capability 0x0001 property 0x81000001 count 1.
Starting HMAC encryption session.
Creating object on TPM.
Successfully created object on TPM in 5ms.
Marshalling private and public part of HMAC key.
Completed TPM2 key sealing in 13.188ms.
Requesting JSON for token 0.
Requesting JSON for token 1.
Requesting JSON for token 2.
Requesting JSON for token 3.
Requesting JSON for token 4.
Requesting JSON for token 5.
Requesting JSON for token 6.
Requesting JSON for token 7.
Requesting JSON for token 8.
Requesting JSON for token 9.
Requesting JSON for token 10.
Requesting JSON for token 11.
Requesting JSON for token 12.
Requesting JSON for token 13.
Requesting JSON for token 14.
Requesting JSON for token 15.
Requesting JSON for token 16.
Requesting JSON for token 17.
Requesting JSON for token 18.
Requesting JSON for token 19.
Requesting JSON for token 20.
Requesting JSON for token 21.
Requesting JSON for token 22.
Requesting JSON for token 23.
Requesting JSON for token 24.
Requesting JSON for token 25.
Requesting JSON for token 26.
Requesting JSON for token 27.
Requesting JSON for token 28.
Requesting JSON for token 29.
Requesting JSON for token 30.
Requesting JSON for token 31.
PCR policy hash not yet enrolled, enrolling now.
Unsealing for verification...
Loading HMAC key into TPM.
Loading object into TPM.
Starting HMAC encryption session.
Starting policy session.
Building sealing policy.
Unknown hash algorithm id 0x0
Reading PCR selection: [n/a(11)]
WARNING:esys:src/tss2-esys/api/Esys_PCR_Read.c:304:Esys_PCR_Read_Finish() Received TPM Error 
ERROR:esys:src/tss2-esys/api/Esys_PCR_Read.c:105:Esys_PCR_Read() Esys Finish ErrorCode (0x000001c3) 
Failed to read TPM2 PCRs: tpm:parameter(1):hash algorithm not supported or not appropriate
Failed to unseal secret using TPM2: State not recoverable
Releasing crypt device /dev/vda3 context.
Releasing device-mapper backend.
Closing read only fd for /dev/vda3.

@Itxaka
Copy link
Author

Itxaka commented May 21, 2024

This can be workaround by skipping the TPM and using the --tpm2-device-key to avoid hitting the tpm device

SYSTEMD_LOG_LEVEL=debug systemd-cryptenroll --tpm2-public-key=/run/systemd/tpm2-pcr-public-key.pem --tpm2-signature=/run/systemd/tpm2-pcr-signature.json --tpm2-public-key-pcrs=11 --tpm2-pcrs= --tpm2-device-key=/run/systemd/tpm2-srk-public-key.tpm2b_public /dev/vda3
Failed to find TPM2 pcrlock policy file 'pcrlock.json': No such file or directory
Allocating context for crypt device /dev/vda3.
Trying to open and read device /dev/vda3 with direct-io.
Initialising device-mapper backend library.
Trying to load LUKS2 crypt type from device /dev/vda3.
Crypto backend (OpenSSL 3.0.13 30 Jan 2024 [default][legacy] [external libargon2]) initialized in cryptsetup library version 2.7.0.
Detected kernel Linux 6.8.0-31-generic x86_64.
Loading LUKS2 header (repair disabled).
Acquiring read lock for device /dev/vda3.
Opening lock resource file /run/cryptsetup/L_253:3
Verifying lock handle for /dev/vda3.
Device /dev/vda3 READ lock taken.
Trying to read primary LUKS2 header at offset 0x0.
Opening locked device /dev/vda3
Verifying locked device handle (bdev)
LUKS2 header version 2 of size 16384 bytes, checksum sha256.
Checksum:75c52ed4e5c10691e6130acacade1e3460f101848bd397332d3b82beabde2fb1 (on-disk)
Checksum:75c52ed4e5c10691e6130acacade1e3460f101848bd397332d3b82beabde2fb1 (in-memory)
Trying to read secondary LUKS2 header at offset 0x4000.
Reusing open ro fd on device /dev/vda3
LUKS2 header version 2 of size 16384 bytes, checksum sha256.
Checksum:00a479f34a6f7250ebb4d23b5e3a6c101319c59aab55aee6bac80581dc9170eb (on-disk)
Checksum:00a479f34a6f7250ebb4d23b5e3a6c101319c59aab55aee6bac80581dc9170eb (in-memory)
Device size 37511757824, offset 16777216.
Device /dev/vda3 READ lock released.
PBKDF argon2id, time_ms 2000 (iterations 0), max_memory_kb 1048576, parallel_threads 4.
Requesting JSON for token 0.
Requesting JSON for token 1.
Requesting JSON for token 2.
Requesting JSON for token 3.
Requesting JSON for token 4.
Requesting JSON for token 5.
Requesting JSON for token 6.
Requesting JSON for token 7.
Requesting JSON for token 8.
Requesting JSON for token 9.
Requesting JSON for token 10.
Requesting JSON for token 11.
Requesting JSON for token 12.
Requesting JSON for token 13.
Requesting JSON for token 14.
Requesting JSON for token 15.
Requesting JSON for token 16.
Requesting JSON for token 17.
Requesting JSON for token 18.
Requesting JSON for token 19.
Requesting JSON for token 20.
Requesting JSON for token 21.
Requesting JSON for token 22.
Requesting JSON for token 23.
Requesting JSON for token 24.
Requesting JSON for token 25.
Requesting JSON for token 26.
Requesting JSON for token 27.
Requesting JSON for token 28.
Requesting JSON for token 29.
Requesting JSON for token 30.
Requesting JSON for token 31.
🔐 Please enter current passphrase for disk /dev/vda3: ••••Failed to adjust kernel keyring key timeout: Permission denied
Added key to kernel keyring as 1072956954.

Keyslot 0 priority 1 != 2 (required), skipped.
Trying to open LUKS2 keyslot 0.
Running keyslot key derivation.
Reading keyslot area [0x8000].
Acquiring read lock for device /dev/vda3.
Opening lock resource file /run/cryptsetup/L_253:3
Verifying lock handle for /dev/vda3.
Device /dev/vda3 READ lock taken.
Reusing open ro fd on device /dev/vda3
Device /dev/vda3 READ lock released.
Verifying key from keyslot 0, digest 0.
Calculated public key name: 000bad2a981c0eed83d41d9544750be2bc8f80b39f8af1ab3463bd7dbefb6576da3e
PolicyAuthorize calculated digest: 513c0686708c06d99dd558564d916e0cfd3ed03040e91cc6de5a8ac89d5b02b6
Calculating sealed object.
Calculating encrypted seed for sealed object.
Calculating encrypted seed for ECC sealed object.
Calculating KDFe().
Calculating public part of sealed object.
Calculated public key name: 000becc2d498e45219ba27efb7775c0f70f40506c5d04be115aa0ecf0fec8890588e
Calculating private part of sealed object.
Calculating KDFa().
Calculating KDFa().
Calculated public key name: 000b459ad70e7d3693b2a933adcc31a27c1801cf4769c470bdf2a41a16e347db9a2c
Requesting JSON for token 0.
Requesting JSON for token 1.
Requesting JSON for token 2.
Requesting JSON for token 3.
Requesting JSON for token 4.
Requesting JSON for token 5.
Requesting JSON for token 6.
Requesting JSON for token 7.
Requesting JSON for token 8.
Requesting JSON for token 9.
Requesting JSON for token 10.
Requesting JSON for token 11.
Requesting JSON for token 12.
Requesting JSON for token 13.
Requesting JSON for token 14.
Requesting JSON for token 15.
Requesting JSON for token 16.
Requesting JSON for token 17.
Requesting JSON for token 18.
Requesting JSON for token 19.
Requesting JSON for token 20.
Requesting JSON for token 21.
Requesting JSON for token 22.
Requesting JSON for token 23.
Requesting JSON for token 24.
Requesting JSON for token 25.
Requesting JSON for token 26.
Requesting JSON for token 27.
Requesting JSON for token 28.
Requesting JSON for token 29.
Requesting JSON for token 30.
Requesting JSON for token 31.
PCR policy hash not yet enrolled, enrolling now.
PBKDF pbkdf2-sha512, time_ms 0 (iterations 1000).
Adding new keyslot -1 by passphrase, volume key provided by key (-1).
Selected keyslot 1.
Keyslot 1 assigned to digest 0.
Trying to allocate LUKS2 keyslot 1.
Found area 290816 -> 548864
Reusing PBKDF values (no benchmark flag is set).
Calculating attributes for LUKS2 keyslot 1.
Acquiring write lock for device /dev/vda3.
Opening lock resource file /run/cryptsetup/L_253:3
Verifying lock handle for /dev/vda3.
Device /dev/vda3 WRITE lock taken.
Checking context sequence id matches value stored on disk.
Reusing open ro fd on device /dev/vda3
Running keyslot key derivation.
Updating keyslot area [0x47000].
Opening locked device /dev/vda3
Verifying locked device handle (bdev)
Device size 37511757824, offset 16777216.
Device /dev/vda3 WRITE lock already held.
Trying to write LUKS2 header (16384 bytes) at offset 0.
Reusing open rw fd on device /dev/vda3
Checksum:7bdcd0096365e98423a3094e413c4a15b03e45bcf12a0bdac2f6906f190bb954 (in-memory)
Trying to write LUKS2 header (16384 bytes) at offset 16384.
Reusing open rw fd on device /dev/vda3
Checksum:7a38999d014ad1b11acfac3cf9181e3334af23541a255ceb23c1431c8ce0dc29 (in-memory)
Device /dev/vda3 WRITE lock released.
Unknown asymmetric algorithm id 0x0
Unknown hash algorithm id 0x0
Adding token text <{"type":"systemd-tpm2","keyslots":["1"],"tpm2-blob":"AGwAIDOqDR/qNzeq6WiNQPU6k0GgEanuMq4IPRNo6pGT/hOANVMo4BPGVp9FyMPiEdt1YQl8ebWtp2lmq+xR2aYaj+H/EpBhhxmcVykgyF2jai6dy/RPLs0YxbU1UE3V0/m/ScSdX7RV0AJUeXsATgAIAAsAAAAAACBRPAaGcIwG2Z3VWFZNkW4M/T7QMEDpHMbeWorInVsCtgAQACBDEVy/ZvjDW7Hg7uGvDClPVjTrX2J3D3fecnPIG6XCYABEACDozK+gyrpHSG82Ylbb0rDFE+gD2Yxh3/+YusU01mlzEQAgZbHVjpFj2u7bZmb7e1ay8cOyEpwklV3ZgniQ2py0spQ=","tpm2-pcrs":[],"tpm2-policy-hash":"513c0686708c06d99dd558564d916e0cfd3ed03040e91cc6de5a8ac89d5b02b6","tpm2-pin":false,"tpm2_pcrlock":false,"tpm2_pubkey_pcrs":[11],"tpm2_pubkey":"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUExTldTU3RWNDRIQVowdkdGaFBuUAp3eHJZbUhHRU1NeHVzUXRPVnBXNVFiLzN2dHRDMFpieG05MGdMQ2w0UjYzNUl2WGVwb2I1NmZhR2YyL2l5TTJyCnA2MlRHSnpLdFNLODFGNjFLQnlZRjdaS2pWeWFNTmMzSjdoMVBmQjdlT0oyZ1EzUGdybWpLM0lKdUkxT2hGMzcKUi9maWt3cFYvZ2VTU2diUGxqZ3IyUmw1b1d4VFluNXFDaC9CQ3dmbDVZTnp0N0lPOEVFdEUwTThycklvTHpTMQp4UnhmaWdoOTNQaEltdG5tbDN2ZDlnd1FIcnJPN2NzNGVsQVkrOFhSdW5kRVZCYmd1TTd6QzBIUlRocDRZYWh0Cmw4bVREQ1YwaGFZOVVvSWp0ZGJkcG10K3NEMmZyYllEVlk5Zis3VTJSZDdZcDFkaDhNc1BHMkJ5M1RVQ2l3a1EKYVFJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==","tpm2_srk":"gQAAAQAiAAtFmtcOfTaTsqkzrcwxonwYAc9HacRwvfKkGhbjR9uaLAAAAAEAWgAjAAsAAwRyAAAABgCAAEMAEAADABAAICn301ozNM+qA0RKpa/ptgcIYxLjBPYKJvcfxSpaCILlACBkbJ6JNOT36Spcm1s3hFSP+RVLj0JG+/ZQPRDTF+0jmA=="}>
Updating JSON for token -1.
Trying to load /lib/x86_64-linux-gnu/cryptsetup/libcryptsetup-token-systemd-tpm2.so.
Loading symbol cryptsetup_token_open@CRYPTSETUP_TOKEN_1.0.
Loading symbol cryptsetup_token_buffer_free@CRYPTSETUP_TOKEN_1.0.
Loading symbol cryptsetup_token_validate@CRYPTSETUP_TOKEN_1.0.
Loading symbol cryptsetup_token_dump@CRYPTSETUP_TOKEN_1.0.
Loading symbol cryptsetup_token_open_pin@CRYPTSETUP_TOKEN_1.0.
Loading symbol cryptsetup_token_version@CRYPTSETUP_TOKEN_1.0.
Token handler systemd-tpm2-1.0 systemd-v255 (255.4-1ubuntu8) loaded successfully.
Device size 37511757824, offset 16777216.
Acquiring write lock for device /dev/vda3.
Opening lock resource file /run/cryptsetup/L_253:3
Verifying lock handle for /dev/vda3.
Device /dev/vda3 WRITE lock taken.
Checking context sequence id matches value stored on disk.
Reusing open ro fd on device /dev/vda3
Trying to write LUKS2 header (16384 bytes) at offset 0.
Reusing open rw fd on device /dev/vda3
Checksum:1ca924e32f849aafdac3886857063e443c44262831abf6397d4771dc910d57df (in-memory)
Trying to write LUKS2 header (16384 bytes) at offset 16384.
Reusing open rw fd on device /dev/vda3
Checksum:06ffa55b609ae20703856539b40f6f47583919bd598888bbe9bd69a921f67e99 (in-memory)
Device /dev/vda3 WRITE lock released.
New TPM2 token enrolled as key slot 1.
Releasing crypt device /dev/vda3 context.
Releasing device-mapper backend.
Closing read only fd for /dev/vda3.
Closing read write fd for /dev/vda3.
Unloading systemd-tpm2 token handler.

I dunno, seems like a bug?

@arvidjaar
Copy link
Contributor

I did regenerate the partition and encrolling the key seems to default to 7+11 no matter what we specify in the flag --tpm2-public-key-pcrs

Yes, systemd-cryptenroll includes both signed policy for --tpm2-public-key-pcrs and PCR policy for --tpm2-pcrs. You really need to use --tpm2-pcrs= (set to empty value) to disable the latter.

And yes, it is not clear from the documentation. Even more confusing is the silent default for --tpm2-pcrs which kicks in even if you do not specify this parameter.

@Itxaka
Copy link
Author

Itxaka commented May 21, 2024

I did regenerate the partition and encrolling the key seems to default to 7+11 no matter what we specify in the flag --tpm2-public-key-pcrs

Yes, systemd-cryptenroll includes both signed policy for --tpm2-public-key-pcrs and PCR policy for --tpm2-pcrs. You really need to use --tpm2-pcrs= (set to empty value) to disable the latter.

And yes, it is not clear from the documentation. Even more confusing is the silent default for --tpm2-pcrs which kicks in even if you do not specify this parameter.

He @arvidjaar thanks for confirming but as you can see above, passing an empty --tpm2-pcrs= fails with:

SYSTEMD_LOG_LEVEL=debug systemd-cryptenroll --tpm2-public-key=/run/systemd/tpm2-pcr-public-key.pem --tpm2-signature=/run/systemd/tpm2-pcr-signature.json --tpm2-public-key-pcrs=11 --tpm2-pcrs="" --tpm2-device=auto /dev/vda3
Failed to find TPM2 pcrlock policy file 'pcrlock.json': No such file or directory
Allocating context for crypt device /dev/vda3.
Trying to open and read device /dev/vda3 with direct-io.
Initialising device-mapper backend library.
Trying to load LUKS2 crypt type from device /dev/vda3.
Crypto backend (OpenSSL 3.0.13 30 Jan 2024 [default][legacy] [external libargon2]) initialized in cryptsetup library version 2.7.0.
Detected kernel Linux 6.8.0-31-generic x86_64.
Loading LUKS2 header (repair disabled).
Acquiring read lock for device /dev/vda3.
Opening lock resource file /run/cryptsetup/L_253:3
Verifying lock handle for /dev/vda3.
Device /dev/vda3 READ lock taken.
Trying to read primary LUKS2 header at offset 0x0.
Opening locked device /dev/vda3
Verifying locked device handle (bdev)
LUKS2 header version 2 of size 16384 bytes, checksum sha256.
Checksum:75c52ed4e5c10691e6130acacade1e3460f101848bd397332d3b82beabde2fb1 (on-disk)
Checksum:75c52ed4e5c10691e6130acacade1e3460f101848bd397332d3b82beabde2fb1 (in-memory)
Trying to read secondary LUKS2 header at offset 0x4000.
Reusing open ro fd on device /dev/vda3
LUKS2 header version 2 of size 16384 bytes, checksum sha256.
Checksum:00a479f34a6f7250ebb4d23b5e3a6c101319c59aab55aee6bac80581dc9170eb (on-disk)
Checksum:00a479f34a6f7250ebb4d23b5e3a6c101319c59aab55aee6bac80581dc9170eb (in-memory)
Device size 37511757824, offset 16777216.
Device /dev/vda3 READ lock released.
PBKDF argon2id, time_ms 2000 (iterations 0), max_memory_kb 1048576, parallel_threads 4.
Requesting JSON for token 0.
Requesting JSON for token 1.
Requesting JSON for token 2.
Requesting JSON for token 3.
Requesting JSON for token 4.
Requesting JSON for token 5.
Requesting JSON for token 6.
Requesting JSON for token 7.
Requesting JSON for token 8.
Requesting JSON for token 9.
Requesting JSON for token 10.
Requesting JSON for token 11.
Requesting JSON for token 12.
Requesting JSON for token 13.
Requesting JSON for token 14.
Requesting JSON for token 15.
Requesting JSON for token 16.
Requesting JSON for token 17.
Requesting JSON for token 18.
Requesting JSON for token 19.
Requesting JSON for token 20.
Requesting JSON for token 21.
Requesting JSON for token 22.
Requesting JSON for token 23.
Requesting JSON for token 24.
Requesting JSON for token 25.
Requesting JSON for token 26.
Requesting JSON for token 27.
Requesting JSON for token 28.
Requesting JSON for token 29.
Requesting JSON for token 30.
Requesting JSON for token 31.
🔐 Please enter current passphrase for disk /dev/vda3: ••••Failed to adjust kernel keyring key timeout: Permission denied
Added key to kernel keyring as 1072956954.

Keyslot 0 priority 1 != 2 (required), skipped.
Trying to open LUKS2 keyslot 0.
Running keyslot key derivation.
Reading keyslot area [0x8000].
Acquiring read lock for device /dev/vda3.
Opening lock resource file /run/cryptsetup/L_253:3
Verifying lock handle for /dev/vda3.
Device /dev/vda3 READ lock taken.
Reusing open ro fd on device /dev/vda3
Device /dev/vda3 READ lock released.
Verifying key from keyslot 0, digest 0.
Using TPM2 TCTI driver 'device' with device '/dev/tpmrm0'.
Loaded TCTI module 'tcti-device' (TCTI module for communication with Linux kernel interface.) [Version 2]
TPM successfully started up.
Getting TPM2 capability 0x0000 property 0x0001 count 127.
Getting TPM2 capability 0x0002 property 0x011f count 256.
Getting TPM2 capability 0x0008 property 0x0000 count 508.
Getting TPM2 capability 0x0005 property 0x0000 count 1.
Calculated public key name: 000bad2a981c0eed83d41d9544750be2bc8f80b39f8af1ab3463bd7dbefb6576da3e
PolicyAuthorize calculated digest: 513c0686708c06d99dd558564d916e0cfd3ed03040e91cc6de5a8ac89d5b02b6
Not adding TPM2 entropy to the kernel random pool again.
Generating secret key data.
Getting TPM2 capability 0x0001 property 0x81000001 count 1.
Starting HMAC encryption session.
Creating object on TPM.
Successfully created object on TPM in 5ms.
Marshalling private and public part of HMAC key.
Completed TPM2 key sealing in 13.188ms.
Requesting JSON for token 0.
Requesting JSON for token 1.
Requesting JSON for token 2.
Requesting JSON for token 3.
Requesting JSON for token 4.
Requesting JSON for token 5.
Requesting JSON for token 6.
Requesting JSON for token 7.
Requesting JSON for token 8.
Requesting JSON for token 9.
Requesting JSON for token 10.
Requesting JSON for token 11.
Requesting JSON for token 12.
Requesting JSON for token 13.
Requesting JSON for token 14.
Requesting JSON for token 15.
Requesting JSON for token 16.
Requesting JSON for token 17.
Requesting JSON for token 18.
Requesting JSON for token 19.
Requesting JSON for token 20.
Requesting JSON for token 21.
Requesting JSON for token 22.
Requesting JSON for token 23.
Requesting JSON for token 24.
Requesting JSON for token 25.
Requesting JSON for token 26.
Requesting JSON for token 27.
Requesting JSON for token 28.
Requesting JSON for token 29.
Requesting JSON for token 30.
Requesting JSON for token 31.
PCR policy hash not yet enrolled, enrolling now.
Unsealing for verification...
Loading HMAC key into TPM.
Loading object into TPM.
Starting HMAC encryption session.
Starting policy session.
Building sealing policy.
Unknown hash algorithm id 0x0
Reading PCR selection: [n/a(11)]
WARNING:esys:src/tss2-esys/api/Esys_PCR_Read.c:304:Esys_PCR_Read_Finish() Received TPM Error 
ERROR:esys:src/tss2-esys/api/Esys_PCR_Read.c:105:Esys_PCR_Read() Esys Finish ErrorCode (0x000001c3) 
Failed to read TPM2 PCRs: tpm:parameter(1):hash algorithm not supported or not appropriate
Failed to unseal secret using TPM2: State not recoverable
Releasing crypt device /dev/vda3 context.
Releasing device-mapper backend.
Closing read only fd for /dev/vda3.

@arvidjaar
Copy link
Contributor

arvidjaar commented May 21, 2024

Building sealing policy.
Unknown hash algorithm id 0x0

What apparently happens here. The tpm2_pcr_values_to_mask:enroll_tpm2() calls tpm2_unseal() with the current value of hash_pcr_bank:

r = tpm2_unseal(tpm2_context,
hash_pcr_mask,
hash_pcr_bank,

The value of hash_pcr_bank is derived from the (default) value of --tpm2-pcrs and remains 0 if --tpm2-pcrs is empty:

if (n_hash_pcr_values > 0) {
size_t hash_count;
r = tpm2_pcr_values_hash_count(hash_pcr_values, n_hash_pcr_values, &hash_count);
if (r < 0)
return log_error_errno(r, "Could not get hash count: %m");
if (hash_count > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Multiple PCR banks selected.");
hash_pcr_bank = hash_pcr_values[0].hash;

This works as long as --tpm2-pcrs is used alone. But the tpm2_unseal() -> tpm2_build_sealing_pokicy() tries to read the combined value of --tpm2-pcrs+--tpm2-pubkey-pcrs using the hash_pcr_bank:

systemd/src/shared/tpm2-util.c

Lines 4218 to 4222 in 72192b6

static int tpm2_build_sealing_policy(
Tpm2Context *c,
const Tpm2Handle *session,
uint32_t hash_pcr_mask,
uint16_t pcr_bank,

systemd/src/shared/tpm2-util.c

Lines 4240 to 4241 in 72192b6

if ((hash_pcr_mask | pubkey_pcr_mask) != 0) {
r = tpm2_pcr_mask_good(c, pcr_bank, hash_pcr_mask|pubkey_pcr_mask);

Which fails due to bank (hash algorithm) being uninitialized.

@Itxaka
Copy link
Author

Itxaka commented May 21, 2024

Building sealing policy.
Unknown hash algorithm id 0x0

What apparently happens here. The tpm2_pcr_values_to_mask:enroll_tpm2() calls tpm2_unseal() with the current value of hash_pcr_bank:

r = tpm2_unseal(tpm2_context,
hash_pcr_mask,
hash_pcr_bank,

The value of hash_pcr_bank is derived from the (default) value of --tpm2-pcrs and remains 0 if --tpm2-pcrs is empty:

if (n_hash_pcr_values > 0) {
size_t hash_count;
r = tpm2_pcr_values_hash_count(hash_pcr_values, n_hash_pcr_values, &hash_count);
if (r < 0)
return log_error_errno(r, "Could not get hash count: %m");
if (hash_count > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Multiple PCR banks selected.");
hash_pcr_bank = hash_pcr_values[0].hash;

This works as long as --tpm2-pcrs is used alone. But the tpm2_unseal() -> tpm2_build_sealing_pokicy() tries to read the combined value of --tpm2-pcrs+--tpm2-pubkey-pcrs using the hash_pcr_bank:

systemd/src/shared/tpm2-util.c

Lines 4218 to 4222 in 72192b6

static int tpm2_build_sealing_policy(
Tpm2Context *c,
const Tpm2Handle *session,
uint32_t hash_pcr_mask,
uint16_t pcr_bank,

systemd/src/shared/tpm2-util.c

Lines 4240 to 4241 in 72192b6

if ((hash_pcr_mask | pubkey_pcr_mask) != 0) {
r = tpm2_pcr_mask_good(c, pcr_bank, hash_pcr_mask|pubkey_pcr_mask);

Which fails due to bank (hash algorithm) being uninitialized.

Awesome troubleshooting!

Locally building systemd and trying with some debug logging seems to confirm indeed that this is the issue.

I guess we should check if hash_pcr_mask AND pubkey_pcr_mask do not equal zero instead of merging both?
Gonna test a bit with the code

@Itxaka
Copy link
Author

Itxaka commented May 21, 2024

ah no, I missed your comment that its using hash_pcr_bank and that its 0. that should not be zero, it should get the bank from one flag or the other if one its empty.

Too complex to fix it myself :D

Itxaka added a commit to Itxaka/systemd that referenced this issue May 21, 2024
From issue systemd#32946

If you want to bind a policy to PCR11 and especify the tpm2-pcr
flag with and empty value, the bank calculation will fail as it tries to
use a non valid value for the calculation of hash.

This works around it by trying to use the public keys pcr values if
they are set and if the usual tpm2 pcrs banks are empty as to not fail

Signed-off-by: Itxaka <itxaka@kairos.io>
poettering added a commit to poettering/systemd that referenced this issue May 23, 2024
…but signed PCR binding is on

We so far derived the PCR bank to use from the PCR values specified fr
literal PCR binding. However, when that's not used then we left the bank
uninitialized – which will break if signed PCR binds are used (where we
need to pick a bank too after all).

Hence, let's explicitly pick a bank to use if literal PCR values are not
used, to make things just work.

Fixes: systemd#32946
@poettering
Copy link
Member

I prepped a simple fix in #32993. Could you give it a whirl?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Programming errors, that need preferential fixing cryptsetup
3 participants