#3355 PR merged: Storing and reading Self Encrypted Disk (SED) password from TPM

Labels: enhancement, ready-to-merge?

prolez opened issue at 2024-12-04 14:11:

Relax-and-Recover (ReaR) Pull Request Template

Please fill in the following items before submitting a new pull request:

Pull Request Details:
  • Type: Enhancement

  • Impact: Low

  • Reference to related issue (URL): https://github.com/rear/rear/issues/3074

  • How was this pull request tested? on production environment

  • Description of the changes in this pull request: Add functions in unlock-opal-disks to offer storing password in TPM2

jsmeix commented at 2024-12-06 13:46:

@prolez
thank you for your enhancement for ReaR!

We are currently in the final process of releasing ReaR 2.8,
cf. https://github.com/rear/rear/issues/3238#issuecomment-2516532775
so we cannot include this PR in the current ReaR 2.8.
We will have a look for the subsequent ReaR 3.0.

I am not a SED user so I cannot try out things on my own.
I can only comment from what I notice form plain looking
at the code changes of this pull request in
https://github.com/rear/rear/pull/3355/files

I notice at_password and when I see something like
"password" or "encryption" or "key" in the code
it indicates the code deals with some kind of "secret value"
and then I am wondering if the code deals sufficiently well
with secrets.

See the inital comments in usr/share/rear/conf/default.conf
currently online at
https://github.com/rear/rear/blob/master/usr/share/rear/conf/default.conf#L13
how to deal sufficiently well with secrets.

See also the function LogSecret() in
usr/share/rear/lib/_input-output-functions.sh
currently online at
https://github.com/rear/rear/blob/master/usr/share/rear/lib/_input-output-functions.sh#L462

See also our "Relax-and-Recover Security Architecture" document at
https://relax-and-recover.org/documentation/security-architecture
which reads (excerpt)

To facilitate protecting secrets even from
verbose tracing of the Bash scripts (set -x),
it is important to wrap statements
that handle secrets like this:

# set a variable with a secret
{ VAR='secret_value' ; } 2>>/dev/$SECRET_OUTPUT_DEV

# use the variable with the secret
{ COMMAND $SECRET_ARGUMENT ; } 2>>/dev/$SECRET_OUTPUT_DEV

For an example how the latter is used see
usr/share/rear/rescue/default/500_ssh.sh
online at
https://github.com/rear/rear/blob/master/usr/share/rear/rescue/default/500_ssh.sh

For an example how the latter is used to get user input
in a confidential way, see the comment of the UserInput function
in usr/share/rear/lib/_input-output-functions.sh
currently online at
https://github.com/rear/rear/blob/master/usr/share/rear/lib/_input-output-functions.sh#L1090

To verify that your code deals sufficiently well with secrets
run it in ReaR debugscript mode with '-D' e.g. like

# rear -D mkrescue

and then carefully inspect your ReaR log file
and verify that no secret value appears therein.

prolez commented at 2024-12-19 15:58:

@jsmeix
Thank you for your feedback!

I based this development on the OPAL_PBA_TKN functionality, which is only used in the mkopalpba function.
The mkrescue function does not utilize this functionality, so I am unable to debug it like this.
The password is managed the same way (like OPAL_PBA_TKN) in the PBA, which resides in the shadow MBR.
I believe this implementation is correct and safe, but I could be mistaken.

paulalesius commented at 2025-01-11 05:47:

@jsmeix Thank you for your feedback!

I based this development on the OPAL_PBA_TKN functionality, which is only used in the mkopalpba function. The mkrescue function does not utilize this functionality, so I am unable to debug it like this. The password is managed the same way (like OPAL_PBA_TKN) in the PBA, which resides in the shadow MBR. I believe this implementation is correct and safe, but I could be mistaken.

The way Secure Boot works in combination with TPM2 is it attempts to measure different parts of the hardware and software during boot, the measured hashes are stored in registers called "PCR registers". The correct way to use TPM is to create a sealed and encrypted object in TPM which will only be released when the specified PCR measurments are the expected measurments to prove that the hardware or software has not been tampered with.

From what I can see in the patch, this uses the TPM as a database and it can be fetched regardless of whether the hardware/firmware/boot software has been tampered with (For instance had UEFI configuration changed to disable Secure Boot or had the firmware/hardware modified in any way).

I'm not an expert in TPM2 but it seems to require the creation of keys first:

tpm2_createprimary -C o -c primary.ctx

And then you can seal the token in TPM based on PCR measruments:

echo -n "<your_token>" | tpm2_create -C primary.ctx -u key.pub -r key.priv -L "sha256:0,2,7" -a "fixedtpm|fixedparent|noda|adminwithpolicy" -i -

And load the sealed and encrypted object into TPM:

tpm2_load -C primary.ctx -u key.pub -r key.priv -c sealedobject.ctx

