Skip to content

Commit

Permalink
add vtpm config
Browse files Browse the repository at this point in the history
Signed-off-by: sal rashid <[email protected]>
  • Loading branch information
salrashid123 committed Nov 25, 2024
1 parent 568ee48 commit 3750971
Show file tree
Hide file tree
Showing 33 changed files with 807 additions and 84 deletions.
241 changes: 177 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,101 +12,214 @@ Finally, the client will establish an mTLS https connection to the server

* **update `7/17/23`**: This sample use RSA keys involves several steps and a custom `crypto.signer`. 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
* openssl v3 (with [https://github.com/tpm2-software/tpm2-openssl](https://github.com/tpm2-software/tpm2-openssl))
* software tpm ([https://github.com/stefanberger/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, just startup software TPMs:

The following will startup two software TPMs where the client and server keys reside

NOTE:
- Server:

- The TPM is a device so concurrent access (eg via goroutines) will result in exceptions:
`Unable to Open TPM: open /dev/tpm0: device or resource busy`
```bash
cd certs/
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/ # or wherever tpm2.so sits, eg /usr/lib/x86_64-linux-gnu/ossl-modules/tpm2.so


$ openssl list -provider tpm2 -provider default --providers
Providers:
default
name: OpenSSL Default Provider
version: 3.2.0
status: active
tpm2
name: TPM 2.0 Provider
version: 1.2.0-25-g87082a3
status: active

$ openssl rsa -provider tpm2 -provider default -in server_key.pem --text
```


```bash
### test with openssl server
cd certs/
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

## or golang server
# 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

```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 ca/root-ca.crt https://server.domain.com:8081/index.html
```

- Client:

```bash
cd certs/
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/

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"
```

---
### Server

First create a server and install golang `go version go1.16.5 linux/amd64`
### Appendix

The following sewts up your own certs and software TPMs

#### Server

The following will setup a server cert where the private key is on a TPM

```bash
## if you'd rather use a software tpm than a real one, set the following and use --tpm-path="127.0.0.1:2321"
### the swtpm seems to not have a resource manager so while curl client will work, running both the go client and server
### while using the swtpm will not. both will run fine on a real tpm with a kernel resource manager
# rm -rf /tmp/myvtpm && mkdir /tmp/myvtpm
# sudo swtpm socket --tpmstate dir=/tmp/myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear
# export TPM2TOOLS_TCTI="swtpm:port=2321"

# tpm2_flushcontext -t -s -l
# tpm2_evictcontrol -C o -c 0x81008001

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/ # or wherever tpm2.so sits, eg /usr/lib/x86_64-linux-gnu/ossl-modules/tpm2.so
# export TSS2_LOG=esys+debug

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 rkey.pub -r rkey.priv -C rprimary.ctx
tpm2_flushcontext -t
tpm2_load -C rprimary.ctx -u rkey.pub -r rkey.priv -c rkey.ctx
tpm2_evictcontrol -C o -c rkey.ctx 0x81008001
tpm2_flushcontext -t
tpm2_create -G rsa2048:rsapss:null -g sha256 -u server.pub -r server.priv -C rprimary.ctx
tpm2_flushcontext -s && tpm2_flushcontext -t && tpm2_flushcontext -l
tpm2_load -C rprimary.ctx -u server.pub -r server.priv -c server.ctx
tpm2_flushcontext -s && tpm2_flushcontext -t && tpm2_flushcontext -l

## convert rkey.pub rkey.priv to PEM format
## using https://github.com/salrashid123/tpm2genkey/releases
./tpm2genkey --mode=tpm2pem --public=server.pub --private=server.priv --out=server_key.pem

# create a csr using the tpm key...i have it in this repo:
git clone https://github.com/salrashid123/signer.git
cd signer/util
go run csrgen/csrgen.go --filename /tmp/server.csr \
--sni server.domain.com --persistentHandle=0x81008001 -tpm-path="/dev/tpmrm0"

openssl req -in /tmp/server.csr -noout -text

# switch to this repo's root; generate the server certificate
#
cd go_tpm_https_embed/certs/
export SAN=DNS:server.domain.com
openssl ca -config single-root-ca.conf -in /tmp/server.csr -out server.crt -subj "/C=US/ST=California/L=Mountain View/O=Google/OU=Enterprise/CN=server.domain.com" -extensions server_ext

# run the server
go run src/server/server.go -cacert certs/ca/root-ca.crt -servercert certs/server.crt \
--persistentHandle=0x81008001 -port :8081 -tpmdevice="/dev/tpmrm0"
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

cd certs/
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

# 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"
```

### curl mTLS

You can test the config locally using the pre-generated client certificates provided in this repo
### Client

For the client,

```bash
curl -v -H "Host: server.domain.com" --resolve server.domain.com:8081:127.0.0.1 \
--cert certs/certs/user10.crt --key certs/certs/user10.key \
--cacert certs/ca/root-ca.crt https://server.domain.com:8081/
```
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

### Client
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/ # or wherever tpm2.so sits, eg /usr/lib/x86_64-linux-gnu/ossl-modules/tpm2.so

```bash
## again with a software tpm
# export TPM2TOOLS_TCTI="swtpm:port=2321"
# tpm2_flushcontext -t -s -l
# tpm2_evictcontrol -C o -c 0x81008000
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_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_flushcontext -s && tpm2_flushcontext -t && tpm2_flushcontext -l
tpm2_load -C rcprimary.ctx -u client.pub -r client.priv -c client.ctx
tpm2_flushcontext -s && tpm2_flushcontext -t && tpm2_flushcontext -l

tpm2_create -G rsa2048:rsapss:null -g sha256 -u rkey.pub -r rkey.priv -C rprimary.ctx
tpm2_flushcontext -t
tpm2_load -C rprimary.ctx -u rkey.pub -r rkey.priv -c rkey.ctx
tpm2_evictcontrol -C o -c rkey.ctx 0x81008000
tpm2_flushcontext -t
## convert rkey.pub rkey.priv to PEM format
## using https://github.com/salrashid123/tpm2genkey/releases
./tpm2genkey --mode=tpm2pem --public=client.pub --private=client.priv --out=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

# get the source repo
git clone https://github.com/salrashid123/signer.git
cd signer/util
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"

go run csrgen/csrgen.go --filename /tmp/kclient.csr --sni server.domain.com --persistentHandle=0x81008000 -tpm-path="/dev/tpmrm0"
openssl req -in client.csr -noout -text

## switch back to the root of this repo
cd go_tpm_https_embed/certs/
export SAN=DNS:client.domain.com
openssl ca -config single-root-ca.conf -in /tmp/kclient.csr -out kclient.crt \
-subj "/C=US/ST=California/L=Mountain View/O=Google/OU=Enterprise/CN=client.domain.com" -extensions client_reqext
openssl ca \
-config single-root-ca.conf \
-in client.csr \
-out client.crt \
-extensions client_ext

# run the client using the server's IPaddress or just connect to the internal dns alias
# echo $SERVER_IP
go run src/client/client.go -cacert certs/ca/root-ca.crt --persistentHandle=0x81008000 --address localhost -tpm-path="/dev/tpmrm0"
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
Expand Down
93 changes: 93 additions & 0 deletions certs/ca/root-ca/03.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3 (0x3)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Google, OU=Enterprise, CN=Enterprise Root CA
Validity
Not Before: Nov 24 17:01:38 2024 GMT
Not After : Nov 24 17:01:38 2034 GMT
Subject: C=US, O=Google, OU=Enterprise, CN=server.domain.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:c0:9b:35:41:dc:8a:2e:e8:fe:4b:a8:5e:d8:c7:
fa:80:72:81:e6:03:79:9c:8c:c3:c2:c5:5f:34:ca:
87:de:fb:1e:10:7a:eb:5e:ea:c6:ff:59:06:09:38:
84:cc:27:4c:22:e4:7b:7a:ed:b8:7f:80:70:5f:d9:
58:87:83:3f:da:f0:a1:86:24:e7:bd:0c:f5:89:50:
b5:d8:1e:49:c6:00:94:1a:7d:60:b6:8f:88:b1:52:
94:e6:1f:ed:ae:9c:0b:33:c6:fa:ac:f0:51:69:ae:
25:19:28:d3:00:9a:32:2f:83:3b:38:79:e8:95:8c:
80:2c:ec:23:dd:8d:ba:17:29:90:5c:9b:fb:58:59:
36:0a:96:71:50:ba:45:df:f5:37:9f:53:ef:69:73:
e9:22:d1:58:ff:48:ac:e0:53:84:e4:25:b3:2d:14:
43:ba:2a:e6:db:01:54:72:d4:d1:24:4d:ce:f8:4d:
85:e3:70:48:34:48:23:37:c0:ce:49:f0:7c:d9:3d:
7a:2d:20:01:29:26:fc:34:31:31:a1:30:b8:42:77:
cd:a3:b6:d1:c1:06:1a:07:fa:ca:cf:1f:c3:7e:0e:
d2:4d:45:b5:a8:0a:04:66:15:5a:70:e0:1d:d5:56:
0f:ed:45:88:08:cd:93:ea:2e:15:d3:4e:ab:ea:a4:
88:17
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Basic Constraints:
CA:FALSE
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Key Identifier:
35:CA:1A:65:09:D7:07:2B:B1:4A:96:41:3E:82:54:01:5D:C5:2D:A4
X509v3 Authority Key Identifier:
EA:AE:CD:0B:91:9B:F2:7E:95:AF:C0:2C:08:FE:46:22:6C:6F:61:F0
Authority Information Access:
CA Issuers - URI:http://pki.esodemoapp2.com/ca/root-ca.cer
X509v3 CRL Distribution Points:
Full Name:
URI:http://pki.esodemoapp2.com/ca/root-ca.crl
X509v3 Subject Alternative Name:
DNS:server.domain.com
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
46:c4:d3:82:e9:85:2a:19:6f:ce:28:3d:8e:d1:32:78:49:43:
69:57:42:f1:56:fa:1a:2a:c5:5b:19:17:0c:da:b5:b5:c3:cd:
d3:03:58:5a:c0:e5:0e:72:30:04:24:fd:3d:d0:be:00:20:22:
14:e8:b8:24:f4:08:e0:77:a2:9f:39:70:05:11:a9:59:4f:30:
c8:92:bc:cc:92:52:80:4e:09:80:ac:54:9b:e3:3a:3c:5a:49:
33:4c:9d:7a:5d:29:11:69:f8:8d:df:9c:5a:a1:20:b3:f5:7e:
4b:86:99:1c:d4:86:2c:91:d6:ab:2a:4d:f3:a2:04:c1:6f:5f:
95:bc:a6:f0:88:39:24:c8:71:5f:73:d7:83:63:7b:6e:12:5a:
34:02:59:9c:f8:c4:a3:41:e8:d2:68:6c:78:16:fd:cb:02:78:
51:59:15:a8:bf:e8:b8:ae:5c:aa:70:87:7f:93:92:ad:dd:3f:
ae:15:a4:04:99:07:2e:f5:1a:d6:5e:95:0c:77:02:d2:af:73:
d1:8d:c9:dc:a0:0e:45:be:67:d5:83:2e:6c:f8:80:62:28:46:
22:85:19:2f:5e:22:c5:fd:32:b7:b4:d6:bd:f4:3d:77:db:61:
da:47:f2:61:a9:13:38:33:9a:d6:4f:13:81:09:1e:3a:83:79:
89:c1:8b:df
-----BEGIN CERTIFICATE-----
MIIEMTCCAxmgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEP
MA0GA1UECgwGR29vZ2xlMRMwEQYDVQQLDApFbnRlcnByaXNlMRswGQYDVQQDDBJF
bnRlcnByaXNlIFJvb3QgQ0EwHhcNMjQxMTI0MTcwMTM4WhcNMzQxMTI0MTcwMTM4
WjBPMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGR29vZ2xlMRMwEQYDVQQLDApFbnRl
cnByaXNlMRowGAYDVQQDDBFzZXJ2ZXIuZG9tYWluLmNvbTCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAMCbNUHcii7o/kuoXtjH+oBygeYDeZyMw8LFXzTK
h977HhB6617qxv9ZBgk4hMwnTCLke3rtuH+AcF/ZWIeDP9rwoYYk570M9YlQtdge
ScYAlBp9YLaPiLFSlOYf7a6cCzPG+qzwUWmuJRko0wCaMi+DOzh56JWMgCzsI92N
uhcpkFyb+1hZNgqWcVC6Rd/1N59T72lz6SLRWP9IrOBThOQlsy0UQ7oq5tsBVHLU
0SRNzvhNheNwSDRIIzfAzknwfNk9ei0gASkm/DQxMaEwuEJ3zaO20cEGGgf6ys8f
w34O0k1FtagKBGYVWnDgHdVWD+1FiAjNk+ouFdNOq+qkiBcCAwEAAaOCARUwggER
MA4GA1UdDwEB/wQEAwIHgDAJBgNVHRMEAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMB
MB0GA1UdDgQWBBQ1yhplCdcHK7FKlkE+glQBXcUtpDAfBgNVHSMEGDAWgBTqrs0L
kZvyfpWvwCwI/kYibG9h8DBFBggrBgEFBQcBAQQ5MDcwNQYIKwYBBQUHMAKGKWh0
dHA6Ly9wa2kuZXNvZGVtb2FwcDIuY29tL2NhL3Jvb3QtY2EuY2VyMDoGA1UdHwQz
MDEwL6AtoCuGKWh0dHA6Ly9wa2kuZXNvZGVtb2FwcDIuY29tL2NhL3Jvb3QtY2Eu
Y3JsMBwGA1UdEQQVMBOCEXNlcnZlci5kb21haW4uY29tMA0GCSqGSIb3DQEBCwUA
A4IBAQBGxNOC6YUqGW/OKD2O0TJ4SUNpV0LxVvoaKsVbGRcM2rW1w83TA1hawOUO
cjAEJP090L4AICIU6Lgk9Ajgd6KfOXAFEalZTzDIkrzMklKATgmArFSb4zo8Wkkz
TJ16XSkRafiN35xaoSCz9X5Lhpkc1IYskdarKk3zogTBb1+VvKbwiDkkyHFfc9eD
Y3tuElo0Almc+MSjQejSaGx4Fv3LAnhRWRWov+i4rlyqcId/k5Kt3T+uFaQEmQcu
9RrWXpUMdwLSr3PRjcncoA5FvmfVgy5s+IBiKEYihRkvXiLF/TK3tNa99D1322Ha
R/JhqRM4M5rWTxOBCR46g3mJwYvf
-----END CERTIFICATE-----
Loading

0 comments on commit 3750971

Please sign in to comment.