Created
August 1, 2023 11:18
-
-
Save danielealbano/d78aeb131074c8071b17a5b70e3bb537 to your computer and use it in GitHub Desktop.
openssl vs mbedtls handshake performances
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compile with | |
// gcc -O3 -o mbedtls-server-test mbedtls-server-test.c -lmbedtls -lmbedx509 -lmbedcrypto | |
// mbedtls from Ubuntu 22.10 | |
#if !defined(MBEDTLS_CONFIG_FILE) | |
#include "mbedtls/config.h" | |
#else | |
#include MBEDTLS_CONFIG_FILE | |
#endif | |
#if defined(MBEDTLS_PLATFORM_C) | |
#include "mbedtls/platform.h" | |
#else | |
#include <stdio.h> | |
#include <stdlib.h> | |
#define mbedtls_time time | |
#define mbedtls_time_t time_t | |
#define mbedtls_fprintf fprintf | |
#define mbedtls_printf printf | |
#define mbedtls_exit exit | |
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS | |
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE | |
#endif | |
#include <stdlib.h> | |
#include <string.h> | |
#include "mbedtls/entropy.h" | |
#include "mbedtls/ctr_drbg.h" | |
#include "mbedtls/certs.h" | |
#include "mbedtls/x509.h" | |
#include "mbedtls/ssl.h" | |
#include "mbedtls/net_sockets.h" | |
#include "mbedtls/error.h" | |
#include "mbedtls/debug.h" | |
static char *HTTP_RESPONSE = "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h2>Hello world!</h2>\r\n"; | |
static size_t HTTP_RESPONSE_LENGTH; | |
int main( void ) { | |
HTTP_RESPONSE_LENGTH = strlen(HTTP_RESPONSE); | |
int ret, len; | |
mbedtls_net_context listen_fd, client_fd; | |
unsigned char buf[1024]; | |
const char *pers = "ssl_server"; | |
mbedtls_entropy_context entropy; | |
mbedtls_ctr_drbg_context ctr_drbg; | |
mbedtls_ssl_context ssl; | |
mbedtls_ssl_config conf; | |
mbedtls_x509_crt srvcert; | |
mbedtls_pk_context pkey; | |
mbedtls_net_init( &listen_fd ); | |
mbedtls_net_init( &client_fd ); | |
mbedtls_ssl_init( &ssl ); | |
mbedtls_ssl_config_init( &conf ); | |
mbedtls_x509_crt_init( &srvcert ); | |
mbedtls_pk_init( &pkey ); | |
mbedtls_entropy_init( &entropy ); | |
mbedtls_ctr_drbg_init( &ctr_drbg ); | |
ret = mbedtls_x509_crt_parse_file(&srvcert, "cert.pem"); | |
if( ret != 0 ) | |
{ | |
mbedtls_printf( "mbedtls_x509_crt_parse returned %d\n\n", ret ); | |
goto exit; | |
} | |
ret = mbedtls_pk_parse_keyfile( &pkey, "cert.key", NULL); | |
if( ret != 0 ) | |
{ | |
mbedtls_printf( "mbedtls_pk_parse_key returned %d\n\n", ret ); | |
goto exit; | |
} | |
if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "12345", MBEDTLS_NET_PROTO_TCP ) ) != 0 ) | |
{ | |
mbedtls_printf( "mbedtls_net_bind returned %d\n\n", ret ); | |
goto exit; | |
} | |
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, | |
(const unsigned char *) pers, | |
strlen( pers ) ) ) != 0 ) | |
{ | |
mbedtls_printf( "mbedtls_ctr_drbg_seed returned %d\n", ret ); | |
goto exit; | |
} | |
if( ( ret = mbedtls_ssl_config_defaults( &conf, | |
MBEDTLS_SSL_IS_SERVER, | |
MBEDTLS_SSL_TRANSPORT_STREAM, | |
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) | |
{ | |
mbedtls_printf( "mbedtls_ssl_config_defaults returned %d\n\n", ret ); | |
goto exit; | |
} | |
// Set mbedtls min and max version to TLS 1.2 | |
mbedtls_ssl_conf_min_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3 ); | |
mbedtls_ssl_conf_max_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3 ); | |
// Set the mbed curve to Curve25519 | |
const mbedtls_ecp_group_id curve_info[2] = { MBEDTLS_ECP_DP_CURVE25519, 0 }; | |
mbedtls_ssl_conf_curves( &conf, curve_info ); | |
// Set the cipher to ECDHE-RSA-AES256-GCM-SHA384,2048,256 | |
const int ciphersuites[2] = { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 0 }; | |
mbedtls_ssl_conf_ciphersuites( &conf, ciphersuites ); | |
mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); | |
mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL ); | |
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 ) | |
{ | |
mbedtls_printf( "mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); | |
goto exit; | |
} | |
if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) | |
{ | |
mbedtls_printf( "mbedtls_ssl_setup returned %d\n\n", ret ); | |
goto exit; | |
} | |
reset: | |
if( ret != 0 ) | |
{ | |
char error_buf[100]; | |
mbedtls_strerror( ret, error_buf, 100 ); | |
mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf ); | |
} | |
mbedtls_net_free( &client_fd ); | |
mbedtls_ssl_session_reset( &ssl ); | |
if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, | |
NULL, 0, NULL ) ) != 0 ) | |
{ | |
mbedtls_printf( "mbedtls_net_accept returned %d\n\n", ret ); | |
goto exit; | |
} | |
mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); | |
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) | |
{ | |
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) | |
{ | |
mbedtls_printf( "mbedtls_ssl_handshake returned %d\n\n", ret ); | |
goto reset; | |
} | |
} | |
do | |
{ | |
len = sizeof( buf ) - 1; | |
memset( buf, 0, sizeof( buf ) ); | |
ret = mbedtls_ssl_read( &ssl, buf, len ); | |
if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) | |
continue; | |
if( ret <= 0 ) | |
{ | |
switch( ret ) | |
{ | |
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: | |
mbedtls_printf( "connection was closed gracefully\n" ); | |
break; | |
case MBEDTLS_ERR_NET_CONN_RESET: | |
mbedtls_printf( "connection was reset by peer\n" ); | |
break; | |
default: | |
mbedtls_printf( "mbedtls_ssl_read returned -0x%x\n", -ret ); | |
break; | |
} | |
break; | |
} | |
if( ret > 0 ) | |
break; | |
} | |
while( 1 ); | |
while( ( ret = mbedtls_ssl_write( &ssl, HTTP_RESPONSE, HTTP_RESPONSE_LENGTH ) ) <= 0 ) | |
{ | |
if( ret == MBEDTLS_ERR_NET_CONN_RESET ) | |
{ | |
goto reset; | |
} | |
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) | |
{ | |
mbedtls_printf( "mbedtls_ssl_write returned %d\n\n", ret ); | |
goto exit; | |
} | |
} | |
while( ( ret = mbedtls_ssl_close_notify( &ssl ) ) < 0 ) | |
{ | |
if( ret != MBEDTLS_ERR_SSL_WANT_READ && | |
ret != MBEDTLS_ERR_SSL_WANT_WRITE ) | |
{ | |
mbedtls_printf( "mbedtls_ssl_close_notify returned %d\n\n", ret ); | |
goto reset; | |
} | |
} | |
ret = 0; | |
goto reset; | |
exit: | |
if( ret != 0 ) | |
{ | |
char error_buf[100]; | |
mbedtls_strerror( ret, error_buf, 100 ); | |
mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf ); | |
} | |
mbedtls_net_free( &client_fd ); | |
mbedtls_net_free( &listen_fd ); | |
mbedtls_x509_crt_free( &srvcert ); | |
mbedtls_pk_free( &pkey ); | |
mbedtls_ssl_free( &ssl ); | |
mbedtls_ssl_config_free( &conf ); | |
mbedtls_ctr_drbg_free( &ctr_drbg ); | |
mbedtls_entropy_free( &entropy ); | |
return ret; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// mbedtls | |
$ ab -l -c 1 -t 10 https://localhost:12345/ | |
This is ApacheBench, Version 2.3 <$Revision: 1901567 $> | |
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ | |
Licensed to The Apache Software Foundation, http://www.apache.org/ | |
Benchmarking localhost (be patient) | |
Finished 223 requests | |
Server Software: | |
Server Hostname: localhost | |
Server Port: 12345 | |
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256 | |
Server Temp Key: X25519 253 bits | |
TLS Server Name: localhost | |
Document Path: / | |
Document Length: Variable | |
Concurrency Level: 1 | |
Time taken for tests: 10.009 seconds | |
Complete requests: 223 | |
Failed requests: 0 | |
Total transferred: 14941 bytes | |
HTML transferred: 5129 bytes | |
Requests per second: 22.28 [#/sec] (mean) | |
Time per request: 44.884 [ms] (mean) | |
Time per request: 44.884 [ms] (mean, across all concurrent requests) | |
Transfer rate: 1.46 [Kbytes/sec] received | |
Connection Times (ms) | |
min mean[+/-sd] median max | |
Connect: 44 45 1.5 44 52 | |
Processing: 0 0 0.0 0 0 | |
Waiting: 0 0 0.0 0 0 | |
Total: 44 45 1.5 44 52 | |
Percentage of the requests served within a certain time (ms) | |
50% 44 | |
66% 44 | |
75% 44 | |
80% 44 | |
90% 48 | |
95% 48 | |
98% 48 | |
99% 48 | |
100% 52 (longest request) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compile with | |
// gcc -O3 -o openssl-server-test openssl-server-test.c -lssl -lcrypto | |
// OpenSSL from Ubuntu 22.10 | |
//SSL-Server.c | |
#include <errno.h> | |
#include <unistd.h> | |
#include <malloc.h> | |
#include <string.h> | |
#include <arpa/inet.h> | |
#include <sys/socket.h> | |
#include <sys/types.h> | |
#include <netinet/in.h> | |
#include <resolv.h> | |
#include "openssl/ssl.h" | |
#include "openssl/err.h" | |
#define FAIL -1 | |
static char *HTTP_RESPONSE = "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h2>Hello world!</h2>\r\n"; | |
static size_t HTTP_RESPONSE_LENGTH; | |
int OpenListener(int port) | |
{ int sd; | |
struct sockaddr_in addr; | |
sd = socket(PF_INET, SOCK_STREAM, 0); | |
bzero(&addr, sizeof(addr)); | |
addr.sin_family = AF_INET; | |
addr.sin_port = htons(port); | |
addr.sin_addr.s_addr = INADDR_ANY; | |
if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) | |
{ | |
perror("can't bind port"); | |
abort(); | |
} | |
if ( listen(sd, 10) != 0 ) | |
{ | |
perror("Can't configure listening port"); | |
abort(); | |
} | |
return sd; | |
} | |
SSL_CTX* InitServerCTX(void) | |
{ | |
const SSL_METHOD *method; | |
SSL_CTX *ctx; | |
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */ | |
SSL_load_error_strings(); /* load all error messages */ | |
method = TLS_server_method(); | |
ctx = SSL_CTX_new(method); /* create new context from method */ | |
if(ctx == NULL) | |
{ | |
ERR_print_errors_fp(stderr); | |
abort(); | |
} | |
SSL_CTX_set_cipher_list(ctx, "ALL:eNULL"); | |
return ctx; | |
} | |
void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile) | |
{ | |
//New lines | |
if (SSL_CTX_load_verify_locations(ctx, CertFile, KeyFile) != 1) | |
ERR_print_errors_fp(stderr); | |
if (SSL_CTX_set_default_verify_paths(ctx) != 1) | |
ERR_print_errors_fp(stderr); | |
//End new lines | |
/* set the local certificate from CertFile */ | |
if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0) | |
{ | |
ERR_print_errors_fp(stderr); | |
abort(); | |
} | |
/* set the private key from KeyFile (may be the same as CertFile) */ | |
// SSL_CTX_set_default_passwd_cb_userdata(ctx, "12345678"); | |
if (SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0) | |
{ | |
ERR_print_errors_fp(stderr); | |
abort(); | |
} | |
/* verify private key */ | |
if (!SSL_CTX_check_private_key(ctx)) | |
{ | |
fprintf(stderr, "Private key does not match the public certificate\n"); | |
abort(); | |
} | |
//New lines - Force the client-side have a certificate | |
//SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); | |
//SSL_CTX_set_verify_depth(ctx, 4); | |
//End new lines | |
} | |
void ShowCerts(SSL* ssl) | |
{ | |
X509 *cert; | |
char *line; | |
cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */ | |
if ( cert != NULL ) | |
{ | |
printf("Server certificates:\n"); | |
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); | |
printf("Subject: %s\n", line); | |
free(line); | |
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); | |
printf("Issuer: %s\n", line); | |
free(line); | |
X509_free(cert); | |
} | |
else | |
printf("No certificates.\n"); | |
} | |
void Servlet(SSL* ssl) /* Serve the connection -- threadable */ | |
{ | |
char buf[1024]; | |
int sd, bytes; | |
if ( SSL_accept(ssl) == FAIL ) /* do SSL-protocol accept */ | |
ERR_print_errors_fp(stderr); | |
else | |
{ | |
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */ | |
if ( bytes > 0 ) | |
{ | |
buf[bytes] = 0; | |
SSL_write(ssl, HTTP_RESPONSE, HTTP_RESPONSE_LENGTH); /* send reply */ | |
} | |
else | |
ERR_print_errors_fp(stderr); | |
} | |
sd = SSL_get_fd(ssl); /* get socket connection */ | |
SSL_shutdown(ssl); /* shutdown SSL connection */ | |
SSL_free(ssl); /* release SSL state */ | |
close(sd); /* close connection */ | |
} | |
int main(int argc, char **argv) | |
{ | |
HTTP_RESPONSE_LENGTH = strlen(HTTP_RESPONSE); | |
SSL_CTX *ctx; | |
int server; | |
char portnum[]="12345"; | |
char CertFile[] = "cert.pem"; | |
char KeyFile[] = "cert.key"; | |
SSL_library_init(); | |
ctx = InitServerCTX(); /* initialize SSL */ | |
LoadCertificates(ctx, CertFile, KeyFile); /* load certs */ | |
server = OpenListener(atoi(portnum)); /* create server socket */ | |
// Set the min version and the max version to TLS 1.2 | |
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); | |
SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION); | |
// Set the cipher to ECDHE-RSA-AES256-GCM-SHA384 | |
SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES256-GCM-SHA384"); | |
// Set the curve to x25519 | |
SSL_CTX_set1_curves_list(ctx, "X25519"); | |
while (1) | |
{ | |
struct sockaddr_in addr; | |
socklen_t len = sizeof(addr); | |
SSL *ssl; | |
int client = accept(server, (struct sockaddr*)&addr, &len); /* accept connection as usual */ | |
// printf("Connection: %s:%d\n",inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); | |
ssl = SSL_new(ctx); /* get new SSL state with context */ | |
SSL_set_fd(ssl, client); /* set connection socket to SSL state */ | |
Servlet(ssl); /* service connection */ | |
} | |
close(server); /* close server socket */ | |
SSL_CTX_free(ctx); /* release context */ | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ ab -l -c 1 -t 10 https://localhost:12345/ | |
This is ApacheBench, Version 2.3 <$Revision: 1901567 $> | |
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ | |
Licensed to The Apache Software Foundation, http://www.apache.org/ | |
Benchmarking localhost (be patient) | |
Completed 5000 requests | |
Finished 6360 requests | |
Server Software: | |
Server Hostname: localhost | |
Server Port: 12345 | |
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256 | |
Server Temp Key: X25519 253 bits | |
TLS Server Name: localhost | |
Document Path: / | |
Document Length: Variable | |
Concurrency Level: 1 | |
Time taken for tests: 10.000 seconds | |
Complete requests: 6360 | |
Failed requests: 0 | |
Total transferred: 426120 bytes | |
HTML transferred: 146280 bytes | |
Requests per second: 635.99 [#/sec] (mean) | |
Time per request: 1.572 [ms] (mean) | |
Time per request: 1.572 [ms] (mean, across all concurrent requests) | |
Transfer rate: 41.61 [Kbytes/sec] received | |
Connection Times (ms) | |
min mean[+/-sd] median max | |
Connect: 1 2 0.1 1 3 | |
Processing: 0 0 0.0 0 0 | |
Waiting: 0 0 0.0 0 0 | |
Total: 2 2 0.1 2 3 | |
ERROR: The median and mean for the initial connection time are more than twice the standard | |
deviation apart. These results are NOT reliable. | |
Percentage of the requests served within a certain time (ms) | |
50% 2 | |
66% 2 | |
75% 2 | |
80% 2 | |
90% 2 | |
95% 2 | |
98% 2 | |
99% 2 | |
100% 3 (longest request) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment