summaryrefslogtreecommitdiff
path: root/lib/auth
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2011-05-27 23:53:38 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2011-05-27 23:55:29 +0200
commit911d1b16482cbe53c0c47db7c08c3c2749731c43 (patch)
tree11393cf32809c77389c19166d6030aa972288d72 /lib/auth
parent5281029f727f18186ee15f0e1021eead09d4f2c5 (diff)
downloadgnutls-911d1b16482cbe53c0c47db7c08c3c2749731c43.tar.gz
Added ECDHE-PSK ciphersuites for TLS (RFC 5489).
Diffstat (limited to 'lib/auth')
-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
8 files changed, 217 insertions, 63 deletions
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,