From c79b99e11735ebbc23b0c37eb7f634e8c5005025 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Thu, 10 Jun 2021 17:26:12 -0500 Subject: [PATCH 1/2] Add sample encrypt-to-TPM scripts --- Attestation/README.md | 8 +- Enrollment/README.md | 93 +++++++++++++++++- Enrollment/send-to-tpm.sh | 165 ++++++++++++++++++++++++++++++++ Enrollment/tpm-receive.sh | 194 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 456 insertions(+), 4 deletions(-) create mode 100755 Enrollment/send-to-tpm.sh create mode 100755 Enrollment/tpm-receive.sh diff --git a/Attestation/README.md b/Attestation/README.md index 4a4d08b..27fcb8b 100644 --- a/Attestation/README.md +++ b/Attestation/README.md @@ -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_ diff --git a/Enrollment/README.md b/Enrollment/README.md index 76a0027..0367c68 100644 --- a/Enrollment/README.md +++ b/Enrollment/README.md @@ -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 diff --git a/Enrollment/send-to-tpm.sh b/Enrollment/send-to-tpm.sh new file mode 100755 index 0000000..372e81a --- /dev/null +++ b/Enrollment/send-to-tpm.sh @@ -0,0 +1,165 @@ +#!/bin/bash + +PROG=${0##*/} + +set -euo pipefail + +function usage { + ((${1:-1} > 0)) && exec 1>&2 + cat <= 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" <&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" diff --git a/Enrollment/tpm-receive.sh b/Enrollment/tpm-receive.sh new file mode 100755 index 0000000..32593f5 --- /dev/null +++ b/Enrollment/tpm-receive.sh @@ -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 <= 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" <&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" From ceeaddbe8837aa7beb88a39f7f01720da11af4a8 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Fri, 11 Jun 2021 11:28:37 -0500 Subject: [PATCH 2/2] Intro: Describe encrypted sessions --- Intro/README.md | 85 ++++++++++++++- TPM-Commands/TPM2_StartAuthSession.md | 151 ++++++++++++++++++++++++++ 2 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 TPM-Commands/TPM2_StartAuthSession.md diff --git a/Intro/README.md b/Intro/README.md index 9469107..edb3d5f 100644 --- a/Intro/README.md +++ b/Intro/README.md @@ -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".] ## Restricted Cryptographic Keys diff --git a/TPM-Commands/TPM2_StartAuthSession.md b/TPM-Commands/TPM2_StartAuthSession.md new file mode 100644 index 0000000..62e0cec --- /dev/null +++ b/TPM-Commands/TPM2_StartAuthSession.md @@ -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)