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

Measure LUKS header fully with luksHeaderBackup, instead of summarized with luksDump #1089

Closed
rustybird opened this issue Jan 16, 2022 · 12 comments

Comments

@rustybird
Copy link

The LUKS header is currently measured via the output of cryptsetup luksDump, which is a human-readable summary of what that version of cryptsetup considers to be relevant header information.

But attacks against LUKS may involve the crafting of an unusual header (CVE-2021-4122, QSB-019), and a hypothetical future attack of this type might not change the luksDump output at all.

Consider measuring via cryptsetup luksHeaderBackup instead (like Qubes Anti Evil Maid), to ensure that every byte of the header is taken into account.

@Tonux599
Copy link
Contributor

If my understanding is correct, at the moment we only confirm the integrity of LUKS header when a user chooses to say yes to the 'Do you wish to add a disk encryption to the TPM' prompt. Is there any reason why we couldn't move away from that and instead keep a hash of luksHeaderBackup in kexec_hashes.txt of /boot which would be signed?

@tlaurion
Copy link
Collaborator

@Tonux599 :

If my understanding is correct, at the moment we only confirm the integrity of LUKS header when a user chooses to say yes to the 'Do you wish to add a disk encryption to the TPM' prompt.

The integrity of LUKS header is verified only when the user chose to say yes to "Do you wish to add a disk encryption to the TPM" prompt when choosing to boot the default boot option which then asks for TPM disk unlock key passphrase, if that is what you meant.

@rustybird As of now, LUKS header is an ouput from LuksDump instead of luksHeaderBackup, correct.

That human readable output is appended into /tmp/luksDump.txt for each encrypted device found under /boot/kexec_key_devices.txt, saved at the time of saving key.

I'm adding to this to discussion because this complexifies a little what would need to be done to save binary header for multiple disks when the user decides to have the same Disk Unlock Key (aka TPM disk encryption key) to unlock multiple disks, if OS configured to attempt to unlock those drives at boot as well.

Basically, we could hack around actual code to output individual luksHeaderBackup files and then concatenate them under /tmp/luksDump.txt for measurement prior of sealing/unsealing.

Thoughts? Comments? PR?

@rustybird
Copy link
Author

Basically, we could hack around actual code to output individual luksHeaderBackup files and then concatenate them under /tmp/luksDump.txt for measurement prior of sealing/unsealing.

Why even concatenate them at all, couldn't tpm extend be called independently after each luksHeaderBackup?

@tlaurion
Copy link
Collaborator

tlaurion commented Jan 18, 2022

@Tonux599

Is there any reason why we couldn't move away from that and instead keep a hash of luksHeaderBackup in kexec_hashes.txt of /boot which would be signed?

Well, keeping the whole luksHeaderBackup under /boot would go against LUKS design decisions.

That header is the only thing that needs to be backuped/restored to be able to have an unusable encrypted container while in transit (if wiped) and is used in some use cases; You backup the header, wipe the header. Travel.

You keep an encrypted backup in the cloud/ have a physical backup copy delivered to your traveling destination and have plausible deniability while in transit and boot from detached signed ISOs from USB Thumb drive while in transit.

The use case: Travel with all your encrypted data but cannot use its content until arrived to your destination, where only restoration of that header and known passphrase/communicated provisioned passphrase is needed upon safe arrival.
That small Header can also be communicated in any other ways and you can actually restore it from Heads prior of booting into encrypted LUKS container's OS installation.

@Tonux599 : I'm not sure we want to keep the whole header backup. In current implementation switch, I think we should continue outputting into /tmp/, concatenate into /tmp/luksDump.txt headers of /boot/kexec_key_devices.txt defined encrypted drives (or change all references to /tmp/luksDump.txt into /tmp/luksHeaderBackup.txt for coherence) and have that file measured. Before booting/entering into recovery shell, /tmp content is wiped so that is not accessed and TPM is extended to not have access to final measurements and be able to unseal secrets.

Additional thoughts?

@tlaurion
Copy link
Collaborator

tlaurion commented Jan 18, 2022

Basically, we could hack around actual code to output individual luksHeaderBackup files and then concatenate them under /tmp/luksDump.txt for measurement prior of sealing/unsealing.

Why even concatenate them at all, couldn't tpm extend be called independently after each luksHeaderBackup?

@rustybird : Will verify. As long as the same process is done when measured/sealed/unsealed, I would say why not.

Meanwile, as a trace, this is where LUKS are measured/sealed/unsealed:

