Skip to content

Instantly share code, notes, and snippets.

@salrashid123
Last active August 8, 2024 14:01
Show Gist options
  • Save salrashid123/a61e09684c5d59440834d91241627458 to your computer and use it in GitHub Desktop.
Save salrashid123/a61e09684c5d59440834d91241627458 to your computer and use it in GitHub Desktop.
Transfer TPM based key using PCR policy

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment