Skip to content

Commit

Permalink
bootscript: Use send-to-tpm for EK and TK methods
Browse files Browse the repository at this point in the history
  • Loading branch information
nicowilliams committed Jul 6, 2021
1 parent 75fb767 commit f8e265a
Showing 1 changed file with 3 additions and 162 deletions.
165 changes: 3 additions & 162 deletions initramfs/bootscript
Original file line number Diff line number Diff line change
Expand Up @@ -46,169 +46,10 @@ if [[ -x $STARTUP ]]; then
. "$STARTUP" || die "startup failed"
fi

tpm2_ek_session() {
tpm2 flushcontext -t
tpm2 flushcontext -s
tpm2 startauthsession \
--session "ek-session.ctx" \
--policy-session \
|| die "tpm2: unable to start policy session"
tpm2 policysecret \
--session "ek-session.ctx" \
--object-context endorsement \
|| die "tpm2: unable to set policysecret for endorsement hierarchy"
}
tpm2_tk_session() {
tpm2 startauthsession \
--session "tk-session.ctx" \
--policy-session \
|| die "tpm2: unable to start tk-policy session"
tpm2 policypcr \
--session "tk-session.ctx" \
--policy "tk-policy.dat" \
--pcr-list="sha256:$POLICY_PCR" \
|| die "tpm2: unable to load policy pcr"
}

try_tk=false
[[ -r "$TMPDIR/tk.seed" ]] && try_tk=true

cat > "$TMPDIR/wkpriv.pem" <<EOF
-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAlMnCWue7CfXjNLibH
PTJrsOLUcoxqU3FLWYEWMI+HuPnzcwwl7SkKN6cpf4H3oQihZANiAAQ1pw6D5QVw
vymljYVDyrUriOet8zPB/9tq9XJ7A54qsVkaVufAuEJ6GIvD4xUZ27manMosJADS
aW2TLJkwxecRh2eTwPtSx2U32M2/yHeuWRV/0juiIozefPsTAlHAi3E=
-----END PRIVATE KEY-----
EOF

# Try using TPM2_ActivateCredential to recover the rootfs key
if [[ -f $TMPDIR/rootfs.key.symkeyenc ]]; then
# See tpm-receive for the theory and details of what we're up to here.
# This is a simplified version of that. Briefly: we're calling
#
# TPM2_ActivateCredential(EK, WK, blob, secret)
#
# where WK is the handle of a "well-known" private key with a
# well-known policy and attributes. We're using MakeCredential as a
# form of asymmetric key encryption with sender-asserted policy, and
# we're relying on ActivateCredential to enforce that policy because
# it's evaluated by a TPM.

# Compute the policy hash for the WK, if the server didn't tell us it
# (yes, we can hard-code it here).
if [[ ! -f ${TMPDIR}/activate-policy.dat ]]; then
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
tpm2 startauthsession --session "${TMPDIR}/trialsession.ctx"
tpm2 policypcr --session "${TMPDIR}/trialsession.ctx" \
--pcr-list="sha256:$POLICY_PCR"
tpm2 policycommandcode \
--session "${TMPDIR}/trialsession.ctx" \
-L "${TMPDIR}/activate-policy.dat" \
TPM2_CC_ActivateCredential

tpm2 flushcontext --saved-session
fi

# Load the WK
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
tpm2 loadexternal \
--hierarchy n \
--key-algorithm ecc \
--private "${TMPDIR}/wkpriv.pem" \
--policy "${TMPDIR}/activate-policy.dat" \
--attributes "sign|adminwithpolicy" \
--key-context "${TMPDIR}/wk.ctx"

# Get the EK, make a session for it, and execute its policy
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
tpm2 createek --ek-context "$TMPDIR/ek.ctx"
tpm2 flushcontext --transient-object
tpm2 startauthsession --session "${TMPDIR}/sessionek.ctx" --policy-session
tpm2 policysecret --session "${TMPDIR}/sessionek.ctx" --object-context endorsement

# Make a session for the wk and execute its policy
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
tpm2 startauthsession --session "${TMPDIR}/sessionwk.ctx" --policy-session
tpm2 policypcr --session "${TMPDIR}/sessionwk.ctx" --pcr-list="sha256:$POLICY_PCR"
tpm2 policycommandcode --session "${TMPDIR}/sessionwk.ctx" TPM2_CC_ActivateCredential

# Finally, decrypt via ActivateCredential
if tpm2 activatecredential \
--credentialedkey-context "${TMPDIR}/wk.ctx" \
--credentialedkey-auth session:"${TMPDIR}/sessionwk.ctx" \
--credentialkey-context "${TMPDIR}/ek.ctx" \
--credentialkey-auth session:"${TMPDIR}/sessionek.ctx" \
--credential-blob "$TMPDIR/rootfs.key.symkeyenc" \
-o "$TMPDIR/rootfs.key.symkey"; then

# Success. We have a small, symmetric key, so use it to
# authenticate and decrypt the plaintext.
aead_decrypt "$TMPDIR/rootfs.key.enc" \
"$TMPDIR/rootfs.key.symkey" \
"$TMPDIR/rootfs.key"

try_tk=false
else
stat=$?

# If we have a TK, well, try that.
$try_tk || (exit $stat)
fi
fi
if $try_tk; then
# attempt to load the secret wrapping key into our TPM
# as a transient object
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
tpm2 createek --ek-context ek.ctx \
|| die "tpm2: unable to create ek object"

warn "tpm2: Importing duplicate transport key"
tpm2_ek_session

tpm2 import \
--parent-context ek.ctx \
--parent-auth "session:ek-session.ctx" \
--key-algorithm rsa \
--input "$TMPDIR/tk.dpriv" \
--seed "$TMPDIR/tk.seed" \
--public "$TMPDIR/tk.pub" \
--private "$TMPDIR/tk.priv" \
|| die "tpm2: unable to import duplicate transport key object"

warn "tpm2: Loading duplicate transport key"
tpm2_ek_session
tpm2 load \
--parent-context ek.ctx \
--auth "session:ek-session.ctx" \
--key-context "$TMPDIR/tk.ctx" \
--public "$TMPDIR/tk.pub" \
--private "$TMPDIR/tk.priv" \
|| die "tpm2: unable to load duplicate transport key object"

# attempt to decrypt the rootfs key with the transport key
warn "tpm2: Decrypting rootfs key"
tpm2_tk_session
tpm2 rsadecrypt \
--auth "session:tk-session.ctx" \
--key-context "$TMPDIR/tk.ctx" \
< "$TMPDIR/rootfs.symkeyenc" \
> "$TMPDIR/rootfs.symkey" \
|| die "tpm2: unable to decrypt the rootfs key with transport key"

aead_decrypt "$TMPDIR/rootfs.enc" \
"$TMPDIR/rootfs.symkey" \
"$TMPDIR/rootfs.key" \
|| die "unable to decrypt the rootfs key"

# extend PCR11 so that the policy can not be satisfied
echo "UNLOCKED" | tpm2 pcrevent "$POLICY_PCR" \
|| die "tmp2: unable to extend PCR$POLICY_PCR"
/safeboot/sbin/tpm-receive "$KEY.symkeyenc" "$KEY.symkey" \
tpm2 policypcr --pcr-list="sha256:$POLICY_PCR"
aead_decrypt "$KEY.enc" "$KEY.symkey" "$KEY"
fi

# If we're testing, stop here.
Expand Down

0 comments on commit f8e265a

Please sign in to comment.