From 0fae60bb7186d9fedb937d1c20d0de4560f86c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 14 Oct 2013 17:39:48 +0200 Subject: [PATCH] Implement RSA-PSK key exchange --- include/polarssl/config.h | 4 +- library/ssl_cli.c | 129 +++++++++++++++++++++++++------------- library/ssl_srv.c | 65 +++++++++++++------ library/ssl_tls.c | 17 +++++ 4 files changed, 152 insertions(+), 63 deletions(-) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index dc22c6df43..3a173b38c3 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -307,7 +307,7 @@ * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED * * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. - * (NOT YET IMPLEMENTED) + * * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, * POLARSSL_X509_CRT_PARSE_C * @@ -321,8 +321,8 @@ * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 -#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED /** * \def POLARSSL_KEY_EXCHANGE_RSA_ENABLED diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 77a18ed35f..4da7149f46 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -1183,6 +1183,72 @@ static int ssl_parse_server_psk_hint( ssl_context *ssl, POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) +/* + * Generate a pre-master secret and encrypt it with the server's RSA key + */ +static int ssl_write_encrypted_pms( ssl_context *ssl, + size_t offset, size_t *olen, + size_t pms_offset ) +{ + int ret; + size_t len_bytes = ssl->minor_ver == SSL_MINOR_VERSION_0 ? 0 : 2; + unsigned char *p = ssl->handshake->premaster + pms_offset; + + /* + * Generate (part of) the pre-master as + * struct { + * ProtocolVersion client_version; + * opaque random[46]; + * } PreMasterSecret; + */ + p[0] = (unsigned char) ssl->max_major_ver; + p[1] = (unsigned char) ssl->max_minor_ver; + + if( ( ret = ssl->f_rng( ssl->p_rng, p + 2, 46 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "f_rng", ret ); + return( ret ); + } + + ssl->handshake->pmslen = 48; + + /* + * Now write it out, encrypted + */ + if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, + POLARSSL_PK_RSA ) ) + { + SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); + return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = pk_encrypt( &ssl->session_negotiate->peer_cert->pk, + p, ssl->handshake->pmslen, + ssl->out_msg + offset + len_bytes, olen, + SSL_MAX_CONTENT_LEN - offset - len_bytes, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret ); + return( ret ); + } + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( len_bytes == 2 ) + { + ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 ); + ssl->out_msg[offset+1] = (unsigned char)( *olen ); + *olen += 2; + } +#endif + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ + #if defined(POLARSSL_SSL_PROTO_TLS1_2) #if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ @@ -1258,6 +1324,7 @@ 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_RSA_PSK && ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_PSK && ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) { @@ -1324,8 +1391,10 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) else #endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ -#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ) +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) { unsigned char *p = ssl->in_msg + 4; unsigned char *end = ssl->in_msg + ssl->in_hslen; @@ -1337,7 +1406,8 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) } } else -#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) { @@ -1803,9 +1873,11 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) #endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) { @@ -1830,6 +1902,14 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) } else #endif +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + { + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 ) + return( ret ); + } + else +#endif #if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) { @@ -1885,56 +1965,21 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) } else #endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED || POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED || POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA ) { - /* - * RSA key exchange -- send rsa_public(pkcs1 v1.5(premaster)) - */ - 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->handshake->premaster + 2, - ssl->handshake->pmslen - 2 ); - if( ret != 0 ) + i = 4; + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 ) return( ret ); - - if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, - POLARSSL_PK_RSA ) ) - { - SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); - return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH ); - } - - i = ssl->minor_ver == SSL_MINOR_VERSION_0 ? 4 : 6; - - ret = pk_encrypt( &ssl->session_negotiate->peer_cert->pk, - ssl->handshake->premaster, ssl->handshake->pmslen, - ssl->out_msg + i, &n, SSL_BUFFER_LEN, - ssl->f_rng, ssl->p_rng ); - if( ret != 0 ) - { - SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret ); - return( ret ); - } - -#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ - defined(POLARSSL_SSL_PROTO_TLS1_2) - if( ssl->minor_ver != SSL_MINOR_VERSION_0 ) - { - ssl->out_msg[4] = (unsigned char)( n >> 8 ); - ssl->out_msg[5] = (unsigned char)( n ); - } -#endif - } else #endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ { ((void) ciphersuite_info); + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); } diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 336add2e3a..6db92d6125 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -2288,10 +2288,14 @@ static int ssl_parse_client_dh_public( ssl_context *ssl, unsigned char **p, POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) -static int ssl_parse_encrypted_pms_secret( ssl_context *ssl ) +static int ssl_parse_encrypted_pms( ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) { - int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; - size_t i, n = 0; + int ret; + size_t len = pk_get_len( ssl_own_key( ssl ) ); + unsigned char *pms = ssl->handshake->premaster + pms_offset; if( ! pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_RSA ) ) { @@ -2302,17 +2306,12 @@ static int ssl_parse_encrypted_pms_secret( ssl_context *ssl ) /* * Decrypt the premaster using own private RSA key */ - i = 4; - n = pk_get_len( ssl_own_key( ssl ) ); - ssl->handshake->pmslen = 48; - #if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ defined(POLARSSL_SSL_PROTO_TLS1_2) if( ssl->minor_ver != SSL_MINOR_VERSION_0 ) { - i += 2; - if( ssl->in_msg[4] != ( ( n >> 8 ) & 0xFF ) || - ssl->in_msg[5] != ( ( n ) & 0xFF ) ) + if( *p++ != ( ( len >> 8 ) & 0xFF ) || + *p++ != ( ( len ) & 0xFF ) ) { SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); @@ -2320,21 +2319,20 @@ static int ssl_parse_encrypted_pms_secret( ssl_context *ssl ) } #endif - if( ssl->in_hslen != i + n ) + if( p + len != end ) { SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); } - ret = pk_decrypt( ssl_own_key( ssl ), - ssl->in_msg + i, n, - ssl->handshake->premaster, &ssl->handshake->pmslen, + ret = pk_decrypt( ssl_own_key( ssl ), p, len, + pms, &ssl->handshake->pmslen, sizeof(ssl->handshake->premaster), ssl->f_rng, ssl->p_rng ); if( ret != 0 || ssl->handshake->pmslen != 48 || - ssl->handshake->premaster[0] != ssl->handshake->max_major_ver || - ssl->handshake->premaster[1] != ssl->handshake->max_minor_ver ) + pms[0] != ssl->handshake->max_major_ver || + pms[1] != ssl->handshake->max_minor_ver ) { SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); @@ -2346,8 +2344,7 @@ static int ssl_parse_encrypted_pms_secret( ssl_context *ssl ) */ ssl->handshake->pmslen = 48; - ret = ssl->f_rng( ssl->p_rng, ssl->handshake->premaster, - ssl->handshake->pmslen ); + ret = ssl->f_rng( ssl->p_rng, pms, ssl->handshake->pmslen ); if( ret != 0 ) return( ret ); } @@ -2541,6 +2538,33 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) } else #endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + { + 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_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); + return( ret ); + } + + if( ( ret = ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) { @@ -2600,7 +2624,10 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) #if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA ) { - if( ( ret = ssl_parse_encrypted_pms_secret( ssl ) ) != 0 ) + if( ( ret = ssl_parse_encrypted_pms( ssl, + ssl->in_msg + 4, + ssl->in_msg + ssl->in_msglen, + 0 ) ) != 0 ) { SSL_DEBUG_RET( 1, ( "ssl_parse_parse_ecrypted_pms_secret" ), ret ); return( ret ); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 2be20163f7..e254f3a54b 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -826,6 +826,7 @@ void ssl_calc_verify_tls_sha384( ssl_context *ssl, unsigned char hash[48] ) #endif /* POLARSSL_SSL_PROTO_TLS1_2 */ #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex ) @@ -852,6 +853,19 @@ int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex ) } else #endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( key_ex == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + { + /* + * other_secret already set by the ClientKeyExchange message, + * and is 48 bytes long + */ + *p++ = 0; + *p++ = 48; + p += 48; + } + else +#endif /* POLARSSL_KEY_EXCHANGE_RSA_PKS_ENABLED */ #if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) if( key_ex == POLARSSL_KEY_EXCHANGE_DHE_PSK ) { @@ -913,6 +927,7 @@ int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex ) return( 0 ); } #endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED || POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED || POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ @@ -3661,6 +3676,7 @@ int ssl_set_own_cert_alt( ssl_context *ssl, x509_crt *own_cert, #endif /* POLARSSL_X509_CRT_PARSE_C */ #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len, @@ -3699,6 +3715,7 @@ void ssl_set_psk_cb( ssl_context *ssl, ssl->p_psk = p_psk; } #endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED || POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED || POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */