https://github.com/salrashid123/go_tpm_https_embed
TPM based mTLS
https://github.com/salrashid123/go_tpm_https_embed
certificate golang tls trusted-computing trusted-platform-module
Last synced: 9 months ago
JSON representation
TPM based mTLS
- Host: GitHub
- URL: https://github.com/salrashid123/go_tpm_https_embed
- Owner: salrashid123
- License: apache-2.0
- Created: 2020-11-23T15:10:42.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2024-06-17T11:28:00.000Z (almost 2 years ago)
- Last Synced: 2024-06-17T12:52:54.250Z (almost 2 years ago)
- Topics: certificate, golang, tls, trusted-computing, trusted-platform-module
- Language: Go
- Homepage:
- Size: 330 KB
- Stars: 9
- Watchers: 4
- Forks: 5
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
### mTLS with TPM bound private key
Simple http client/server in golang where the private key used in the connection is generated and embedded within a [Trusted Platform Module](https://trustedcomputinggroup.org/resource/trusted-platform-module-tpm-summary/).
The steps here will create a client and server using a local software tpm `swtpm`. On that TPM, create two RSA keys, generate a CSR using those keys, then an external CA will issue an x509 cert using that csr.
Finally, the client will establish an mTLS https connection to the server
---
* If you want to see one-way TLS where the server's private key is embedded in a TPM and the private key is cryptographically verified (tpm remote attestation), please instead see [https://github.com/salrashid123/tls_ak](https://github.com/salrashid123/tls_ak)
for python, see [Python mTLS client/server with TPM based key](https://gist.github.com/salrashid123/4cb714d800c9e8777dfbcd93ff076100)
---
>> NOTE: this repo is not supported by Google
To use this sample, you'll need:
* golang
* `tpm2_tools`
* openssl3 (with [tpm2-openssl](https://github.com/tpm2-software/tpm2-openssl))
* software tpm ([swtpm](https://github.com/stefanberger/swtpm))
The TPM based private keys conforms to [ASN.1 Specification for TPM 2.0 Key Files](https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html) which in its basic mode is compatible with openssl
### QuickStart
if you want to use the keys provided in this repo, you just need `swtpm`
#### Start swtpm
Start two software TPMs on different ports to simulate the client and server's TPMs
```bash
cd certs/
## tpm for server
swtpm socket --tpmstate dir=myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear --log level=2
## in a new window, start tpm for the client
swtpm socket --tpmstate dir=myvtpm2 --tpm2 --server type=tcp,port=2341 --ctrl type=tcp,port=2342 --flags not-need-init,startup-clear --log level=2
```
##### Start Server
To start the server using the built in demo `swtpm`
```bash
go run src/server/server.go -cacert certs/ca/root-ca.crt \
-servercert certs/server.crt \
--severkey=certs/server_key.pem -port :8081 \
--tpm-path="127.0.0.1:2321"
```
You can test the config locally using the pre-generated client certificates provided in this repo
(the following uses curl and ordinary (non-tpm) client certifcates)
```bash
curl -v -H "Host: server.domain.com" --resolve server.domain.com:8081:127.0.0.1 \
--cert certs/user10.crt --key certs/user10.key \
--cacert certs/ca/root-ca.crt https://server.domain.com:8081/index.html
```
##### Start Client
Run the client which uses TPM-based client certificates, in a new window:
```bash
go run src/client/client.go -cacert certs/ca/root-ca.crt \
--clientkey=certs/client_key.pem --pubCert=certs/client.crt \
--address localhost --tpm-path="127.0.0.1:2341"
```
WHat this shows is mTLS where both ends have the TLS private key on the TPM.
---
### Appendix
The following sets up your own certs and software or real TPMs.
If you want to use a real TPM, you need openssl tpm support but you don't need to export the `TPM2*` environment variables. For a real tpm, you'll also need to speicfy `--tpm-path=/dev/tpmrm0`
#### Server
The following will setup a server cert where the private key is on a TPM. For this you need to install openssl tpm support and `tpm2_tools`
if you'd rather use a real tpm than a sotware one, dont' export the TPM* env variables or start the swtpms.
Finally, while running the client or server set `--tpm-path="/dev/tpmrm0"`
For a swtpm:
```bash
mkdir myvtpm
sudo swtpm_setup --tpmstate myvtpm --tpm2 --create-ek-cert
sudo swtpm socket --tpmstate dir=myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear --log level=2
export TPM2TOOLS_TCTI="swtpm:port=2321"
export TPM2OPENSSL_TCTI="swtpm:port=2321"
export TPM2TSSENGINE_TCTI="swtpm:port=2321"
export OPENSSL_MODULES=/usr/lib/x86_64-linux-gnu/ossl-modules/
tpm2_flushcontext -t && tpm2_flushcontext -s && tpm2_flushcontext -l
# export TSS2_LOG=esys+debug
### first verify you have openssl installed and configured for TPM:
openssl list -provider tpm2 -provider default --providers
Providers:
default
name: OpenSSL Default Provider
version: 3.5.0
status: active
tpm2
name: TPM 2.0 Provider
version: 1.3.0
status: active
cd certs/
printf '\x00\x00' > unique.dat
tpm2_createprimary -C o -G ecc -g sha256 -c rprimary.ctx -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt" -u unique.dat
tpm2_create -G rsa2048:rsapss:null -g sha256 -u server.pub -r server.priv -C rprimary.ctx
tpm2_flushcontext -t && tpm2_flushcontext -s && tpm2_flushcontext -l
# tpm2_load -C rprimary.ctx -u server.pub -r server.priv -c server.ctx
## convert rkey.pub rkey.priv to PEM format
## note, you may need to add a -p parameter to tpm2_encodeobject if the version of tpm2_tools does not include (https://github.com/tpm2-software/tpm2-tools/issues/3458)
tpm2_encodeobject -C rprimary.ctx -u server.pub -r server.priv -o server_key.pem
### you'll know if you need to if you run the following and it prompts for a password
openssl rsa -provider tpm2 -provider default -in server_key.pem --text
export SAN="DNS:server.domain.com"
openssl req -new -provider tpm2 -provider default -config server.conf \
-out server.csr \
-key server_key.pem -reqexts server_reqext \
-subj "/C=US/O=Google/OU=Enterprise/CN=server.domain.com"
openssl req -in server.csr -noout -text
openssl ca \
-config single-root-ca.conf \
-in server.csr \
-out server.crt \
-extensions server_ext
# run the server as go
go run src/server/server.go -cacert certs/ca/root-ca.crt \
-servercert certs/server.crt \
--severkey=certs/server_key.pem -port :8081 \
--tpm-path="127.0.0.1:2321"
```
#### Client
For the client,
```bash
mkdir myvtpm2
sudo swtpm_setup --tpmstate myvtpm2 --tpm2 --create-ek-cert
sudo swtpm socket --tpmstate dir=myvtpm2 --tpm2 --server type=tcp,port=2341 --ctrl type=tcp,port=2342 --flags not-need-init,startup-clear --log level=2
export TPM2TOOLS_TCTI="swtpm:port=2341"
export TPM2OPENSSL_TCTI="swtpm:port=2341"
export TPM2TSSENGINE_TCTI="swtpm:port=2341"
export OPENSSL_MODULES=/usr/lib/x86_64-linux-gnu/ossl-modules/
tpm2_flushcontext -t && tpm2_flushcontext -s && tpm2_flushcontext -l
printf '\x00\x00' > unique.dat
tpm2_createprimary -C o -G ecc -g sha256 -c rcprimary.ctx -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt" -u unique.dat
tpm2_create -G rsa2048:rsapss:null -g sha256 -u client.pub -r client.priv -C rcprimary.ctx
tpm2_load -C rcprimary.ctx -u client.pub -r client.priv -c client.ctx
## note, you may need to add a -p parameter to tpm2_encodeobject (https://github.com/tpm2-software/tpm2-tools/issues/3458)
tpm2_encodeobject -C rcprimary.ctx -u client.pub -r client.priv -o client_key.pem
# create a csr using the tpm key...i have it in this repo:
openssl rsa -provider tpm2 -provider default -in client_key.pem --text
export SAN="DNS:client.domain.com"
openssl req -new -provider tpm2 -provider default -config client.conf \
-out client.csr \
-key client_key.pem -reqexts client_reqext \
-subj "/C=US/O=Google/OU=Enterprise/CN=client.domain.com"
openssl req -in client.csr -noout -text
openssl ca \
-config single-root-ca.conf \
-in client.csr \
-out client.crt \
-extensions client_ext
go run src/client/client.go -cacert certs/ca/root-ca.crt \
--clientkey=certs/client_key.pem --pubCert=certs/client.crt \
--address localhost --tpm-path="127.0.0.1:2341"
```
At this point, you should see a simple 'ok' from the sever
#### Openssl
If you would rather test the client/server using openssl
```bash
swtpm socket --tpmstate dir=myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear --log level=2
export TPM2TOOLS_TCTI="swtpm:port=2321"
export TPM2OPENSSL_TCTI="swtpm:port=2321"
export TPM2TSSENGINE_TCTI="swtpm:port=2321"
export OPENSSL_MODULES=/usr/lib/x86_64-linux-gnu/ossl-modules/
tpm2_flushcontext -t && tpm2_flushcontext -s && tpm2_flushcontext -l
openssl s_server -provider tpm2 -provider default \
-cert server.crt \
-key server_key.pem \
-port 8081 \
-CAfile ca/root-ca.crt \
-tlsextdebug \
-tls1_3 \
-trace \
-WWW
```
```bash
swtpm socket --tpmstate dir=myvtpm2 --tpm2 --server type=tcp,port=2341 --ctrl type=tcp,port=2342 --flags not-need-init,startup-clear --log level=2
export TPM2TOOLS_TCTI="swtpm:port=2341"
export TPM2OPENSSL_TCTI="swtpm:port=2341"
export TPM2TSSENGINE_TCTI="swtpm:port=2341"
export OPENSSL_MODULES=/usr/lib/x86_64-linux-gnu/ossl-modules/
tpm2_flushcontext -t && tpm2_flushcontext -s && tpm2_flushcontext -l
## in new window
go run src/client/client.go -cacert certs/ca/root-ca.crt \
--clientkey=certs/client_key.pem --pubCert=certs/client.crt \
--address localhost --tpm-path="127.0.0.1:2341"
```
### References
Other references:
- [Trusted Platform Module (TPM) and Google Cloud KMS based mTLS auth to HashiCorp Vault](https://github.com/salrashid123/vault_mtls_tpm)
- TPM TLS with nginx, openssl: [https://github.com/salrashid123/go_tpm_https#nginx](https://github.com/salrashid123/go_tpm_https#nginx)]
RSA-PSS padding:
- [Synthesized PSS support](https://github.com/tpm2-software/tpm2-pkcs11/issues/417)
- [PSS advertising during TLS handshake for TPM signing ](https://chromium-review.googlesource.com/c/chromium/src/+/2984231)
- [TLS salt length auto detection, switch from DIGEST to AUTO](http://openssl.6102.n7.nabble.com/RFC-TLS-salt-length-auto-detection-switch-from-DIGEST-to-AUTO-td78057.html)