user@heads-tests:~/heads/initrd$ grep -Rin luksDump.txt
bin/kexec-seal-key:81:# to get the /tmp/luksDump.txt file.  We use PCR16
bin/kexec-seal-key:85:luks_pcr=`tpm calcfuturepcr -ix 16 -if /tmp/luksDump.txt`
bin/qubes-measure-luks:11:done > /tmp/luksDump.txt
bin/qubes-measure-luks:13:tpm extend -ix 6 -if /tmp/luksDump.txt \
user@heads-tests:~/heads/initrd$ grep -Rin kexec_key_devices.txt
bin/kexec-select-boot:328:	TMP_KEY_DEVICES="/tmp/kexec/kexec_key_devices.txt"
bin/kexec-seal-key:21:KEY_DEVICES="$paramsdir/kexec_key_devices.txt"
bin/kexec-save-default:45:KEY_DEVICES="$paramsdir/kexec_key_devices.txt"
bin/kexec-insert-key:6:TMP_KEY_DEVICES="/tmp/kexec/kexec_key_devices.txt"
bin/kexec-save-key:52:rm -f $paramsdir/kexec_key_devices.txt || true
bin/kexec-save-key:56:	echo "$dev $uuid" >> $paramsdir/kexec_key_devices.txt \

@Tonux599
Copy link
Contributor

@tlaurion I wasn't suggesting we keep the whole header backed up. My thinking was along these lines:

- User boots into heads.
- User select default boot.
- the contents of kexec_hashes.txt is check against files in boot and PGP checked.
- iterate through each LUKS UUID attached to the system
     - Dump their headers and generate sha256 for each one
     - If UUID exists in /boot/luks_sums.txt AND checksum is correct AND /boot/luks_sums.txt is PGP signed correctly.
          - Boot into system
     - Else
          - If uuid exists but checksum failed
               - Notify user or modified LUKS header
          - else
               - Ask user if they would like to add this checksum of the drives LUKS header to /boot/luks_sums.txt
               - Ask to sign /boot/luks_sums.txt

Only threw that together in 5 mins but hopefully conveys my idea.

@tlaurion
Copy link
Collaborator

@Tonux599 I like the idea!

But an addition to the current implementation, which use case where LUKS disk unlock key released by TPM.

Problem with actual code base is that the LUKS UUID you are talking about are stored under /boot/kexec_key_devices.txt only by:
bin/kexec-save-default:45:KEY_DEVICES="$paramsdir/kexec_key_devices.txt"

We could definitely implement that dynamic, and implement under kexec-sign-config if LUKS container are detected.
@MrChromebox would you be interested in such implementation?

@tlaurion
Copy link
Collaborator

tlaurion commented Jan 18, 2022

@Tonux599 @rustybird please take a look into #1090

@SvenSemmler since you are the only one I know unlocking 2 devices with one Disk Unlock Key passphrase, would you mind testing and reporting back here? Should work!

tlaurion added a commit to tlaurion/heads that referenced this issue Jan 18, 2022
@MrChromebox
Copy link
Contributor

@tlaurion I discussed this with @kylerankin and as Purism doesn't use this feature currently, not have plans to do so, we don't have a strong opinion one way or another as to how LUKS unlocking via TPM is implemented

@tlaurion
Copy link
Collaborator

tlaurion commented Jan 19, 2022

@MrChromebox @kylerankin: what @Tonux599 proposed has a workflow had nothing to do with LUKS unlocking from TPM disk unlock key, but with having LUKS header being verified prior of booting an OS from a LUKS container that was hacked on and different then measured, as reported by @rustybird on OP for possible LUKS2 existing vulns and future ones:

But attacks against LUKS may involve the crafting of an unusual header (CVE-2021-4122, QSB-019), and a hypothetical future attack of this type might not change the luksDump output at all.

#1090 just replaces luksDump as requested in OP. But would not inform of what failed in measurements leading to a failed unsealing of TPM disk unlock key.

It would just refuse to unseal TPM LUKS sealed disk unlock key. Without telling why.

While not having LUKS disk unlock sealed file released by TPM leaves the user blunt about anything having happened on the LUKS container at all for the moment, other then #1090.

@tlaurion
Copy link
Collaborator

tlaurion commented Jan 19, 2022

#1091 proposed by @hardenedvault.
luksDump.txt there is just sha256sum of the different luksDumpHeader dumped and deleted. I like the approach.

Will create another issue from that comment and merge #1091.

@tlaurion
Copy link
Collaborator

OP issue fixed on merged #1091. #1090 closed because #1091 cleaner.

Implementation suggestion of @Tonux599 moved to #1092.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants