Git Product home page Git Product logo

tpm2-totp's Introduction

Linux Build Status Code Coverage Language grade: C/C++ Coverity Scan

Overview

This is a reimplementation of Matthew Garrett's tpmtotp software for TPM 2.0 using the tpm2-tss software stack. Its purpose is to attest the trustworthiness of a device against a human using time-based one-time passwords (TOTP), facilitating the Trusted Platform Module (TPM) to bind the TOTP secret to the known trustworthy system state. In addition to the original tpmtotp, given the new capabilities of in-TPM HMAC calculation, the tpm2-totp's secret HMAC keys do not have to be exported from the TPM to the CPU's RAM on boot anymore. Another addition is the ability to rebind an old secret to the current PCRs in case a software component was changed on purpose, using a user-defined password.

Operations

Setup

When the platform is in a known trustworthy state, the user will generate a tpm2-totp secret that is sealed to the current PCR values of the TPM. The secret is also exported (e.g. via QR-Code) so it can be recorded in a TOTP application (e.g. freeotp on Android phones). The secret is also stored inside the TPM's NV space.

Boot

During boot the OS sends the current time to the TPM. The TPM checks that the correct PCR values are present and calculates the HMAC of the time input. This result is the TOTP value that will be displayed to the user. The user can compare this value to the TOTP value of his/her external device (e.g. phone) and thus assert the unalteredness and trustworthiness of his/her device.

Recovery

If the TOTP secret on the external device gets lost, there is a way to recover the secret, if a password was set during its generation. In this case the same QR code will be displayed to the user again.

If an update occurs that changes one of the PCR values (e.g. BIOS or Bootloader) then the secret can be resealed to the new PCR values using the password. Then it will be available again on the next boot.

Build and install instructions

Standard installation using

./bootstrap
./configure
make
make install

Followed by setting up the initrd, see below.

Instructions on packages needed to build and install tpm2-totp and different build options are available in the INSTALL file.

Initramfs integration

The project includes hooks for dracut, initramfs-tools and mkinitcpio to display the TOTP during boot using Plymouth. They are automatically installed if the corresponding tool is found on the system (also see INSTALL regarding necessary configuration options). To use them, install tpm2-totp and initialize a TOTP secret, then enable the tpm2-totp hook in your initramfs generator and rebuild the initramfs.

Usage

Setup

The TOTP secret can be initialized with and without password. It is recommended to set a password -P in order to enable recovery options. Further, it is strongly recommended to provide the password via stdin, rather than directly as a command line option, to protect it from other processes, shell history, etc. Also the PCRs and PCR banks can be selected -p and -b. Default values are PCRs 0,2,4 and banks SHA1, SHA256.

tpm2-totp init

tpm2-totp -P - init
verysecret<CTRL-D>
# or (recommended)
gpg --decrypt /path/to/password.gpg | tpm2-totp -P - init
# or (discouraged)
tpm2-totp -P verysecret init

tpm2-totp -P - -p 0,1,2,3,4,5,6 init
tpm2-totp -p 0,1,2,3,4,5,6 -b SHA1,SHA256 init

Boot

During boot the TOTP value for the current time, together with the current time should be shown to the user, e.g. using plymouth from mkinitrd or from dracut. The command to be executed is:

tpm2-totp show
tpm2-totp -t show

Recovery

In order to recover the QR code:

tpm2-totp -P - recover

In order to reseal the secret:

tpm2-totp -P - reseal
tpm2-totp -P - -p 1,3,5,6 reseal

Deletion

In order to delete the created NV index:

tpm2-totp clean

NV index

All command additionally take the -N option to specify the NV index to be used. By default, 0x018094AF is used and recommended.

tpm2-totp -N 0x01800001 -P - init
tpm2-totp -N 0x01800001 show
tpm2-totp -N 0x01800001 -P - recover
tpm2-totp -N 0x01800001 -P - reseal

Limitations

Whilst tpm2-totp provided the added security (in comparison to tpm-totp) that the key will not leave the TPM during the calculate operation, the time source is still not trustworthy and thus an attacker might in some situations be able to calculate a set of TOTP values for the future. Depending on the size of the possible attack window this can be very large though.

It is not yet possible to specify specific PCR values independent of the currently set PCR values. This would allow disabling the password-less calculate operation after booting the device. This makes most sense, once a TSS2 FAPI is available that will enable an interface to a canonical PCR event log.

Currently, an empty owner password is assumed.

tpm2-totp's People

Contributors

alonbl avatar artefact2 avatar casantos avatar diabonas avatar dilyanpalauzov avatar dominic5787 avatar evilbit avatar ffontaine avatar jacmet avatar lgtm-migrator avatar malikabhi05 avatar orbea avatar osresearch avatar peterhuewe avatar tstruk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tpm2-totp's Issues

no OTP shown with sd-plymouth

With these Hooks the OTP wont show up:

HOOKS=(systemd consolefont sd-plymouth tpm2-totp autodetect modconf block filesystems keyboard fsck)

I use systemd instead of udev.

no TOTP displayed in systemd-based initramfs

Similar to #74, TOTP is not displayed when using systemd initramfs, i.e. following mkinitcpio.conf hooks on Arch:
HOOKS=(… systemd tpm2-totp …)

I tried writing a small systemd unit file and accompanying installation hook, but no luck.
I checked that all the files are present in the initramfs with lsinitcpio and tried to trace unit execution with systemd-analyze plot.
The unit always gets started way too late in the boot process, long after systemd-ask-password-console.service.

Also, tpm2-totp seemed to fail on first invocation during initramfs stage with:
tpm2-totp[…]: failed to allocate dbus proxy object: Could not connect: No such file or directory
Could this be a side effect of having tpm2-abrmd installed? I saw that it uses dbus and usr/lib/libtss2-tcti-tabrmd.so got included in the initramfs.

On a side note - I haven't researched how to stop the service after the initrd.target. Right now it keeps lingering in the booted system until stopped manually.

Thanks for writing awesome tpm2 tools ;)


For reference, the systemd unit (commented out parameters are from exploring possible permutations):
tpm2-totp.service

[Unit]
Description=Display attestation using tpm2-totp
#Requires=dev-tpm0.device
#After=dev-tpm0.device
Before=systemd-ask-password-console.service
DefaultDependencies=no

[Service]
Type=exec
#ExecStart=/usr/bin/show-tpm2-totp
ExecStart=/usr/lib/tpm2-totp/show-tpm2-totp
#StandardOutput=kmsg+console
StandardOutput=tty

#[Install]
#WantedBy=sysinit.target
#WantedBy=initrd.target

… and a small install hook:
sd-tpm2-totp

#!/bin/bash

build() {
    add_systemd_unit "tpm2-totp.service"
}

NOTE: The unit has to be installed in /usr/lib/systemd/system, not /etc/systemd/system, otherwise the add_systemd_unit function fails silently during mkinitcpio and the unit doesn't get included in the initramfs.

Refine CLI interface semantics

Before setting the CLI API in stone for a long time in milestone v1.0, I suggest remodeling the semantics of the sub-commands slightly.

For example:
generate and calculate are semantically not too dissimilar and generate at least some amount of cognitive friction on usage (e.g. generate could just as well refer to generating the TOTP).
I suggest e.g. the following transition:

  • generate -> init (ubiquitous and well understood from modern CLI design)
  • calculate -> attest or simply show

Also refer to the request for a status command in #85.
Great reference on modern and idiomatic CLI design e.g. here, specifically on sub-commands and noun verb vs verb noun ordering here.

This is less of a pressing issue, than an invitation for an open collection of ideas about future CLI design :)

P.S.: I hope, creating a number of issues is not considered rude - it surely isn't intended that way.

Password should never be passed as an argument

Passing the password as an argument exposes it to other processes via /proc and constitutes a potential leak of this critical secret.

The password should only ever be passed via a file descriptor, possibly stdin per default or if called interactively.

Add ability to seal against user-specified PCR values

Quoting README.md:

It is not yet possible to specify specific PCR values independent of the currently set PCR values. This would allow disabling the password-less calculate operation after booting the device. This makes most sense, once a TSS2 FAPI is available that will enable an interface to a canonical PCR event log.

Probably the most convenient way to handle this is to add a new option that accepts a file generated by tpm2_pcrlist --out-file.

Since this requires breaking changes to the library ABI, it would be good to implement this before releasing version 1.0.

User-friendly error messages

Currently running tpm2-totp generate with a secret already stored results in

Calling Esys_GetRandom for 20 bytes
Calling Esys_CreatePrimary
WARNING:esys:src/tss2-esys/api/Esys_NV_DefineSpace.c:333:Esys_NV_DefineSpace_Finish() Received TPM Error 
ERROR:esys:src/tss2-esys/api/Esys_NV_DefineSpace.c:122:Esys_NV_DefineSpace() Esys Finish ErrorCode (0x0000014c) 
ERROR in tpm2totp_storeKey_nv (src/libtpm2-totp.c:590): 0x0000014c

ERROR in main (src/tpm2-totp.c:337): 0x0000014c

We should at least use tss2-rc to also return a human-readable error message like "NV Index or persistent object already defined".

Additionally custom error message for common error cases, e.g. "Secret already stored, use tpm2-totp calculate to show the TOTP or tpm2-totp clean to delete the stored secret", would be nice as well.

Release GPG Key

I'm currently trying to package TPM2-TOTP for QubesOS. As part of this, I would like to verify the source code as released. However, I've been unable to find the public key used to sign releases. I have also noticed that none of the other Linux distributions are using GPG verification of the release tarballs.
Would it be possible to either reply to this issue with the public key or commit it to the repository in a similar way as TPM2-Tools?

Thanks for your work on this.

Typo

ExecStart=/bin/sh -c 'echo "TOTP: $(tpm2-totp --time show)"'

