From cf4c0bba3446ce3e735a9fc4616ef366678c5808 Mon Sep 17 00:00:00 2001 From: slaff Date: Mon, 21 Nov 2016 21:03:24 +0100 Subject: [PATCH] Added initial support for max fragment size extension. (#25) Refactored the code to support more SSL extensions in the future. --- ssl/ssl.h | 20 ++++++++++++++++++-- ssl/tls1.c | 34 ++++++++++++++++++++++++++++++--- ssl/tls1.h | 8 +++++++- ssl/tls1_clnt.c | 50 ++++++++++++++++++++++++++++++------------------- 4 files changed, 87 insertions(+), 25 deletions(-) diff --git a/ssl/ssl.h b/ssl/ssl.h index 9bf91b39b..4869fa879 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -225,6 +225,22 @@ EXP_FUNC SSL_CTX * STDCALL ssl_ctx_new(uint32_t options, int num_sessions); */ EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx); +/** + * @brief Allocates new SSL extensions structure and returns pointer to it + * + * @return ssl_ext Pointer to SSL_EXTENSIONS structure + * + */ +EXP_FUNC SSL_EXTENSIONS * STDCALL ssl_ext_new(); + +/** + * @brief Frees SSL extensions structure + * + * @param ssl_ext [in] Pointer to SSL_EXTENSION structure + * + */ +EXP_FUNC void STDCALL ssl_ext_free(SSL_EXTENSIONS *ssl_ext); + /** * @brief (server only) Establish a new SSL connection to an SSL client. * @@ -251,11 +267,11 @@ EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd); * can be null if no session resumption is being used or required. This option * is not used in skeleton mode. * @param sess_id_size The size of the session id (max 32) - * @param host_name If non-zero, host name to be sent to server for SNI support + * @param ssl_ext pointer to a structure with the activated SSL extensions and their values * @return An SSL object reference. Use ssl_handshake_status() to check * if a handshake succeeded. */ -EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id, uint8_t sess_id_size, const char* host_name); +EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id, uint8_t sess_id_size, SSL_EXTENSIONS* ssl_ext); /** * @brief Free any used resources on this connection. diff --git a/ssl/tls1.c b/ssl/tls1.c index ccb253a9b..0cf2e4c2f 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -139,6 +139,35 @@ void DISPLAY_BYTES(SSL *ssl, const char *format, const uint8_t *data, int size, ...) {} #endif +/** + * Allocates new SSL extensions structure and returns pointer to it + * + */ +EXP_FUNC SSL_EXTENSIONS * STDCALL ssl_ext_new() +{ + SSL_EXTENSIONS *ssl_ext = (SSL_EXTENSIONS *)malloc(sizeof(SSL_EXTENSIONS)); + ssl_ext->max_fragment_size = 0; + ssl_ext->host_name = NULL; + + return ssl_ext; +} + +/** + * Allocates new SSL extensions structure and returns pointer to it + * + */ +EXP_FUNC void STDCALL ssl_ext_free(SSL_EXTENSIONS *ssl_ext) +{ + if(ssl_ext == NULL ) { + return; + } + + if(ssl_ext->host_name != NULL) { + free(ssl_ext->host_name); + } + free(ssl_ext); +} + /** * Establish a new client/server context. */ @@ -257,7 +286,8 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl) disposable_free(ssl); certificate_free(ssl); free(ssl->bm_all_data); - free(ssl->host_name); + ssl_ext_free(ssl->extensions); + ssl->extensions = NULL; free(ssl); } @@ -631,8 +661,6 @@ SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd) ssl->encrypt_ctx = malloc(sizeof(AES_CTX)); ssl->decrypt_ctx = malloc(sizeof(AES_CTX)); - ssl->host_name = NULL; - SSL_CTX_UNLOCK(ssl_ctx->mutex); return ssl; } diff --git a/ssl/tls1.h b/ssl/tls1.h index d62bdb258..6565625ae 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -120,6 +120,7 @@ enum enum { SSL_EXT_SERVER_NAME = 0, + SSL_EXT_MAX_FRAGMENT_SIZE, SSL_EXT_SIG_ALG = 0x0d, }; @@ -172,6 +173,11 @@ typedef struct uint8_t key_block_generated; } DISPOSABLE_CTX; +typedef struct { + char *host_name; /* Needed for the SNI support */ + uint16_t max_fragment_size; /* Needed for the Max Fragment Size Extension. Allowed values: 2^9, 2^10 .. 2^14 */ +} SSL_EXTENSIONS; + struct _SSL { uint32_t flag; @@ -213,7 +219,7 @@ struct _SSL uint8_t read_sequence[8]; /* 64 bit sequence number */ uint8_t write_sequence[8]; /* 64 bit sequence number */ uint8_t hmac_header[SSL_RECORD_SIZE]; /* rx hmac */ - char *host_name; /* Needed for the SNI support */ + SSL_EXTENSIONS *extensions; /* Contains the SSL (client) extensions */ }; typedef struct _SSL SSL; diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index 81738cfb4..fab26676a 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -64,7 +64,7 @@ static int send_cert_verify(SSL *ssl); * Establish a new SSL connection to an SSL server. */ EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const - uint8_t *session_id, uint8_t sess_id_size, const char* host_name) + uint8_t *session_id, uint8_t sess_id_size, SSL_EXTENSIONS* ssl_ext) { SSL *ssl = ssl_new(ssl_ctx, client_fd); ssl->version = SSL_PROTOCOL_VERSION_MAX; /* try top version first */ @@ -82,9 +82,7 @@ EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const SET_SSL_FLAG(SSL_SESSION_RESUME); /* just flag for later */ } - if(host_name != NULL && strlen(host_name) > 0) { - ssl->host_name = (char *)strdup(host_name); - } + ssl->extensions = ssl_ext; SET_SSL_FLAG(SSL_IS_CLIENT); do_client_connect(ssl); @@ -259,22 +257,36 @@ static int send_client_hello(SSL *ssl) ext_len += sizeof(g_sig_alg); } - /* send the host name if specified */ - if (ssl->host_name != NULL) { - unsigned int host_len = strlen(ssl->host_name); + if (ssl->extensions != NULL) { + /* send the host name if specified */ + if (ssl->extensions->host_name != NULL) { + unsigned int host_len = strlen(ssl->extensions->host_name); - buf[offset++] = 0; - buf[offset++] = SSL_EXT_SERVER_NAME; /* server_name(0) (65535) */ - buf[offset++] = 0; - buf[offset++] = host_len+5; /* server_name length */ - buf[offset++] = 0; - buf[offset++] = host_len+3; /* server_list length */ - buf[offset++] = 0; /* host_name(0) (255) */ - buf[offset++] = 0; - buf[offset++] = host_len; /* host_name length */ - strncpy((char*) &buf[offset], ssl->host_name, host_len); - offset += host_len; - ext_len += host_len + 9; + buf[offset++] = 0; + buf[offset++] = SSL_EXT_SERVER_NAME; /* server_name(0) (65535) */ + buf[offset++] = 0; + buf[offset++] = host_len + 5; /* server_name length */ + buf[offset++] = 0; + buf[offset++] = host_len + 3; /* server_list length */ + buf[offset++] = 0; /* host_name(0) (255) */ + buf[offset++] = 0; + buf[offset++] = host_len; /* host_name length */ + strncpy((char*) &buf[offset], ssl->extensions->host_name, host_len); + offset += host_len; + ext_len += host_len + 9; + } + + if (ssl->extensions->max_fragment_size) { + buf[offset++] = 0; + buf[offset++] = SSL_EXT_MAX_FRAGMENT_SIZE; + + buf[offset++] = 0; // size of data + buf[offset++] = 2; + + buf[offset++] = (uint8_t)((ssl->extensions->max_fragment_size >> 8) & 0xff); + buf[offset++] = (uint8_t)(ssl->extensions->max_fragment_size & 0xff); + ext_len += 6; + } } if(ext_len > 0) {