The problem
When an SSH client connects to a server, it needs to know it is talking to the real server and not an attacker in the middle. Classic SSH handles this with a raw host key that the client remembers on first connection. That works for a single machine, but it does not scale to fleets of devices and gives you no way to establish trust ahead of time. There is also the question of the server’s private key: if it lives in a file on disk, anyone who compromises the server can copy it and impersonate the device somewhere else.
What we added
wolfSSH can now run a server whose host key is an X.509 certificate, with the matching private key sealed inside a TPM. This solves both problems at once. The certificate is signed by a CA the client already trusts, so the client verifies the server’s identity up front instead of guessing on first use. The private key is generated inside the TPM and never leaves it, so even a fully compromised server cannot hand the key to an attacker. During the SSH key exchange the TPM signs the exchange hash, and there is never a software copy of the key. Both ECDSA and RSA are supported.
Server integration is two calls. Bind the TPM key first so the certificate links to it, then load the certificate:
wolfSSH_CTX_UseTpmHostKey(ctx, &tpmDev, &tpmKey); wolfSSH_CTX_UseCert_buffer(ctx, certDer, certDerSz, WOLFSSH_FORMAT_ASN1);
On the client, load the CA you trust and require the certificate host key algorithms so the connection cannot quietly fall back to a plain key and skip the CA check:
wolfSSH_CTX_SetAlgoListKey(ctx, "x509v3-ecdsa-sha2-nistp256,x509v3-ssh-rsa"); wolfSSH_CTX_AddRootCert_buffer(ctx, caDer, caDerSz, WOLFSSH_FORMAT_ASN1);
We tested this end to end against a real TPM. With the correct CA the client connects and exchanges data. With an unrelated CA the client refuses to connect, which is the behavior that actually stops a man in the middle. Both cases pass for ECDSA and RSA.
Try it out
Build wolfSSL, wolfTPM, and wolfSSH with certificate and TPM support:
wolfSSL: ./configure --enable-wolfssh --enable-wolftpm --enable-keygen \
--enable-certgen --enable-certreq --enable-certext \
--enable-cryptocb \
CFLAGS="-DWC_RSA_NO_PADDING"
wolfTPM: ./configure --enable-fwtpm --enable-swtpm
wolfSSH: ./configure --enable-tpm --enable-certs
Start a TPM simulator (the wolfTPM fwtpm server or ibmswtpm2), then run the new example:
$ ./examples/tpmcertserver/tpmcertserver -k ecc $ ./examples/tpmcertserver/tpmcertclient -A tpm-server-cert.der
The server creates a signing key in the TPM, generates a certificate from it, and serves. The client verifies that certificate against its CA before exchanging a byte of data. The example under examples/tpmcertserver is the full working reference.
The example and support landed in wolfSSH pull request wolfSSL/wolfssh#1081.
If you have questions about any of the above, please contact us at facts@wolfssl.com or call us at +1 425 245 8247.
Download wolfSSL Now

