#!/bin/sh # Generate a random secret, seal it with the PCRs # and write it to the TPM NVRAM. # # Pass in a hostname if you want to change it from the default string # . /etc/functions TPM_NVRAM_SPACE=4d47 HOST="$1" if [ -z "$HOST" ]; then HOST="TPMTOTP" fi TOTP_SECRET="/tmp/secret/totp.key" TOTP_SEALED="/tmp/secret/totp.sealed" dd \ if=/dev/urandom \ of="$TOTP_SECRET" \ count=1 \ bs=20 \ 2>/dev/null \ || die "Unable to generate 20 random bytes" secret="`base32 < $TOTP_SECRET`" # Use the current values of the PCRs, which will be read # from the TPM as part of the sealing ("X"). # PCR4 == 0 means that we are still in the boot process and # not a recovery shell. # should this read the storage root key? if ! tpm sealfile2 \ -if "$TOTP_SECRET" \ -of "$TOTP_SEALED" \ -hk 40000000 \ -ix 0 X \ -ix 1 X \ -ix 2 X \ -ix 3 X \ -ix 4 0000000000000000000000000000000000000000 \ -ix 7 X \ ; then shred -n 10 -z -u "$TOTP_SECRET" 2> /dev/null die "Unable to seal secret" fi shred -n 10 -z -u "$TOTP_SECRET" 2> /dev/null # to create an nvram space we need the TPM owner password # and the TPM physical presence must be asserted. # # The permissions are 0 since there is nothing special # about the sealed file tpm physicalpresence -s \ || warn "Warning: Unable to assert physical presence" # Try to write it without the password first, and then create # the NVRAM space using the owner password if it fails for some reason. if ! tpm nv_writevalue \ -in $TPM_NVRAM_SPACE \ -if "$TOTP_SEALED" \ ; then warn 'NVRAM space does not exist? Owner password is required' read -s -p "TPM Owner password: " tpm_password echo tpm nv_definespace \ -in $TPM_NVRAM_SPACE \ -sz 312 \ -pwdo "$tpm_password" \ -per 0 \ || die "Unable to define NVRAM space" tpm nv_writevalue \ -in $TPM_NVRAM_SPACE \ -if "$TOTP_SEALED" \ || die "Unable to write sealed secret to NVRAM" fi shred -n 10 -z -u "$TOTP_SEALED" 2> /dev/null url="otpauth://totp/$HOST?secret=$secret" secret="" qrenc "$url" echo "$url"