This procedure will transfer an HMAC key created inside TPM-A to TPM-B but prevent TPM-B to transfer it to TPM-C.
Basically, and extension of As an end-to-end example, the following will transfer an RSA key generated on TPM-A to TPM-B but
using tpm2_policyduplicationselect
tp prevent further duplication
Step 1 below will transfer a key from A->B, step 2 attempts B->C but is prevented duplication on B by policy
## on B, first create a parent object
tpm2_createprimary -C o -g sha256 -G rsa -c primary.ctx
tpm2_create -C primary.ctx -g sha256 -G rsa -r new_parent.prv \
-u new_parent.pub -a "fixedtpm|fixedparent|restricted|sensitivedataorigin|decrypt|userwithauth"
copy new_parent.pub to A
## read the paren public part, load it and export its "name"
tpm2_print -t TPM2B_PUBLIC new_parent.pub
tpm2_loadexternal -C o -u new_parent.pub -c new_parent.ctx -n dst_n.name
## create a primary object and a policy that that restricts duplicatoin to just `dst_n.name`
tpm2_createprimary -C o -g sha256 -G rsa -c primary.ctx
tpm2_startauthsession -S session.dat
tpm2_policyduplicationselect -S session.dat -N dst_n.name -L dpolicy.dat
tpm2_flushcontext session.dat
rm session.dat
## create an hmac key with that policy
tpm2_create -C primary.ctx -g sha256 -G hmac -r key.prv -u key.pub -L dpolicy.dat -a "sensitivedataorigin|userwithauth|sign"
tpm2_load -C primary.ctx -r key.prv -u key.pub -c key.ctx
## create a test hmac
export plain="foo"
echo -n $plain | tpm2_hmac -g sha256 -c key.ctx | xxd -p -c 256
42a1fad918fa0e4cbea94d759da89ccdfac5a640672d0170f4930cafe14d179c
### print the key context and export the public part
tpm2_readpublic -c key.ctx -o dup.pub
## now start an auth session
## bind the duplicate to the destination "name"
tpm2_startauthsession --policy-session -S session.dat
tpm2_readpublic -c key.ctx -n dupkey.name
tpm2_policyduplicationselect -S session.dat -N dst_n.name -L dpolicy.dat -n dupkey.name
## now duplicate
tpm2_duplicate -C new_parent.ctx -c key.ctx -G null -p "session:session.dat" -r dup.dup -s dup.seed
copy dup.dup dup.seed dup.pub to B
## reload the parent used for the transfer
tpm2_flushcontext --transient-object
tpm2_load -C primary.ctx -u new_parent.pub -r new_parent.prv -c new_parent.ctx
## just import the duplicated key
tpm2_import -C new_parent.ctx -u dup.pub -i dup.dup -r dup.prv -s dup.seed
tpm2_load -C new_parent.ctx -u dup.pub -r dup.prv -c dup.ctx
## test hmac
## this will be the same as on A
export plain="foo"
echo -n $plain | tpm2_hmac -g sha256 -c dup.ctx | xxd -p -c 256
42a1fad918fa0e4cbea94d759da89ccdfac5a640672d0170f4930cafe14d179c
tpm2_print -t TPM2B_PUBLIC dup.pub
Now try to tranfer the same key from B to C
## create a parent on C used for the transfer
tpm2_createprimary -C o -g sha256 -G rsa -c primary_2.ctx
tpm2_create -C primary_2.ctx -g sha256 -G rsa -r new_parent_2.prv \
-u new_parent_2.pub -a "fixedtpm|fixedparent|restricted|sensitivedataorigin|decrypt|userwithauth"
_ copy new_parent_2.pub to B_
## just as a sanity check load the **original** hmac key and check it
## remember this key was transfered from A->B using new_parent (new_parent_2 is from B->C)
tpm2_load -C new_parent.ctx -u dup.pub -r dup.prv -c dup.ctx
export plain="foo"
echo -n $plain | tpm2_hmac -g sha256 -c dup.ctx | xxd -p -c 256
## load load new_parent_2 (which is the key from C)
tpm2_loadexternal -C o -u new_parent_2.pub -c new_parent_2.ctx -n dst_n.name
tpm2_startauthsession --policy-session -S session_2.dat
tpm2_readpublic -c dup.ctx -n dupkey.name
## set the policy duplicate against the "name" from C
tpm2_policyduplicationselect -S session_2.dat -N dst_n.name -L dpolicy_2.dat -n dupkey.name
## duplication will fail by policy
### since the key is restricted to a parent
tpm2_duplicate -C new_parent_2.ctx -c dup.ctx -G null -p "session:session_2.dat" -r dup_2.dup -s dup_2.seed
WARNING:esys:src/tss2-esys/api/Esys_Duplicate.c:354:Esys_Duplicate_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_Duplicate.c:116:Esys_Duplicate() Esys Finish ErrorCode (0x0000099d)
ERROR: Esys_Duplicate(0x99D) - tpm:session(1):a policy check failed
ERROR: Unable to run tpm2_duplicate