summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS8
-rw-r--r--lib/algorithms/ciphersuites.c38
-rw-r--r--lib/algorithms/kx.c7
-rw-r--r--lib/auth/anon.c6
-rw-r--r--lib/auth/anon_ecdh.c3
-rw-r--r--lib/auth/dh_common.c36
-rw-r--r--lib/auth/dh_common.h7
-rw-r--r--lib/auth/dhe.c9
-rw-r--r--lib/auth/dhe_psk.c145
-rw-r--r--lib/auth/ecdh_common.c55
-rw-r--r--lib/auth/ecdh_common.h19
-rw-r--r--lib/gnutls_state.c3
-rw-r--r--lib/includes/gnutls/gnutls.h.in2
13 files changed, 272 insertions, 66 deletions
diff --git a/NEWS b/NEWS
index b3edf687fe..86abf15d30 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,14 @@ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
See the end for copying conditions.
+* Version 2.99.3 (unreleased)
+
+** libgnutls: Added ECDHE-PSK ciphersuites for TLS (RFC 5489).
+
+** API and ABI modifications:
+GNUTLS_KX_ECDHE_PSK: New key exchange method
+
+
* Version 2.99.2 (released 2011-05-26)
** libgnutls: Added Elliptic curve support. This is not
diff --git a/lib/algorithms/ciphersuites.c b/lib/algorithms/ciphersuites.c
index 09b115dd86..e834e165d7 100644
--- a/lib/algorithms/ciphersuites.c
+++ b/lib/algorithms/ciphersuites.c
@@ -216,6 +216,15 @@ typedef struct
#define GNUTLS_ECDHE_ECDSA_AES_128_GCM_SHA256 {0xC0,0x2B}
#define GNUTLS_ECDHE_RSA_AES_128_GCM_SHA256 {0xC0,0x2F}
+/* ECC with PSK */
+#define GNUTLS_ECDHE_PSK_3DES_EDE_CBC_SHA { 0xC0, 0x34 }
+#define GNUTLS_ECDHE_PSK_AES_128_CBC_SHA { 0xC0, 0x35 }
+#define GNUTLS_ECDHE_PSK_AES_256_CBC_SHA { 0xC0, 0x36 }
+#define GNUTLS_ECDHE_PSK_AES_128_CBC_SHA256 { 0xC0, 0x37 }
+#define GNUTLS_ECDHE_PSK_AES_256_CBC_SHA384 { 0xC0, 0x38 }
+#define GNUTLS_ECDHE_PSK_NULL_SHA256 { 0xC0, 0x3A }
+#define GNUTLS_ECDHE_PSK_NULL_SHA384 { 0xC0, 0x3B }
+
#define CIPHER_SUITES_COUNT (sizeof(cs_algorithms)/sizeof(gnutls_cipher_suite_entry)-1)
/* FIXME: what we don't handle here is TLS 1.2 requirement
@@ -581,6 +590,35 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_ECDHE_RSA,
GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
GNUTLS_VERSION_MAX, 1),
+ /* ECC - PSK */
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_PSK_3DES_EDE_CBC_SHA,
+ GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_ECDHE_PSK,
+ GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+ GNUTLS_VERSION_MAX, 1),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_PSK_AES_128_CBC_SHA,
+ GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ECDHE_PSK,
+ GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+ GNUTLS_VERSION_MAX, 1),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_PSK_AES_256_CBC_SHA,
+ GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ECDHE_PSK,
+ GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+ GNUTLS_VERSION_MAX, 1),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_PSK_AES_128_CBC_SHA256,
+ GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ECDHE_PSK,
+ GNUTLS_MAC_SHA256, GNUTLS_TLS1_0,
+ GNUTLS_VERSION_MAX, 1),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_PSK_AES_256_CBC_SHA384,
+ GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ECDHE_PSK,
+ GNUTLS_MAC_SHA384, GNUTLS_TLS1_0,
+ GNUTLS_VERSION_MAX, 1),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_PSK_NULL_SHA256,
+ GNUTLS_CIPHER_NULL, GNUTLS_KX_ECDHE_PSK,
+ GNUTLS_MAC_SHA256, GNUTLS_TLS1_0,
+ GNUTLS_VERSION_MAX, 1),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_PSK_NULL_SHA384,
+ GNUTLS_CIPHER_NULL, GNUTLS_KX_ECDHE_PSK,
+ GNUTLS_MAC_SHA384, GNUTLS_TLS1_0,
+ GNUTLS_VERSION_MAX, 1),
{0, {{0, 0}}, 0, 0, 0, 0, 0, 0}
};
diff --git a/lib/algorithms/kx.c b/lib/algorithms/kx.c
index 36a5647190..f3e2196afa 100644
--- a/lib/algorithms/kx.c
+++ b/lib/algorithms/kx.c
@@ -32,6 +32,7 @@ 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 ecdhe_psk_auth_struct;
extern mod_auth_st ecdhe_ecdsa_auth_struct;
extern mod_auth_st dhe_dss_auth_struct;
extern mod_auth_st anon_auth_struct;
@@ -66,6 +67,7 @@ static const gnutls_cred_map cred_mappings[] = {
{GNUTLS_KX_DHE_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
{GNUTLS_KX_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_PSK},
{GNUTLS_KX_DHE_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_PSK},
+ {GNUTLS_KX_ECDHE_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_PSK},
{GNUTLS_KX_SRP, GNUTLS_CRD_SRP, GNUTLS_CRD_SRP},
{GNUTLS_KX_SRP_RSA, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE},
{GNUTLS_KX_SRP_DSS, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE},
@@ -98,8 +100,8 @@ 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},
- {"ECDHE-ECDSA", GNUTLS_KX_ECDHE_ECDSA, &ecdhe_ecdsa_auth_struct, 1, 0},
+ {"ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, &ecdhe_rsa_auth_struct, 0, 0},
+ {"ECDHE-ECDSA", GNUTLS_KX_ECDHE_ECDSA, &ecdhe_ecdsa_auth_struct, 0, 0},
{"DHE-DSS", GNUTLS_KX_DHE_DSS, &dhe_dss_auth_struct, 1, 0},
#ifdef ENABLE_SRP
@@ -111,6 +113,7 @@ static const gnutls_kx_algo_entry _gnutls_kx_algorithms[] = {
{"PSK", GNUTLS_KX_PSK, &psk_auth_struct, 0, 0},
{"DHE-PSK", GNUTLS_KX_DHE_PSK, &dhe_psk_auth_struct,
1 /* needs DHE params */ , 0},
+ {"ECDHE-PSK", GNUTLS_KX_ECDHE_PSK, &ecdhe_psk_auth_struct, 0 , 0},
#endif
{0, 0, 0, 0, 0}
};
diff --git a/lib/auth/anon.c b/lib/auth/anon.c
index ef3b910a8d..691b5d6d1a 100644
--- a/lib/auth/anon.c
+++ b/lib/auth/anon.c
@@ -101,7 +101,7 @@ gen_anon_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
_gnutls_dh_set_group (session, g, p);
- ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 0);
+ ret = _gnutls_dh_common_print_server_kx (session, g, p, data);
if (ret < 0)
{
gnutls_assert ();
@@ -141,7 +141,7 @@ proc_anon_client_kx (gnutls_session_t session, opaque * data,
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, NULL);
return ret;
@@ -163,7 +163,7 @@ proc_anon_server_kx (gnutls_session_t session, opaque * data,
return ret;
}
- ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size, 0);
+ ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size);
if (ret < 0)
{
gnutls_assert ();
diff --git a/lib/auth/anon_ecdh.c b/lib/auth/anon_ecdh.c
index e87f80c88f..8506a55ae7 100644
--- a/lib/auth/anon_ecdh.c
+++ b/lib/auth/anon_ecdh.c
@@ -109,7 +109,8 @@ proc_anon_ecdh_client_kx (gnutls_session_t session, opaque * data,
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- return _gnutls_proc_ecdh_common_client_kx (session, data, _data_size, _gnutls_session_ecc_curve_get(session));
+ return _gnutls_proc_ecdh_common_client_kx (session, data, _data_size,
+ _gnutls_session_ecc_curve_get(session), NULL);
}
int
diff --git a/lib/auth/dh_common.c b/lib/auth/dh_common.c
index 5b8aab3613..a0fb9c42bd 100644
--- a/lib/auth/dh_common.c
+++ b/lib/auth/dh_common.c
@@ -55,7 +55,8 @@ _gnutls_free_dh_info (dh_info_st * dh)
int
_gnutls_proc_dh_common_client_kx (gnutls_session_t session,
opaque * data, size_t _data_size,
- bigint_t g, bigint_t p)
+ bigint_t g, bigint_t p,
+ gnutls_datum_t* psk_key)
{
uint16_t n_Y;
size_t _n_Y;
@@ -89,9 +90,7 @@ _gnutls_proc_dh_common_client_kx (gnutls_session_t session,
_gnutls_mpi_release (&session->key->dh_secret);
- if (_gnutls_cipher_suite_get_kx_algo
- (&session->security_parameters.current_cipher_suite)
- != GNUTLS_KX_DHE_PSK)
+ if (psk_key == NULL)
{
ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
}
@@ -105,7 +104,7 @@ _gnutls_proc_dh_common_client_kx (gnutls_session_t session,
return ret;
}
- ret = _gnutls_set_psk_session_key (session, NULL, &tmp_dh_key);
+ ret = _gnutls_set_psk_session_key (session, psk_key, &tmp_dh_key);
_gnutls_free_datum (&tmp_dh_key);
}
@@ -205,26 +204,18 @@ error:
/* Returns the bytes parsed */
int
_gnutls_proc_dh_common_server_kx (gnutls_session_t session,
- opaque * data, size_t _data_size, int psk)
+ opaque * data, size_t _data_size)
{
uint16_t n_Y, n_g, n_p;
size_t _n_Y, _n_g, _n_p;
uint8_t *data_p;
uint8_t *data_g;
uint8_t *data_Y;
- int i, bits, psk_size, ret;
+ int i, bits, ret;
ssize_t data_size = _data_size;
i = 0;
- if (psk != 0)
- {
- DECR_LEN (data_size, 2);
- psk_size = _gnutls_read_uint16 (&data[i]);
- DECR_LEN (data_size, psk_size);
- i += 2 + psk_size;
- }
-
DECR_LEN (data_size, 2);
n_p = _gnutls_read_uint16 (&data[i]);
i += 2;
@@ -290,8 +281,6 @@ _gnutls_proc_dh_common_server_kx (gnutls_session_t session,
_gnutls_dh_set_peer_public (session, session->key->client_Y);
ret = n_Y + n_p + n_g + 6;
- if (psk != 0)
- ret += 2;
return ret;
}
@@ -300,8 +289,7 @@ _gnutls_proc_dh_common_server_kx (gnutls_session_t session,
* be inserted */
int
_gnutls_dh_common_print_server_kx (gnutls_session_t session,
- bigint_t g, bigint_t p, gnutls_buffer_st* data,
- int psk)
+ bigint_t g, bigint_t p, gnutls_buffer_st* data)
{
bigint_t x, X;
int ret;
@@ -316,16 +304,6 @@ _gnutls_dh_common_print_server_kx (gnutls_session_t session,
session->key->dh_secret = x;
_gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x));
- if (psk != 0)
- {
- ret = _gnutls_buffer_append_prefix(data, 16, 0);
- if (ret < 0)
- {
- ret = gnutls_assert_val(ret);
- goto cleanup;
- }
- }
-
ret = _gnutls_buffer_append_mpi(data, 16, p, 0);
if (ret < 0)
{
diff --git a/lib/auth/dh_common.h b/lib/auth/dh_common.h
index 9c528f1081..2ad459b524 100644
--- a/lib/auth/dh_common.h
+++ b/lib/auth/dh_common.h
@@ -42,10 +42,11 @@ int _gnutls_gen_dh_common_client_kx_int (gnutls_session_t, gnutls_buffer_st*, gn
int _gnutls_gen_dh_common_client_kx (gnutls_session_t, gnutls_buffer_st*);
int _gnutls_proc_dh_common_client_kx (gnutls_session_t session,
opaque * data, size_t _data_size,
- bigint_t p, bigint_t g);
+ bigint_t p, bigint_t g,
+ gnutls_datum_t* psk_key);
int _gnutls_dh_common_print_server_kx (gnutls_session_t, bigint_t g,
- bigint_t p, gnutls_buffer_st* data, int psk);
+ bigint_t p, gnutls_buffer_st* data);
int _gnutls_proc_dh_common_server_kx (gnutls_session_t session, opaque * data,
- size_t _data_size, int psk);
+ size_t _data_size);
#endif
diff --git a/lib/auth/dhe.c b/lib/auth/dhe.c
index c43c9dfe97..422ce59f9f 100644
--- a/lib/auth/dhe.c
+++ b/lib/auth/dhe.c
@@ -170,7 +170,7 @@ gen_dhe_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
_gnutls_dh_set_group (session, g, p);
- ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 0);
+ ret = _gnutls_dh_common_print_server_kx (session, g, p, data);
}
else
{
@@ -273,7 +273,7 @@ proc_dhe_server_kx (gnutls_session_t session, opaque * data,
}
if (!_gnutls_session_is_ecc (session))
- ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size, 0);
+ ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size);
else
ret = _gnutls_proc_ecdh_common_server_kx (session, data, _data_size);
@@ -367,10 +367,11 @@ proc_dhe_client_kx (gnutls_session_t session, opaque * data,
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, NULL);
}
else
- ret = _gnutls_proc_ecdh_common_client_kx (session, data, _data_size, _gnutls_session_ecc_curve_get(session));
+ ret = _gnutls_proc_ecdh_common_client_kx (session, data, _data_size,
+ _gnutls_session_ecc_curve_get(session), NULL);
return ret;
diff --git a/lib/auth/dhe_psk.c b/lib/auth/dhe_psk.c
index c73631f3fc..d39b6dcdc7 100644
--- a/lib/auth/dhe_psk.c
+++ b/lib/auth/dhe_psk.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2005, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -30,6 +30,9 @@
#ifdef ENABLE_PSK
+/* Contains PSK code for DHE and ECDHE
+ */
+
#include "gnutls_auth.h"
#include "gnutls_errors.h"
#include "gnutls_dh.h"
@@ -38,12 +41,17 @@
#include "gnutls_mpi.h"
#include <gnutls_state.h>
#include <auth/dh_common.h>
+#include <auth/ecdh_common.h>
#include <gnutls_datum.h>
+#include <auth/psk_passwd.h>
static int gen_psk_server_kx (gnutls_session_t, gnutls_buffer_st*);
static int gen_psk_client_kx (gnutls_session_t, gnutls_buffer_st*);
static int proc_psk_client_kx (gnutls_session_t, opaque *, size_t);
static int proc_psk_server_kx (gnutls_session_t, opaque *, size_t);
+static int gen_ecdhe_psk_server_kx (gnutls_session_t session, gnutls_buffer_st* data);
+static int proc_ecdhe_psk_client_kx (gnutls_session_t session, opaque * data,
+ size_t _data_size);
const mod_auth_st dhe_psk_auth_struct = {
"DHE PSK",
@@ -62,6 +70,23 @@ const mod_auth_st dhe_psk_auth_struct = {
NULL
};
+const mod_auth_st ecdhe_psk_auth_struct = {
+ "ECDHE PSK",
+ NULL,
+ NULL,
+ gen_ecdhe_psk_server_kx,
+ gen_psk_client_kx,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL, /* certificate */
+ proc_psk_server_kx,
+ proc_ecdhe_psk_client_kx,
+ NULL,
+ NULL
+};
+
static int
gen_psk_client_kx (gnutls_session_t session, gnutls_buffer_st* data)
{
@@ -87,7 +112,11 @@ gen_psk_client_kx (gnutls_session_t session, gnutls_buffer_st* data)
}
/* The PSK key is set in there */
- ret = _gnutls_gen_dh_common_client_kx_int (session, data, &key);
+ if (!_gnutls_session_is_ecc (session))
+ ret = _gnutls_gen_dh_common_client_kx_int (session, data, &key);
+ else
+ ret = _gnutls_gen_ecdh_common_client_kx_int (session, data, &key);
+
if (ret < 0)
{
gnutls_assert ();
@@ -146,12 +175,39 @@ gen_psk_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
_gnutls_dh_set_group (session, g, p);
- ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 1);
+ ret = _gnutls_buffer_append_prefix(data, 16, 0);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_dh_common_print_server_kx (session, g, p, data);
if (ret < 0)
+ gnutls_assert ();
+
+ return ret;
+}
+
+static int
+gen_ecdhe_psk_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
+{
+ int ret;
+
+ if ((ret =
+ _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
+ sizeof (psk_auth_info_st), 1)) < 0)
{
gnutls_assert ();
+ return ret;
}
+ ret = _gnutls_buffer_append_prefix(data, 16, 0);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_ecdh_common_print_server_kx (session, data,
+ _gnutls_session_ecc_curve_get(session));
+ if (ret < 0)
+ gnutls_assert ();
+
return ret;
}
@@ -164,6 +220,7 @@ proc_psk_client_kx (gnutls_session_t session, opaque * data,
bigint_t p, g;
gnutls_dh_params_t dh_params;
const bigint_t *mpis;
+ gnutls_datum_t psk_key;
gnutls_psk_server_credentials_t cred;
psk_auth_info_t info;
gnutls_datum_t username;
@@ -221,9 +278,74 @@ proc_psk_client_kx (gnutls_session_t session, opaque * data,
/* Adjust the data */
data += username.size + 2;
- ret = _gnutls_proc_dh_common_client_kx (session, data, data_size, g, p);
+ ret = _gnutls_psk_pwd_find_entry(session, info->username, &psk_key);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
- return ret;
+ return _gnutls_proc_dh_common_client_kx (session, data, data_size,
+ g, p, &psk_key);
+
+}
+
+static int
+proc_ecdhe_psk_client_kx (gnutls_session_t session, opaque * data,
+ size_t _data_size)
+{
+ int ret;
+ gnutls_psk_server_credentials_t cred;
+ gnutls_datum_t psk_key;
+ psk_auth_info_t info;
+ gnutls_datum_t username;
+ ssize_t data_size = _data_size;
+
+ cred = (gnutls_psk_server_credentials_t)
+ _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);
+
+ if (cred == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ if ((ret =
+ _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
+ sizeof (psk_auth_info_st), 1)) < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ DECR_LEN (data_size, 2);
+ username.size = _gnutls_read_uint16 (&data[0]);
+
+ DECR_LEN (data_size, username.size);
+
+ username.data = &data[2];
+
+ /* copy the username to the auth info structures
+ */
+ info = _gnutls_get_auth_info (session);
+
+ if (username.size > MAX_USERNAME_SIZE)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_ILLEGAL_SRP_USERNAME;
+ }
+
+ memcpy (info->username, username.data, username.size);
+ info->username[username.size] = 0;
+
+ /* Adjust the data */
+ data += username.size + 2;
+
+ /* should never fail. It will always return a key even if it is
+ * a random one */
+ ret = _gnutls_psk_pwd_find_entry(session, info->username, &psk_key);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return _gnutls_proc_ecdh_common_client_kx(session, data, data_size,
+ _gnutls_session_ecc_curve_get(session), &psk_key);
}
@@ -232,7 +354,8 @@ proc_psk_server_kx (gnutls_session_t session, opaque * data,
size_t _data_size)
{
- int ret;
+ int ret, psk_size;
+ ssize_t data_size = _data_size;
/* set auth_info */
if ((ret =
@@ -243,7 +366,15 @@ proc_psk_server_kx (gnutls_session_t session, opaque * data,
return ret;
}
- ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size, 1);
+ DECR_LEN (data_size, 2);
+ psk_size = _gnutls_read_uint16 (data);
+ DECR_LEN (data_size, psk_size);
+ data += 2 + psk_size;
+
+ if (!_gnutls_session_is_ecc (session))
+ ret = _gnutls_proc_dh_common_server_kx (session, data, data_size);
+ else
+ ret = _gnutls_proc_ecdh_common_server_kx (session, data, data_size);
if (ret < 0)
{
gnutls_assert ();
diff --git a/lib/auth/ecdh_common.c b/lib/auth/ecdh_common.c
index f04526a5ec..cebd4ffb04 100644
--- a/lib/auth/ecdh_common.c
+++ b/lib/auth/ecdh_common.c
@@ -43,7 +43,7 @@
#include <auth/psk.h>
#include <gnutls_pk.h>
-static int calc_ecdh_key( gnutls_session_t session)
+static int calc_ecdh_key( gnutls_session_t session, gnutls_datum_t * psk_key)
{
gnutls_pk_params_st pub;
int ret;
@@ -61,21 +61,43 @@ int ret;
_gnutls_mpi_set_ui(pub.params[7], 1);
- ret = _gnutls_pk_derive(GNUTLS_PK_ECC, &session->key->key, &session->key->ecdh_params, &pub);
-
- _gnutls_mpi_release(&pub.params[7]);
+ if (psk_key == NULL)
+ ret = _gnutls_pk_derive(GNUTLS_PK_ECC, &session->key->key, &session->key->ecdh_params, &pub);
+ else
+ {
+ gnutls_datum_t tmp_dh_key;
+
+ ret = _gnutls_pk_derive(GNUTLS_PK_ECC, &tmp_dh_key, &session->key->ecdh_params, &pub);
+ if (ret < 0)
+ {
+ ret = gnutls_assert_val(ret);
+ goto cleanup;
+ }
+
+ ret = _gnutls_set_psk_session_key (session, psk_key, &tmp_dh_key);
+ _gnutls_free_datum (&tmp_dh_key);
+ }
if (ret < 0)
- return gnutls_assert_val(ret);
+ {
+ ret = gnutls_assert_val(ret);
+ goto cleanup;
+ }
- return 0;
+ ret = 0;
+
+cleanup:
+ _gnutls_mpi_release(&pub.params[7]);
+ return ret;
+
}
int
_gnutls_proc_ecdh_common_client_kx (gnutls_session_t session,
- opaque * data, size_t _data_size,
- gnutls_ecc_curve_t curve)
+ opaque * data, size_t _data_size,
+ gnutls_ecc_curve_t curve,
+ gnutls_datum_t *psk_key)
{
ssize_t data_size = _data_size;
int ret, i = 0;
@@ -94,7 +116,7 @@ _gnutls_proc_ecdh_common_client_kx (gnutls_session_t session,
return gnutls_assert_val(ret);
/* generate pre-shared key */
- ret = calc_ecdh_key(session);
+ ret = calc_ecdh_key(session, psk_key);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -102,7 +124,16 @@ _gnutls_proc_ecdh_common_client_kx (gnutls_session_t session,
}
int
-_gnutls_gen_ecdh_common_client_kx (gnutls_session_t session, gnutls_buffer_st* data)
+_gnutls_gen_ecdh_common_client_kx (gnutls_session_t session,
+ gnutls_buffer_st* data)
+{
+ return _gnutls_gen_ecdh_common_client_kx_int(session, data, NULL);
+}
+
+int
+_gnutls_gen_ecdh_common_client_kx_int (gnutls_session_t session,
+ gnutls_buffer_st* data,
+ gnutls_datum_t * psk_key)
{
int ret;
gnutls_datum_t out;
@@ -124,9 +155,9 @@ _gnutls_gen_ecdh_common_client_kx (gnutls_session_t session, gnutls_buffer_st* d
if (ret < 0)
return gnutls_assert_val(ret);
-
+
/* generate pre-shared key */
- ret = calc_ecdh_key(session);
+ ret = calc_ecdh_key(session, psk_key);
if (ret < 0)
return gnutls_assert_val(ret);
diff --git a/lib/auth/ecdh_common.h b/lib/auth/ecdh_common.h
index 9b7a92b653..a945fedfd7 100644
--- a/lib/auth/ecdh_common.h
+++ b/lib/auth/ecdh_common.h
@@ -27,10 +27,21 @@
#include <gnutls_auth.h>
-int _gnutls_gen_ecdh_common_client_kx (gnutls_session_t, gnutls_buffer_st*);
-int _gnutls_proc_ecdh_common_client_kx (gnutls_session_t session,
- opaque * data, size_t _data_size,
- gnutls_ecc_curve_t curve);
+int
+_gnutls_gen_ecdh_common_client_kx (gnutls_session_t session,
+ gnutls_buffer_st* data);
+
+int
+_gnutls_gen_ecdh_common_client_kx_int (gnutls_session_t session,
+ gnutls_buffer_st* data,
+ gnutls_datum_t * psk_key);
+
+int
+_gnutls_proc_ecdh_common_client_kx (gnutls_session_t session,
+ opaque * data, size_t _data_size,
+ gnutls_ecc_curve_t curve,
+ gnutls_datum_t *psk_key);
+
int _gnutls_ecdh_common_print_server_kx (gnutls_session_t, gnutls_buffer_st* data,
gnutls_ecc_curve_t curve);
int _gnutls_proc_ecdh_common_server_kx (gnutls_session_t session, opaque * data,
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
index 3f15f08a45..a8be1854d4 100644
--- a/lib/gnutls_state.c
+++ b/lib/gnutls_state.c
@@ -1194,7 +1194,8 @@ _gnutls_session_is_ecc (gnutls_session_t session)
kx =
_gnutls_cipher_suite_get_kx_algo (&session->
security_parameters.current_cipher_suite);
- if (kx == GNUTLS_KX_ECDHE_RSA || kx == GNUTLS_KX_ECDHE_ECDSA || kx == GNUTLS_KX_ANON_ECDH)
+ if (kx == GNUTLS_KX_ECDHE_RSA || kx == GNUTLS_KX_ECDHE_ECDSA ||
+ kx == GNUTLS_KX_ANON_ECDH || kx == GNUTLS_KX_ECDHE_PSK)
return 1;
return 0;
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index a44205bb05..9375f6acb5 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -138,6 +138,7 @@ extern "C"
* @GNUTLS_KX_SRP_DSS: SRP-DSS key-exchange algorithm.
* @GNUTLS_KX_PSK: PSK key-exchange algorithm.
* @GNUTLS_KX_DHE_PSK: DHE-PSK key-exchange algorithm.
+ * @GNUTLS_KX_ECDHE_PSK: ECDHE-PSK key-exchange algorithm.
*
* Enumeration of different key exchange algorithms.
*/
@@ -157,6 +158,7 @@ extern "C"
GNUTLS_KX_ANON_ECDH = 11,
GNUTLS_KX_ECDHE_RSA = 12,
GNUTLS_KX_ECDHE_ECDSA = 13,
+ GNUTLS_KX_ECDHE_PSK = 14,
} gnutls_kx_algorithm_t;
/**