Skip to content

Instantly share code, notes, and snippets.

@salrashid123
Last active March 18, 2025 11:23
Show Gist options
  • Save salrashid123/db54e06f47ba7c6d801fe09f9f9c834a to your computer and use it in GitHub Desktop.
Save salrashid123/db54e06f47ba7c6d801fe09f9f9c834a to your computer and use it in GitHub Desktop.
openssl server with TPM based private key

TLS with TPM based private key

Requires openssl-tpm2 provider

# export OPENSSL_MODULES=/usr/lib/x86_64-linux-gnu/ossl-modules/
# 
# cat /etc/ssl/openssl.cnf
# [openssl_init]
# providers = provider_sect
# ssl_conf = ssl_sect

# [provider_sect]
# default = default_sect
# tpm2 = tpm2_sect

# [tpm2_sect]
# activate = 1
#
# [default_sect]
# activate = 1


$ openssl list --providers
    Providers:
    default
        name: OpenSSL Default Provider
        version: 3.0.2
        status: active
    tpm2
        name: TPM 2.0 Provider
        version: 1.3.0
        status: active

generate key

$ openssl req  --provider tpm2 --provider default -x509 -newkey rsa \
   -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 \
   -keyout key.pem -out cert.pem -sha256 -days 365

$ openssl rsa -provider tpm2  -provider default -in key.pem --text

Private-Key: (RSA 2048 bit, TPM 2.0)
Parent: 0x40000001
Modulus:
    00:c9:1b:e4:fb:db:a1:49:27:4d:b7:f5:f1:44:c6:
    4c:ba:d0:d9:20:4e:8f:bd:ad:78:d4:b0:5b:58:26:
    f6:b0:c1:d0:71:18:73:64:cc:72:7d:d3:77:8a:11:
    ec:70:69:ab:8c:a4:0c:2f:94:d3:54:47:d3:79:c8:
    6a:16:d9:4e:c0:9d:5b:67:a3:28:89:44:4b:c5:c4:
    c4:49:45:7a:23:e0:48:69:a4:01:63:47:5b:82:35:
    3e:37:f3:6e:db:81:3f:16:b1:39:a1:ae:82:2e:a9:
    81:f5:46:be:e3:e4:8e:84:4f:d9:5c:7c:f8:42:aa:
    d1:2a:bb:e4:cc:4c:c8:59:32:c1:80:e9:c1:5d:86:
    62:c7:e7:46:2b:a8:3d:4f:82:30:f1:c6:c7:ff:a5:
    13:88:6e:0a:ee:d4:5d:d6:b9:8f:61:8b:20:71:10:
    50:f9:7b:87:ff:c7:78:51:3f:4b:52:65:64:3a:9f:
    2a:4f:c6:93:e8:eb:c0:52:49:25:05:3a:25:65:ae:
    ed:b3:23:1a:97:24:42:3f:fd:21:db:68:21:6e:15:
    24:06:25:07:c4:7c:0a:01:0f:a5:dc:e2:13:ad:68:
    3c:42:b6:2a:8b:ba:68:32:bc:af:ad:17:07:26:4c:
    1f:2c:bd:99:87:da:e1:86:04:e4:f7:62:dc:0c:e5:
    45:7b
Exponent: 65537 (0x10001)
Object Attributes:
  fixedTPM
  fixedParent
  sensitiveDataOrigin
  userWithAuth
  decrypt
  sign / encrypt
Signature Scheme: <NULL>
  Hash: <NULL>
