]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added support for ECDHE-RSA ciphersuites.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 21 May 2011 07:23:48 +0000 (09:23 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 21 May 2011 07:23:48 +0000 (09:23 +0200)
lib/auth/anon_ecdh.c
lib/auth/dh_common.c
lib/auth/dhe.c
lib/auth/ecdh_common.c
lib/gnutls_algorithms.c
lib/gnutls_global.c
lib/gnutls_handshake.c
lib/gnutls_state.c
lib/gnutls_state.h
lib/includes/gnutls/gnutls.h.in

index 5e9932faa35dcfb3ac40e7d7c8792d25826a8468..e87f80c88f586ca985a2e2d1e33b546430177b68 100644 (file)
@@ -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
index d5c3506169d94ea621a87e6db9d8253410cd4b67..f887af6930d495692ef390a9ad513f6d7ab39189 100644 (file)
@@ -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)
index c8badfeffe9ffcd5468b4d5ad1075bdec75ad0d5..a2615764e66e5d01d56bba00177b72b7783c2bae 100644 (file)
 #include <gnutls_x509.h>
 #include <gnutls_state.h>
 #include <auth/dh_common.h>
+#include <auth/ecdh_common.h>
 
 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;
 
index 502396d1b00f33de78aef81b9d86860c6df8cb1c..e4440c1e503021717d554fe69f702134af440ac4 100644 (file)
@@ -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;
   
index dd95f2d3bbde3625a23daf12fec27acac77daac4..df9d1e61f10f5a53d168066054f1e08f94b25919 100644 (file)
@@ -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}
 };
 
index 483d2456bb389fba96bb7922b976171ae182e296..15bf0cdf17a9d40e77ca9fead106501395cb3224 100644 (file)
@@ -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;
 
index 759987463d11972e79711e7dd7bb4bb5bc7f15b1..c262f6f69c483a624e20c59d3dac879a4ee5eefb 100644 (file)
@@ -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;
index ab4d9d0793bc38af67adb67340674dd468b3ced9..c8c83b8555702154227ad3fde12133a520b6a24d 100644 (file)
@@ -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.
index edd4b0dab1d47f26350f7ff053de0278ff579280..7e51463d8e98609853b909281ddb154aa0c54ece 100644 (file)
@@ -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);
index 053970f3b44a0d7dc485c13dab00507b144504e7..0a08825f5a00f8f3d053808a6428e8a3f885af84 100644 (file)
@@ -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;
 
   /**