| |

Ubuntu 20.04 and TPM2 encrypted system disk

An update: I am adding a link to a post where I share my thoughts about the additional steps required to protect a Linux system against physical access to data. I add it at the top of this article, because I want some insight from you – the people who might read this post. It deals with the chain of trust beyond the scope of this article – the entire boot process. Please proceed reading to handle only the technical aspects of obtaining your protected system’s encryption keys using TPM2, and remember that this is not enough to protect a system entirely against this attack vector. You key can be obtained if the remaining of the tasks, which are out of the scope of this article, are not followed. End of update

Following the conversation around a past post about Ubuntu 18.04 and TPM2 encrypted system disk (can be found here), I have added a post about using a more modern Ubuntu (20.04) with TPM2. This post includes all the updates (many thanks to the commenter kelderek for setting up a very well working setup!) and has just been tested on a virtual Ubuntu with (virtual) TPM2 device. A note about how to get this setup – sometime in the future. Please be advised that this process works with LVM block device encryption – LUKS, and not with other methods, such as BTRFS or ZFS. If you’re using either – this is not the guide for you, although you might be able to create a working flow derived from this guide (and if you do – please do post a link!)

A very important note, before we begin – This is not enough! To fully prevent your data from being stolen by a bad person with a screwdriver, you will need to add some additional measures, like locking up your BIOS with a password (resetting the BIOS password resets TPM2 data, which is good) ; Signing and using your own embedded GRUB2 (which is not covered here, and maybe one day will be), with your own certificate ; Protect GRUB2 from booth changed using password ; Lock down boot devices in the BIOS (so the evil hacker cannot boot from a USB or CDROM without unlocking the BIOS first) ; Lock the hard drive (or SSD, or NVME) with a security to the BIOS (possible on some models of laptops and hard drives). All these steps are required to complete the security process in order to make the life of a cracker/hacker harder to the point of impossible, when attempting to obtain your data. Without them, the effort is great, but not impossible.
Also note that all the above described actions might lock you out of your own system in case of any hardware failure or forgotten password, so make sure you have a (secure!) backup of your data, or else…

I should also add about the above mentioned GRUB2 lockdown (using grub-standalone) – Ubuntu has changed starting with grub2 versions later than 2.04-1ubuntu26 (both on Ubuntu 18.04 and 20.04. I do not know how it is on 22.04, but I will probably soon find out) their internal workflow, and they are basing their kernel verification on SHIM certificate, and not on GPG signature – which they find imperative (they provide signed kernels), but at this time, I find it relaxed compared to the method I am working on (meaning – working on providing a guide) because it allows for other Microsoft-signed loaders, where I would have none other than self-signed files. A guide would be provided soon, and maybe even a patched GRUB2 package, to undo their change (which has a lot of advancements, but in my small real-life usecase – mostly disadvantages).

Now – to the process. The idea is this: We add a new key to the cryptsetup – a long one, and this key is stored in TPM2. We add scripts which pull this key out of TPM2 store whenever the system boots. Thanks to some additional comments by Kelderek, we also add some failback, in case of an incorrect key, to allow up to recover and boot using manual key.

I will not wrap all my actions with ‘sudo’ command. All commands need to be called as root, so you can prefix this guide with ‘sudo -s’ or ‘sudo bash’ if you like. I can also assume you ‘cd’ to the root’s directory to protect the root.key file while it is still there. So – ‘sudo’ yourselves, and let’s begin.

Install required packages:

apt install tpm2-tools

Define TPM2 memory space to hold the key:

tpm2_nvdefine -s 64 0x1500016
# This command will define a 64 byte memory space in TPM2, at the above mentioned address

Create a random 64 byte key file:

cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 64 > root.key

Save the contents of the key file to TPM2:

tpm2_nvwrite -i root.key 0x1500016

Compare the contents of the TPM and the file, to verify that they are exactly the same:

echo root.key file contents: `cat root.key`
echo The value stored in TPM: `tpm2_nvread 0x1500016`
tpm2_nvread 0x1500016 2> /dev/null | diff root.key - && echo The root.key file matches what is stored in the TPM. It is ok to proceed! || echo The root.key file does not match what is stored in the TPM. Do NOT proceed until the two match!

Identify the encrypted device, and add the key to the LUKS:

lsblk # Identify the owner of 'crypt'. We will assume it is /dev/sda3 in our example
cryptsetup luksAddKey /dev/sda3 root.key

Create a script to pull the key from TPM2:

cat << EOF > /usr/local/sbin/tpm2-getkey
#!/bin/sh
if [ -f ".tpm2-getkey.tmp" ]; then
# tmp file exists, meaning we tried the TPM this boot, but it didn’t work for the drive and this must be the second
# or later pass for the drive. Either the TPM is failed/missing, or has the wrong key stored in it.
/lib/cryptsetup/askpass "Automatic disk unlock via TPM failed for  () Enter passphrase: "
exit
fi
# No tmp, so it is the first time trying the script. Create a tmp file and try the TPM
touch .tpm2-getkey.tmp
 
tpm2_nvread 0x1500016
EOF

This script will be embedded into the future initramfs (or initrd), and will pull the key from TPM2. Now, we need to set its permissions and ownerships:

chown root: /usr/local/sbin/tpm2-getkey
chmod 750 /usr/local/sbin/tpm2-getkey

Create a hook script to initramfs:

cat << EOF > /etc/initramfs-tools/hooks/tpm2-decryptkey
#!/bin/sh
PREREQ=""
prereqs()
{
echo ""
}
case \$1 in
prereqs)
prereqs
exit 0
;;
esac
. /usr/share/initramfs-tools/hook-functions
copy_exec `which tpm2_nvread`
copy_exec /usr/lib/x86_64-linux-gnu/libtss2-tcti-device.so.0.0.0
copy_exec /usr/lib/x86_64-linux-gnu/libtss2-tcti-device.so.0
copy_exec /lib/cryptsetup/askpass
exit 0
EOF

Set file permissions:

chown root: /etc/initramfs-tools/hooks/tpm2-decryptkey
chmod 755 /etc/initramfs-tools/hooks/tpm2-decryptkey

Edit crypttab:

The file /etc/crypttab needs to have an entry added at the end of the line containing the boot volume. For example (taken from the previous post’s comments):

sda3_crypt UUID=d4a5a9a4-a2da-4c2e-a24c-1c1f764a66d2 none luks,discard

should become:

sda3_crypt UUID=d4a5a9a4-a2da-4c2e-a24c-1c1f764a66d2 none luks,discard,keyscript=/usr/local/sbin/tpm2-getkey

First – backup your existing crypttab file:

cp /etc/crypttab /etc/crypttab.backup

If you have a single line in the file (only the boot volume is encrypted), you can use the following command:

sed -i 's%$%,keyscript=/usr/local/sbin/tpm2-getkey%' /etc/crypttab

Otherwise, you will have to append it manually.

Backup the original initrd and create a new one

cp /boot/initrd.img-$(uname -r) /boot/initrd.img-$(uname -r).orig
mkinitramfs -o /boot/initrd.img-$(uname -r) $(uname -r)

Reboot.

If all works well – you can now delete the file root.key holding a clear text key. You will still have your original manually defined decryption key working, and the initrd will fail-over to handle manual askpass if the automatic TPM2 fails to work, so you should be rather safe there, as well as update-proof.

