{"id":30622271,"url":"https://github.com/salrashid123/tpmcopy","last_synced_at":"2026-01-31T02:15:15.405Z","repository":{"id":305063081,"uuid":"1021807319","full_name":"salrashid123/tpmcopy","owner":"salrashid123","description":"securely transfer and embed RSA|ECC|AES|HMAC key to a remote Trusted Platform Module (TPM)","archived":false,"fork":false,"pushed_at":"2026-01-26T11:56:58.000Z","size":272,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-27T01:18:21.154Z","etag":null,"topics":["tpm2","trusted-platform-module"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/salrashid123/tpmcopy","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/salrashid123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-18T01:42:13.000Z","updated_at":"2026-01-26T11:57:02.000Z","dependencies_parsed_at":"2025-07-18T06:16:11.079Z","dependency_job_id":"8195b4c7-5a2b-4303-b1cc-29cd7e41400d","html_url":"https://github.com/salrashid123/tpmcopy","commit_stats":null,"previous_names":["salrashid123/tpmcopy"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/salrashid123/tpmcopy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Ftpmcopy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Ftpmcopy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Ftpmcopy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Ftpmcopy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salrashid123","download_url":"https://codeload.github.com/salrashid123/tpmcopy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Ftpmcopy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28926639,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-30T22:32:35.345Z","status":"online","status_checked_at":"2026-01-31T02:00:09.179Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["tpm2","trusted-platform-module"],"created_at":"2025-08-30T15:35:59.135Z","updated_at":"2026-01-31T02:15:15.397Z","avatar_url":"https://github.com/salrashid123.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## tpmcopy:  Transfer  RSA|ECC|AES|HMAC key to a remote Trusted Platform Module (TPM)\n\nUtility function you can use to securely copy an `RSA` or `ECC` or `AES` or `HMAC`  **KEY** from your laptop to a remote `Trusted Platform MOdule (TPM)`\n\nBasically, you can transfer a key from your laptop (`local`)  to `TPM-B` such that the key cannot get decrypted or exposed outside of `TPM-B`.  \n\nThe key you transfer will not get exposed into user space but can be used to sign/encrypt/decrypt/hmac while always existing _inside_ the destination `TPM`.\n\nFurthermore, you can place TPM based conditions on the transfer and the use of that key on the destination TPM\n\nFor examples, you can specify a passphrase or certain `PCR` values must be present on use for the destination key.\n\nAlternativley, if you just want some secret to get transferred securely only to get decrypted in userspace (eg securely transfer raw data as opposed to a TPM-embedded key), see \n\n* [Go-TPM-Wrapping - Go library and CLI utiity for encrypting data using Trusted Platform Module (TPM)](https://github.com/salrashid123/go-tpm-wrapping)\n\n\n---\n\n* [Overview](#overview)\n* [Options](#options)\n* [References](#references)\n* [Build](#build)\n* [Usage CLI](#usage-cli)\n  - [RSA](#rsa)\n  - [ECC](#ecc)\n  - [AES](#aes)\n  - [HMAC](#hmac)\n  - [KeyedHash](#keyedhash)  \n* [Usage Library](#usage-library)\n* [Key Policies](#key-policies)\n  - [Skip Policy](#skippolicy)\n  - [Bound Key Policy](#bound-key-policy)\n  - [Password Policy](#password-policy)\n  - [PCR Policy](#pcr-policy)\n* [Key Parent](#key-parent)\n  - [Using EK Parent](#using-ek-parent)\n  - [Using H2 Parent](#using-h2-parent)\n  - [Using SRK Parent](#using-srk-parent)  \n* [TPM2_TOOLS Compatibility](#tpm2_tools-compatibility)\n* [Parent Persistent Handle](#parent-persistent-handle)\n* [Key persistent handle](#key-persistent-handle)\n* [Openssl Compatibility](#openssl-compatiblity)\n* [Session Encryption](#session-encryption)\n* [Key Formats](#key-formats)\n* [TPMPolicy Syntax PEM Encoding](#tpmpolicy-syntax-pem-encoding)\n* [Setup Software TPM](#setup-software-tpm)\n* [tpmcopy using tpm2_tools](#tpmcopy-using-tpm2_tools)\n\n---\n\n### Overview\n\nAt a high level, this utility basically performs [tpm2_duplicate](https://github.com/tpm2-software/tpm2-tools/blob/master/man/tpm2_duplicate.1.md) and involves several steps:\n\nIf you want to transfer an external `RSA|ECC|AES|HMAC` key _from_  a `local` system  to `TPM-B`, you will need to\n\n1. On `TPM-B`, extract the [Endorsement Public Key](https://trustedcomputinggroup.org/wp-content/uploads/EK-Credential-Profile-For-TPM-Family-2.0-Level-0-V2.5-R1.0_28March2022.pdf), the [H2 ECC SRK](https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html#name-parent) or the RSA|ECC Storage Root Key (`SRK`)\n   Copy the public key to the system from which you want to transfer the secret key (eg, local)\n\n2. On `local`, create the secret `RSA|ECC|AES|HMAC`\n\n3. On `local` use `TPM-B` public key to [duplicate](https://github.com/tpm2-software/tpm2-tools/blob/master/man/tpm2_duplicate.1.md) the secret key such that it can only get loaded -inside- `TPM-B`\n   The duplicate step will encrypt the external key such that only `TPM-B` can import it.\n   The encrypted key is saved as a file which you will need to copy to `TPM-B`\n\n4. On `TPM-B`  [import](https://github.com/tpm2-software/tpm2-tools/blob/master/man/tpm2_import.1.md) the duplicated key you  copied from `local`\n   The imported key is saved in TPM encoded PEM format for later use\n\n5. On `TPM-B`, use the imported key to sign,encrypt,decrypt,hmac\n\n\nIt is critical to note the key that is transferred carries specific TPM policies which must be fulfilled upon use.  \nThese policies ensure the key cannot get duplicated beyond the target TPM. Specifically, the keys carry:\n\n* PCR: `tpm2_policyor(tpm2_policypcr | tpm2_policyduplicateselect)`\n* Password: `tpm2_policyor(tpm2_policyauthvalue | tpm2_policyduplicateselct)`.\n\nFor more details, see the section below on [Bound Key Policy](#bound-key-policy)\n\nYou can skip binding to the policies using the `--skipPolicy` flag\n\nFurthermore, the `TPM-B` parent must be the Endorsement ECC/RSA key or the H2 Primary from Storage.  No other parent types are currently supported.  A TODO: maybe to supply the `name` of any parent directly to the local system vs deriving it from the public key for known types.\n\n---\n\n### Options\n\n#### Basic Options\n\n| Option | Description |\n|:------------|-------------|\n| **`-tpm-path`** | Path to the TPM device (default: `/dev/tpmrm0`) |\n| **`-mode`** | Operation mode: `publickey duplicate import` (default: ``) |\n| **`-help`** | print usage |\n\n#### PublicKey Options\n\n| Option | Description |\n|:------------|-------------|\n| **`-parentKeyType`** | type of the parent Key (`rsa ecc`) (default: \"rsa\") |\n\n#### Duplicate Options\n\n| Option | Description |\n|:------------|-------------|\n| **`-keyType`** | type of key to import/export (`rsa ecc aes hmac keyedhash`) (default: \"rsa\") |\n| **`-rsaScheme`** | rsa Key Scheme (`rsassa rsapss`) (default: \"rsassa\") |\n| **`-hashScheme`** | hash Scheme (`sha256 sha384 sha512`) (default: \"sha256\") |\n| **`-eccScheme`** | ecc Key Alg (`ecc256 ecc384 ecc521`) (default: \"ecc256\") |\n| **`-keySize`** | AES key size (`128 256`) (default: \"128\") |\n| **`-secret`** | File with secret to duplicate (rsa | ecc | hex encoded symmetric key or hmac pass) (default: `/tmp/key.pem`) |\n| **`-out`** | Output file  (default: `\"\"`) |\n| **`-in`** | Import file (default: `\"\"`) |\n| **`-pubout`** | Save the imported key as `TPM2B_PUBLIC` (default: `\"`) |\n| **`-privout`** | Save the imported private as , `TPM2B_PRIVATE` (default: `\"`) |\n| **`-parent`** | parent to to encode the key parent against or load. |\n| **`-keyName`** | description of the key to annotate (default: \"\") |\n| **`-tpmPublicKeyFile`** | File to write the public key to  (default: ` /tmp/public.pem`) |\n\n#### TPM Options\n\n| Option | Description |\n|:------------|-------------|\n| **`-pcrValues`** | comma separated list of current pcr values to bind the key to (default: \"\") |\n| **`-persistentHandle`** | persistentHandle to save the key to (default `0x81008001` owner) |\n| **`-password`** | passphrase for the TPM key (default: \"\") |\n| **`-skipPolicy`** | skip binding the key to any policy |\n| **`-ownerpw`** | passphrase for the TPM owner (default: \"\") |\n| **`-tpm-session-encrypt-with-name`** | \"hex encoded TPM object 'name' to use with an encrypted session\" |\n\n\u003e\u003e This repo is not supported by Google\n\n---\n\n### References\n\n* [tpm2 key utility](https://github.com/salrashid123/tpm2genkey)\n* [Sign, Verify and decode using Google Cloud vTPM Attestation Key and Certificate](https://github.com/salrashid123/gcp-vtpm-ek-ak)\n* [TPM based Google Cloud Credential Access Token](https://github.com/salrashid123/oauth2)\n* [golang-jwt for Trusted Platform Module (TPM)](https://github.com/salrashid123/golang-jwt-tpm)\n* [TPM Credential Source for Google Cloud SDK](https://github.com/salrashid123/gcp-adc-tpm)\n* [go-tpm-tools: Transferring RSA and Symmetric keys with GCP vTPMs](https://github.com/salrashid123/gcp_tpm_sealed_keys)\n\n---\n\n## Build\n\nYou can use the binary in the [Releases](https://github.com/salrashid123/tpmcopy/releases) page as a standalone cli or load as a library or just build: \n\n```bash\ngo build -o tpmcopy cmd/main.go\n```\n\n## Usage CLI\n\nTo tranfer an `RSA` key from `local` to `TPM-B`\n\nYou'll first need the endorsement public key or the H2 parent from `TPM-B`.  You can get that either from TPM-B directly using `tpmcopy` or with a utility like `tpm2_tools`:\n\nFor the Endorsement Public:\n\n```bash\ntpm2_createek -c primaryB.ctx -G rsa -u ekB.pub -Q\ntpm2_readpublic -c primaryB.ctx -o ekpubB.pem -f PEM -Q\n```\n\nNote, if you have the EKCertificate, you can easily extract the ekPub\n\n```bash\ntpm2_getekcertificate -X -o ECcert.bin\nopenssl x509 -in ECcert.bin -inform DER -noout -text\nopenssl x509 -pubkey -noout -in ECcert.bin  -inform DER \n```\n\nIf you wanted to use the `H2` Parent instead of the EK, you need to do that on `TPM-B` itself:\n\n```bash\nprintf '\\x00\\x00' \u003e unique.dat\ntpm2_createprimary -C o -G ecc  -g sha256 \\\n     -c primary.ctx \\\n     -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\ntpm2_readpublic -c primary.ctx -o h2Public.pem -f PEM -n primary.name \n```\n\nIf you want the RSA or ECC Storage Root Key (SRK)\n\n```bash\ntpm2_createprimary -C o -G rsa  -g sha256  -c primary.ctx\ntpm2_readpublic -c primary.ctx -o rsa_srk.pem -f PEM\n```\n\n### RSA\n\nTo transfer an RSASSA key\n\n```bash\n### Local\nopenssl genpkey -algorithm rsa -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 -out /tmp/key_rsa.pem\n\n### TPM-B\nexport TPMB=\"/dev/tpmrm0\"  # TPMB=\"127.0.0.1:2321\"\ntpmcopy --mode publickey --parentKeyType=rsa_ek -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n\n###  copy public.pem to Local\n\n### local\ntpmcopy --mode duplicate --keyType=rsa --secret=/tmp/key_rsa.pem --rsaScheme=rsassa \\\n --hashScheme=sha256 --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\n###  copy /tmp/out.json to TPM-B\n\n### TPM-B\ntpmcopy --mode import --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem  --tpm-path=$TPMB\n\n### test\ncd example/\ngo run rsa/password/main.go --pemFile=/tmp/tpmkey.pem  --password=bar --tpm-path=$TPMB\n```\n\n### ECC\n\nTo transfer an `ECC-P256` key\n\n```bash\n### Local\nopenssl genpkey -algorithm ec -pkeyopt  ec_paramgen_curve:P-256  -out /tmp/key_ecc.pem\n\n### TPM-B\nexport TPMB=\"/dev/tpmrm0\"\n\ntpmcopy --mode publickey --parentKeyType=rsa_ek -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n###  copy public.pem to Local\n\n## Password\ntpmcopy --mode duplicate --keyType=ecc --secret=/tmp/key_ecc.pem --eccScheme=ecc256 --hashScheme=sha256 \\\n   --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\n###  copy /tmp/out.json to TPM-B\n\n### TPM-B\ntpmcopy --mode import --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem  --tpm-path=$TPMB\n\n### test\ncd example/\ngo run ecc/password/main.go --pemFile=/tmp/tpmkey.pem --password=bar --tpm-path=$TPMB\n```\n\n### AES\n\nTo transfer `AES-128 CFB`\n\n```bash\n### Local\necho -n \"46be0927a4f86577f17ce6d10bc6aa61\" \u003e /tmp/aes.key\n\n### TPM-B\nexport TPMB=\"/dev/tpmrm0\"\n\ntpmcopy --mode publickey --parentKeyType=rsa_ek -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n\n###  copy  public.pem to local\n\n### Local\ntpmcopy --mode duplicate --keyType=aes --aesScheme=cfb --keySize=128 --secret=/tmp/aes.key \\\n   --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\n###  copy /tmp/out.json to TPM-B\n\n### TPM-B\ntpmcopy --mode import --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem  --tpm-path=$TPMB\n\n### test\ncd example/\ngo run aes/password/main.go --pemFile=/tmp/tpmkey.pem  --password=bar --tpm-path=$TPMB\n```\n\n### HMAC\n\nTo transfer an `HMAC 256` key,\n\n```bash\n### Local\necho -n \"change this password to a secret\" \u003e /tmp/hmac_256.key\n\n### TPM-B\nexport TPMB=\"/dev/tpmrm0\"\n\ntpmcopy --mode publickey --parentKeyType=rsa_ek -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n###  copy public.pem to Local\n\n### loal\ntpmcopy --mode duplicate --keyType=hmac --hashScheme=sha256 --secret=/tmp/hmac_256.key \\\n   --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\n###  copy /tmp/out.json to TPM-B\n\n### TPM-B\ntpmcopy --mode import --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem  --tpm-path=$TPMB\n\n### test\ncd example/\ngo run hmac/password/main.go --pemFile=/tmp/tpmkey.pem --password=bar --tpm-path=$TPMB\n```\n\n### KeyedHash\n\nTo transfer an arbitrary secret to unseal remotely (eg a`KeyedHash`) run the following. \n\nIn other words, The secret you seal is unsealed into userspace on the remote system.\n\nNote that if all you want to do is to transfer a secret, you can also use the standalone tool here which specificly only coverst this:\n\n* [go-tpm-wrapping:  AEAD encryption using Trusted Platform Module (TPM)](https://github.com/salrashid123/go-tpm-wrapping)\n\nanyway,\n\n```bash\n### Local\necho -n \"mysecretdata\" \u003e /tmp/keyed_hash.key\n\n### TPM-B\nexport TPMB=\"/dev/tpmrm0\"\n\ntpmcopy --mode publickey --parentKeyType=rsa_ek -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n###  copy public.pem to Local\n\n### loal\ntpmcopy --mode duplicate --keyType=keyedhash --secret=/tmp/keyed_hash.key \\\n   --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\n###  copy /tmp/out.json to TPM-B\n\n### TPM-B\ntpmcopy --mode import --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem  --tpm-path=$TPMB\n\n### test\ncd example/\ngo run keyedhash/main.go --pemFile=/tmp/tpmkey.pem --password=bar --tpm-path=$TPMB\n# prints \"mysecretdata\"\n```\n\n---\n\n## Usage Library\n\nYou can also use this utility in go directly.  For an example of using as a library, see the testcases or the `example/direct` folder which creates a public key, then duplicates an HMAC key and finally import it into a destination TPM\n\nBy default the example uses a software TPM:\n\n```bash\n### get public key\n\n$ go run direct/public/main.go -tpmPublicKeyFile /tmp/public.pem -tpm-path \"127.0.0.1:2321\"\n\n$ cat /tmp/public.pem \n-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAne5iFdkj4QETbjUnWcOl\n+wQl6s9tBR2bSOp3gRUCn1noG7E62U5T3jCP9k0883rWeUh6fTICTzxhoPRIlm/R\nz0vFnKOm51VYAgT/XwhirLTqaskvS76B9OXGRt+9BVo0RkbzV8fhYzd2kGQPGdj5\nncRSqF/wzLEnfdv5tZziPmdtHQXvlGdVOEIP3Zz2VPi36DP3IW5wnxohrTIB9R/o\nm+1jdG2CRn7rkv2ZRvBKP9umNttG3wFM4qn2Pn+mBZ9rfxPCeZULC/EMu2lvG/+q\nlBSUzXVDECes2SdamtwvA2o0Wnfw4SunIY2ehT+J8jq7c/4mMHus8amCBs1tgcDA\nbwIDAQAB\n-----END PUBLIC KEY-----\n\n\necho -n \"change this password to a secret\" \u003e /tmp/hmac_256.key\n\n\n### duplicate\n\n$ go run direct/duplicate/main.go  -parentKeyType rsa_ek \\\n    -secret /tmp/hmac_256.key -tpmPublicKeyFile /tmp/public.pem \n\n\n$ cat /tmp/out.json | jq '.'\n{\n  \"version\": 1,\n  \"type\": \"HMAC\",\n  \"parentKeyType\": \"EndorsementRSA\",\n  \"key\": \"-----BEGIN TSS2 PRIVATE KEY-----\\nMIIB4QYGZ4EFCgEEoAMBAf+iggEGBIIBAgEAlXOL+W9RnYQFb3zoatVISsgZnMJS\\nwBKtSKwHMh9vBCvIGl69puX9Od4JGBZyi4uUf48Cjci+CRBEKX3ijjC5RWVnPpLt\\nCndMK3jNxoGQK3hoIzDvfHitVzEHcOa151Wg8WKq2uAOJoDVSEgPf7OqPYWnCiQE\\nbMdogZhZWPM6BYbUOF0dsC96kEd1Bj6AXUNKa5sD8AgPWJAPhujQyaiuhybCwAjN\\nzVOi04VA5bGcPr4DOpsQ7dWFPcRYtpkQQ7tMllJaMDouAeibVOE2zDd30aklolsc\\nb5/hroxpSTQk317DakuqmAAinb6+QGcStNqhUl1i2xL9kJQpEulM7HBMoQIEQAAB\\nQARSAFAACAALAAQAAAAgOY9wqZE2tqP3VTLztEEjQI8CmVJpp/aP2wFpaT1zA2AA\\nBQALACAL1ozkZPJRncVrwrLS3XqEQsHUR4Nw/ujnWE0HbfPrrwRuAGwAIDlUgijx\\nH4z+Kh1XWChiuswtgZkpdGZPbdAAVy2g7bsiokFY/CDMyzawCGyR6THxsn6FH/Aj\\nXiGwMuOm/jJsnC2vEwAb6pZ8bU/M+4lhQteR4ZfaCMlZvKS7Ka0tMyurlPjvG9CH\\nV8yP6/E=\\n-----END TSS2 PRIVATE KEY-----\\n\",\n  \"parentName\": \"000b8b6e4856595f2a27e663f7b727cfd9ae6f4ab085d8548f785b7ae8f11a107c06\"\n}\n\n\n### import\n$ go run direct/import/main.go  -in /tmp/out.json \\\n   -out /tmp/key.pem -tpm-path \"127.0.0.1:2321\"\n\n\n$ cat /tmp/key.pem \n-----BEGIN TSS2 PRIVATE KEY-----\nMIIBCwYGZ4EFCgEDoAMBAf8CBQCAAAABBFIAUAAIAAsABAAAACA5j3CpkTa2o/dV\nMvO0QSNAjwKZUmmn9o/bAWlpPXMDYAAFAAsAIE1UrKKNAGtyjMUXvFb4/xdC8CaE\n/tlocqTCOiSjORZ6BIGgAJ4AIIH39gnyjK0B/SM8WzscKpgzvWXD92h+wBoM7ha1\nYrWVABChCu4bQTtNOSPmYD4uX3CjNFc5BCr2vgRngTUdz74dCY3CZNCvRU9/VYAq\n++q8lVZP1nHBZxK0m2vllJJHO56HnFUCcJ5hZKCaNbyUbWZ4LJi/9WoaaRtFONIE\n5APNOKtWvcb/s9rqXkfStVNTXF56/AE0/HoFegzHbA==\n-----END TSS2 PRIVATE KEY-----\n\n\n### use the key to run hmac\n$ go run hmac/password/main.go --pemFile=/tmp/key.pem -tpm-path \"127.0.0.1:2321\"\n\n2025/11/24 22:27:38 Hmac: 7c50506d993b4a10e5ae6b33ca951bf2b8c8ac399e0a34026bb0ac469bea3de2\n```\n\n## Key Policies\n\n### SkipPolicy\n\nTo transfer an key which is **NOT** bound by a policy, set `--skipPolicy` parameter on duplicate\n\n```bash\n### Local\nopenssl genpkey -algorithm rsa -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 -out /tmp/key_rsa.pem\n\n### TPM-B\nexport TPMB=\"/dev/tpmrm0\"  # TPMB=\"127.0.0.1:2321\"\ntpmcopy --mode publickey --parentKeyType=rsa_ek -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n\n###  copy public.pem to Local\n\n### local\ntpmcopy --mode duplicate --keyType=rsa --secret=/tmp/key_rsa.pem --rsaScheme=rsassa --skipPolicy \\\n --hashScheme=sha256 -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\n###  copy /tmp/out.json to TPM-B\n\n### TPM-B\ntpmcopy --mode import --parentKeyType=rsa_ek \\\n  --in=/tmp/out.json --out=/tmp/tpmkey.pem \\\n  --pubout=/tmp/pub.dat --privout=/tmp/priv.dat  --tpm-path=$TPMB\n\n### test\ncd example/\ngo run rsa/skipPolicy/main.go --pemFile=/tmp/tpmkey.pem  --tpm-path=$TPMB\n\n### with tpm2_tools\ntpm2_createek -c ek.ctx -G rsa -u ek.pub\ntpm2 startauthsession --session session.ctx --policy-session\ntpm2 policysecret --session session.ctx --object-context endorsement\ntpm2_load -C ek.ctx -c key.ctx -u /tmp/pub.dat -r /tmp/priv.dat --auth session:session.ctx\necho -n \"foo\" \u003e /tmp/file.txt\ntpm2_sign -c key.ctx -g sha256  -f plain  -o sig.rss  /tmp/file.txt\n```\n\n### Bound Key Policy\n\nEach key that is exported to `TPM-B` is bound using TPM Policies which ensure the key cannot be duplicated further.\n\nThe specific base policy applied is [PolicyDuplicateSelect](https://github.com/tpm2-software/tpm2-tools/blob/master/man/tpm2_policyduplicationselect.1.md) which ensures the key can only exist on the target TPM and cannot get exported further.  For more information, see [Transfer TPM based key using PCR policy](https://gist.github.com/salrashid123/a61e09684c5d59440834d91241627458)\n\nFurthermore, they key will be bound using [tpm2_policyauthvalue](https://github.com/tpm2-software/tpm2-tools/blob/master/man/tpm2_policyauthvalue.1.md) for password and [tpm2_policypcr](https://github.com/tpm2-software/tpm2-tools/blob/master/man/tpm2_policypcr.1.md) for PCR.\n\nSince the key is always bound via policy, the [UserWithAuth](https://trustedcomputinggroup.org/wp-content/uploads/TPM-2p0-Keys-for-Device-Identity-and-Attestation_v1_r12_pub10082021.pdf) flag is always CLEAR (false)\n\n\"UserWithAuth: this attribute refers to key use policy and indicates that the object's authValue may be used to\nprovide the USER role authorizations for the object. If this attribute is CLEAR, then USER role authorizations may\nonly be provided by satisfying the object's authPolicy in a policy session. Refer to section 3.10 for more details.\"\n\nEssentially, when you use the duplicated key on the destination, you need to replay\n\n- Password: `tpm2_policyor(tpm2_policyauthvalue, tpm2_policyduplicateselect)` and specify the final `PolicySession` with the passphrase\n\n- PCR: `tpm2_policyor(tpm2_policypcr, tpm2_policyduplicateselect)`\n\nand when the parent is loaded, since by default its the RSA or ECC Endorsement, you need to use `tpm2_policysecret`\n\nTo help with construction of the policy session in go, you can use the utility functions here:\n\n- `Password`\n\n```golang\nimport (\n\ttpmcopy \"github.com/salrashid123/tpmcopy\"\n)\n\t// for password and with the parent name as primaryKey.Name:\n\ttc, err := tpmcopy.NewPolicyAuthValueAndDuplicateSelectSession(rwr, []byte(*password), primaryKey.Name, primaryKey.ObjectHandle)\n\tor_sess, or_cleanup, err := tc.GetSession()\n\tdefer or_cleanup()\n```\n\n- `PCR`\n\n```golang\nimport (\n\ttpmcopy \"github.com/salrashid123/tpmcopy\"\n)\n// for pcr's bound to bank 23 and with the parent name as primaryKey.Name:\n\tse, err := tpmcopy.NewPCRAndDuplicateSelectSession(rwr, []tpm2.TPMSPCRSelection{\n\t\t{\n\t\t\tHash:      tpm2.TPMAlgSHA256,\n\t\t\tPCRSelect: tpm2.PCClientCompatible.PCRs(uint(23)),\n\t\t},\n\t}, nil, primaryKey.Name, primaryKey.ObjectHandle)\n\tor_sess, or_cleanup, err := se.GetSession()\n\n\tdefer or_cleanup()\n```\n\nFor python, you will need to implement both policies as shown [here](https://github.com/salrashid123/cloud_auth_tpm?tab=readme-ov-file#policyauthvalue-and-policyduplicateselect)\n\n\n### Password Policy\n\nIf you want to bind the key to a passphrase\n\n```bash\n### local, generate RSA-SSA key\nopenssl genpkey -algorithm rsa -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 -out /tmp/key_rsa.pem\n\n### TPM-B\nexport TPMB=\"/dev/tpmrm0\"\n\ntpmcopy --mode publickey --parentKeyType=rsa_ek -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n\n# Alternatively, you can use `tpm2_tools`:\n# tpm2_createek -c /tmp/ek.ctx -G rsa -u /tmp/ek.pub\n# tpm2_readpublic -c /tmp/ek.ctx -o /tmp/public.pem -f PEM -n /tmp/ek.name \n# ## or extract the ekcert x509 \n# tpm2_getekcertificate -X -o EKCert.bin\n# openssl x509 -in EKCert.bin -inform DER -noout -text\n\n# copy `public.pem` to `local`\n\n### local\ntpmcopy --mode duplicate  --secret=/tmp/key_rsa.pem --keyType=rsa \\\n   --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\n# copy `/tmp/out.json` to `TPM-B`\n\n## TPM-B\ntpmcopy --mode import --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem  --tpm-path=$TPMB\n\ncd example/\ngo run rsa/password/main.go --pemFile=/tmp/tpmkey.pem  --password=bar --tpm-path=$TPMB\n```\n\n### PCR Policy\n\nIf you wanted to use a PCR policy like one that enforces that to use the key `TPM-B` must have `pcr 23=f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b`\n\n```bash\n## TPM-B\ntpmcopy --mode publickey --parentKeyType=rsa_ek -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n### copy `public.pem` to `Local`\n\n$ tpm2_flushcontext -t \u0026\u0026  tpm2_flushcontext -s  \u0026\u0026  tpm2_flushcontext -l\n\n$ tpm2_pcrread sha256:23\n  sha256:\n    23: 0x0000000000000000000000000000000000000000000000000000000000000000\n\n$ tpm2_pcrextend 23:sha256=0x0000000000000000000000000000000000000000000000000000000000000000\n\n$ tpm2_pcrread sha256:23\n  sha256:\n    23: 0xF5A5FD42D16A20302798EF6ED309979B43003D2320D9F0E8EA9831A92759FB4B\n\n\n### local\ntpmcopy --mode duplicate --keyType=rsa \\\n   --secret=/tmp/key_rsa.pem  --pcrValues=23:f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b \\\n   -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\n# copy `/tmp/out.json` to `TPM-B`\n\ntpmcopy --mode import --in=/tmp/out.json --out=/tmp/tpmkey.pem --tpm-path=$TPMB\n\n### test\ncd example\n### sign directly\ngo run rsa/pcr/main.go --pemFile=/tmp/tpmkey.pem --tpm-path=$TPMB\n### using crypto.Signer\ngo run rsa/signer_pcr/main.go --pemFile=/tmp/tpmkey.pem --tpm-path=$TPMB\n```\n\n## Key Parent\n\n### Using EK Parent\n\nThe examples above all use `RSAEK` parent, if you want to generate and use an EK ECC parent\n\n```bash\ntpmcopy --mode publickey --parentKeyType=ecc_ek \\\n   -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n\ntpmcopy --mode duplicate  --secret=/tmp/key_rsa.pem \\\n   --keyType=rsa --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json \n\ntpmcopy --mode import --parentKeyType=ecc_ek \\\n   --in=/tmp/out.json --out=/tmp/tpmkey.pem  --tpm-path=$TPMB\n\ncd example/\ngo run rsa/password/main.go --pemFile=/tmp/tpmkey.pem \\\n   --password=bar --parentKeyType=ecc_ek --tpm-path=$TPMB\n```\n\n### Using H2 Parent\n\nThe examples above all use EK RSA/ECC parent, if you want to use the [H2 profile](https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html#name-parent)\n\n```bash\ntpmcopy --mode publickey --parentKeyType=h2 \\\n   -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n\ntpmcopy --mode duplicate --parentKeyType=h2 --secret=/tmp/key_rsa.pem \\\n   --keyType=rsa --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json \n\ntpmcopy --mode import --parentKeyType=h2  \\\n   --in=/tmp/out.json --out=/tmp/tpmkey.pem --pubout=/tmp/pub.dat --privout=/tmp/priv.dat \\\n    --tpm-path=$TPMB\n\ncd example/\ngo run rsa/persistent_h2_parent/main.go --pemFile=/tmp/tpmkey.pem \\\n   --password=bar  --tpm-path=$TPMB\n```\n\n### Using SRK Parent\n\nIf you want to use the storage root key as the parent, see\n\n```bash\n### RSA_SRK\nprintf '\\x00\\x01' \u003e ud.1\ndd if=/dev/zero bs=256 count=1 of=ud.2\ncat ud.1 ud.2 \u003e unique.dat\n\ntpm2_createprimary -C o  -u unique.dat \\\n   -G rsa2048  -g sha256  -c primary.ctx --attributes=\"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -Q\ntpm2_readpublic -c primary.ctx -o rsa_srk.pem -f PEM\ntpm2_flushcontext -t\n\n## or\ngo run cmd/main.go --mode publickey --parentKeyType=rsa_srk -tpmPublicKeyFile=/tmp/rsa_srk.pem --tpm-path=$TPMB\n\n# echo -n \"46be0927a4f86577f17ce6d10bc6aa61\" \u003e /tmp/aes.key\ngo run cmd/main.go --mode duplicate --parentKeyType=rsa_srk --keyType=aes --aesScheme=cfb --keySize=128 --secret=/tmp/aes.key \\\n   --password=bar -tpmPublicKeyFile=/tmp/rsa_srk.pem -out=/tmp/out.json\n\n###  copy /tmp/out.json to TPM-B\n### TPM-B\ngo run cmd/main.go --mode import --parentKeyType=rsa_srk --in=/tmp/out.json --out=/tmp/tpmkey.pem  --tpm-path=$TPMB\n\n### test\ncd example/\ngo run aes/srk/main.go --pemFile=/tmp/tpmkey.pem  --password=bar --tpm-path=$TPMB\n```\n\nAlternatively, if you want to `SkipPolicy`\n\n```bash\ngo run cmd/main.go --mode duplicate --parentKeyType=rsa_srk --skipPolicy --keyType=aes --aesScheme=cfb --keySize=128 --secret=/tmp/aes.key \\\n   --password=bar -tpmPublicKeyFile=/tmp/rsa_srk.pem -out=/tmp/out.json\n\n###  copy /tmp/out.json to TPM-B\n### TPM-B\ngo run cmd/main.go --mode import --parentKeyType=rsa_srk --in=/tmp/out.json --out=/tmp/tpmkey.pem  --tpm-path=$TPMB\n\n### test\ncd example/\ngo run aes/skipPolicy/main.go --pemFile=/tmp/tpmkey.pem  --password=bar --tpm-path=$TPMB\n```\n\n## TPM2_TOOLS compatibility\n\nIf you wanted to use `tpm2_tools` on the key imported to `TPM-B`, then use the `--pubout=` and `--privout=` parameters when importing.\n\nWhat that'll do is save the key as `[TPM2B_PUBLIC, TPM2B_PRIVATE]`\n\nFor example, the follwoing will import the password or pcr policy encoded files and use tpm2_tools to perform further operations.\n\non `TPM-B`, save the ek (and optionallhy as a persistent handle)\n\n```bash\ncd /tmp/\ntpm2_createek -c ek.ctx -G rsa -u ek.pub\ntpm2_readpublic -c ek.ctx -o ek.pem -f PEM -n ek.name\n```\n\ntransfer the key using `ek.pem` from local then when running `import` on TPM-B, specify the output pub/private part\n\n```bash\ntpmcopy --mode import --parentKeyType=rsa_ek \\\n   --pubout=/tmp/pub.dat --privout=/tmp/priv.dat --in=/tmp/out.json \\\n   --out=/tmp/tpmkey.pem --tpm-path=$TPMB\n```\n\nIf the key had a policy password:\n\n```bash\n### load\ncd /tmp/\ntpm2 flushcontext -t\ntpm2 startauthsession --session session.ctx --policy-session\ntpm2 policysecret --session session.ctx --object-context endorsement\ntpm2_load -C ek.ctx -c key.ctx -u pub.dat -r priv.dat --auth session:session.ctx\n\n## regenerate the full policy\ntpm2_startauthsession -S sessionA.dat --policy-session\ntpm2_policyduplicationselect -S sessionA.dat  -N ek.name -L policyA_dupselect.dat \ntpm2_flushcontext sessionA.dat\nrm sessionA.dat\n\ntpm2_startauthsession -S sessionA.dat --policy-session\ntpm2_policyauthvalue -S sessionA.dat  -L policyA_auth.dat \n\necho -n foo \u003e /tmp/file.txt\ntpm2_policyor -S sessionA.dat -L policyA_or.dat sha256:policyA_auth.dat,policyA_dupselect.dat \ntpm2_sign -c key.ctx -g sha256  -f plain  -p\"session:sessionA.dat+bar\"  -o sig.rss  /tmp/file.txt\n```\n\nIf the key had a pcr policy\n\n```bash\n### load\ncd /tmp/\ntpm2 flushcontext -t\ntpm2 startauthsession --session session.ctx --policy-session\ntpm2 policysecret --session session.ctx --object-context endorsement\ntpm2_load -C ek.ctx -c key.ctx -u pub.dat -r priv.dat --auth session:session.ctx\n\n## regenerate the full policy\ntpm2_startauthsession -S sessionA.dat --policy-session\ntpm2_policyduplicationselect -S sessionA.dat  -N ek.name -L policyA_dupselect.dat \ntpm2_flushcontext sessionA.dat\nrm sessionA.dat\n\ntpm2_startauthsession -S sessionA.dat --policy-session\ntpm2_policypcr -S sessionA.dat -l \"sha256:23\" -f pcr23_valA.bin -L policyA_pcr.dat \ntpm2_policyor -S sessionA.dat -L policyA_or.dat sha256:policyA_pcr.dat,policyA_dupselect.dat \n\n### test sign\necho -n foo \u003e/tmp/file.txt\ntpm2_sign -c key.ctx -g sha256 -f plain  -o signB.raw /tmp/file.txt -p \"session:sessionA.dat\" \nrm sessionA.dat\n```\n\nFor  an `H2`  primary, the steps to sign with password would be\n\n```bash\n# ## create H2 Template\nprintf '\\x00\\x00' \u003e /tmp/unique.dat\ntpm2_createprimary -C o -G ecc  -g sha256 \\\n     -c primary.ctx \\\n     -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u /tmp/unique.dat\ntpm2_readpublic -c /tmp/primary.ctx -o /tmp/public.pem -f PEM -n /tmp/primary.name \n\ntpm2 flushcontext -t\ntpm2_load -C /tmp/primary.ctx -c /tmp/key.ctx -u /tmp/pub.dat -r /tmp/priv.dat \n\n## regenerate the full policy\ntpm2_startauthsession -S sessionA.dat --policy-session\ntpm2_policyduplicationselect -S sessionA.dat  -N/tmp/primary.name  -L policyA_dupselect.dat \ntpm2_flushcontext sessionA.dat\nrm sessionA.dat\n\ntpm2_startauthsession -S sessionA.dat --policy-session\ntpm2_policyauthvalue -S sessionA.dat  -L policyA_auth.dat \n\necho -n \"foo\" \u003e /tmp/file.txt\ntpm2_policyor -S sessionA.dat -L policyA_or.dat sha256:policyA_auth.dat,policyA_dupselect.dat \ntpm2_sign -c key.ctx -g sha256  -f plain  -p\"session:sessionA.dat+bar\"  -o sig.rss  /tmp/file.txt\n```\n\n## Parent persistent handle\n\nIf you want to encode the PEM key with a preset persistent handle parent, then during import specify the `-parentpersistentHandle=` flag:\n\nFor example, the following will create a key on `TPM-B` and persist it to `0x81008001`.  \n\nFrom there, you can import the key and and encode the parent into the PEM file directly\n\n```bash\n## TPM-B\ntpm2_getcap handles-persistent\ntpm2_evictcontrol -C o -c 0x81008001\ntpm2_createek -c /tmp/ek.ctx -G rsa -u /tmp/ek.pub \ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\ntpm2_evictcontrol -c /tmp/ek.ctx 0x81008001\ntpm2_readpublic -c /tmp/ek.ctx -o /tmp/public.pem -f PEM -n ek.name -Q\ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\n## Local\ntpmcopy --mode duplicate  --secret=/tmp/key_rsa.pem --keyType=rsa \\\n    --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\n## TPM-B\ntpmcopy --mode import --parentKeyType=rsa_ek --password=bar \\\n   --in=/tmp/out.json  --pubout=/tmp/pub.dat --privout=/tmp/priv.dat  \\\n   --out=/tmp/tpmkey.pem --parentpersistentHandle=0x81008001  --tpm-path=$TPMB\n\n$ openssl asn1parse -in  /tmp/tpmkey.pem\n\n    0:d=0  hl=4 l= 565 cons: SEQUENCE          \n    4:d=1  hl=2 l=   6 prim: OBJECT            :2.23.133.10.1.3\n   12:d=1  hl=2 l=   3 cons: cont [ 0 ]        \n   14:d=2  hl=2 l=   1 prim: BOOLEAN           :255\n   17:d=1  hl=2 l=   5 prim: INTEGER           :81008001   \u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\u003c\n   24:d=1  hl=4 l= 314 prim: OCTET STRING      [HEX DUMP]:01380001000B0004000000207487CF644F9B7D548C7CEF7D...\n  342:d=1  hl=3 l= 224 prim: OCTET STRING      [HEX DUMP]:00DE0020742AC11B...\n```\n\nthen run the following sample:  note that the \"parent\" is read in from the PEM file and initialized automatically\n\n```bash\ncd example/\ngo run rsa/persistent_parent/main.go --pemFile=/tmp/tpmkey.pem  --password=bar --tpm-path=$TPMB\n```\n\n## Key persistent handle\n\nIf you want to persist the actual key into NV:\n\n```bash\n# tpm-b\ntpmcopy --mode publickey --parentKeyType=rsa_ek -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n\n# local\ntpmcopy --mode duplicate  \\\n   --secret=/tmp/key_rsa.pem --keyType=rsa \\\n    --password=bar -tpmPublicKeyFile=/tmp/public.pem \\\n     -out=/tmp/out.json \n\n# tpm-b\ntpmcopy --mode import \\\n   --pubout=/tmp/pub.dat --privout=/tmp/priv.dat --in=/tmp/out.json \\\n   --out=/tmp/tpmkey.pem --tpm-path=$TPMB\n\n### then load\ntpmcopy --mode evict \\\n    --persistentHandle=0x81008001 \\\n   --in=/tmp/tpmkey.pem --tpm-path=$TPMB\n\n## or using tpm2_tools:\n# tpm2_createek -c ek.ctx -G rsa -u ek.pub \n# tpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\n# tpm2 startauthsession --session session.ctx --policy-session\n# tpm2 policysecret --session session.ctx --object-context endorsement\n# tpm2_load -C ek.ctx -c key.ctx -u pub.dat -r priv.dat --auth session:session.ctx\n# tpm2_evictcontrol -c key.ctx 0x81008001\n\ngo run rsa/persistent_key/main.go --persistentHandle=0x81008001 --password=bar  --tpm-path=$TPMB\n```\n\n## Openssl compatiblity\n\nNote that while openssl does have a tpm2 provider, the default CLI does not support complex policy statements bound to keys.\n\nFor example, with openssl is limited to basic auth constructors as described [here]](https://github.com/tpm2-software/tpm2-openssl/blob/master/docs/keys.md) \n\nSince default keys transferred by this utility uses more complex policies, you can't easily really use openssl (but you can use `tpm2_tools`).\n\nIf you did not use the default policies by setting the `--skipPolicy` and the `h2` template, then some basic openssl operations are possible\n\n```bash\nexport TPM2TOOLS_TCTI=\"swtpm:port=2321\"\nexport TPM2OPENSSL_TCTI=\"swtpm:port=2321\"\n\nopenssl list --providers -provider tpm2\n   Providers:\n   tpm2\n      name: TPM 2.0 Provider\n      version: 1.3.0\n      status: active\n\ntpmcopy --mode publickey --parentKeyType=h2 \\\n   -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n\ntpmcopy --mode duplicate --parentKeyType=h2 --secret=/tmp/key_rsa.pem --skipPolicy \\\n   --keyType=rsa -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json \n\ntpmcopy --mode import --parentKeyType=h2  \\\n   --in=/tmp/out.json --out=/tmp/tpmkey.pem --pubout=/tmp/pub.dat --privout=/tmp/priv.dat \\\n    --tpm-path=$TPMB\n\n### assume tpmkey.pem is an rsa key with password using the H2 primary\nopenssl asn1parse -in  /tmp/tpmkey.pem\n\nopenssl rsa -provider tpm2 -provider default   -in /tmp/tpmkey.pem  -text\n\n## test signature\n\ncd example/\ngo run rsa/skipPolicy/main.go --pemFile=/tmp/tpmkey.pem  --tpm-path=$TPMB --parentKeyType=h2\n\necho -n \"foo\" \u003e/tmp/data.txt\nopenssl dgst -sha256 -binary -out /tmp/data.hash /tmp/data.txt\n\nopenssl  pkeyutl -provider tpm2 -provider default \\\n   -sign -inkey /tmp/tpmkey.pem   -in /tmp/data.hash -out /tmp/signature.sig\n```\n\n## Session Encryption\n\nEach operation uses [encrypted sessions](https://trustedcomputinggroup.org/wp-content/uploads/TCG_CPU_TPM_Bus_Protection_Guidance_Passive_Attack_Mitigation_8May23-3.pdf) by default and interrogates the TPM for the current EK directly.\n\nIf for whatever reason you want to specify the \"name\" of the EK to to use, set the `--tpm-session-encrypt-with-name=` parameter shown below\n\n```bash\n# for tpmB\ntpm2_createek -c /tmp/primaryB.ctx -G rsa  -Q\ntpm2_readpublic -c /tmp/primaryB.ctx -o /tmp/ekpubB.pem -n /tmp/ekpubBname.bin -f PEM -Q\nxxd -p -c 100 /tmp/ekpubBname.bin \n   000b47ab97fdda365cbb86a37548e38468f72e8baccc633cffc42402183679956608\n\n# Then use the hex value returned in the --tpm-session-encrypt-with-name= argument.\n   --tpm-session-encrypt-with-name=000b47ab97fdda365cbb86a37548e38468f72e8baccc633cffc42402183679956608\n```\n\n## Key Formats\n\nThis utility encodes the key to transfer as protobuf during the `Duplicate()` step\n\n```proto\nsyntax = \"proto3\";\n\npackage duplicatepb;\n\noption go_package = \"github.com/salrashid123/go-tpm-wrapping/tpmwrappb\";\n\nmessage Secret {\n  string name = 1;\n  int32 version = 2;\n  KeyType type = 3; \n  enum KeyType {\n    ECC = 0;\n    RSA = 1;\n    HMAC = 2;\n    AES = 3;\n    KEYEDHASH = 4;        \n  }\n  ParentKeyType parentKeyType = 4;\n  enum ParentKeyType {\n    EndoresementECC = 0;\n    EndorsementRSA = 1;\n    H2 = 2;\n    OwnerECC = 3;\n    OwnerRSA = 4;        \n  }  \n  repeated PCRS pcrs = 5;  \n  string key = 6;\n  string parentName = 7;\n}\n\nmessage PCRS {\n  int32 pcr = 1;\n  bytes value = 2;\n}\n```\n\nSo an output file may look like:\n\n```json\n{\n  \"version\": 1,\n  \"type\": \"RSA\",\n  \"parentKeyType\": \"EndorsementRSA\",\n  \"key\": \"-----BEGIN TSS2 PRIVATE KEY-----\\nMIIDowYGZ4EFCgEEoYGWMIGTMAqgBAICAWuhAgQAMDGgBAICAYihKQQnAAAAIgAL\\nTTWiK01Z+KGkuImOvdG/WUm/oz/Lcb2Z4Jhmyw1YOEsAMFKgBAICAXGhSgRIAAAA\\nAgAgj80haauSaU4MYz8at3KEK4JBu8ICiJgfx6we3cH92w4AIG4KC9eaWaph5FAK\\nm5HsPBnfHpV1KLWu/ngsdFGgGmuyooIBBgSCAQIBAMOl4GvDGXWAz2Z3W/NNwjd9\\n1dFnqKD4FMtm1TlVsptk1hVSdzZ6C0cut3u15LiekeJZwWmFpOyiuJr/lV3cIjKv\\naUlq+a3DjcvBPhcYC8Y20J+JFsLujekDOnrDzc6OrTvM8qoXMLJenYmwCAHtdN+0\\nH/5s5SeZpDsVCOZZWDfRJLh/F3oM5f5R1VRElyHrx7rbrduLgkqh5j7kCAnC+fet\\n1IpSSW55CiwecyHq7ewqqjH9pXLwrMu5DTxUr4OLiuQQD+JISFyLWZI8E06HqzMh\\nXT1vyU9J6aQ+hIUQdbFvh639+QyCj/SL3tdqW59/nHbwfxm8MeQxG9Sx0/fPiLkC\\nBEAAAUAEggE6ATgAAQALAAQAAAAgtzGhqUcZ8m14fqMMDjocDbzpInzeMioNYjn1\\nVKVXqI0AEAAUAAsIAAABAAEBAOopWu7BnpqZMH04VfA6o2SXtlrGHSMPUBducP26\\n+eTTPXy0Y4fHOw/qWyYsnzLCcySiZ1sM/vx1mUcQLeyf/u6y1FRPAdv1RX+Bzzvm\\nAwnSqyttFqOwfUnu1AFLh7MR/wwqgGL2iBTHuDbXPtzK2IrjqevTwnfLJke9dW4K\\nSWdxcEPxMz1mUdV0N4wgIw7NeDp3R8vRS+6MY9IgRiepuZjgOWkjRG50wCw60By1\\nujsOrvG6JIFxb2yXHFJ7XyY7r/cgkA0pWUeTKemNMSTPNyEpHlusKi166RwuFI9O\\nVI2aS/ME5dsNPJGGuuzwcTK59AZzgwYuNK2lMU2w4fLXGqcEgbEArwAgm/YdhGaF\\nigcO0yJEqphb9bitPf8ZJ7DbicHeOt6shx4hTyDG6hgT/RVwMjPN5wRgRZuZfcKR\\n0V67QDN9elXn0grU4vk3uDulNP+bePVPHmDE3dJ8kZUp4VYn167PFStPu7+r+okl\\nuOAKCjfy71yu6OG73epxdzIXvuTAjuY/zc1AKZqeSonTWHZq4R2whynIpSDFZ6Jh\\nehLs1g4RBZpyUQ1PItng8mHJl1Q10OY=\\n-----END TSS2 PRIVATE KEY-----\\n\",\n  \"parentName\": \"000b4d35a22b4d59f8a1a4b8898ebdd1bf5949bfa33fcb71bd99e09866cb0d58384b\"\n}\n```\n\nwhere the `parentName` is actually the duplicating parents 'name' on `TPM-B`:\n\n```bash\n$ xxd -p -c 100 /tmp/ek.name \n000bbc0c7f8b565f09e4614624fa6f46ece235c9904d47050e8a8dd466ac9b96d49b\n```\n\nAs mentioned, the `Import()` function saves the imported using in two ways:\n\n1.  `--out=` parameter saves the imported key as [ASN.1 Specification for TPM 2.0 Key Files](https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html) which is the format openssl (mostly) follows.  However, to use this you need to specify the parent as the endorsement RSA key and not the H2 tepmplate.\n\n2. `--pubout=` and `--privout=` parameters saves they key in raw formats which can be used with `tpm2_tools`\n\n---\n\n## TPMPolicy Syntax PEM Encoding\n\nIf you want to encode the policies into the PEM file based on the __draft__ [ASN.1 Specification for TPM 2.0 Key Files](https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html#name-key-policy-specification), then set `ENABLE_POLICY_SYNTAX` environment variable to any value during the duplicate and import steps.\n\nPlease note that it the specs are still draft and is incompatible with the PEM format used by openssl\n\nAnyway, the big advantage of this encoding is the PEM file describes the steps to generate the policy itself and execute them.\n\nFor example, see the link here on how to [manually generate](https://github.com/salrashid123/tpm2/tree/master/policy_gen) the policies and  use [policySyntax utility](https://github.com/salrashid123/tpm2genkey/tree/main?tab=readme-ov-file#policy-command-parameters).\n\nIn the following note that the same codebase will execute the both types of policies in `keyfile_policy/main.go`:\n\n- PolicyAuthValue\n\nFor auth value, the following will generate a key with the syntax variables already baked in\n```bash\nexport ENABLE_POLICY_SYNTAX=1\ntpmcopy --mode publickey --parentKeyType=rsa_ek \\\n    -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n\ntpmcopy --mode duplicate \\\n   --keyType=aes --secret=/tmp/aes.key  \\\n     --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json \n\ntpm2_evictcontrol -c 0x81008000\ntpmcopy  --mode import \\\n   --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey_auth.pem  --tpm-path=$TPMB\n\ntpm2_flushcontext -t \u0026\u0026  tpm2_flushcontext -s  \u0026\u0026  tpm2_flushcontext -l\n\ncd example/\ngo run keyfile_policy/main.go --pemFile=/tmp/tpmkey_auth.pem --tpm-path=$TPMB --password=bar\n```\n\n- PolicyPCR\n\n```bash\nexport ENABLE_POLICY_SYNTAX=1\ntpmcopy --mode publickey --parentKeyType=rsa_ek \\\n    -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n\ntpmcopy --mode duplicate --keyType=aes    --secret=/tmp/aes.key  \\\n     --pcrValues=23:f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b  \\\n      -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\ntpmcopy --mode import --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey_pcr.pem --tpm-path=$TPMB\n\ncd example/\ngo run keyfile_policy/main.go --pemFile=/tmp/tpmkey_pcr.pem --tpm-path=$TPMB\n```\n\nthe specific PEM files generated has the polices encode into it itself.\n\nNote that the command code for `PolicyDuplicateSelect=0x00000188`, `TPMCCPolicyOR=0x00000171`, `TPMCCPolicyPCR=0x0000017F`\n\nfor authvalue \n\n```bash\n$ openssl asn1parse -in  /tmp/tpmkey_auth.pem \n    0:d=0  hl=4 l= 406 cons: SEQUENCE          \n    4:d=1  hl=2 l=   6 prim: OBJECT            :2.23.133.10.1.3\n   12:d=1  hl=2 l=   3 cons: cont [ 0 ]        \n   14:d=2  hl=2 l=   1 prim: BOOLEAN           :255\n   17:d=1  hl=3 l= 150 cons: cont [ 1 ]        \n   20:d=2  hl=3 l= 147 cons: SEQUENCE          \n   23:d=3  hl=2 l=  10 cons: SEQUENCE          \n   25:d=4  hl=2 l=   4 cons: cont [ 0 ]        \n   27:d=5  hl=2 l=   2 prim: INTEGER           :016B\n   31:d=4  hl=2 l=   2 cons: cont [ 1 ]        \n   33:d=5  hl=2 l=   0 prim: OCTET STRING      \n   35:d=3  hl=2 l=  49 cons: SEQUENCE          \n   37:d=4  hl=2 l=   4 cons: cont [ 0 ]        \n   39:d=5  hl=2 l=   2 prim: INTEGER           :0188\n   43:d=4  hl=2 l=  41 cons: cont [ 1 ]        \n   45:d=5  hl=2 l=  39 prim: OCTET STRING      [HEX DUMP]:00000022000B75CE518FE809BFF11C7C3575FB50B943F9EFC3E4C3E0FA4AC3AD796D7DF66DE700\n   86:d=3  hl=2 l=  82 cons: SEQUENCE          \n   88:d=4  hl=2 l=   4 cons: cont [ 0 ]        \n   90:d=5  hl=2 l=   2 prim: INTEGER           :0171\n   94:d=4  hl=2 l=  74 cons: cont [ 1 ]        \n   96:d=5  hl=2 l=  72 prim: OCTET STRING      [HEX DUMP]:0000000200208FCD2169AB92694E0C633F1AB772842B8241BBC20288981FC7AC1EDDC1FDDB0E0020E6613C6F3F14B6A9C8613FA7D2766BAB170C6E477BB047C5E10928DA897FCB1D\n  170:d=1  hl=2 l=   5 prim: INTEGER           :81008000\n  177:d=1  hl=2 l=  84 prim: OCTET STRING      [HEX DUMP]:00520025000B000600000020B27A9BE905FD3C543969DF3965EA3B62F554DCB20681BC484E90FAF03FA6E04300060080004300206D1078F0CF8B17C99CD183C71D3E0F29F62FB655B97EC1135832EAFDDB795FF7\n  263:d=1  hl=3 l= 144 prim: OCTET STRING      [HEX DUMP]:008E0020F99928C2177F50253A7F8568EC7B14CB1A39C538B3CF4AC83A031257857355EE0010E7A442207E6488A97D046687B925135F5A4F579FA4E4120A2BC274B568DA75EAF2D24299EA17EF2B3132EF39BB64FB9CFF83E772B1FEF2916D0BB3283322B7A4EC809DB0F5229232C5D8EA4A858AADC17D8889A7327A589DFE9560C335D843C725CD21ACD441ED8ACA17\n```\n\nfor PCR:\n\n```bash\n$ openssl asn1parse -in  /tmp/tpmkey_pcr.pem \n    0:d=0  hl=4 l= 450 cons: SEQUENCE          \n    4:d=1  hl=2 l=   6 prim: OBJECT            :2.23.133.10.1.3\n   12:d=1  hl=2 l=   3 cons: cont [ 0 ]        \n   14:d=2  hl=2 l=   1 prim: BOOLEAN           :255\n   17:d=1  hl=3 l= 194 cons: cont [ 1 ]        \n   20:d=2  hl=3 l= 191 cons: SEQUENCE          \n   23:d=3  hl=2 l=  54 cons: SEQUENCE          \n   25:d=4  hl=2 l=   4 cons: cont [ 0 ]        \n   27:d=5  hl=2 l=   2 prim: INTEGER           :017F\n   31:d=4  hl=2 l=  46 cons: cont [ 1 ]        \n   33:d=5  hl=2 l=  44 prim: OCTET STRING      [HEX DUMP]:0020E2F61C3F71D1DEFD3FA999DFA36953755C690689799962B48BEBD836974E8CF900000001000B03000080\n   79:d=3  hl=2 l=  49 cons: SEQUENCE          \n   81:d=4  hl=2 l=   4 cons: cont [ 0 ]        \n   83:d=5  hl=2 l=   2 prim: INTEGER           :0188\n   87:d=4  hl=2 l=  41 cons: cont [ 1 ]        \n   89:d=5  hl=2 l=  39 prim: OCTET STRING      [HEX DUMP]:00000022000B75CE518FE809BFF11C7C3575FB50B943F9EFC3E4C3E0FA4AC3AD796D7DF66DE700\n  130:d=3  hl=2 l=  82 cons: SEQUENCE          \n  132:d=4  hl=2 l=   4 cons: cont [ 0 ]        \n  134:d=5  hl=2 l=   2 prim: INTEGER           :0171\n  138:d=4  hl=2 l=  74 cons: cont [ 1 ]        \n  140:d=5  hl=2 l=  72 prim: OCTET STRING      [HEX DUMP]:0000000200202094289099C2CB180F28F99C71C8D681123935F7330BDAE5AA1AE1E09F0FE5320020E6613C6F3F14B6A9C8613FA7D2766BAB170C6E477BB047C5E10928DA897FCB1D\n  214:d=1  hl=2 l=   5 prim: INTEGER           :81008000\n  221:d=1  hl=2 l=  84 prim: OCTET STRING      [HEX DUMP]:00520025000B000600000020114DE1F5BD4B2EC1AA51DE81CA4CEE5EB7B34FD338DCFB0D635F7F65DB56DBF80006008000430020237668CD3AF2827B9A590B32EAA8056226DB1C0D89000E403845AE13C4E35240\n  307:d=1  hl=3 l= 144 prim: OCTET STRING      [HEX DUMP]:008E002034CC17FD41CE5414923D8C75624E746276809068E34EF06A2DBBC933004A2E900010EEDBD95BE8D7746EF004BC0DA7CE289B3EEC0FCDC969ADD1D3DC4122FC79BF72F02D2DD9DE11171767FF3979ABA236BC8BF27914B682AFDA920802CD10297594E1A5094A9936AE6CAFE16DDCE1170E65F7A819B1310F8378641DCEF141E3592701D3D80CB35FDC16FB12\n```\n\n## Setup Software TPM\n\nIf you want to test locally with a [software TPM](https://github.com/stefanberger/swtpm)\n\n- Start `TPM-B`\n\n```bash\n## TPMB\nrm -rf /tmp/myvtpm \u0026\u0026 mkdir /tmp/myvtpm\n/usr/share/swtpm/swtpm-create-user-config-files\nswtpm_setup --tpmstate /tmp/myvtpm --tpm2 --create-ek-cert\nswtpm socket --tpmstate dir=/tmp/myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear --log level=2\n\n## in new window\nexport TPM2TOOLS_TCTI=\"swtpm:port=2321\"\nexport TPMB=\"127.0.0.1:2321\"\n\n$ tpm2_flushcontext -t \u0026\u0026  tpm2_flushcontext -s  \u0026\u0026  tpm2_flushcontext -l\n$ tpm2_pcrread sha256:23\n  sha256:\n    23: 0x0000000000000000000000000000000000000000000000000000000000000000\n$ tpm2_pcrextend 23:sha256=0x0000000000000000000000000000000000000000000000000000000000000000\n$ tpm2_pcrread sha256:23\n  sha256:\n    23: 0xF5A5FD42D16A20302798EF6ED309979B43003D2320D9F0E8EA9831A92759FB4B\n\n## export the ekPub\n### derive the RSA EK \ntpm2_createek -c /tmp/ek.ctx -G rsa -u /tmp/ek.pub \n\ntpm2_readpublic -c /tmp/ek.ctx -o /tmp/ek.pem -f PEM -n ek.name -Q\n\ntpm2_getekcertificate -X -o EKCert.bin\nopenssl x509 -in EKCert.bin -inform DER -noout -text\n```\n\nTo run all the examples:\n\n```bash\nexport TPMB=\"127.0.0.1:2321\"\nexport TPM2TOOLS_TCTI=\"swtpm:port=2321\"\n\n### TPM-B make sure the pcr value is 0xF5A5FD42D16A20302798EF6ED309979B43003D2320D9F0E8EA9831A92759FB4B\n### tpm2_pcrextend 23:sha256=0x0000000000000000000000000000000000000000000000000000000000000000\ntpm2_pcrread sha256:23\n\n### RSA\ntpmcopy --mode publickey --parentKeyType=rsa_ek -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\n\n# openssl genpkey -algorithm rsa -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 -out /tmp/key_rsa.pem\ntpmcopy --mode duplicate  --secret=/tmp/key_rsa.pem --keyType=rsa \\\n   --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\ntpmcopy --mode import --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem --tpm-path=$TPMB\n\ncd example/\ngo run rsa/password/main.go --pemFile=/tmp/tpmkey.pem  --password=bar --tpm-path=$TPMB\ncd ..\n\n### pcr\ntpmcopy --mode duplicate --keyType=rsa    --secret=/tmp/key_rsa.pem \\\n     --pcrValues=23:f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b  \\\n      -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\ntpmcopy --mode import --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem --tpm-path=$TPMB\n\ncd example/\ngo run rsa/pcr/main.go --pemFile=/tmp/tpmkey.pem --tpm-path=$TPMB\n\ngo run rsa/signer_pcr/main.go --pemFile=/tmp/tpmkey.pem --tpm-path=$TPMB\ncd ..\n\n### ECC\n# openssl genpkey -algorithm ec -pkeyopt  ec_paramgen_curve:P-256  -out /tmp/key_ecc.pem\ntpmcopy --mode duplicate --keyType=ecc --secret=/tmp/key_ecc.pem \\\n   --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\ntpmcopy --mode import --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem --tpm-path=$TPMB\n\ncd example/\ngo run ecc/password/main.go --pemFile=/tmp/tpmkey.pem --password=bar --tpm-path=$TPMB\ncd ..\n\n### AES\n# echo -n \"46be0927a4f86577f17ce6d10bc6aa61\" \u003e /tmp/aes.key\ntpmcopy --mode duplicate --keyType=aes --aesScheme=cfb --keySize=128 --secret=/tmp/aes.key  \\\n  --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\ntpmcopy --mode import --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem  --password=bar --tpm-path=$TPMB\n\ncd example/\ngo run aes/password/main.go --pemFile=/tmp/tpmkey.pem --password=bar --tpm-path=$TPMB\ncd ..\n\n### HMAC\n# echo -n \"change this password to a secret\" \u003e /tmp/hmac.key\ntpmcopy --mode duplicate --keyType=hmac --hashScheme=sha256 --secret=/tmp/hmac.key \\\n   --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\ntpmcopy --mode import  --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem   --tpm-path=$TPMB\n\ncd example/\ngo run hmac/password/main.go --pemFile=/tmp/tpmkey.pem  --password=bar --tpm-path=$TPMB\ncd ..\n\n### KeyedHash\n# echo -n \"change this password to a secret\" \u003e /tmp/seal.key\ntpmcopy --mode duplicate --keyType=keyedhash --secret=/tmp/seal.key \\\n   --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\n\ntpmcopy --mode import  --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem   --tpm-path=$TPMB\n\ncd example/\ngo run keyedhash/main.go --pemFile=/tmp/tpmkey.pem  --password=bar --tpm-path=$TPMB\ncd ..\n\n### Python RSA\ntpmcopy --mode publickey --parentKeyType=rsa_ek -tpmPublicKeyFile=/tmp/public.pem --tpm-path=$TPMB\ntpmcopy --mode duplicate  --secret=/tmp/key_rsa.pem --keyType=rsa \\\n   --password=bar -tpmPublicKeyFile=/tmp/public.pem -out=/tmp/out.json\ntpmcopy --mode import --parentKeyType=rsa_ek --in=/tmp/out.json --out=/tmp/tpmkey.pem --tpm-path=$TPMB\n\ncd example/python\nvirtualenv env\napt-get install libtss2-dev\npython3 -m pip install git+https://github.com/tpm2-software/tpm2-pytss.git\npython3 esapi_keyfile_policy_duplicateselect_password.py\n```\n\n---\n\n## tpmcopy using tpm2_tools\n\nIf you want to see how this flow works with pure `tpm2_tools`, see  [PolicyDuplicateSelect and PolicyAuthValue bound PolicyDuplicate](https://gist.github.com/salrashid123/e487848bd5d3538a68c2284e1b24d89d)\n\nSpecifically, the following will transfer an rsa key from one TPM to another.  We're using two tpms although `tpmcopy` does not require a a TPM at the source.  We're doing that because tpm2_tools does not allow for an easy way to synthetically duplicate without an actual local TPM.\n\nstart two TPMs\n\n```bash\nrm -rf /tmp/myvtpm \u0026\u0026 mkdir /tmp/myvtpm\nswtpm_setup --tpmstate /tmp/myvtpm --tpm2 --create-ek-cert\n\nrm -rf /tmp/myvtpm2 \u0026\u0026 mkdir /tmp/myvtpm2\nswtpm_setup --tpmstate /tmp/myvtpm2 --tpm2 --create-ek-cert\n\nswtpm socket --tpmstate dir=/tmp/myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear --log level=2\nswtpm socket --tpmstate dir=/tmp/myvtpm2 --tpm2 --server type=tcp,port=2341 --ctrl type=tcp,port=2342 --flags not-need-init,startup-clear --log level=2\n```\n\nTo transfer from `TPM-A` to `TPM-B`\n\n1) `TPM-B`\n\nCreate an endorsement public key and extract the ECC PEM public key:\n\n```bash\nexport TPM2TOOLS_TCTI=\"swtpm:port=2341\"\n\ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\ntpm2_createek -c ek.ctx -G ecc -u ek.pub \ntpm2_readpublic -c ek.ctx -o ek.pem -f PEM -n ek.name\ntpm2_print -t TPM2B_PUBLIC ek.pub\n```\n\ncopy `ek.pem` to `TPM-A`\n\n2) `TPM-A`\n\n```bash\nexport TPM2TOOLS_TCTI=\"swtpm:port=2321\"\n## generate an rsa key\nopenssl genpkey -algorithm rsa -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 -out /tmp/key_rsa.pem\n\ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\n# create any primary\ntpm2_createprimary -C o -g sha256 -G rsa -c primaryA.ctx\n\ntpm2_loadexternal -C o -g sha256 -G ecc:null:aes128cfb  -u ek.pem -c newparent.ctx \\\n    --attributes=\"fixedtpm|fixedparent|sensitivedataorigin|adminwithpolicy|restricted|decrypt\"\ntpm2_readpublic -c newparent.ctx -o new_parent.pub -n new_parent.name\n\n## create a policy_or(policyAuthValue|policyDuplicateSelect)\ntpm2_startauthsession -S sessionA.dat\ntpm2_policyauthvalue -S sessionA.dat -L policyA_auth.dat \ntpm2_flushcontext sessionA.dat\nrm sessionA.dat\n\ntpm2_startauthsession -S sessionA.dat\ntpm2_policyduplicationselect -S sessionA.dat  -N new_parent.name -L policyA_dupselect.dat \ntpm2_flushcontext sessionA.dat\nrm sessionA.dat\n\ntpm2_startauthsession -S sessionA.ctx\ntpm2_policyor -S sessionA.ctx -L policyA_or.dat sha256:policyA_auth.dat,policyA_dupselect.dat \ntpm2_flushcontext sessionA.ctx\ntpm2_flushcontext -t\n\n### now import the external rsa key\ntpm2_import -C primaryA.ctx -G rsa2048:rsassa:null  -i /tmp/key_rsa.pem -u key.pub -r key.prv  -p bar -a \"sign\" -L policyA_or.dat\n\ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\ntpm2_load -C primaryA.ctx -r key.prv -u key.pub -c key.ctx -n key.name\ntpm2_readpublic -c key.ctx -o dup.pub\n\ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\n### create a binding policy\ntpm2_startauthsession -S sessionA.dat --policy-session\ntpm2_policyduplicationselect -S sessionA.dat  -N new_parent.name  -n key.name -L policyA_dupselect.dat \ntpm2_policyor -S sessionA.dat -L policyA_or.dat sha256:policyA_auth.dat,policyA_dupselect.dat \n\n## now duplicate\ntpm2_flushcontext -t\ntpm2_duplicate -C newparent.ctx -c key.ctx -G null  -p \"session:sessionA.dat\" -r dup.dpriv -s dup.seed\ntpm2_flushcontext -t\n```\n\n3)  `TPM-B`\n\non TPM B, import the duplicated keys, seed:\n\n```bash\nexport TPM2TOOLS_TCTI=\"swtpm:port=2341\"\n\ntpm2 flushcontext -t\ntpm2 startauthsession --session session.ctx --policy-session\ntpm2 policysecret --session session.ctx --object-context endorsement\n\ntpm2_import -C ek.ctx -u dup.pub -i dup.dpriv -r dup.prv -s dup.seed  --parent-auth session:session.ctx\ntpm2_flushcontext -t\ntpm2_flushcontext session.ctx\ntpm2_flushcontext -t\n\ntpm2 flushcontext -t\ntpm2 startauthsession --session session.ctx --policy-session\ntpm2 policysecret --session session.ctx --object-context endorsement \ntpm2_load -C ek.ctx -u dup.pub -r dup.prv -c dup.ctx  --auth session:session.ctx\ntpm2_readpublic -c dup.ctx -o dup.pub\ntpm2_flushcontext session.ctx\ntpm2_flushcontext -t\n\n\n### now create a real policy which will full the conditions set earlier\ntpm2_startauthsession -S sessionB.dat  --policy-session\ntpm2_policyauthvalue -S sessionB.dat  -L policyB_auth.dat \ntpm2_flushcontext sessionB.dat\nrm sessionB.dat\n\ntpm2_startauthsession -S sessionB.dat --policy-session\ntpm2_policyduplicationselect -S sessionB.dat  -N new_parent.name -L policyB_dupselect.dat \ntpm2_flushcontext sessionB.dat\nrm sessionB.dat\n\ntpm2_startauthsession -S sessionB.dat --policy-session\ntpm2_policyauthvalue -S sessionB.dat  -L policyB_auth.dat \ntpm2_policyor -S sessionB.dat -L policyB_or.dat sha256:policyB_auth.dat,policyB_dupselect.dat \n\necho \"meet me at..\" \u003efile.txt\nopenssl dgst -sha256  -keyform PEM - -sign /tmp/key_rsa.pem -out sig.dat file.txt\n\ntpm2_flushcontext -t\ntpm2_sign -c dup.ctx -g sha256  -f plain  -p\"session:sessionB.dat+bar\" -o sig.rss  file.txt\ntpm2_flushcontext -t\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Ftpmcopy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalrashid123%2Ftpmcopy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Ftpmcopy/lists"}