Procedure to transfer a TPM key from one TPMA to TPMB with policies:
policy_duplicateselect
: TPMB cannot re-export it.policy_pcr
: allows TPMA to set which PCR values must be preset on B to use this key
see Prevent Chained duplication from A -> B -> C using tpm2_policyduplicationselect
- Create two TPMs
## TPM A
rm -rf /tmp/myvtpm && mkdir /tmp/myvtpm
sudo swtpm_setup --tpmstate /tmp/myvtpm --tpm2 --create-ek-cert
sudo swtpm socket --tpmstate dir=/tmp/myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear
## TPM B
rm -rf /tmp/myvtpm2 && mkdir /tmp/myvtpm2
sudo swtpm_setup --tpmstate /tmp/myvtpm2 --tpm2 --create-ek-cert
sudo swtpm socket --tpmstate dir=/tmp/myvtpm2 --tpm2 --server type=tcp,port=2341 --ctrl type=tcp,port=2342 --flags not-need-init,startup-clear
- read the pcr23 values
export TPM2TOOLS_TCTI="swtpm:port=2321"
export TPM2OPENSSL_TCTI="swtpm:port=2321"
tpm2_pcrread sha256:23
export TPM2TOOLS_TCTI="swtpm:port=2341"
export TPM2OPENSSL_TCTI="swtpm:port=2341"
tpm2_pcrread sha256:23
- on TPMB
### create the new parent
export TPM2TOOLS_TCTI="swtpm:port=2341"
export TPM2OPENSSL_TCTI="swtpm:port=2341"
tpm2_flushcontext -t
tpm2_createprimary -C o -g sha256 -G rsa -c primaryB.ctx
tpm2_create -C primaryB.ctx -g sha256 -G rsa \
-r new_parent.prv -u new_parent.pub \
-a "restricted|sensitivedataorigin|decrypt|userwithauth"
tpm2_flushcontext -t
- on TPMA
## load the new parent
export TPM2TOOLS_TCTI="swtpm:port=2321"
export TPM2OPENSSL_TCTI="swtpm:port=2321"
tpm2_flushcontext -t
tpm2_flushcontext -s
### craeate a primary
tpm2_createprimary -C o -g sha256 -G rsa -c primaryA.ctx
## and session bound to the current PCR values and restrict its duplication targets
### the following is an OR policy (since we need to do the duplication later)
### first PCR
tpm2_pcrread -o pcr23_valA.bin "sha256:23"
tpm2_startauthsession -S sessionA.dat
tpm2_policypcr -S sessionA.dat -l "sha256:23" -f pcr23_valA.bin -L policyA_pcr.dat
tpm2_flushcontext sessionA.dat
rm sessionA.dat
### then tpm2_policyduplicationselect
## load the remote parent and get its 'name'
tpm2_loadexternal -C o -u new_parent.pub -c new_parent.ctx -n dst_n.name
tpm2_startauthsession -S sessionA.dat
tpm2_policyduplicationselect -S sessionA.dat -N dst_n.name -L policyA_dupselect.dat
tpm2_flushcontext sessionA.dat
rm sessionA.dat
### create an OR policy together
tpm2_startauthsession -S sessionA.ctx
tpm2_policyor -S sessionA.ctx -L policyA_or.dat sha256:policyA_pcr.dat,policyA_dupselect.dat
tpm2_flushcontext sessionA.ctx
### create the key with that policy
tpm2_flushcontext -t
tpm2_create -C primaryA.ctx -G rsa -g sha256 -r key.prv -u key.pub -L policyA_or.dat -a "sensitivedataorigin|decrypt|sign"
tpm2_flushcontext -t
### load the new key
tpm2_load -C primaryA.ctx -r key.prv -u key.pub -c key.ctx -n key.name
tpm2_readpublic -c key.ctx -o dup.pub
tpm2_flushcontext -t
### create a policy-session as policy_or
tpm2_pcrread -o pcr23_valA.bin "sha256:23"
tpm2_startauthsession -S sessionA.dat --policy-session
tpm2_policypcr -S sessionA.dat -l "sha256:23" -f pcr23_valA.bin -L policyA_pcr.dat
tpm2_flushcontext sessionA.dat
rm sessionA.dat
tpm2_startauthsession -S sessionA.dat --policy-session
tpm2_policyduplicationselect -S sessionA.dat -N dst_n.name -L policyA_dupselect.dat
tpm2_flushcontext sessionA.dat
rm sessionA.dat
tpm2_startauthsession -S sessionA.dat --policy-session
tpm2_policypcr -S sessionA.dat -l "sha256:23" -f pcr23_valA.bin -L policyA_pcr.dat
tpm2_policyor -S sessionA.dat -L policyA_or.dat sha256:policyA_pcr.dat,policyA_dupselect.dat
### test sgnature
echo "meet me at.." >file.txt
tpm2_sign -c key.ctx -g sha256 -f plain -p"session:sessionA.dat" -o signA.raw file.txt
tpm2_flushcontext -t
### load the new parent
tpm2_loadexternal -C o -u new_parent.pub -c new_parent.ctx -n dst_n.name
tpm2_flushcontext -t
## create the full policy
tpm2_startauthsession -S sessionA.dat --policy-session
tpm2_policyduplicationselect -S sessionA.dat -N dst_n.name -n key.name -L policyA_dupselect.dat
tpm2_policyor -S sessionA.dat -L policyA_or.dat sha256:policyA_pcr.dat,policyA_dupselect.dat
### duplicate
tpm2_flushcontext -t
tpm2_duplicate -C new_parent.ctx -c key.ctx -G null -p "session:sessionA.dat" -r dup.dpriv -s dup.seed
tpm2_flushcontext -t
- on TPMB
export TPM2TOOLS_TCTI="swtpm:port=2341"
export TPM2OPENSSL_TCTI="swtpm:port=2341"
## load the parent
tpm2_flushcontext -t
tpm2_load -C primaryB.ctx -u new_parent.pub -r new_parent.prv -c new_parent.ctx
### import the key
tpm2_import -C new_parent.ctx -u dup.pub -i dup.dpriv -r dup.prv -s dup.seed
tpm2_flushcontext -t
tpm2_load -C new_parent.ctx -u dup.pub -r dup.prv -c dup.ctx
tpm2_readpublic -c dup.ctx -o dup.pub
tpm2_flushcontext -t
## test failure with no auth
tpm2_sign -c dup.ctx -g sha256 -f plain -o signB.raw file.txt
tpm2_flushcontext -t
## regenerate the full policy
tpm2_pcrread -o pcr23_valA.bin "sha256:23"
tpm2_startauthsession -S sessionA.dat --policy-session
tpm2_policypcr -S sessionA.dat -l "sha256:23" -f pcr23_valA.bin -L policyA_pcr.dat
tpm2_flushcontext sessionA.dat
rm sessionA.dat
tpm2_startauthsession -S sessionA.dat --policy-session
tpm2_policyduplicationselect -S sessionA.dat -N dst_n.name -L policyA_dupselect.dat
tpm2_flushcontext sessionA.dat
rm sessionA.dat
tpm2_startauthsession -S sessionA.dat --policy-session
tpm2_policypcr -S sessionA.dat -l "sha256:23" -f pcr23_valA.bin -L policyA_pcr.dat
tpm2_policyor -S sessionA.dat -L policyA_or.dat sha256:policyA_pcr.dat,policyA_dupselect.dat
### test sign
tpm2_sign -c dup.ctx -g sha256 -f plain -o signB.raw file.txt -p "session:sessionA.dat"
tpm2_flushcontext sessionA.dat
rm sessionA.dat
to extend
$ tpm2_pcrread "sha256:23"
sha256:
23: 0xF5A5FD42D16A20302798EF6ED309979B43003D2320D9F0E8EA9831A92759FB4B
$ tpm2_pcrextend 23:sha256=0xF5A5FD42D16A20302798EF6ED309979B43003D2320D9F0E8EA9831A92759FB4B
$ tpm2_pcrread "sha256:23"
sha256:
23: 0xDB56114E00FDD4C1F85C892BF35AC9A89289AAECB1EBD0A96CDE606A748B5D71
$ tpm2_sign -c dup.ctx -g sha256 -f plain -o signB.raw file.txt -p "session:sessionA.dat"
WARNING:esys:src/tss2-esys/api/Esys_Sign.c:311:Esys_Sign_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_Sign.c:105:Esys_Sign() Esys Finish ErrorCode (0x0000099d)
ERROR: Esys_Sign(0x99D) - tpm:session(1):a policy check failed
ERROR: Unable to run tpm2_sign