{"id":13645955,"url":"https://github.com/folbricht/tpmk","last_synced_at":"2025-10-23T20:13:02.024Z","repository":{"id":35000545,"uuid":"170790650","full_name":"folbricht/tpmk","owner":"folbricht","description":"Toolkit to manage keys and certificates in TPM2 chips","archived":false,"fork":false,"pushed_at":"2025-04-17T05:36:24.000Z","size":389,"stargazers_count":41,"open_issues_count":1,"forks_count":9,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-17T20:04:27.205Z","etag":null,"topics":["go","golang","ssh","tls","tpm","tpm2"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/folbricht.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}},"created_at":"2019-02-15T02:37:48.000Z","updated_at":"2025-04-17T05:36:20.000Z","dependencies_parsed_at":"2024-11-09T19:31:23.566Z","dependency_job_id":"10ad9271-0be9-4ec1-ae7b-788307f9e59a","html_url":"https://github.com/folbricht/tpmk","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/folbricht%2Ftpmk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/folbricht%2Ftpmk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/folbricht%2Ftpmk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/folbricht%2Ftpmk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/folbricht","download_url":"https://codeload.github.com/folbricht/tpmk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250100499,"owners_count":21374957,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["go","golang","ssh","tls","tpm","tpm2"],"created_at":"2024-08-02T01:02:45.773Z","updated_at":"2025-10-23T20:13:01.939Z","avatar_url":"https://github.com/folbricht.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# tmpk - TPM2 key and storage management toolkit\n\n[![GoDoc](https://godoc.org/github.com/folbricht/tpmk?status.svg)](https://godoc.org/github.com/folbricht/tpmk)\n\nThis toolkit strives to simplify common tasks around key and certificates involving TPM2. It also provides the tools necessary to make use of keys in the module for TLS connections and OpenPGP in Go. It does not attempt to provide a feature-rich interface to support all possible use-cases and features. tpmk consists of a Go library and a tool with a simple interface. It currently provides:\n\n- Generating RSA/SHA256 primary keys in the TPM and exporting the public key\n- Generating x509 certificates and signing with a (file) CA\n- Writing of arbitrary data to NV storage - intended to be used to store certificates\n- Creating SSH certificates for keys in the TPM\n- Generating OpenPGP public keys based on RSA keys in the TPM\n- OpenPGP Signing and Decryption\n\nA range of features and options are **not** available at this point, but may be implemented in the future. Suggestions and contributions are welcome.\n\n- Generating ECC keys\n- PCRs\n- TPM policies\n- Only supports the owner hierarchy\n\n## Tool\n\nThe tool is provided for convenience and should allow the use of the most common features. Some of the operations offered by its sub-commands, like `x509` can be performed with more feature-rich tools such as `openssl`. The tool is able to operate on a TPM 2.0 simulator (use option `-d sim`).\n\n### Installation\n\n```text\ngo get -u github.com/folbricht/tpmk/cmd/tpmk\n```\n\n### Sub-Commands\n\n- `key` Groups commands that operate on keys in the TPM\n\n  - `generate` Generates a new primary key and makes it persistent\n  - `read` Reads the public key\n  - `rm` Removes a persistent key\n  - `ls` List persistent keys\n\n- `nv` Contains commands to operate on non-volatile indexes in the TPM\n\n  - `write` Write arbitrary data into an index\n  - `read` Read data from an index\n  - `rm` Delete data in an index\n  - `ls` List indexes\n\n- `x509` Offers commands to generate and sign certificates\n\n  - `generate` Generate a new certificate for a public key and sign it\n\n- `ssh` Commands to operate on SSH certificates\n\n  - `certificate` Create and sign an SSH certificate\n  - `pub` Convert a PKCS1 key to OpenSSH format\n  - `client` Start SSH client and execute remote command\n\n- `openpgp` Commands to use keys in OpenPGP format\n\n  - `generate` Create an OpenPGP identity based on a key in the TPM\n  - `sign` Sign data with a TPM key\n  - `decrypt` Decrypt data using the private TPM key\n\n## Use-cases / Examples\n\n### RSA key generation and certificate storage in NV\n\nIn this example, the goal is to have an RSA key generated in the TPM, and have a signed certificate for the key stored in NV in the TPM. This allows a machine to retain a signed key+certificate without relying on disk storage. While the generated keys doesn't leave the module, the CA to sign it is expected to be available as files at time of signing.\n\nGenerate the key in the TPM and write the public key (in PEM format) to disk.\n\n```sh\ntpmk key generate 0x81000000 pub.pem\n```\n\nBuild a certificate using the public key and signing it with a (file) CA and writing it to disk in PEM format. Options to set the common name, SAN properties, expiry, and others are available.\n\n```sh\ntpmk x509 generate -c ca.crt -k ca.key -f der pub.pem cert.pem\n```\n\nStore the (signed) certificate in the TPM in an NV storage index. This command stores the PEM cert which is not recommended since the amount of data that can be stored in a single NV index is limited. A large PEM may not fit. It'd be better to store the cert in DER format instead (available with `--out-format=der` option above).\n\n```sh\ntpmk nv -d sim write 0x1500000 cert.pem\n```\n\nThe following does the same, but passes the data through STDIN/STDOUT without storing anything on disk. It also stores the certificate in DER format instead of PEM to ensure it fits into the NV index.\n\n```sh\ntpmk key generate 0x81000000 - | tpmk x509 generate -c ca.crt -k ca.key --out-format=der - -| tpmk nv write 0x1500000 -\n```\n\n### Establishing a mutual TLS connection using a TPM key\n\nHere the goal is to use a key from the TPM to establish a mutual TLS connection with a server. The key is assumed to have been generated already (see prior example). While not strictly neccessary, the signed x509 is kept in NV as well.\n\nStart off with some setup. Defining the handle/index that hold the key and certificate and open the TPM.\n\n```go\nconst (\n  keyHandle = 0x81000000\n  nvHandle  = 0x1500000\n  password  = \"\"\n)\n\n// Open the TPM\ndev, err := tpmk.OpenDevice(\"/dev/tpmrm0\")\nif err!=nil{\n    panic(err)\n}\ndefer dev.Close()\n```\n\nThe next step is to create a crypto.PrivateKey that can be used in the TLS negotiation, as well as loading the x509 certificate from NV.\n\n```go\n// Use the private key in the TPM\nprivate, err := tpmk.NewRSAPrivateKey(dev, keyHandle, password)\nif err != nil {\n  panic(err)\n}\n\n// Read the certificate (DER format) from NV\ncertDER, err := tpmk.NVRead(dev, nvHandle, password)\nif err != nil {\n  panic(err)\n}\n```\n\nWith the client certificate and key it's now possible to build the TLS client config. The CA certificate is also required to trust the server.\n\n```go\n// Build the client certificate for the mutual TLS connection\nclientCrt := tls.Certificate{\n  Certificate: [][]byte{certDER},\n  PrivateKey:  private,\n}\n\n// Load the CA certificate\ncaCrt, err := tpmk.LoadX509CertificateFile(\"ca.crt\")\nif err != nil {\n  panic(err)\n}\n\n// Build the client TLS config\nroot := x509.NewCertPool()\nroot.AddCert(caCrt)\nclientCfg := \u0026tls.Config{\n  Certificates: []tls.Certificate{clientCrt},\n  RootCAs:      root,\n}\n```\n\nUsing the TLS client config, the client can now connect to a server that expects a client certificate. The client key remains in the TPM.\n\n```go\n// Connect to the server\nconn, err := tls.Dial(\"tcp\", \"localhost:1234\", clientCfg)\nif err != nil {\n  panic(err)\n}\ndefer conn.Close()\nconn.Write([]byte(\"hello\"))\n```\n\n### SSH certificate generation\n\nThis example shows how to create an SSH certificate for a key in the TPM. It also covers reading and converting a key to OpenSSH format. The key is assumed to be present in the TPM already. An earlier example shows how to generate one.\n\nFirst, the public key is read from the TPM. The result is PEM encoded PKCS#1.\n\n```sh\ntpmk key read 0x81000000 pub.pem\n```\n\nTo generate and sign an SSH certificate, an SSH CA key is required which is provided as file (ssh-ca) in this example. A key identifier, serial or certificate option can be provided. If the generated certificate is to be stored in an NV index, the `-f wire` option is recommended as this will produce a more compact encoding.\n\n```sh\ntpmk ssh certificate --ca-key ssh-ca --id myKey -O force-command=ls pub.pem tpm-cert.pub\n```\n\nIf a public key conversion to OpenSSH format is needed, the `pub` subcommand can be used.\n\n```sh\ntpmk ssh pub pub.pem id_rsa.pub\n```\n\nAs before, these commands can be chained together via STDOUT/STDIN by providing `-` in place of filenames.\n\n### Open SSH connection using public key authentication with TPM key\n\nThe following example shows how to utilize a TPM key to open an SSH connection to a server using [golang.org/x/crypto/ssh](https://godoc.org/golang.org/x/crypto/ssh) as client.\n\nFirst open the TPM device or simulator. The key 0x81000000 is assumed to be present and will be used for authentication.\n\n```go\nconst (\n  keyHandle = 0x81000000\n  password  = \"\"\n)\n\ndev, err := tpmk.OpenDevice(\"/dev/tpmrm0\")\nif err!=nil{\n    panic(err)\n}\ndefer dev.Close()\n```\n\nRead the public key from the TPM and use it to create crypto.Signer which can be used to build an ssh.Signer used in public key authentication.\n\n``` go\n// Use the private key in the TPM\nprivate, err := tpmk.NewRSAPrivateKey(dev, keyHandle, password)\nif err != nil {\n  panic(err)\n}\n// Create an ssh.Signer to be used for key authentication\nsigner, err := ssh.NewSignerFromSigner(private)\nif err != nil {\n  panic(err)\n}\n// Build the client configuration\nconfig := \u0026ssh.ClientConfig{\n  User: \"username\",\n  Auth: []ssh.AuthMethod{\n    ssh.PublicKeys(signer),\n  },\n  HostKeyCallback: ssh.InsecureIgnoreHostKey(),\n}\n```\n\nOpen the SSH client connection. The public key in OpenSSH format needs to be setup on the server for authentication to succeed.\n\n```go\nclient, err := ssh.Dial(\"tcp\", \"hostname:22\", config)\nif err != nil {\n  panic(err)\n}\n\nsession, err := client.NewSession()\nif err != nil {\n  panic(err)\n}\ndefer session.Close()\n\nb, err := session.Output(\"/usr/bin/whoami\")\nif err != nil {\n  panic(err)\n}\nfmt.Println(string(b))\n```\n\n### Create an OpenPGP identity and sign data with it\n\nThis example shows how to produce an OpenPGP public key (identity) and use it to sign data.\n\nIn order to sign with a TPM key, an OpenPGP identity needs to be created with name and email address. This identity contains the public key and should be stored (either separately or in a TPM NV index). For this command, the key (handle 0x81000000 in this example) has to be present in the TPM already and must have the `sign` attribute to allow signing.\n\n```sh\ntpmk openpgp generate -n Testing -e test@example.com 0x81000000 identity.pgp\n```\n\nThe same key and identity should be used when signing data. In this case a detached and armored signature is created and written to STDOUT.\n\n```sh\ntpmk openpgp sign -a 0x81000000 identity.pgp data.txt -\n```\n\n## Links\n\n- TPM2 specification - [https://trustedcomputinggroup.org/resource/tpm-library-specification/](https://trustedcomputinggroup.org/resource/tpm-library-specification/)\n- Go TPM2 library used by tpmk - [https://github.com/google/go-tpm](https://github.com/google/go-tpm)\n- IBM TPM2.0 Simulator - [https://sourceforge.net/projects/ibmswtpm2/](https://sourceforge.net/projects/ibmswtpm2/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffolbricht%2Ftpmk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffolbricht%2Ftpmk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffolbricht%2Ftpmk/lists"}