From 48916f9b670999e53f73f2c6085128ade47eafd8 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 16 Sep 2012 19:57:18 +0000 Subject: [PATCH] - Added Secure Renegotiation (RFC 5746) --- ChangeLog | 3 +- include/polarssl/ssl.h | 229 +++++-- library/ssl_cli.c | 341 +++++++--- library/ssl_srv.c | 351 +++++++--- library/ssl_tls.c | 1090 +++++++++++++++++++------------- programs/ssl/ssl_client2.c | 26 +- programs/ssl/ssl_fork_server.c | 2 + programs/ssl/ssl_mail_client.c | 4 +- programs/ssl/ssl_server.c | 20 +- programs/x509/cert_app.c | 6 +- 10 files changed, 1405 insertions(+), 667 deletions(-) diff --git a/ChangeLog b/ChangeLog index fc19198a8..821e8d863 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,7 +13,7 @@ Features * Added key_app_writer example application * Added cert_req example application * Added base Galois Counter Mode (GCM) for AES - * Added TLS 1.2 support + * Added TLS 1.2 support (RFC 5246) * Added GCM suites to TLS 1.2 (RFC 5288) * Added commandline error code convertor (util/strerror) * Added support for Hardware Acceleration hooking in SSL/TLS @@ -24,6 +24,7 @@ Features * Added DEFLATE compression support as per RFC3749 (requires zlib) * Added blowfish algorithm (Generic and cipher layer) * Added PKCS#5 PBKDF2 key derivation function + * Added Secure Renegotiation (RFC 5746) Changes * Removed redundant POLARSSL_DEBUG_MSG define diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 2201bde81..3d6e42c80 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -30,7 +30,6 @@ #include #include "net.h" -#include "dhm.h" #include "rsa.h" #include "md5.h" #include "sha1.h" @@ -39,6 +38,10 @@ #include "x509.h" #include "config.h" +#if defined(POLARSSL_DHM_C) +#include "dhm.h" +#endif + #if defined(POLARSSL_PKCS11_C) #include "pkcs11.h" #endif @@ -110,6 +113,18 @@ #define SSL_VERIFY_OPTIONAL 1 #define SSL_VERIFY_REQUIRED 2 +#define SSL_INITIAL_HANDSHAKE 0 +#define SSL_RENEGOTIATION 1 + +#define SSL_LEGACY_RENEGOTIATION 0 +#define SSL_SECURE_RENEGOTIATION 1 + +#define SSL_RENEGOTIATION_ENABLED 0 +#define SSL_RENEGOTIATION_DISABLED 1 + +#define SSL_NO_LEGACY_RENEGOTIATION 0 +#define SSL_ALLOW_LEGACY_RENEGOTIATION 1 + #define SSL_MAX_CONTENT_LEN 16384 /* @@ -164,6 +179,8 @@ #define SSL_EDH_RSA_AES_128_GCM_SHA256 0x9E #define SSL_EDH_RSA_AES_256_GCM_SHA384 0x9F +#define SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ + /* * Supported Signature and Hash algorithms (For TLS 1.2) */ @@ -233,6 +250,8 @@ #define TLS_EXT_SIG_ALG 13 +#define TLS_EXT_RENEGOTIATION_INFO 0xFF01 + /* * SSL state machine */ @@ -253,12 +272,15 @@ typedef enum SSL_SERVER_CHANGE_CIPHER_SPEC, SSL_SERVER_FINISHED, SSL_FLUSH_BUFFERS, + SSL_HANDSHAKE_WRAPUP, SSL_HANDSHAKE_OVER } ssl_states; typedef struct _ssl_session ssl_session; typedef struct _ssl_context ssl_context; +typedef struct _ssl_transform ssl_transform; +typedef struct _ssl_handshake_params ssl_handshake_params; /* * This structure is used for session resuming. @@ -271,15 +293,83 @@ struct _ssl_session size_t length; /*!< session id length */ 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 */ }; +/* + * This structure contains a full set of runtime transform parameters + * either in negotiation or active. + */ +struct _ssl_transform +{ + /* + * Session specific crypto layer + */ + unsigned int keylen; /*!< symmetric key length */ + size_t minlen; /*!< min. ciphertext length */ + size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ + size_t maclen; /*!< MAC length */ + + unsigned char iv_enc[16]; /*!< IV (encryption) */ + unsigned char iv_dec[16]; /*!< IV (decryption) */ + + unsigned char mac_enc[32]; /*!< MAC (encryption) */ + unsigned char mac_dec[32]; /*!< MAC (decryption) */ + + unsigned long ctx_enc[134]; /*!< encryption context */ + unsigned long ctx_dec[134]; /*!< decryption context */ + + /* + * Session specific compression layer + */ +#if defined(POLARSSL_ZLIB_SUPPORT) + z_stream ctx_deflate; /*!< compression context */ + z_stream ctx_inflate; /*!< decompression context */ +#endif +}; + +/* + * This structure contains the parameters only needed during handshake. + */ +struct _ssl_handshake_params +{ + /* + * Handshake specific crypto variables + */ +#if defined(POLARSSL_DHM_C) + dhm_context dhm_ctx; /*!< DHM key exchange */ +#endif + + /* + * Checksum contexts + */ + md5_context fin_md5; + sha1_context fin_sha1; + sha2_context fin_sha2; + sha4_context fin_sha4; + + void (*update_checksum)(ssl_context *, unsigned char *, size_t); + void (*calc_verify)(ssl_context *, unsigned char *); + void (*calc_finished)(ssl_context *, unsigned char *, int); + int (*tls_prf)(unsigned char *, size_t, char *, + unsigned char *, size_t, + unsigned char *, size_t); + + size_t pmslen; /*!< premaster length */ + + unsigned char randbytes[64]; /*!< random bytes */ + unsigned char premaster[256]; /*!< premaster secret */ +}; + struct _ssl_context { /* * Miscellaneous */ int state; /*!< SSL handshake: current state */ + int renegotiation; /*!< Initial or renegotiation */ int major_ver; /*!< equal to SSL_MAJOR_VERSION_3 */ int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ @@ -307,10 +397,24 @@ struct _ssl_context */ int resume; /*!< session resuming flag */ int timeout; /*!< sess. expiration time */ - ssl_session *session; /*!< current session data */ + 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 */ + + /* + * Record layer transformations + */ + ssl_transform *transform_in; /*!< current transform params (in) */ + ssl_transform *transform_out; /*!< current transform params (in) */ + ssl_transform *transform; /*!< negotiated transform params */ + ssl_transform *transform_negotiate; /*!< transform params in negotiation */ + /* * Record layer (incoming data) */ @@ -347,51 +451,22 @@ struct _ssl_context x509_cert *own_cert; /*!< own X.509 certificate */ x509_cert *ca_chain; /*!< own trusted CA chain */ x509_crl *ca_crl; /*!< trusted CA CRLs */ - x509_cert *peer_cert; /*!< peer X.509 cert chain */ const char *peer_cn; /*!< expected peer CN */ + /* + * User settings + */ int endpoint; /*!< 0: client, 1: server */ int authmode; /*!< verification mode */ int client_auth; /*!< flag for client auth. */ int verify_result; /*!< verification result */ - - /* - * Crypto layer - */ - dhm_context dhm_ctx; /*!< DHM key exchange */ - unsigned char ctx_checksum[500]; /*!< Checksum context(s) */ - - void (*update_checksum)(ssl_context *, unsigned char *, size_t); - void (*calc_verify)(ssl_context *, unsigned char *); - void (*calc_finished)(ssl_context *, unsigned char *, int); - int (*tls_prf)(unsigned char *, size_t, char *, - unsigned char *, size_t, - unsigned char *, size_t); - - int do_crypt; /*!< en(de)cryption flag */ + int disable_renegotiation; /*!< enable/disable renegotiation */ + int allow_legacy_renegotiation; /*!< allow legacy renegotiation */ const int *ciphersuites; /*!< allowed ciphersuites */ - size_t pmslen; /*!< premaster length */ - unsigned int keylen; /*!< symmetric key length */ - size_t minlen; /*!< min. ciphertext length */ - size_t ivlen; /*!< IV length */ - size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ - size_t maclen; /*!< MAC length */ - unsigned char randbytes[64]; /*!< random bytes */ - unsigned char premaster[256]; /*!< premaster secret */ - - unsigned char iv_enc[16]; /*!< IV (encryption) */ - unsigned char iv_dec[16]; /*!< IV (decryption) */ - - unsigned char mac_enc[32]; /*!< MAC (encryption) */ - unsigned char mac_dec[32]; /*!< MAC (decryption) */ - - unsigned long ctx_enc[134]; /*!< encryption context */ - unsigned long ctx_dec[134]; /*!< decryption context */ - -#if defined(POLARSSL_ZLIB_SUPPORT) - z_stream ctx_deflate; /*!< compression context */ - z_stream ctx_inflate; /*!< decompression context */ +#if defined(POLARSSL_DHM_C) + mpi dhm_P; /*!< prime modulus for DHM */ + mpi dhm_G; /*!< generator for DHM */ #endif /* @@ -399,6 +474,15 @@ struct _ssl_context */ unsigned char *hostname; size_t hostname_len; + + /* + * Secure renegotiation + */ + int secure_renegotiation; /*!< does peer support legacy or + secure renegotiation */ + size_t verify_data_len; /*!< length of verify data stored */ + char own_verify_data[36]; /*!< previous handshake verify data */ + char peer_verify_data[36]; /*!< previous handshake verify data */ }; #ifdef __cplusplus @@ -465,7 +549,8 @@ int ssl_init( ssl_context *ssl ); * pointers and data. * * \param ssl SSL context - * \return 0 if successful, or POLARSSL_ERR_SSL_HW_ACCEL_FAILED or + * \return 0 if successful, or POLASSL_ERR_SSL_MALLOC_FAILED, + POLARSSL_ERR_SSL_HW_ACCEL_FAILED or * POLARSSL_ERR_SSL_COMPRESSION_FAILED */ int ssl_session_reset( ssl_context *ssl ); @@ -614,6 +699,7 @@ void ssl_set_own_cert_pkcs11( ssl_context *ssl, x509_cert *own_cert, pkcs11_context *pkcs11_key ); #endif +#if defined(POLARSSL_DHM_C) /** * \brief Set the Diffie-Hellman public P and G values, * read as hexadecimal strings (server-side only) @@ -636,6 +722,7 @@ int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G ); * \return 0 if successful */ int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx ); +#endif /** * \brief Set hostname for ServerName TLS Extension @@ -659,6 +746,29 @@ int ssl_set_hostname( ssl_context *ssl, const char *hostname ); */ void ssl_set_max_version( ssl_context *ssl, int major, int minor ); +/** + * \brief Enable / Disable renegotiation support for connection + * (Default: SSL_RENEGOTIATION_ENABLED) + * + * \param ssl SSL context + * \param renegotiation Enable or disable (SSL_RENEGOTIATION_ENABLED or + * SSL_RENEGOTIATION_DISABLED) + */ +void ssl_set_renegotiation( ssl_context *ssl, int renegotiation ); + +/** + * \brief Prevent or allow legacy renegotiation. + * (Default: SSL_NO_LEGACY_RENEGOTIATION) + * Allowing legacy renegotiation makes the connection + * vulnerable to specific man in the middle attacks. + * (See RFC 5746) + * + * \param ssl SSL context + * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION or + * SSL_ALLOW_LEGACY_RENEGOTIATION) + */ +void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy ); + /** * \brief Return the number of data bytes available to read * @@ -709,6 +819,15 @@ const char *ssl_get_version( const ssl_context *ssl ); */ int ssl_handshake( ssl_context *ssl ); +/** + * \brief Perform an SSL renegotiation on the running connection + * + * \param ssl SSL context + * + * \return 0 if succesful, or any ssl_handshake() return value. + */ +int ssl_renegotiate( ssl_context *ssl ); + /** * \brief Read at most 'len' application data bytes * @@ -758,17 +877,42 @@ int ssl_send_alert_message( ssl_context *ssl, int ssl_close_notify( ssl_context *ssl ); /** - * \brief Free an SSL context + * \brief Free referenced items in an SSL context and clear memory * * \param ssl SSL context */ void ssl_free( ssl_context *ssl ); +/** + * \brief Free referenced items in an SSL session and free all + * sessions in the chain. Memory is cleared + * + * \param session SSL session + */ +void ssl_session_free( ssl_session *session ); + +/** + * \brief Free referenced items in an SSL transform context and clear + * memory + * + * \param transform SSL transform context + */ +void ssl_transform_free( ssl_transform *transform ); + +/** + * \brief Free referenced items in an SSL handshake context and clear + * memory + * + * \param handshake SSL handshake context + */ +void ssl_handshake_free( ssl_handshake_params *handshake ); + /* * Internal functions (do not call directly) */ int ssl_handshake_client( ssl_context *ssl ); int ssl_handshake_server( ssl_context *ssl ); +void ssl_handshake_wrapup( ssl_context *ssl ); int ssl_derive_keys( ssl_context *ssl ); @@ -791,8 +935,7 @@ int ssl_write_change_cipher_spec( ssl_context *ssl ); int ssl_parse_finished( ssl_context *ssl ); int ssl_write_finished( ssl_context *ssl ); -void ssl_kickstart_checksum( ssl_context *ssl, int ciphersuite, - unsigned char *input_buf, size_t len ); +void ssl_optimize_checksum( ssl_context *ssl, int ciphersuite ); #ifdef __cplusplus } diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 49123795f..9b821100b 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -54,8 +54,11 @@ static int ssl_write_client_hello( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); - ssl->major_ver = SSL_MAJOR_VERSION_3; - ssl->minor_ver = SSL_MINOR_VERSION_0; + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) + { + ssl->major_ver = SSL_MAJOR_VERSION_3; + ssl->minor_ver = SSL_MINOR_VERSION_0; + } if( ssl->max_major_ver == 0 && ssl->max_minor_ver == 0 ) { @@ -92,7 +95,7 @@ static int ssl_write_client_hello( ssl_context *ssl ) p += 28; - memcpy( ssl->randbytes, buf + 6, 32 ); + memcpy( ssl->handshake->randbytes, buf + 6, 32 ); SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 6, 32 ); @@ -106,24 +109,36 @@ static int ssl_write_client_hello( ssl_context *ssl ) * .. . .. extensions length * .. . .. extensions */ - n = ssl->session->length; + n = ssl->session_negotiate->length; if( n < 16 || n > 32 || ssl->resume == 0 || - ( ssl->timeout != 0 && t - ssl->session->start > ssl->timeout ) ) + ( ssl->timeout != 0 && + t - ssl->session_negotiate->start > ssl->timeout ) ) n = 0; *p++ = (unsigned char) n; for( i = 0; i < n; i++ ) - *p++ = ssl->session->id[i]; + *p++ = ssl->session_negotiate->id[i]; SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) ); SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); for( n = 0; ssl->ciphersuites[n] != 0; n++ ); + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) n++; *p++ = (unsigned char)( n >> 7 ); *p++ = (unsigned char)( n << 1 ); + /* + * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) + { + *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); + *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO ); + n--; + } + SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) ); for( i = 0; i < n; i++ ) @@ -138,11 +153,11 @@ static int ssl_write_client_hello( ssl_context *ssl ) #if defined(POLARSSL_ZLIB_SUPPORT) SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) ); SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d", - SSL_COMPRESS_NULL, SSL_COMPRESS_DEFLATE ) ); + SSL_COMPRESS_DEFLATE, SSL_COMPRESS_NULL ) ); *p++ = 2; - *p++ = SSL_COMPRESS_NULL; *p++ = SSL_COMPRESS_DEFLATE; + *p++ = SSL_COMPRESS_NULL; #else SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", SSL_COMPRESS_NULL ) ); @@ -159,6 +174,12 @@ static int ssl_write_client_hello( ssl_context *ssl ) ext_len += ssl->hostname_len + 9; } + if( ssl->renegotiation == SSL_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 3, ( "client hello, prepping for renegotiation extension" ) ); + ext_len += 5 + ssl->verify_data_len; + } + /* * Prepare signature_algorithms extension (TLS 1.2) */ @@ -184,7 +205,7 @@ static int ssl_write_client_hello( ssl_context *ssl ) sig_alg_list[sig_alg_len++] = SSL_HASH_MD5; sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; #endif - ext_len = 6 + sig_alg_len; + ext_len += 6 + sig_alg_len; } SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", @@ -230,10 +251,27 @@ static int ssl_write_client_hello( ssl_context *ssl ) *p++ = (unsigned char)( ( ssl->hostname_len ) & 0xFF ); memcpy( p, ssl->hostname, ssl->hostname_len ); - p += ssl->hostname_len; } + if( ssl->renegotiation == SSL_RENEGOTIATION ) + { + /* + * Secure renegotiation + */ + SSL_DEBUG_MSG( 3, ( "client hello, renegotiation info extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + + *p++ = 0x00; + *p++ = ( ssl->verify_data_len + 1 ) & 0xFF; + *p++ = ssl->verify_data_len & 0xFF; + + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + } + if( ssl->max_minor_ver == SSL_MINOR_VERSION_3 ) { /* @@ -286,6 +324,38 @@ static int ssl_write_client_hello( ssl_context *ssl ) return( 0 ); } +static int ssl_parse_renegotiation_info( ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) + { + if( len != 1 || buf[0] != 0x0 ) + { + SSL_DEBUG_MSG( 1, ( "non-zero length renegotiated connection field" ) ); + /* TODO: Send handshake failure alert */ + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION; + } + else + { + if( len != 1 + ssl->verify_data_len * 2 || + buf[0] != ssl->verify_data_len * 2 || + memcmp( buf + 1, ssl->own_verify_data, ssl->verify_data_len ) != 0 || + memcmp( buf + 1 + ssl->verify_data_len, + ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) ); + /* TODO: Send handshake failure alert */ + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + + return( 0 ); +} + static int ssl_parse_server_hello( ssl_context *ssl ) { #if defined(POLARSSL_DEBUG_C) @@ -293,8 +363,9 @@ static int ssl_parse_server_hello( ssl_context *ssl ) #endif int ret, i, comp; size_t n; - int ext_len; - unsigned char *buf; + size_t ext_len = 0; + unsigned char *buf, *ext; + int renegotiation_info_seen = 0; SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); @@ -345,13 +416,19 @@ static int ssl_parse_server_hello( ssl_context *ssl ) | ( (time_t) buf[9] ); #endif - memcpy( ssl->randbytes + 32, buf + 6, 32 ); + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); n = buf[38]; SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); + if( n > 32 ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + /* * 38 . 38 session id length * 39 . 38+n session id @@ -360,20 +437,17 @@ static int ssl_parse_server_hello( ssl_context *ssl ) * 42+n . 43+n extensions length * 44+n . 44+n+m extensions */ - if( n > 32 || ssl->in_hslen > 42 + n ) + if( ssl->in_hslen > 42 + n ) { ext_len = ( ( buf[42 + n] << 8 ) - | ( buf[43 + n] ) ) + 2; - } - else - { - ext_len = 0; - } + | ( buf[43 + n] ) ); - if( n > 32 || ssl->in_hslen != 42 + n + ext_len ) - { - SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + if( ( ext_len > 0 && ext_len < 4 ) || + ssl->in_hslen != 44 + n + ext_len ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } } i = ( buf[39 + n] << 8 ) | buf[40 + n]; @@ -382,7 +456,7 @@ static int ssl_parse_server_hello( ssl_context *ssl ) /* * Initialize update checksum functions */ - ssl_kickstart_checksum( ssl, i, buf, ssl->in_hslen ); + ssl_optimize_checksum( ssl, i ); SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); @@ -391,18 +465,18 @@ static int ssl_parse_server_hello( ssl_context *ssl ) * Check if the session can be resumed */ if( ssl->resume == 0 || n == 0 || - ssl->session->ciphersuite != i || - ssl->session->compression != comp || - ssl->session->length != n || - memcmp( ssl->session->id, buf + 39, 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->session->start = time( NULL ); - ssl->session->ciphersuite = i; - ssl->session->compression = comp; - ssl->session->length = n; - memcpy( ssl->session->id, buf + 39, n ); + ssl->session_negotiate->start = time( NULL ); + ssl->session_negotiate->ciphersuite = i; + ssl->session_negotiate->compression = comp; + ssl->session_negotiate->length = n; + memcpy( ssl->session_negotiate->id, buf + 39, n ); } else { @@ -430,7 +504,7 @@ static int ssl_parse_server_hello( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); } - if( ssl->ciphersuites[i++] == ssl->session->ciphersuite ) + if( ssl->ciphersuites[i++] == ssl->session_negotiate->ciphersuite ) break; } @@ -443,9 +517,66 @@ static int ssl_parse_server_hello( ssl_context *ssl ) SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); } - ssl->session->compression = comp; + ssl->session_negotiate->compression = comp; - /* TODO: Process extensions */ + ext = buf + 44 + n; + + while( ext_len ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + switch( ext_id ) + { + case TLS_EXT_RENEGOTIATION_INFO: + SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); + renegotiation_info_seen = 1; + + if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; + + default: + SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( !ssl->allow_legacy_renegotiation && + ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); @@ -467,18 +598,18 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); - if( ssl->session->ciphersuite != SSL_EDH_RSA_DES_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_DES_168_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_GCM_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_GCM_SHA384 ) + if( ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_DES_SHA && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_DES_168_SHA && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_AES_128_SHA && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_AES_256_SHA && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_AES_128_SHA256 && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_AES_256_SHA256 && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA256 && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_AES_128_GCM_SHA256 && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_AES_256_GCM_SHA384 ) { SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); ssl->state++; @@ -521,7 +652,7 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) p = ssl->in_msg + 4; end = ssl->in_msg + ssl->in_hslen; - if( ( ret = dhm_read_params( &ssl->dhm_ctx, &p, end ) ) != 0 ) + if( ( ret = dhm_read_params( &ssl->handshake->dhm_ctx, &p, end ) ) != 0 ) { SSL_DEBUG_MSG( 2, ( "DHM Read Params returned -0x%x", -ret ) ); SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); @@ -585,21 +716,22 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } - if( (unsigned int)( end - p ) != ssl->peer_cert->rsa.len ) + if( (unsigned int)( end - p ) != + ssl->session_negotiate->peer_cert->rsa.len ) { SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } - if( ssl->dhm_ctx.len < 64 || ssl->dhm_ctx.len > 512 ) + if( ssl->handshake->dhm_ctx.len < 64 || ssl->handshake->dhm_ctx.len > 512 ) { SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } - SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->dhm_ctx.P ); - SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G ); - SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY ); + SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); if( ssl->minor_ver != SSL_MINOR_VERSION_3 ) { @@ -619,12 +751,12 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) n = ssl->in_hslen - ( end - p ) - 6; md5_starts( &md5 ); - md5_update( &md5, ssl->randbytes, 64 ); + md5_update( &md5, ssl->handshake->randbytes, 64 ); md5_update( &md5, ssl->in_msg + 4, n ); md5_finish( &md5, hash ); sha1_starts( &sha1 ); - sha1_update( &sha1, ssl->randbytes, 64 ); + sha1_update( &sha1, ssl->handshake->randbytes, 64 ); sha1_update( &sha1, ssl->in_msg + 4, n ); sha1_finish( &sha1, hash + 16 ); @@ -650,7 +782,7 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) #if defined(POLARSSL_MD5_C) case SIG_RSA_MD5: md5_starts( &md5 ); - md5_update( &md5, ssl->randbytes, 64 ); + md5_update( &md5, ssl->handshake->randbytes, 64 ); md5_update( &md5, ssl->in_msg + 4, n ); md5_finish( &md5, hash ); hashlen = 16; @@ -659,7 +791,7 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) #if defined(POLARSSL_SHA1_C) case SIG_RSA_SHA1: sha1_starts( &sha1 ); - sha1_update( &sha1, ssl->randbytes, 64 ); + sha1_update( &sha1, ssl->handshake->randbytes, 64 ); sha1_update( &sha1, ssl->in_msg + 4, n ); sha1_finish( &sha1, hash ); hashlen = 20; @@ -668,14 +800,14 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) #if defined(POLARSSL_SHA2_C) case SIG_RSA_SHA224: sha2_starts( &sha2, 1 ); - sha2_update( &sha2, ssl->randbytes, 64 ); + sha2_update( &sha2, ssl->handshake->randbytes, 64 ); sha2_update( &sha2, ssl->in_msg + 4, n ); sha2_finish( &sha2, hash ); hashlen = 28; break; case SIG_RSA_SHA256: sha2_starts( &sha2, 0 ); - sha2_update( &sha2, ssl->randbytes, 64 ); + sha2_update( &sha2, ssl->handshake->randbytes, 64 ); sha2_update( &sha2, ssl->in_msg + 4, n ); sha2_finish( &sha2, hash ); hashlen = 32; @@ -684,14 +816,14 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) #if defined(POLARSSL_SHA4_C) case SIG_RSA_SHA384: sha4_starts( &sha4, 1 ); - sha4_update( &sha4, ssl->randbytes, 64 ); + sha4_update( &sha4, ssl->handshake->randbytes, 64 ); sha4_update( &sha4, ssl->in_msg + 4, n ); sha4_finish( &sha4, hash ); hashlen = 48; break; case SIG_RSA_SHA512: sha4_starts( &sha4, 0 ); - sha4_update( &sha4, ssl->randbytes, 64 ); + sha4_update( &sha4, ssl->handshake->randbytes, 64 ); sha4_update( &sha4, ssl->in_msg + 4, n ); sha4_finish( &sha4, hash ); hashlen = 64; @@ -702,7 +834,8 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); - if( ( ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC, + if( ( ret = rsa_pkcs1_verify( &ssl->session_negotiate->peer_cert->rsa, + RSA_PUBLIC, hash_id, hashlen, hash, p ) ) != 0 ) { SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret ); @@ -802,18 +935,18 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); - if( ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_DES_168_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + if( ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_DES_SHA || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_DES_168_SHA || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_128_SHA || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_256_SHA || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) { #if !defined(POLARSSL_DHM_C) SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) ); @@ -822,13 +955,13 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) /* * DHM key exchange -- send G^X mod P */ - n = ssl->dhm_ctx.len; + n = ssl->handshake->dhm_ctx.len; ssl->out_msg[4] = (unsigned char)( n >> 8 ); ssl->out_msg[5] = (unsigned char)( n ); i = 6; - ret = dhm_make_public( &ssl->dhm_ctx, 256, + ret = dhm_make_public( &ssl->handshake->dhm_ctx, 256, &ssl->out_msg[i], n, ssl->f_rng, ssl->p_rng ); if( ret != 0 ) @@ -837,20 +970,20 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) return( ret ); } - SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->dhm_ctx.X ); - SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX ); + SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); - ssl->pmslen = ssl->dhm_ctx.len; + ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len; - if( ( ret = dhm_calc_secret( &ssl->dhm_ctx, - ssl->premaster, - &ssl->pmslen ) ) != 0 ) + if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + &ssl->handshake->pmslen ) ) != 0 ) { SSL_DEBUG_RET( 1, "dhm_calc_secret", ret ); return( ret ); } - SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->dhm_ctx.K ); + SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); #endif } else @@ -858,16 +991,17 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) /* * RSA key exchange -- send rsa_public(pkcs1 v1.5(premaster)) */ - ssl->premaster[0] = (unsigned char) ssl->max_major_ver; - ssl->premaster[1] = (unsigned char) ssl->max_minor_ver; - ssl->pmslen = 48; + ssl->handshake->premaster[0] = (unsigned char) ssl->max_major_ver; + ssl->handshake->premaster[1] = (unsigned char) ssl->max_minor_ver; + ssl->handshake->pmslen = 48; - ret = ssl->f_rng( ssl->p_rng, ssl->premaster + 2, ssl->pmslen - 2 ); + ret = ssl->f_rng( ssl->p_rng, ssl->handshake->premaster + 2, + ssl->handshake->pmslen - 2 ); if( ret != 0 ) return( ret ); i = 4; - n = ssl->peer_cert->rsa.len; + n = ssl->session_negotiate->peer_cert->rsa.len; if( ssl->minor_ver != SSL_MINOR_VERSION_0 ) { @@ -876,10 +1010,11 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) ssl->out_msg[5] = (unsigned char)( n ); } - ret = rsa_pkcs1_encrypt( &ssl->peer_cert->rsa, + ret = rsa_pkcs1_encrypt( &ssl->session_negotiate->peer_cert->rsa, ssl->f_rng, ssl->p_rng, RSA_PUBLIC, - ssl->pmslen, ssl->premaster, + ssl->handshake->pmslen, + ssl->handshake->premaster, ssl->out_msg + i ); if( ret != 0 ) { @@ -934,8 +1069,8 @@ static int ssl_write_certificate_verify( ssl_context *ssl ) // Certificate Request according to RFC 5246. But OpenSSL only allows // SHA256 and SHA384. Find out why OpenSSL does this. // - if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + if( ssl->session_negotiate->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) { hash_id = SIG_RSA_SHA384; hashlen = 48; @@ -963,7 +1098,7 @@ static int ssl_write_certificate_verify( ssl_context *ssl ) /* * Make an RSA signature of the handshake digests */ - ssl->calc_verify( ssl, hash ); + ssl->handshake->calc_verify( ssl, hash ); if ( ssl->rsa_key ) n = ssl->rsa_key->len; @@ -978,8 +1113,8 @@ static int ssl_write_certificate_verify( ssl_context *ssl ) // Certificate Request according to RFC 5246. But OpenSSL only allows // SHA256 and SHA384. Find out why OpenSSL does this. // - if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + if( ssl->session_negotiate->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) { ssl->out_msg[4] = SSL_HASH_SHA384; ssl->out_msg[5] = SSL_SIG_RSA; @@ -999,12 +1134,12 @@ static int ssl_write_certificate_verify( ssl_context *ssl ) if( ssl->rsa_key ) { ret = rsa_pkcs1_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng, - RSA_PRIVATE, hash_id, - hashlen, hash, ssl->out_msg + 6 + offset ); + RSA_PRIVATE, hash_id, + hashlen, hash, ssl->out_msg + 6 + offset ); } else { #if defined(POLARSSL_PKCS11_C) ret = pkcs11_sign( ssl->pkcs11_key, RSA_PRIVATE, hash_id, - hashlen, hash, ssl->out_msg + 6 + offset ); + hashlen, hash, ssl->out_msg + 6 + offset ); #endif /* defined(POLARSSL_PKCS11_C) */ } @@ -1128,7 +1263,11 @@ int ssl_handshake_client( ssl_context *ssl ) case SSL_FLUSH_BUFFERS: SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); - ssl->state = SSL_HANDSHAKE_OVER; + ssl->state = SSL_HANDSHAKE_WRAPUP; + break; + + case SSL_HANDSHAKE_WRAPUP: + ssl_handshake_wrapup( ssl ); break; default: diff --git a/library/ssl_srv.c b/library/ssl_srv.c index d54e3eca7..742b9126e 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -38,6 +38,36 @@ #include #include +static int ssl_parse_renegotiation_info( ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) + { + if( len != 1 || buf[0] != 0x0 ) + { + SSL_DEBUG_MSG( 1, ( "non-zero length renegotiated connection field" ) ); + /* TODO: Send handshake failure alert */ + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION; + } + else + { + if( len != 1 + ssl->verify_data_len || + buf[0] != ssl->verify_data_len || + memcmp( buf + 1, ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) ); + /* TODO: Send handshake failure alert */ + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + return( 0 ); +} + static int ssl_parse_client_hello( ssl_context *ssl ) { int ret; @@ -45,11 +75,14 @@ static int ssl_parse_client_hello( ssl_context *ssl ) size_t n; unsigned int ciph_len, sess_len; unsigned int comp_len; - unsigned char *buf, *p; + unsigned int ext_len = 0; + unsigned char *buf, *p, *ext; + int renegotiation_info_seen; SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); - if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 ) + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE && + ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 ) { SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); return( ret ); @@ -89,16 +122,20 @@ static int ssl_parse_client_hello( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); } - if( ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 ) + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE && + ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 ) { SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); return( ret ); } buf = ssl->in_msg; - n = ssl->in_left - 5; + if( !ssl->renegotiation ) + n = ssl->in_left - 5; + else + n = ssl->in_msglen; - ssl->update_checksum( ssl, buf, n ); + ssl->handshake->update_checksum( ssl, buf, n ); /* * SSL layer: @@ -140,7 +177,7 @@ static int ssl_parse_client_hello( ssl_context *ssl ) ssl->max_major_ver = buf[4]; ssl->max_minor_ver = buf[5]; - memcpy( ssl->randbytes, buf + 6, 32 ); + memcpy( ssl->handshake->randbytes, buf + 6, 32 ); /* * Check the handshake message length @@ -162,9 +199,11 @@ static int ssl_parse_client_hello( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); } - ssl->session->length = sess_len; - memset( ssl->session->id, 0, sizeof( ssl->session->id ) ); - memcpy( ssl->session->id, buf + 39 , ssl->session->length ); + ssl->session_negotiate->length = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, buf + 39, + ssl->session_negotiate->length ); /* * Check the ciphersuitelist length @@ -189,13 +228,30 @@ static int ssl_parse_client_hello( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); } - ssl->session->compression = SSL_COMPRESS_NULL; + /* + * Check the extension length + */ + if( n > 42 + sess_len + ciph_len + comp_len ) + { + ext_len = ( buf[42 + sess_len + ciph_len + comp_len] << 8 ) + | ( buf[43 + sess_len + ciph_len + comp_len] ); + + if( ( ext_len > 0 && ext_len < 4 ) || + n != 44 + sess_len + ciph_len + comp_len + ext_len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + SSL_DEBUG_BUF( 3, "Ext", buf + 44 + sess_len + ciph_len + comp_len, ext_len); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + ssl->session_negotiate->compression = SSL_COMPRESS_NULL; #if defined(POLARSSL_ZLIB_SUPPORT) for( i = 0; i < comp_len; ++i ) { - if( buf[41 + sess_len + ciph_len + i] == SSL_COMPRESS_DEFLATE ) + if( buf[42 + sess_len + ciph_len + i] == SSL_COMPRESS_DEFLATE ) { - ssl->session->compression = SSL_COMPRESS_DEFLATE; + ssl->session_negotiate->compression = SSL_COMPRESS_DEFLATE; break; } } @@ -210,6 +266,24 @@ static int ssl_parse_client_hello( ssl_context *ssl ) SSL_DEBUG_BUF( 3, "client hello, compression", buf + 42 + sess_len + ciph_len, comp_len ); + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + 41 + sess_len; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == 0 && p[1] == SSL_EMPTY_RENEGOTIATION_INFO ) + { + SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); + if( ssl->renegotiation == SSL_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION; + break; + } + } + /* * Search for a matching ciphersuite */ @@ -228,9 +302,75 @@ static int ssl_parse_client_hello( ssl_context *ssl ) return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); have_ciphersuite: + ssl->session_negotiate->ciphersuite = ssl->ciphersuites[i]; + ssl_optimize_checksum( ssl, ssl->session_negotiate->ciphersuite ); - ssl->session->ciphersuite = ssl->ciphersuites[i]; - ssl_kickstart_checksum( ssl, ssl->session->ciphersuite, buf, n ); + ext = buf + 44 + sess_len + ciph_len + comp_len; + renegotiation_info_seen = 0; + + while( ext_len ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + switch( ext_id ) + { + case TLS_EXT_RENEGOTIATION_INFO: + SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); + renegotiation_info_seen = 1; + + if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; + + default: + SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( !ssl->allow_legacy_renegotiation && + ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } ssl->in_left = 0; ssl->state++; @@ -244,6 +384,7 @@ static int ssl_write_server_hello( ssl_context *ssl ) { time_t t; int ret, n; + size_t ext_len = 0; unsigned char *buf, *p; SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); @@ -277,7 +418,7 @@ static int ssl_write_server_hello( ssl_context *ssl ) p += 28; - memcpy( ssl->randbytes + 32, buf + 6, 32 ); + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); @@ -287,8 +428,8 @@ static int ssl_write_server_hello( ssl_context *ssl ) * 39+n . 40+n chosen ciphersuite * 41+n . 41+n chosen compression alg. */ - ssl->session->length = n = 32; - *p++ = (unsigned char) ssl->session->length; + ssl->session_negotiate->length = n = 32; + *p++ = (unsigned char) ssl->session_negotiate->length; if( ssl->s_get == NULL || ssl->s_get( ssl ) != 0 ) @@ -299,13 +440,14 @@ static int ssl_write_server_hello( ssl_context *ssl ) ssl->resume = 0; ssl->state++; - if( ssl->session == NULL ) + 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->id, n ) ) != 0 ) + if( ( ret = ssl->f_rng( ssl->p_rng, ssl->session_negotiate->id, + n ) ) != 0 ) return( ret ); } else @@ -323,22 +465,48 @@ static int ssl_write_server_hello( ssl_context *ssl ) } } - memcpy( p, ssl->session->id, ssl->session->length ); - p += ssl->session->length; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->length ); + p += ssl->session_negotiate->length; 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" ) ); - *p++ = (unsigned char)( ssl->session->ciphersuite >> 8 ); - *p++ = (unsigned char)( ssl->session->ciphersuite ); - *p++ = (unsigned char)( ssl->session->compression ); + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 ); + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite ); + *p++ = (unsigned char)( ssl->session_negotiate->compression ); SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d", - ssl->session->ciphersuite ) ); + ssl->session_negotiate->ciphersuite ) ); SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", - ssl->session->compression ) ); + ssl->session_negotiate->compression ) ); + + SSL_DEBUG_MSG( 3, ( "server hello, prepping for secure renegotiation extension" ) ); + ext_len += 5 + ssl->verify_data_len * 2; + + SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", + ext_len ) ); + + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + + /* + * Secure renegotiation + */ + SSL_DEBUG_MSG( 3, ( "client hello, secure renegotiation extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + + *p++ = 0x00; + *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; + *p++ = ssl->verify_data_len * 2 & 0xFF; + + memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; ssl->out_msglen = p - buf; ssl->out_msgtype = SSL_MSG_HANDSHAKE; @@ -431,18 +599,18 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); - if( ssl->session->ciphersuite != SSL_EDH_RSA_DES_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_DES_168_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_GCM_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_GCM_SHA384 ) + if( ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_DES_SHA && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_DES_168_SHA && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_AES_128_SHA && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_AES_256_SHA && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_AES_128_SHA256 && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_AES_256_SHA256 && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA256 && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_AES_128_GCM_SHA256 && + ssl->session_negotiate->ciphersuite != SSL_EDH_RSA_AES_256_GCM_SHA384 ) { SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); ssl->state++; @@ -476,17 +644,24 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) * opaque dh_Ys<1..2^16-1>; * } ServerDHParams; */ - if( ( ret = dhm_make_params( &ssl->dhm_ctx, 256, ssl->out_msg + 4, - &n, ssl->f_rng, ssl->p_rng ) ) != 0 ) + if( ( ret = mpi_copy( &ssl->handshake->dhm_ctx.P, &ssl->dhm_P ) ) != 0 || + ( ret = mpi_copy( &ssl->handshake->dhm_ctx.G, &ssl->dhm_G ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_copy", ret ); + return( ret ); + } + + if( ( ret = dhm_make_params( &ssl->handshake->dhm_ctx, 256, ssl->out_msg + 4, + &n, ssl->f_rng, ssl->p_rng ) ) != 0 ) { SSL_DEBUG_RET( 1, "dhm_make_params", ret ); return( ret ); } - SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->dhm_ctx.X ); - SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->dhm_ctx.P ); - SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G ); - SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX ); + SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); if( ssl->minor_ver != SSL_MINOR_VERSION_3 ) { @@ -504,12 +679,12 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) * + ServerParams); */ md5_starts( &md5 ); - md5_update( &md5, ssl->randbytes, 64 ); + md5_update( &md5, ssl->handshake->randbytes, 64 ); md5_update( &md5, ssl->out_msg + 4, n ); md5_finish( &md5, hash ); sha1_starts( &sha1 ); - sha1_update( &sha1, ssl->randbytes, 64 ); + sha1_update( &sha1, ssl->handshake->randbytes, 64 ); sha1_update( &sha1, ssl->out_msg + 4, n ); sha1_finish( &sha1, hash + 16 ); @@ -530,7 +705,7 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) */ sha1_starts( &sha1 ); - sha1_update( &sha1, ssl->randbytes, 64 ); + sha1_update( &sha1, ssl->handshake->randbytes, 64 ); sha1_update( &sha1, ssl->out_msg + 4, n ); sha1_finish( &sha1, hash ); @@ -646,18 +821,18 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); } - if( ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_DES_168_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + if( ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_DES_SHA || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_DES_168_SHA || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_128_SHA || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_256_SHA || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || + ssl->session_negotiate->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) { #if !defined(POLARSSL_DHM_C) SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) ); @@ -668,32 +843,33 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) */ n = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; - if( n < 1 || n > ssl->dhm_ctx.len || + if( n < 1 || n > ssl->handshake->dhm_ctx.len || n + 6 != ssl->in_hslen ) { SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); } - if( ( ret = dhm_read_public( &ssl->dhm_ctx, + if( ( ret = dhm_read_public( &ssl->handshake->dhm_ctx, ssl->in_msg + 6, n ) ) != 0 ) { SSL_DEBUG_RET( 1, "dhm_read_public", ret ); return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP ); } - SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY ); + SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); - ssl->pmslen = ssl->dhm_ctx.len; + ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len; - if( ( ret = dhm_calc_secret( &ssl->dhm_ctx, - ssl->premaster, &ssl->pmslen ) ) != 0 ) + if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + &ssl->handshake->pmslen ) ) != 0 ) { SSL_DEBUG_RET( 1, "dhm_calc_secret", ret ); return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS ); } - SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->dhm_ctx.K ); + SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); #endif } else @@ -721,7 +897,7 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) else n = ssl->pkcs11_key->len; #endif - ssl->pmslen = 48; + ssl->handshake->pmslen = 48; if( ssl->minor_ver != SSL_MINOR_VERSION_0 ) { @@ -741,21 +917,25 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) } if( ssl->rsa_key ) { - ret = rsa_pkcs1_decrypt( ssl->rsa_key, RSA_PRIVATE, &ssl->pmslen, - ssl->in_msg + i, ssl->premaster, - sizeof(ssl->premaster) ); + ret = rsa_pkcs1_decrypt( ssl->rsa_key, RSA_PRIVATE, + &ssl->handshake->pmslen, + ssl->in_msg + i, + ssl->handshake->premaster, + sizeof(ssl->handshake->premaster) ); } #if defined(POLARSSL_PKCS11_C) else { - ret = pkcs11_decrypt( ssl->pkcs11_key, RSA_PRIVATE, &ssl->pmslen, - ssl->in_msg + i, ssl->premaster, - sizeof(ssl->premaster) ); + ret = pkcs11_decrypt( ssl->pkcs11_key, RSA_PRIVATE, + &ssl->handshake->pmslen, + ssl->in_msg + i, + ssl->handshake->premaster, + sizeof(ssl->handshake->premaster) ); } #endif /* defined(POLARSSL_PKCS11_C) */ - if( ret != 0 || ssl->pmslen != 48 || - ssl->premaster[0] != ssl->max_major_ver || - ssl->premaster[1] != ssl->max_minor_ver ) + if( ret != 0 || ssl->handshake->pmslen != 48 || + ssl->handshake->premaster[0] != ssl->max_major_ver || + ssl->handshake->premaster[1] != ssl->max_minor_ver ) { SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); @@ -765,9 +945,10 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) * the connection to end immediately; instead, * send a bad_record_mac later in the handshake. */ - ssl->pmslen = 48; + ssl->handshake->pmslen = 48; - ret = ssl->f_rng( ssl->p_rng, ssl->premaster, ssl->pmslen ); + ret = ssl->f_rng( ssl->p_rng, ssl->handshake->premaster, + ssl->handshake->pmslen ); if( ret != 0 ) return( ret ); } @@ -797,14 +978,14 @@ static int ssl_parse_certificate_verify( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); - if( ssl->peer_cert == NULL ) + if( ssl->session_negotiate->peer_cert == NULL ) { SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); ssl->state++; return( 0 ); } - ssl->calc_verify( ssl, hash ); + ssl->handshake->calc_verify( ssl, hash ); if( ( ret = ssl_read_record( ssl ) ) != 0 ) { @@ -826,7 +1007,7 @@ static int ssl_parse_certificate_verify( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); } - n1 = ssl->peer_cert->rsa.len; + n1 = ssl->session_negotiate->peer_cert->rsa.len; n2 = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; if( n1 + 6 != ssl->in_hslen || n1 != n2 ) @@ -835,7 +1016,7 @@ static int ssl_parse_certificate_verify( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); } - ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC, + ret = rsa_pkcs1_verify( &ssl->session_negotiate->peer_cert->rsa, RSA_PUBLIC, SIG_RSA_RAW, 36, hash, ssl->in_msg + 6 ); if( ret != 0 ) { @@ -945,7 +1126,11 @@ int ssl_handshake_server( ssl_context *ssl ) case SSL_FLUSH_BUFFERS: SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); - ssl->state = SSL_HANDSHAKE_OVER; + ssl->state = SSL_HANDSHAKE_WRAPUP; + break; + + case SSL_HANDSHAKE_WRAPUP: + ssl_handshake_wrapup( ssl ); break; default: diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 905f7cf03..d47ec9f40 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -272,6 +272,9 @@ int ssl_derive_keys( ssl_context *ssl ) unsigned char *key1; unsigned char *key2; unsigned int iv_copy_len; + ssl_session *session = ssl->session_negotiate; + ssl_transform *transform = ssl->transform_negotiate; + ssl_handshake_params *handshake = ssl->handshake; SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); @@ -280,28 +283,28 @@ int ssl_derive_keys( ssl_context *ssl ) */ if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) { - ssl->tls_prf = ssl3_prf; - ssl->calc_verify = ssl_calc_verify_ssl; - ssl->calc_finished = ssl_calc_finished_ssl; + handshake->tls_prf = ssl3_prf; + handshake->calc_verify = ssl_calc_verify_ssl; + handshake->calc_finished = ssl_calc_finished_ssl; } else if( ssl->minor_ver < SSL_MINOR_VERSION_3 ) { - ssl->tls_prf = tls1_prf; - ssl->calc_verify = ssl_calc_verify_tls; - ssl->calc_finished = ssl_calc_finished_tls; + handshake->tls_prf = tls1_prf; + handshake->calc_verify = ssl_calc_verify_tls; + handshake->calc_finished = ssl_calc_finished_tls; } - else if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + else if( session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || + session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) { - ssl->tls_prf = tls_prf_sha384; - ssl->calc_verify = ssl_calc_verify_tls_sha384; - ssl->calc_finished = ssl_calc_finished_tls_sha384; + handshake->tls_prf = tls_prf_sha384; + handshake->calc_verify = ssl_calc_verify_tls_sha384; + handshake->calc_finished = ssl_calc_finished_tls_sha384; } else { - ssl->tls_prf = tls_prf_sha256; - ssl->calc_verify = ssl_calc_verify_tls_sha256; - ssl->calc_finished = ssl_calc_finished_tls_sha256; + handshake->tls_prf = tls_prf_sha256; + handshake->calc_verify = ssl_calc_verify_tls_sha256; + handshake->calc_finished = ssl_calc_finished_tls_sha256; } /* @@ -316,12 +319,14 @@ int ssl_derive_keys( ssl_context *ssl ) */ if( ssl->resume == 0 ) { - SSL_DEBUG_BUF( 3, "premaster secret", ssl->premaster, ssl->pmslen ); + SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, + handshake->pmslen ); - ssl->tls_prf( ssl->premaster, ssl->pmslen, "master secret", - ssl->randbytes, 64, ssl->session->master, 48 ); + handshake->tls_prf( handshake->premaster, handshake->pmslen, + "master secret", + handshake->randbytes, 64, session->master, 48 ); - memset( ssl->premaster, 0, sizeof( ssl->premaster ) ); + memset( handshake->premaster, 0, sizeof( handshake->premaster ) ); } else SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); @@ -329,9 +334,9 @@ int ssl_derive_keys( ssl_context *ssl ) /* * Swap the client and server random values. */ - memcpy( tmp, ssl->randbytes, 64 ); - memcpy( ssl->randbytes, tmp + 32, 32 ); - memcpy( ssl->randbytes + 32, tmp, 32 ); + memcpy( tmp, handshake->randbytes, 64 ); + memcpy( handshake->randbytes, tmp + 32, 32 ); + memcpy( handshake->randbytes + 32, tmp, 32 ); memset( tmp, 0, sizeof( tmp ) ); /* @@ -346,80 +351,81 @@ int ssl_derive_keys( ssl_context *ssl ) * TLSv1: * key block = PRF( master, "key expansion", randbytes ) */ - ssl->tls_prf( ssl->session->master, 48, "key expansion", - ssl->randbytes, 64, keyblk, 256 ); + handshake->tls_prf( session->master, 48, "key expansion", + handshake->randbytes, 64, keyblk, 256 ); - SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", ssl_get_ciphersuite( ssl ) ) ); - SSL_DEBUG_BUF( 3, "master secret", ssl->session->master, 48 ); - SSL_DEBUG_BUF( 4, "random bytes", ssl->randbytes, 64 ); + SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", + ssl_get_ciphersuite_name( session->ciphersuite ) ) ); + SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); + SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); - memset( ssl->randbytes, 0, sizeof( ssl->randbytes ) ); + memset( handshake->randbytes, 0, sizeof( handshake->randbytes ) ); /* * Determine the appropriate key, IV and MAC length. */ - switch( ssl->session->ciphersuite ) + switch( session->ciphersuite ) { #if defined(POLARSSL_ARC4_C) case SSL_RSA_RC4_128_MD5: - ssl->keylen = 16; ssl->minlen = 16; - ssl->ivlen = 0; ssl->maclen = 16; + transform->keylen = 16; transform->minlen = 16; + transform->ivlen = 0; transform->maclen = 16; break; case SSL_RSA_RC4_128_SHA: - ssl->keylen = 16; ssl->minlen = 20; - ssl->ivlen = 0; ssl->maclen = 20; + transform->keylen = 16; transform->minlen = 20; + transform->ivlen = 0; transform->maclen = 20; break; #endif #if defined(POLARSSL_DES_C) case SSL_RSA_DES_168_SHA: case SSL_EDH_RSA_DES_168_SHA: - ssl->keylen = 24; ssl->minlen = 24; - ssl->ivlen = 8; ssl->maclen = 20; + transform->keylen = 24; transform->minlen = 24; + transform->ivlen = 8; transform->maclen = 20; break; #endif #if defined(POLARSSL_AES_C) case SSL_RSA_AES_128_SHA: case SSL_EDH_RSA_AES_128_SHA: - ssl->keylen = 16; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 20; + transform->keylen = 16; transform->minlen = 32; + transform->ivlen = 16; transform->maclen = 20; break; case SSL_RSA_AES_256_SHA: case SSL_EDH_RSA_AES_256_SHA: - ssl->keylen = 32; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 20; + transform->keylen = 32; transform->minlen = 32; + transform->ivlen = 16; transform->maclen = 20; break; #if defined(POLARSSL_SHA2_C) case SSL_RSA_AES_128_SHA256: case SSL_EDH_RSA_AES_128_SHA256: - ssl->keylen = 16; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 32; + transform->keylen = 16; transform->minlen = 32; + transform->ivlen = 16; transform->maclen = 32; break; case SSL_RSA_AES_256_SHA256: case SSL_EDH_RSA_AES_256_SHA256: - ssl->keylen = 32; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 32; + transform->keylen = 32; transform->minlen = 32; + transform->ivlen = 16; transform->maclen = 32; break; #endif #if defined(POLARSSL_GCM_C) case SSL_RSA_AES_128_GCM_SHA256: case SSL_EDH_RSA_AES_128_GCM_SHA256: - ssl->keylen = 16; ssl->minlen = 1; - ssl->ivlen = 12; ssl->maclen = 0; - ssl->fixed_ivlen = 4; + transform->keylen = 16; transform->minlen = 1; + transform->ivlen = 12; transform->maclen = 0; + transform->fixed_ivlen = 4; break; case SSL_RSA_AES_256_GCM_SHA384: case SSL_EDH_RSA_AES_256_GCM_SHA384: - ssl->keylen = 32; ssl->minlen = 1; - ssl->ivlen = 12; ssl->maclen = 0; - ssl->fixed_ivlen = 4; + transform->keylen = 32; transform->minlen = 1; + transform->ivlen = 12; transform->maclen = 0; + transform->fixed_ivlen = 4; break; #endif #endif @@ -427,27 +433,27 @@ int ssl_derive_keys( ssl_context *ssl ) #if defined(POLARSSL_CAMELLIA_C) case SSL_RSA_CAMELLIA_128_SHA: case SSL_EDH_RSA_CAMELLIA_128_SHA: - ssl->keylen = 16; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 20; + transform->keylen = 16; transform->minlen = 32; + transform->ivlen = 16; transform->maclen = 20; break; case SSL_RSA_CAMELLIA_256_SHA: case SSL_EDH_RSA_CAMELLIA_256_SHA: - ssl->keylen = 32; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 20; + transform->keylen = 32; transform->minlen = 32; + transform->ivlen = 16; transform->maclen = 20; break; #if defined(POLARSSL_SHA2_C) case SSL_RSA_CAMELLIA_128_SHA256: case SSL_EDH_RSA_CAMELLIA_128_SHA256: - ssl->keylen = 16; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 32; + transform->keylen = 16; transform->minlen = 32; + transform->ivlen = 16; transform->maclen = 32; break; case SSL_RSA_CAMELLIA_256_SHA256: case SSL_EDH_RSA_CAMELLIA_256_SHA256: - ssl->keylen = 32; ssl->minlen = 32; - ssl->ivlen = 16; ssl->maclen = 32; + transform->keylen = 32; transform->minlen = 32; + transform->ivlen = 16; transform->maclen = 32; break; #endif #endif @@ -455,72 +461,77 @@ int ssl_derive_keys( ssl_context *ssl ) #if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) #if defined(POLARSSL_CIPHER_NULL_CIPHER) case SSL_RSA_NULL_MD5: - ssl->keylen = 0; ssl->minlen = 0; - ssl->ivlen = 0; ssl->maclen = 16; + transform->keylen = 0; transform->minlen = 0; + transform->ivlen = 0; transform->maclen = 16; break; case SSL_RSA_NULL_SHA: - ssl->keylen = 0; ssl->minlen = 0; - ssl->ivlen = 0; ssl->maclen = 20; + transform->keylen = 0; transform->minlen = 0; + transform->ivlen = 0; transform->maclen = 20; break; case SSL_RSA_NULL_SHA256: - ssl->keylen = 0; ssl->minlen = 0; - ssl->ivlen = 0; ssl->maclen = 32; + transform->keylen = 0; transform->minlen = 0; + transform->ivlen = 0; transform->maclen = 32; break; #endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ #if defined(POLARSSL_DES_C) case SSL_RSA_DES_SHA: case SSL_EDH_RSA_DES_SHA: - ssl->keylen = 8; ssl->minlen = 8; - ssl->ivlen = 8; ssl->maclen = 20; + transform->keylen = 8; transform->minlen = 8; + transform->ivlen = 8; transform->maclen = 20; break; #endif #endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */ default: SSL_DEBUG_MSG( 1, ( "ciphersuite %s is not available", - ssl_get_ciphersuite( ssl ) ) ); + ssl_get_ciphersuite_name( session->ciphersuite ) ) ); return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); } SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d", - ssl->keylen, ssl->minlen, ssl->ivlen, ssl->maclen ) ); + transform->keylen, transform->minlen, transform->ivlen, + transform->maclen ) ); /* * Finally setup the cipher contexts, IVs and MAC secrets. */ if( ssl->endpoint == SSL_IS_CLIENT ) { - key1 = keyblk + ssl->maclen * 2; - key2 = keyblk + ssl->maclen * 2 + ssl->keylen; + key1 = keyblk + transform->maclen * 2; + key2 = keyblk + transform->maclen * 2 + transform->keylen; - memcpy( ssl->mac_enc, keyblk, ssl->maclen ); - memcpy( ssl->mac_dec, keyblk + ssl->maclen, ssl->maclen ); + memcpy( transform->mac_enc, keyblk, transform->maclen ); + memcpy( transform->mac_dec, keyblk + transform->maclen, + transform->maclen ); /* * This is not used in TLS v1.1. */ - iv_copy_len = ( ssl->fixed_ivlen ) ? ssl->fixed_ivlen : ssl->ivlen; - memcpy( ssl->iv_enc, key2 + ssl->keylen, iv_copy_len ); - memcpy( ssl->iv_dec, key2 + ssl->keylen + iv_copy_len, + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_enc, key2 + transform->keylen, iv_copy_len ); + memcpy( transform->iv_dec, key2 + transform->keylen + iv_copy_len, iv_copy_len ); } else { - key1 = keyblk + ssl->maclen * 2 + ssl->keylen; - key2 = keyblk + ssl->maclen * 2; + key1 = keyblk + transform->maclen * 2 + transform->keylen; + key2 = keyblk + transform->maclen * 2; - memcpy( ssl->mac_dec, keyblk, ssl->maclen ); - memcpy( ssl->mac_enc, keyblk + ssl->maclen, ssl->maclen ); + memcpy( transform->mac_dec, keyblk, transform->maclen ); + memcpy( transform->mac_enc, keyblk + transform->maclen, + transform->maclen ); /* * This is not used in TLS v1.1. */ - iv_copy_len = ( ssl->fixed_ivlen ) ? ssl->fixed_ivlen : ssl->ivlen; - memcpy( ssl->iv_dec, key1 + ssl->keylen, iv_copy_len ); - memcpy( ssl->iv_enc, key1 + ssl->keylen + iv_copy_len, + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_dec, key1 + transform->keylen, iv_copy_len ); + memcpy( transform->iv_enc, key1 + transform->keylen + iv_copy_len, iv_copy_len ); } @@ -531,9 +542,9 @@ int ssl_derive_keys( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_init()" ) ); - if( ( ret = ssl_hw_record_init( ssl, key1, key2, ssl->iv_enc, - ssl->iv_dec, ssl->mac_enc, - ssl->mac_dec ) ) != 0 ) + if( ( ret = ssl_hw_record_init( ssl, key1, key2, transform->iv_enc, + transform->iv_dec, transform->mac_enc, + transform->mac_dec ) ) != 0 ) { SSL_DEBUG_RET( 1, "ssl_hw_record_init", ret ); return POLARSSL_ERR_SSL_HW_ACCEL_FAILED; @@ -541,21 +552,23 @@ int ssl_derive_keys( ssl_context *ssl ) } #endif - switch( ssl->session->ciphersuite ) + switch( session->ciphersuite ) { #if defined(POLARSSL_ARC4_C) case SSL_RSA_RC4_128_MD5: case SSL_RSA_RC4_128_SHA: - arc4_setup( (arc4_context *) ssl->ctx_enc, key1, ssl->keylen ); - arc4_setup( (arc4_context *) ssl->ctx_dec, key2, ssl->keylen ); + arc4_setup( (arc4_context *) transform->ctx_enc, key1, + transform->keylen ); + arc4_setup( (arc4_context *) transform->ctx_dec, key2, + transform->keylen ); break; #endif #if defined(POLARSSL_DES_C) case SSL_RSA_DES_168_SHA: case SSL_EDH_RSA_DES_168_SHA: - des3_set3key_enc( (des3_context *) ssl->ctx_enc, key1 ); - des3_set3key_dec( (des3_context *) ssl->ctx_dec, key2 ); + des3_set3key_enc( (des3_context *) transform->ctx_enc, key1 ); + des3_set3key_dec( (des3_context *) transform->ctx_dec, key2 ); break; #endif @@ -564,29 +577,29 @@ int ssl_derive_keys( ssl_context *ssl ) case SSL_EDH_RSA_AES_128_SHA: case SSL_RSA_AES_128_SHA256: case SSL_EDH_RSA_AES_128_SHA256: - aes_setkey_enc( (aes_context *) ssl->ctx_enc, key1, 128 ); - aes_setkey_dec( (aes_context *) ssl->ctx_dec, key2, 128 ); + aes_setkey_enc( (aes_context *) transform->ctx_enc, key1, 128 ); + aes_setkey_dec( (aes_context *) transform->ctx_dec, key2, 128 ); break; case SSL_RSA_AES_256_SHA: case SSL_EDH_RSA_AES_256_SHA: case SSL_RSA_AES_256_SHA256: case SSL_EDH_RSA_AES_256_SHA256: - aes_setkey_enc( (aes_context *) ssl->ctx_enc, key1, 256 ); - aes_setkey_dec( (aes_context *) ssl->ctx_dec, key2, 256 ); + aes_setkey_enc( (aes_context *) transform->ctx_enc, key1, 256 ); + aes_setkey_dec( (aes_context *) transform->ctx_dec, key2, 256 ); break; #if defined(POLARSSL_GCM_C) case SSL_RSA_AES_128_GCM_SHA256: case SSL_EDH_RSA_AES_128_GCM_SHA256: - gcm_init( (gcm_context *) ssl->ctx_enc, key1, 128 ); - gcm_init( (gcm_context *) ssl->ctx_dec, key2, 128 ); + gcm_init( (gcm_context *) transform->ctx_enc, key1, 128 ); + gcm_init( (gcm_context *) transform->ctx_dec, key2, 128 ); break; case SSL_RSA_AES_256_GCM_SHA384: case SSL_EDH_RSA_AES_256_GCM_SHA384: - gcm_init( (gcm_context *) ssl->ctx_enc, key1, 256 ); - gcm_init( (gcm_context *) ssl->ctx_dec, key2, 256 ); + gcm_init( (gcm_context *) transform->ctx_enc, key1, 256 ); + gcm_init( (gcm_context *) transform->ctx_dec, key2, 256 ); break; #endif #endif @@ -596,16 +609,16 @@ int ssl_derive_keys( ssl_context *ssl ) case SSL_EDH_RSA_CAMELLIA_128_SHA: case SSL_RSA_CAMELLIA_128_SHA256: case SSL_EDH_RSA_CAMELLIA_128_SHA256: - camellia_setkey_enc( (camellia_context *) ssl->ctx_enc, key1, 128 ); - camellia_setkey_dec( (camellia_context *) ssl->ctx_dec, key2, 128 ); + camellia_setkey_enc( (camellia_context *) transform->ctx_enc, key1, 128 ); + camellia_setkey_dec( (camellia_context *) transform->ctx_dec, key2, 128 ); break; case SSL_RSA_CAMELLIA_256_SHA: case SSL_EDH_RSA_CAMELLIA_256_SHA: case SSL_RSA_CAMELLIA_256_SHA256: case SSL_EDH_RSA_CAMELLIA_256_SHA256: - camellia_setkey_enc( (camellia_context *) ssl->ctx_enc, key1, 256 ); - camellia_setkey_dec( (camellia_context *) ssl->ctx_dec, key2, 256 ); + camellia_setkey_enc( (camellia_context *) transform->ctx_enc, key1, 256 ); + camellia_setkey_dec( (camellia_context *) transform->ctx_dec, key2, 256 ); break; #endif @@ -620,8 +633,8 @@ int ssl_derive_keys( ssl_context *ssl ) #if defined(POLARSSL_DES_C) case SSL_RSA_DES_SHA: case SSL_EDH_RSA_DES_SHA: - des_setkey_enc( (des_context *) ssl->ctx_enc, key1 ); - des_setkey_dec( (des_context *) ssl->ctx_dec, key2 ); + des_setkey_enc( (des_context *) transform->ctx_enc, key1 ); + des_setkey_dec( (des_context *) transform->ctx_dec, key2 ); break; #endif #endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */ @@ -635,15 +648,15 @@ int ssl_derive_keys( ssl_context *ssl ) #if defined(POLARSSL_ZLIB_SUPPORT) // Initialize compression // - if( ssl->session->compression == SSL_COMPRESS_DEFLATE ) + if( session->compression == SSL_COMPRESS_DEFLATE ) { SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); - memset( &ssl->ctx_deflate, 0, sizeof( ssl->ctx_deflate ) ); - memset( &ssl->ctx_inflate, 0, sizeof( ssl->ctx_inflate ) ); + memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) ); + memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) ); - if( deflateInit( &ssl->ctx_deflate, Z_DEFAULT_COMPRESSION ) != Z_OK || - inflateInit( &ssl->ctx_inflate ) != Z_OK ) + if( deflateInit( &transform->ctx_deflate, Z_DEFAULT_COMPRESSION ) != Z_OK || + inflateInit( &transform->ctx_inflate ) != Z_OK ) { SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) ); return( POLARSSL_ERR_SSL_COMPRESSION_FAILED ); @@ -665,29 +678,28 @@ void ssl_calc_verify_ssl( ssl_context *ssl, unsigned char hash[36] ) SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); - memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) ); - memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ), - sizeof( sha1_context ) ); + memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) ); + memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) ); memset( pad_1, 0x36, 48 ); memset( pad_2, 0x5C, 48 ); - md5_update( &md5, ssl->session->master, 48 ); + md5_update( &md5, ssl->session_negotiate->master, 48 ); md5_update( &md5, pad_1, 48 ); md5_finish( &md5, hash ); md5_starts( &md5 ); - md5_update( &md5, ssl->session->master, 48 ); + md5_update( &md5, ssl->session_negotiate->master, 48 ); md5_update( &md5, pad_2, 48 ); md5_update( &md5, hash, 16 ); md5_finish( &md5, hash ); - sha1_update( &sha1, ssl->session->master, 48 ); + sha1_update( &sha1, ssl->session_negotiate->master, 48 ); sha1_update( &sha1, pad_1, 40 ); sha1_finish( &sha1, hash + 16 ); sha1_starts( &sha1 ); - sha1_update( &sha1, ssl->session->master, 48 ); + sha1_update( &sha1, ssl->session_negotiate->master, 48 ); sha1_update( &sha1, pad_2, 40 ); sha1_update( &sha1, hash + 16, 20 ); sha1_finish( &sha1, hash + 16 ); @@ -705,11 +717,10 @@ void ssl_calc_verify_tls( ssl_context *ssl, unsigned char hash[36] ) SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); - memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) ); - memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ), - sizeof( sha1_context ) ); + memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) ); + memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) ); - md5_finish( &md5, hash ); + md5_finish( &md5, hash ); sha1_finish( &sha1, hash + 16 ); SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); @@ -724,7 +735,7 @@ void ssl_calc_verify_tls_sha256( ssl_context *ssl, unsigned char hash[32] ) SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); - memcpy( &sha2 , (sha2_context *) ssl->ctx_checksum, sizeof(sha2_context) ); + memcpy( &sha2, &ssl->handshake->fin_sha2, sizeof(sha2_context) ); sha2_finish( &sha2, hash ); SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); @@ -739,7 +750,7 @@ void ssl_calc_verify_tls_sha384( ssl_context *ssl, unsigned char hash[48] ) SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); - memcpy( &sha4 , (sha4_context *) ssl->ctx_checksum, sizeof(sha4_context) ); + memcpy( &sha4, &ssl->handshake->fin_sha4, sizeof(sha4_context) ); sha4_finish( &sha4, hash ); SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); @@ -852,66 +863,68 @@ static int ssl_encrypt_buf( ssl_context *ssl ) */ if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) { - if( ssl->maclen == 16 ) - ssl_mac_md5( ssl->mac_enc, + if( ssl->transform_out->maclen == 16 ) + ssl_mac_md5( ssl->transform_out->mac_enc, ssl->out_msg, ssl->out_msglen, ssl->out_ctr, ssl->out_msgtype ); - else if( ssl->maclen == 20 ) - ssl_mac_sha1( ssl->mac_enc, + else if( ssl->transform_out->maclen == 20 ) + ssl_mac_sha1( ssl->transform_out->mac_enc, ssl->out_msg, ssl->out_msglen, ssl->out_ctr, ssl->out_msgtype ); - else if( ssl->maclen == 32 ) - ssl_mac_sha2( ssl->mac_enc, + else if( ssl->transform_out->maclen == 32 ) + ssl_mac_sha2( ssl->transform_out->mac_enc, ssl->out_msg, ssl->out_msglen, ssl->out_ctr, ssl->out_msgtype ); - else if( ssl->maclen != 0 ) + else if( ssl->transform_out->maclen != 0 ) { - SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d", ssl->maclen ) ); + SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d", + ssl->transform_out->maclen ) ); return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); } } else { - if( ssl->maclen == 16 ) + if( ssl->transform_out->maclen == 16 ) { md5_context ctx; - md5_hmac_starts( &ctx, ssl->mac_enc, 16 ); + md5_hmac_starts( &ctx, ssl->transform_out->mac_enc, 16 ); md5_hmac_update( &ctx, ssl->out_ctr, 13 ); md5_hmac_update( &ctx, ssl->out_msg, ssl->out_msglen ); md5_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen ); memset( &ctx, 0, sizeof(md5_context)); } - else if( ssl->maclen == 20 ) + else if( ssl->transform_out->maclen == 20 ) { sha1_context ctx; - sha1_hmac_starts( &ctx, ssl->mac_enc, 20 ); + sha1_hmac_starts( &ctx, ssl->transform_out->mac_enc, 20 ); sha1_hmac_update( &ctx, ssl->out_ctr, 13 ); sha1_hmac_update( &ctx, ssl->out_msg, ssl->out_msglen ); sha1_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen ); memset( &ctx, 0, sizeof(sha1_context)); } - else if( ssl->maclen == 32 ) + else if( ssl->transform_out->maclen == 32 ) { sha2_context ctx; - sha2_hmac_starts( &ctx, ssl->mac_enc, 32, 0 ); + sha2_hmac_starts( &ctx, ssl->transform_out->mac_enc, 32, 0 ); sha2_hmac_update( &ctx, ssl->out_ctr, 13 ); sha2_hmac_update( &ctx, ssl->out_msg, ssl->out_msglen ); sha2_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen ); memset( &ctx, 0, sizeof(sha2_context)); } - else if( ssl->maclen != 0 ) + else if( ssl->transform_out->maclen != 0 ) { - SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d", ssl->maclen ) ); + SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d", + ssl->transform_out->maclen ) ); return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); } } SSL_DEBUG_BUF( 4, "computed mac", - ssl->out_msg + ssl->out_msglen, ssl->maclen ); + ssl->out_msg + ssl->out_msglen, ssl->transform_out->maclen ); - ssl->out_msglen += ssl->maclen; + ssl->out_msglen += ssl->transform_out->maclen; - if( ssl->ivlen == 0 ) + if( ssl->transform_out->ivlen == 0 ) { padlen = 0; @@ -923,24 +936,24 @@ static int ssl_encrypt_buf( ssl_context *ssl ) ssl->out_msg, ssl->out_msglen ); #if defined(POLARSSL_ARC4_C) - if( ssl->session->ciphersuite == SSL_RSA_RC4_128_MD5 || - ssl->session->ciphersuite == SSL_RSA_RC4_128_SHA ) + if( ssl->session_out->ciphersuite == SSL_RSA_RC4_128_MD5 || + ssl->session_out->ciphersuite == SSL_RSA_RC4_128_SHA ) { - arc4_crypt( (arc4_context *) ssl->ctx_enc, + arc4_crypt( (arc4_context *) ssl->transform_out->ctx_enc, ssl->out_msglen, ssl->out_msg, ssl->out_msg ); } else #endif #if defined(POLARSSL_CIPHER_NULL_CIPHER) - if( ssl->session->ciphersuite == SSL_RSA_NULL_MD5 || - ssl->session->ciphersuite == SSL_RSA_NULL_SHA || - ssl->session->ciphersuite == SSL_RSA_NULL_SHA256 ) + if( ssl->session_out->ciphersuite == SSL_RSA_NULL_MD5 || + ssl->session_out->ciphersuite == SSL_RSA_NULL_SHA || + ssl->session_out->ciphersuite == SSL_RSA_NULL_SHA256 ) { } else #endif return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); } - else if( ssl->ivlen == 12 ) + else if( ssl->transform_out->ivlen == 12 ) { size_t enc_msglen; unsigned char *enc_msg; @@ -962,33 +975,38 @@ static int ssl_encrypt_buf( ssl_context *ssl ) #if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C) - if( ssl->session->ciphersuite == SSL_RSA_AES_128_GCM_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || - ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + if( ssl->session_out->ciphersuite == SSL_RSA_AES_128_GCM_SHA256 || + ssl->session_out->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || + ssl->session_out->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || + ssl->session_out->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) { /* * Generate IV */ - ret = ssl->f_rng( ssl->p_rng, ssl->iv_enc + ssl->fixed_ivlen, - ssl->ivlen - ssl->fixed_ivlen ); + ret = ssl->f_rng( ssl->p_rng, + ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, + ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); if( ret != 0 ) return( ret ); /* * Shift message for ivlen bytes and prepend IV */ - memmove( ssl->out_msg + ssl->ivlen - ssl->fixed_ivlen, + memmove( ssl->out_msg + ssl->transform_out->ivlen - + ssl->transform_out->fixed_ivlen, ssl->out_msg, ssl->out_msglen ); - memcpy( ssl->out_msg, ssl->iv_enc + ssl->fixed_ivlen, - ssl->ivlen - ssl->fixed_ivlen ); + memcpy( ssl->out_msg, + ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, + ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); /* * Fix pointer positions and message length with added IV */ - enc_msg = ssl->out_msg + ssl->ivlen - ssl->fixed_ivlen; + enc_msg = ssl->out_msg + ssl->transform_out->ivlen - + ssl->transform_out->fixed_ivlen; enc_msglen = ssl->out_msglen; - ssl->out_msglen += ssl->ivlen - ssl->fixed_ivlen; + ssl->out_msglen += ssl->transform_out->ivlen - + ssl->transform_out->fixed_ivlen; SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " "including %d bytes of padding", @@ -1002,9 +1020,9 @@ static int ssl_encrypt_buf( ssl_context *ssl ) */ ssl->out_msglen += 16; - gcm_crypt_and_tag( (gcm_context *) ssl->ctx_enc, + gcm_crypt_and_tag( (gcm_context *) ssl->transform_out->ctx_enc, GCM_ENCRYPT, enc_msglen, - ssl->iv_enc, ssl->ivlen, + ssl->transform_out->iv_enc, ssl->transform_out->ivlen, add_data, 13, enc_msg, enc_msg, 16, enc_msg + enc_msglen ); @@ -1021,8 +1039,9 @@ static int ssl_encrypt_buf( ssl_context *ssl ) unsigned char *enc_msg; size_t enc_msglen; - padlen = ssl->ivlen - ( ssl->out_msglen + 1 ) % ssl->ivlen; - if( padlen == ssl->ivlen ) + padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) % + ssl->transform_out->ivlen; + if( padlen == ssl->transform_out->ivlen ) padlen = 0; for( i = 0; i <= padlen; i++ ) @@ -1042,82 +1061,85 @@ static int ssl_encrypt_buf( ssl_context *ssl ) /* * Generate IV */ - int ret = ssl->f_rng( ssl->p_rng, ssl->iv_enc, ssl->ivlen ); + int ret = ssl->f_rng( ssl->p_rng, ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ); if( ret != 0 ) return( ret ); /* * Shift message for ivlen bytes and prepend IV */ - memmove( ssl->out_msg + ssl->ivlen, ssl->out_msg, ssl->out_msglen ); - memcpy( ssl->out_msg, ssl->iv_enc, ssl->ivlen ); + memmove( ssl->out_msg + ssl->transform_out->ivlen, ssl->out_msg, + ssl->out_msglen ); + memcpy( ssl->out_msg, ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ); /* * Fix pointer positions and message length with added IV */ - enc_msg = ssl->out_msg + ssl->ivlen; + enc_msg = ssl->out_msg + ssl->transform_out->ivlen; enc_msglen = ssl->out_msglen; - ssl->out_msglen += ssl->ivlen; + ssl->out_msglen += ssl->transform_out->ivlen; } SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " "including %d bytes of IV and %d bytes of padding", - ssl->out_msglen, ssl->ivlen, padlen + 1 ) ); + ssl->out_msglen, ssl->transform_out->ivlen, padlen + 1 ) ); SSL_DEBUG_BUF( 4, "before encrypt: output payload", ssl->out_msg, ssl->out_msglen ); - switch( ssl->ivlen ) + switch( ssl->transform_out->ivlen ) { #if defined(POLARSSL_DES_C) case 8: #if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) - if( ssl->session->ciphersuite == SSL_RSA_DES_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA ) + if( ssl->session_out->ciphersuite == SSL_RSA_DES_SHA || + ssl->session_out->ciphersuite == SSL_EDH_RSA_DES_SHA ) { - des_crypt_cbc( (des_context *) ssl->ctx_enc, + des_crypt_cbc( (des_context *) ssl->transform_out->ctx_enc, DES_ENCRYPT, enc_msglen, - ssl->iv_enc, enc_msg, enc_msg ); + ssl->transform_out->iv_enc, enc_msg, enc_msg ); } else #endif - des3_crypt_cbc( (des3_context *) ssl->ctx_enc, - DES_ENCRYPT, enc_msglen, - ssl->iv_enc, enc_msg, enc_msg ); + des3_crypt_cbc( (des3_context *) ssl->transform_out->ctx_enc, + DES_ENCRYPT, enc_msglen, + ssl->transform_out->iv_enc, enc_msg, enc_msg ); break; #endif case 16: #if defined(POLARSSL_AES_C) - if ( ssl->session->ciphersuite == SSL_RSA_AES_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA || - ssl->session->ciphersuite == SSL_RSA_AES_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA || - ssl->session->ciphersuite == SSL_RSA_AES_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 || - ssl->session->ciphersuite == SSL_RSA_AES_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 ) + if ( ssl->session_out->ciphersuite == SSL_RSA_AES_128_SHA || + ssl->session_out->ciphersuite == SSL_EDH_RSA_AES_128_SHA || + ssl->session_out->ciphersuite == SSL_RSA_AES_256_SHA || + ssl->session_out->ciphersuite == SSL_EDH_RSA_AES_256_SHA || + ssl->session_out->ciphersuite == SSL_RSA_AES_128_SHA256 || + ssl->session_out->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 || + ssl->session_out->ciphersuite == SSL_RSA_AES_256_SHA256 || + ssl->session_out->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 ) { - aes_crypt_cbc( (aes_context *) ssl->ctx_enc, + aes_crypt_cbc( (aes_context *) ssl->transform_out->ctx_enc, AES_ENCRYPT, enc_msglen, - ssl->iv_enc, enc_msg, enc_msg); + ssl->transform_out->iv_enc, enc_msg, enc_msg); break; } #endif #if defined(POLARSSL_CAMELLIA_C) - if ( ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || - ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || - ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 ) + if ( ssl->session_out->ciphersuite == SSL_RSA_CAMELLIA_128_SHA || + ssl->session_out->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || + ssl->session_out->ciphersuite == SSL_RSA_CAMELLIA_256_SHA || + ssl->session_out->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || + ssl->session_out->ciphersuite == SSL_RSA_CAMELLIA_128_SHA256 || + ssl->session_out->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || + ssl->session_out->ciphersuite == SSL_RSA_CAMELLIA_256_SHA256 || + ssl->session_out->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 ) { - camellia_crypt_cbc( (camellia_context *) ssl->ctx_enc, + camellia_crypt_cbc( (camellia_context *) ssl->transform_out->ctx_enc, CAMELLIA_ENCRYPT, enc_msglen, - ssl->iv_enc, enc_msg, enc_msg ); + ssl->transform_out->iv_enc, enc_msg, enc_msg ); break; } #endif @@ -1148,35 +1170,35 @@ static int ssl_decrypt_buf( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); - if( ssl->in_msglen < ssl->minlen ) + if( ssl->in_msglen < ssl->transform_in->minlen ) { SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)", - ssl->in_msglen, ssl->minlen ) ); + ssl->in_msglen, ssl->transform_in->minlen ) ); return( POLARSSL_ERR_SSL_INVALID_MAC ); } - if( ssl->ivlen == 0 ) + if( ssl->transform_in->ivlen == 0 ) { #if defined(POLARSSL_ARC4_C) padlen = 0; - if( ssl->session->ciphersuite == SSL_RSA_RC4_128_MD5 || - ssl->session->ciphersuite == SSL_RSA_RC4_128_SHA ) + if( ssl->session_in->ciphersuite == SSL_RSA_RC4_128_MD5 || + ssl->session_in->ciphersuite == SSL_RSA_RC4_128_SHA ) { - arc4_crypt( (arc4_context *) ssl->ctx_dec, + arc4_crypt( (arc4_context *) ssl->transform_in->ctx_dec, ssl->in_msglen, ssl->in_msg, ssl->in_msg ); } else #endif #if defined(POLARSSL_CIPHER_NULL_CIPHER) - if( ssl->session->ciphersuite == SSL_RSA_NULL_MD5 || - ssl->session->ciphersuite == SSL_RSA_NULL_SHA || - ssl->session->ciphersuite == SSL_RSA_NULL_SHA256 ) + if( ssl->session_in->ciphersuite == SSL_RSA_NULL_MD5 || + ssl->session_in->ciphersuite == SSL_RSA_NULL_SHA || + ssl->session_in->ciphersuite == SSL_RSA_NULL_SHA256 ) { } else #endif return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); } - else if( ssl->ivlen == 12 ) + else if( ssl->transform_in->ivlen == 12 ) { unsigned char *dec_msg; unsigned char *dec_msg_result; @@ -1187,14 +1209,16 @@ static int ssl_decrypt_buf( ssl_context *ssl ) padlen = 0; #if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C) - if( ssl->session->ciphersuite == SSL_RSA_AES_128_GCM_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || - ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + if( ssl->session_in->ciphersuite == SSL_RSA_AES_128_GCM_SHA256 || + ssl->session_in->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || + ssl->session_in->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || + ssl->session_in->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) { - dec_msglen = ssl->in_msglen - ( ssl->ivlen - ssl->fixed_ivlen ); + dec_msglen = ssl->in_msglen - ( ssl->transform_in->ivlen - + ssl->transform_in->fixed_ivlen ); dec_msglen -= 16; - dec_msg = ssl->in_msg + ( ssl->ivlen - ssl->fixed_ivlen ); + dec_msg = ssl->in_msg + ( ssl->transform_in->ivlen - + ssl->transform_in->fixed_ivlen ); dec_msg_result = ssl->in_msg; ssl->in_msglen = dec_msglen; @@ -1208,18 +1232,22 @@ static int ssl_decrypt_buf( ssl_context *ssl ) SSL_DEBUG_BUF( 4, "additional data used for AEAD", add_data, 13 ); - memcpy( ssl->iv_dec + ssl->fixed_ivlen, ssl->in_msg, - ssl->ivlen - ssl->fixed_ivlen ); + memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen, + ssl->in_msg, + ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen ); - SSL_DEBUG_BUF( 4, "IV used", ssl->iv_dec, ssl->ivlen ); + SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec, + ssl->transform_in->ivlen ); SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 ); - memcpy( ssl->iv_dec + ssl->fixed_ivlen, ssl->in_msg, - ssl->ivlen - ssl->fixed_ivlen ); + memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen, + ssl->in_msg, + ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen ); - ret = gcm_auth_decrypt( (gcm_context *) ssl->ctx_dec, + ret = gcm_auth_decrypt( (gcm_context *) ssl->transform_in->ctx_dec, dec_msglen, - ssl->iv_dec, ssl->ivlen, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, add_data, 13, dec_msg + dec_msglen, 16, dec_msg, dec_msg_result ); @@ -1244,10 +1272,10 @@ static int ssl_decrypt_buf( ssl_context *ssl ) /* * Decrypt and check the padding */ - if( ssl->in_msglen % ssl->ivlen != 0 ) + if( ssl->in_msglen % ssl->transform_in->ivlen != 0 ) { SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", - ssl->in_msglen, ssl->ivlen ) ); + ssl->in_msglen, ssl->transform_in->ivlen ) ); return( POLARSSL_ERR_SSL_INVALID_MAC ); } @@ -1260,65 +1288,65 @@ static int ssl_decrypt_buf( ssl_context *ssl ) */ if( ssl->minor_ver >= SSL_MINOR_VERSION_2 ) { - dec_msg += ssl->ivlen; - dec_msglen -= ssl->ivlen; - ssl->in_msglen -= ssl->ivlen; + dec_msg += ssl->transform_in->ivlen; + dec_msglen -= ssl->transform_in->ivlen; + ssl->in_msglen -= ssl->transform_in->ivlen; - for( i = 0; i < ssl->ivlen; i++ ) - ssl->iv_dec[i] = ssl->in_msg[i]; + for( i = 0; i < ssl->transform_in->ivlen; i++ ) + ssl->transform_in->iv_dec[i] = ssl->in_msg[i]; } - switch( ssl->ivlen ) + switch( ssl->transform_in->ivlen ) { #if defined(POLARSSL_DES_C) case 8: #if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) - if( ssl->session->ciphersuite == SSL_RSA_DES_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA ) + if( ssl->session_in->ciphersuite == SSL_RSA_DES_SHA || + ssl->session_in->ciphersuite == SSL_EDH_RSA_DES_SHA ) { - des_crypt_cbc( (des_context *) ssl->ctx_dec, + des_crypt_cbc( (des_context *) ssl->transform_in->ctx_dec, DES_DECRYPT, dec_msglen, - ssl->iv_dec, dec_msg, dec_msg_result ); + ssl->transform_in->iv_dec, dec_msg, dec_msg_result ); } else #endif - des3_crypt_cbc( (des3_context *) ssl->ctx_dec, + des3_crypt_cbc( (des3_context *) ssl->transform_in->ctx_dec, DES_DECRYPT, dec_msglen, - ssl->iv_dec, dec_msg, dec_msg_result ); + ssl->transform_in->iv_dec, dec_msg, dec_msg_result ); break; #endif case 16: #if defined(POLARSSL_AES_C) - if ( ssl->session->ciphersuite == SSL_RSA_AES_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA || - ssl->session->ciphersuite == SSL_RSA_AES_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA || - ssl->session->ciphersuite == SSL_RSA_AES_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 || - ssl->session->ciphersuite == SSL_RSA_AES_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 ) + if ( ssl->session_in->ciphersuite == SSL_RSA_AES_128_SHA || + ssl->session_in->ciphersuite == SSL_EDH_RSA_AES_128_SHA || + ssl->session_in->ciphersuite == SSL_RSA_AES_256_SHA || + ssl->session_in->ciphersuite == SSL_EDH_RSA_AES_256_SHA || + ssl->session_in->ciphersuite == SSL_RSA_AES_128_SHA256 || + ssl->session_in->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 || + ssl->session_in->ciphersuite == SSL_RSA_AES_256_SHA256 || + ssl->session_in->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 ) { - aes_crypt_cbc( (aes_context *) ssl->ctx_dec, + aes_crypt_cbc( (aes_context *) ssl->transform_in->ctx_dec, AES_DECRYPT, dec_msglen, - ssl->iv_dec, dec_msg, dec_msg_result ); + ssl->transform_in->iv_dec, dec_msg, dec_msg_result ); break; } #endif #if defined(POLARSSL_CAMELLIA_C) - if ( ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || - ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || - ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 ) + if ( ssl->session_in->ciphersuite == SSL_RSA_CAMELLIA_128_SHA || + ssl->session_in->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || + ssl->session_in->ciphersuite == SSL_RSA_CAMELLIA_256_SHA || + ssl->session_in->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || + ssl->session_in->ciphersuite == SSL_RSA_CAMELLIA_128_SHA256 || + ssl->session_in->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || + ssl->session_in->ciphersuite == SSL_RSA_CAMELLIA_256_SHA256 || + ssl->session_in->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 ) { - camellia_crypt_cbc( (camellia_context *) ssl->ctx_dec, + camellia_crypt_cbc( (camellia_context *) ssl->transform_in->ctx_dec, CAMELLIA_DECRYPT, dec_msglen, - ssl->iv_dec, dec_msg, dec_msg_result ); + ssl->transform_in->iv_dec, dec_msg, dec_msg_result ); break; } #endif @@ -1331,11 +1359,11 @@ static int ssl_decrypt_buf( ssl_context *ssl ) if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) { - if( padlen > ssl->ivlen ) + if( padlen > ssl->transform_in->ivlen ) { SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " "should be no more than %d", - padlen, ssl->ivlen ) ); + padlen, ssl->transform_in->ivlen ) ); padlen = 0; } } @@ -1363,14 +1391,14 @@ static int ssl_decrypt_buf( ssl_context *ssl ) /* * Always compute the MAC (RFC4346, CBCTIME). */ - if( ssl->in_msglen < ssl->maclen + padlen ) + if( ssl->in_msglen < ssl->transform_in->maclen + padlen ) { SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", - ssl->in_msglen, ssl->maclen, padlen ) ); + ssl->in_msglen, ssl->transform_in->maclen, padlen ) ); return( POLARSSL_ERR_SSL_INVALID_MAC ); } - ssl->in_msglen -= ( ssl->maclen + padlen ); + ssl->in_msglen -= ( ssl->transform_in->maclen + padlen ); ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 ); ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen ); @@ -1379,37 +1407,53 @@ static int ssl_decrypt_buf( ssl_context *ssl ) if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) { - if( ssl->maclen == 16 ) - ssl_mac_md5( ssl->mac_dec, + if( ssl->transform_in->maclen == 16 ) + ssl_mac_md5( ssl->transform_in->mac_dec, ssl->in_msg, ssl->in_msglen, ssl->in_ctr, ssl->in_msgtype ); - else if( ssl->maclen == 20 ) - ssl_mac_sha1( ssl->mac_dec, + else if( ssl->transform_in->maclen == 20 ) + ssl_mac_sha1( ssl->transform_in->mac_dec, ssl->in_msg, ssl->in_msglen, ssl->in_ctr, ssl->in_msgtype ); + else if( ssl->transform_in->maclen == 32 ) + ssl_mac_sha2( ssl->transform_in->mac_dec, + ssl->in_msg, ssl->in_msglen, + ssl->in_ctr, ssl->in_msgtype ); + else if( ssl->transform_in->maclen != 0 ) + { + SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d", + ssl->transform_in->maclen ) ); + return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); + } } else { - if( ssl->maclen == 16 ) - md5_hmac( ssl->mac_dec, 16, + if( ssl->transform_in->maclen == 16 ) + md5_hmac( ssl->transform_in->mac_dec, 16, ssl->in_ctr, ssl->in_msglen + 13, ssl->in_msg + ssl->in_msglen ); - else if( ssl->maclen == 20 ) - sha1_hmac( ssl->mac_dec, 20, + else if( ssl->transform_in->maclen == 20 ) + sha1_hmac( ssl->transform_in->mac_dec, 20, ssl->in_ctr, ssl->in_msglen + 13, ssl->in_msg + ssl->in_msglen ); - else if( ssl->maclen == 32 ) - sha2_hmac( ssl->mac_dec, 32, + else if( ssl->transform_in->maclen == 32 ) + sha2_hmac( ssl->transform_in->mac_dec, 32, ssl->in_ctr, ssl->in_msglen + 13, ssl->in_msg + ssl->in_msglen, 0 ); + else if( ssl->transform_in->maclen != 0 ) + { + SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d", + ssl->transform_in->maclen ) ); + return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); + } } - SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->maclen ); + SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->transform_in->maclen ); SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen, - ssl->maclen ); + ssl->transform_in->maclen ); if( memcmp( tmp, ssl->in_msg + ssl->in_msglen, - ssl->maclen ) != 0 ) + ssl->transform_in->maclen ) != 0 ) { SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); return( POLARSSL_ERR_SSL_INVALID_MAC ); @@ -1419,7 +1463,8 @@ static int ssl_decrypt_buf( ssl_context *ssl ) * Finally check the padding length; bad padding * will produce the same error as an invalid MAC. */ - if( ssl->ivlen != 0 && ssl->ivlen != 12 && padlen == 0 ) + if( ssl->transform_in->ivlen != 0 && ssl->transform_in->ivlen != 12 && + padlen == 0 ) return( POLARSSL_ERR_SSL_INVALID_MAC ); if( ssl->in_msglen == 0 ) @@ -1477,19 +1522,19 @@ static int ssl_compress_buf( ssl_context *ssl ) SSL_DEBUG_BUF( 4, "before compression: output payload", ssl->out_msg, ssl->out_msglen ); - ssl->ctx_deflate.next_in = msg_pre; - ssl->ctx_deflate.avail_in = len_pre; - ssl->ctx_deflate.next_out = msg_post; - ssl->ctx_deflate.avail_out = SSL_BUFFER_LEN; + ssl->transform_out->ctx_deflate.next_in = msg_pre; + ssl->transform_out->ctx_deflate.avail_in = len_pre; + ssl->transform_out->ctx_deflate.next_out = msg_post; + ssl->transform_out->ctx_deflate.avail_out = SSL_BUFFER_LEN; - ret = deflate( &ssl->ctx_deflate, Z_SYNC_FLUSH ); + ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); if( ret != Z_OK ) { SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); return( POLARSSL_ERR_SSL_COMPRESSION_FAILED ); } - ssl->out_msglen = SSL_BUFFER_LEN - ssl->ctx_deflate.avail_out; + ssl->out_msglen = SSL_BUFFER_LEN - ssl->transform_out->ctx_deflate.avail_out; free( msg_pre ); @@ -1528,19 +1573,19 @@ static int ssl_decompress_buf( ssl_context *ssl ) SSL_DEBUG_BUF( 4, "before decompression: input payload", ssl->in_msg, ssl->in_msglen ); - ssl->ctx_inflate.next_in = msg_pre; - ssl->ctx_inflate.avail_in = len_pre; - ssl->ctx_inflate.next_out = msg_post; - ssl->ctx_inflate.avail_out = SSL_MAX_CONTENT_LEN; + ssl->transform_in->ctx_inflate.next_in = msg_pre; + ssl->transform_in->ctx_inflate.avail_in = len_pre; + ssl->transform_in->ctx_inflate.next_out = msg_post; + ssl->transform_in->ctx_inflate.avail_out = SSL_MAX_CONTENT_LEN; - ret = inflate( &ssl->ctx_inflate, Z_SYNC_FLUSH ); + ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); if( ret != Z_OK ) { SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); return( POLARSSL_ERR_SSL_COMPRESSION_FAILED ); } - ssl->in_msglen = SSL_MAX_CONTENT_LEN - ssl->ctx_inflate.avail_out; + ssl->in_msglen = SSL_MAX_CONTENT_LEN - ssl->transform_in->ctx_inflate.avail_out; free( msg_pre ); @@ -1651,12 +1696,12 @@ int ssl_write_record( ssl_context *ssl ) ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 ); ssl->out_msg[3] = (unsigned char)( ( len - 4 ) ); - ssl->update_checksum( ssl, ssl->out_msg, len ); + ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); } #if defined(POLARSSL_ZLIB_SUPPORT) - if( ssl->do_crypt != 0 && - ssl->session->compression == SSL_COMPRESS_DEFLATE ) + if( ssl->transform_out != NULL && + ssl->session_out->compression == SSL_COMPRESS_DEFLATE ) { if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) { @@ -1690,7 +1735,7 @@ int ssl_write_record( ssl_context *ssl ) ssl->out_hdr[3] = (unsigned char)( len >> 8 ); ssl->out_hdr[4] = (unsigned char)( len ); - if( ssl->do_crypt != 0 ) + if( ssl->transform_out != NULL ) { if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 ) { @@ -1742,7 +1787,7 @@ int ssl_read_record( ssl_context *ssl ) ssl->in_msglen -= ssl->in_hslen; memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, - ssl->in_msglen ); + ssl->in_msglen ); ssl->in_hslen = 4; ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3]; @@ -1763,7 +1808,7 @@ int ssl_read_record( ssl_context *ssl ) return( POLARSSL_ERR_SSL_INVALID_RECORD ); } - ssl->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); return( 0 ); } @@ -1802,7 +1847,7 @@ int ssl_read_record( ssl_context *ssl ) /* * Make sure the message length is acceptable */ - if( ssl->do_crypt == 0 ) + if( ssl->transform_in == NULL ) { if( ssl->in_msglen < 1 || ssl->in_msglen > SSL_MAX_CONTENT_LEN ) @@ -1813,14 +1858,14 @@ int ssl_read_record( ssl_context *ssl ) } else { - if( ssl->in_msglen < ssl->minlen ) + if( ssl->in_msglen < ssl->transform_in->minlen ) { SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( POLARSSL_ERR_SSL_INVALID_RECORD ); } if( ssl->minor_ver == SSL_MINOR_VERSION_0 && - ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN ) + ssl->in_msglen > ssl->transform_in->minlen + SSL_MAX_CONTENT_LEN ) { SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( POLARSSL_ERR_SSL_INVALID_RECORD ); @@ -1830,7 +1875,7 @@ int ssl_read_record( ssl_context *ssl ) * TLS encrypted messages can have up to 256 bytes of padding */ if( ssl->minor_ver >= SSL_MINOR_VERSION_1 && - ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN + 256 ) + ssl->in_msglen > ssl->transform_in->minlen + SSL_MAX_CONTENT_LEN + 256 ) { SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( POLARSSL_ERR_SSL_INVALID_RECORD ); @@ -1863,7 +1908,7 @@ int ssl_read_record( ssl_context *ssl ) done = 1; } #endif - if( !done && ssl->do_crypt != 0 ) + if( !done && ssl->transform_in != NULL ) { if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 ) { @@ -1882,8 +1927,8 @@ int ssl_read_record( ssl_context *ssl ) } #if defined(POLARSSL_ZLIB_SUPPORT) - if( ssl->do_crypt != 0 && - ssl->session->compression == SSL_COMPRESS_DEFLATE ) + if( ssl->transform_in != NULL && + ssl->session_in->compression == SSL_COMPRESS_DEFLATE ) { if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) { @@ -1903,8 +1948,9 @@ int ssl_read_record( ssl_context *ssl ) { SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); - if( ( ret = ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, - SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 ) + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 ) { return( ret ); } @@ -1936,7 +1982,8 @@ int ssl_read_record( ssl_context *ssl ) return( POLARSSL_ERR_SSL_INVALID_RECORD ); } - ssl->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + if( ssl->state != SSL_HANDSHAKE_OVER ) + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); } if( ssl->in_msgtype == SSL_MSG_ALERT ) @@ -2183,7 +2230,7 @@ int ssl_parse_certificate( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); } - if( ( ssl->peer_cert = (x509_cert *) malloc( + if( ( ssl->session_negotiate->peer_cert = (x509_cert *) malloc( sizeof( x509_cert ) ) ) == NULL ) { SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", @@ -2191,7 +2238,7 @@ int ssl_parse_certificate( ssl_context *ssl ) return( POLARSSL_ERR_SSL_MALLOC_FAILED ); } - memset( ssl->peer_cert, 0, sizeof( x509_cert ) ); + memset( ssl->session_negotiate->peer_cert, 0, sizeof( x509_cert ) ); i = 7; @@ -2213,7 +2260,8 @@ int ssl_parse_certificate( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); } - ret = x509parse_crt( ssl->peer_cert, ssl->in_msg + i, n ); + ret = x509parse_crt( ssl->session_negotiate->peer_cert, ssl->in_msg + i, + n ); if( ret != 0 ) { SSL_DEBUG_RET( 1, " x509parse_crt", ret ); @@ -2223,7 +2271,7 @@ int ssl_parse_certificate( ssl_context *ssl ) i += n; } - SSL_DEBUG_CRT( 3, "peer certificate", ssl->peer_cert ); + SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert ); if( ssl->authmode != SSL_VERIFY_NONE ) { @@ -2233,7 +2281,8 @@ int ssl_parse_certificate( ssl_context *ssl ) return( POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED ); } - ret = x509parse_verify( ssl->peer_cert, ssl->ca_chain, ssl->ca_crl, + ret = x509parse_verify( ssl->session_negotiate->peer_cert, + ssl->ca_chain, ssl->ca_crl, ssl->peer_cn, &ssl->verify_result, ssl->f_vrfy, ssl->p_vrfy ); @@ -2259,7 +2308,6 @@ int ssl_write_change_cipher_spec( ssl_context *ssl ) ssl->out_msglen = 1; ssl->out_msg[0] = 1; - ssl->do_crypt = 0; ssl->state++; if( ( ret = ssl_write_record( ssl ) ) != 0 ) @@ -2279,8 +2327,6 @@ int ssl_parse_change_cipher_spec( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); - ssl->do_crypt = 0; - if( ( ret = ssl_read_record( ssl ) ) != 0 ) { SSL_DEBUG_RET( 1, "ssl_read_record", ret ); @@ -2306,60 +2352,45 @@ int ssl_parse_change_cipher_spec( ssl_context *ssl ) return( 0 ); } -void ssl_kickstart_checksum( ssl_context *ssl, int ciphersuite, - unsigned char *input_buf, size_t len ) +void ssl_optimize_checksum( ssl_context *ssl, int ciphersuite ) { if( ssl->minor_ver < SSL_MINOR_VERSION_3 ) - { - md5_starts( (md5_context *) ssl->ctx_checksum ); - sha1_starts( (sha1_context *) ( ssl->ctx_checksum + - sizeof(md5_context) ) ); - - ssl->update_checksum = ssl_update_checksum_md5sha1; - } + ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; else if ( ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) { - sha4_starts( (sha4_context *) ssl->ctx_checksum, 1 ); - ssl->update_checksum = ssl_update_checksum_sha384; + ssl->handshake->update_checksum = ssl_update_checksum_sha384; } else - { - sha2_starts( (sha2_context *) ssl->ctx_checksum, 0 ); - ssl->update_checksum = ssl_update_checksum_sha256; - } - - if( ssl->endpoint == SSL_IS_CLIENT ) - ssl->update_checksum( ssl, ssl->out_msg, ssl->out_msglen ); - ssl->update_checksum( ssl, input_buf, len ); + ssl->handshake->update_checksum = ssl_update_checksum_sha256; } static void ssl_update_checksum_start( ssl_context *ssl, unsigned char *buf, size_t len ) { - ((void) ssl); - ((void) buf); - ((void) len); + md5_update( &ssl->handshake->fin_md5 , buf, len ); + sha1_update( &ssl->handshake->fin_sha1, buf, len ); + sha2_update( &ssl->handshake->fin_sha2, buf, len ); + sha4_update( &ssl->handshake->fin_sha4, buf, len ); } static void ssl_update_checksum_md5sha1( ssl_context *ssl, unsigned char *buf, size_t len ) { - md5_update( (md5_context *) ssl->ctx_checksum, buf, len ); - sha1_update( (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ), - buf, len ); + md5_update( &ssl->handshake->fin_md5 , buf, len ); + sha1_update( &ssl->handshake->fin_sha1, buf, len ); } static void ssl_update_checksum_sha256( ssl_context *ssl, unsigned char *buf, size_t len ) { - sha2_update( (sha2_context *) ssl->ctx_checksum, buf, len ); + sha2_update( &ssl->handshake->fin_sha2, buf, len ); } static void ssl_update_checksum_sha384( ssl_context *ssl, unsigned char *buf, size_t len ) { - sha4_update( (sha4_context *) ssl->ctx_checksum, buf, len ); + sha4_update( &ssl->handshake->fin_sha4, buf, len ); } static void ssl_calc_finished_ssl( @@ -2373,11 +2404,14 @@ static void ssl_calc_finished_ssl( unsigned char md5sum[16]; unsigned char sha1sum[20]; + ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) ); - memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) ); - memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ), - sizeof( sha1_context ) ); + memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) ); + memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) ); /* * SSLv3: @@ -2400,25 +2434,25 @@ static void ssl_calc_finished_ssl( memset( padbuf, 0x36, 48 ); md5_update( &md5, (unsigned char *) sender, 4 ); - md5_update( &md5, ssl->session->master, 48 ); + md5_update( &md5, session->master, 48 ); md5_update( &md5, padbuf, 48 ); md5_finish( &md5, md5sum ); sha1_update( &sha1, (unsigned char *) sender, 4 ); - sha1_update( &sha1, ssl->session->master, 48 ); + sha1_update( &sha1, session->master, 48 ); sha1_update( &sha1, padbuf, 40 ); sha1_finish( &sha1, sha1sum ); memset( padbuf, 0x5C, 48 ); md5_starts( &md5 ); - md5_update( &md5, ssl->session->master, 48 ); + md5_update( &md5, session->master, 48 ); md5_update( &md5, padbuf, 48 ); md5_update( &md5, md5sum, 16 ); md5_finish( &md5, buf ); sha1_starts( &sha1 ); - sha1_update( &sha1, ssl->session->master, 48 ); + sha1_update( &sha1, session->master, 48 ); sha1_update( &sha1, padbuf , 40 ); sha1_update( &sha1, sha1sum, 20 ); sha1_finish( &sha1, buf + 16 ); @@ -2444,11 +2478,14 @@ static void ssl_calc_finished_tls( sha1_context sha1; unsigned char padbuf[36]; + ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) ); - memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) ); - memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ), - sizeof( sha1_context ) ); + memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) ); + memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) ); /* * TLSv1: @@ -2469,8 +2506,8 @@ static void ssl_calc_finished_tls( md5_finish( &md5, padbuf ); sha1_finish( &sha1, padbuf + 16 ); - ssl->tls_prf( ssl->session->master, 48, sender, - padbuf, 36, buf, len ); + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 36, buf, len ); SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); @@ -2490,9 +2527,13 @@ static void ssl_calc_finished_tls_sha256( sha2_context sha2; unsigned char padbuf[32]; + ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); - memcpy( &sha2 , (sha2_context *) ssl->ctx_checksum, sizeof(sha2_context) ); + memcpy( &sha2, &ssl->handshake->fin_sha2, sizeof(sha2_context) ); /* * TLSv1.2: @@ -2509,8 +2550,8 @@ static void ssl_calc_finished_tls_sha256( sha2_finish( &sha2, padbuf ); - ssl->tls_prf( ssl->session->master, 48, sender, - padbuf, 32, buf, len ); + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 32, buf, len ); SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); @@ -2529,9 +2570,13 @@ static void ssl_calc_finished_tls_sha384( sha4_context sha4; unsigned char padbuf[48]; + ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); - memcpy( &sha4 , (sha4_context *) ssl->ctx_checksum, sizeof(sha4_context) ); + memcpy( &sha4, &ssl->handshake->fin_sha4, sizeof(sha4_context) ); /* * TLSv1.2: @@ -2548,8 +2593,8 @@ static void ssl_calc_finished_tls_sha384( sha4_finish( &sha4, padbuf ); - ssl->tls_prf( ssl->session->master, 48, sender, - padbuf, 48, buf, len ); + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 48, buf, len ); SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); @@ -2560,17 +2605,66 @@ static void ssl_calc_finished_tls_sha384( SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); } +void ssl_handshake_wrapup( ssl_context *ssl ) +{ + SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); + + /* + * Free our handshake params + */ + ssl_handshake_free( ssl->handshake ); + free( ssl->handshake ); + ssl->handshake = NULL; + + /* + * Switch in our now active transform context + */ + if( ssl->transform ) + { + ssl_transform_free( ssl->transform ); + free( ssl->transform ); + } + 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 ); + ssl->session_negotiate = NULL; + + ssl->state++; + + SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); +} + int ssl_write_finished( ssl_context *ssl ) { int ret, hash_len; SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); - ssl->calc_finished( ssl, ssl->out_msg + 4, ssl->endpoint ); + ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->endpoint ); // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63) hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12; + ssl->verify_data_len = hash_len; + memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len ); + ssl->out_msglen = 4 + hash_len; ssl->out_msgtype = SSL_MSG_HANDSHAKE; ssl->out_msg[0] = SSL_HS_FINISHED; @@ -2582,14 +2676,20 @@ int ssl_write_finished( ssl_context *ssl ) if( ssl->resume != 0 ) { if( ssl->endpoint == SSL_IS_CLIENT ) - ssl->state = SSL_HANDSHAKE_OVER; + ssl->state = SSL_HANDSHAKE_WRAPUP; else ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC; } else ssl->state++; - ssl->do_crypt = 1; + /* + * Switch to our negotiated transform and session parameters for outbound data. + */ + SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); + ssl->transform_out = ssl->transform_negotiate; + ssl->session_out = ssl->session_negotiate; + memset( ssl->out_ctr, 0, 8 ); if( ( ret = ssl_write_record( ssl ) ) != 0 ) { @@ -2610,9 +2710,15 @@ int ssl_parse_finished( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); - ssl->calc_finished( ssl, buf, ssl->endpoint ^ 1 ); + ssl->handshake->calc_finished( ssl, buf, ssl->endpoint ^ 1 ); - ssl->do_crypt = 1; + /* + * Switch to our negotiated transform and session parameters for inbound data. + */ + SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); + ssl->transform_in = ssl->transform_negotiate; + ssl->session_in = ssl->session_negotiate; + memset( ssl->in_ctr, 0, 8 ); if( ( ret = ssl_read_record( ssl ) ) != 0 ) { @@ -2642,13 +2748,16 @@ int ssl_parse_finished( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_FINISHED ); } + ssl->verify_data_len = hash_len; + memcpy( ssl->peer_verify_data, buf, hash_len ); + if( ssl->resume != 0 ) { if( ssl->endpoint == SSL_IS_CLIENT ) ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC; if( ssl->endpoint == SSL_IS_SERVER ) - ssl->state = SSL_HANDSHAKE_OVER; + ssl->state = SSL_HANDSHAKE_WRAPUP; } else ssl->state++; @@ -2658,11 +2767,51 @@ int ssl_parse_finished( ssl_context *ssl ) return( 0 ); } +int ssl_handshake_init( ssl_context *ssl ) +{ + if( ssl->transform_negotiate ) + ssl_transform_free( ssl->transform_negotiate ); + else + ssl->transform_negotiate = malloc( sizeof(ssl_transform) ); + + if( ssl->session_negotiate ) + ssl_session_free( ssl->session_negotiate ); + else + ssl->session_negotiate = malloc( sizeof(ssl_session) ); + + if( ssl->handshake ) + ssl_handshake_free( ssl->handshake ); + else + ssl->handshake = malloc( sizeof(ssl_handshake_params) ); + + if( ssl->handshake == NULL || + ssl->transform_negotiate == NULL || + ssl->session_negotiate == NULL ) + { + SSL_DEBUG_MSG( 1, ( "malloc() of ssl sub-contexts failed" ) ); + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + + memset( ssl->handshake, 0, sizeof(ssl_handshake_params) ); + memset( ssl->transform_negotiate, 0, sizeof(ssl_transform) ); + memset( ssl->session_negotiate, 0, sizeof(ssl_session) ); + + md5_starts( &ssl->handshake->fin_md5 ); + sha1_starts( &ssl->handshake->fin_sha1 ); + sha2_starts( &ssl->handshake->fin_sha2, 0 ); + sha4_starts( &ssl->handshake->fin_sha4, 1 ); + + ssl->handshake->update_checksum = ssl_update_checksum_start; + + return( 0 ); +} + /* * Initialize an SSL context */ int ssl_init( ssl_context *ssl ) { + int ret; int len = SSL_BUFFER_LEN; memset( ssl, 0, sizeof( ssl_context ) ); @@ -2694,7 +2843,8 @@ int ssl_init( ssl_context *ssl ) ssl->hostname = NULL; ssl->hostname_len = 0; - ssl->update_checksum = ssl_update_checksum_start; + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); return( 0 ); } @@ -2705,8 +2855,16 @@ int ssl_init( ssl_context *ssl ) */ int ssl_session_reset( ssl_context *ssl ) { + int ret; + ssl->state = SSL_HELLO_REQUEST; - + ssl->renegotiation = SSL_INITIAL_HANDSHAKE; + ssl->secure_renegotiation = SSL_LEGACY_RENEGOTIATION; + + ssl->verify_data_len = 0; + memset( ssl->own_verify_data, 0, 36 ); + memset( ssl->peer_verify_data, 0, 36 ); + ssl->in_offt = NULL; ssl->in_msgtype = 0; @@ -2720,25 +2878,11 @@ int ssl_session_reset( ssl_context *ssl ) ssl->out_msglen = 0; ssl->out_left = 0; - ssl->do_crypt = 0; - ssl->pmslen = 0; - ssl->keylen = 0; - ssl->minlen = 0; - ssl->ivlen = 0; - ssl->maclen = 0; + ssl->transform_in = NULL; + ssl->transform_out = NULL; memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); memset( ssl->in_ctr, 0, SSL_BUFFER_LEN ); - memset( ssl->randbytes, 0, 64 ); - memset( ssl->premaster, 0, 256 ); - memset( ssl->iv_enc, 0, 16 ); - memset( ssl->iv_dec, 0, 16 ); - memset( ssl->mac_enc, 0, 32 ); - memset( ssl->mac_dec, 0, 32 ); - memset( ssl->ctx_enc, 0, 128 ); - memset( ssl->ctx_dec, 0, 128 ); - - ssl->update_checksum = ssl_update_checksum_start; #if defined(POLARSSL_SSL_HW_RECORD_ACCEL) if( ssl_hw_record_reset != NULL) @@ -2752,29 +2896,15 @@ int ssl_session_reset( ssl_context *ssl ) } #endif -#if defined(POLARSSL_ZLIB_SUPPORT) - // Reset compression state - // - if( ssl->session->compression == SSL_COMPRESS_DEFLATE ) + if( ssl->transform ) { - ssl->ctx_deflate.next_in = Z_NULL; - ssl->ctx_deflate.next_out = Z_NULL; - ssl->ctx_deflate.avail_in = 0; - ssl->ctx_deflate.avail_out = 0; - - ssl->ctx_inflate.next_in = Z_NULL; - ssl->ctx_inflate.next_out = Z_NULL; - ssl->ctx_inflate.avail_in = 0; - ssl->ctx_inflate.avail_out = 0; - - if( deflateReset( &ssl->ctx_deflate ) != Z_OK || - inflateReset( &ssl->ctx_inflate ) != Z_OK ) - { - SSL_DEBUG_MSG( 1, ( "Failed to reset compression" ) ); - return( POLARSSL_ERR_SSL_COMPRESSION_FAILED ); - } + ssl_transform_free( ssl->transform ); + free( ssl->transform ); + ssl->transform = NULL; } -#endif /* POLARSSL_ZLIB_SUPPORT */ + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); return( 0 ); } @@ -2871,17 +3001,18 @@ void ssl_set_own_cert_pkcs11( ssl_context *ssl, x509_cert *own_cert, } #endif +#if defined(POLARSSL_DHM_C) int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G ) { int ret; - if( ( ret = mpi_read_string( &ssl->dhm_ctx.P, 16, dhm_P ) ) != 0 ) + if( ( ret = mpi_read_string( &ssl->dhm_P, 16, dhm_P ) ) != 0 ) { SSL_DEBUG_RET( 1, "mpi_read_string", ret ); return( ret ); } - if( ( ret = mpi_read_string( &ssl->dhm_ctx.G, 16, dhm_G ) ) != 0 ) + if( ( ret = mpi_read_string( &ssl->dhm_G, 16, dhm_G ) ) != 0 ) { SSL_DEBUG_RET( 1, "mpi_read_string", ret ); return( ret ); @@ -2894,13 +3025,13 @@ int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx ) { int ret; - if( ( ret = mpi_copy(&ssl->dhm_ctx.P, &dhm_ctx->P) ) != 0 ) + if( ( ret = mpi_copy(&ssl->dhm_P, &dhm_ctx->P) ) != 0 ) { SSL_DEBUG_RET( 1, "mpi_copy", ret ); return( ret ); } - if( ( ret = mpi_copy(&ssl->dhm_ctx.G, &dhm_ctx->G) ) != 0 ) + if( ( ret = mpi_copy(&ssl->dhm_G, &dhm_ctx->G) ) != 0 ) { SSL_DEBUG_RET( 1, "mpi_copy", ret ); return( ret ); @@ -2908,6 +3039,7 @@ int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx ) return( 0 ); } +#endif /* POLARSSL_DHM_C */ int ssl_set_hostname( ssl_context *ssl, const char *hostname ) { @@ -2934,6 +3066,16 @@ void ssl_set_max_version( ssl_context *ssl, int major, int minor ) ssl->max_minor_ver = minor; } +void ssl_set_renegotiation( ssl_context *ssl, int renegotiation ) +{ + ssl->disable_renegotiation = renegotiation; +} + +void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy ) +{ + ssl->allow_legacy_renegotiation = allow_legacy; +} + /* * SSL get accessors */ @@ -3284,6 +3426,35 @@ int ssl_handshake( ssl_context *ssl ) return( ret ); } +/* + * Renegotiate current connection + */ +int ssl_renegotiate( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); + + if( ssl->state != SSL_HANDSHAKE_OVER ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + ssl->state = SSL_HELLO_REQUEST; + ssl->renegotiation = SSL_RENEGOTIATION; + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + if( ( ret = ssl_handshake( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_handshake", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); + + return( 0 ); +} + /* * Receive application data decrypted from the SSL layer */ @@ -3330,7 +3501,41 @@ int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ) } } - if( ssl->in_msgtype != SSL_MSG_APPLICATION_DATA ) + if( ssl->in_msgtype == SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); + + if( ssl->endpoint == SSL_IS_CLIENT && + ( ssl->in_msg[0] != SSL_HS_HELLO_REQUEST || + ssl->in_hslen != 4 ) ) + { + SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->disable_renegotiation == SSL_RENEGOTIATION_DISABLED ) + { + SSL_DEBUG_MSG( 3, ( "ignoring renegotiation, sending alert" ) ); + + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_WARNING, + SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) + { + return( ret ); + } + } + else + { + if( ( ret = ssl_renegotiate( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_renegotiate", ret ); + return( ret ); + } + + return( POLARSSL_ERR_NET_WANT_READ ); + } + } + else if( ssl->in_msgtype != SSL_MSG_APPLICATION_DATA ) { SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); @@ -3422,14 +3627,10 @@ int ssl_close_notify( ssl_context *ssl ) if( ssl->state == SSL_HANDSHAKE_OVER ) { - ssl->out_msgtype = SSL_MSG_ALERT; - ssl->out_msglen = 2; - ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING; - ssl->out_msg[1] = SSL_ALERT_MSG_CLOSE_NOTIFY; - - if( ( ret = ssl_write_record( ssl ) ) != 0 ) + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_WARNING, + SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) { - SSL_DEBUG_RET( 1, "ssl_write_record", ret ); return( ret ); } } @@ -3439,6 +3640,45 @@ int ssl_close_notify( ssl_context *ssl ) return( ret ); } +void ssl_transform_free( ssl_transform *transform ) +{ +#if defined(POLARSSL_ZLIB_SUPPORT) + deflateEnd( &transform->ctx_deflate ); + inflateEnd( &transform->ctx_inflate ); +#endif + + memset( transform, 0, sizeof( ssl_transform ) ); +} + +void ssl_handshake_free( ssl_handshake_params *handshake ) +{ +#if defined(POLARSSL_DHM_C) + dhm_free( &handshake->dhm_ctx ); +#endif + memset( handshake, 0, sizeof( ssl_handshake_params ) ); +} + +void ssl_session_free( ssl_session *session ) +{ + ssl_session *cur = session, *prv; + + while( cur != 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 ); + } +} + /* * Free an SSL context */ @@ -3446,13 +3686,6 @@ void ssl_free( ssl_context *ssl ) { SSL_DEBUG_MSG( 2, ( "=> free" ) ); - if( ssl->peer_cert != NULL ) - { - x509_free( ssl->peer_cert ); - memset( ssl->peer_cert, 0, sizeof( x509_cert ) ); - free( ssl->peer_cert ); - } - if( ssl->out_ctr != NULL ) { memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); @@ -3466,9 +3699,27 @@ void ssl_free( ssl_context *ssl ) } #if defined(POLARSSL_DHM_C) - dhm_free( &ssl->dhm_ctx ); + mpi_free( &ssl->dhm_P ); + mpi_free( &ssl->dhm_G ); #endif + if( ssl->transform ) + { + ssl_transform_free( ssl->transform ); + free( ssl->transform ); + } + + if( ssl->handshake ) + { + ssl_handshake_free( ssl->handshake ); + ssl_transform_free( ssl->transform_negotiate ); + ssl_session_free( ssl->session_negotiate ); + + free( ssl->handshake ); + free( ssl->transform_negotiate ); + free( ssl->session_negotiate ); + } + if ( ssl->hostname != NULL) { memset( ssl->hostname, 0, ssl->hostname_len ); @@ -3484,11 +3735,6 @@ void ssl_free( ssl_context *ssl ) } #endif -#if defined(POLARSSL_ZLIB_SUPPORT) - deflateEnd( &ssl->ctx_deflate ); - inflateEnd( &ssl->ctx_inflate ); -#endif - SSL_DEBUG_MSG( 2, ( "<= free" ) ); /* Actually free after last debug message */ diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 8c0a94df0..df5274a13 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -50,6 +50,8 @@ #define DFL_CRT_FILE "" #define DFL_KEY_FILE "" #define DFL_FORCE_CIPHER 0 +#define DFL_RENEGOTIATION SSL_RENEGOTIATION_ENABLED +#define DFL_ALLOW_LEGACY SSL_NO_LEGACY_RENEGOTIATION #define GET_REQUEST "GET %s HTTP/1.0\r\n\r\n" @@ -67,6 +69,8 @@ struct options char *crt_file; /* the file with the client certificate */ char *key_file; /* the file with the client key */ int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */ + int renegotiation; /* enable / disable renegotiation */ + int allow_legacy; /* allow legacy renegotiation */ } opt; void my_debug( void *ctx, int level, const char *str ) @@ -97,6 +101,8 @@ void my_debug( void *ctx, int level, const char *str ) " debug_level=%%d default: 0 (disabled)\n" \ USAGE_IO \ " request_page=%%s default: \".\"\n" \ + " renegotiation=%%d default: 1 (enabled)\n" \ + " allow_legacy=%%d default: 0 (disabled)\n" \ " force_ciphersuite= default: all enabled\n"\ " acceptable ciphersuite names:\n" @@ -171,6 +177,8 @@ int main( int argc, char *argv[] ) opt.crt_file = DFL_CRT_FILE; opt.key_file = DFL_KEY_FILE; opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; + opt.renegotiation = DFL_RENEGOTIATION; + opt.allow_legacy = DFL_ALLOW_LEGACY; for( i = 1; i < argc; i++ ) { @@ -224,6 +232,17 @@ int main( int argc, char *argv[] ) } opt.force_ciphersuite[1] = 0; } + else if( strcmp( p, "renegotiation" ) == 0 ) + { + opt.renegotiation = (atoi( q )) ? SSL_RENEGOTIATION_ENABLED : + SSL_RENEGOTIATION_DISABLED; + } + else if( strcmp( p, "allow_legacy" ) == 0 ) + { + opt.allow_legacy = atoi( q ); + if( opt.allow_legacy < 0 || opt.allow_legacy > 1 ) + goto usage; + } else goto usage; } @@ -367,6 +386,9 @@ int main( int argc, char *argv[] ) else ssl_set_ciphersuites( &ssl, opt.force_ciphersuite ); + 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 ); @@ -419,7 +441,8 @@ int main( int argc, char *argv[] ) printf( " ok\n" ); printf( " . Peer certificate information ...\n" ); - x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, " ", ssl.peer_cert ); + x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, " ", + ssl.session->peer_cert ); printf( "%s\n", buf ); /* @@ -495,6 +518,7 @@ 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 881a68e40..416d4bf18 100644 --- a/programs/ssl/ssl_fork_server.c +++ b/programs/ssl/ssl_fork_server.c @@ -379,7 +379,9 @@ int main( int argc, char *argv[] ) ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL ); ssl_set_own_cert( &ssl, &srvcert, &rsa ); +#if defined(POLARSSL_DHM_C) ssl_set_dh_param( &ssl, my_dhm_P, my_dhm_G ); +#endif /* * 5. Handshake diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c index 6bf64af63..ea7068c0d 100644 --- a/programs/ssl/ssl_mail_client.c +++ b/programs/ssl/ssl_mail_client.c @@ -171,7 +171,8 @@ int do_handshake( ssl_context *ssl, struct options *opt ) printf( " ok\n" ); printf( " . Peer certificate information ...\n" ); - x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, " ", ssl->peer_cert ); + x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, " ", + ssl->session->peer_cert ); printf( "%s\n", buf ); return( 0 ); @@ -803,6 +804,7 @@ 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_server.c b/programs/ssl/ssl_server.c index 0d2478718..ca1477ebd 100644 --- a/programs/ssl/ssl_server.c +++ b/programs/ssl/ssl_server.c @@ -370,7 +370,9 @@ int main( int argc, char *argv[] ) ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL ); ssl_set_own_cert( &ssl, &srvcert, &rsa ); +#if defined(POLARSSL_DHM_C) ssl_set_dh_param( &ssl, my_dhm_P, my_dhm_G ); +#endif printf( " ok\n" ); @@ -484,8 +486,11 @@ reset: len = ret; printf( " %d bytes read\n\n%s", len, (char *) buf ); + + if( ret > 0 ) + break; } - while( 0 ); + while( 1 ); /* * 7. Write the 200 Response @@ -531,19 +536,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 ); - 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/x509/cert_app.c b/programs/x509/cert_app.c index 08d1b9a47..18c23b28d 100644 --- a/programs/x509/cert_app.c +++ b/programs/x509/cert_app.c @@ -312,7 +312,8 @@ int main( int argc, char *argv[] ) * 5. Print the certificate */ printf( " . Peer certificate information ...\n" ); - ret = x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, " ", ssl.peer_cert ); + ret = x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, " ", + ssl.session->peer_cert ); if( ret == -1 ) { printf( " failed\n ! x509parse_cert_info returned %d\n\n", ret ); @@ -332,10 +333,9 @@ exit: net_close( server_fd ); x509_free( &clicert ); 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();