From: Felix Rubio <felix@kngnt.org>
To: tpm2@lists.linux.dev
Subject: Re: Is possible to seal a secret once, and authorize any policy properly signed to unseal it?
Date: Sun, 28 Dec 2025 10:28:53 +0100 [thread overview]
Message-ID: <2334520.iZASKD2KPV@altair> (raw)
In-Reply-To: <3394779.44csPzL39Z@altair>
Fixed it, I think, by... carefully looking at the examples. This is my current
flow, now, which seems to work. Sharing in case somebody is interested:
########################################################
#!/bin/bash
set -euf
OUTDIR=/tmp/outdir
SIGN_HANDLE="0x81010021"
mkdir -p "${OUTDIR:?}"
rm -rf "${OUTDIR:?}/*"
############# ONE OFF: CREATE SIGNING KEYS, AUTHORIZED POLICY
AUTH_PRIV="$OUTDIR/auth.priv"
TMPDIR=$(mktemp -d /run/tpm-primary.XXXXXX)
AUTH_PUB="$TMPDIR/auth.pub"
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 -c "$AUTH_PRIMARY_CTX"
tpm2_create -Q -C "$AUTH_PRIMARY_CTX" -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 "$TMPDIR"
############# ONE OFF: CREATE AUTHORIZED POLICY, SEAL THE SECRET
# Seal secret under authorizedPolicy
TMPDIR=$(mktemp -d /run/tpm-seal.XXXXXX)
TPM_CTX="$TMPDIR/tpm.ctx"
AUTHORIZED_POLICY="$TMPDIR/authorized_policy.bin"
echo "[*] Compute authorized policyDigest"
tpm2_startauthsession -Q -S "$TPM_CTX"
tpm2_policyauthorize -Q -S "$TPM_CTX" -n "$OUTDIR/auth.name" -L
"$AUTHORIZED_POLICY"
tpm2_flushcontext -Q "$TPM_CTX"
# Create primary key to seal under, and seal the ZFS key
echo "[*] Seal the secret"
tpm2_createprimary -Q -C o -G rsa -c "$TPM_CTX"
tpm2_create -Q -C "$TPM_CTX" -i- -L "$AUTHORIZED_POLICY" -u "$OUTDIR/
secret.pub" -r "$OUTDIR/secret.priv" <<< "This is my secret"
tpm2_flushcontext -t
rm -rf "$TMPDIR"
############# AFTER UKI UPDATE: SIGN THE NEW PCR VALUES
# Generate signature for PCRS
TMPDIR=$(mktemp -d /run/tpm-pcr-sig.XXXXXX)
SESSION_CTX="$TMPDIR/session.ctx"
POLICY_FILE="$TMPDIR/policy.bin"
echo "[*] Create PCRs signature"
tpm2_startauthsession -S "$SESSION_CTX"
POLICY_HASH=$(tpm2_policypcr -S "$SESSION_CTX" -l sha256:11 -L "$POLICY_FILE")
tpm2_flushcontext "$SESSION_CTX"
tpm2_sign -c "$SIGN_HANDLE" -g sha256 -o "$OUTDIR/policy-$POLICY_HASH.sig"
"$POLICY_FILE"
rm -rf "$TMPDIR"
############# IN INITRAMFS: UNSEAL SECRET
# 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"
tpm2_startauthsession -S "$SESSION_CTX"
POLICY_HASH=$(tpm2_policypcr -S "$SESSION_CTX" -l sha256:11 -L "$POLICY")
tpm2_flushcontext "$SESSION_CTX"
echo "[*] Verifying signature"
tpm2_verifysignature -c "$SIGN_HANDLE" -g sha256 -m "$POLICY" -s "$OUTDIR/
policy-$POLICY_HASH.sig" -t "$TICKET"
echo "[*] Starting policy session"
tpm2_startauthsession --policy-session -S "$SESSION_CTX"
echo "[*] Applying PCR policy"
tpm2_policypcr -Q -S "$SESSION_CTX" -l sha256:11
echo "[*] Authorizing policy"
tpm2_policyauthorize -Q -S "$SESSION_CTX" -i "$POLICY" -n "$OUTDIR/auth.name"
-t "$TICKET"
echo "[*] Loading sealed object"
tpm2_createprimary -Q -C o -c "$PRIMARY_CTX"
tpm2_load -Q -C "$PRIMARY_CTX" -u "$OUTDIR/secret.pub" -r "$OUTDIR/
secret.priv" -c "$ZFSKEY_CTX"
tpm2_flushcontext -Q -t
echo "[*] Unsealing ZFS key"
tpm2_unseal -c "$ZFSKEY_CTX" -p "session:$SESSION_CTX"
tpm2_flushcontext -Q "$SESSION_CTX"
rm -rf "$TMPDIR"
Regards!
On Saturday, 27 December 2025 18:39:37 Central European Standard Time Felix
Rubio wrote:
> 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
prev parent reply other threads:[~2025-12-28 9:30 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-27 17:39 Is possible to seal a secret once, and authorize any policy properly signed to unseal it? Felix Rubio
2025-12-28 9:28 ` Felix Rubio [this message]
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=2334520.iZASKD2KPV@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.