Notes:

  • The procedure might work on older Ubuntu systems, although it was not tested. A comment in the previous post suggested that the addition of the source
    deb http://cz.archive.ubuntu.com/ubuntu focal main universe
    to your Ubuntu 18.04, the same procedure should work. I did not test it yet.
  • The security of the system is not complete until you handle the other tasks mentioned at the beginning of the text.
  • This procedure does not cover TPM1.2 systems, and will not work without modification on them. I might document such process in the future.

Good luck, and post here if it works for you, or if you have any suggestions!

Similar Posts

103 Comments

  1. Couple of syntactical corrections:
    – tpm2_nvdefine is missing the underline
    – “uname -r” should be surrounded by backquote
    – in the line “cat << EOF" EOF should be surrounded by apostrophes, or else "$1" in line 8 will be evaluated immediately

    1. Thank you for your review. I have corrected these errors in the text. Unfortunately, sometimes, script lines get sanitised in WordPress…
      I have encapsulated the ‘uname -r’ with $( ) signs, fixed the underline, and escaped the dollar signs in cat << EOF blocks, so it should be fine now. Thanks for your input!

  2. Thank you so much for this article !
    Had trouble setting up tpm2 before and this work like a charm !

  3. I just wanted to say thank you! This worked a treat, and saved me a lot of fiddling on my Dell 2-in-1.

    (I hacked something similar using TPS 1.2 on my old Dell Venue 11 Pro with Ubuntu 16.04 , but the new laptop does not support tpm 1. – and I did not know about/have the keyscript option then! ) The beauty of doing things this way is that I one can make use of the on-screen keyboard to enter a password to unlock the computer and bypass the need to have a keyboard plugged in to decrypt the hard drive.

  4. Thanks for the amazing writeup!

    Just some quick question:
    1. Is 0x1500016 the only option, can I use something else ? And how to choose something else ?
    2. Suppose that I want to reinstall everything with a new key, what should I run to delete they key from the TPM (at 0x1500016) ?
    3. If somehow the attacker can boot with another drive and run `tpm2_nvread 0x1500016`. Can they see the key that I have set ? If I can use other address, they can do a brute force right ?

    1. 1. You can use different address spaces. Try and see.
      2. You don’t need to delete the key (although, you can) – you can reset the NV either from the BIOS, or from tpm2_nvundefine command, or you can (try) and skip the nvdefine in the 2nd run and just use nvwrite
      3. In theory – yes. This is why you lock the BIOS, and should lock your boot loader with password. In this case – the “attacker” cannot override your boot settings with another device, and cannot override boot options in Linux. The tpm2_nvread command, as I have discovered after an upgrade, is somehow signed and registered to the TPM2 (I didn’t check what mechanism it was, but it did not allow me to pull data after OS update), so alternate executables won’t work, I think.

  5. Thanks for the quick response @etzion.

    I actually tried to boot from a Live USB Ubuntu, run `tpm2_nvread 0x1500016` and was able to retrieve the key. Even though I locked my BIOS and GRUB menu with password, and disable boot from external device like USB, the setup still bug me with 2 question:
    1. According to this: https://github.com/fox-it/linux-luks-tpm-boot. I learned that Microsoft’s Bitlocker will take ownership of the TPM and it will not release the decryption keys to a changed O/S. So in case of a zero day vulnerability of a BIOS was used to boot into another OS, the approach that BitLocker use will still works. What should I try to take it from here and have something like that (I tried that repo and it does not work yet), just asking you to get some direction before trying again :3
    2. Since I don’t have a separate TPM chip. I used Intel Platform Trust Technology (PTT) (my CPU and Motherboard support it), which looks the same as a TPM 2.0 to the OS. So I’m not sure if a BIOS reset (via jumper) will clear the Intel PTT? Or if the attacker just took aways the whole pack of (CPU + Hard Drive) and put it into another machine, will the Intel PTT be clear ? Do you have any experience with Intel PTT ? Can you comment on this question ?

    Again, thanks for the amazing blog

  6. There are several methods to enforce harder. The first would be to use ‘grub-standalone’ with GPG signature (for the kernel and modules) internally. Since I did not invest the time in mapping how to automate this process for each time Ubuntu updates a kernel (and with it – initramfs), I have never written anything about it. But this is a very valid, hard-to-perform, and very-hard-to-override act.
    The idea is that you replace your whole grub_calls_kernel_and_initramfs_where_someone_can_replace_a_component with a single file (aka – grub standalone) with a private GPG key embedded, with the kernel and initramfs signed, so that the GRUB can (and will) load them; and the GRUB standalone itself is signed using a self-signed certificate the TPM is familiar with, and only you can re-sign it. So the trust flow goes like this:
    BIOS TPM has custom CA and certificate, which you control; grub standalone is signed using this CA, and only files signed by this CA are allowed to boot; grub standalone has embedded GPG key (as well as all the required modules built-in, with no ability to load external grub drivers), which is used to verify the kernel and the initramfs signatures. You add to this mess password protecting your grub, and I hope for your sake you never forget the passwords involved.

    About BitLocker – there are several methods of using TPM2 chip. The simple one allows keeping there keys, like in this article. The other is about placing SSL CA-approved key in it, and allowing the TPM to verify a signature of a request in order to provide the key, or something around this flow. This, too, was way too complex, compared to the level of protection I was aiming at, so I didn’t go there.

    If it works like TPM, it is TPM, meaning that if you reset your BIOS, the TPM keys are gone. You are most invited to check it (just have a backup of your key somewhere, or have another key placed into LUKS, and know this one)

    Good luck. Keep me posted. You’ve made me curious 🙂

  7. Thanks for the quick response @etzion.

    I will try reset BIOS or replacing the CPU first to see the Intel PTT works for my self :P. Will get u updated.

    Also, I will looks around and read more about “grub-standalone’ with GPG signature”.

  8. Thanks so much for publishing this.
    However I’ve noticed you are currently not linking to the tpm2-getkey bash code but instead you are linking twice to the tpm2-decryptkey code.
    Hopefully you will be able to correct this soon.

    Thanks

    1. That is true. It seems that an add-on I am using to make my scripts more visible is failing the cache tests, and causing the whole cache of the Internet to show the same script twice. Weird. I have modified its settings enough to override it, although it is less pretty now.
      Thanks for letting me know!

  9. Thanks for response @etzion.
    Just got it all working 🙂

    One question re updates:
    You say that the askpass addition makes this setup update-proof: Could you explain what you mean by this please?

    Tks SF

    1. I’ve meant that if and when you update something and break the scripts (let’s say that TPM commands were broken, or that your TPM was somehow erased) – you will still be able to manually enter the passphrase to unlock your disk, even if the TPM does not serve it anymore. It will allow you to survive faulty updates, without locking yourself out. And that is verified, because I have tested such a scenario as well (where TPM was not working well) and it did fail-over to manually asking for password. In the original note for Ubuntu 18.04, at least in the initial post release, the script could not handle TPM failures, and would kick you to a boot loop, where there is no method of entering the passphrase. A comment there (which I greatly appreciate) has pointed the way towards a failover-capable solution.

      Hope it explains.

  10. I’ve followed these instructions, but when I boot and get to the unlock stage, I get ” /usr/local/sbin/tpm2-getkey: line 11: tpm2_nvread: not found \n Nothing to read on input.” The manual password entry works fine, so I can get back in, but I don’t know what the issue is with my getkey

    1. It seems as tpm2_nvread command is missing in your initramfs file. What do you get (in a booted OS) when you type ‘which tpm2_nvread’?

  11. Booted and logged in:
    admin_name@my_server:~$ which tpm2_nvread
    /usr/bin/tpm2_nvread

    Thanks for the help with this

    1. Could you verify /usr/local/sbin/tpm2-getkey ? This script should identify and collect your tpm2_nvread, per its 15th line. You might want to replace this line with “copy_exec /usr/bin/tpm2_nvread” instead and recreate initramfs (subsection “Backup the original initrd and create a new one”)

    2. Check the created file “/etc/initramfs-tools/hooks/tpm2-decryptkey”
      It should have, at its 14th line, something like:
      copy_exec `which tpm2_nvread`
      If it doesn’t – fix it, or replace it with:
      copy_exec /usr/bin/tpm2_nvread
      and recreate initramfs, per the subsection “Backup the original initrd and create a new one”

  12. My “/etc/initramfs-tools/hooks/tpm2-decryptkey” has ‘copy_exec /usr/bin/tpm2_nvread’ on the 14th line, which I assume was changed automatically from the “copy_exec `which tpm2_nvread`” I put in the file. I recreated initramfs anyway but there was no difference, the output at boot still says:
    /usr/local/sbin/tpm2-getkey: line 11: tpm2_nvread: not found
    Nothing to read on input.

    /usr/local/sbin/tpm2-getkey does have ‘tpm2_nvread 0x1500016’ on line 11, the last line.

  13. I don’t know what the issue was, but it’s now resolved. If I can isolate the cause, I’ll let you know! Thanks for the terrific write up and your support.

  14. A couple of thoughts I wanted to share with you.
    1) Don’t you think that from some points of view this procedure weakens a system? I mean, BEFORE the ‘tweak’ to go past the encryption an attacker needed the key, now if he stole my PC (with the hard disk inside) he can decrypt and proceed with the boot.
    2) The problem that a user with sudo privs can ‘reverse engineer’ the pwd is not secondary. It makes the procedure unfeasible for the use case in which you want to give a third part (customer) full control on the device but avoid the disk to be booted elsewehere (recover password – nvwrite in another TPM – boot will work)
    3) Is there a way to obtain a NON TAMPERABLE, NON CHANGEABLE unique ID from the TPM, that you know?

    Thanks for the great work, keep on with it!!

    Paolo

    1. The best security would be achieved with a turned off, disconnected, and, preferably, empty and uninstalled computer. In real life, we need to find some balance between the usability and security, to get something done.
      Keeping your secrets in the TPM saves typing the decryption password every time. It will not allow an attacker who doesn’t know your user’s password access to the disk still. It will not allow an attacker to obtain the password from the TPM without that specific OS running, to which the attacked does not have credentials. Of course – security is measured by the weakest link in the chain, so if your password is very simple and allows easy hacking, you are likely to get your data stolen, or guessed, but it doesn’t matter – if the attacker has access to your account, what is the use of cracking your TPM? The attacker already had access to your files, so all this security is for nothing.
      Keep your passwords safe enough, your OS updated, your BIOS password protected, disk encrypted with TPM enabled, and GRUB password (and better – GPG signed) to prevent tempering, and the efforts of getting into your computer would be so high (although it’s never really impossible, if enough resources are put into it. Don’t assume you will be able to resist the NSA, or some other organisation this big for too long), so a random thief would find it easier resetting and cleaning the laptop than attempting to get your files – which is usually the case anyhow.
      It just has to be hard enough, and either with or without TPM (given the other security measures pointed both here and in the post itself) – the difference is minor. It’s just you, then, who saves typing a long passphrase every time you reboot your computer.

  15. Minor note, the text references 64 bits, but your example is coded using 64 bytes (tpm2_nvdefine -s 64 … and head -c 64 …)

    Perhaps to simplify the comparison between the nvread and file, ie who wants to compare 64 characters :), you could reference a command like: tpm2_nvread 0x1500016 | diff – root.key || echo “Key mismatch: TPM2 Read vs. File”

    jrd

  16. Thanks, you got one, but it looks like “bit” still exists here: “Create a random 64 bit key file:”

    It took me a bit to figure out how to automatically unencrypt a non-boot partition using the above process, so I figured I mention how I did it and ideas on how the guide above might be modified to make things easier for those attempting to do this in the future. First, by default, the initramfs hook “processes the root device, any resume devices and any devices with the initramfs option set.” As such, if you have some other drive that you’d also like to unencrypt at boot using the above approach you would need to add the “initramfs” flag at the end of any appropriate line in /etc/crypttab. Although redundant, I think this might be more clearly expressed in the docs above by having the user add “,keyscript=/usr/local/sbin/tpm2-getkey,initramfs” instead of just the keyscript part.

    Second, the example tpm2-getkey script won’t work for multiple drives because the name of the tmp file would be the same for each. The first time its called works, but not the second. Additionally, outputting () in the askpass line doesn’t really provide any useful info. Luckily, when running the keyscript command has access to several environment variables to make distinguishing between multiple drives clear for both operation and logging. As such, I modified the script to look like:

    #!/bin/sh

    # CRYPTTAB_NAME = sda3_crypt
    # CRYPTTAB_SOURCE = /dev/sda3

    TMP_FILE=”.tpm2-getkey.${CRYPTTAB_NAME}.tmp”

    if [ -f “${TMP_FILE}” ]; then
    # tmp file exists, meaning we tried the TPM this boot, but it didn’t work for the drive and this must be the second
    # or later pass for the drive. Either the TPM is failed/missing, or has the wrong key stored in it.
    /lib/cryptsetup/askpass “Automatic disk unlock via TPM failed for ($CRYPTTAB_SOURCE) Enter passphrase: ”
    exit
    fi
    # No tmp, so it is the first time trying the script. Create a tmp file and try the TPM
    touch ${TMP_FILE}

    tpm2_nvread 0x1500016

    Hope this saves others some time 🙂

    1. Thank you. I have corrected the additional location. Missed this one…

      This is not a common case to have multiple encrypted volumes which should be available at boot time, so I have not tested it, and to be frank – did not even think of that. So your contribution is much appreciated – thank you!

  17. Thanks for this post!
    I wrote my final exam of my vocational training last year about the automatic encryption in Linux.
    So the tester was glad about my project!

    This is the best manual i found in web!

    Thank you and best greetings from Germany 🙂

  18. I’ve followed these instructions, but when I boot and get to the unlock stage, I get ” /usr/local/sbin/tpm2-getkey: line 11: tpm2_nvread:
    No key available with this passphrase.
    cryptsetup: ERROR: nvme0n1p4_crypt: cryptsetup failed, back password or options?”
    It then falls back to the manual password entry which works fine, so I can get back in, but I don’t know what the issue is with my getkey. When I run the tpm2-getkey by hand the correct passphrase shows in the terminal.

    1. It means that the key exists in the TPM, but is it (really) allocated to your LUKS? Did you remember to create the key (or – in your case and at this stage – extract it manually from the TPM) to a file root.key and then (re)define it for LUKS:
      cryptsetup luksAddKey /dev/sda3 root.key
      If things go well (without any error message), it means that the key obtained from TPM is defined for LUKS.
      If it still doesn’t work – make sure that the lines are at the correct length, and that you do not have any Windows trailing end-of-line or things like this, which will prevent the script from running.
      You can also test your key (I don’t remember the command line) for an open LUKS device, so you can verify that your root.key actually works correctly.
      Keep us posted.

  19. Thanks so much for the pointers. The partition was already encrypted on the install media with a set passphrase. I never ran the luksAddKey myself but I created a root.key file with the know pw and verified that the tpm2_nvread gives the same output as far as I can tell. However, in trying to verify the getkey script I got the following results:
    Enter via keyboard:
    root@bb-smpa-aft:/etc# cryptsetup luksOpen –test-passphrase /dev/nvme0n1p4 && echo OK || echo FAIL
    Enter passphrase for /dev/nvme0n1p4:
    OK
    Enter via the root.key file
    root@bb-smpa-aft:/etc# cryptsetup luksOpen –test-passphrase /dev/nvme0n1p4 < root.key && echo OK || echo FAIL
    OK
    Enter via tpm2_read:
    root@bb-smpa-aft:/etc# cryptsetup luksOpen –test-passphrase /dev/nvme0n1p4 < /usr/bin/tpm2_nvread 0x1500016 && echo OK || echo FAIL
    No key available with this passphrase.
    FAIL
    I am not quite sure what this tells me.

  20. It looks like the crux of my problem is this command returns that there is a mismatch even though the printed characters look the same:

    tpm2_nvread 0x1500016 | diff – root.key || echo “Key mismatch: TPM2 Read vs. File”

  21. I found the problem. I defined a slot as you did for 64 bytes but my passphrase only has 17. After changed the TPM slot size, the diff command works.

  22. Still not fixed. The test passphrase cryptsetup command still fails with the /usr/bin/tpm2_nvread input.

  23. I think it possible my root.key file has the trailing null byte and that is being put in the TPM slot. I will check that out.

  24. Finally, tried adding the key in my root.key file and it added as a new key but the test with the tpm2_nvread still fails.

  25. Next option was to create the 64 byte key file like you did above and add that the luks table. Now the tpm2_nvread clearly shows there is no on the end of the key string output but using tpm2_nvread in the test-passphrase option STILL fails. Bummer.

  26. Good news. Even though the command line test did not work. During the boot sequence the TPM module did unlock the encryption. I think I am good to go. Thanks for the great write up and suggestions. It just needs to be followed to the letter (and byte) 🙂

    1. Hehehe… This is a common problem. Understanding the flow is one thing (which now you do) and following it to the letter. This is the thing…
      Mind you that we, humans, handle long random strings worse than computers. So the idea is to keep a long random secret (which we, humans) never have to remember, but the TPM does, and additional shorter, more memorable passphrase, which we can remember. You can think of it as a human-backdoor, for when the TPM fails.
      And it usually has to do with key length, trailing new line and the likes.
      I am happy it is working for you. The reason this guide was created was to allow people to define their TPM half numb-minded. It does not make good use of TPM2 features, like SSL keystore and async encryption and additional stuff, but it’s good enough and should be easy enough to follow (you won’t stop NSA, if they want your data, but you will stop most others).
      Mind you that to complete the hardening process you must lock your BIOS, lock your boot order, lock your GRUB with password, and (sometimes I will write a guide for that too) – best is to use personal GPG signature and sign the kernel, grub configuration, and use grabstandalone with password protection. But on that sometime in the future.
      Thank you for updating me/us, and thank you for using this guide. I hope it serves you well. And as always – don’t forget to keep your human-readable key somewhere safe, outside the machine, in case you will have to replace a motherboard or something.

  27. The manual root.key comparison with TPM can be automated. Here is my personal preference, which is very similar to the posts from JRDavisUF and mhr6091:
    tpm2_nvread 0x1500016 2> /dev/null | diff root.key – && echo The root.key file matches what is stored in the TPM. It is ok to proceed! || echo The root.key file does not match what is stored in the TPM. Do NOT proceed until the two match!

    In the “Create a script to pull the key from TPM2” section:
    1) you don’t explicitly say that should be saved as /usr/local/sbin/tpm2-getkey
    2) JRDavisUF’s suggestion for multiple drives is great and I recommend integrating it. The only issue I have is that ($CRYPTTAB_SOURCE) doesn’t work for me, it needs to be (${CRYPTTAB_SOURCE})

    In the “Create a hook script to initramfs” section, line 1 has you creating a new file, likely from a script, but never has the EOF. Either line 1 should be removed and people directed to save the remaining lines as /etc/initramfs-tools/hooks/tpm2-decryptkey, or you could add a line at the end that is just EOF so the whole thing can be run from a script or shell

    Here are the results of some testing I just did on Ubuntu 22.04:

    I tested upgrading a system with this setup from 20.04 to 22.04 and it worked properly. It unlocked automatically at boot as expected, then I tried corrupting the value in the TPM and rebooting, and it prompted for the passphrase as expected.

    I then nuked and did a fresh install of 22.04 using ZFS. That appears to use native ZFS encryption instead of LUKS on the data partition, so this guide won’t work if someone manually picks ZFS in the advanced options during install.

    I fresh installed again, this time using LVM and encryption and it worked! The only trouble I had was user error when I copied and pasted JRDavisUF’s updated tpm2-getkey. I wasn’t paying attention to the smart quotes in the post, which blew it up. Once I fixed my copy/paste problem and rebuilt the initramfs, it worked perfectly!

  28. FYI I have this all bundled in a script with some error checking at key points like making sure the root.key and TPM match, and that adding the key to LUKS didn’t end in an error. It is here and I welcome feedback, pull requests, etc.

    https://github.com/kelderek/TPM2-LUKS

    @etzion, I made sure to credit you and link back here, but you are uncomfortable with me having this in my github account please let me know. Thanks!

    1. Also – I have starred your github repository. I see your contribution as a compliment and greatly appreciate it.
      Thanks!

  29. Hi Kelderek and thank you for your great insights. I have updated the post based on your notes. I did not handle multiple disks issue, because the common use case if a laptop (which is more vulnerable to theft) and laptops with more than a single disk (to be decrypted on boot) are rather uncommon.
    You can see my corrections:
    – Added a single test line, per your suggestion
    – Create a script to pull the key – added two lines involving EOF to ‘automate’ the creation of the script.

    Again – thanks for your contribution!
    Etzion

  30. This was such a helpful writeup. Thanks for putting these things together. I was able to do this on 20.04 server with very little problem.
    I do see this in the boot log:

    systemd-cryptsetup[952]: Encountered unknown /etc/crypttab option ‘keyscript=/usr/local/sbin/tpm2-getkey’, ignoring.

    It seems to proceed, without prompting for a passphrase, and allowing me to log in. I guess this means it’s not a problem, but I generally don’t like these types of messages! Do you know why it ignores the keyscript option, and then proceeds to decrypt and continue?

  31. Hello Etzion,

    Thanks for this great contribution!
    I am able to follow the instruction to make this work on 20.04. However, we also have some legacy systems with 16.04. It seems like tpm tools can only be executed while tpm2 resource manager is running on ubuntu 16.04. However, it seems like Ubuntu 16.04 does not allow resource manager to run within initramfs. do you or any other readers have ideas to work this around? I understand in Ubuntu 18.04 tpm2 nvread is able to use -T device to work around this resource manager. But this option seems lacking under system 16.04. any hints will be highly appreciated!

    Thanks!

  32. Hi Kelderek
    Thanks for great work. Script works great with just one mod, the variable for the luks partition name. I added the code:
    vLUKSpart=$(blkid|grep LUKS|awk ‘{print $1}’|tr -d 🙂

    1. Hi. I have modified the code as well, and created a pull request to Kelderek. I hope it gets merged soon. If not, I will put a link to my fork, and give him credit for the excellent work he’s done.
      Just to be clear – I am referring to the device name (in my new laptop it’s nvme0n1p3)

      Etzion

  33. @Nate – according to man crypttab on my 22.04 system, the keyscript parameter of /etc/crypttab is Debian specific, and systemd doesn’t support it, hence the log message. As you saw, the initramfs environment on Debian understands it an unlocks the disk, but when systemd starts it doesn’t know what to make of it and just ignores it. It is definitely not an indicator of a problem, but unfortunately, I don’t know if there is anything you can do about it other than just ignore it, unless you want to add support for it in systemd…

    @Su – based on this: https://askubuntu.com/questions/1175086/tpm2-tools-on-ubuntu-16-04 I think you may be out of luck for 16.04, sorry!

    @Magnus – What system are you running? When I run blkid, “LUKS” doesn’t show up anywhere so your code leaves vLUKSpart empty. What do you use vLUKSpart for after you define it?

    @etzion – Thanks for the PR! I will review it today. Coincidentally, I spent some time yesterday adding a bunch of stuff that I hope to finish and commit today, that may address your PR items as well 🙂

  34. @Kelderek – it’s just that I have a new laptop and I am testing your script. In addition, I am working on GRUB alternatives which will allow me to fix my own chain of trust. On a VM for now, because I don’t feel like reinstalling the laptop (mind you that modifying Ubuntu’s default encrypted partition layout can cause a mess you have to solve on your own…)

    Etzion

    1. True. However, the advantages of being lazy is that things work for you. If you can ensure the chain of trust from your BIOS up to your login page, you can ensure that there will be no viable attack vector there. It doesn’t prevent your computer from being vulnerable to other remote-network attacks – it just saves your time and efforts, while maintaining a very high level of security. And still – keeping your data safe at rest, and your computer usable without network connection.

  35. Hi. I followed the steps, but tpm2_nvread isn’t working at boot.

    I believe my key is stored in my tpm and verified it should work with a command from the comments:

    cryptsetup luksOpen –test-passphrase /dev/nvme0n1p4 < root.key && echo OK || echo FAIL

    To diagnose my problem, I modified tpm2-getkey script as attached at the bottom of this comment.

    It seems that tpm2_nvread is failing to read the key during boot, as the "key" value in my modified askpass prompt is empty.

    Running the script from command line after boot, it does display the stored key.

    It's been some years since I did any kernel building, etc. I wonder if somehow a kernel module required by tpm2_nvread isn't loaded, but looking at the output of lsmod I don't see any obvious suspects.

    Any ideas?

    #!/bin/sh
    tpm_key=$(tpm2_nvread 0x1500016)
    if [ -f ".tpm2-getkey.tmp" ]; then
    # tmp file exists, meaning we tried the TPM this boot, but it didn’t work for the drive and this must be the second
    # or later pass for the drive. Either the TPM is failed/missing, or has the wrong key stored in it.
    /lib/cryptsetup/askpass "Automatic disk unlock via TPM failed for (key ${tpm_key})\nEnter passphrase: "
    exit
    fi
    # No tmp, so it is the first time trying the script. Create a tmp file and try the TPM
    touch .tpm2-getkey.tmp

    tpm2_nvread 0x1500016

  36. Haven’t solved my problem, but after further diagnoses I realize /usr/bin/tpm2_nvread doesn’t exist at boot. Something is wrong with thie initramfs step for me…

  37. Fixed. It was my mistake.

    My tpm2-decryptkey didn’t have the required permissions, the initramfs setup was broken. I think I must have overwritten it at some point and didn’t remember the permissions step.

  38. In case anyone is wondering, I’ve setup and tested this on a fresh Ubuntu 22.04 lenovo laptop and works with no modification.

    1. It does.
      I have not posted an update on this, because I am not happy with the remaining chain-of-security here. I cannot signed kernel/initramfs to work without skipping SHIM, or without allowing any attacker with a signed distribution kernel+initramfs to hijack my system. I have problems with the whole chain-of-trust I am still working on (at a very slow rate, due to life and everything), but I hope to be able to complete it one day, and get a whole and full security solution, which remains updating and working as it should (workarounds exist, which will prevent unauthorized boot, HOWEVER – they might not survive os updates, so I felt it was wrong to share them)

      Etzion

  39. First let me say “thank you”. I am deeply impressed with the amount of background work underlying this blog entry as well as with the clarity with which you explain your process.

    I am in the attempting to replicate your process (using Ubuntu 22.04) while attempting a deeper understanding of TMP2. While I am curious about your selection of the “0x1500016” index into the NV area, of more immediate concern is a warning I received when attempting to read the area as root on the running host:

    # tpm2_nvread 0x1500016
    WARN: Reading full size of the NV index
    WARN: Cannot determine size from TPM properties.Setting max NV index size value to TPM2_MAX_NV_BUFFER_SIZE
    #

    It would seem that as /usr/local/sbin/tpm2-getkey is current written, any unexpected warnings on stderr will cause the boot to fail and I believe this to be the case as my boot fails-over into BusyBox.

    Given my modest understanding of tpm2_vmread, it is not clear why this warning is appearing nor how it can be suppressed other than perhaps by redirection of stderr to /dev/null.

    I would welcome any thoughts on how to debug tpm2-getkey related boot failures as well how to address the warning being generated by tpm2_nvread.

    1. First, thank you for reading this. I hope this process works better after my comment.
      It might have been that you have forgotten to define the NV memory size, by using the previously specified command “tpm2_nvdefine -s 64 0x1500016”. This command defines a 64bit memory space, starting at address 0x1500016. As soon as it is defined, reading it will result in a 64bit memory chunk, which, if all followed correctly, would hold your passphrase for LUKS. However, if you’ve skipped this step somehow, and did not define your memory address range, then the TPM chip has no fixed range it should query, and you get the message you have described. Verify you’ve gone through all the steps, and if not – drop a comment here. You will see that there are many comments – many people went through this process, both on Ubuntu 20.04 and 22.04 (me included) and usually – when something went unexpectedly, it was usually because of a step missed (overconfident, I’ve missed a step once, and sat for a very long time debugging the problem. So this is not a unique scenario). Try this again, and I believe that if you drop a comment here, you will get an answer.
      Good luck!

  40. I kept careful notes the first time I attempted to replicate your results, but to be sure I cleared the TPM in the BIOS and restarted hopefully with a clean slate.

    Here is the exact sequence recorded on my second attempt:

    # rm root.key
    # tpm2_nvdefine -s 64 0x1500016
    nv-index: 0x1500016
    # cat /dev/urandom | tr -dc ‘a-zA-Z0-9’ | head -c 64 > root.key
    # tpm2_nvwrite -i root.key 0x1500016
    WARN: Cannot determine size from TPM properties.Setting max NV index size value to TPM2_MAX_NV_BUFFER_SIZE

    Clearly this already deviates from the results you published.

    Continuing, and verifying the NV write:

    # cat root.key
    vyP▒gRpk6sqxAMYX8QUsQsXARK1agE▒Z2Aq▒Ha8SLWpWihYn7HNVEDOAD▒pN8qqI

    Note that I have omitted the CLI prompt that would be appended to the end of the output for clarity.

    Also note the nonprinting characters in the output stream. Now obtaining the content of the NV:

    # tpm2_nvread 0x1500016
    WARN: Reading full size of the NV index
    WARN: Cannot determine size from TPM properties.Setting max NV index size value to TPM2_MAX_NV_BUFFER_SIZE
    vyP▒gRpk6sqxAMYX8QUsQsXARK1agE▒Z2Aq▒Ha8SLWpWihYn7HNVEDOAD▒pN8qqI

    Once again I have omitted the CLI prompt for clarity.

    The strings appear to match excluding the non-printing characters and this can be verified with sum:

    # cat root.key | sum
    22680 1
    # tpm2_nvread 0x1500016 | sum
    WARN: Reading full size of the NV index
    WARN: Cannot determine size from TPM properties.Setting max NV index size value to TPM2_MAX_NV_BUFFER_SIZE
    22680 1

    So the sums match and I am still obtaining the warning despite following your process faithfully.

    Clearly something is being overlooked and/or there is something different on the Dell OptiPlex 5040 (20170119 ship date) that needs to be addressed.

    I would welcome any other observations you might have. In any event, I will continue to examine this problem to see where it leads.

    1. This is very interesting. I assume that the warning (which might be related to a newer version of tpm_nvread, but this is only a guess) is going to STDERR, right? If so, you can modify the command in /usr/local/sbin/tpm2-getkey to drop stderr to /dev/null like this:
      tpm2_nvread 0x1500016 2>/dev/null
      and you should have your key correctly.
      I have a Dell laptop as well, and I do not think this is related directly to the hardware model, but maybe to kernel driver source or TPM commands modifications. However, since my laptop is 22.04, fully updated, and it does reboot correctly, it seems that the result (STDOUT) of this script is being taken into the decryption process, and not the error messages, if there are any. Mind you that if the key is incorrect, the script will ask for manual passphrase using askpass, so you should have your (original) passphrase ready in case of a problem, but it should work fine.

      Originally, it would not have asked, and it was hell getting into the system after a failed script run… At least now it’s easier 🙂

  41. I also use this without issue on Ubuntu 22.04 and I even see the “WARN: Reading full size of the NV index” when I hit esc during boot to hide the Ubuntu logo and show what is going on (also in /var/log/boot.log) so I don’t think STDERR is the problem.

    I am wondering if there is a hardware problem on the system, likely CPU or RAM. Of course it could be the TPM2 device itself, but I can’t get over the non-printing characters in root.key. The whole point of the tr command is that it removes anything that isn’t an English letter or number. I recommend running a memory test using your Ubuntu install medium or memtest86+, but you could also try the Dell built in diagnostics.

    If etzion’s suggestion doesn’t work, you could also force tpm2_nvread to only read 64 bytes with:
    tpm2_nvread -s 64 0x1500016

  42. One other thing I just noticed when you create root.key is that your tr statement is showing with smart quotes instead of normal single quotes. That may just be an artifact of copying into the comments here, but it looks like there are also smart quotes in the original post itself. If I copy and paste directly from it I also get some non-printing characters in the output. So that likely answers that question and the non-printing characters were a red herring.

    Etzion, can you please update the post to replace the smart quotes with single quotes? Thanks!

  43. My apology for the extended delay; I was on vacation.

    Please forgive me for addressing all of the suggestions and observations in one posting.

    Yes, the warning is going to STDERR. Being an old Unix/Linux developer my first thought was “2> /dev/null”, but that needs to be thought through for what it does within the context of a boot environment.

    With respect to the age of workstation & BIOS; I have access to a large number of new, used, and “discard” systems. For my initial experiments I choose a “discard” workstation so I didn’t have to worry about bricking it if I did something wrong with the TPM. Now that I have a little confidence from experience, I plan to test on other, newer, workstation & laptops to see if this issue is specific to one TPM.

    Along the way, I have picked up two books for TPM background information as well as to get a sense of how much variation there might be in chips. They are worth mentioning here:

    A Practical Guide to TPM 2.0 – Using the Trusted Platform Module in the New Age of Security by Will Arthur and David Challener
    Trusted Platform Modules – Why, when and how to use them by Ariel Segall

    Finally, I’m reading a current copy of the TPM2 code to see if I can follow the logic that is causing the error to be thrown. That’s going to take a little while….

    1. There are better and more secure ways of using the TPM2 device. You need to take into consideration two points:
      * There are (older) devices with TPM1 devices. They are incompatible with this guide, although the logic is very much similar.
      * The “correct” was of using TPM2 is by using it as a certificate store for private secrets, and then using a public key to unlock the boot. This is extremely complicated, and will result in a very bloated procedure to make any use of it.

      That said – the TPM2 encryption solution is far from perfect. Currently – on modern Linux systems with SecureBoot, Grub makes use of SHIM which is, in turn, signed by MS. I was unable to use SHIM which was self-signed in a manner that will allow me to lock the system if not “my” shim/GRUB/kernel was used. This means that if someone took your laptop, they can replace the disk with another, having regular GRUB and kernel, and pull the secret out, if the attacker is aware of how you protected your system. The only viable method of locking down the system correctly I found was to skip SHIM (and trusted-computing, along with it) and use custom-compiled GRUB which verifies the kernel’s GPG signature, and not certificate correctness (GRUB+SHIM will fail(!) GPG signature check, especially if you want to use your own encapsulated grub-standalone). You can see here: https://run.tournament.org.il/linux-boot-security-a-discussion/ for additional info.

  44. Hi guys,

    For Kali Linux OS users following the tutorial: I only managed to get it working after switching to Ubuntu 20.04. For some reason tpm2_nvmread didn’t return the key in Kali initramfs (idk why :-/).

    @mhr6091, I saw you were trying above:

    cryptsetup luksOpen –test-passphrase /dev/nvme0n1p4 < /usr/bin/tpm2_nvread 0x1500016 && echo OK || echo FAIL
    No key available with this passphrase.
    FAIL

    To validate the key from TPM2.0. Actually, the command should be:

    /usr/bin/tpm2_nvread 0x1500016 | cryptsetup luksOpen –test-passphrase /dev/nvme0n1p4 && echo OK || echo FAIL
    OK

    Which returns a correct result – as expected. Commenting just so as not to lead other readers into a "rabbit hole" (thinking the key is not being derived correctly or something like that).

  45. @ferrelrasc – my guess as to why it didn’t work on Kali is that initramfs didn’t have the libraries it needs. Part of what /etc/initramfs-tools/hooks/tpm2-decryptkey does is to make sure the required libraries are included in the initramfs with these lines, because Ubuntu doesn’t do it by default:

    copy_exec /usr/lib/x86_64-linux-gnu/libtss2-tcti-device.so.0.0.0
    copy_exec /usr/lib/x86_64-linux-gnu/libtss2-tcti-device.so.0

    If Kali uses a different version or different libraries altogether, those lines would have to be modified

  46. I used this guide today with Ubuntu 22.04.1 LTS and it worked pretty well.
    My only complaint is that while checking that the keys match I get “diff: –: No such file or directory”
    I changed it up to this:
    diff /dev/null) <(cat root.key) && echo The root.key file matches what is stored in the TPM. It is ok to proceed! || echo The root.key file does not match what is stored in the TPM. Do NOT proceed until the two match!

    1. The said script worked fine for others as well. Could it be that you copied it incorrectly somehow?

    2. I think that the dash (-) sign was incorrect. Caused by enhanced formatting of text, where regular dash changes to a longer dash with a different Unicode name. I fixed it.

      1. creating the root.key has a similar issue on this line:
        cat /dev/urandom | tr -dc ‘a-zA-Z0-9’ | head -c 64 > root.key

        Where the site replaced the single quotes ‘ ‘ with smart quotes ‘ ’ which was the source of the weird characters that Bill saw back in October. It doesn’t stop the process from working, but does make the key non-alphanumeric so I recommend fixing it

        1. It does that. “They look better” it thinks to itself, and kills scripts as carelessly as breathing is.
          I don’t think I know how to modify these settings just for specific areas, but I do try to use code plugins where applicable so that I will maintain the original characters. I will update the post and fix the extra fault you’ve noted. I hope it will make things more usable.

          On one of the comments there is a link to github holding a script which does the dirty job of this post for you. I have a plan(!) to continue this excellent work and expand it to a script which will also lock-down GRUB and the remaining loose ends I have there. This TPM solution is not secure enough as is, and needs enhancement. I’ve written about it – it can be found in the related posts.

          1. Yes! Sorry, and I think that the web form even messed up what I changed it to. Your code works now that the hyphen is fixed.

  47. hi Etzion,
    I used your guide to encrypt my ubuntu server 22.04. It works well. Thank you so much for your job.
    but after I hard reboot it at the interval of 20 seconds to test, half hours or longer (sometimes, I did not test ,just power cycle).
    1. An error 1 happen:
    it shows “Automatic disk unlock via TPM failed for () Enter passphrase:” so I have to input passphrase manually.
    but it is a server as a product, it will automatically reboot. but I add command “reboot” after this line:
    at file: /usr/local/sbin/tpm2-getkey

    #!/bin/sh
    if [ -f “.tpm2-getkey.tmp” ]; then
    # tmp file exists, meaning we tried the TPM this boot, but it didn’t work for the drive and this must be the second
    # or later pass for the drive. Either the TPM is failed/missing, or has the wrong key stored in it.
    /lib/cryptsetup/askpass “Automatic disk unlock via TPM failed for () Enter passphrase: ”
    rm .tpm2-getkey.tmp ### or /usr/bin/rm .tpm2-getkey.tmp
    reboot. ## or /usr/sbin/reboot
    exit

    ————-
    but after the error happy again, it DO NOT reboot, it still nee to manually input passphrase.
    somy Question is:
    I want to know, Can I auto reboot it after showing “Automatic disk unlock via TPM failed for () Enter passphrase:”?
    if can ,how to add command to where to reboot it?

    2. Another error:
    Aftering showing: “Automatic disk unlock via TPM failed for () Enter passphrase:”,
    I have to input passphrase every time. after login, tpm2_nvread 0x1500016 error,
    I have to use : echo 5 > /sys/class/tpm/tpm0/ppi/request. and tmp2_clear , and format the disk and install ubuntu and encrypt again.
    here say: that would trigger the rate-limiting feature of the TPM ,right?
    https://unix.stackexchange.com/questions/552181/resolving-message-loading-jwk-to-tpm2-failed

    how to fix this error?
    3. it shows: TPM is in DA Lockout Mode
    I want to know : Can we avoid this issue ?

    all above, as a server products, we can not manually to input the passphrase. if auto reboot can solve the issue, how to do?

    Thank you so much. I look forward to your reply very soon.
    anybody any ideas ?
    Thanks.

    1. It seems as if your problem is that your TPM2 does not hold the key, or that it cannot allow you to read the key. Maybe after you have placed the secret there, something changed or blocked it. I cannot tell, and a reboot sequences after failed TPM login will block your system from any access. My laptop reboots without any problem repeatedly – and neither did I nor others seen anything like this before. If your TPM is somehow slow to respond, it could be BIOS issue which should be resolved with the vendor of the hardware. Alternatively, adding a long sleep to the script, if it fails. You can add different possible scenarios.
      If you want to hard reset the OS, just run:
      echo b > /proc/sysrq-trigger

      You do not need to reinstall your system. You need to reimplement the key in your TPM, or add/modify keys to LUKs (which supports up to 8 keys, if I am not mistaken). It feels to me that you have made a mess out of this somehow, maybe by following other guides (maybe in parallel to this guide?), or by running commands without understanding them.

      1. Hi etzion,
        thank you very much for your reply.
        after I formatted the whole disk and following your guide tested again, at an interval 20s to reboot, actually
        An error happened :”authorization for object to DA protection are not allowd at this time because the TPM is in DA lockout mode” the last weekend. (I knew when happened). today Tuesday, I went to my office, and I found it happened. So I did not input the passphrase. and only powered cycle it . It auto startuped again, did not input manually the passphrase. that’s fine if it always work like that.
        I checked online, and someplace said, if DA lock happened, after 48 hours it should unlock. right? Maybe last weekend, it reached 48 hours. Maybe the repeated rebooting triggered the DA mode. can not test like that.
        I will try command to increase DA counter to avoid this issue. ,can I do ?
        tpm2_dictionarylockout –setup-parameters –max-tries=4294967295 –clear-lockout

        I will try the command again echo b > /proc/sysrq-trigger ( I added the command line
        in the last weekend’s testing,it seemed it’s not useful)

        Actually, in the last weekend’s testing, not showing “Automatic disk unlock via TPM failed for () Enter passphrase:”
        I will test more. I hope, as you said, I messed up something before making the error happen.

        Thank you again.

        1. sorry,
          a little input wrong
          An error happened :”authorization for object to DA protection are not allowd at this time because the TPM is in DA lockout mode” the last weekend. (I did know when happened)

          1. sorry again:
            An error happened :”authorization for object to DA protection are not allowd at this time because the TPM is in DA lockout mode” the last weekend. (I did not know when happened)

          2. It can be related to the hardware model you are using. Which hardware are you using? What BIOS version?
            This is a very specific to hardware, or to a TPM with previously held keys. You might want to clean the TPM (using the BIOS) and repeat the relevant steps in the configuration where you create/replace the LUKS key and store it in the TPM. If the hardware is not buggy, it should solve your problem.

  48. hi etzion ,

    if error “Automatic disk unlock via TPM failed for () Enter passphrase: ” happen in ubuntu 22.04 server
    Can I add commands to auto reboot it ? if can ,how to do ? my products can not allow manually input passphrase.

    I added commands as blow, but did NOT work!
    Thanks.

    /usr/local/sbin/tpm2-getkey
    #!/bin/sh
    if [ -f “.tpm2-getkey.tmp” ]; then
    # tmp file exists, meaning we tried the TPM this boot, but it didn’t work for the drive and this must be the second
    # or later pass for the drive. Either the TPM is failed/missing, or has the wrong key stored in it.
    /lib/cryptsetup/askpass “Automatic disk unlock via TPM failed for () Enter passphrase: ”

    rm .tpm2-getkey.tmp ## or /usr/bin/rm .tpm2-getkey.tmp
    reboot. ## or /usr/sbin/reboot

    exit
    fi
    # No tmp, so it is the first time trying the script. Create a tmp file and try the TPM
    touch .tpm2-getkey.tmp

    tpm2_nvread 0x1500016
    EOF

      1. Hi Kelderek. It appears somewhere here in the comments, however, this is not the problem, as described. The problem seems to be related to hardware, in which the TPM gets blocked if under a too-frequent set of queries. I have never encountered this, and the work-around for this is to either inject some delay in the initramfs script TPM query module, or add a reboot in case the server is unable to boot (instead of asking for passphrase, or after a certain wait for passphrase has passed). This is not a “regular” solution, but a custom-tailored solution for a very specific case. We can share the insight about it, however, from here – he has to take it forward himself.

        1. Ah, I see I missed the earlier thread and saw only Peter’s last message, sorry about that!
          It may be helpful to try to check and set the max tries . I was able to get the properties with:
          tpm2_getcap properties-variable

          I believe the relevant ones here are TPM_PT_MAX_AUTH_FAIL, TPM_PT_LOCKOUT_INTERVAL, and TPM_PT_LOCKOUT_RECOVERY. This should set the the max tries:
          tpm2_dictionarylockout –setup-parameters –max-tries=31 –clear-lockout

          But when I tried on my test system it immediately threw it in to DA lockout mode, so I don’t know. Even in DA lockout mode it still unlocked automatically for me, so as you said there must be something unusual about Peter’s specific TPM config.

          BTW I did notice one other minor issue with the tpm2-getkey script, though. It looks like the askpass message has some remnants of my script where I tried to have it work on all disks in crypttab and create separate unlock scripts. Instead of:
          “Automatic disk unlock via TPM failed for () Enter passphrase: ”

          It should probably either specify /dev/sda3 as used in your example
          “Automatic disk unlock via TPM failed for (/dev/sda3) Enter passphrase: ”
          or be non-specific
          “Automatic disk unlock via TPM failed. Enter passphrase: ”

          1. today happened again:
            right!
            in DA lockout mode it still unlocked automatically for me, I inputed my passphrase. no any reaction.
            I have to waiting for the DA mode expired to try.

          2. when I set my tpm2 before. I used the following command:
            tpm2_dictionarylockout –setup-parameters –max-tries=4294967295 –clear-lockout
            but the DA mode happended again. it’s not useful.
            the chatgpt recommend use : sudo tpm2_changeauth –auth-old=owner -c lockout –failed-attempts=50 to avoid the issue.
            or use a complex passphrase. Maybe my first installing one is to simple that can triggle DA mode . before I tried to change my ubuntu password, I used the same passphrase. it showed : password can triggle DA ,I was surprised before. so my ubuntu password and my first encrypt passphrase are sameand simple. Maybe the issue is here.

      1. Your problem seems to be related to your specific hardware. I can only offer you to check for firmware updates both to the motherboard, and the TPM module (the TPM module is not built-in, unlike most modern motherboards). Check with the vendor of the TPM, because it seems as if some defaults are set either incorrectly, or very limited. This is not something within the scope of this article.
        Injecting a delay into the script by using either sleep, or a hard-reboot command, as shown to you before is possible, but this is a ‘hack’ you need to use for your own specific case only, and is probably irrelevant to most other readers of this article.
        Good luck

        1. hi etzion
          after 24 hours healing time, it can auto bootup.
          but I repeated the error again. just I pressured the power button of my mini PC for a while and directly cut off the power and then I powered on .the error generated again at once, and showed: ”authorization for object to DA protection are not allowd at this time because the TPM is in DA lockout mode” .
          so is it possible the error is from ubuntu system not only from hardware?
          anyway, before I used reboot command in script to soft reboot it, the error same happened.

          Thank you.

        2. Hi etzion,
          I used a tpm2 module to try,but after unplug and plug power supply for about 20 time, The DA mode came again.
          I want to know can I add the following line in your /usr/local/sbin/tpm2-getkey after find DA mode happening ?
          tpm2_dictionarylockout –setup-parameters –max-tries=429496729 –clear-lockout –recovery-time=50 –lockout-recovery-time=50

          after I manually input the password and login to add the line like below:

          #!/bin/sh
          if [ -f “.tpm2-getkey.tmp” ]; then
          # tmp file exists, meaning we tried the TPM this boot, but it didn’t work for the drive and this must be the second
          # or later pass for the drive. Either the TPM is failed/missing, or has the wrong key stored in it.

          tpm2_dictionarylockout –setup-parameters –max-tries=429496729 –clear-lockout –recovery-time=1 –lockout-recovery-time=1

          #/lib/cryptsetup/askpass “Automatic disk unlock via TPM failed for () Enter passphrase: ”

          and I commented #/lib/cryptsetup/askpass “Automatic disk unlock via TPM failed for () Enter passphrase: ”
          but after reboot, it’s not useful it still display :Automatic disk unlock via TPM failed for () Enter passphrase:

          it seemed the process in not running to there. my DID not remove the line:/lib/cryptsetup/askpass “Automatic disk unlock via TPM failed for () Enter passphrase: ”

          so do I need to add the lines from beginning at the first time? after tmp2 for your scripts installed, I can not change /usr/local/sbin/tpm2-getkey? right?

          Thank you very much.

          1. You can enter whatever you want. This is not “my” script, but a script for the use of everyone, and many people helped making it work.
            After modifications to the script, you need to make sure two things happen – you have to modify the script creating the initramfs, as was created here: /etc/initramfs-tools/hooks/tpm2-decryptkey to include the commands you expect to run (tpm2_dictionarylockout and its dependants), and you have to recreate initramfs, by running:
            cp /boot/initrd.img-$(uname -r) /boot/initrd.img-$(uname -r).orig # Copies the already existing ramdisk to backup
            mkinitramfs -o /boot/initrd.img-$(uname -r) $(uname -r) # Creates a new ramdisk with your changes in it

  49. thanks etzion.
    yes. I think you script and my whole encryption script which is similar to Kelderek’s are correct. because it worked for some days and suddenly error happened.
    I guess it is the hardware issue. let me ask the motherboard vendor if it happened before.
    Thanks again

  50. Hey,
    Great tutorial.

    I am just running in one issue, my crypttab has only follwing line:

    cryptoswap /dev/sda2 /dev/urandom swap,initramfs

    So any sdax_crypt entry is missing. I am on unbuntu 22.04.3 with ZFS.
    Can somebody help me how to proceed to get that working ? Would be really warmly welcome.

    Thanks a lot in advance.

    1. ZFS makes use of different mechanisms, and you need to modify the initramfs module to work with that. I haven’t done it, so I can’t give you any relevant directions about it. Try to understand the mechanism used to mount ZFS root, and unlock encrypted ZFS, and see if you can adjust it to read from the TPM, in a manner similar to the one described in this article.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.