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 | |
parent | 5281029f727f18186ee15f0e1021eead09d4f2c5 (diff) | |
download | gnutls-911d1b16482cbe53c0c47db7c08c3c2749731c43.tar.gz |
Added ECDHE-PSK ciphersuites for TLS (RFC 5489).
Diffstat (limited to 'lib/auth')
-rw-r--r-- | lib/auth/anon.c | 6 | ||||
-rw-r--r-- | lib/auth/anon_ecdh.c | 3 | ||||
-rw-r--r-- | lib/auth/dh_common.c | 36 | ||||
-rw-r--r-- | lib/auth/dh_common.h | 7 | ||||
-rw-r--r-- | lib/auth/dhe.c | 9 | ||||
-rw-r--r-- | lib/auth/dhe_psk.c | 145 | ||||
-rw-r--r-- | lib/auth/ecdh_common.c | 55 | ||||
-rw-r--r-- | lib/auth/ecdh_common.h | 19 |
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, |