From 0a5970752349f33865b4f141f9f6d2375bd8c92c Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Tue, 25 Sep 2012 21:55:46 +0000 Subject: [PATCH] - Added simple SSL session cache implementation - Revamped session resumption handling --- ChangeLog | 2 + include/polarssl/config.h | 14 ++- include/polarssl/ssl.h | 76 ++++++++++++----- include/polarssl/ssl_cache.h | 105 +++++++++++++++++++++++ library/CMakeLists.txt | 1 + library/Makefile | 4 +- library/ssl_cache.c | 152 +++++++++++++++++++++++++++++++++ library/ssl_cli.c | 12 +-- library/ssl_srv.c | 22 ++--- library/ssl_tls.c | 76 +++++++---------- programs/ssl/ssl_client1.c | 3 - programs/ssl/ssl_client2.c | 5 -- programs/ssl/ssl_fork_server.c | 91 -------------------- programs/ssl/ssl_mail_client.c | 8 -- programs/ssl/ssl_server.c | 99 ++++----------------- programs/ssl/ssl_server2.c | 101 ++++------------------ programs/test/ssl_test.c | 4 - programs/x509/cert_app.c | 5 -- 18 files changed, 408 insertions(+), 372 deletions(-) create mode 100644 include/polarssl/ssl_cache.h create mode 100644 library/ssl_cache.c diff --git a/ChangeLog b/ChangeLog index 5f51ff0df..d662bcf54 100644 --- a/ChangeLog +++ b/ChangeLog @@ -26,6 +26,7 @@ Features * Added PKCS#5 PBKDF2 key derivation function * Added Secure Renegotiation (RFC 5746) * Added predefined DHM groups from RFC 5114 + * Added simple SSL session cache implementation Changes * Removed redundant POLARSSL_DEBUG_MSG define @@ -38,6 +39,7 @@ Changes * Cipher layer cipher_mode_t POLARSSL_MODE_CFB128 is renamed to POLARSSL_MODE_CFB, to also handle different block size CFB modes. * Removed handling for SSLv2 Client Hello (as per RFC 5246 recommendation) + * Revamped session resumption handling Bugfix * Fixed handling error in mpi_cmp_mpi() on longer B values (found by diff --git a/include/polarssl/config.h b/include/polarssl/config.h index c5ac1c56d..538ef817d 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -3,7 +3,7 @@ * * \brief Configuration options (set of defines) * - * Copyright (C) 2006-2011, Brainspark B.V. + * Copyright (C) 2006-2012, Brainspark B.V. * * This file is part of PolarSSL (http://www.polarssl.org) * Lead Maintainer: Paul Bakker @@ -683,6 +683,18 @@ */ #define POLARSSL_SHA4_C +/** + * \def POLARSSL_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: POLARSSL_SSL_CACHE_C + */ +#define POLARSSL_SSL_CACHE_C + /** * \def POLARSSL_SSL_CLI_C * diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index dc2619ad0..fcf8a8ffe 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -284,7 +284,7 @@ typedef struct _ssl_transform ssl_transform; typedef struct _ssl_handshake_params ssl_handshake_params; /* - * This structure is used for session resuming. + * This structure is used for storing current session data. */ struct _ssl_session { @@ -295,7 +295,6 @@ struct _ssl_session unsigned char id[32]; /*!< session identifier */ unsigned char master[48]; /*!< the master secret */ x509_cert *peer_cert; /*!< peer X.509 cert chain */ - ssl_session *next; /*!< next session entry */ }; /* @@ -362,6 +361,8 @@ struct _ssl_handshake_params unsigned char randbytes[64]; /*!< random bytes */ unsigned char premaster[256]; /*!< premaster secret */ + + int resume; /*!< session resume indicator*/ }; struct _ssl_context @@ -386,24 +387,24 @@ struct _ssl_context int (*f_recv)(void *, unsigned char *, size_t); int (*f_send)(void *, const unsigned char *, size_t); int (*f_vrfy)(void *, x509_cert *, int, int); + int (*f_get_cache)(void *, ssl_session *); + int (*f_set_cache)(void *, const ssl_session *); void *p_rng; /*!< context for the RNG function */ void *p_dbg; /*!< context for the debug function */ void *p_recv; /*!< context for reading operations */ void *p_send; /*!< context for writing operations */ - void *p_vrfy; /*!< context for verification */ + void *p_vrfy; /*!< context for verification */ + void *p_get_cache; /*!< context for cache retrieval */ + void *p_set_cache; /*!< context for cache store */ /* * Session layer */ - int resume; /*!< session resuming flag */ - int timeout; /*!< sess. expiration time */ ssl_session *session_in; /*!< current session data (in) */ ssl_session *session_out; /*!< current session data (out) */ ssl_session *session; /*!< negotiated session data */ ssl_session *session_negotiate; /*!< session data in negotiation */ - int (*s_get)(ssl_context *); /*!< (server) get callback */ - int (*s_set)(ssl_context *); /*!< (server) set callback */ ssl_handshake_params *handshake; /*!< params required only during the handshake process */ @@ -636,26 +637,59 @@ void ssl_set_bio( ssl_context *ssl, int (*f_send)(void *, const unsigned char *, size_t), void *p_send ); /** - * \brief Set the session callbacks (server-side only) + * \brief Set the session cache callbacks (server-side only) + * If not set, no session resuming is done. * - * \param ssl SSL context - * \param s_get session get callback - * \param s_set session set callback + * The session cache has the responsibility to check for stale + * entries based on timeout. See RFC 5246 for recommendations. + * + * Warning: session.peer_cert is cleared by the SSL/TLS layer on + * connection shutdown, so do not cache the pointer! Either set + * it to NULL or make a full copy of the certificate. + * + * The get callback is called once during the initial handshake + * to enable session resuming. The get function has the + * following parameters: (void *parameter, ssl_session *session) + * If a valid entry is found, it should fill the master of + * the session object with the cached values and return 0, + * return 1 otherwise. Optionally peer_cert can be set as well + * if it is properly present in cache entry. + * + * The set callback is called once during the initial handshake + * to enable session resuming after the entire handshake has + * been finished. The set function has the following parameters: + * (void *parameter, const ssl_session *session). The function + * should create a cache entry for future retrieval based on + * the data in the session structure and should keep in mind + * that the ssl_session object presented (and all its referenced + * data) is cleared by the SSL/TLS layer when the connection is + * terminated. It is recommended to add metadata to determine if + * an entry is still valid in the future. Return 0 if + * successfully cached, return 0 otherwise. + * + * \param ssl SSL context + * \param f_get_cache session get callback + * \param p_get_cache session get parameter + * \param f_set_cache session set callback + * \param p_set_cache session set parameter */ -void ssl_set_scb( ssl_context *ssl, - int (*s_get)(ssl_context *), - int (*s_set)(ssl_context *) ); +void ssl_set_session_cache( ssl_context *ssl, + int (*f_get_cache)(void *, ssl_session *), void *p_get_cache, + int (*f_set_cache)(void *, const ssl_session *), void *p_set_cache ); /** - * \brief Set the session resuming flag, timeout and data + * \brief Request resumption of session (client-side only) + * Session data is copied from presented session structure. + * + * Warning: session.peer_cert is cleared by the SSL/TLS layer on + * connection shutdown, so do not cache the pointer! Either set + * it to NULL or make a full copy of the certificate when + * storing the session for use in this function. * * \param ssl SSL context - * \param resume if 0 (default), the session will not be resumed - * \param timeout session timeout in seconds, or 0 (no timeout) * \param session session context */ -void ssl_set_session( ssl_context *ssl, int resume, int timeout, - ssl_session *session ); +void ssl_set_session( ssl_context *ssl, const ssl_session *session ); /** * \brief Set the list of allowed ciphersuites @@ -900,8 +934,8 @@ int ssl_close_notify( ssl_context *ssl ); void ssl_free( ssl_context *ssl ); /** - * \brief Free referenced items in an SSL session and free all - * sessions in the chain. Memory is cleared + * \brief Free referenced items in an SSL session including the + * peer certificate and clear memory * * \param session SSL session */ diff --git a/include/polarssl/ssl_cache.h b/include/polarssl/ssl_cache.h new file mode 100644 index 000000000..e13c0875d --- /dev/null +++ b/include/polarssl/ssl_cache.h @@ -0,0 +1,105 @@ +/** + * \file ssl_cache.h + * + * \brief SSL session cache implementation + * + * Copyright (C) 2006-2012, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SSL_CACHE_H +#define POLARSSL_SSL_CACHE_H + +#include "ssl.h" + +#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _ssl_cache_context ssl_cache_context; +typedef struct _ssl_cache_entry ssl_cache_entry; + +/** + * \brief This structure is used for storing cache entries + */ +struct _ssl_cache_entry +{ + time_t timestamp; /*!< entry timestamp */ + ssl_session session; /*!< entry session */ + ssl_cache_entry *next; /*!< chain pointer */ +}; + +/** + * \brief Cache context + */ +struct _ssl_cache_context +{ + ssl_cache_entry *chain; /*!< start of the chain */ + int timeout; /*!< cache timeout */ +}; + +/** + * \brief Initialize an SSL cache context + * + * \param cache SSL cache context + */ +void ssl_cache_init( ssl_cache_context *cache ); + +/** + * \brief Cache get callback implementation + * + * \param data SSL cache context + * \param session session to retrieve entry for + */ +int ssl_cache_get( void *data, ssl_session *session ); + +/** + * \brief Cache set callback implementation + * + * \param data SSL cache context + * \param session session to store entry for + */ +int ssl_cache_set( void *data, const ssl_session *session ); + +/** + * \brief Set the cache timeout + * (Default: SSL_CACHE_DEFAULT_TIMEOUT (1 day)) + * + * A timeout of 0 indicates no timeout. + * + * \param cache SSL cache context + * \param timeout cache entry timeout + */ +void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout ); + +/** + * \brief Free referenced items in a cache context and clear memory + * + * \param cache SSL cache context + */ +void ssl_cache_free( ssl_cache_context *cache ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cache.h */ diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 7a0cedf35..b75766906 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -35,6 +35,7 @@ set(src sha1.c sha2.c sha4.c + ssl_cache.c ssl_cli.c ssl_srv.c ssl_tls.c diff --git a/library/Makefile b/library/Makefile index 56148a009..cd25c5190 100644 --- a/library/Makefile +++ b/library/Makefile @@ -44,10 +44,10 @@ OBJS= aes.o arc4.o asn1parse.o \ padlock.o pbkdf2.o pem.o \ pkcs11.o \ rsa.o sha1.o sha2.o \ - sha4.o ssl_cli.o ssl_srv.o \ + sha4.o ssl_cache.o ssl_cli.o \ + ssl_srv.o \ ssl_tls.o timing.o version.o \ x509parse.o x509write.o xtea.o - .SILENT: diff --git a/library/ssl_cache.c b/library/ssl_cache.c new file mode 100644 index 000000000..203a4b786 --- /dev/null +++ b/library/ssl_cache.c @@ -0,0 +1,152 @@ +/* + * SSL session cache implementation + * + * Copyright (C) 2006-2012, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#include "polarssl/config.h" + +#if defined(POLARSSL_SSL_CACHE_C) + +#include "polarssl/ssl_cache.h" + +#include + +void ssl_cache_init( ssl_cache_context *cache ) +{ + memset( cache, 0, sizeof( ssl_cache_context ) ); + + cache->timeout = SSL_CACHE_DEFAULT_TIMEOUT; +} + +int ssl_cache_get( void *data, ssl_session *session ) +{ + time_t t = time( NULL ); + ssl_cache_context *cache = (ssl_cache_context *) data; + ssl_cache_entry *cur, *entry; + + cur = cache->chain; + entry = NULL; + + while( cur != NULL ) + { + entry = cur; + cur = cur->next; + + if( cache->timeout != 0 && + (int) ( t - entry->timestamp ) > cache->timeout ) + continue; + + if( session->ciphersuite != entry->session.ciphersuite || + session->compression != entry->session.compression || + session->length != entry->session.length ) + continue; + + if( memcmp( session->id, entry->session.id, + entry->session.length ) != 0 ) + continue; + + memcpy( session->master, entry->session.master, 48 ); + return( 0 ); + } + + return( 1 ); +} + +int ssl_cache_set( void *data, const ssl_session *session ) +{ + time_t t = time( NULL ); + ssl_cache_context *cache = (ssl_cache_context *) data; + ssl_cache_entry *cur, *prv; + + cur = cache->chain; + prv = NULL; + + while( cur != NULL ) + { + if( cache->timeout != 0 && + (int) ( t - cur->timestamp ) > cache->timeout ) + { + cur->timestamp = t; + break; /* expired, reuse this slot, update timestamp */ + } + + if( memcmp( session->id, cur->session.id, cur->session.length ) == 0 ) + break; /* client reconnected, keep timestamp for session id */ + + prv = cur; + cur = cur->next; + } + + if( cur == NULL ) + { + cur = (ssl_cache_entry *) malloc( sizeof( ssl_cache_entry ) ); + if( cur == NULL ) + return( 1 ); + + memset( cur, 0, sizeof( ssl_cache_entry ) ); + + if( prv == NULL ) + cache->chain = cur; + else + prv->next = cur; + + cur->timestamp = t; + } + + memcpy( &cur->session, session, sizeof( ssl_session ) ); + + // Do not include peer_cert in cache entry + // + cur->session.peer_cert = NULL; + + return( 0 ); +} + +void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout ) +{ + if( timeout < 0 ) timeout = 0; + + cache->timeout = timeout; +} + +void ssl_cache_free( ssl_cache_context *cache ) +{ + ssl_cache_entry *cur, *prv; + + cur = cache->chain; + + while( cur != NULL ) + { + prv = cur; + cur = cur->next; + + ssl_session_free( &prv->session ); + free( prv ); + } +} + +#endif /* POLARSSL_SSL_CACHE_C */ diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 570785fdf..b44af2ba3 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -111,9 +111,8 @@ static int ssl_write_client_hello( ssl_context *ssl ) */ n = ssl->session_negotiate->length; - if( n < 16 || n > 32 || ssl->resume == 0 || - ( ssl->timeout != 0 && - t - ssl->session_negotiate->start > ssl->timeout ) ) + if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE || n < 16 || n > 32 || + ssl->handshake->resume == 0 ) n = 0; *p++ = (unsigned char) n; @@ -473,14 +472,15 @@ static int ssl_parse_server_hello( ssl_context *ssl ) /* * Check if the session can be resumed */ - if( ssl->resume == 0 || n == 0 || + if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE || + ssl->handshake->resume == 0 || n == 0 || ssl->session_negotiate->ciphersuite != i || ssl->session_negotiate->compression != comp || ssl->session_negotiate->length != n || memcmp( ssl->session_negotiate->id, buf + 39, n ) != 0 ) { ssl->state++; - ssl->resume = 0; + ssl->handshake->resume = 0; ssl->session_negotiate->start = time( NULL ); ssl->session_negotiate->ciphersuite = i; ssl->session_negotiate->compression = comp; @@ -499,7 +499,7 @@ static int ssl_parse_server_hello( ssl_context *ssl ) } SSL_DEBUG_MSG( 3, ( "%s session has been resumed", - ssl->resume ? "a" : "no" ) ); + ssl->handshake->resume ? "a" : "no" ) ); SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d", i ) ); SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[41 + n] ) ); diff --git a/library/ssl_srv.c b/library/ssl_srv.c index c28716c11..64b0d2df4 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -456,21 +456,16 @@ static int ssl_write_server_hello( ssl_context *ssl ) ssl->session_negotiate->length = n = 32; *p++ = (unsigned char) ssl->session_negotiate->length; - if( ssl->s_get == NULL || - ssl->s_get( ssl ) != 0 ) + if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE || + ssl->f_get_cache == NULL || + ssl->f_get_cache( ssl->p_get_cache, ssl->session_negotiate ) != 0 ) { /* * Not found, create a new session id */ - ssl->resume = 0; + ssl->handshake->resume = 0; ssl->state++; - if( ssl->session_negotiate == NULL ) - { - SSL_DEBUG_MSG( 1, ( "No session struct set" ) ); - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - } - if( ( ret = ssl->f_rng( ssl->p_rng, ssl->session_negotiate->id, n ) ) != 0 ) return( ret ); @@ -478,9 +473,9 @@ static int ssl_write_server_hello( ssl_context *ssl ) else { /* - * Found a matching session, resume it + * Found a matching session, resuming it */ - ssl->resume = 1; + ssl->handshake->resume = 1; ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC; if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) @@ -496,7 +491,7 @@ static int ssl_write_server_hello( ssl_context *ssl ) SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); SSL_DEBUG_MSG( 3, ( "%s session has been resumed", - ssl->resume ? "a" : "no" ) ); + ssl->handshake->resume ? "a" : "no" ) ); *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 ); *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite ); @@ -987,9 +982,6 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) return( ret ); } - if( ssl->s_set != NULL ) - ssl->s_set( ssl ); - ssl->state++; SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 7e638cd7d..61920042b 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -317,7 +317,7 @@ int ssl_derive_keys( ssl_context *ssl ) * TLSv1: * master = PRF( premaster, "master secret", randbytes )[0..47] */ - if( ssl->resume == 0 ) + if( handshake->resume == 0 ) { SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, handshake->pmslen ); @@ -2641,25 +2641,21 @@ void ssl_handshake_wrapup( ssl_context *ssl ) ssl->transform = ssl->transform_negotiate; ssl->transform_negotiate = NULL; - /* - * Migrate data to existing session structure (in chain) - * Step 1. Clear existing data (but not the rest of the chain) - * Step 2. Migrate data to existing object in chain - * Step 3. Remove negotiation session object without removing items pointed - * to - */ - ssl->session_negotiate->next = ssl->session->next; - ssl->session->next = NULL; - ssl_session_free( ssl->session ); - - memcpy( ssl->session, ssl->session_negotiate, sizeof(ssl_session) ); - ssl->session_in = ssl->session; - ssl->session_out = ssl->session; - - memset( ssl->session_negotiate, 0, sizeof(ssl_session) ); - free( ssl->session_negotiate ); + if( ssl->session ) + { + ssl_session_free( ssl->session ); + free( ssl->session ); + } + ssl->session = ssl->session_negotiate; ssl->session_negotiate = NULL; + /* + * Add cache entry + */ + if( ssl->f_set_cache != NULL ) + if( ssl->f_set_cache( ssl->p_set_cache, ssl->session ) != 0 ) + SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); + ssl->state++; SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); @@ -2687,7 +2683,7 @@ int ssl_write_finished( ssl_context *ssl ) * In case of session resuming, invert the client and server * ChangeCipherSpec messages order. */ - if( ssl->resume != 0 ) + if( ssl->handshake->resume != 0 ) { if( ssl->endpoint == SSL_IS_CLIENT ) ssl->state = SSL_HANDSHAKE_WRAPUP; @@ -2765,7 +2761,7 @@ int ssl_parse_finished( ssl_context *ssl ) ssl->verify_data_len = hash_len; memcpy( ssl->peer_verify_data, buf, hash_len ); - if( ssl->resume != 0 ) + if( ssl->handshake->resume != 0 ) { if( ssl->endpoint == SSL_IS_CLIENT ) ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC; @@ -2970,20 +2966,20 @@ void ssl_set_bio( ssl_context *ssl, ssl->p_send = p_send; } -void ssl_set_scb( ssl_context *ssl, - int (*s_get)(ssl_context *), - int (*s_set)(ssl_context *) ) +void ssl_set_session_cache( ssl_context *ssl, + int (*f_get_cache)(void *, ssl_session *), void *p_get_cache, + int (*f_set_cache)(void *, const ssl_session *), void *p_set_cache ) { - ssl->s_get = s_get; - ssl->s_set = s_set; + ssl->f_get_cache = f_get_cache; + ssl->p_get_cache = p_get_cache; + ssl->f_set_cache = f_set_cache; + ssl->p_set_cache = p_set_cache; } -void ssl_set_session( ssl_context *ssl, int resume, int timeout, - ssl_session *session ) +void ssl_set_session( ssl_context *ssl, const ssl_session *session ) { - ssl->resume = resume; - ssl->timeout = timeout; - ssl->session = session; + memcpy( ssl->session_negotiate, session, sizeof(ssl_session) ); + ssl->handshake->resume = 1; } void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites ) @@ -3687,23 +3683,13 @@ void ssl_handshake_free( ssl_handshake_params *handshake ) void ssl_session_free( ssl_session *session ) { - ssl_session *cur = session, *prv; - - while( cur != NULL ) + if( session->peer_cert != NULL ) { - prv = cur; - cur = cur->next; - - if( prv->peer_cert != NULL ) - { - x509_free( prv->peer_cert ); - free( prv->peer_cert ); - } - - memset( prv, 0, sizeof( ssl_session ) ); - if( prv != session ) - free( prv ); + x509_free( session->peer_cert ); + free( session->peer_cert ); } + + memset( session, 0, sizeof( ssl_session ) ); } /* diff --git a/programs/ssl/ssl_client1.c b/programs/ssl/ssl_client1.c index 9bd578d15..3cd05ab52 100644 --- a/programs/ssl/ssl_client1.c +++ b/programs/ssl/ssl_client1.c @@ -78,7 +78,6 @@ int main( int argc, char *argv[] ) entropy_context entropy; ctr_drbg_context ctr_drbg; ssl_context ssl; - ssl_session ssn; ((void) argc); ((void) argv); @@ -86,7 +85,6 @@ int main( int argc, char *argv[] ) /* * 0. Initialize the RNG and the session data */ - memset( &ssn, 0, sizeof( ssl_session ) ); memset( &ssl, 0, sizeof( ssl_context ) ); printf( "\n . Seeding the random number generator..." ); @@ -141,7 +139,6 @@ int main( int argc, char *argv[] ) net_send, &server_fd ); ssl_set_ciphersuites( &ssl, ssl_default_ciphersuites ); - ssl_set_session( &ssl, 1, 600, &ssn ); /* * 3. Write the GET request diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 0c962f210..4c4cf3e71 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -131,7 +131,6 @@ int main( int argc, char *argv[] ) entropy_context entropy; ctr_drbg_context ctr_drbg; ssl_context ssl; - ssl_session ssn; x509_cert cacert; x509_cert clicert; rsa_context rsa; @@ -144,7 +143,6 @@ int main( int argc, char *argv[] ) * Make sure memory references are valid. */ server_fd = 0; - memset( &ssn, 0, sizeof( ssl_session ) ); memset( &ssl, 0, sizeof( ssl_context ) ); memset( &cacert, 0, sizeof( x509_cert ) ); memset( &clicert, 0, sizeof( x509_cert ) ); @@ -389,8 +387,6 @@ int main( int argc, char *argv[] ) ssl_set_renegotiation( &ssl, opt.renegotiation ); ssl_legacy_renegotiation( &ssl, opt.allow_legacy ); - ssl_set_session( &ssl, 1, 600, &ssn ); - ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name ); ssl_set_own_cert( &ssl, &clicert, &rsa ); @@ -518,7 +514,6 @@ exit: x509_free( &clicert ); x509_free( &cacert ); rsa_free( &rsa ); - ssl_session_free( &ssn ); ssl_free( &ssl ); memset( &ssl, 0, sizeof( ssl ) ); diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c index 416d4bf18..0ef3cf98c 100644 --- a/programs/ssl/ssl_fork_server.c +++ b/programs/ssl/ssl_fork_server.c @@ -126,80 +126,6 @@ void my_debug( void *ctx, int level, const char *str ) } } -/* - * These session callbacks use a simple chained list - * to store and retrieve the session information. - */ -ssl_session *s_list_1st = NULL; -ssl_session *cur, *prv; - -static int my_get_session( ssl_context *ssl ) -{ - time_t t = time( NULL ); - - if( ssl->resume == 0 ) - return( 1 ); - - cur = s_list_1st; - prv = NULL; - - while( cur != NULL ) - { - prv = cur; - cur = cur->next; - - if( ssl->timeout != 0 && t - prv->start > ssl->timeout ) - continue; - - if( ssl->session->ciphersuite != prv->ciphersuite || - ssl->session->length != prv->length ) - continue; - - if( memcmp( ssl->session->id, prv->id, prv->length ) != 0 ) - continue; - - memcpy( ssl->session->master, prv->master, 48 ); - return( 0 ); - } - - return( 1 ); -} - -static int my_set_session( ssl_context *ssl ) -{ - time_t t = time( NULL ); - - cur = s_list_1st; - prv = NULL; - - while( cur != NULL ) - { - if( ssl->timeout != 0 && t - cur->start > ssl->timeout ) - break; /* expired, reuse this slot */ - - if( memcmp( ssl->session->id, cur->id, cur->length ) == 0 ) - break; /* client reconnected */ - - prv = cur; - cur = cur->next; - } - - if( cur == NULL ) - { - cur = (ssl_session *) malloc( sizeof( ssl_session ) ); - if( cur == NULL ) - return( 1 ); - - if( prv == NULL ) - s_list_1st = cur; - else prv->next = cur; - } - - memcpy( cur, ssl->session, sizeof( ssl_session ) ); - - return( 0 ); -} - int main( int argc, char *argv[] ) { int ret, len, cnt = 0, pid; @@ -211,7 +137,6 @@ int main( int argc, char *argv[] ) entropy_context entropy; ctr_drbg_context ctr_drbg; ssl_context ssl; - ssl_session ssn; x509_cert srvcert; rsa_context rsa; @@ -369,13 +294,8 @@ int main( int argc, char *argv[] ) ssl_set_dbg( &ssl, my_debug, stdout ); ssl_set_bio( &ssl, net_recv, &client_fd, net_send, &client_fd ); - ssl_set_scb( &ssl, my_get_session, - my_set_session ); ssl_set_ciphersuites( &ssl, my_ciphersuites ); - ssl_set_session( &ssl, 1, 0, &ssn ); - - memset( &ssn, 0, sizeof( ssl_session ) ); ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL ); ssl_set_own_cert( &ssl, &srvcert, &rsa ); @@ -482,17 +402,6 @@ exit: rsa_free( &rsa ); ssl_free( &ssl ); - cur = s_list_1st; - while( cur != NULL ) - { - prv = cur; - cur = cur->next; - memset( prv, 0, sizeof( ssl_session ) ); - free( prv ); - } - - memset( &ssl, 0, sizeof( ssl_context ) ); - #if defined(_WIN32) printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c index ea7068c0d..a94d38a24 100644 --- a/programs/ssl/ssl_mail_client.c +++ b/programs/ssl/ssl_mail_client.c @@ -349,7 +349,6 @@ int main( int argc, char *argv[] ) entropy_context entropy; ctr_drbg_context ctr_drbg; ssl_context ssl; - ssl_session ssn; x509_cert cacert; x509_cert clicert; rsa_context rsa; @@ -362,8 +361,6 @@ int main( int argc, char *argv[] ) * Make sure memory references are valid. */ server_fd = 0; - memset( &ssn, 0, sizeof( ssl_session ) ); - memset( &ssl, 0, sizeof( ssl_context ) ); memset( &cacert, 0, sizeof( x509_cert ) ); memset( &clicert, 0, sizeof( x509_cert ) ); memset( &rsa, 0, sizeof( rsa_context ) ); @@ -607,8 +604,6 @@ int main( int argc, char *argv[] ) else ssl_set_ciphersuites( &ssl, opt.force_ciphersuite ); - ssl_set_session( &ssl, 1, 600, &ssn ); - ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name ); ssl_set_own_cert( &ssl, &clicert, &rsa ); @@ -804,11 +799,8 @@ exit: x509_free( &clicert ); x509_free( &cacert ); rsa_free( &rsa ); - ssl_session_free( &ssn ); ssl_free( &ssl ); - memset( &ssl, 0, sizeof( ssl ) ); - #if defined(_WIN32) printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c index a8855b8c2..070d5347c 100644 --- a/programs/ssl/ssl_server.c +++ b/programs/ssl/ssl_server.c @@ -45,6 +45,10 @@ #include "polarssl/net.h" #include "polarssl/error.h" +#if defined(POLARSSL_SSL_CACHE_C) +#include "polarssl/ssl_cache.h" +#endif + #define HTTP_RESPONSE \ "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ "

PolarSSL Test Server

\r\n" \ @@ -153,80 +157,6 @@ void my_debug( void *ctx, int level, const char *str ) } } -/* - * These session callbacks use a simple chained list - * to store and retrieve the session information. - */ -ssl_session *s_list_1st = NULL; -ssl_session *cur, *prv; - -static int my_get_session( ssl_context *ssl ) -{ - time_t t = time( NULL ); - - if( ssl->resume == 0 ) - return( 1 ); - - cur = s_list_1st; - prv = NULL; - - while( cur != NULL ) - { - prv = cur; - cur = cur->next; - - if( ssl->timeout != 0 && (int) ( t - prv->start ) > ssl->timeout ) - continue; - - if( ssl->session->ciphersuite != prv->ciphersuite || - ssl->session->length != prv->length ) - continue; - - if( memcmp( ssl->session->id, prv->id, prv->length ) != 0 ) - continue; - - memcpy( ssl->session->master, prv->master, 48 ); - return( 0 ); - } - - return( 1 ); -} - -static int my_set_session( ssl_context *ssl ) -{ - time_t t = time( NULL ); - - cur = s_list_1st; - prv = NULL; - - while( cur != NULL ) - { - if( ssl->timeout != 0 && (int) ( t - cur->start ) > ssl->timeout ) - break; /* expired, reuse this slot */ - - if( memcmp( ssl->session->id, cur->id, cur->length ) == 0 ) - break; /* client reconnected */ - - prv = cur; - cur = cur->next; - } - - if( cur == NULL ) - { - cur = (ssl_session *) malloc( sizeof( ssl_session ) ); - if( cur == NULL ) - return( 1 ); - - if( prv == NULL ) - s_list_1st = cur; - else prv->next = cur; - } - - memcpy( cur, ssl->session, sizeof( ssl_session ) ); - - return( 0 ); -} - #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_CERTS_C) || \ !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_SSL_TLS_C) || \ !defined(POLARSSL_SSL_SRV_C) || !defined(POLARSSL_NET_C) || \ @@ -254,14 +184,17 @@ int main( int argc, char *argv[] ) entropy_context entropy; ctr_drbg_context ctr_drbg; ssl_context ssl; - ssl_session ssn; x509_cert srvcert; rsa_context rsa; ((void) argc); ((void) argv); - memset( &ssl, 0, sizeof( ssl_context ) ); +#if defined(POLARSSL_SSL_CACHE_C) + ssl_cache_context cache; + + ssl_cache_init( &cache ); +#endif /* * 1. Load the certificates and private RSA key @@ -351,13 +284,12 @@ int main( int argc, char *argv[] ) ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg ); ssl_set_dbg( &ssl, my_debug, stdout ); - ssl_set_scb( &ssl, my_get_session, - my_set_session ); +#if defined(POLARSSL_SSL_CACHE_C) + ssl_set_session_cache( &ssl, ssl_cache_get, &cache, + ssl_cache_set, &cache ); +#endif ssl_set_ciphersuites( &ssl, my_ciphersuites ); - ssl_set_session( &ssl, 1, 0, &ssn ); - - memset( &ssn, 0, sizeof( ssl_session ) ); ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL ); ssl_set_own_cert( &ssl, &srvcert, &rsa ); @@ -527,9 +459,10 @@ exit: net_close( client_fd ); x509_free( &srvcert ); rsa_free( &rsa ); - ssl_session_free( &ssn ); - ssl_session_free( s_list_1st ); ssl_free( &ssl ); +#if defined(POLARSSL_SSL_CACHE_C) + ssl_cache_free( &cache ); +#endif #if defined(_WIN32) printf( " Press Enter to exit this program.\n" ); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index bc5402f8d..6f97de31b 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -45,6 +45,10 @@ #include "polarssl/x509.h" #include "polarssl/error.h" +#if defined(POLARSSL_SSL_CACHE_C) +#include "polarssl/ssl_cache.h" +#endif + #define DFL_SERVER_PORT 4433 #define DFL_REQUEST_PAGE "/" #define DFL_DEBUG_LEVEL 0 @@ -94,80 +98,6 @@ void my_debug( void *ctx, int level, const char *str ) } } -/* - * These session callbacks use a simple chained list - * to store and retrieve the session information. - */ -ssl_session *s_list_1st = NULL; -ssl_session *cur, *prv; - -static int my_get_session( ssl_context *ssl ) -{ - time_t t = time( NULL ); - - if( ssl->resume == 0 ) - return( 1 ); - - cur = s_list_1st; - prv = NULL; - - while( cur != NULL ) - { - prv = cur; - cur = cur->next; - - if( ssl->timeout != 0 && (int) ( t - prv->start ) > ssl->timeout ) - continue; - - if( ssl->session->ciphersuite != prv->ciphersuite || - ssl->session->length != prv->length ) - continue; - - if( memcmp( ssl->session->id, prv->id, prv->length ) != 0 ) - continue; - - memcpy( ssl->session->master, prv->master, 48 ); - return( 0 ); - } - - return( 1 ); -} - -static int my_set_session( ssl_context *ssl ) -{ - time_t t = time( NULL ); - - cur = s_list_1st; - prv = NULL; - - while( cur != NULL ) - { - if( ssl->timeout != 0 && (int) ( t - cur->start ) > ssl->timeout ) - break; /* expired, reuse this slot */ - - if( memcmp( ssl->session->id, cur->id, cur->length ) == 0 ) - break; /* client reconnected */ - - prv = cur; - cur = cur->next; - } - - if( cur == NULL ) - { - cur = (ssl_session *) malloc( sizeof( ssl_session ) ); - if( cur == NULL ) - return( 1 ); - - if( prv == NULL ) - s_list_1st = cur; - else prv->next = cur; - } - - memcpy( cur, ssl->session, sizeof( ssl_session ) ); - - return( 0 ); -} - #if defined(POLARSSL_FS_IO) #define USAGE_IO \ " ca_file=%%s default: \"\" (pre-loaded)\n" \ @@ -218,10 +148,12 @@ int main( int argc, char *argv[] ) entropy_context entropy; ctr_drbg_context ctr_drbg; ssl_context ssl; - ssl_session ssn; x509_cert cacert; x509_cert srvcert; rsa_context rsa; +#if defined(POLARSSL_SSL_CACHE_C) + ssl_cache_context cache; +#endif int i; size_t j, n; @@ -232,11 +164,12 @@ int main( int argc, char *argv[] ) * Make sure memory references are valid. */ listen_fd = 0; - memset( &ssn, 0, sizeof( ssl_session ) ); - memset( &ssl, 0, sizeof( ssl_context ) ); memset( &cacert, 0, sizeof( x509_cert ) ); memset( &srvcert, 0, sizeof( x509_cert ) ); memset( &rsa, 0, sizeof( rsa_context ) ); +#if defined(POLARSSL_SSL_CACHE_C) + ssl_cache_init( &cache ); +#endif if( argc == 0 ) { @@ -455,8 +388,10 @@ int main( int argc, char *argv[] ) ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg ); ssl_set_dbg( &ssl, my_debug, stdout ); - ssl_set_scb( &ssl, my_get_session, - my_set_session ); +#if defined(POLARSSL_SSL_CACHE_C) + ssl_set_session_cache( &ssl, ssl_cache_get, &cache, + ssl_cache_set, &cache ); +#endif if( opt.force_ciphersuite[0] == DFL_FORCE_CIPHER ) ssl_set_ciphersuites( &ssl, ssl_default_ciphersuites ); @@ -466,8 +401,6 @@ int main( int argc, char *argv[] ) ssl_set_renegotiation( &ssl, opt.renegotiation ); ssl_legacy_renegotiation( &ssl, opt.allow_legacy ); - ssl_set_session( &ssl, 1, 0, &ssn ); - ssl_set_ca_chain( &ssl, &cacert, NULL, NULL ); ssl_set_own_cert( &ssl, &srvcert, &rsa ); @@ -673,10 +606,12 @@ exit: x509_free( &srvcert ); x509_free( &cacert ); rsa_free( &rsa ); - ssl_session_free( &ssn ); - ssl_session_free( s_list_1st ); ssl_free( &ssl ); +#if defined(POLARSSL_SSL_CACHE_C) + ssl_cache_free( &cache ); +#endif + #if defined(_WIN32) printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); diff --git a/programs/test/ssl_test.c b/programs/test/ssl_test.c index 59fab01a7..802fda0c2 100644 --- a/programs/test/ssl_test.c +++ b/programs/test/ssl_test.c @@ -167,7 +167,6 @@ static int ssl_test( struct options *opt ) entropy_context entropy; ctr_drbg_context ctr_drbg; ssl_context ssl; - ssl_session ssn; x509_cert srvcert; rsa_context rsa; @@ -273,9 +272,6 @@ static int ssl_test( struct options *opt ) ssl_set_bio( &ssl, net_recv, &client_fd, net_send, &client_fd ); - ssl_set_session( &ssl, opt->session_reuse, - opt->session_lifetime, &ssn ); - if( opt->force_ciphersuite[0] == DFL_FORCE_CIPHER ) ssl_set_ciphersuites( &ssl, ssl_default_ciphersuites ); else ssl_set_ciphersuites( &ssl, opt->force_ciphersuite ); diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c index 18c23b28d..a0610b370 100644 --- a/programs/x509/cert_app.c +++ b/programs/x509/cert_app.c @@ -108,7 +108,6 @@ int main( int argc, char *argv[] ) entropy_context entropy; ctr_drbg_context ctr_drbg; ssl_context ssl; - ssl_session ssn; x509_cert clicert; rsa_context rsa; int i, j, n; @@ -119,8 +118,6 @@ int main( int argc, char *argv[] ) * Set to sane values */ server_fd = 0; - memset( &ssl, 0, sizeof( ssl_context ) ); - memset( &ssn, 0, sizeof( ssl_session ) ); memset( &clicert, 0, sizeof( x509_cert ) ); memset( &rsa, 0, sizeof( rsa_context ) ); @@ -288,7 +285,6 @@ int main( int argc, char *argv[] ) net_send, &server_fd ); ssl_set_ciphersuites( &ssl, ssl_default_ciphersuites ); - ssl_set_session( &ssl, 1, 600, &ssn ); ssl_set_own_cert( &ssl, &clicert, &rsa ); @@ -333,7 +329,6 @@ exit: net_close( server_fd ); x509_free( &clicert ); rsa_free( &rsa ); - ssl_session_free( &ssn ); ssl_free( &ssl ); #if defined(_WIN32)