From c27807dd1e09c735337261fdb92a0fd7d0703ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 30 Jun 2014 17:27:49 +0200 Subject: [PATCH 1/6] Make SSL_BUFFER_LEN overhead depend more on config --- include/polarssl/ssl.h | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 91e398144..9db0fc6bc 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -249,7 +249,9 @@ * Note: the RFC defines the default size of SSL / TLS messages. If you * change the value here, other clients / servers may not be able to * communicate with you anymore. Only change this value if you control - * both sides of the connection and have it reduced at both sides! + * both sides of the connection and have it reduced at both sides, or + * if you're using the Max Fragment Length extension and you know all your + * peers are using it too! */ #if !defined(SSL_MAX_CONTENT_LEN) #define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ @@ -258,8 +260,8 @@ /* \} name SECTION: Module settings */ /* - * Allow an extra 301 bytes for the record header and encryption overhead: - * counter (8) + header (5) + IV(16) + MAC (48) + padding (256) + * Allow extra bytes for record, authentication and encryption overhead: + * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) * and allow for a maximum of 1024 of compression expansion if * enabled. */ @@ -269,8 +271,36 @@ #define SSL_COMPRESSION_ADD 0 #endif -#define SSL_BUFFER_LEN (SSL_MAX_CONTENT_LEN + SSL_COMPRESSION_ADD + 333) +#if defined(POLARSSL_RC4_C) || defined(POLARSSL_CIPHER_MODE_CBC) +/* Ciphersuites using HMAC */ +#if defined(POLARSSL_SHA512_C) +#define SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ +#elif defined(POLARSSL_SHA256_C) +#define SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ +#else +#define SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ +#endif +#else +/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ +#define SSL_MAC_ADD 16 +#endif +#if defined(POLARSSL_CIPHER_MODE_CBC) +#define SSL_PADDING_ADD 256 +#else +#define SSL_PADDING_ADD 0 +#endif + +#define SSL_BUFFER_LEN ( SSL_MAX_CONTENT_LEN \ + + SSL_COMPRESSION_ADD \ + + 29 /* counter + header + IV */ \ + + SSL_MAC_ADD \ + + SSL_PADDING_ADD \ + ) + +/* + * Signaling ciphersuite values (SCSV) + */ #define SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ /* From 791684c058ce7d9eba7accc06c03eb714f18b60d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 30 Jun 2014 17:38:22 +0200 Subject: [PATCH 2/6] Save RAM when only a few ciphersuites are defined --- library/ssl_ciphersuites.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c index 608e26d2f..ea12146ef 100644 --- a/library/ssl_ciphersuites.c +++ b/library/ssl_ciphersuites.c @@ -260,10 +260,6 @@ static const int ciphersuite_preference[] = 0 }; -#define MAX_CIPHERSUITES 176 -static int supported_ciphersuites[MAX_CIPHERSUITES]; -static int supported_init = 0; - static const ssl_ciphersuite_t ciphersuite_definitions[] = { #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) @@ -1679,6 +1675,11 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] = { 0, "", 0, 0, 0, 0, 0, 0, 0, 0 } }; +#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ + sizeof( ciphersuite_definitions[0] ) +static int supported_ciphersuites[MAX_CIPHERSUITES]; +static int supported_init = 0; + const int *ssl_list_ciphersuites( void ) { /* @@ -1687,21 +1688,21 @@ const int *ssl_list_ciphersuites( void ) */ if( supported_init == 0 ) { - const int *p = ciphersuite_preference; - int *q = supported_ciphersuites; - size_t i; - size_t max = sizeof(supported_ciphersuites) / sizeof(int); + const int *p; + int *q; - for( i = 0; i < max - 1 && p[i] != 0; i++ ) + for( p = ciphersuite_preference, q = supported_ciphersuites; + *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; + p++ ) { #if defined(POLARSSL_REMOVE_ARC4_CIPHERSUITES) const ssl_ciphersuite_t *cs_info; - if( ( cs_info = ssl_ciphersuite_from_id( p[i] ) ) != NULL && + if( ( cs_info = ssl_ciphersuite_from_id( *p ) ) != NULL && cs_info->cipher != POLARSSL_CIPHER_ARC4_128 ) #else - if( ssl_ciphersuite_from_id( p[i] ) != NULL ) + if( ssl_ciphersuite_from_id( *p ) != NULL ) #endif - *(q++) = p[i]; + *(q++) = *p; } *q = 0; From dfc7df0bec15b03fd2b84b1a0c8db8987af63bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 30 Jun 2014 17:59:55 +0200 Subject: [PATCH 3/6] Add SSL_CIPHERSUITES config option --- ChangeLog | 2 ++ include/polarssl/config.h | 14 ++++++++++++++ library/ssl_ciphersuites.c | 11 +++++++++++ 3 files changed, 27 insertions(+) diff --git a/ChangeLog b/ChangeLog index a0a8a18f9..142ea30be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -20,6 +20,8 @@ Features * Optimize for RAM usage in example config.h for NSA Suite B profile. * Add POLARSSL_REMOVE_ARC4_CIPHERSUITES to allow removing RC4 ciphersuites from the default list (inactive by default). + * Add SSL_CIPHERSUITES config.h flag to allow specifying a list of + ciphersuites to use and save some memory if the list is small. Changes * Add LINK_WITH_PTHREAD option in CMake for explicit linking that is diff --git a/include/polarssl/config.h b/include/polarssl/config.h index bfd68c401..e83518a84 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -2155,6 +2155,20 @@ //#define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ //#define SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define SSL_CIPHERSUITES TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + /* Debug options */ //#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */ diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c index ea12146ef..df838e260 100644 --- a/library/ssl_ciphersuites.c +++ b/library/ssl_ciphersuites.c @@ -57,6 +57,9 @@ */ static const int ciphersuite_preference[] = { +#if defined(SSL_CIPHERSUITES) + SSL_CIPHERSUITES, +#else /* All AES-256 ephemeral suites */ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, @@ -257,6 +260,7 @@ static const int ciphersuite_preference[] = TLS_PSK_WITH_NULL_SHA256, TLS_PSK_WITH_NULL_SHA, +#endif 0 }; @@ -1675,6 +1679,12 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] = { 0, "", 0, 0, 0, 0, 0, 0, 0, 0 } }; +#if defined(SSL_CIPHERSUITES) +const int *ssl_list_ciphersuites( void ) +{ + return( ciphersuite_preference ); +} +#else #define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ sizeof( ciphersuite_definitions[0] ) static int supported_ciphersuites[MAX_CIPHERSUITES]; @@ -1711,6 +1721,7 @@ const int *ssl_list_ciphersuites( void ) return( supported_ciphersuites ); }; +#endif /* SSL_CIPHERSUITES */ const ssl_ciphersuite_t *ssl_ciphersuite_from_string( const char *ciphersuite_name ) From cc10f4ddfe3ff71e8fa829aeecbf66efbd298997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 30 Jun 2014 19:22:44 +0200 Subject: [PATCH 4/6] Use SSL_CIPHERSUITES in example configs --- configs/config-ccm-psk-tls1_2.h | 9 ++++++++- configs/config-suite-b.h | 5 +++++ tests/scripts/test-ref-configs.pl | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/configs/config-ccm-psk-tls1_2.h b/configs/config-ccm-psk-tls1_2.h index f425391d0..c80c912ed 100644 --- a/configs/config-ccm-psk-tls1_2.h +++ b/configs/config-ccm-psk-tls1_2.h @@ -3,7 +3,7 @@ * Distinguishing features: * - no bignum, no PK, no X509 * - fully modern and secure (provided the pre-shared keys have high entropy) - * - very low record overhead if using the CCM-8 suites + * - very low record overhead with CCM-8 * - optimized for low RAM usage * * See README.txt for usage instructions. @@ -43,6 +43,13 @@ */ #define ENTROPY_MAX_SOURCES 2 +/* + * Use only CCM_8 ciphersuites, and + * save ROM and a few bytes of RAM by specifying our own ciphersuite list + */ +#define SSL_CIPHERSUITES \ + TLS_PSK_WITH_AES_256_CCM_8, \ + TLS_PSK_WITH_AES_128_CCM_8 /* * Save RAM at the expense of interoperability: do this only if you control * both ends of the connection! (See coments in "polarssl/ssl.h".) diff --git a/configs/config-suite-b.h b/configs/config-suite-b.h index d10cf6320..cd38f3334 100644 --- a/configs/config-suite-b.h +++ b/configs/config-suite-b.h @@ -77,6 +77,11 @@ */ #define ENTROPY_MAX_SOURCES 2 +/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */ +#define SSL_CIPHERSUITES \ + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \ + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + /* * Save RAM at the expense of interoperability: do this only if you control * both ends of the connection! (See coments in "polarssl/ssl.h".) diff --git a/tests/scripts/test-ref-configs.pl b/tests/scripts/test-ref-configs.pl index 9b09e3464..6546b05af 100755 --- a/tests/scripts/test-ref-configs.pl +++ b/tests/scripts/test-ref-configs.pl @@ -20,7 +20,7 @@ my %configs = ( 'config-picocoin.h' => 0, 'config-ccm-psk-tls1_2.h' - => '-m tls1_2 -f \'TLS-PSK.*AES.*CCM\'', + => '-m tls1_2 -f \'^TLS-PSK-WITH-AES-...-CCM-8\'', ); # If no config-name is provided, use all known configs. From 481fcfde93759dc77dfc3124a38feeaeaa2e73c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 3 Jul 2014 16:12:50 +0200 Subject: [PATCH 5/6] Make PSK_LEN configurable and adjust PMS size --- include/polarssl/config.h | 1 + include/polarssl/ssl.h | 40 ++++++++++++++++++++++++++--- include/polarssl/ssl_ciphersuites.h | 1 + library/ssl_tls.c | 7 +---- programs/ssl/ssl_client2.c | 2 +- programs/ssl/ssl_server2.c | 8 +++--- 6 files changed, 43 insertions(+), 16 deletions(-) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index e83518a84..d43365ff5 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -2154,6 +2154,7 @@ /* SSL options */ //#define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ //#define SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define POLARSSL_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ /** * Complete list of ciphersuites to use, in order of preference. diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 9db0fc6bc..f1de49940 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -34,6 +34,7 @@ #endif #include "net.h" #include "bignum.h" +#include "ecp.h" #include "ssl_ciphersuites.h" @@ -409,12 +410,43 @@ /* * Size defines */ -#if !defined(POLARSSL_MPI_MAX_SIZE) -#define POLARSSL_PREMASTER_SIZE 512 -#else -#define POLARSSL_PREMASTER_SIZE POLARSSL_MPI_MAX_SIZE +#if !defined(POLARSSL_PSK_MAX_LEN) +#define POLARSSL_PSK_MAX_LEN 32 /* 256 bits */ #endif +/* Dummy type used only for its size */ +union _ssl_premaster_secret +{ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) + unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) + unsigned char _pms_dhm[POLARSSL_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + unsigned char _pms_ecdh[POLARSSL_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + unsigned char _pms_psk[4 + 2 * POLARSSL_PSK_MAX_LEN]; /* RFC 4279 2 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_dhe_psk[4 + POLARSSL_MPI_MAX_SIZE + + POLARSSL_PSK_MAX_LEN]; /* RFC 4279 3 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + unsigned char _pms_rsa_psk[52 + POLARSSL_PSK_MAX_LEN]; /* RFC 4279 4 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_ecdhe_psk[4 + POLARSSL_ECP_MAX_BYTES + + POLARSSL_PSK_MAX_LEN]; /* RFC 5489 2 */ +#endif +}; + +#define POLARSSL_PREMASTER_SIZE sizeof( union _ssl_premaster_secret ) + #ifdef __cplusplus extern "C" { #endif diff --git a/include/polarssl/ssl_ciphersuites.h b/include/polarssl/ssl_ciphersuites.h index 5ecd5febd..c4f1ffe64 100644 --- a/include/polarssl/ssl_ciphersuites.h +++ b/include/polarssl/ssl_ciphersuites.h @@ -233,6 +233,7 @@ extern "C" { #define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ #define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ +/* Reminder: update _ssl_premaster_secret when adding a new key exchange */ typedef enum { POLARSSL_KEY_EXCHANGE_NONE = 0, POLARSSL_KEY_EXCHANGE_RSA, diff --git a/library/ssl_tls.c b/library/ssl_tls.c index a1428dccf..373a1f5bd 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -3740,12 +3740,7 @@ int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len, if( psk == NULL || psk_identity == NULL ) return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - /* - * The length will be check later anyway, but in case it is obviously - * too large, better abort now. The PMS is as follows: - * other_len (2 bytes) + other + psk_len (2 bytes) + psk - */ - if( psk_len + 4 > POLARSSL_PREMASTER_SIZE ) + if( psk_len > POLARSSL_PSK_MAX_LEN ) return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); if( ssl->psk != NULL ) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 3af54f904..4682ee5bc 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -325,7 +325,7 @@ int main( int argc, char *argv[] ) int ret = 0, len, server_fd, i, written, frags; unsigned char buf[SSL_MAX_CONTENT_LEN + 1]; #if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) - unsigned char psk[256]; + unsigned char psk[POLARSSL_PSK_MAX_LEN]; size_t psk_len = 0; #endif #if defined(POLARSSL_SSL_ALPN) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index d5f01bc0b..935a7a513 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -126,8 +126,6 @@ int main( int argc, char *argv[] ) "

