diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-05-27 23:53:38 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-05-27 23:55:29 +0200 |
commit | 911d1b16482cbe53c0c47db7c08c3c2749731c43 (patch) | |
tree | 11393cf32809c77389c19166d6030aa972288d72 /lib/auth/dhe_psk.c | |
parent | 5281029f727f18186ee15f0e1021eead09d4f2c5 (diff) | |
download | gnutls-911d1b16482cbe53c0c47db7c08c3c2749731c43.tar.gz |
Added ECDHE-PSK ciphersuites for TLS (RFC 5489).
Diffstat (limited to 'lib/auth/dhe_psk.c')
-rw-r--r-- | lib/auth/dhe_psk.c | 145 |
1 files changed, 138 insertions, 7 deletions
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 (); |