writing RSA key
-----BEGIN TSS2 PRIVATE KEY-----
MIICEgYGZ4EFCgEDoAMBAQECBEAAAAEEggEYARYAAQALAAYAcgAAABAAEAgAAAAA
AAEAyRvk+9uhSSdNt/XxRMZMutDZIE6Pva141LBbWCb2sMHQcRhzZMxyfdN3ihHs
cGmrjKQML5TTVEfTechqFtlOwJ1bZ6MoiURLxcTESUV6I+BIaaQBY0dbgjU+N/Nu
24E/FrE5oa6CLqmB9Ua+4+SOhE/ZXHz4QqrRKrvkzEzIWTLBgOnBXYZix+dGK6g9
T4Iw8cbH/6UTiG4K7tRd1rmPYYsgcRBQ+XuH/8d4UT9LUmVkOp8qT8aT6OvAUkkl
BTolZa7tsyMalyRCP/0h22ghbhUkBiUHxHwKAQ+l3OITrWg8QrYqi7poMryvrRcH
JkwfLL2Zh9rhhgTk92LcDOVFewSB4ADeACDekeQS2q1DW+fhExstNAaz/NI6mQSY
BaUcsUAkM5CrrQAQj/lMCy8sH81RqFpzXrBlrC/N2yWIiCwNw/uPM/XOLq/Ma/Tc
g3k4Vy4FsXKYi0ckXiT7Id1oATCt+cE9lIpIF8SMVOyB0hdU0Duo8xwtFtVi4GTV
ReITtrmog3Xxf+iu94qlcExGkRCiy+0ZPMMIZ/hez2J+tT8F4isXUOAbP9vBLmf2
U2Ic4K1nR30mhUiSyQkwKiPDmGyq45muAHHDmPFF7bnP6xwsV+pCuLBr4hVR24Mw
+N25jOAG
-----END TSS2 PRIVATE KEY-----

$ openssl x509 -provider tpm2  -provider default  -in cert.pem -text -noout

Server

  • openssl c
gcc server.c -lcrypto -lssl -o server
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/provider.h>


int create_socket(int port)
{
    int s;
    struct sockaddr_in addr;

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    s = socket(AF_INET, SOCK_STREAM, 0);
    if (s < 0) {
        perror("Unable to create socket");
        exit(EXIT_FAILURE);
    }

    if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("Unable to bind");
        exit(EXIT_FAILURE);
    }

    if (listen(s, 1) < 0) {
        perror("Unable to listen");
        exit(EXIT_FAILURE);
    }

    return s;
}

SSL_CTX *create_context()
{
    const SSL_METHOD *method;
    SSL_CTX *ctx;

    method = TLS_server_method();

    ctx = SSL_CTX_new(method);
    if (!ctx) {
        perror("Unable to create SSL context");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    return ctx;
}

void configure_context(SSL_CTX *ctx)
{
    /* Set the key and cert */
    if (SSL_CTX_use_certificate_file(ctx, "cert.pem", SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    if (SSL_CTX_use_PrivateKey_file(ctx, "key.pem", SSL_FILETYPE_PEM) <= 0 ) {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char **argv)
{



    OSSL_PROVIDER* provider;

    provider = OSSL_PROVIDER_load(NULL, "default");
    if (provider == NULL) {
        printf("Failed to load Default provider\n");
        exit(EXIT_FAILURE);
    }
    printf("Default Provider name: %s\n", OSSL_PROVIDER_get0_name(provider));

    OSSL_PROVIDER* custom_provider = OSSL_PROVIDER_load(NULL, "tpm2");
    if (custom_provider == NULL) {
      perror("Could not create custom provider");
      exit(EXIT_FAILURE);
    }
    printf("Custom Provider name: %s\n", OSSL_PROVIDER_get0_name(custom_provider));



    int sock;
    SSL_CTX *ctx;

    /* Ignore broken pipe signals */
    signal(SIGPIPE, SIG_IGN);

    ctx = create_context();

    configure_context(ctx);

    sock = create_socket(4433);

    /* Handle connections */
    while(1) {
        struct sockaddr_in addr;
        unsigned int len = sizeof(addr);
        SSL *ssl;
        const char reply[] = "test\n";

        int client = accept(sock, (struct sockaddr*)&addr, &len);
        if (client < 0) {
            perror("Unable to accept");
            exit(EXIT_FAILURE);
        }

        ssl = SSL_new(ctx);
        SSL_set_fd(ssl, client);

        if (SSL_accept(ssl) <= 0) {
            ERR_print_errors_fp(stderr);
        } else {
            SSL_write(ssl, reply, strlen(reply));
        }

        SSL_shutdown(ssl);
        SSL_free(ssl);
        close(client);
    }

    close(sock);
    SSL_CTX_free(ctx);
}

  • python
import http.server
import ssl
import os

class HTTPServerRequestHandler(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        return http.server.SimpleHTTPRequestHandler.do_GET(self)

if __name__ == '__main__':
    httpd = http.server.HTTPServer(('localhost', 4433), HTTPServerRequestHandler)
    ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
    ssl_context.load_cert_chain(certfile='cert.pem', keyfile='key.pem')
    httpd.socket = ssl_context.wrap_socket(httpd.socket, server_side=True)

    print("Serving at https://localhost:4433")
    httpd.serve_forever()

Client

$ openssl s_client --connect localhost:4433

CONNECTED(00000003)
Can't use SSL_get_servername
depth=0 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
verify error:num=18:self-signed certificate
verify return:1
depth=0 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
verify return:1
---
Certificate chain
 0 s:C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
   i:C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Mar 17 11:20:18 2025 GMT; NotAfter: Mar 17 11:20:18 2026 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUEdXrJSw3yQWqAMrpFwQykfaDXUQwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNTAzMTcxMTIwMThaFw0yNjAz
MTcxMTIwMThaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQDJG+T726FJJ0239fFExky60NkgTo+9rXjUsFtYJvaw
wdBxGHNkzHJ903eKEexwaauMpAwvlNNUR9N5yGoW2U7AnVtnoyiJREvFxMRJRXoj
4EhppAFjR1uCNT43827bgT8WsTmhroIuqYH1Rr7j5I6ET9lcfPhCqtEqu+TMTMhZ
MsGA6cFdhmLH50YrqD1PgjDxxsf/pROIbgru1F3WuY9hiyBxEFD5e4f/x3hRP0tS
ZWQ6nypPxpPo68BSSSUFOiVlru2zIxqXJEI//SHbaCFuFSQGJQfEfAoBD6Xc4hOt
aDxCtiqLumgyvK+tFwcmTB8svZmH2uGGBOT3YtwM5UV7AgMBAAGjUzBRMB0GA1Ud
DgQWBBQVQCodV9VwfmIQ+1CaokkltQcP2DAfBgNVHSMEGDAWgBQVQCodV9VwfmIQ
+1CaokkltQcP2DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCE
mflQr7zoq3pgicnSO0V3XUQzNcMJz+WacCcLftmc78p/ggX5lpxjptUaMtsnHQIn
AyqkQ4SzNrugoP3ItEI9/v/u/sG0jNHQ7mh5hW3uvIk7p5tc/epAIgDjPY+gZlzb
Fk2eahsTPhZwktaTjfAkyD1zpKonmltXbSpj5tmkRy0Nv6d3p+OluU9RjyC5PyvP
g/Q0MwUs9hq64a+YlYobc4/IszubduS771qlmrxxjgzUVPUR6pHl+1ULjSlnOT44
udAC9aqsuWMVvJxhSJmsXAclqsc5gOqmFwx4CHVDnlMSGMJjVt7LnJo/Haw3OtT+
5pm8GR/ea7Pjloulu3zy
-----END CERTIFICATE-----
subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
issuer=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 1435 bytes and written 373 bytes
Verification error: self-signed certificate
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 18 (self-signed certificate)
---
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
    Protocol  : TLSv1.3
    Cipher    : TLS_AES_256_GCM_SHA384
    Session-ID: EB4C62ACA2DBCC01FD09ADA8AA620BF7DC7410C1DE581F9BEA19BBE14F369BFE
    Session-ID-ctx: 
    Resumption PSK: B93B01BE74E775A87E37C5178103E04A1C09DB67D95016C29C05F5EB051F19A0D2318784ABF8AC585DD3F6FD40D07BE1
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - b6 14 64 60 ea 5c ec 12-43 59 cd 66 6b 0a c4 e4   ..d`.\..CY.fk...
    0010 - c1 59 ab 6d 21 bc c7 fd-1e eb c3 a3 e2 f8 ac 8f   .Y.m!...........
    0020 - 0a 9e d9 4d f5 3d dd 6b-3b f8 13 59 cb 5e a8 b7   ...M.=.k;..Y.^..
    0030 - 38 bd bf 01 f3 0c 5d 59-40 c2 90 63 1d fa 26 cc   8.....][email protected]..&.
    0040 - ad e9 78 e6 d5 3c 39 f3-36 b8 4d 63 30 5a df 62   ..x..<9.6.Mc0Z.b
    0050 - f7 b1 97 2a f8 9a e4 1f-7c 6c 06 d9 e0 ff 9f de   ...*....|l......
    0060 - 2c 0c f5 10 aa 92 8a ca-4e 88 cb 03 c6 c8 b8 9b   ,.......N.......
    0070 - 65 5d d3 2f 4d ac e8 51-e9 5d 61 c7 ab f9 fe 80   e]./M..Q.]a.....
    0080 - 4b a9 87 be 39 47 88 68-96 37 a4 0f 9c 98 ea c9   K...9G.h.7......
    0090 - 94 3a 58 b5 f2 cb 3e 69-f8 96 95 d4 41 6d f6 6c   .:X...>i....Am.l
    00a0 - bd bf 4a 4c b4 ae 24 c5-77 a9 64 29 9a 76 00 f6   ..JL..$.w.d).v..
    00b0 - 39 8e 8e b2 44 ac eb e7-3c 4b 18 fc e3 ed 6c 36   9...D...<K....l6
    00c0 - 5d 6c 52 07 41 ec 57 1d-da e0 a2 2b 8a fa bf 62   ]lR.A.W....+...b

    Start Time: 1742210478
    Timeout   : 7200 (sec)
    Verify return code: 18 (self-signed certificate)
    Extended master secret: no
    Max Early Data: 0
---
read R BLOCK
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
    Protocol  : TLSv1.3
    Cipher    : TLS_AES_256_GCM_SHA384
    Session-ID: 509FD58BBB4B2492AB8CBDBBD8BF7BA5D816B3C05C15F104C8C283442E5AE378
    Session-ID-ctx: 
    Resumption PSK: 9BEA90B8715391F9D4466A067D0E8AFEEA77E2F5245D4032C56D1DA0DCA6677BD05BB423F1B731509883B3C3F7595339
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - b6 14 64 60 ea 5c ec 12-43 59 cd 66 6b 0a c4 e4   ..d`.\..CY.fk...
    0010 - bd a6 60 ce 3e 47 21 d6-cd 41 61 06 60 e6 98 70   ..`.>G!..Aa.`..p
    0020 - 3b c8 65 07 98 4c ba 34-5d 53 c6 38 10 71 c3 50   ;.e..L.4]S.8.q.P
    0030 - 87 d0 6b 1e 4e f3 ac 0b-cb 7d 67 2c 7a ac 4a e7   ..k.N....}g,z.J.
    0040 - d3 bd bd 13 29 20 1e 2f-29 92 c5 42 ad 8b 53 41   ....) ./)..B..SA
    0050 - 2a 2f a0 f6 e2 91 bf e3-5f 76 86 76 89 d4 bf aa   */......_v.v....
    0060 - 89 b6 28 29 92 bb eb 75-03 e7 88 13 95 85 96 71   ..()...u.......q
    0070 - b7 b2 eb a4 5d 53 1a c6-61 23 68 32 4d 43 8b 63   ....]S..a#h2MC.c
    0080 - 10 55 0a 26 4d cb 9f 6a-10 90 0d 8b e3 a8 02 96   .U.&M..j........
    0090 - 92 d6 11 89 4b 68 0d 1e-9f 88 64 87 37 d2 a6 03   ....Kh....d.7...
    00a0 - 6b 31 c2 06 aa 07 4b 28-4e 95 c5 e3 76 7c aa 6b   k1....K(N...v|.k
    00b0 - d1 8c c8 78 e6 51 c0 6d-f3 ad 55 27 b7 01 e7 dc   ...x.Q.m..U'....
    00c0 - 95 55 dd 5c 7c d0 4e 22-9a 75 b3 ec b1 f6 8c 6c   .U.\|.N".u.....l

    Start Time: 1742210478
    Timeout   : 7200 (sec)
    Verify return code: 18 (self-signed certificate)
    Extended master secret: no
    Max Early Data: 0
---
read R BLOCK
test
closed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment