diff --git a/ChangeLog b/ChangeLog index 59a43dcb4..ef1002083 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,12 @@ PolarSSL ChangeLog = Development +Features + * Elliptic Curve Cryptography module added + * Elliptic Curve Diffie Hellman module added + * Ephemeral Elliptic Curve Diffie Hellman support for SSL/TLS + (ECDHE-based ciphersuites) + Changes * Introduced separate SSL Ciphersuites module that is based on Cipher and MD information diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 7640a96eb..40ea45582 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -140,6 +140,7 @@ * TLS_RSA_WITH_NULL_MD5 * TLS_RSA_WITH_NULL_SHA * TLS_RSA_WITH_NULL_SHA256 + * TLS_ECDHE_RSA_WITH_NULL_SHA * * Uncomment this macro to enable the NULL cipher and ciphersuites #define POLARSSL_CIPHER_NULL_CIPHER @@ -345,6 +346,8 @@ * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 * TLS_RSA_WITH_AES_128_GCM_SHA256 * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA * * PEM uses AES for decrypting encrypted keys. */ @@ -358,9 +361,11 @@ * Module: library/arc4.c * Caller: library/ssl_tls.c * - * This module enables the following ciphersuites: + * This module enables the following ciphersuites (if other requisites are + * enabled as well): * TLS_RSA_WITH_RC4_128_MD5 * TLS_RSA_WITH_RC4_128_SHA + * TLS_ECDHE_RSA_WITH_RC4_128_SHA */ #define POLARSSL_ARC4_C @@ -505,6 +510,7 @@ * enabled as well): * TLS_RSA_WITH_3DES_EDE_CBC_SHA * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA * * PEM uses DES/3DES for decrypting encrypted keys. */ @@ -542,7 +548,16 @@ * Enable the elliptic curve Diffie-Hellman library. * * Module: library/ecdh.c - * Caller: + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_RSA_WITH_NULL_SHA + * TLS_ECDHE_RSA_WITH_RC4_128_SHA + * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA * * Requires: POLARSSL_ECP_C */ diff --git a/include/polarssl/debug.h b/include/polarssl/debug.h index 511e926eb..f0cc26177 100644 --- a/include/polarssl/debug.h +++ b/include/polarssl/debug.h @@ -29,6 +29,9 @@ #include "config.h" #include "ssl.h" +#if defined(POLARSSL_ECP_C) +#include "ecp.h" +#endif #if defined(POLARSSL_DEBUG_C) @@ -44,6 +47,9 @@ #define SSL_DEBUG_MPI( level, text, X ) \ debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ); +#define SSL_DEBUG_ECP( level, text, X ) \ + debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X ); + #define SSL_DEBUG_CRT( level, text, crt ) \ debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ); @@ -53,6 +59,7 @@ #define SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) #define SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) #define SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) +#define SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) #define SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) #endif @@ -78,6 +85,12 @@ void debug_print_mpi( const ssl_context *ssl, int level, const char *file, int line, const char *text, const mpi *X ); +#if defined(POLARSSL_ECP_C) +void debug_print_ecp( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const ecp_point *X ); +#endif + void debug_print_crt( const ssl_context *ssl, int level, const char *file, int line, const char *text, const x509_cert *crt ); diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 756441c8e..a2235863f 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -43,6 +43,10 @@ #include "dhm.h" #endif +#if defined(POLARSSL_ECDH_C) +#include "ecdh.h" +#endif + #if defined(POLARSSL_ZLIB_SUPPORT) #include "zlib.h" #endif @@ -82,8 +86,8 @@ #define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ #define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ #define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM Read Public. */ -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM Calculate Secret. */ +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ #define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ #define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ #define POLARSSL_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ @@ -140,44 +144,6 @@ #define SSL_BUFFER_LEN (SSL_MAX_CONTENT_LEN + SSL_COMPRESSION_ADD + 512) -/* - * Supported ciphersuites (Official IANA names) - */ -#define TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ -#define TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ -#define TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ -#define TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ -#define TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ - -#define TLS_RSA_WITH_RC4_128_MD5 0x04 -#define TLS_RSA_WITH_RC4_128_SHA 0x05 - -#define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A -#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 - -#define TLS_RSA_WITH_AES_128_CBC_SHA 0x2F -#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 -#define TLS_RSA_WITH_AES_256_CBC_SHA 0x35 -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 -#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ -#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ -#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ - -#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 -#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 -#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 -#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 -#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ -#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ -#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ -#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ - -#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C -#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D -#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E -#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F - #define SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ /* @@ -250,12 +216,15 @@ /* * TLS extensions */ -#define TLS_EXT_SERVERNAME 0 -#define TLS_EXT_SERVERNAME_HOSTNAME 0 +#define TLS_EXT_SERVERNAME 0 +#define TLS_EXT_SERVERNAME_HOSTNAME 0 -#define TLS_EXT_SIG_ALG 13 +#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define TLS_EXT_SUPPORTED_POINT_FORMATS 11 -#define TLS_EXT_RENEGOTIATION_INFO 0xFF01 +#define TLS_EXT_SIG_ALG 13 + +#define TLS_EXT_RENEGOTIATION_INFO 0xFF01 /* @@ -368,6 +337,13 @@ struct _ssl_handshake_params #if defined(POLARSSL_DHM_C) dhm_context dhm_ctx; /*!< DHM key exchange */ #endif +#if defined(POLARSSL_ECDH_C) + ecdh_context ecdh_ctx; /*!< ECDH key exchange */ +#endif +#if defined(POLARSSL_ECP_C) + int ec_curve; /*!< Selected elliptic curve */ + int ec_point_format; /*!< Client supported format */ +#endif /* * Checksum contexts @@ -1114,7 +1090,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_optimize_checksum( ssl_context *ssl, int ciphersuite ); +void ssl_optimize_checksum( ssl_context *ssl, const ssl_ciphersuite_t *ciphersuite_info ); #ifdef __cplusplus } diff --git a/include/polarssl/ssl_ciphersuites.h b/include/polarssl/ssl_ciphersuites.h index 62a928e87..5e1e28dff 100644 --- a/include/polarssl/ssl_ciphersuites.h +++ b/include/polarssl/ssl_ciphersuites.h @@ -34,15 +34,61 @@ extern "C" { #endif +/* + * Supported ciphersuites (Official IANA names) + */ +#define TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ +#define TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ +#define TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ +#define TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ +#define TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ + +#define TLS_RSA_WITH_RC4_128_MD5 0x04 +#define TLS_RSA_WITH_RC4_128_SHA 0x05 + +#define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A +#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 + +#define TLS_RSA_WITH_AES_128_CBC_SHA 0x2F +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 +#define TLS_RSA_WITH_AES_256_CBC_SHA 0x35 +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 +#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ +#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ + +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ + +#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C +#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D +#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E +#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F + +#define TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 +#define TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 +#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 + typedef enum { POLARSSL_KEY_EXCHANGE_NONE = 0, POLARSSL_KEY_EXCHANGE_RSA, - POLARSSL_KEY_EXCHANGE_DHE_RSA + POLARSSL_KEY_EXCHANGE_DHE_RSA, + POLARSSL_KEY_EXCHANGE_ECDHE_RSA, } key_exchange_type_t; typedef struct _ssl_ciphersuite_t ssl_ciphersuite_t; -#define POLARSSL_CIPHERSUITE_WEAK 0x01 +#define POLARSSL_CIPHERSUITE_WEAK 0x01 /*f_dbg( ssl->p_dbg, level, "\n" ); } +#if defined(POLARSSL_ECP_C) +void debug_print_ecp( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const ecp_point *X ) +{ + char str[512]; + int maxlen = sizeof( str ) - 1; + + snprintf( str, maxlen, "%s(X)", text ); + str[maxlen] = '\0'; + debug_print_mpi( ssl, level, file, line, str, &X->X ); + + snprintf( str, maxlen, "%s(Y)", text ); + str[maxlen] = '\0'; + debug_print_mpi( ssl, level, file, line, str, &X->Y ); + + snprintf( str, maxlen, "%s(Z)", text ); + str[maxlen] = '\0'; + debug_print_mpi( ssl, level, file, line, str, &X->Z ); +} +#endif /* POLARSSL_ECP_C */ + void debug_print_mpi( const ssl_context *ssl, int level, const char *file, int line, const char *text, const mpi *X ) diff --git a/library/ecdh.c b/library/ecdh.c index e30ae3a71..df21eac3e 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -212,8 +212,11 @@ int ecdh_calc_secret( ecdh_context *ctx, size_t *olen, != 0 ) return( ret ); - *olen = mpi_size( &ctx->z ); - return mpi_write_binary( &ctx->z, buf, blen ); + if( mpi_size( &ctx->z ) > blen ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + *olen = ctx->grp.nbits / 8 + ( ( ctx->grp.nbits % 8 ) != 0 ); + return mpi_write_binary( &ctx->z, buf, *olen ); } diff --git a/library/error.c b/library/error.c index 1a8457bad..fce6b2cfe 100644 --- a/library/error.c +++ b/library/error.c @@ -189,6 +189,8 @@ void error_strerror( int ret, char *buf, size_t buflen ) #if defined(POLARSSL_ECP_C) if( use_ret == -(POLARSSL_ERR_ECP_BAD_INPUT_DATA) ) snprintf( buf, buflen, "ECP - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_ECP_BUFFER_TOO_SMALL) ) + snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); if( use_ret == -(POLARSSL_ERR_ECP_GENERIC) ) snprintf( buf, buflen, "ECP - Generic ECP error" ); #endif /* POLARSSL_ECP_C */ @@ -296,10 +298,10 @@ void error_strerror( int ret, char *buf, size_t buflen ) snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP) ) - snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM Read Public" ); - if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS) ) - snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM Calculate Secret" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) ) + snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) ) + snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c index 0218194f3..b9b041a61 100644 --- a/library/ssl_ciphersuites.c +++ b/library/ssl_ciphersuites.c @@ -34,107 +34,100 @@ #include -const int supported_ciphersuites[] = +/* + * Ordered from most preferred to least preferred in terms of security. + */ +static const int ciphersuite_preference[] = { -#if defined(POLARSSL_DHM_C) -#if defined(POLARSSL_AES_C) -#if defined(POLARSSL_SHA2_C) TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, -#endif + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, -#if defined(POLARSSL_SHA2_C) - TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) - TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, -#endif - TLS_DHE_RSA_WITH_AES_128_CBC_SHA, -#endif /* POLARSSL_AES_C */ -#if defined(POLARSSL_CAMELLIA_C) -#if defined(POLARSSL_SHA2_C) TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, -#if defined(POLARSSL_SHA2_C) + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, -#endif /* POLARSSL_CAMELLIA_C */ -#if defined(POLARSSL_DES_C) + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, -#endif -#endif /* POLARSSL_DHM_C */ - -#if defined(POLARSSL_AES_C) -#if defined(POLARSSL_SHA2_C) + TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_256_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) TLS_RSA_WITH_AES_256_GCM_SHA384, -#endif TLS_RSA_WITH_AES_256_CBC_SHA, -#endif /* POLARSSL_AES_C */ -#if defined(POLARSSL_CAMELLIA_C) -#if defined(POLARSSL_SHA2_C) TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, -#endif /* POLARSSL_CAMELLIA_C */ -#if defined(POLARSSL_AES_C) -#if defined(POLARSSL_SHA2_C) TLS_RSA_WITH_AES_128_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) TLS_RSA_WITH_AES_128_GCM_SHA256, -#endif /* POLARSSL_SHA2_C */ TLS_RSA_WITH_AES_128_CBC_SHA, -#endif /* POLARSSL_AES_C */ -#if defined(POLARSSL_CAMELLIA_C) -#if defined(POLARSSL_SHA2_C) TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, -#endif /* POLARSSL_CAMELLIA_C */ -#if defined(POLARSSL_DES_C) TLS_RSA_WITH_3DES_EDE_CBC_SHA, -#endif /* POLARSSL_DES_C */ -#if defined(POLARSSL_ARC4_C) TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_RC4_128_MD5, -#endif /* POLARSSL_ARC4_C */ -#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) -#if defined(POLARSSL_DES_C) -#if defined(POLARSSL_DHM_C) TLS_DHE_RSA_WITH_DES_CBC_SHA, -#endif /* POLARSSL_DHM_C */ TLS_RSA_WITH_DES_CBC_SHA, -#endif /* POLARSSL_DES_C */ -#if defined(POLARSSL_CIPHER_NULL_CIPHER) -#if defined(POLARSSL_SHA2_C) + TLS_ECDHE_RSA_WITH_NULL_SHA, TLS_RSA_WITH_NULL_SHA256, -#endif TLS_RSA_WITH_NULL_SHA, TLS_RSA_WITH_NULL_MD5, -#endif /* POLARSSL_CIPHER_NULL_CIPHER */ -#endif /* POLARSSL_ENABLE_WEAK_CIPHERSUITES */ 0 }; +#define MAX_CIPHERSUITES 60 +static int supported_ciphersuites[MAX_CIPHERSUITES]; +static int supported_init = 0; + static const ssl_ciphersuite_t ciphersuite_definitions[] = { +#if defined(POLARSSL_ECDH_C) +#if defined(POLARSSL_AES_C) + { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_EC }, + { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_EC }, +#endif +#if defined(POLARSSL_DES_C) + { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_EC }, +#endif /* POLARSSL_DES_C */ +#if defined(POLARSSL_ARC4_C) + { TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_EC }, +#endif +#if defined(POLARSSL_CIPHER_NULL_CIPHER) + { TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_EC | POLARSSL_CIPHERSUITE_WEAK }, +#endif +#endif + #if defined(POLARSSL_ARC4_C) { TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_MD5, POLARSSL_KEY_EXCHANGE_RSA, - SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, 0 }, { TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, - SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, 0 }, #endif /* POLARSSL_ARC4_C */ @@ -345,6 +338,27 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] = const int *ssl_list_ciphersuites( void ) { + /* + * On initial call filter out all ciphersuites not supported by current + * build based on presence in the ciphersuite_definitions. + */ + if( supported_init == 0 ) + { + const int *p = ciphersuite_preference; + int *q = supported_ciphersuites; + + memset( supported_ciphersuites, 0x00, sizeof(supported_ciphersuites) ); + + while( *p != 0 ) + { + if( ssl_ciphersuite_from_id( *p ) != NULL ) + *(q++) = *p; + + p++; + } + supported_init = 1; + } + return supported_ciphersuites; }; diff --git a/library/ssl_cli.c b/library/ssl_cli.c index c426fa875..68c06cc51 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -47,6 +47,10 @@ static int ssl_write_client_hello( ssl_context *ssl ) time_t t; unsigned char sig_alg_list[20]; size_t sig_alg_len = 0; +#if defined(POLARSSL_ECDH_C) + unsigned char elliptic_curve_list[20]; + size_t elliptic_curve_len = 0; +#endif SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); @@ -203,6 +207,26 @@ static int ssl_write_client_hello( ssl_context *ssl ) ext_len += 6 + sig_alg_len; } +#if defined(POLARSSL_ECDH_C) + SSL_DEBUG_MSG( 3, ( "client hello, prepping for supported elliptic curves extension" ) ); + + elliptic_curve_list[elliptic_curve_len++] = 0x00; + elliptic_curve_list[elliptic_curve_len++] = POLARSSL_ECP_DP_SECP521R1; + elliptic_curve_list[elliptic_curve_len++] = 0x00; + elliptic_curve_list[elliptic_curve_len++] = POLARSSL_ECP_DP_SECP384R1; + elliptic_curve_list[elliptic_curve_len++] = 0x00; + elliptic_curve_list[elliptic_curve_len++] = POLARSSL_ECP_DP_SECP256R1; + elliptic_curve_list[elliptic_curve_len++] = 0x00; + elliptic_curve_list[elliptic_curve_len++] = POLARSSL_ECP_DP_SECP224R1; + elliptic_curve_list[elliptic_curve_len++] = 0x00; + elliptic_curve_list[elliptic_curve_len++] = POLARSSL_ECP_DP_SECP192R1; + + ext_len += 6 + elliptic_curve_len; + + SSL_DEBUG_MSG( 3, ( "client hello, prepping for supported point formats extension" ) ); + ext_len += 7; +#endif + SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", ext_len ) ); @@ -302,6 +326,35 @@ static int ssl_write_client_hello( ssl_context *ssl ) p += sig_alg_len; } +#if defined(POLARSSL_ECDH_C) + SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF ); + + memcpy( p, elliptic_curve_list, elliptic_curve_len ); + + p+= elliptic_curve_len; + + SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + + *p++ = 0x00; + *p++ = 3; + + *p++ = 2; + *p++ = POLARSSL_ECP_PF_COMPRESSED; + *p++ = POLARSSL_ECP_PF_UNCOMPRESSED; +#endif + ssl->out_msglen = p - buf; ssl->out_msgtype = SSL_MSG_HANDSHAKE; ssl->out_msg[0] = SSL_HS_CLIENT_HELLO; @@ -472,8 +525,8 @@ static int ssl_parse_server_hello( ssl_context *ssl ) /* * Initialize update checksum functions */ - ssl_optimize_checksum( ssl, i ); ssl->transform_negotiate->ciphersuite_info = ssl_ciphersuite_from_id( i ); + ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); if( ssl->transform_negotiate->ciphersuite_info == NULL ) { @@ -629,9 +682,17 @@ static int ssl_parse_server_hello( ssl_context *ssl ) return( 0 ); } +#if !defined(POLARSSL_DHM_C) && !defined(POLARSSL_ECDH_C) +static int ssl_parse_server_key_exchange( ssl_context *ssl ) +{ + SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); + SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); +} +#else static int ssl_parse_server_key_exchange( ssl_context *ssl ) { -#if defined(POLARSSL_DHM_C) int ret; size_t n; unsigned char *p, *end; @@ -640,22 +701,19 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) sha1_context sha1; int hash_id = SIG_RSA_RAW; unsigned int hashlen = 0; -#endif + + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); - if( ssl->transform_negotiate->ciphersuite_info->key_exchange != - POLARSSL_KEY_EXCHANGE_DHE_RSA ) + if( ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_RSA && + ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_RSA ) { SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); ssl->state++; return( 0 ); } -#if !defined(POLARSSL_DHM_C) - SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) ); - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); -#else if( ( ret = ssl_read_record( ssl ) ) != 0 ) { SSL_DEBUG_RET( 1, "ssl_read_record", ret ); @@ -676,24 +734,55 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) SSL_DEBUG_BUF( 3, "server key exchange", ssl->in_msg + 4, ssl->in_hslen - 4 ); - /* - * Ephemeral DH parameters: - * - * struct { - * opaque dh_p<1..2^16-1>; - * opaque dh_g<1..2^16-1>; - * opaque dh_Ys<1..2^16-1>; - * } ServerDHParams; - */ - p = ssl->in_msg + 4; - end = ssl->in_msg + ssl->in_hslen; - - if( ( ret = dhm_read_params( &ssl->handshake->dhm_ctx, &p, end ) ) != 0 ) +#if defined(POLARSSL_DHM_C) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ) { - SSL_DEBUG_MSG( 2, ( "DHM Read Params returned -0x%x", -ret ) ); - SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + p = ssl->in_msg + 4; + end = ssl->in_msg + ssl->in_hslen; + + 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" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } } +#endif /* POLARSSL_DHM_C */ + +#if defined(POLARSSL_ECDH_C) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ) + { + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + ecdh_init( &ssl->handshake->ecdh_ctx ); + + p = ssl->in_msg + 4; + end = ssl->in_msg + ssl->in_hslen; + + if( ( ret = ecdh_read_params( &ssl->handshake->ecdh_ctx, + (const unsigned char **) &p, end ) ) != 0 ) + { + SSL_DEBUG_MSG( 2, ( "ECDH Read Params returned -0x%x", -ret ) ); + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } +#endif /* POLARSSL_ECDH_C */ if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) { @@ -759,15 +848,35 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } - if( ssl->handshake->dhm_ctx.len < 64 || ssl->handshake->dhm_ctx.len > 512 ) +#if defined(POLARSSL_DHM_C) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ) { - SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } + if( ssl->handshake->dhm_ctx.len < 64 || + ssl->handshake->dhm_ctx.len > 512 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message (DHM length)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } - 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 ); + 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 ); + } +#endif + +#if defined(POLARSSL_ECDH_C) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ) + { + if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || + ssl->handshake->ecdh_ctx.grp.nbits > 521 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDH length)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp ); + } +#endif if( ssl->minor_ver != SSL_MINOR_VERSION_3 ) { @@ -885,8 +994,8 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); return( 0 ); -#endif } +#endif /* POLARSSL_DHM_C || POLARSSL_ECDH_C */ static int ssl_parse_certificate_request( ssl_context *ssl ) { @@ -1039,16 +1148,15 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) { int ret; size_t i, n; +#if defined(POLARSSL_DHM_C) || defined(POLARSSL_ECDH_C) + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; +#endif SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); - if( ssl->transform_negotiate->ciphersuite_info->key_exchange == - POLARSSL_KEY_EXCHANGE_DHE_RSA ) +#if defined(POLARSSL_DHM_C) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ) { -#if !defined(POLARSSL_DHM_C) - SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) ); - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); -#else /* * DHM key exchange -- send G^X mod P */ @@ -1082,9 +1190,42 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) } SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); -#endif } else +#endif /* POLARSSL_DHM_C */ +#if defined(POLARSSL_ECDH_C) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ) + { + /* + * ECDH key exchange -- send client public value + */ + i = 4; + + ret = ecdh_make_public( &ssl->handshake->ecdh_ctx, + &n, + &ssl->out_msg[i], 1000, + ssl->f_rng, ssl->p_rng ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_make_public", ret ); + return( ret ); + } + + SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + + if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + POLARSSL_MPI_MAX_SIZE ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret ); + return( ret ); + } + + SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* POLARSSL_ECDH_C */ { /* * RSA key exchange -- send rsa_public(pkcs1 v1.5(premaster)) @@ -1206,8 +1347,8 @@ static int ssl_write_certificate_verify( ssl_context *ssl ) * Reason: Otherwise we should have running hashes for SHA512 and SHA224 * in order to satisfy 'weird' needs from the server side. */ - if( ssl->session_negotiate->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 || - ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ) + if( ssl->transform_negotiate->ciphersuite_info->cipher == + POLARSSL_CIPHER_AES_256_GCM ) { hash_id = SIG_RSA_SHA384; hashlen = 48; diff --git a/library/ssl_srv.c b/library/ssl_srv.c index c5788ace4..bab0aa819 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -29,6 +29,9 @@ #include "polarssl/debug.h" #include "polarssl/ssl.h" +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif #include #include @@ -191,6 +194,75 @@ static int ssl_parse_signature_algorithms_ext( ssl_context *ssl, return( 0 ); } +#if defined(POLARSSL_ECP_C) +int ssl_parse_supported_elliptic_curves( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( list_size + 2 != len || + list_size % 2 != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 2; + while( list_size > 0 ) + { + if( p[0] == 0x00 && ( + p[1] == POLARSSL_ECP_DP_SECP192R1 || + p[1] == POLARSSL_ECP_DP_SECP224R1 || + p[1] == POLARSSL_ECP_DP_SECP256R1 || + p[1] == POLARSSL_ECP_DP_SECP384R1 || + p[1] == POLARSSL_ECP_DP_SECP521R1 ) ) + { + ssl->handshake->ec_curve = p[1]; + return( 0 ); + } + + list_size -= 2; + p += 2; + } + + return( 0 ); +} + +int ssl_parse_supported_point_formats( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + list_size = buf[0]; + if( list_size + 1 != len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 2; + while( list_size > 0 ) + { + if( p[0] == POLARSSL_ECP_PF_UNCOMPRESSED || + p[0] == POLARSSL_ECP_PF_COMPRESSED ) + { + ssl->handshake->ec_point_format = p[0]; + return( 0 ); + } + + list_size--; + p++; + } + + return( 0 ); +} +#endif /* POLARSSL_ECP_C */ + #if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) static int ssl_parse_client_hello_v2( ssl_context *ssl ) { @@ -363,9 +435,12 @@ static int ssl_parse_client_hello_v2( ssl_context *ssl ) { for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) { + // Only allow non-ECC ciphersuites as we do not have extensions + // if( p[0] == 0 && p[1] == 0 && - p[2] == ssl->ciphersuites[i] ) + ( ( ssl->ciphersuites[i] >> 8 ) & 0xFF ) == 0 && + p[2] == ( ssl->ciphersuites[i] & 0xFF ) ) goto have_ciphersuite_v2; } } @@ -376,7 +451,7 @@ static int ssl_parse_client_hello_v2( ssl_context *ssl ) have_ciphersuite_v2: ssl->session_negotiate->ciphersuite = ssl->ciphersuites[i]; - ssl_optimize_checksum( ssl, ssl->session_negotiate->ciphersuite ); + ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); /* * SSLv2 Client Hello relevant renegotiation security checks @@ -412,6 +487,7 @@ static int ssl_parse_client_hello( ssl_context *ssl ) unsigned char *buf, *p, *ext; int renegotiation_info_seen = 0; int handshake_failure = 0; + const ssl_ciphersuite_t *ciphersuite_info; SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); @@ -639,37 +715,6 @@ static int ssl_parse_client_hello( ssl_context *ssl ) } } - /* - * Search for a matching ciphersuite - */ - for( i = 0; ssl->ciphersuites[i] != 0; i++ ) - { - for( j = 0, p = buf + 41 + sess_len; j < ciph_len; - j += 2, p += 2 ) - { - if( p[0] == 0 && p[1] == ssl->ciphersuites[i] ) - goto have_ciphersuite; - } - } - - SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); - - return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); - -have_ciphersuite: - ssl->session_negotiate->ciphersuite = ssl->ciphersuites[i]; - ssl->transform_negotiate->ciphersuite_info = - ssl_ciphersuite_from_id( ssl->ciphersuites[i] ); - - if( ssl->transform_negotiate->ciphersuite_info == NULL ) - { - SSL_DEBUG_MSG( 1, ( "ciphersuite info for %02x not found", - ssl->ciphersuites[i] ) ); - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - } - - ssl_optimize_checksum( ssl, ssl->session_negotiate->ciphersuite ); - ext = buf + 44 + sess_len + ciph_len + comp_len; while( ext_len ) @@ -715,6 +760,24 @@ have_ciphersuite: return( ret ); break; +#if defined(POLARSSL_ECP_C) + case TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: + SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); + + ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + + case TLS_EXT_SUPPORTED_POINT_FORMATS: + SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); + + ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_ECP_C */ + default: SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", ext_id ) ); @@ -769,6 +832,48 @@ have_ciphersuite: return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); } + /* + * Search for a matching ciphersuite + * (At the end because we need information from the EC-based extensions) + */ + for( i = 0; ssl->ciphersuites[i] != 0; i++ ) + { + for( j = 0, p = buf + 41 + sess_len; j < ciph_len; + j += 2, p += 2 ) + { + if( p[0] == ( ( ssl->ciphersuites[i] >> 8 ) & 0xFF ) && + p[1] == ( ( ssl->ciphersuites[i] ) & 0xFF ) ) + { + ciphersuite_info = ssl_ciphersuite_from_id( ssl->ciphersuites[i] ); + + if( ciphersuite_info == NULL ) + { + SSL_DEBUG_MSG( 1, ( "ciphersuite info for %02x not found", + ssl->ciphersuites[i] ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ( ciphersuite_info->flags & POLARSSL_CIPHERSUITE_EC ) && + ssl->handshake->ec_curve == 0 ) + continue; + + goto have_ciphersuite; + } + } + } + + SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); + +have_ciphersuite: + ssl->session_negotiate->ciphersuite = ssl->ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); + ssl->in_left = 0; ssl->state++; @@ -963,8 +1068,8 @@ static int ssl_write_certificate_request( ssl_context *ssl ) *p++ = 0; *p++ = 2; - if( ssl->session_negotiate->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 || - ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ) + if( ssl->transform_negotiate->ciphersuite_info->cipher == + POLARSSL_CIPHER_AES_256_GCM ) { ssl->handshake->verify_sig_alg = SSL_HASH_SHA384; } @@ -1009,30 +1114,36 @@ static int ssl_write_certificate_request( ssl_context *ssl ) return( ret ); } +#if !defined(POLARSSL_DHM_C) && !defined(POLARSSL_ECDH_C) +static int ssl_write_server_key_exchange( ssl_context *ssl ) +{ + SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); +} +#else static int ssl_write_server_key_exchange( ssl_context *ssl ) { -#if defined(POLARSSL_DHM_C) int ret; size_t n, rsa_key_len = 0; unsigned char hash[64]; int hash_id = 0; unsigned int hashlen = 0; -#endif + + const ssl_ciphersuite_t *ciphersuite_info; + ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); - if( ssl->transform_negotiate->ciphersuite_info->key_exchange != - POLARSSL_KEY_EXCHANGE_DHE_RSA ) + if( ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_RSA && + ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_RSA ) { SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); ssl->state++; return( 0 ); } -#if !defined(POLARSSL_DHM_C) - SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) ); - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); -#else if( ssl->rsa_key == NULL ) { @@ -1040,35 +1151,72 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); } - /* - * Ephemeral DH parameters: - * - * struct { - * opaque dh_p<1..2^16-1>; - * opaque dh_g<1..2^16-1>; - * opaque dh_Ys<1..2^16-1>; - * } ServerDHParams; - */ - 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 ) +#if defined(POLARSSL_DHM_C) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ) { - SSL_DEBUG_RET( 1, "mpi_copy", ret ); - return( ret ); - } + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + 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, - mpi_size( &ssl->handshake->dhm_ctx.P ), - ssl->out_msg + 4, - &n, ssl->f_rng, ssl->p_rng ) ) != 0 ) + if( ( ret = dhm_make_params( &ssl->handshake->dhm_ctx, + mpi_size( &ssl->handshake->dhm_ctx.P ), + 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->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 ); + } +#endif /* POLARSSL_DHM_C */ + +#if defined(POLARSSL_ECDH_C) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ) { - SSL_DEBUG_RET( 1, "dhm_make_params", ret ); - return( ret ); - } + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + ecdh_init( &ssl->handshake->ecdh_ctx ); + if( ( ret = ecp_use_known_dp( &ssl->handshake->ecdh_ctx.grp, + ssl->handshake->ec_curve ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecp_use_known_dp", ret ); + return( ret ); + } - 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( ( ret = ecdh_make_params( &ssl->handshake->ecdh_ctx, + &n, + ssl->out_msg + 4, + 1000, ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_make_params", ret ); + return( ret ); + } + + SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); + } +#endif /* POLARSSL_ECDH_INIT */ if( ssl->minor_ver != SSL_MINOR_VERSION_3 ) { @@ -1237,8 +1385,8 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); return( 0 ); -#endif } +#endif /* POLARSSL_DHM_C || POLARSSL_ECDH_C */ static int ssl_write_server_hello_done( ssl_context *ssl ) { @@ -1267,6 +1415,10 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) { int ret; size_t i, n = 0; +#if defined(POLARSSL_DHM_C) || defined(POLARSSL_ECDH_C) + const ssl_ciphersuite_t *ciphersuite_info; + ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; +#endif SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); @@ -1288,13 +1440,9 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); } - if( ssl->transform_negotiate->ciphersuite_info->key_exchange == - POLARSSL_KEY_EXCHANGE_DHE_RSA ) +#if defined(POLARSSL_DHM_C) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ) { -#if !defined(POLARSSL_DHM_C) - SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) ); - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); -#else /* * Receive G^Y mod P, premaster = (G^Y)^X mod P */ @@ -1311,7 +1459,7 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) 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 ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); } SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); @@ -1323,13 +1471,50 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) &ssl->handshake->pmslen ) ) != 0 ) { SSL_DEBUG_RET( 1, "dhm_calc_secret", ret ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); } SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); -#endif } else +#endif +#if defined(POLARSSL_ECDH_C) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ) + { + /* + * Receive client public key and calculate premaster + */ + n = ssl->in_msg[3]; + + if( n < 1 || n > mpi_size( &ssl->handshake->ecdh_ctx.grp.P ) * 2 + 2 || + n + 4 != ssl->in_hslen ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = ecdh_read_public( &ssl->handshake->ecdh_ctx, + ssl->in_msg + 4, n ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_read_public", ret ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + + if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + POLARSSL_MPI_MAX_SIZE ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif { if( ssl->rsa_key == NULL ) { diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 08880beb2..60ef3bee5 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -346,8 +346,8 @@ int ssl_derive_keys( ssl_context *ssl ) handshake->calc_finished = ssl_calc_finished_tls; } #if defined(POLARSSL_SHA4_C) - else if( session->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 || - session->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ) + else if( transform->ciphersuite_info->cipher == + POLARSSL_CIPHER_AES_256_GCM ) { handshake->tls_prf = tls_prf_sha384; handshake->calc_verify = ssl_calc_verify_tls_sha384; @@ -2151,7 +2151,8 @@ int ssl_parse_change_cipher_spec( ssl_context *ssl ) return( 0 ); } -void ssl_optimize_checksum( ssl_context *ssl, int ciphersuite ) +void ssl_optimize_checksum( ssl_context *ssl, + const ssl_ciphersuite_t *ciphersuite_info ) { #if !defined(POLARSSL_SHA4_C) ((void) ciphersuite); @@ -2160,8 +2161,7 @@ void ssl_optimize_checksum( ssl_context *ssl, int ciphersuite ) if( ssl->minor_ver < SSL_MINOR_VERSION_3 ) ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; #if defined(POLARSSL_SHA4_C) - else if ( ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 || - ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ) + else if( ciphersuite_info->cipher == POLARSSL_CIPHER_AES_256_GCM ) { ssl->handshake->update_checksum = ssl_update_checksum_sha384; } diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index c1b3810c4..abca186d6 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -94,96 +94,6 @@ void my_debug( void *ctx, int level, const char *str ) } } -/* - * Sorted by order of preference - */ -int my_ciphersuites[] = -{ -#if defined(POLARSSL_DHM_C) -#if defined(POLARSSL_AES_C) -#if defined(POLARSSL_SHA2_C) - TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) - TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, -#endif - TLS_DHE_RSA_WITH_AES_256_CBC_SHA, -#if defined(POLARSSL_SHA2_C) - TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, -#endif -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) - TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, -#endif - TLS_DHE_RSA_WITH_AES_128_CBC_SHA, -#endif -#if defined(POLARSSL_CAMELLIA_C) -#if defined(POLARSSL_SHA2_C) - TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ - TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, -#if defined(POLARSSL_SHA2_C) - TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ - TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, -#endif -#if defined(POLARSSL_DES_C) - TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, -#endif -#endif - -#if defined(POLARSSL_AES_C) -#if defined(POLARSSL_SHA2_C) - TLS_RSA_WITH_AES_256_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) - TLS_RSA_WITH_AES_256_GCM_SHA384, -#endif /* POLARSSL_SHA2_C */ - TLS_RSA_WITH_AES_256_CBC_SHA, -#endif -#if defined(POLARSSL_CAMELLIA_C) -#if defined(POLARSSL_SHA2_C) - TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ - TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, -#endif -#if defined(POLARSSL_AES_C) -#if defined(POLARSSL_SHA2_C) - TLS_RSA_WITH_AES_128_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ -#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) - TLS_RSA_WITH_AES_128_GCM_SHA256, -#endif /* POLARSSL_SHA2_C */ - TLS_RSA_WITH_AES_128_CBC_SHA, -#endif -#if defined(POLARSSL_CAMELLIA_C) -#if defined(POLARSSL_SHA2_C) - TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, -#endif /* POLARSSL_SHA2_C */ - TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, -#endif -#if defined(POLARSSL_DES_C) - TLS_RSA_WITH_3DES_EDE_CBC_SHA, -#endif -#if defined(POLARSSL_ARC4_C) - TLS_RSA_WITH_RC4_128_SHA, - TLS_RSA_WITH_RC4_128_MD5, -#endif - -#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) -#if defined(POLARSSL_DES_C) - TLS_DHE_RSA_WITH_DES_CBC_SHA, - TLS_RSA_WITH_DES_CBC_SHA, -#endif -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - TLS_RSA_WITH_NULL_MD5, - TLS_RSA_WITH_NULL_SHA, - TLS_RSA_WITH_NULL_SHA256, -#endif -#endif - 0 -}; - - #if defined(POLARSSL_FS_IO) #define USAGE_IO \ " ca_file=%%s The single file containing the top-level CA(s) you fully trust\n" \ @@ -503,9 +413,7 @@ int main( int argc, char *argv[] ) ssl_cache_set, &cache ); #endif - if( opt.force_ciphersuite[0] == DFL_FORCE_CIPHER ) - ssl_set_ciphersuites( &ssl, my_ciphersuites ); - else + if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER ) ssl_set_ciphersuites( &ssl, opt.force_ciphersuite ); ssl_set_renegotiation( &ssl, opt.renegotiation ); diff --git a/tests/compat.sh b/tests/compat.sh index d35a8138d..6a3c70a55 100644 --- a/tests/compat.sh +++ b/tests/compat.sh @@ -36,6 +36,12 @@ P_CIPHERS=" \ TLS-RSA-WITH-NULL-SHA \ TLS-RSA-WITH-DES-CBC-SHA \ TLS-DHE-RSA-WITH-DES-CBC-SHA \ + TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA \ + TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA \ + TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA \ + TLS-ECDHE-RSA-WITH-RC4-128-SHA \ + TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA \ + TLS-ECDHE-RSA-WITH-NULL-SHA \ " O_CIPHERS=" \ @@ -55,6 +61,11 @@ O_CIPHERS=" \ NULL-SHA \ DES-CBC-SHA \ EDH-RSA-DES-CBC-SHA \ + ECDHE-RSA-AES256-SHA \ + ECDHE-RSA-AES128-SHA \ + ECDHE-RSA-DES-CBC3-SHA \ + ECDHE-RSA-RC4-SHA \ + ECDHE-RSA-NULL-SHA \ " # Also add SHA256 ciphersuites