I think this is now "calculate"?

May I also ask to generate a new release so that this finds its way into the arch repos?

Working with systemd-cryptsetup?

Hello! This is a really neat project and I have a feature request.

Following some of the conversation in issues #74 and #82 I seem to have the plymouth systemd module running correctly. However, I'm not seeing any output. I think it might be because my current setup is a little unique: I'm using the systemd-cryptsetup module to load my encryption key out of the TPM. I see elsewhere (e.g. in this talk) that the code is usually shown while the decryption password is being entered.

I'm wondering if there is a way to get the cryptsetup module to wait until after the Plymouth screen, and if there could be a pause at boot where the TOTP is shown before the disk is decrypted using cryptsetup, with a "Press any key to continue" sort of setup.

I realize that not entering a password is potentially less secure, but I'm in the process of building secure devices for folks with lower tech literacy, and the though of distributing thousands of decryption passwords to them that they have to type in at boot is not a desirable option.

TOTP code not shown by Debian 12 running cryptroot-unlock

I am experimenting with Debian 12 (bookworm) and measured boot. For that, I have compiled (current latest revision 826c103) and initialized tpm2-totp successfully.

./configure --sysconfdir=/etc --prefix /usr
make -j$(nproc)
make install
tpm2-totp init

When requesting the TOTP value with tpm2-totp show -t I get the correct value 2023-05-06 16:45:06: 005163root@vmware ~ # . I also have installed plymouth that gets also added to the initramfs.

When trying to unlock the encrypted disk from initramfs, however the TOTP values are not shown until the LUKS password was entered locally, which is not what is the intended use of measured boot. ;-)

When logging in via dropbear TOTP values are also not displayed automatically. However, having tpm2-totp added to the initramfs, the correct TOTP values are displayed. The execution of plymouth-tpm2-totp -t from command prompt blocks, but does not output any text on the following line (cursor stays on line start):

~ # plymouth-tpm2-totp -t

Here is a screenshot of the output when operating on console (not via dropbear; roughly waited 5 minutes until LUKS password was entered):
tpm2-totp-initramfs

Just for completion, the built Debian package is here (.zip file because Github doesn't support extension .deb):
tpm2-totp_0.3.0+git20230105.826c103-1.deb.zip

Does anyone have an idea what I am doing wrong?
May this be related to #92?

Implement GUI client

Implement a GUI client in Gnome, GTK, KDE, QT, wxWidgets or whatever for setting up a totp binding.
Thus making it "Desktop ready"

[Feature] Add available HOOKS to man page

I moved to a systemd-based initramfs. It took me quite a while to figure out there was an sd-tpm2-totp hook added 3 years ago.

It would enhance the documentation if available hooks were added to the man page or the README on this repo. Thanks for your consideration!

Implement plymouth interface

Implement an executable that uses plymouth to show the totp value during early boot.
This will alllow the inclusion in initrd systems.

udev error in bootlog when using dracut + plymouth

I just tested this package in a fresh Fedora 31 VM (KVM and swtpm).
In the bootlog (journalctl -b) I found this line:

Dec 22 11:11:19 localhost.localdomain systemd-udevd[407]: /etc/udev/rules.d/80-tpm2-totp.rules:1 Invalid value "/sbin/initqueue --settled --onetime /bin/show-tpm2-totp & show_tpm2_totp_pid=$!" for RUN (char 79: invalid substitution type),ignoring, but please fix it.

The strange thing is, it works! I see the correct totp code on the screen.
I built tmpm2-totp from git, following the README.

Compilation error due to variable used uninitialized

Some inline declarations of strtok_r (specifically in Sourcery CodeBench Lite 2016.11-19) contain code where an '__s' local variable can be used uninitialized.

When GCC expands that declaration in 'parse_pcrs', __s becomes an alias to the local variable 'saveptr', which in fact is not initialized, but this is not relevant, since the 'str' argument is knowingly not NULL when passed to strtok_r because it comes from 'optarg' in parse_opts.

Anyway, applying the attached patch to initialize saveptr to NULL prevents the compilation error.

fix-compilation-failure.txt

Fixes: http://autobuild.buildroot.net/results/5693a35e4d6bc76a1f46fe0e217abc49f7188aad/

Use tpm2-totp with pam?

Hello,

is there a possibility to integrate tpm2-totp into pam?
This is already possible with pam_oauth, but the file with the secret needs to be stored on the harddrive. Protecting the secret in the tpm2 would increase the security a lot.

Implement `status` sub-command

Having a sub-command à la tpm2-totp status to show the currently enrolled configuration would be helpful and very much appreciated.

Infos to display could include:

  • general enrollment status
  • selected PCR registers
    • possibly with short description for well-known PCRs (man 1 systemd-cryptenroll has a nice summary)
  • resealing possible? (enrolled with password or not)
  • PCR banks
  • nvindex used
  • label
  • etc.

Possibly/Optionally in YAML format.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.