Skip to content

Add TPM 1.2 support #462

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

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open

Add TPM 1.2 support #462

wants to merge 16 commits into from

Conversation

oldium
Copy link
Contributor

@oldium oldium commented May 5, 2024

This patch series adds TPM 1.2 support and fixes few other things (I can split this into multiple Pull Requests if you wish):

  • Added missing shutdown SystemD dependencies when using DefaultDependencies=no.
  • When Dracut without SystemD is used, benefit cryptsetup unlocking workflow to let it handle the crypttab and other options. This uses pipe to unlock with password similarly like the initramfs-tools image does. See commit message for more details.
  • Added full support for TPM 1.2.

Status:

  • [✅ Done] Clevis encrypt, decrypt, bind support
  • [✅ Done] initramfs-tools support
  • [✅ Done] Systemd support
  • [✅ Done] Manual page for clevis-encrypt-tpm1
  • [✅ Done] Tests for tpm1 pin
  • [✅ Done] Dracut support

Example usage:

  • Boot and unlock with TPM1.2:
    clevis luks bind -d /dev/<device> tpm1 '{"pcr_ids":"0,4,7"}'
  • Encrypt and decrypt:
    echo test | clevis encrypt tpm1 '{"pcr_ids":"0,4,7"}' | clevis decrypt

Tested:

  • Tested with initramfs-tools, used both TPM 1.2 and null pins with "fail":true to test success and failed unlocking
  • Tested with Dracut with SystemD. Tested both success and failed cases
  • Tested with Dracut without SystemD (module was disabled). Tested both success and failed cases
  • Tested with Dracut without SystemD (module was disabled), with programmatically changed detection that null pin is a network pin. Tested that with rd.neednet the unlocking happens after network gets online.

Fixes: #84, #456

@oldium oldium force-pushed the feature/tpm1 branch 2 times, most recently from 556332d to 04d5e9f Compare May 5, 2024 22:09
@oldium oldium force-pushed the feature/tpm1 branch 4 times, most recently from 2c32eb7 to a7de265 Compare May 8, 2024 14:26
@oldium oldium force-pushed the feature/tpm1 branch 2 times, most recently from b4cc648 to e83e669 Compare June 23, 2024 12:20
@oldium oldium force-pushed the feature/tpm1 branch 3 times, most recently from dc1c5c3 to 40bfdf4 Compare June 23, 2024 13:46
@oldium oldium marked this pull request as ready for review June 23, 2024 14:08
@oldium oldium changed the title [WIP] Add TPM 1.2 support Add TPM 1.2 support Jun 23, 2024
@oldium
Copy link
Contributor Author

oldium commented Jun 30, 2024

Work is done, pre-built packages for Debian 12 and amd64 arch are available here https://github.com/oldium/clevis/releases/tag/v20_tpm1

@oldium
Copy link
Contributor Author

oldium commented Jul 3, 2024

The CentOS test build image needs some love, the mirrorlist.centos.org site does not exist any more it seems.
image

@oldium
Copy link
Contributor Author

oldium commented Jul 3, 2024

Rebased to latest master to fix the build.

Signed-off-by: Oldřich Jedlička <[email protected]>
The DefaultDependencies=yes option adds conflicting dependency on the
shutdown.target automatically to ensure the service is terminated during
the shutdown, so add it when we use DefaultDependencies=no.

Signed-off-by: Oldřich Jedlička <[email protected]>
Current Dracut integration for bootup without Systemd ignores all
cryptsetup options, which are usually handled by Dracut itself (like
reading /etc/crypttab). We need to hook into the Dracut cryptsetup process
in order to allow Dracut handling the options and us handling the password
only.

Dracut uses generated udev rules to create cryptsetup unlocking scripts
in initqueue/settled dynamically when the corresponding device appears. The
unlocking tries to unlock by the key file first and then by password read
from user.

We can hook into the key file reading stage by providing our own pipe and
send the password via the pipe similarly to how the initramfs-tools
clevisloop is doing it. There is one difference, though, we have only one
try to unlock, but that should be enough.

