From: Felix Rubio <felix@kngnt.org>
To: tpm2@lists.linux.dev
Subject: Is possible to seal a secret once, and authorize any policy properly signed to unseal it?
Date: Sat, 27 Dec 2025 18:39:37 +0100 [thread overview]
Message-ID: <3394779.44csPzL39Z@altair> (raw)
Hi everybody,
I am trying to get a secret sealed once (ZFS encryption key), while being able
to unseal it with any key that is properly signed (so that when I recreate a
UKI I do not have to reseal but just to calculate the new PCR values). I have
played with tpm2-tools across the years, but my knowledge is still quite
basic: I do not know even if this is possible.
This is the script I am using:
########################################################
#!/bin/bash
set -eufx
OUTDIR=/tmp/outdir
SIGN_HANDLE="0x81010021"
mkdir -p "${OUTDIR:?}"
rm -rf "${OUTDIR:?}/*"
#############
# Step 0: Create signing key
AUTH_PUB="$OUTDIR/auth.pub"
AUTH_PRIV="$OUTDIR/auth.priv"
# Create an isolated tmpdir for TPM transient files
TMPDIR=$(mktemp -d /run/tpm-primary.XXXXXX)
AUTH_CTX="$TMPDIR/auth.ctx"
AUTH_PRIMARY_CTX="$TMPDIR/auth_primary.ctx"
# Create a new signing key under a primary key
tpm2_evictcontrol -Q -C o -c "$SIGN_HANDLE" || true
tpm2_createprimary -Q -C o -g 'sha256' -G rsa -c "$AUTH_PRIMARY_CTX"
tpm2_create -Q -C "$AUTH_PRIMARY_CTX" -G rsa -u "$AUTH_PUB" -r "$AUTH_PRIV"
tpm2_load -Q -C "$AUTH_PRIMARY_CTX" -u "$AUTH_PUB" -r "$AUTH_PRIV" -c
"$AUTH_CTX"
tpm2_evictcontrol -Q -C o -c "$AUTH_CTX" "$SIGN_HANDLE"
tpm2_flushcontext -t
# Save Name now that is persistent
tpm2_readpublic -Q -c "$SIGN_HANDLE" -n "$OUTDIR/auth.name"
rm -rf "$AUTH_PUB" "$TMPDIR"
#############
# Step 1: Seal secret under authorizedPolicy using policyRef
TMPDIR=$(mktemp -d /run/tpm-seal.XXXXXX)
TPM_CTX="$TMPDIR/tpm.ctx"
AUTHORIZED_POLICY="$TMPDIR/authorized_policy.bin"
DUMMY_POLICY="$TMPDIR/dummy_policy.bin"
DUMMY_SIG="$TMPDIR/dummy_policy.sig"
echo "[*] Create a dummy policy and sign it"
tpm2_startauthsession -Q --policy-session --hash-algorithm 'sha256' -S
"$TPM_CTX"
tpm2_getpolicydigest -Q -S "$TPM_CTX" -o "$DUMMY_POLICY"
tpm2_flushcontext -Q -s
tpm2_sign -c "$SIGN_HANDLE" -g 'sha256' -d "$DUMMY_POLICY" -o "$DUMMY_SIG"
echo "[*] Compute authorized policyDigest"
tpm2_startauthsession -Q -S "$TPM_CTX"
tpm2_policyauthorize -Q -S "$TPM_CTX" -i "$DUMMY_POLICY" -n "$OUTDIR/
auth.name" -L "$AUTHORIZED_POLICY" < "$DUMMY_SIG"
tpm2_flushcontext -Q -s
# Create primary key to seal under, and seal the ZFS key
echo "[*] Seal the secret"
tpm2_createprimary -Q -C o -g 'sha256' -G rsa -c "$TPM_CTX"
tpm2_create -Q -C "$TPM_CTX" -L "$AUTHORIZED_POLICY" -u "$OUTDIR/secret.pub"
-r "$OUTDIR/secret.priv" <<< "This is my secret"
tpm2_flushcontext -t
rm -rf "$TMPDIR"
#############
# Generate signature for PCRS
TMPDIR=$(mktemp -d /run/tpm-pcr-sig.XXXXXX)
polfile="$TMPDIR/policy.bin"
echo "[*] Create PCRs signature"
POLICY_HASH=$(tpm2_createpolicy --policy-pcr -l sha256:11 -L "$polfile")
tpm2_sign -c "$SIGN_HANDLE" -d "$polfile" -o "$OUTDIR/policy-$POLICY_HASH.sig"
rm -rf "$TMPDIR"
#############
# validate signature for PCRS
TMPDIR=$(mktemp -d /run/tpm-unseal.XXXXXX)
POLICY="$TMPDIR/current_policy.bin"
SESSION_CTX="$TMPDIR/session.ctx"
PRIMARY_CTX="$TMPDIR/primary.ctx"
ZFSKEY_CTX="$TMPDIR/zfskey.ctx"
TICKET="$TMPDIR/verification.tkt"
echo "[*] Get the policy hash"
POLICY_HASH=$(tpm2_createpolicy --policy-pcr -l sha256:11 -L "$POLICY")
echo "[*] Starting policy session"
tpm2_startauthsession --policy-session --hash-algorithm sha256 -S
"$SESSION_CTX"
echo "[*] Verifying signature"
tpm2_verifysignature -c "$SIGN_HANDLE" -d "$POLICY" -s "$OUTDIR/policy-
$POLICY_HASH.sig" -t "$TICKET"
echo "[*] Authorizing policy"
tpm2_policyauthorize -S "$SESSION_CTX" -i "$POLICY" -n "$OUTDIR/auth.name" -t
"$TICKET"
echo "[*] Applying PCR policy"
tpm2_policypcr -S "$SESSION_CTX" -l sha256:11
echo "[*] Loading sealed object"
tpm2_createprimary -Q -C o -g sha256 -G rsa -c "$PRIMARY_CTX"
tpm2_load -Q -C "$PRIMARY_CTX" -u "$OUTDIR/secret.pub" -r "$OUTDIR/
secret.priv" -c "$ZFSKEY_CTX"
echo "[*] Unsealing ZFS key"
tpm2_unseal -c "$ZFSKEY_CTX" -p "session:$SESSION_CTX"
tpm2_flushcontext -Q -s -t
rm -rf "$TMPDIR"
########################################################
What am I doing wrong?
Thank you for any advise you can provide :-) (and happy new year! just in
case...)
--
Felix Rubio
next reply other threads:[~2025-12-27 17:39 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-27 17:39 Felix Rubio [this message]
2025-12-28 9:28 ` Is possible to seal a secret once, and authorize any policy properly signed to unseal it? Felix Rubio
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3394779.44csPzL39Z@altair \
--to=felix@kngnt.org \
--cc=tpm2@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.