#!/usr/bin/env bash # # Store a password in a TPM 2.0 NV index, as plaintext inside the TPM's # non-volatile memory (no sealing/encryption layer, no PCR policy). # Requires: tpm2-tools, access to /dev/tpmrm0 (tss group or root). set -euo pipefail HANDLE="0x1500016" FORCE=0 usage() { cat <<-EOF Usage: $(basename "$0") [-H handle] [-f] -H handle NV index to store the password at (default: ${HANDLE}) -f Undefine an existing NV index at that handle before storing EOF } while getopts "H:fh" opt; do case "$opt" in H) HANDLE="$OPTARG" ;; f) FORCE=1 ;; h) usage; exit 0 ;; *) usage; exit 1 ;; esac done command -v tpm2_nvdefine >/dev/null || { echo "tpm2-tools is required (apt install tpm2-tools)" >&2 exit 1 } if tpm2_nvreadpublic | grep -q "^${HANDLE}:"; then if [ "$FORCE" -eq 1 ]; then tpm2_nvundefine -C o "$HANDLE" else echo "An NV index already exists at ${HANDLE}; rerun with -f to replace it" >&2 exit 1 fi fi umask 077 read -r -s -p "Password to store: " PASSWORD echo >&2 read -r -s -p "Confirm password: " PASSWORD_CONFIRM echo >&2 if [ "$PASSWORD" != "$PASSWORD_CONFIRM" ]; then echo "Passwords do not match" >&2 exit 1 fi SIZE=$(printf '%s' "$PASSWORD" | wc -c) tpm2_nvdefine -C o -s "$SIZE" -a "ownerread|ownerwrite" "$HANDLE" printf '%s' "$PASSWORD" | tpm2_nvwrite -C o -i- "$HANDLE" unset PASSWORD PASSWORD_CONFIRM echo "Password stored in NV index ${HANDLE}"