For the network pins (tang and sss/tang at the moment) we can move the
generated Dracut cryptsetup unlocking scripts to initqueue/online to
ensure the unlocking happens at the right time.

Signed-off-by: Oldřich Jedlička <[email protected]>
This is useful during testing.

Signed-off-by: Oldřich Jedlička <oldium.pro.gmail.com>
Signed-off-by: Oldřich Jedlička <[email protected]>
This is a weak requirement, so when TCSD is missing, it does not influence
the Clevis askpass service startup. Similarly if the TCSD startup fails,
it does not affect the Clevis askpass service startup.

Signed-off-by: Oldřich Jedlička <[email protected]>
Signed-off-by: Oldřich Jedlička <[email protected]>
The command fails in Docker or otherwise limited environments, so skip the
test when it is not usable.

Signed-off-by: Oldřich Jedlička <[email protected]>
Copy link

@akostadinov akostadinov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just performed a clean install on Fedora. Works like a charm. Thanks a lot!

Can any member of the repo review and get this merged? It's very useful to get skylake class machines running as they make quiet good servers.

[ "$decrypted" != "" ] || continue
local cache="/var/cache/clevis-disks/${CRYPTTAB_SOURCE//\//_}"
if [ ! -f "$cache" ]; then
local pins=$(clevis_luks_read_used_pins "$CRYPTTAB_SOURCE")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess return code from clevis_luks_read_used_pins should be checked here and return 1 in case of error

local cache="/var/cache/clevis-disks/${CRYPTTAB_SOURCE//\//_}"
if [ ! -f "$cache" ]; then
local pins
pins=$(clevis_luks_read_used_pins "$CRYPTTAB_SOURCE")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess return code from clevis_luks_read_used_pins should be checked here and return 1 in case of error

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, most probably. I will also check this code, which after all that time looks suspicious to me too.

echo >&2
echo "$SUMMARY": >&2
echo >&2
echo " -d DEV The LUKS device to list bound pins" >&2
echo >&2
echo " -s SLOT The slot number to list" >&2
echo >&2
echo " -p Print only a sorted space-separated list of bound pins" >&2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not this be rewritten to something like:
Print only a sorted space-separated list of used pins bound to the specified device

Copy link
Collaborator

@sarroutbi sarroutbi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. Could you please review provided comments?

@sarroutbi
Copy link
Collaborator

sarroutbi commented Apr 10, 2025

I have downloaded the code in this branch and tried to test it on a VM with TPM1 chip. I followed next steps:

  1. Install dependencies:
sudo dnf install -y meson gcc clang cmake jose libjose-devel cryptsetup-devel socat trousers tpm-tools tpm2-tools luksmeta libluksmeta-devel
  1. Installed clevis:
mkdir build; pushd build; meson setup --prefix=/usr --wipe ..; meson compile -v; sudo meson install; popd
  1. Enabled tcsd daemon:
sudo systemctl enable --now tcsd.service
  1. I checked status of tpm:
tpm_selftest 
  TPM Test Results: 53687574 646f776e 20303030 30303030 320a
  1. TPM encryption/decryption is failing with next errors:
echo hi | clevis encrypt tpm1 '{}' 
Tspi_Context_LoadKeyByUUID failed: 0x00002020 - layer=tcs, code=0020 (32), Key not found in persistent storage
Unable to seal jwk
  1. I checked the repository and branches:
$ git remote -v
origin  https://github.com/oldium/clevis (fetch)
origin  https://github.com/oldium/clevis (push)
$ git branch
* feature/tpm1
  1. I checked unlocking is correct through other pin:
echo hi | clevis encrypt tang '{"url":"localhost"}' -y | clevis decrypt

@oldium : Can you please provide some hints about the process or commands to execute to verify what can be go wrong in my scenario? I am using Fedora 41. This is a brand new VM, so I discard some previous Clevis installation ...

@akostadinov
Copy link

@sarroutbi , did you start tcsd.service (not only enable it)? Did you run your commands as root?

@sarroutbi
Copy link
Collaborator

sarroutbi commented Apr 10, 2025