The "sha256:0,2,7" specifies that the token is sealed based on PCR0 PCR2 and PCR7, and if these TPM registers contain unexpected hashes then the system has been modified/tampered with and the token will not be released from TPM to unlock in PBA. It is also necessary to allow the user to configure which PCR values to bind to, as different computers have different security requirements and configurations.

I'm unsure if TPM2 works with multiple primary keys but you can check how systemd-cryptenroll stores the LUKS2 password in TPM to enable automatic authentication during boot, bound by PCR measurments:

systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7+8 /dev/$DEVICE

https://github.com/systemd/systemd/blob/main/src/cryptenroll/cryptenroll-tpm2.c

A new TPM2 context is created or reused if already present (tpm2_create, but it uses an abstraction layer Tpm2Context instead of calling the shell commands):

r = tpm2_context_new_or_warn(device, &tpm2_context);

Without sealing the key, it defeats the purpose of using TPM when the keys are released regardless of whether the system has been modified, or had the disk changed just to fetch the password from TPM.

prolez commented at 2025-02-26 10:19:

@jsmeix Thank you for your feedback!
I based this development on the OPAL_PBA_TKN functionality, which is only used in the mkopalpba function. The mkrescue function does not utilize this functionality, so I am unable to debug it like this. The password is managed the same way (like OPAL_PBA_TKN) in the PBA, which resides in the shadow MBR. I believe this implementation is correct and safe, but I could be mistaken.

The way Secure Boot works in combination with TPM2 is it attempts to measure different parts of the hardware and software during boot, the measured hashes are stored in registers called "PCR registers". The correct way to use TPM is to create a sealed and encrypted object in TPM which will only be released when the specified PCR measurments are the expected measurments to prove that the hardware or software has not been tampered with.

From what I can see in the patch, this uses the TPM as a database and it can be fetched regardless of whether the hardware/firmware/boot software has been tampered with (For instance had UEFI configuration changed to disable Secure Boot or had the firmware/hardware modified in any way).

I'm not an expert in TPM2 but it seems to require the creation of keys first:

tpm2_createprimary -C o -c primary.ctx

And then you can seal the token in TPM based on PCR measruments:

echo -n "<your_token>" | tpm2_create -C primary.ctx -u key.pub -r key.priv -L "sha256:0,2,7" -a "fixedtpm|fixedparent|noda|adminwithpolicy" -i -

And load the sealed and encrypted object into TPM:

tpm2_load -C primary.ctx -u key.pub -r key.priv -c sealedobject.ctx

The "sha256:0,2,7" specifies that the token is sealed based on PCR0 PCR2 and PCR7, and if these TPM registers contain unexpected hashes then the system has been modified/tampered with and the token will not be released from TPM to unlock in PBA. It is also necessary to allow the user to configure which PCR values to bind to, as different computers have different security requirements and configurations.

I'm unsure if TPM2 works with multiple primary keys but you can check how systemd-cryptenroll stores the LUKS2 password in TPM to enable automatic authentication during boot, bound by PCR measurments:

systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7+8 /dev/$DEVICE

https://github.com/systemd/systemd/blob/main/src/cryptenroll/cryptenroll-tpm2.c

A new TPM2 context is created or reused if already present (tpm2_create, but it uses an abstraction layer Tpm2Context instead of calling the shell commands):

r = tpm2_context_new_or_warn(device, &tpm2_context);

Without sealing the key, it defeats the purpose of using TPM when the keys are released regardless of whether the system has been modified, or had the disk changed just to fetch the password from TPM.

@paulalesius Regrettably, my schedule doesn't permit me to develop and test this approach for now. Could you take it on, as I believe it is a better solution?

gdha commented at 2025-05-09 08:56:

Thanks for working on this, much appreciated!

TBH, all of this is quite cryptic for me to understand it like this, but all of the OPAL code is like that, too...

Could you also update https://github.com/rear/rear/blob/master/doc/user-guide/13-tcg-opal-support.adoc together with this change to explain how to use it and what the requirements are?

Please also note with which distros you managed to test this, ideally we cover RHEL/SLES/Debian.

@prolez This seems the last open item for you (updating the document). Once that is done we can merge this PR - thanks for your contribution.

prolez commented at 2025-06-12 15:24:

@gdha Sorry for the response time... I wanted to position myself in the same area as the AuthToken container management, but I couldn't locate it. Should we consider adding a new section for : Storing and reading Self Encrypted Disk (SED) password automatically on boot? (either from an external device or from the TPM)

gdha commented at 2025-06-13 06:41:

@gdha Sorry for the response time... I wanted to position myself in the same area as the AuthToken container management, but I couldn't locate it. Should we consider adding a new section for : Storing and reading Self Encrypted Disk (SED) password automatically on boot? (either from an external device or from the TPM)

@prolez Sounds good to me - thanks!

gdha commented at 2025-06-17 08:47:

@rear/contributors Would like to merge this PR upcoming Friday if there are no updates or comments?

gdha commented at 2025-06-20 09:55:

@prolez The PR has been merged. Thank you very much for your contribution.


[Export of Github issue for rear/rear.]