Merge pull request #16 from nicowilliams/master

Add sample encrypt-to-TPM scripts and parameter encryption introduction
This commit is contained in:
Dimitar Tomov 2021-06-14 22:58:35 +03:00 committed by GitHub
commit d0cbddfea4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 689 additions and 7 deletions

View file

@ -1,6 +1,7 @@
# What Attestation is
A computer can use a TPM to demonstrate:
An [enrolled device](/Enrollment/README.md) can use a TPM to
demonstrate:
- possession of a valid TPM
@ -820,6 +821,11 @@ We'll discuss two ways to do this:
the value zero so that extending it can disable use of
`TPM2_MakeCredential()` post-boot.
We have two sample bash scripts demonstrating this approach:
- [`send-to-tpm.sh`](/Enrollment/send-to-tpm.sh)
- [`tpm-receive.sh`](/Enrollment/tpm-receive.sh)
- use an `LTAK` -- a long-term `AK`
I.e., an `AK` that lacks the `stClear` attribute, and _preferably_

View file

@ -38,7 +38,7 @@ device using only that information.
- encrypted filesystems?
- device credentials? (e.g., TLS server certificates, Kerberos keys ["keytabs"], etc.)
# Secrets Transport
# Secrets Long-Term Storage and Transport
Every time an enrolled device reboots, or possibly more often, it may
have to connect to an attestation server to obtain secrets from it that
@ -46,8 +46,95 @@ the device needs in order to proceed. For example, filesystem
decryption keys, general network access, device authentication
credentials, etc.
See [attestation](/Attestation/README.md) for details of how to
transport secrets onto an enrolled device post-enrollment.
See [attestation](/Attestation/README.md#Secret-Transport-Sub-Protocols)
for details of how to store and transport secrets onto an enrolled
device post-enrollment.
## Encrypt-to-TPM Sample Scripts
A pair of scripts are included here to demonstrate how to make long-term
secrets encrypted to TPMs for use in
[attestation](/Attestation/README.md) protocols. The method used is the
one described in the [attestation
tutorial](/Attestation/README.md#Secret-Transport-Sub-Protocols) using
[`TPM2_MakeCredential()`](/TPM-Commands/TPM2_MakeCredential.md) and
[`TPM2_ActivateCredential()`](/TPM-Commands/TPM2_ActivateCredential.md)
with a hard-coded, _well-known_ activation key (`WK`) to implement
encryption-to-`EKpub` with (optional) sender-asserted authorization
policy:
- [`send-to-tpm.sh`](send-to-tpm.sh)
- [`tpm-receive.sh`](tpm-receive.sh)
You can use these scripts like so:
- without policy:
```bash
: ; # Make a secret
: ; dd if=/dev/urandom of=secret.bin bs=16 count=1
: ;
: ; # Encrypt the secret to some TPM whose EKpub is in a file named
: ; # ek.pub:
: ; /safeboot/sbin/send-to-tpm.sh ek.pub secret.bin cipher.bin
fd32fa22c52cfc8e1a0c29eb38519f87084cab0b04b0d8f020a4d38b2f4e223e
7fdad037a921f7eec4f97c08722692028e96888f0b970dc7b3bb6a9c97e8f988
```
```bash
: ; # Decrypt the secret:
: ; tpm-receive.sh cipher.bin secret.bin
fd32fa22c52cfc8e1a0c29eb38519f87084cab0b04b0d8f020a4d38b2f4e223e
7fdad037a921f7eec4f97c08722692028e96888f0b970dc7b3bb6a9c97e8f988
name: 000be1fe1b777ead331f2da896ced2bf7a3949d732a0c6adf6f0a292567d587c4408
837197674484b3f81a90cc8d46a5d724fd52d76e06520b64f2a1da1b331469aa
fd32fa22c52cfc8e1a0c29eb38519f87084cab0b04b0d8f020a4d38b2f4e223e
7fdad037a921f7eec4f97c08722692028e96888f0b970dc7b3bb6a9c97e8f988
certinfodata:b7bd59980628c33a14377d53e165c229
: ;
- with policy
```bash
: ; # Make up a policy (here that PCR11 must be unextended):
: ; dd if=/dev/zero of=pcr.dat bs=32 count=1
: ; policy=(tpm2 policypcr -l sha256:11 -f pcr.dat)
: ;
: ; send-to-tpm.sh ek.pub secret.bin cipher.bin "${policy[@]}"
fd32fa22c52cfc8e1a0c29eb38519f87084cab0b04b0d8f020a4d38b2f4e223e
7fdad037a921f7eec4f97c08722692028e96888f0b970dc7b3bb6a9c97e8f988
```
```bash
: ; # We have to satisfy the same policy on the receive side:
: ; policy=(tpm2 policypcr -l sha256:11 -f pcr.dat)
: ;
: ; tpm-receive.sh -f cipher.bin "${policy[@]}"
fd32fa22c52cfc8e1a0c29eb38519f87084cab0b04b0d8f020a4d38b2f4e223e
7fdad037a921f7eec4f97c08722692028e96888f0b970dc7b3bb6a9c97e8f988
name: 000be1fe1b777ead331f2da896ced2bf7a3949d732a0c6adf6f0a292567d587c4408
837197674484b3f81a90cc8d46a5d724fd52d76e06520b64f2a1da1b331469aa
fd32fa22c52cfc8e1a0c29eb38519f87084cab0b04b0d8f020a4d38b2f4e223e
7fdad037a921f7eec4f97c08722692028e96888f0b970dc7b3bb6a9c97e8f988
certinfodata:b7bd59980628c33a14377d53e165c229
: ;
```
Multiple policy commands can be separated with a quoted semi-colon:
```bash
send-to-tpm.sh ... tpm2 policyblah ... \; policyfoo ...
```
Multiple policy commands can be separated with a quoted semi-colon:
```bash
send-to-tpm.sh ... tpm2 policyblah ... \; policyfoo ...
```
When a policy is specified, these scripts will automatically set the
`adminWithPolicy` attribute of the activation object, and will add
`tpm2 policycommandcode TPM2_CC_ActivateCredential` to the policy, as
that is required for activation objects with `adminWithPolicy` set.
# Enrollment Semantics

165
Enrollment/send-to-tpm.sh Executable file
View file

@ -0,0 +1,165 @@
#!/bin/bash
PROG=${0##*/}
set -euo pipefail
function usage {
((${1:-1} > 0)) && exec 1>&2
cat <<EOF
Usage: $PROG EK-PUB-FILE SECRET-FILE OUT-FILE
$PROG EK-PUB-FILE SECRET-FILE OUT-FILE [POLICY-CMD [ARGS [\\; ...]]]
$PROG -P well-known-key-name EK-PUB-FILE SECRET-FILE OUT-FILE
Encrypts a small secret to a TPM's EKpub with the caller's choice of
policy.
Policies should be specified as a sequence of {tpm2 policy...}
commands, with all necessary arguments except for {--session}|{-S}
and {--policy}|{-L} options. Also, no need to include {tpm2
policycommandcode}, as that will get added. E.g.:
$ $PROG ./ekpub ./secret ./madecredential \\
tpm2 policypcr -l "sha256:0,1,2,3" -f pcrs
Options:
-h This help message.
-P WKname Use the given cryptographic name binding a policy for
recipient to meet.
-f Overwrite OUT-FILE.
-x Trace this script.
EOF
exit ${1:-1}
}
force=false
wkname=
while getopts +:hfxP: opt; do
case "$opt" in
P) wkname=$OPTARG;;
h) usage 0;;
f) force=true;;
x) set -vx;;
*) usage;;
esac
done
shift $((OPTIND - 1))
(($# >= 3)) || usage
ekpub_file=$1
secret_file=$2
out_file=$3
shift 3
function err {
echo "ERROR: $*" 1>&2
exit 1
}
[[ -f ${ekpub_file:-} ]] || usage
[[ -f ${secret_file:-} ]] || usage
[[ -f ${out_file:-} ]] && $force && rm -f "${out_file:-}"
[[ -f ${out_file:-} ]] && err "output file ($out_file) exists"
# Make a temp dir and remove it when we exit:
d=
trap 'rm -rf "$d"' EXIT
d=$(mktemp -d)
function exec_policy {
local add_commandcode=true
local has_policy=false
while (($# > 0)); do
has_policy=true
cmd=()
while (($# > 0)) && [[ $1 != ';' ]]; do
cmd+=("$1")
if ((${#cmd[@]} == 1)) && [[ ${cmd[0]} = tpm2_* ]]; then
cmd+=(--session "${d}/session.ctx" --policy "${d}/policy")
elif ((${#cmd[@]} == 2)) && [[ ${cmd[0]} = tpm2 ]]; then
cmd+=(--session "${d}/session.ctx" --policy "${d}/policy")
fi
shift
done
(($# > 0)) && shift
# Run the policy command in the temp dir. It -or the last command- must
# leave a file there named 'policy'.
"${cmd[@]}"
if [[ ${cmd[0]} = tpm2 ]] && ((${#cmd[@]} == 1)); then
echo "Policy is incomplete" 1>&2
exit 1
fi
[[ ${cmd[0]} = tpm2 && ${cmd[1]} = policycommandcode ]] &&
add_commandcode=false
[[ ${cmd[0]} = tpm2_policycommandcode ]] && add_commandcode=false
done
$has_policy && $add_commandcode &&
tpm2 policycommandcode --session "${d}/session.ctx" \
--policy "${d}/policy" \
TPM2_CC_ActivateCredential
}
function make_policyDigest {
# Start a trial session, execute the given policy commands, save the
# policyDigest.
tpm2 startauthsession --session "${d}/session.ctx"
exec_policy "$@"
}
function wkname {
local attrs='decrypt|sign'
local has_policy
# This is the WK. It was generated with:
# openssl genpkey -genparam \
# -algorithm EC \
# -out "${d}/ecp.pem" \
# -pkeyopt ec_paramgen_curve:secp384r1 \
# -pkeyopt ec_param_enc:named_curve
# openssl genpkey -paramfile "${d}/ecp.pem"
cat > "${d}/wkpriv.pem" <<EOF
-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAlMnCWue7CfXjNLibH
PTJrsOLUcoxqU3FLWYEWMI+HuPnzcwwl7SkKN6cpf4H3oQihZANiAAQ1pw6D5QVw
vymljYVDyrUriOet8zPB/9tq9XJ7A54qsVkaVufAuEJ6GIvD4xUZ27manMosJADS
aW2TLJkwxecRh2eTwPtSx2U32M2/yHeuWRV/0juiIozefPsTAlHAi3E=
-----END PRIVATE KEY-----
EOF
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
tpm2 flushcontext --saved-session 1>&2
# Load
attrs='decrypt|sign'
if (($# > 0)); then
make_policyDigest "$@" 1>&2
attrs='adminwithpolicy|decrypt|sign'
has_policy=true
# Flush again, but this time not saved sessions
tpm2 flushcontext --transient-object 1>&2
tpm2 flushcontext --loaded-session 1>&2
fi
# Load the WK
tpm2 loadexternal -C n \
-Gecc \
-r "${d}/wkpriv.pem" \
${has_policy:+-L "${d}/policy"} \
-a "$attrs" \
-c "${d}/wk.ctx" |
grep ^name: | cut -d' ' -f2
}
[[ -z $wkname ]] && wkname=$(wkname "$@")
tpm2 makecredential \
--tcti "none" \
--encryption-key "${ekpub_file}" \
--name "$wkname" \
--secret "${secret_file}" \
--credential-blob "$out_file"

194
Enrollment/tpm-receive.sh Executable file
View file

@ -0,0 +1,194 @@
#!/bin/bash
PROG=${0##*/}
set -euo pipefail
function usage {
echo "Usage: $PROG [OPTIONS] CIPHERTEXT-FILE OUT-FILE [POLICY-CMD [ARGS] [\; ...]]"
cat <<EOF
Usage: $PROG CIPHERTEXT-FILE OUT-FILE [POLICY-CMD [ARGS] [;] ...]
"Activates" (decrypts) CIPHERTEXT-FILE made with TPM2_MakeCredential and
writes the plaintext to OUT-FILE. If the sender asserted some policy,
that policy must be repeated when invoking this program to decrypt the
secret.
Policies should be specified as a sequence of {tpm2 policy...}
commands, with all necessary arguments except for {--session}|{-S}
and {--policy}|{-L} options. Also, no need to include {tpm2
policycommandcode}, as that will get added. E.g.:
$ $PROG ./ekpub ./secret ./madecredential \\
tpm2 policypcr -l "sha256:0,1,2,3" -f pcrs
Options:
-h This help message.
-f Overwrite OUT-FILE.
-x Trace this script.
EOF
exit 1
}
force=false
verbose=false
while getopts +:hfvx opt; do
case "$opt" in
h) usage 0;;
f) force=true;;
v) verbose=true;;
x) set -vx;;
*) usage;;
esac
done
shift $((OPTIND - 1))
(($# >= 2)) || usage
ciphertext_file=$1
out_file=$2
shift 2
[[ -f ${ciphertext_file:-} ]] || usage
[[ -f ${out_file:-} ]] && $force && rm -f "$out_file"
[[ -f ${out_file:-} ]] && usage
d=
trap 'rm -rf "$d"' EXIT
d=$(mktemp -d)
function v {
if $verbose; then
printf 'Running:'
printf ' %q' "$@"
printf '\n'
fi >/dev/tty || true
if "$@"; then
$verbose && printf '(SUCCESS)\n' >/dev/tty || true
else
stat=$?
printf 'ERROR: Command exited with %d\n' $stat >/dev/tty || true
return $stat
fi
}
function exec_policy {
local add_commandcode=true
local has_policy=false
while (($# > 0)); do
has_policy=true
cmd=()
while (($# > 0)) && [[ $1 != ';' ]]; do
cmd+=("$1")
if ((${#cmd[@]} == 1)) && [[ ${cmd[0]} = tpm2_* ]]; then
cmd+=(--session "${d}/session.ctx" --policy "${d}/policy")
elif ((${#cmd[@]} == 2)) && [[ ${cmd[0]} = tpm2 ]]; then
cmd+=(--session "${d}/session.ctx" --policy "${d}/policy")
fi
shift
done
(($# > 0)) && shift
# Run the policy command in the temp dir. It -or the last command- must
# leave a file there named 'policy'.
"${cmd[@]}"
if [[ ${cmd[0]} = tpm2 ]] && ((${#cmd[@]} == 1)); then
echo "Policy is incomplete" 1>&2
exit 1
fi
[[ ${cmd[0]} = tpm2 && ${cmd[1]} = policycommandcode ]] &&
add_commandcode=false
[[ ${cmd[0]} = tpm2_policycommandcode ]] && add_commandcode=false
done
$has_policy && $add_commandcode &&
tpm2 policycommandcode --session "${d}/session.ctx" \
--policy "${d}/policy" \
TPM2_CC_ActivateCredential
}
function make_policyDigest {
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
v tpm2 startauthsession --session "${d}/session.ctx"
exec_policy "$@"
}
# Get the EK handle:
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
tpm2 flushcontext --saved-session 1>&2
tpm2 createek --key-algorithm rsa \
--ek-context "${d}/ek.ctx" \
--public "${d}/ek.pub"
# Make policyDigest and load WK
attrs='decrypt|sign'
adminwithpolicy=
if (($# > 0)); then
make_policyDigest "$@"
attrs='adminwithpolicy|decrypt|sign'
adminwithpolicy=true
fi
rm -f "${d}/session.ctx"
# This is the WK. It was generated with:
# openssl genpkey -genparam \
# -algorithm EC \
# -out "${d}/ecp.pem" \
# -pkeyopt ec_paramgen_curve:secp384r1 \
# -pkeyopt ec_param_enc:named_curve
# openssl genpkey -paramfile "${d}/ecp.pem"
cat > "${d}/wkpriv.pem" <<EOF
-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAlMnCWue7CfXjNLibH
PTJrsOLUcoxqU3FLWYEWMI+HuPnzcwwl7SkKN6cpf4H3oQihZANiAAQ1pw6D5QVw
vymljYVDyrUriOet8zPB/9tq9XJ7A54qsVkaVufAuEJ6GIvD4xUZ27manMosJADS
aW2TLJkwxecRh2eTwPtSx2U32M2/yHeuWRV/0juiIozefPsTAlHAi3E=
-----END PRIVATE KEY-----
EOF
# Load the WK
v tpm2 flushcontext --transient-object 1>&2
v tpm2 flushcontext --loaded-session 1>&2
if v tpm2 loadexternal -C n \
-Gecc \
-r "${d}/wkpriv.pem" \
${adminwithpolicy:+-L "${d}/policy"} \
-a "$attrs" \
-c "${d}/wk.ctx" > "${d}/out" 2> "${d}/err"; then
cat "${d}/out" 1>&2
else
stat=$?
echo "ERROR: Failed to load WK:" 1>&2
cat "${d}/out"
cat "${d}/err" 1>&2
exit $stat
fi
# Create empty auth session for EK
v tpm2 flushcontext --transient-object
v tpm2 flushcontext --loaded-session
v tpm2 startauthsession --session "${d}/sessionek.ctx" --policy-session
v tpm2 policysecret --session "${d}/sessionek.ctx" --object-context endorsement
activatecredential_args=()
if (($# > 0)); then
activatecredential_args+=(--credentialedkey-auth session:"${d}/session.ctx")
# Create auth session for the WK, since it has adminWithPolicy
v tpm2 flushcontext --transient-object
v tpm2 flushcontext --loaded-session
v tpm2 startauthsession --session "${d}/session.ctx" --policy-session
exec_policy "$@"
v tpm2 flushcontext --transient-object
v tpm2 flushcontext --loaded-session
fi
# Finally, ActivateCredential
$verbose && tpm2 readpublic -c "${d}/wk.ctx" | grep name:
v tpm2 activatecredential --credentialedkey-context "${d}/wk.ctx" \
"${activatecredential_args[@]}" \
--credentialkey-context "${d}/ek.ctx" \
--credentialkey-auth session:"${d}/sessionek.ctx" \
--credential-blob "$ciphertext_file" \
-o "$out_file"

View file

@ -606,6 +606,9 @@ other state. TPM commands may check that an authorization session's
state satisfies the requirements for use of the argument objects passed
to the commands.
> NOTE: Every command input parameter that is a handle that requires
> authorization must have its own session associated with it.
### Authorization Session State
Authorization sessions have a number of state attributes. Some of these
@ -688,13 +691,89 @@ ways. These state attributes are:
### Encryption Sessions
> Work in progress.
Sessions can also be used for encrypting TPM command arguments and
results. This can be useful when one does not trust the path to the
TPM, such as when the TPM is remote.
> TODO: Discuss key exchange options, etc.
Only the first input parameter of a TPM command will be encrypted, and
only the first output parameter of a TPM command will be encrypted, and
that only if when that first parameter is of type `TPM2B`. Those first
`TPM2B` type command input and/or output parameters will be encrypted
with a symmetrict AES key derived from a secret key established via RSA
key transport or ECDH key agreement.
> Encryption sessions are useful for when the path to a TPM is not
> trused, such as when a TPM is a remote TPM, or when otherwise the path
> to the TPM is not trusted.
### Key Exchange for Encryption Sessions
> Encryption sessions are useful for when the path to a TPM is not
> trused, such as when a TPM is a remote TPM, or when otherwise the path
> to the TPM is not trusted. This section talks about key exchange for
> such situations.
The symmetric keys used for TPM command encryption are exchanged at
session creation time.
Keys can be provided by one of either RSA key transport or ECC key
agreement, and/or the secret `authValue` of a loaded entity.
Sessions are created with
[`TPM2_StartAuthSession()`](/TPM-Commands/TPM2_StartAuthSession.md),
which has serveral _optional_ input and output parameters related to
session encryption. In particular it provides ways to create a session
key for command parameter encryption:
- RSA key transport
The caller can encrypt a secret to a public key for which the TPM has
loaded the private key as identified by the `tpmKey` input parameter
of [`TPM2_StartAuthSession()`].
- ECDH key agreement
The caller can generate an ephemeral ECDH key and use it with the
public key of the ECDH key object identified by the `tpmKey` input
parameter of [`TPM2_StartAuthSession()`]. The TPM will use the
private key of the object identified by the `tpmKey` input parameter
and the ephemeral public key sent by the caller in the
`encryptedSalt` input parameter.
- use the `authHash` of the entity identified by the `bind` input
parameter
The caller computes the same session key as the TPM.
To authenticate the TPM and prevent active attacks, the caller of
`TPM2_StartAuthSession()` should use an `EK` as the `tpmKey` and its
`EKpub` to locally compute the session key. Alternatively the caller
can use a non-`EK` key object created over an earlier encrypted session
that authenticated the target TPM.
> A non-null `bind` parameter can be used to create a "bound" session
> that can be used to satisfy HMAC-based authorization for specific
> objects. We will not cover this in detail here.
### HMAC Sessions
An HMAC session proves the caller knows the `authValue` secret of some
entity. This functions a lot like a password, with the `authValue`
used to compute HMACs that prove possession, but with the `authValue`
generally being large and randomly generated, thus much stronger than a
password.
Typically the `authValue` of some entity should be sent encrypted to the
TPM when creating an entity, with [the encrypted session being keyed via
RSA key transport or ECDH](#Key-Exchange-for-Encryption-Sessions). This
way an `authValue`, though a simple, password-like binary string, can be
strong and secure due to being large, randomly chosen and sent over
an encrypted session.
### Password Sessions
> WIP [Say something about passwords and password sessions, besides
> "don't use them" and "support remains mostly for TPM 1.2 reasons".]
Alternatively a session can be for encryption of command inputs/outputs,
which is useful when the path to the TPM is not secure.

View file

@ -0,0 +1,151 @@
# `TPM2_StartAuthSession()`
This command starts a session that can be used for authorization and/or
encryption.
## Inputs
- `TPMI_DH_OBJECT+ tpmKey`
This optional _input_ parameter specifies the handle of a loaded RSA
decryption key or of a loaded ECDH key.
- `TPMI_DH_ENTITY+ bind`
This parameter, if not null, references a loaded entity whose
`authValue` will be used in the session key computation.
- `TPM2B_NONCE nonceCaller`
This is a nonce chosen by the caller.
- `TPM2B_ENCRYPTED_SECRET encryptedSalt`
This optional _input_ parameter must be present if `tpmKey` is
present.
If `tpmKey` is an RSA decryption key then `encryptedSalt` must be an
RSA OEAP ciphertext that will be decrypted with the `tpmKey`. The
plaintext will be used to derive symmetric AES-CFB encryption keys.
If `tpmKey` is an ECDH key, then `encryptedSalt` must be a public key
that will be used to generate a shared secret key from which
symmetric AES-CFB encryption keys will be derived.
- `TPM_SE sessionType`
- `TPMT_SYM_DEF+ symmetric`
- `TPMI_ALG_HASH authHash`
A hash algorithm for the key derivation function.
## Outputs (success case)
- `TPMI_SH_AUTH_SESSION sessionHandle`
- `TPM2B_NONCE nonceTPM`
This is an _output_ parameter that is generated by the TPM, and it is
a nonce that is used for key derivation.
## Session Types
The `sessionType` input parameter must be one of:
- `TPM_SE_HMAC`
- `TPM_SE_POLICY`
- `TPM_SE_TRIAL`
### HMAC Sessions
If the session is to be an HMAC session authenticating knowledge of some
entity's `authValue`, then the `bind` argument must be provided.
### Authorization Sessions
For policy sessions, the caller should now call one or more
`TPM2_Policy*()` commands to execute the policy identified by the
`authPolicy` value of the entity to be accessed via this session.
### Trial Policies
For trial sessions, the caller should now call one or more
`TPM2_Policy*()` commands as will be used in future actual policy
sessions, then extract the `policyDigest` of the
session after the last policy command -- that will be a value
suitablefor use as an `authPolicy` value for TPM entities.
### Encryption Sessions
> All sessions can be used for encryption that were created with either
> or both of the `bind` input parameter and the pair of input parameters
> `tpmKey` and `encryptedSalt` set.
> Encryption sessions are useful for when the path to a TPM is not
> trused, such as when a TPM is a remote TPM, or when otherwise the path
> to the TPM is not trusted. This section talks about key exchange for
> such situations.
For encryption sessions the `symmetric` parameter should also be set.
Encryption sessions can have a session key derived from either or both
of the `authValue` of the `bind` entity or the key exchange represented
by the `tpmKey` and `encryptedSalt` inputs. The `nonceCaller` input and
the `nonceTPM` output will also salt the key derivation.
The symmetric keys used for TPM command encryption are set at session
creation time.
Session keys are derived from the `tpmKey` and `encryptedSalt` inputs
(if provided) and the `authValue` of a loaded entity referred to by
`bind` (if provided), along with the nonces and other things.
The `tpmKey` and `encryptedSalt` inputs can inject a secret either via
RSA key transport or elliptic curve Diffie-Hellman (ECDH).
The key will be derived as follows:
- if `tpmKey` and `encryptedSalt` are provided, then the key is
recovered (RSA case) or computed (ECDH case)
In the RSA case the `encryptedSalt` is the ciphertext resulting from
RSA PKCS#2 (OEAP) encryption to the public key of the object referred
to by `tpmKey`. The TPM will decrypt the `encryptedSalt` to recover
the secret.
In the ECDH case the `encryptedSalt` is an ephemeral public key, and
the secret will be the ECDH shared secret constructed from that key
and the private part of the `tpmKey`.
- then the internal `KDFa()` function will invoked as follows:
```
sessionKey := KDFa(authHash,
(bind.authValue || tmpKey.get(encryptedSalt)),
"ATH",
nonceTPM,
nonceCaller,
authHash.digestSize)
```
where:
- `bind.authValue` is the `authValue` of the `bind` entity (if
provided)
- `tmpKey.get(encryptedSalt)` is the result of RSA decryption of
`encryptedSalt` if `tpmKey` is an RSA key, or the result of ECDH
key agreement between the private part of `tpmKey` and the public
ECDH key in `encryptedSalt` if `tpmKey` is an ECDH key
To avoid active attacks, one would use the EK as the `tpmKey` input
parameter of `TPM2_StartAuthSession()`. Or one could use a `tpmKey`
input created with, e.g., `TPM2_Create()` over another encrypted session
that itself used the EK as its `tpmKey` input.
> A non-null `bind` parameter can be used to create a "bound" session
> that can be used to satisfy HMAC-based authorization for specific
> objects. We will not cover this in detail here.
## References
- [TCG TPM Library part 1: Architecture, sections 18.6, 19, and 21](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part1_Architecture.pdf)
- [TCG TPM Library part 3: Commands, section 11.1](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part3_Commands_pub.pdf)