@sarroutbi , did you start tcsd.service (not only enable it)? Did you run your commands as root?

Yes, it is. Option --now enables it and starts it:

sudo systemctl status tcsd.service
● tcsd.service - TCG Core Services Daemon
     Loaded: loaded (/usr/lib/systemd/system/tcsd.service; enabled; preset: disabled)
     ...
     Active: active (running) since Thu 2025-04-10 12:27:14 CEST; 1h 7min ago

@oldium
Copy link
Contributor Author

oldium commented Apr 10, 2025

@sarroutbi Do you own the TPM with “well-known” SRK password? For fresh TPM installations (like new VM, first time usage of TPM on existing HW) you need to call tpm_takeownership --srk-well-known and for existing installations tpm_changeownerauth --srk --set-well-known (as documented). You can check if TPM works correctly by issuing the same commands as TPM1 PIN:

$ echo test | tpm_sealdata -z
-----BEGIN TSS-----
-----TSS KEY-----
AQEAAAARAAAABAEAAAABAAMAAQAAAAwAAAgAAAAAAgAAAAAAAAAAAAABALqHTk5k
/c9idJgjUD676OErez4BG2ZXX+kcMJYyD5l3sUuO+FbARcwHWDil5kOf1VwKEoBR
XLu1u6Cpo/+Ha8nDdmKEoSAmCL7cqF125jLeZPBqYlOm4R03FFp5ShUdp1UOLN0y
J+fQaE2C11R0JPrLqzao+6AMqkY3DVlY2EYnnUH4cJlSIvcxK3WDsXcNAI9Hr02a
Ku2hHXrXTrQlVKe+LEfyOQfqFij1ix+ApJ2nMh5lTwXgE4RZhCFRQdI5gjTTirAf
QBTQJnAgPYVbgxUOgjEN8She4y4Qks1cGjjrvGCYGuwvbbuZkU/3IJPXi05ZThQB
2/9fg4b65wh9YyEAAAEAcMH4BeLZyaYHwacvNYcZO3iE7q8ImjwvwuAbaF8b+1Ja
AFuNayK1fdwluCl0g0tvKz4WEdkDeYxA6Q4hhgL8yWquwnqGYG8vY7oAJIB8ONMj
FV3VVuVIVW2rUd2D4Kpgn0ErM79QJ8ULtSwVM03VPOsdCYce0coktQDiAvDyNkQk
ae046UrPYlznI37SQ/D+FCAW4kL/D6bc6QMPH2kgcBTdRYhLhBQ4uWkpf6+DfFi2
D7ZXVTQp7+adObiYDc0Gd9YRV2JLW3e017Yls7ky8Ks8AHDyF4QuHvta5gRrrAO6
LMB9sZTVtZZEsUf7psUH2Aa3B4j8pm/FrEiF6s0zvQ==
-----ENC KEY-----
Symmetric Key: AES-256-CBC
AQEAAAAAAAAAAAEAJyeDJqzvS0avmsYyEMfVN8PhPhS5TWr5nmwu8RWg9Yd9Jzov
buMg9tfOK7EGiMo+tnspYlKzszuFY922VN3NAT6do5prqao7+/jp3legzczXCj9V
MZdels6WeoobRyXHrFXHkAuCmXuVF9xw/LTsEuTuLkLCgqUXZY2C/93VSZNPFrQs
4Rr763HIKPgnLSS6SRVPqGN0BAihVBbUQ9FGAtOZfwbNaX3QMYtxRGs+r/ylDN0w
MznfDPhUnvxuUFToqQK8kZRbXB4x8TnlfgB7RJ3m6CX58RAefLJaPG+oU5YG84bX
rvPDf2QMrek4xyhe8RGiFfKeLDtI+RgrZEOs1Q==
-----ENC DAT-----
LZq+S5A2z6ybFhGU2KK3kA==
-----END TSS-----

If you still see error even after taking ownership, there might be problem with your /var/lib/tpm/system.data.

@oldium
Copy link
Contributor Author

oldium commented Apr 10, 2025

Thanks for the PR. Could you please review provided comments?