PolarSSL Test Server

\r\n" \ "

Successful connection using: %s

\r\n" // LONG_RESPONSE -#define MAX_PSK_LEN 256 - /* * Size of the basic I/O buffer. Able to hold our default response. * @@ -460,7 +458,7 @@ int unhexify( unsigned char *output, const char *input, size_t *olen ) size_t j; *olen = strlen( input ); - if( *olen % 2 != 0 || *olen / 2 > MAX_PSK_LEN ) + if( *olen % 2 != 0 || *olen / 2 > POLARSSL_PSK_MAX_LEN ) return( -1 ); *olen /= 2; @@ -484,7 +482,7 @@ struct _psk_entry { const char *name; size_t key_len; - unsigned char key[MAX_PSK_LEN]; + unsigned char key[POLARSSL_PSK_MAX_LEN]; psk_entry *next; }; @@ -573,7 +571,7 @@ int main( int argc, char *argv[] ) int version_suites[4][2]; unsigned char buf[IO_BUF_LEN]; #if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) - unsigned char psk[MAX_PSK_LEN]; + unsigned char psk[POLARSSL_PSK_MAX_LEN]; size_t psk_len = 0; psk_entry *psk_info = NULL; #endif From ac7dd33de1b68011318cc751eb346f39344c7cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 3 Jul 2014 16:17:59 +0200 Subject: [PATCH 6/6] Update the ccm-psk config with psk_len 128 bits --- configs/config-ccm-psk-tls1_2.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/configs/config-ccm-psk-tls1_2.h b/configs/config-ccm-psk-tls1_2.h index c80c912ed..1da9f6a6b 100644 --- a/configs/config-ccm-psk-tls1_2.h +++ b/configs/config-ccm-psk-tls1_2.h @@ -13,7 +13,7 @@ /* System support */ //#define POLARSSL_HAVE_IPV6 /* Optional */ -//#define POLARSSL_HAVE_TIME /* Optionnaly used in Hello messages */ +//#define POLARSSL_HAVE_TIME /* Optionally used in Hello messages */ /* Other POLARSSL_HAVE_XXX flags irrelevant for this configuration */ /* PolarSSL feature support */ @@ -36,6 +36,9 @@ /* Save RAM at the expense of ROM */ #define POLARSSL_AES_ROM_TABLES +/* Save some RAM by adjusting to your exact needs */ +#define POLARSSL_PSK_MAX_LEN 16 /* 128-bits keys are generally enough */ + /* * You should adjust this to the exact number of sources you're using: default * is the "platform_entropy_poll" source, but you may want to add other ones @@ -50,9 +53,10 @@ #define SSL_CIPHERSUITES \ TLS_PSK_WITH_AES_256_CCM_8, \ TLS_PSK_WITH_AES_128_CCM_8 + /* * Save RAM at the expense of interoperability: do this only if you control - * both ends of the connection! (See coments in "polarssl/ssl.h".) + * both ends of the connection! (See comments in "polarssl/ssl.h".) * The optimal size here depends on the typical size of records. */ #define SSL_MAX_CONTENT_LEN 512