diff --git a/include/polarssl/config.h b/include/polarssl/config.h index bd1234396..ed5ae2c8c 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -280,6 +280,18 @@ */ #define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + */ +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + /** * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED * @@ -1736,6 +1748,11 @@ #error "POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" #endif +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(POLARSSL_ECDH_C) +#error "POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + #if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ ( !defined(POLARSSL_DHM_C) || !defined(POLARSSL_RSA_C) || \ !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) ) diff --git a/include/polarssl/ssl_ciphersuites.h b/include/polarssl/ssl_ciphersuites.h index 73d626067..715762282 100644 --- a/include/polarssl/ssl_ciphersuites.h +++ b/include/polarssl/ssl_ciphersuites.h @@ -166,6 +166,7 @@ typedef enum { POLARSSL_KEY_EXCHANGE_PSK, POLARSSL_KEY_EXCHANGE_DHE_PSK, POLARSSL_KEY_EXCHANGE_RSA_PSK, + POLARSSL_KEY_EXCHANGE_ECDHE_PSK, } key_exchange_type_t; typedef struct _ssl_ciphersuite_t ssl_ciphersuite_t; diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 81d8e8834..178393a97 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -1106,7 +1106,8 @@ static int ssl_parse_server_dh_params( ssl_context *ssl, unsigned char **p, POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) static int ssl_parse_server_ecdh_params( ssl_context *ssl, unsigned char **p, unsigned char *end ) @@ -1143,10 +1144,12 @@ static int ssl_parse_server_ecdh_params( ssl_context *ssl, return( ret ); } #endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) || \ - defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) static int ssl_parse_server_psk_hint( ssl_context *ssl, unsigned char **p, unsigned char *end ) @@ -1177,7 +1180,8 @@ static int ssl_parse_server_psk_hint( ssl_context *ssl, return( ret ); } #endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED || - POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ + POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(POLARSSL_SSL_PROTO_TLS1_2) #if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ @@ -1254,7 +1258,8 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_RSA && ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA && ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_PSK && - ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_PSK ) + ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_PSK && + ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) { SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); ssl->state++; @@ -1352,6 +1357,25 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) } else #endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + unsigned char *p = ssl->in_msg + 4; + unsigned char *end = ssl->in_msg + ssl->in_hslen; + + if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ { return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); } @@ -1880,6 +1904,75 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) } else #endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + unsigned char *p = ssl->handshake->premaster; + + /* + * ECDHE_PSK key exchange: RFC 5489, section 2 + * + * opaque psk_identity<0..2^16-1>; + * ClientECDiffieHellmanPublic public; + */ + if( ssl->psk == NULL ) + return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); + + if( sizeof(ssl->handshake->premaster) < 4 + ssl->psk_identity_len ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + i = 4; + n = ssl->psk_identity_len; + ssl->out_msg[4] = (unsigned char)( n >> 8 ); + ssl->out_msg[5] = (unsigned char)( n ); + + memcpy( ssl->out_msg + 6, ssl->psk_identity, ssl->psk_identity_len ); + + ret = ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, + &ssl->out_msg[8 + ssl->psk_identity_len], 512, + ssl->f_rng, ssl->p_rng ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_make_public", ret ); + return( ret ); + } + + ssl->out_msg[6 + ssl->psk_identity_len] = (unsigned char)( n >> 8 ); + ssl->out_msg[7 + ssl->psk_identity_len] = (unsigned char)( n ); + + SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + + /* + * PMS = struct { + * opaque other_secret<0..2^16-1>; + * opaque psk<0..2^16-1>; + * }; + * with "other_secret" containing Z from ECDH + */ + if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &n, + p + 2, POLARSSL_MPI_MAX_SIZE, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( n >> 8 ); + *(p++) = (unsigned char)( n ); + p += n; + + SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + + *(p++) = (unsigned char)( ssl->psk_len >> 8 ); + *(p++) = (unsigned char)( ssl->psk_len ); + memcpy( p, ssl->psk, ssl->psk_len ); + p += ssl->psk_len; + + ssl->handshake->pmslen = 4 + n + ssl->psk_len; + n = ssl->handshake->pmslen; + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA ) { diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 15d14fa88..b128d9dad 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -1750,7 +1750,8 @@ static int ssl_write_certificate_request( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) { SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); ssl->state++; @@ -1776,6 +1777,7 @@ static int ssl_write_certificate_request( ssl_context *ssl ) if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || ssl->authmode == SSL_VERIFY_NONE ) { SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); @@ -1928,15 +1930,18 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) if( ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_RSA && ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_RSA && ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA && - ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_PSK ) + ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_PSK && + ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) { SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); ssl->state++; return( 0 ); } -#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) { /* TODO: Support identity hints */ *(p++) = 0x00; @@ -1944,7 +1949,8 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) n += 2; } -#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) @@ -1991,9 +1997,12 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ) + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) { /* * Ephemeral ECDH parameters: @@ -2031,7 +2040,8 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); } #endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ @@ -2278,10 +2288,11 @@ static int ssl_parse_client_dh_public( ssl_context *ssl, unsigned char **p, POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) static int ssl_parse_client_ecdh_public( ssl_context *ssl ) { - int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + int ret; size_t n; /* @@ -2308,7 +2319,8 @@ static int ssl_parse_client_ecdh_public( ssl_context *ssl ) return( ret ); } #endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) static int ssl_parse_encrypted_pms_secret( ssl_context *ssl ) @@ -2380,7 +2392,8 @@ static int ssl_parse_encrypted_pms_secret( ssl_context *ssl ) #endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) || \ - defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) static int ssl_parse_client_psk_identity( ssl_context *ssl, unsigned char **p, const unsigned char *end ) { @@ -2447,7 +2460,8 @@ static int ssl_parse_client_psk_identity( ssl_context *ssl, unsigned char **p, return( ret ); } #endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED || - POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ + POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ static int ssl_parse_client_key_exchange( ssl_context *ssl ) { @@ -2490,7 +2504,6 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len; - /* No blinding needed for DHE, but will be needed for fixed DH! */ if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx, ssl->handshake->premaster, &ssl->handshake->pmslen, @@ -2584,7 +2597,6 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) n = ssl->handshake->dhm_ctx.len; - /* No blinding needed since this is ephemeral DHM */ if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx, p, &n, ssl->f_rng, ssl->p_rng ) ) != 0 ) { @@ -2605,6 +2617,52 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) } else #endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + size_t n; + unsigned char *p = ssl->in_msg + 4; + unsigned char *end = ssl->in_msg + ssl->in_msglen; + + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + if( ( ret = ssl_parse_client_ecdh_public( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_ecdh_public" ), ret ); + return( ret ); + } + + // Set up the premaster secret + // + p = ssl->handshake->premaster; + + if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &n, + p + 2, POLARSSL_MPI_MAX_SIZE, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( n >> 8 ); + *(p++) = (unsigned char)( n ); + p += n; + + SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + + *(p++) = (unsigned char)( ssl->psk_len >> 8 ); + *(p++) = (unsigned char)( ssl->psk_len ); + memcpy( p, ssl->psk, ssl->psk_len ); + p += ssl->psk_len; + + ssl->handshake->pmslen = 4 + n + ssl->psk_len; + n = ssl->handshake->pmslen; + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA ) { diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 39291fa43..d3b4ce3a0 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2241,7 +2241,8 @@ int ssl_write_certificate( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) { SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); ssl->state++; @@ -2260,7 +2261,8 @@ int ssl_parse_certificate( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) { SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); ssl->state++; @@ -2281,7 +2283,8 @@ int ssl_write_certificate( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) { SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); ssl->state++; @@ -2390,7 +2393,8 @@ int ssl_parse_certificate( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) { SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); ssl->state++;