Yes, thanks for review, I will update the commits.

@sarroutbi
Copy link
Collaborator

@sarroutbi Do you own the TPM with “well-known” SRK password? For fresh TPM installations (like new VM, first time usage of TPM on existing HW) you need to call tpm_takeownership --srk-well-known and for existing installations tpm_changeownerauth --srk --set-well-known (as documented). You can check if TPM works correctly by issuing the same commands as TPM1 PIN:

$ echo test | tpm_sealdata -z
-----BEGIN TSS-----
-----TSS KEY-----
AQEAAAARAAAABAEAAAABAAMAAQAAAAwAAAgAAAAAAgAAAAAAAAAAAAABALqHTk5k
/c9idJgjUD676OErez4BG2ZXX+kcMJYyD5l3sUuO+FbARcwHWDil5kOf1VwKEoBR
XLu1u6Cpo/+Ha8nDdmKEoSAmCL7cqF125jLeZPBqYlOm4R03FFp5ShUdp1UOLN0y
J+fQaE2C11R0JPrLqzao+6AMqkY3DVlY2EYnnUH4cJlSIvcxK3WDsXcNAI9Hr02a
Ku2hHXrXTrQlVKe+LEfyOQfqFij1ix+ApJ2nMh5lTwXgE4RZhCFRQdI5gjTTirAf
QBTQJnAgPYVbgxUOgjEN8She4y4Qks1cGjjrvGCYGuwvbbuZkU/3IJPXi05ZThQB
2/9fg4b65wh9YyEAAAEAcMH4BeLZyaYHwacvNYcZO3iE7q8ImjwvwuAbaF8b+1Ja
AFuNayK1fdwluCl0g0tvKz4WEdkDeYxA6Q4hhgL8yWquwnqGYG8vY7oAJIB8ONMj
FV3VVuVIVW2rUd2D4Kpgn0ErM79QJ8ULtSwVM03VPOsdCYce0coktQDiAvDyNkQk
ae046UrPYlznI37SQ/D+FCAW4kL/D6bc6QMPH2kgcBTdRYhLhBQ4uWkpf6+DfFi2
D7ZXVTQp7+adObiYDc0Gd9YRV2JLW3e017Yls7ky8Ks8AHDyF4QuHvta5gRrrAO6
LMB9sZTVtZZEsUf7psUH2Aa3B4j8pm/FrEiF6s0zvQ==
-----ENC KEY-----
Symmetric Key: AES-256-CBC
AQEAAAAAAAAAAAEAJyeDJqzvS0avmsYyEMfVN8PhPhS5TWr5nmwu8RWg9Yd9Jzov
buMg9tfOK7EGiMo+tnspYlKzszuFY922VN3NAT6do5prqao7+/jp3legzczXCj9V
MZdels6WeoobRyXHrFXHkAuCmXuVF9xw/LTsEuTuLkLCgqUXZY2C/93VSZNPFrQs
4Rr763HIKPgnLSS6SRVPqGN0BAihVBbUQ9FGAtOZfwbNaX3QMYtxRGs+r/ylDN0w
MznfDPhUnvxuUFToqQK8kZRbXB4x8TnlfgB7RJ3m6CX58RAefLJaPG+oU5YG84bX
rvPDf2QMrek4xyhe8RGiFfKeLDtI+RgrZEOs1Q==
-----ENC DAT-----
LZq+S5A2z6ybFhGU2KK3kA==
-----END TSS-----

If you still see error even after taking ownership, there might be problem with your /var/lib/tpm/system.data.

This was the problem. Thanks !!!

I can continue my smoke testing after taking ownsership

@sarroutbi
Copy link
Collaborator

sarroutbi commented Apr 10, 2025

After fixing TPM ownership I was able to boot with TPM1 simulated chip in a Fedora 41 VM so changes LGTM.

After including suggested changes, please, let's wait for @sergio-correia review in order to double check about it and have a second opinion. Once he agrees, we can merge this

Thanks again @oldium for this great contribution

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 this pull request may close these issues.

Support for TPM 1.x
7 participants