From: Nikos Mavrogiannopoulos Date: Sat, 21 May 2011 07:23:48 +0000 (+0200) Subject: Added support for ECDHE-RSA ciphersuites. X-Git-Tag: gnutls_2_99_2~57 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6bfd33b21877d02b2fe81fd5629d604976f460c8;p=thirdparty%2Fgnutls.git Added support for ECDHE-RSA ciphersuites. --- diff --git a/lib/auth/anon_ecdh.c b/lib/auth/anon_ecdh.c index 5e9932faa3..e87f80c88f 100644 --- a/lib/auth/anon_ecdh.c +++ b/lib/auth/anon_ecdh.c @@ -66,7 +66,6 @@ const mod_auth_st anon_ecdh_auth_struct = { static int gen_anon_ecdh_server_kx (gnutls_session_t session, gnutls_buffer_st* data) { - ecc_curve_t curve; int ret; gnutls_anon_server_credentials_t cred; @@ -78,10 +77,6 @@ gen_anon_ecdh_server_kx (gnutls_session_t session, gnutls_buffer_st* data) return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } - curve = _gnutls_session_ecc_curve_get(session); - if (curve == GNUTLS_ECC_CURVE_INVALID) - return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); - if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_ANON, sizeof (anon_auth_info_st), 1)) < 0) @@ -90,7 +85,7 @@ gen_anon_ecdh_server_kx (gnutls_session_t session, gnutls_buffer_st* data) return ret; } - ret = _gnutls_ecdh_common_print_server_kx (session, data, curve); + ret = _gnutls_ecdh_common_print_server_kx (session, data, _gnutls_session_ecc_curve_get(session)); if (ret < 0) { gnutls_assert (); @@ -105,7 +100,6 @@ proc_anon_ecdh_client_kx (gnutls_session_t session, opaque * data, size_t _data_size) { gnutls_anon_server_credentials_t cred; - ecc_curve_t curve; cred = (gnutls_anon_server_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_ANON, NULL); @@ -115,11 +109,7 @@ proc_anon_ecdh_client_kx (gnutls_session_t session, opaque * data, return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } - curve = _gnutls_session_ecc_curve_get(session); - if (curve == GNUTLS_ECC_CURVE_INVALID) - return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); - - return _gnutls_proc_ecdh_common_client_kx (session, data, _data_size, curve); + return _gnutls_proc_ecdh_common_client_kx (session, data, _data_size, _gnutls_session_ecc_curve_get(session)); } int diff --git a/lib/auth/dh_common.c b/lib/auth/dh_common.c index d5c3506169..f887af6930 100644 --- a/lib/auth/dh_common.c +++ b/lib/auth/dh_common.c @@ -202,6 +202,7 @@ error: return ret; } +/* Returns the bytes parsed */ int _gnutls_proc_dh_common_server_kx (gnutls_session_t session, opaque * data, size_t _data_size, int psk) diff --git a/lib/auth/dhe.c b/lib/auth/dhe.c index c8badfeffe..a2615764e6 100644 --- a/lib/auth/dhe.c +++ b/lib/auth/dhe.c @@ -40,11 +40,29 @@ #include #include #include +#include static int gen_dhe_server_kx (gnutls_session_t, gnutls_buffer_st*); static int proc_dhe_server_kx (gnutls_session_t, opaque *, size_t); static int proc_dhe_client_kx (gnutls_session_t, opaque *, size_t); +const mod_auth_st ecdhe_rsa_auth_struct = { + "ECDHE_RSA", + _gnutls_gen_cert_server_certificate, + _gnutls_gen_cert_client_certificate, + gen_dhe_server_kx, + _gnutls_gen_ecdh_common_client_kx, /* This is the only different */ + _gnutls_gen_cert_client_cert_vrfy, + _gnutls_gen_cert_server_cert_req, + + _gnutls_proc_cert_server_certificate, + _gnutls_proc_cert_client_certificate, + proc_dhe_server_kx, + proc_dhe_client_kx, + _gnutls_proc_cert_client_cert_vrfy, + _gnutls_proc_cert_cert_req +}; + const mod_auth_st dhe_rsa_auth_struct = { "DHE_RSA", _gnutls_gen_cert_server_certificate, @@ -112,18 +130,6 @@ gen_dhe_server_kx (gnutls_session_t session, gnutls_buffer_st* data) return ret; } - dh_params = - _gnutls_get_dh_params (cred->dh_params, cred->params_func, session); - mpis = _gnutls_dh_params_to_mpi (dh_params); - if (mpis == NULL) - { - gnutls_assert (); - return GNUTLS_E_NO_TEMPORARY_DH_PARAMS; - } - - p = mpis[0]; - g = mpis[1]; - if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE, sizeof (cert_auth_info_st), 0)) < 0) { @@ -131,9 +137,29 @@ gen_dhe_server_kx (gnutls_session_t session, gnutls_buffer_st* data) return ret; } - _gnutls_dh_set_group (session, g, p); + if (!_gnutls_session_is_ecc (session)) + { + dh_params = + _gnutls_get_dh_params (cred->dh_params, cred->params_func, session); + mpis = _gnutls_dh_params_to_mpi (dh_params); + if (mpis == NULL) + { + gnutls_assert (); + return GNUTLS_E_NO_TEMPORARY_DH_PARAMS; + } + + p = mpis[0]; + g = mpis[1]; + + _gnutls_dh_set_group (session, g, p); + + ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 0); + } + else + { + ret = _gnutls_ecdh_common_print_server_kx (session, data, _gnutls_session_ecc_curve_get(session)); + } - ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 0); if (ret < 0) { gnutls_assert (); @@ -229,7 +255,11 @@ proc_dhe_server_kx (gnutls_session_t session, opaque * data, return GNUTLS_E_INTERNAL_ERROR; } - ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size, 0); + if (!_gnutls_session_is_ecc (session)) + ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size, 0); + else + ret = _gnutls_proc_ecdh_common_server_kx (session, data, _data_size); + if (ret < 0) { gnutls_assert (); @@ -309,19 +339,21 @@ proc_dhe_client_kx (gnutls_session_t session, opaque * data, return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } - dh_params = - _gnutls_get_dh_params (cred->dh_params, cred->params_func, session); - mpis = _gnutls_dh_params_to_mpi (dh_params); - if (mpis == NULL) + if (!_gnutls_session_is_ecc (session)) { - gnutls_assert (); - return GNUTLS_E_NO_TEMPORARY_DH_PARAMS; - } + dh_params = + _gnutls_get_dh_params (cred->dh_params, cred->params_func, session); + mpis = _gnutls_dh_params_to_mpi (dh_params); + if (mpis == NULL) + return gnutls_assert_val(GNUTLS_E_NO_TEMPORARY_DH_PARAMS); - p = mpis[0]; - g = mpis[1]; + p = mpis[0]; + g = mpis[1]; - ret = _gnutls_proc_dh_common_client_kx (session, data, _data_size, g, p); + ret = _gnutls_proc_dh_common_client_kx (session, data, _data_size, g, p); + } + else + ret = _gnutls_proc_ecdh_common_client_kx (session, data, _data_size, _gnutls_session_ecc_curve_get(session)); return ret; diff --git a/lib/auth/ecdh_common.c b/lib/auth/ecdh_common.c index 502396d1b0..e4440c1e50 100644 --- a/lib/auth/ecdh_common.c +++ b/lib/auth/ecdh_common.c @@ -81,6 +81,9 @@ _gnutls_proc_ecdh_common_client_kx (gnutls_session_t session, int ret, i = 0; int point_size; + if (curve == GNUTLS_ECC_CURVE_INVALID) + return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); + DECR_LEN (data_size, 1); point_size = data[i]; i+=1; @@ -130,6 +133,7 @@ _gnutls_gen_ecdh_common_client_kx (gnutls_session_t session, gnutls_buffer_st* d return data->length; } +/* Returns the bytes parsed */ int _gnutls_proc_ecdh_common_server_kx (gnutls_session_t session, opaque * data, size_t _data_size) @@ -155,14 +159,16 @@ _gnutls_proc_ecdh_common_server_kx (gnutls_session_t session, DECR_LEN (data_size, 1); point_size = data[i]; - i+=1; + i++; DECR_LEN (data_size, point_size); ret = _gnutls_ecc_ansi_x963_import(curve, &data[i], point_size, &session->key->ecdh_x, &session->key->ecdh_y); if (ret < 0) return gnutls_assert_val(ret); - return ret; + i+=point_size; + + return i; } /* If the psk flag is set, then an empty psk_identity_hint will @@ -174,6 +180,9 @@ int _gnutls_ecdh_common_print_server_kx (gnutls_session_t session, gnutls_buffer int ret; gnutls_datum_t out; + if (curve == GNUTLS_ECC_CURVE_INVALID) + return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); + /* curve type */ p = 3; diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index dd95f2d3bb..df9d1e61f1 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -73,6 +73,7 @@ static const gnutls_cred_map cred_mappings[] = { {GNUTLS_KX_ANON_ECDH, GNUTLS_CRD_ANON, GNUTLS_CRD_ANON}, {GNUTLS_KX_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE}, {GNUTLS_KX_RSA_EXPORT, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE}, + {GNUTLS_KX_ECDHE_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE}, {GNUTLS_KX_DHE_DSS, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE}, {GNUTLS_KX_DHE_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE}, {GNUTLS_KX_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_PSK}, @@ -114,6 +115,7 @@ static const gnutls_pk_map pk_mappings[] = { {GNUTLS_KX_RSA_EXPORT, GNUTLS_PK_RSA, CIPHER_SIGN}, {GNUTLS_KX_DHE_RSA, GNUTLS_PK_RSA, CIPHER_SIGN}, {GNUTLS_KX_SRP_RSA, GNUTLS_PK_RSA, CIPHER_SIGN}, + {GNUTLS_KX_ECDHE_RSA, GNUTLS_PK_RSA, CIPHER_SIGN}, {GNUTLS_KX_DHE_DSS, GNUTLS_PK_DSA, CIPHER_SIGN}, {GNUTLS_KX_SRP_DSS, GNUTLS_PK_DSA, CIPHER_SIGN}, {0, 0, 0} @@ -259,6 +261,7 @@ static const gnutls_hash_entry hash_algorithms[] = { extern mod_auth_st rsa_auth_struct; extern mod_auth_st rsa_export_auth_struct; extern mod_auth_st dhe_rsa_auth_struct; +extern mod_auth_st ecdhe_rsa_auth_struct; extern mod_auth_st dhe_dss_auth_struct; extern mod_auth_st anon_auth_struct; extern mod_auth_st anon_ecdh_auth_struct; @@ -287,6 +290,7 @@ static const gnutls_kx_algo_entry _gnutls_kx_algorithms[] = { {"RSA-EXPORT", GNUTLS_KX_RSA_EXPORT, &rsa_export_auth_struct, 0, 1 /* needs RSA params */ }, {"DHE-RSA", GNUTLS_KX_DHE_RSA, &dhe_rsa_auth_struct, 1, 0}, + {"ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, &ecdhe_rsa_auth_struct, 1, 0}, {"DHE-DSS", GNUTLS_KX_DHE_DSS, &dhe_dss_auth_struct, 1, 0}, #ifdef ENABLE_SRP @@ -467,10 +471,17 @@ typedef struct #define GNUTLS_DHE_PSK_NULL_SHA256 { 0x00, 0xB4 } /* ECC */ +#define GNUTLS_ECDH_ANON_NULL_SHA { 0xC0, 0x15 } #define GNUTLS_ECDH_ANON_3DES_EDE_CBC_SHA { 0xC0, 0x17 } #define GNUTLS_ECDH_ANON_AES_128_CBC_SHA { 0xC0, 0x18 } #define GNUTLS_ECDH_ANON_AES_256_CBC_SHA { 0xC0, 0x19 } +/* ECC-RSA */ +#define GNUTLS_ECDHE_RSA_NULL_SHA { 0xC0, 0x10 } +#define GNUTLS_ECDHE_RSA_3DES_EDE_CBC_SHA { 0xC0, 0x12 } +#define GNUTLS_ECDHE_RSA_AES_128_CBC_SHA { 0xC0, 0x13 } +#define GNUTLS_ECDHE_RSA_AES_256_CBC_SHA { 0xC0, 0x14 } + #define CIPHER_SUITES_COUNT sizeof(cs_algorithms)/sizeof(gnutls_cipher_suite_entry)-1 @@ -769,6 +780,10 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = { GNUTLS_MAC_AEAD, GNUTLS_TLS1_2, GNUTLS_VERSION_MAX, 1), /* ECC-ANON */ + GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_NULL_SHA, + GNUTLS_CIPHER_NULL, GNUTLS_KX_ANON_ECDH, + GNUTLS_MAC_SHA1, GNUTLS_TLS1_0, + GNUTLS_VERSION_MAX, 1), GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_3DES_EDE_CBC_SHA, GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_ANON_ECDH, GNUTLS_MAC_SHA1, GNUTLS_TLS1_0, @@ -781,7 +796,23 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = { GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ANON_ECDH, GNUTLS_MAC_SHA1, GNUTLS_TLS1_0, GNUTLS_VERSION_MAX, 1), - +/* ECC-RSA */ + GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_RSA_NULL_SHA, + GNUTLS_CIPHER_NULL, GNUTLS_KX_ECDHE_RSA, + GNUTLS_MAC_SHA1, GNUTLS_TLS1_0, + GNUTLS_VERSION_MAX, 1), + GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_RSA_3DES_EDE_CBC_SHA, + GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_ECDHE_RSA, + GNUTLS_MAC_SHA1, GNUTLS_TLS1_0, + GNUTLS_VERSION_MAX, 1), + GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_RSA_AES_128_CBC_SHA, + GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ECDHE_RSA, + GNUTLS_MAC_SHA1, GNUTLS_TLS1_0, + GNUTLS_VERSION_MAX, 1), + GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_RSA_AES_256_CBC_SHA, + GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ECDHE_RSA, + GNUTLS_MAC_SHA1, GNUTLS_TLS1_0, + GNUTLS_VERSION_MAX, 1), {0, {{0, 0}}, 0, 0, 0, 0, 0, 0} }; diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c index 483d2456bb..15bf0cdf17 100644 --- a/lib/gnutls_global.c +++ b/lib/gnutls_global.c @@ -155,8 +155,6 @@ gnutls_global_set_mem_functions (gnutls_alloc_function alloc_func, } static int _gnutls_init = 0; -int ecc_test(void); - /** * gnutls_global_init: @@ -196,9 +194,6 @@ gnutls_global_init (void) if (_gnutls_init++) goto out; -res = ecc_test(); -if (res != 0) exit(1); - if (gl_sockets_startup (SOCKETS_1_1)) return GNUTLS_E_LIBRARY_VERSION_MISMATCH; diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 759987463d..c262f6f69c 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -3348,7 +3348,8 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t session, /* If we have not agreed to a common curve with the peer don't bother * negotiating ECDH. */ - if (session->security_parameters.entity == GNUTLS_SERVER && (kx == GNUTLS_KX_ANON_ECDH)) + if (session->security_parameters.entity == GNUTLS_SERVER && (kx == GNUTLS_KX_ANON_ECDH || + kx == GNUTLS_KX_ECDHE_RSA)) { if (_gnutls_session_ecc_curve_get(session) == GNUTLS_ECC_CURVE_INVALID) delete = 1; diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index ab4d9d0793..c8c83b8555 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -1176,6 +1176,27 @@ _gnutls_session_is_psk (gnutls_session_t session) return 0; } +/*- + * _gnutls_session_is_ecc - Used to check whether this session uses ECC kx + * @session: is a #gnutls_session_t structure. + * + * This function will return non zero if this session uses an elliptic + * curves key exchange exchange algorithm. + -*/ +int +_gnutls_session_is_ecc (gnutls_session_t session) +{ + gnutls_kx_algorithm_t kx; + + kx = + _gnutls_cipher_suite_get_kx_algo (&session-> + security_parameters.current_cipher_suite); + if (kx == GNUTLS_KX_ECDHE_RSA || kx == GNUTLS_KX_ANON_ECDH) + return 1; + + return 0; +} + /** * gnutls_session_get_ptr: * @session: is a #gnutls_session_t structure. diff --git a/lib/gnutls_state.h b/lib/gnutls_state.h index edd4b0dab1..7e51463d8e 100644 --- a/lib/gnutls_state.h +++ b/lib/gnutls_state.h @@ -36,6 +36,8 @@ inline static ecc_curve_t _gnutls_session_ecc_curve_get(gnutls_session_t session return session->security_parameters.ecc_curve; } +int _gnutls_session_is_ecc (gnutls_session_t session); + void _gnutls_session_ecc_curve_set (gnutls_session_t session, ecc_curve_t c); diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 053970f3b4..0a08825f5a 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -128,6 +128,7 @@ extern "C" * @GNUTLS_KX_RSA: RSA key-exchange algorithm. * @GNUTLS_KX_DHE_DSS: DHE-DSS key-exchange algorithm. * @GNUTLS_KX_DHE_RSA: DHE-RSA key-exchange algorithm. + * @GNUTLS_KX_ECDHE_RSA: ECDHE-RSA key-exchange algorithm. * @GNUTLS_KX_ANON_DH: Anon-DH key-exchange algorithm. * @GNUTLS_KX_ANON_ECDH: Anon-ECDH key-exchange algorithm. * @GNUTLS_KX_SRP: SRP key-exchange algorithm. @@ -153,6 +154,7 @@ extern "C" GNUTLS_KX_PSK = 9, GNUTLS_KX_DHE_PSK = 10, GNUTLS_KX_ANON_ECDH = 11, + GNUTLS_KX_ECDHE_RSA = 12, } gnutls_kx_algorithm_t; /**