Skip to content

Instantly share code, notes, and snippets.

@salrashid123
Created February 13, 2025 11:49
Show Gist options
  • Save salrashid123/e14497bf87834cf5cd2dd8ed8fc6b2b7 to your computer and use it in GitHub Desktop.
Save salrashid123/e14497bf87834cf5cd2dd8ed8fc6b2b7 to your computer and use it in GitHub Desktop.
TLS PSK with opennsl C

TLS 1.2, 1.3 PSK with C

also see

$ gcc server.c -lcrypto -lssl -o server
k$ ./server

OpenSSL 3.3.2 3 Sep 2024 (Library: OpenSSL 3.3.0 9 Apr 2024)
built on: Tue Jan 14 12:15:04 2025 UTC
platform: linux-x86_64
options:  bn(64,64)
client random:
95 63 CE 74 D2 56 D3 B4 E0 F4 4B 16 C9 05 6F FE
CB 88 A0 CF 7A 9E D1 47 E5 43 69 F0 36 4A 05 EA
server random:
89 FB DE 08 F2 0E 09 C8 EC 32 AD AA 6B 58 16 F9
BF 08 6C 15 2C 6C 6E 87 A7 C7 8D 3C 89 F1 D5 00


$ gcc client.c -lcrypto -lssl -o client
$ ./client
OpenSSL 3.3.2 3 Sep 2024 (Library: OpenSSL 3.3.0 9 Apr 2024)
built on: Tue Jan 14 12:15:04 2025 UTC
platform: linux-x86_64
options:  bn(64,64)
client random:
95 63 CE 74 D2 56 D3 B4 E0 F4 4B 16 C9 05 6F FE
CB 88 A0 CF 7A 9E D1 47 E5 43 69 F0 36 4A 05 EA
server random:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
test

  • server.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/hmac.h>


#include <stdlib.h>





void handleErrors(void)
{
    unsigned long errCode;

    printf("An error occurred\n");
    while(errCode = ERR_get_error())
    {
        char *err = ERR_error_string(errCode, NULL);
        printf("%s\n", err);
    }
    abort();
}

#define PSK_ID "Client1"
#define PSK_KEY "6d1bbd1e6235c9d9ec8cdbdf9b32d4d08304a7f305f7c6c67775130d914f4dc4"


unsigned int tls_psk_serv_cb(SSL *ssl, const char *id,
                                            unsigned char *psk,
                                            unsigned int max_psk_len)
{
    if (strcmp(PSK_ID, id) != 0) {
        printf("Unknown Client's PSK ID\n");
        goto err;
    }
    if (strlen(PSK_KEY) > max_psk_len) {
        printf("Insufficient buffer size to copy PSK_KEY\n");
        goto err;
    }

    unsigned char outc[SSL3_RANDOM_SIZE];
    SSL_get_client_random(ssl, outc, SSL3_RANDOM_SIZE);
    printf("client random:\n"); 
    for (int z = 0; z < SSL3_RANDOM_SIZE; z++) {
       printf("%02X%c", outc[z], ((z + 1) % 16) ? ' ' : '\n');
    }


    unsigned char outs[SSL3_RANDOM_SIZE];
    SSL_get_server_random(ssl, outs, SSL3_RANDOM_SIZE);
    printf("server random:\n");
    for (int z = 0; z < SSL3_RANDOM_SIZE; z++) {
       printf("%02X%c", outs[z], ((z + 1) % 16) ? ' ' : '\n');
    }

    memcpy(psk, PSK_KEY, strlen(PSK_KEY));
    return strlen(PSK_KEY);
err:
    return 0;
}


int main(int argc, char **argv)
{
    int sock;
    SSL_CTX *ctx;

    printf("%s (Library: %s)\n",
               OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
    printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON));
    printf("%s\n", OpenSSL_version(OPENSSL_PLATFORM));
    
    printf("options: ");
    printf(" %s", BN_options());
    printf("\n");
    
    ctx = SSL_CTX_new(TLS_server_method());
    if (!ctx) {
        perror("Unable to create SSL context");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
	SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
	SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);    
	//SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION);
	//SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);

    struct sockaddr_in addr;

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

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

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

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

    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);

        SSL_set_psk_server_callback(ssl, tls_psk_serv_cb);
        

        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);
}

  • client.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/hmac.h>


#include <stdlib.h>





void handleErrors(void)
{
    unsigned long errCode;

    printf("An error occurred\n");
    while(errCode = ERR_get_error())
    {
        char *err = ERR_error_string(errCode, NULL);
        printf("%s\n", err);
    }
    abort();
}

#define PSK_ID "Client1"
#define PSK_KEY "6d1bbd1e6235c9d9ec8cdbdf9b32d4d08304a7f305f7c6c67775130d914f4dc4"


unsigned int tls_psk_client_cb(SSL *ssl,
                                                const char *hint,
                                                char *id,
                                                unsigned int max_identity_len,
                                                unsigned char *psk,
                                                unsigned int max_psk_len)
{

    memcpy(id, PSK_ID, strlen(PSK_ID));

    unsigned char outc[SSL3_RANDOM_SIZE];
    SSL_get_client_random(ssl, outc, SSL3_RANDOM_SIZE);
    printf("client random:\n"); 
    for (int z = 0; z < SSL3_RANDOM_SIZE; z++) {
       printf("%02X%c", outc[z], ((z + 1) % 16) ? ' ' : '\n');
    }


    unsigned char outs[SSL3_RANDOM_SIZE];
    SSL_get_server_random(ssl, outs, SSL3_RANDOM_SIZE);
    printf("server random:\n");
    for (int z = 0; z < SSL3_RANDOM_SIZE; z++) {
       printf("%02X%c", outs[z], ((z + 1) % 16) ? ' ' : '\n');
    }

    memcpy(psk, PSK_KEY, strlen(PSK_KEY));
    return strlen(PSK_KEY);
err:
    return 0;
}


int main(int argc, char **argv)
{
    SSL_CTX *ctx;
    BIO *web = NULL, *out = NULL;
    SSL *ssl = NULL;

    long res = 1;

    printf("%s (Library: %s)\n",
               OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
    printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON));
    printf("%s\n", OpenSSL_version(OPENSSL_PLATFORM));
    
    printf("options: ");
    printf(" %s", BN_options());
    printf("\n");
    
    ctx = SSL_CTX_new(TLS_client_method());
    if (!ctx) {
        perror("Unable to create SSL context");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
	SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
	SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);    
	// SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION);
	// SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);

    web = BIO_new_ssl_connect(ctx);
    if(!(web != NULL)) handleErrors();

    res = BIO_set_conn_hostname(web, "127.0.0.1:8081");
    if(!(1 == res)) handleErrors();

    BIO_get_ssl(web, &ssl);
    if(!(ssl != NULL)) handleErrors();
    SSL_set_psk_client_callback(ssl, tls_psk_client_cb);

    // const char PREFERRED_CIPHERS[] = "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256";
    // res = SSL_set_cipher_list(ssl, PREFERRED_CIPHERS);
    // if(!(1 == res)) handleErrors();

    out = BIO_new_fp(stdout, BIO_NOCLOSE);
    if(!(NULL != out)) handleErrors();

    res = BIO_do_connect(web);
    if(!(1 == res)) handleErrors();

    res = BIO_do_handshake(web);
    if(!(1 == res)) handleErrors();


    int len = 0;
    do
    {
    char buff[1536] = {};
    len = BIO_read(web, buff, sizeof(buff));
                
    if(len > 0)
        BIO_write(out, buff, len);

    } while (len > 0 || BIO_should_retry(web));

    if(out)
    BIO_free(out);

    if(web != NULL)
    BIO_free_all(web);


    SSL_CTX_free(ctx);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment