{"id":27998748,"url":"https://github.com/salrashid123/tpm-kdf","last_synced_at":"2026-02-09T14:05:20.297Z","repository":{"id":289932096,"uuid":"972862179","full_name":"salrashid123/tpm-kdf","owner":"salrashid123","description":"TPM based Key Deriviation Function (KDF)","archived":false,"fork":false,"pushed_at":"2026-02-06T23:50:35.000Z","size":497,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-07T10:38:27.451Z","etag":null,"topics":["key-derivation-function","trusted-platform-module"],"latest_commit_sha":null,"homepage":"","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-04-25T19:42:26.000Z","updated_at":"2026-02-06T23:50:39.000Z","dependencies_parsed_at":"2025-05-08T22:54:57.567Z","dependency_job_id":"410076f9-e994-4fc6-960e-b7dc4508e0db","html_url":"https://github.com/salrashid123/tpm-kdf","commit_stats":null,"previous_names":["salrashid123/tpm-kdf"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/salrashid123/tpm-kdf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Ftpm-kdf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Ftpm-kdf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Ftpm-kdf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Ftpm-kdf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salrashid123","download_url":"https://codeload.github.com/salrashid123/tpm-kdf/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Ftpm-kdf/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29268468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-09T13:47:44.167Z","status":"ssl_error","status_checked_at":"2026-02-09T13:47:43.721Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["key-derivation-function","trusted-platform-module"],"created_at":"2025-05-08T22:54:49.665Z","updated_at":"2026-02-09T14:05:20.291Z","avatar_url":"https://github.com/salrashid123.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## TPM based Key Deriviation Function (KDF)\n\n\nCLI and library which provides a `counter mode KDF` as described in [NIST SP 800-108](https://csrc.nist.gov/pubs/sp/800/108/r1/upd1/final).\n\nThis CLI utilizes an TPM-based HMAC key as a basis to derive the KDF.\n\nLibrary basically overrides [Canonicals KDF](https://github.com/canonical/go-kbkdf) and has been verified against some of the [NIST test vectors](https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Key-Derivation).\n\n---\n\n### References\n\n* [Trusted Platform Module (TPM) recipes with tpm2_tools and go-tpm](https://github.com/salrashid123/tpm2)\n* [golang-jwt for Trusted Platform Module (TPM)](https://github.com/salrashid123/golang-jwt-tpm)\n* [tpm2 key utility](https://github.com/salrashid123/tpm2genkey)\n* [ASN1 format for TPM keys](https://github.com/salrashid123/tpm2/tree/master/tpm-key)\n\n---\n\n### Parent Key\n\nCurrently, only the parent key represented by the [H2 Template](https://trustedcomputinggroup.org/wp-content/uploads/TCG_IWG_EKCredentialProfile_v2p4_r2_10feb2021.pdf) is supported.  This was done for compatibility with openssl (which by default only supports the `h2`)\n\nThe H2 template is also what is specified in [ASN.1 Specification for TPM 2.0 Key Files](https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html#name-parent)\n\nIts possible to support other parent key types (`rsa_ek`, `ecc_ek`, `rsa_srk`, `ecc_srk`) but H2 is the easiest.  If you need other parent types, pls create an issue in github..\n\nThe following shows an example of creating the `h2 parent` and then an HMAC key on the TPM \n\n```bash\nprintf '\\x00\\x00' \u003e unique.dat\ntpm2_createprimary -C o -G ecc \\\n    -g sha256  -c primary.ctx -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\n\ntpm2_create -C primary.ctx -g sha256 -G hmac -u hmac-fixed.pub -r hmac-fixed.priv\ntpm2_encodeobject -C primary.ctx -u hmac-fixed.pub -r hmac-fixed.priv -o tpm-key-fixed.pem\n```\n\nIf you want to _import_ an external hmac key, the flow uses the same parent\n\n```bash\necho -n \"my_api_key\" \u003e hmac.key\nhexkey=$(xxd -p -c 256 \u003c hmac.key)\n\nprintf '\\x00\\x00' \u003e unique.dat\ntpm2_createprimary -C o -G ecc \\\n    -g sha256  -c primary.ctx -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\n\ntpm2_import -C primary.ctx -G hmac -i hmac.key -u hmac.pub -r hmac.priv\ntpm2_load -C primary.ctx -u hmac.pub -r hmac.priv -c hmac.ctx\ntpm2_encodeobject -C primary.ctx -u hmac.pub -r hmac.priv -o tpm-key.pem\n```\n\n### Library\n\nAs a library, you need to import Vault's base KDF class and override it with this libarary.\n\nThe following with derive a key from \"foo\":\n\n```golang\nimport (\n\t\"encoding/hex\"\n\ttpmkdf \"github.com/salrashid123/tpm-kdf\"\n)\n\n\tkeyFileBytes, err := os.ReadFile(\"/path/to/tpm-key.pem\")\n\n\tkeyLengthBits := uint32(256)\n\tlabel := []byte(\"foo\")\n\tcontext := []byte(\"context\")\n\n\tprf, err := tpmkdf.NewTPMPRF(\"/dev/tpmrm0\", nil, keyFileBytes, nil, nil, \"\")\n\n\t// Derive the key using the Counter Mode KDF\n\tderivedKey, err := tpmkdf.CounterModeKey(\n\t\tprf,           // The pseudorandom function (HMAC-SHA256)\n\t\tnil,           // The master secret key, set this to nil since its derived from the PRF\n\t\tlabel,         // Optional label\n\t\tcontext,       // Optional context\n\t\tkeyLengthBits, // Desired key length in bits\n\t)\n\n\tfmt.Printf(\"Derived Key (%d bytes): %x\\n\", len(derivedKey), derivedKey)\n```\n\nThe core accepts the following parameters:\n\n```golang\nfunc TPMKDF(\n\ttpmPath string, \n\trwc io.ReadWriteCloser, \n\tpemkeyBytes []byte, \n\tparentAuth []byte, \n\tkeyAuth []byte,\n\tsessionEncryptionName string,\n\tdata []byte) (*tpmPrf, error) {\n```\n\nif you want the library to open and close the tpm for every call, specify the `tpmPath` (eg `tpmPath=/dev/tpmrm0`)\n\nif you want to manage the TPM read closer externally, set `tpmPath` nil and set the `rwc` to a TPM\n\n```golang\n\trwc, err := tkdf.OpenTPM(*tpmPath)\n\n\tkeyFileBytes, err := os.ReadFile(\"/path/to/tpm-key.pem\")\n\n\tprf, err := tpmkdf.NewTPMPRF(nil, rwc, keyFileBytes, nil, nil, \"\")\n\n\t// Derive the key using the Counter Mode KDF\n\tderivedKey, err := tpmkdf.CounterModeKey(\n\t\tprf,           // The pseudorandom function (HMAC-SHA256)\n\t\tnil,           // The master secret key, set this to nil since its derived from the PRF\n\t\tlabel,         // Optional label\n\t\tcontext,       // Optional context\n\t\tkeyLengthBits, // Desired key length in bits\n\t)\n\n\tfmt.Printf(\"Derived Key (%d bytes): %x\\n\", len(derivedKey), derivedKey)\n```\n\n### CLI\n\nAs a library, provide the PEM formatted TPM private key and the length of of the data to mac.\n\nYou can get the signed and attested binary on the `Releases` page\n\n```bash\n./tpm-kdf  --label=foo   --context=context  \\\n    --keyFile=example/certs/tpm-key.pem --length=256 --tpm-path=\"127.0.0.1:2321\n```\n\n| Option | Description |\n|:------------|-------------|\n| **`-tpmPath`** | Path to the TPM device (character device or a Unix socket). (default: `/dev/tpmrm0`) |\n| **`-keyFile`** | Path to the PEM formatted KeyFile |\n| **`-length`** | result size |\n| **`-label`** | kdf label |\n| **`-context`** | kdf context |\n| **`-tpm-session-encrypt-with-name`** | hex encoded TPM object 'name' to use with an encrypted session|\n| **`-outputBase64`** | output as base64 |\n\nThe `keyFile` parameter here accepts a PEM formatted key as described in [ASN.1 Specification for TPM 2.0 Key Files](https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html).\n\nYou can save a key in PEM format using [tpm2_encodeobject](https://github.com/tpm2-software/tpm2-tools/blob/master/man/tpm2_encodeobject.1.md) or [tpm2 key utility](https://github.com/salrashid123/tpm2genkey)\n\n#### Setup\n\nThe following sets up a sofware TPM but you can ofcourse use the real thing.  \n\n```bash\ncd example/\n\n# mkdir myvtpm\n# swtpm_setup --tpmstate myvtpm --tpm2 --create-ek-cert\n\nswtpm socket --tpmstate dir=myvtpm \\\n   --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear --log level=5\n\nexport TPM2TOOLS_TCTI=\"swtpm:port=2321\"\n\n### if you wanted to generate a new key, then run the following.\n###  the example/ folder contains key files with this passphrase.\n\necho -n \"my_api_key\" \u003e hmac.key\nhexkey=$(xxd -p -c 256 \u003c hmac.key)\n\nprintf '\\x00\\x00' \u003e unique.dat\ntpm2_createprimary -C o -G ecc \\\n    -g sha256  -c primary.ctx -a \"fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt\" -u unique.dat\n\ntpm2_import -C primary.ctx -G hmac -i hmac.key -u hmac.pub -r hmac.priv\ntpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\ntpm2_load -C primary.ctx -u hmac.pub -r hmac.priv -c hmac.ctx\ntpm2_encodeobject -C primary.ctx -u hmac.pub -r hmac.priv -o tpm-key.pem\n\ngo run cmd/main.go  --label=foo --context=context \\\n   --keyFile=example/certs/tpm-key.pem --length=256 --tpm-path=\"127.0.0.1:2321\"\n```\n\nIf you want to setup a key with auth, create an authsession and `policypassword` after the primary\n\n```bash\n# tpm2_startauthsession -S session.dat\n# tpm2_policypassword -S session.dat -L policy.dat\n# tpm2_flushcontext session.dat\n\n# tpm2_import -C primary.ctx -G hmac -i hmac.key -u hmac.pub -r hmac.priv -L policy.dat -p testpswd\n# tpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n# tpm2_load -C primary.ctx -u hmac.pub -r hmac.priv -c hmac.ctx\n# tpm2_encodeobject -C primary.ctx -u hmac.pub -r hmac.priv -o tpm-key.pem \n# tpm2_flushcontext -t \u0026\u0026 tpm2_flushcontext -s \u0026\u0026 tpm2_flushcontext -l\n\ngo run cmd/main.go  --label=foo  \\\n   --keyFile=example/certs_policy/tpm-key.pem --keyPass=testpswd --length=256 --tpm-path=\"127.0.0.1:2321\"\n```\n\nTHe current release only uses passwordAuth.  \n\nOther policy times can get encoded into the TPM but i'm just waiting for the  specs to finalize.  For now, see [Reconstruct Policy using command parameters](https://github.com/salrashid123/tpm2/tree/master/policy_gen)\n\n\n### Encrypted TPM Sessions\n\nIf you want to enable [TPM Encrypted sessions](https://github.com/salrashid123/tpm2/tree/master/tpm_encrypted_session), you should provide the \"name\" of a trusted key on the TPM for each call.\n\nA trusted key can only be the `RSA-EK` Key. You can get the name using `tpm2_tools`:\n\n```bash\ntpm2_createek -c ekprimary.ctx -G rsa -u ek.pub -Q\ntpm2_readpublic -c ekprimary.ctx -o ek.pem -n name.bin -f pem -Q\nxxd -p -c 100 name.bin \n  000b84c403b83cdf6472d9e84f87169cac746be95c1182ed61bffd12f18adaea8e63\n```\n\nThen use the hex value returned in the `--tpm-session-encrypt-with-name=` argument.\n\nFor example:\n\n```bash\n   --tpm-session-encrypt-with-name=000b84c403b83cdf6472d9e84f87169cac746be95c1182ed61bffd12f18adaea8e63\n\n# for example\n go run policy/main.go \\\n    --tpm-session-encrypt-with-name=000b84c403b83cdf6472d9e84f87169cac746be95c1182ed61bffd12f18adaea8e63\n```\n\nFor example, most TPM calls are encrypted.\n\nstart\n\n![images/hmac_start.png](images/hmac_start.png)\n\ncomplete\n\n![images/hmac_complete.png](images/hmac_complete.png)\n\nIf you do *not* specify an encryption name, the default `rsa-ek` is recalled and used anyway.\n\n### Latency\n\nIts certainly expected that there is significant latency in the KDF generation for keys (proportional to the number of hmac calls are made)\n\nIn an unscientific test, the TPM based operations has far larger latency:\n\n```bash\n$ time ./counter/main \nDerived Key (32 bytes): aa8c90530bb6c6e3e7d9047dfe4bd750c4c0c7a6206e4b75905a62a27b479333\n\nreal\t0m0.443s\nuser\t0m0.050s\nsys\t0m0.028s\n\n$ time ./baseline/main \nDerived Key (32 bytes): aa8c90530bb6c6e3e7d9047dfe4bd750c4c0c7a6206e4b75905a62a27b479333\n\nreal\t0m0.031s\nuser\t0m0.012s\nsys\t0m0.023s\n```\n\n### Testing\n\nUsing [swtpm](https://github.com/stefanberger/swtpm)\n\n```bash\nrm -rf /tmp/myvtpm \u0026\u0026 mkdir /tmp/myvtpm\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\n\n# then specify \"127.0.0.1:2321\"  as the TPM device path in the examples\n# and for tpm2_tools, export the following var\nexport TPM2TOOLS_TCTI=\"swtpm:port=2321\"\n\ngo test -v\n```\n\nYou can also verify using canonical's default library and with python:\n\n```bash\n$ go run counter/main.go \nDerived Key (32 bytes): aa8c90530bb6c6e3e7d9047dfe4bd750c4c0c7a6206e4b75905a62a27b479333\n\n$ go run baseline/main.go \nDerived Key (32 bytes): aa8c90530bb6c6e3e7d9047dfe4bd750c4c0c7a6206e4b75905a62a27b479333\n\n$ python3 baseline/kdf.py \naa8c90530bb6c6e3e7d9047dfe4bd750c4c0c7a6206e4b75905a62a27b479333\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Ftpm-kdf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalrashid123%2Ftpm-kdf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Ftpm-kdf/lists"}