public inbox for tpm2@lists.linux.dev
 help / color / mirror / Atom feed
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




             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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox