diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-03-11 19:46:59 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-03-11 19:46:59 +0000 |
commit | d3e5848bfde0598b806607302d35079a19bf0e42 (patch) | |
tree | 47456fb4ae8a83c1b7f7f3c64c6fb4ebbebbde89 | |
parent | ccef91a9aff47be28e14139bd71f559f9b602a64 (diff) | |
download | gnutls-d3e5848bfde0598b806607302d35079a19bf0e42.tar.gz |
Key exchange (authentication) algorithms were reorganized, and now are
more modular. Most changes however are not much tested and only anonymous
authentication is currently used.
-rw-r--r-- | lib/Makefile.am | 6 | ||||
-rw-r--r-- | lib/gnutls.c | 25 | ||||
-rw-r--r-- | lib/gnutls_algorithms.c | 29 | ||||
-rw-r--r-- | lib/gnutls_algorithms.h | 3 | ||||
-rw-r--r-- | lib/gnutls_anon.c | 261 | ||||
-rw-r--r-- | lib/gnutls_anon.h | 2 | ||||
-rw-r--r-- | lib/gnutls_auth.h | 15 | ||||
-rw-r--r-- | lib/gnutls_dhe_dss.c | 266 | ||||
-rw-r--r-- | lib/gnutls_dhe_dss.h | 1 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 28 | ||||
-rw-r--r-- | lib/gnutls_int.h | 20 | ||||
-rw-r--r-- | lib/gnutls_kx.c | 376 |
12 files changed, 704 insertions, 328 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 65b27c871f..1ce9993981 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -3,11 +3,13 @@ EXTRA_DIST = debug.h gnutls_compress.h defines.h gnutls_plaintext.h \ gnutls_cipher.h gnutls_buffers.h gnutls_errors.h gnutls_int.h \ gnutls_handshake.h gnutls_num.h gnutls_algorithms.h gnutls_dh.h \ gnutls_kx.h gnutls_hash_int.h gnutls_cipher_int.h gnutls_db.h \ - gnutls_compress_int.h gnutls_session.h gnutls_priority.h + gnutls_compress_int.h gnutls_session.h gnutls_priority.h gnutls_auth.h \ + gnutls_anon.h gnutls_dhe_dss.h lib_LTLIBRARIES = libgnutls.la libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c \ gnutls_cipher.c gnutls_buffers.c gnutls_handshake.c gnutls_num.c \ gnutls_errors.c gnutls_algorithms.c gnutls_dh.c gnutls_kx.c \ gnutls_priority.c gnutls_hash_int.c gnutls_cipher_int.c \ - gnutls_compress_int.c gnutls_session.c gnutls_db.c cert_b64.c + gnutls_compress_int.c gnutls_session.c gnutls_db.c cert_b64.c \ + gnutls_anon.c gnutls_dhe_dss.c libgnutls_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) diff --git a/lib/gnutls.c b/lib/gnutls.c index 3d798d4385..c6b5e4af7d 100644 --- a/lib/gnutls.c +++ b/lib/gnutls.c @@ -100,11 +100,13 @@ int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end) gnutls_set_current_version ( (*state), GNUTLS_TLS1); /* default */ - (*state)->gnutls_internals.KEY = NULL; - (*state)->gnutls_internals.client_Y = NULL; - (*state)->gnutls_internals.client_p = NULL; - (*state)->gnutls_internals.client_g = NULL; - (*state)->gnutls_internals.dh_secret = NULL; + (*state)->gnutls_key = gnutls_malloc(sizeof(GNUTLS_KEY_A)); + + (*state)->gnutls_key->KEY = NULL; + (*state)->gnutls_key->client_Y = NULL; + (*state)->gnutls_key->client_p = NULL; + (*state)->gnutls_key->client_g = NULL; + (*state)->gnutls_key->dh_secret = NULL; (*state)->gnutls_internals.certificate_requested = 0; (*state)->gnutls_internals.certificate_verify_needed = 0; @@ -170,11 +172,12 @@ int gnutls_deinit(GNUTLS_STATE * state) secure_free((*state)->cipher_specs.server_write_key); secure_free((*state)->cipher_specs.client_write_key); - mpi_release((*state)->gnutls_internals.KEY); - mpi_release((*state)->gnutls_internals.client_Y); - mpi_release((*state)->gnutls_internals.client_p); - mpi_release((*state)->gnutls_internals.client_g); - mpi_release((*state)->gnutls_internals.dh_secret); + mpi_release((*state)->gnutls_key->KEY); + mpi_release((*state)->gnutls_key->client_Y); + mpi_release((*state)->gnutls_key->client_p); + mpi_release((*state)->gnutls_key->client_g); + mpi_release((*state)->gnutls_key->dh_secret); + gnutls_free((*state)->gnutls_key); /* free priorities */ if ((*state)->gnutls_internals.MACAlgorithmPriority.algorithm_priority!=NULL) @@ -605,7 +608,7 @@ ssize_t gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char *data if (_gnutls_version_is_supported(state, version) == 0) { #ifdef DEBUG - fprintf(stderr, "INVALID VERSION PACKET: %d.%d\n", version.major, version.minor); + fprintf(stderr, "INVALID VERSION PACKET: %d.%d\n", headers[1], headers[2]); #endif _gnutls_send_alert(cd, state, GNUTLS_FATAL, GNUTLS_PROTOCOL_VERSION); state->gnutls_internals.resumable = RESUME_FALSE; diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index 3ec1cbcff1..8bed99e1b8 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -23,6 +23,10 @@ #include "gnutls_algorithms.h" #include "gnutls_errors.h" +/* include all the kx handler's definitions */ +#include "gnutls_anon.h" +#include "gnutls_dhe_dss.h" + /* TLS Versions */ typedef struct { @@ -129,8 +133,8 @@ static gnutls_compression_entry compression_algorithms[] = { /* Key Exchange Section */ -#define GNUTLS_KX_ALGO_ENTRY(name, server_cert, server_kx, client_cert, RSA_premaster, DH_public_value) \ - { #name, name, server_cert, server_kx, client_cert, RSA_premaster, DH_public_value } +#define GNUTLS_KX_ALGO_ENTRY(name, server_cert, server_kx, client_cert, RSA_premaster, DH_public_value, auth_struct) \ + { #name, name, server_cert, server_kx, client_cert, RSA_premaster, DH_public_value, auth_struct } struct gnutls_kx_algo_entry { char *name; @@ -140,16 +144,17 @@ struct gnutls_kx_algo_entry { int client_cert; int RSA_premaster; int DH_public_value; + MOD_AUTH_STRUCT *auth_struct; }; typedef struct gnutls_kx_algo_entry gnutls_kx_algo_entry; static gnutls_kx_algo_entry kx_algorithms[] = { - GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_ANON_DH, 0, 1, 0, 0, 1), - GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_RSA, 1, 0, 1, 1, 0), - GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DHE_DSS, 1, 1, 1, 0, 0), - GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DHE_RSA, 1, 1, 1, 0, 0), - GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DH_DSS, 1, 0, 1, 0, 0), - GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DH_RSA, 1, 0, 1, 0, 0), + GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_ANON_DH, 0, 1, 0, 0, 1, &anon_auth_struct), + GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_RSA, 1, 0, 1, 1, 0, NULL), + GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DHE_DSS, 1, 1, 1, 0, 0, &dhe_dss_auth_struct), + GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DHE_RSA, 1, 1, 1, 0, 0, NULL), + GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DH_DSS, 1, 0, 1, 0, 0, NULL), + GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DH_RSA, 1, 0, 1, 0, 0, NULL), {0} }; @@ -530,6 +535,14 @@ int _gnutls_kx_server_certificate(KXAlgorithm algorithm) } +MOD_AUTH_STRUCT * _gnutls_kx_auth_struct(KXAlgorithm algorithm) +{ + MOD_AUTH_STRUCT * ret = NULL; + GNUTLS_KX_ALG_LOOP(ret = p->auth_struct); + return ret; + +} + inline int _gnutls_kx_priority(GNUTLS_STATE state, KXAlgorithm algorithm) { int i; diff --git a/lib/gnutls_algorithms.h b/lib/gnutls_algorithms.h index c019a31aae..0e3197bbf0 100644 --- a/lib/gnutls_algorithms.h +++ b/lib/gnutls_algorithms.h @@ -18,6 +18,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +#include "gnutls_auth.h" + /* functions for version */ int _gnutls_version_is_supported(GNUTLS_STATE state, const GNUTLS_Version version); int _gnutls_version_get_major( GNUTLS_Version ver); @@ -61,6 +63,7 @@ int _gnutls_kx_server_key_exchange(KXAlgorithm algorithm); int _gnutls_kx_client_certificate(KXAlgorithm algorithm); int _gnutls_kx_RSA_premaster(KXAlgorithm algorithm); int _gnutls_kx_DH_public_value(KXAlgorithm algorithm); +MOD_AUTH_STRUCT * _gnutls_kx_auth_struct(KXAlgorithm algorithm); char *_gnutls_kx_get_name(KXAlgorithm algorithm); int _gnutls_kx_is_ok(KXAlgorithm algorithm); int _gnutls_kx_count(); diff --git a/lib/gnutls_anon.c b/lib/gnutls_anon.c new file mode 100644 index 0000000000..73b69426e4 --- /dev/null +++ b/lib/gnutls_anon.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2000 Nikos Mavroyanopoulos + * + * This file is part of GNUTLS. + * + * GNUTLS is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNUTLS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <defines.h> +#include "gnutls_int.h" +#include "gnutls_errors.h" +#include "gnutls_dh.h" + +int gen_anon_server_kx( GNUTLS_KEY, opaque**); +int gen_anon_client_kx( GNUTLS_KEY, opaque**); +int proc_anon_server_kx( GNUTLS_KEY, opaque*, int); +int proc_anon_client_kx( GNUTLS_KEY, opaque*, int); + +int gen_anon_client_cert_vrfy( GNUTLS_KEY, opaque**); +int proc_anon_client_cert_vrfy( GNUTLS_KEY, opaque*, int); + +int gen_anon_server_cert_vrfy( GNUTLS_KEY, opaque**); +int proc_anon_server_cert_vrfy( GNUTLS_KEY, opaque*, int); + +MOD_AUTH_STRUCT anon_auth_struct = { + "ANON", + gen_anon_server_kx, + gen_anon_client_kx, + gen_anon_client_cert_vrfy, + gen_anon_server_cert_vrfy, + proc_anon_server_kx, + proc_anon_client_kx, + proc_anon_client_cert_vrfy, + proc_anon_server_cert_vrfy +}; + +int gen_anon_server_kx( GNUTLS_KEY key, opaque** data) { + GNUTLS_MPI x, X, g, p; + size_t n_X, n_g, n_p; + uint16 _n_X, _n_g, _n_p; + uint8 *data_p; + uint8 *data_g; + uint8 *data_X; + int ret = 0; + + X = gnutls_calc_dh_secret(&x); + key->dh_secret = x; + g = gnutls_get_dh_params(&p); + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_g, g); + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_p, p); + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_X, X); + (*data) = gnutls_malloc(n_g + n_p + n_X + 6); + data_p = &(*data)[0]; + gcry_mpi_print(GCRYMPI_FMT_USG, &data_p[2], &n_p, p); + gnutls_mpi_release(p); + _n_p = n_p; +#ifndef WORDS_BIGENDIAN + _n_p = byteswap16(_n_p); + memmove(data_p, &_n_p, 2); +#else + memmove(data_p, &_n_p, 2); +#endif + data_g = &data_p[2 + n_p]; + gcry_mpi_print(GCRYMPI_FMT_USG, &data_g[2], &n_g, g); + gnutls_mpi_release(g); + _n_g = n_g; +#ifndef WORDS_BIGENDIAN + _n_g = byteswap16(_n_g); + memmove(data_g, &_n_g, 2); +#else + memmove(data_g, &_n_g, 2); +#endif + data_X = &data_g[2 + n_g]; + gcry_mpi_print(GCRYMPI_FMT_USG, &data_X[2], &n_X, X); + gnutls_mpi_release(X); + _n_X = n_X; +#ifndef WORDS_BIGENDIAN + _n_X = byteswap16(_n_X); + memmove(data_X, &_n_X, 2); +#else + memmove(data_X, &_n_X, 2); +#endif + ret = n_p+n_g+n_X+6; + + return ret; +} + +int gen_anon_client_kx( GNUTLS_KEY key, opaque** data) { +GNUTLS_MPI x, X; +size_t n_X; +uint16 _n_X; +int data_size; + + X = _gnutls_calc_dh_secret(&x, key->client_g, + key->client_p); + + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_X, X); + (*data) = gnutls_malloc(n_X + 2); + + gcry_mpi_print(GCRYMPI_FMT_USG, &(*data)[2], &n_X, X); + (*data)[0] = 1; /* extern - explicit since we do not have + certificate */ + gnutls_mpi_release(X); + _n_X = n_X; +#ifndef WORDS_BIGENDIAN + _n_X = byteswap16(_n_X); + memmove(&(*data)[0], &_n_X, 2); +#else + memmove(&(*data)[0], &_n_X, 2); +#endif + data_size = _n_X+2; + + /* calculate the key after calculating the message */ + key->KEY = _gnutls_calc_dh_key(key->client_Y, x, key->client_p); + + /* THESE SHOULD BE DISCARDED */ + gnutls_mpi_release(key->client_Y); + gnutls_mpi_release(key->client_p); + gnutls_mpi_release(key->client_g); + key->client_Y = NULL; + key->client_p = NULL; + key->client_g = NULL; + + return data_size; +} + +int proc_anon_server_kx( GNUTLS_KEY key, opaque* data, int data_size) { + uint16 n_Y, n_g, n_p; + size_t _n_Y, _n_g, _n_p; + uint8 *data_p; + uint8 *data_g; + uint8 *data_Y; + int i; + + + i = 0; + memmove(&n_p, &data[i], 2); + i += 2; +#ifndef WORDS_BIGENDIAN + n_p = byteswap16(n_p); +#endif + + data_p = &data[i]; + i += n_p; + if (i > data_size) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + memmove(&n_g, &data[i], 2); +#ifndef WORDS_BIGENDIAN + n_g = byteswap16(n_g); +#endif + i += 2; + data_g = &data[i]; + i += n_g; + if (i > data_size) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + memmove(&n_Y, &data[i], 2); + i += 2; +#ifndef WORDS_BIGENDIAN + n_Y = byteswap16(n_Y); +#endif + + data_Y = &data[i]; + i += n_Y; + if (i > data_size) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + _n_Y = n_Y; + _n_g = n_g; + _n_p = n_p; + + if (gcry_mpi_scan(&key->client_Y, + GCRYMPI_FMT_USG, data_Y, &_n_Y) != 0) { + gnutls_assert(); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + if (gcry_mpi_scan(&key->client_g, + GCRYMPI_FMT_USG, data_g, &_n_g) != 0) { + gnutls_assert(); + return GNUTLS_E_MPI_SCAN_FAILED; + } + if (gcry_mpi_scan(&key->client_p, + GCRYMPI_FMT_USG, data_p, &_n_p) != 0) { + gnutls_assert(); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + /* We should check signature in non-anonymous KX + * this is anonymous however + */ + + return 0; +} + +int proc_anon_client_kx( GNUTLS_KEY key, opaque* data, int data_size) { + uint16 n_Y; + size_t _n_Y; + +#if 0 /* removed. I do not know why - maybe I didn't get the protocol, + * but openssl does not use that byte + */ + if (data[0] != 1) { + gnutls_assert(); + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + } +#endif + + memmove(&n_Y, &data[0], 2); +#ifndef WORDS_BIGENDIAN + n_Y = byteswap16(n_Y); +#endif + _n_Y = n_Y; + if (gcry_mpi_scan(&key->client_Y, + GCRYMPI_FMT_USG, &data[2], &_n_Y)) { + gnutls_assert(); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + key->KEY = gnutls_calc_dh_key( key->client_Y, key->dh_secret); + + gnutls_mpi_release(key->client_Y); + gnutls_mpi_release(key->dh_secret); + key->client_Y = NULL; + key->dh_secret = NULL; + + return 0; +} + +int gen_anon_client_cert_vrfy( GNUTLS_KEY key, opaque** data) { + (*data) = NULL; + return 0; +} +int gen_anon_server_cert_vrfy( GNUTLS_KEY key, opaque** data) { + (*data) = NULL; + return 0; +} +int proc_anon_client_cert_vrfy( GNUTLS_KEY key, opaque* data, int data_size) { + /* no certificate check in anonymous KX */ + return 0; +} +int proc_anon_server_cert_vrfy( GNUTLS_KEY key, opaque* data, int data_size) { + /* no certificate check in this algorithm */ + return 0; +} diff --git a/lib/gnutls_anon.h b/lib/gnutls_anon.h new file mode 100644 index 0000000000..6df3b8e821 --- /dev/null +++ b/lib/gnutls_anon.h @@ -0,0 +1,2 @@ +/* this is not to be included by gnutls_anon.c */ +extern MOD_AUTH_STRUCT anon_auth_struct; diff --git a/lib/gnutls_auth.h b/lib/gnutls_auth.h new file mode 100644 index 0000000000..4316f0eaf4 --- /dev/null +++ b/lib/gnutls_auth.h @@ -0,0 +1,15 @@ +#ifndef GNUTLS_AUTH_H + #define GNUTLS_AUTH_H +typedef struct { + char* name; /* null terminated */ + int (*gnutls_generate_server_kx)( GNUTLS_KEY, opaque**); + int (*gnutls_generate_client_kx)( GNUTLS_KEY, opaque**); + int (*gnutls_generate_client_cert_vrfy) ( GNUTLS_KEY, opaque**); + int (*gnutls_generate_server_cert_vrfy) ( GNUTLS_KEY, opaque**); + + int (*gnutls_process_server_kx)( GNUTLS_KEY, opaque*, int); + int (*gnutls_process_client_kx)( GNUTLS_KEY, opaque*, int); + int (*gnutls_process_client_cert_vrfy) ( GNUTLS_KEY, opaque*, int); + int (*gnutls_process_server_cert_vrfy) ( GNUTLS_KEY, opaque*, int); +} MOD_AUTH_STRUCT; +#endif diff --git a/lib/gnutls_dhe_dss.c b/lib/gnutls_dhe_dss.c new file mode 100644 index 0000000000..5e0b156878 --- /dev/null +++ b/lib/gnutls_dhe_dss.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2000 Nikos Mavroyanopoulos + * + * This file is part of GNUTLS. + * + * GNUTLS is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNUTLS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* DHE_DSS is not really working. It is used as a template */ + +#include <defines.h> +#include "gnutls_int.h" +#include "gnutls_errors.h" +#include "gnutls_dh.h" + +int gen_dhe_dss_server_kx( GNUTLS_KEY , opaque**); +int gen_dhe_dss_client_kx( GNUTLS_KEY , opaque**); +int proc_dhe_dss_server_kx( GNUTLS_KEY , opaque*, int); +int proc_dhe_dss_client_kx( GNUTLS_KEY , opaque*, int); + +int gen_dhe_dss_client_cert_vrfy( GNUTLS_KEY, opaque**); +int proc_dhe_dss_client_cert_vrfy( GNUTLS_KEY, opaque*, int); + +int gen_dhe_dss_server_cert_vrfy( GNUTLS_KEY, opaque**); +int proc_dhe_dss_server_cert_vrfy( GNUTLS_KEY, opaque*, int); + +MOD_AUTH_STRUCT dhe_dss_auth_struct = { + "DHE_DSS", + gen_dhe_dss_server_kx, + gen_dhe_dss_client_kx, + gen_dhe_dss_client_cert_vrfy, + gen_dhe_dss_server_cert_vrfy, + proc_dhe_dss_server_kx, + proc_dhe_dss_client_kx, + proc_dhe_dss_client_cert_vrfy, + proc_dhe_dss_server_cert_vrfy +}; + +int gen_dhe_dss_server_kx( GNUTLS_KEY key, opaque** data) { + GNUTLS_MPI x, X, g, p; + size_t n_X, n_g, n_p; + uint16 _n_X, _n_g, _n_p; + uint8 *data_p; + uint8 *data_g; + uint8 *data_X; + int ret = 0; + + X = gnutls_calc_dh_secret(&x); + key->dh_secret = x; + g = gnutls_get_dh_params(&p); + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_g, g); + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_p, p); + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_X, X); + (*data) = gnutls_malloc(n_g + n_p + n_X + 6); + data_p = &(*data)[0]; + gcry_mpi_print(GCRYMPI_FMT_USG, &data_p[2], &n_p, p); + gnutls_mpi_release(p); + _n_p = n_p; +#ifndef WORDS_BIGENDIAN + _n_p = byteswap16(_n_p); + memmove(data_p, &_n_p, 2); +#else + memmove(data_p, &_n_p, 2); +#endif + data_g = &data_p[2 + n_p]; + gcry_mpi_print(GCRYMPI_FMT_USG, &data_g[2], &n_g, g); + gnutls_mpi_release(g); + _n_g = n_g; +#ifndef WORDS_BIGENDIAN + _n_g = byteswap16(_n_g); + memmove(data_g, &_n_g, 2); +#else + memmove(data_g, &_n_g, 2); +#endif + data_X = &data_g[2 + n_g]; + gcry_mpi_print(GCRYMPI_FMT_USG, &data_X[2], &n_X, X); + gnutls_mpi_release(X); + _n_X = n_X; +#ifndef WORDS_BIGENDIAN + _n_X = byteswap16(_n_X); + memmove(data_X, &_n_X, 2); +#else + memmove(data_X, &_n_X, 2); +#endif + ret = n_p+n_g+n_X+6; + + return ret; +} + +int gen_dhe_dss_client_kx( GNUTLS_KEY key, opaque** data) { +GNUTLS_MPI x, X; +size_t n_X; +uint16 _n_X; +int data_size; + + X = _gnutls_calc_dh_secret(&x, key->client_g, + key->client_p); + + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_X, X); + (*data) = gnutls_malloc(n_X + 2); + + gcry_mpi_print(GCRYMPI_FMT_USG, &(*data)[2], &n_X, X); + (*data)[0] = 1; /* extern - explicit since we do not have + certificate */ + gnutls_mpi_release(X); + _n_X = n_X; +#ifndef WORDS_BIGENDIAN + _n_X = byteswap16(_n_X); + memmove(&(*data)[0], &_n_X, 2); +#else + memmove(&(*data)[0], &_n_X, 2); +#endif + data_size = _n_X+2; + + /* calculate the key after calculating the message */ + key->KEY = _gnutls_calc_dh_key(key->client_Y, x, key->client_p); + + /* THESE SHOULD BE DISCARDED */ + gnutls_mpi_release(key->client_Y); + gnutls_mpi_release(key->client_p); + gnutls_mpi_release(key->client_g); + key->client_Y = NULL; + key->client_p = NULL; + key->client_g = NULL; + + return data_size; +} + +int proc_dhe_dss_server_kx( GNUTLS_KEY key, opaque* data, int data_size) { + uint16 n_Y, n_g, n_p; + size_t _n_Y, _n_g, _n_p; + uint8 *data_p; + uint8 *data_g; + uint8 *data_Y; + int i; + + + i = 0; + memmove(&n_p, &data[i], 2); + i += 2; +#ifndef WORDS_BIGENDIAN + n_p = byteswap16(n_p); +#endif + + data_p = &data[i]; + i += n_p; + if (i > data_size) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + memmove(&n_g, &data[i], 2); +#ifndef WORDS_BIGENDIAN + n_g = byteswap16(n_g); +#endif + i += 2; + data_g = &data[i]; + i += n_g; + if (i > data_size) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + memmove(&n_Y, &data[i], 2); + i += 2; +#ifndef WORDS_BIGENDIAN + n_Y = byteswap16(n_Y); +#endif + + data_Y = &data[i]; + i += n_Y; + if (i > data_size) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + _n_Y = n_Y; + _n_g = n_g; + _n_p = n_p; + + if (gcry_mpi_scan(&key->client_Y, + GCRYMPI_FMT_USG, data_Y, &_n_Y) != 0) { + gnutls_assert(); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + if (gcry_mpi_scan(&key->client_g, + GCRYMPI_FMT_USG, data_g, &_n_g) != 0) { + gnutls_assert(); + return GNUTLS_E_MPI_SCAN_FAILED; + } + if (gcry_mpi_scan(&key->client_p, + GCRYMPI_FMT_USG, data_p, &_n_p) != 0) { + gnutls_assert(); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + /* We should check signature in non-anonymous KX + * this is anonymous however + */ + gnutls_free(data); + + return 0; +} + +int proc_dhe_dss_client_kx( GNUTLS_KEY key, opaque* data, int data_size) { + uint16 n_Y; + size_t _n_Y; + +#if 0 /* removed. I do not know why - maybe I didn't get the protocol, + * but openssl does not use that byte + */ + if (data[0] != 1) { + gnutls_assert(); + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + } +#endif + + memmove(&n_Y, &data[0], 2); +#ifndef WORDS_BIGENDIAN + n_Y = byteswap16(n_Y); +#endif + _n_Y = n_Y; + if (gcry_mpi_scan(&key->client_Y, + GCRYMPI_FMT_USG, &data[2], &_n_Y)) { + gnutls_assert(); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + key->KEY = gnutls_calc_dh_key( key->client_Y, key->dh_secret); + + gnutls_mpi_release(key->client_Y); + gnutls_mpi_release(key->dh_secret); + key->client_Y = NULL; + key->dh_secret = NULL; + + return 0; +} + +int gen_dhe_dss_client_cert_vrfy( GNUTLS_KEY key, opaque** data) { + /* FIXME: not ready yet */ + (*data)=gnutls_calloc(1, 20); + return 20; +} +int gen_dhe_dss_server_cert_vrfy( GNUTLS_KEY key, opaque** data) { + /* FIXME: not ready yet */ + (*data)=gnutls_calloc(1, 20); + return 20; +} +int proc_dhe_dss_client_cert_vrfy( GNUTLS_KEY key, opaque* data, int data_size) { + /* no certificate check in anonymous KX */ + return 0; +} +int proc_dhe_dss_server_cert_vrfy( GNUTLS_KEY key, opaque* data, int data_size) { + /* no certificate check in this algorithm */ + return 0; +} diff --git a/lib/gnutls_dhe_dss.h b/lib/gnutls_dhe_dss.h new file mode 100644 index 0000000000..8e301e87cd --- /dev/null +++ b/lib/gnutls_dhe_dss.h @@ -0,0 +1 @@ +extern MOD_AUTH_STRUCT dhe_dss_auth_struct; diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index f99aea9e63..0be5f3d3d2 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -689,6 +689,21 @@ int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char *data, int datalen) fprintf(stderr, "Selected cipher suite: "); fprintf(stderr, "%s\n", _gnutls_cipher_suite_get_name(state->gnutls_internals.current_cipher_suite ) ); #endif + /* set the MOD_AUTH_STRUCT to the appropriate struct + * according to the KX algorithm. This is needed since all the + * handshake functions are read from there; + */ + state->gnutls_internals.auth_struct = _gnutls_kx_auth_struct( _gnutls_cipher_suite_get_kx_algo( cipher_suite)); + if (state->gnutls_internals.auth_struct==NULL) { +#ifdef DEBUG + fprintf(stderr, "Cannot find the appropriate handler for the KX algorithm\n"); +#endif + gnutls_assert(); + return GNUTLS_E_UNKNOWN_CIPHER_TYPE; + } + + + /* move to compression */ z = 1; memmove(&compression_method, &data[pos++], 1); z = @@ -778,6 +793,19 @@ int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char *data, int datalen) sizeOfSuites); if (ret<0) return ret; + + /* set the MOD_AUTH_STRUCT to the appropriate struct + * according to the KX algorithm. This is needed since all the + * handshake functions are read from there; + */ + state->gnutls_internals.auth_struct = _gnutls_kx_auth_struct( _gnutls_cipher_suite_get_kx_algo( state->gnutls_internals.current_cipher_suite)); + if (state->gnutls_internals.auth_struct==NULL) { +#ifdef DEBUG + fprintf(stderr, "Cannot find the appropriate handler for the KX algorithm\n"); +#endif + gnutls_assert(); + return GNUTLS_E_UNKNOWN_CIPHER_TYPE; + } pos += sizeOfSuites; diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index bbf13428d2..4b056ce341 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -110,6 +110,16 @@ typedef struct { AlertDescription description; } Alert; +typedef struct { + /* For DH KX */ + MPI KEY; + MPI client_Y; + MPI client_g; + MPI client_p; + MPI dh_secret; +} GNUTLS_KEY_A; +typedef GNUTLS_KEY_A* GNUTLS_KEY; + /* STATE */ enum ConnectionEnd { GNUTLS_SERVER, GNUTLS_CLIENT }; @@ -135,6 +145,7 @@ typedef enum CompressionMethod CompressionMethod; #include <gnutls_hash_int.h> #include <gnutls_cipher_int.h> +#include <gnutls_auth.h> typedef struct { ConnectionEnd entity; @@ -217,12 +228,7 @@ typedef struct { /* resumed session */ ResumableSession resumed; /* TRUE or FALSE - if we are resuming a session */ SecurityParameters resumed_security_parameters; - /* For DH KX */ - MPI KEY; - MPI client_Y; - MPI client_g; - MPI client_p; - MPI dh_secret; + int certificate_requested; /* non zero if client certificate was requested */ int certificate_verify_needed; /* non zero if we should expect for certificate verify */ /* sockets internals */ @@ -230,6 +236,7 @@ typedef struct { /* gdbm */ char* db_name; int expire_time; + MOD_AUTH_STRUCT* auth_struct; /* used in handshake packets and KX algorithms */ } GNUTLS_INTERNALS; typedef struct { @@ -237,6 +244,7 @@ typedef struct { CipherSpecs cipher_specs; ConnectionState connection_state; GNUTLS_INTERNALS gnutls_internals; + GNUTLS_KEY gnutls_key; } GNUTLS_STATE_INT; typedef GNUTLS_STATE_INT *GNUTLS_STATE; diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c index d39f1ed0c5..ffa7a18c0a 100644 --- a/lib/gnutls_kx.c +++ b/lib/gnutls_kx.c @@ -35,84 +35,24 @@ */ int _gnutls_send_server_kx_message(int cd, GNUTLS_STATE state) { - KXAlgorithm algorithm; - GNUTLS_MPI x, X, g, p; - size_t n_X, n_g, n_p; - uint16 _n_X, _n_g, _n_p; uint8 *data = NULL; - uint8 *data_p; - uint8 *data_g; - uint8 *data_X; + int data_size = 0; int ret = 0; #ifdef HARD_DEBUG fprintf(stderr, "Sending server KX message\n"); #endif + data_size = state->gnutls_internals.auth_struct->gnutls_generate_server_kx( state->gnutls_key, &data); - algorithm = - _gnutls_cipher_suite_get_kx_algo(state-> - gnutls_internals.current_cipher_suite); - - /* Do key exchange only if the algorithm permits it */ - if (_gnutls_kx_server_key_exchange(algorithm) != 0) { - switch (_gnutls_cipher_suite_get_kx_algo - (state->gnutls_internals.current_cipher_suite)) { - case GNUTLS_KX_ANON_DH: - case GNUTLS_KX_DHE_DSS: - case GNUTLS_KX_DHE_RSA: - X = gnutls_calc_dh_secret(&x); - state->gnutls_internals.dh_secret = x; - g = gnutls_get_dh_params(&p); - gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_g, g); - gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_p, p); - gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_X, X); - data = gnutls_malloc(n_g + n_p + n_X + 6); - data_p = &data[0]; - gcry_mpi_print(GCRYMPI_FMT_USG, &data_p[2], - &n_p, p); - gnutls_mpi_release(p); - _n_p = n_p; -#ifndef WORDS_BIGENDIAN - _n_p = byteswap16(_n_p); - memmove(data_p, &_n_p, 2); -#else - memmove(data_p, &_n_p, 2); -#endif - data_g = &data_p[2 + n_p]; - gcry_mpi_print(GCRYMPI_FMT_USG, &data_g[2], - &n_g, g); - gnutls_mpi_release(g); - _n_g = n_g; -#ifndef WORDS_BIGENDIAN - _n_g = byteswap16(_n_g); - memmove(data_g, &_n_g, 2); -#else - memmove(data_g, &_n_g, 2); -#endif - data_X = &data_g[2 + n_g]; - gcry_mpi_print(GCRYMPI_FMT_USG, &data_X[2], - &n_X, X); - gnutls_mpi_release(X); - _n_X = n_X; -#ifndef WORDS_BIGENDIAN - _n_X = byteswap16(_n_X); - memmove(data_X, &_n_X, 2); -#else - memmove(data_X, &_n_X, 2); -#endif - ret = - _gnutls_send_handshake(cd, state, data, - n_p + n_g + n_X + 6, - GNUTLS_SERVER_KEY_EXCHANGE); - gnutls_free(data); - break; - default: - gnutls_assert(); - ret = GNUTLS_E_UNKNOWN_KX_ALGORITHM; - } + if (data_size<0) { + gnutls_assert(); + return data_size; } - return ret; + ret = _gnutls_send_handshake(cd, state, data, data_size, GNUTLS_SERVER_KEY_EXCHANGE); + gnutls_free(data); + + return data_size; } /* This is the function for the client to send the key @@ -120,91 +60,45 @@ int _gnutls_send_server_kx_message(int cd, GNUTLS_STATE state) */ int _gnutls_send_client_kx_message(int cd, GNUTLS_STATE state) { - KXAlgorithm algorithm; - GNUTLS_MPI x, X; - size_t n_X; - uint16 _n_X; uint8 *data; + int data_size; int ret = 0; uint8 *premaster = NULL; int premaster_size = 0; svoid *master; - char *random = gnutls_malloc(64); + char random[64]; #ifdef HARD_DEBUG int i; fprintf(stderr, "Sending client KX message\n"); #endif - memmove(random, state->security_parameters.client_random, 32); memmove(&random[32], state->security_parameters.server_random, 32); - algorithm = - _gnutls_cipher_suite_get_kx_algo - (state->gnutls_internals.current_cipher_suite); - switch (_gnutls_cipher_suite_get_kx_algo - (state->gnutls_internals.current_cipher_suite)) { - case GNUTLS_KX_ANON_DH: - case GNUTLS_KX_DHE_DSS: - case GNUTLS_KX_DHE_RSA: - X = - _gnutls_calc_dh_secret(&x, - state-> - gnutls_internals.client_g, - state-> - gnutls_internals.client_p); - gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_X, X); - data = gnutls_malloc(n_X + 2); - gcry_mpi_print(GCRYMPI_FMT_USG, &data[2], &n_X, X); - data[0] = 1; /* extern - explicit since we do not have - certificate */ - gnutls_mpi_release(X); - _n_X = n_X; -#ifndef WORDS_BIGENDIAN - _n_X = byteswap16(_n_X); - memmove(&data[0], &_n_X, 2); -#else - memmove(&data[0], &_n_X, 2); -#endif - ret = - _gnutls_send_handshake(cd, state, data, - n_X + 2, - GNUTLS_CLIENT_KEY_EXCHANGE); - gnutls_free(data); - /* calculate the key after sending the message */ - state->gnutls_internals.KEY = - _gnutls_calc_dh_key(state->gnutls_internals.client_Y, - x, - state->gnutls_internals.client_p); - - gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &premaster_size, - state->gnutls_internals.KEY); - premaster = secure_malloc(premaster_size); - gcry_mpi_print(GCRYMPI_FMT_USG, premaster, - &premaster_size, - state->gnutls_internals.KEY); + data_size = state->gnutls_internals.auth_struct->gnutls_generate_client_kx( state->gnutls_key, &data); + if (data_size < 0) { + gnutls_assert(); + return data_size; + } + + ret = _gnutls_send_handshake(cd, state, data, data_size, GNUTLS_CLIENT_KEY_EXCHANGE); + gnutls_free(data); + + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &premaster_size, state->gnutls_key->KEY); + premaster = secure_malloc(premaster_size); + gcry_mpi_print(GCRYMPI_FMT_USG, premaster, &premaster_size, state->gnutls_key->KEY); #ifdef HARD_DEBUG - fprintf(stderr, "PREMASTER SECRET: "); - for (i=0;i<premaster_size;i++) fprintf(stderr, "%x",premaster[i]); - fprintf(stderr, "\n"); + fprintf(stderr, "PREMASTER SECRET: "); + for (i=0;i<premaster_size;i++) fprintf(stderr, "%x",premaster[i]); + fprintf(stderr, "\n"); #endif - /* THIS SHOULD BE DISCARDED */ - gnutls_mpi_release(state->gnutls_internals.KEY); - gnutls_mpi_release(state->gnutls_internals.client_Y); - gnutls_mpi_release(state->gnutls_internals.client_p); - gnutls_mpi_release(state->gnutls_internals.client_g); - state->gnutls_internals.KEY = NULL; - state->gnutls_internals.client_Y = NULL; - state->gnutls_internals.client_p = NULL; - state->gnutls_internals.client_g = NULL; - break; - default: - gnutls_assert(); - ret = GNUTLS_E_UNKNOWN_KX_ALGORITHM; - } + /* THIS SHOULD BE DISCARDED */ + gnutls_mpi_release(state->gnutls_key->KEY); + state->gnutls_key->KEY = NULL; + if (_gnutls_version_ssl3(state->connection_state.version) == 0) { master = @@ -222,7 +116,6 @@ int _gnutls_send_client_kx_message(int cd, GNUTLS_STATE state) #endif memmove(state->security_parameters.master_secret, master, 48); secure_free(master); - gnutls_free(random); return ret; } @@ -235,6 +128,7 @@ int _gnutls_send_client_certificate_verify(int cd, GNUTLS_STATE state) { uint8 *data; int ret = 0; + int data_size; /* if certificate verify is not needed just exit */ if (state->gnutls_internals.certificate_verify_needed==0) return 0; @@ -242,28 +136,14 @@ int _gnutls_send_client_certificate_verify(int cd, GNUTLS_STATE state) #ifdef HARD_DEBUG fprintf(stderr, "Sending client certificate verify message\n"); #endif - - switch (_gnutls_cipher_suite_get_kx_algo - (state->gnutls_internals.current_cipher_suite)) { - case GNUTLS_KX_DHE_DSS: - data=gnutls_calloc(1, 20); - ret = - _gnutls_send_handshake(cd, state, data, - 20, - GNUTLS_CERTIFICATE_VERIFY); - gnutls_free(data); - break; - case GNUTLS_KX_DHE_RSA: - data=gnutls_calloc(1, 20+16); - ret = - _gnutls_send_handshake(cd, state, data, - 20+16, - GNUTLS_CERTIFICATE_VERIFY); - gnutls_free(data); - break; - default: - ret = 0; - } + data_size = state->gnutls_internals.auth_struct->gnutls_generate_client_cert_vrfy( state->gnutls_key, &data); + if (data_size < 0) + return data_size; + ret = + _gnutls_send_handshake(cd, state, data, + data_size, + GNUTLS_CERTIFICATE_VERIFY); + gnutls_free(data); return ret; } @@ -272,14 +152,9 @@ int _gnutls_send_client_certificate_verify(int cd, GNUTLS_STATE state) int _gnutls_recv_server_kx_message(int cd, GNUTLS_STATE state) { KXAlgorithm algorithm; - uint16 n_Y, n_g, n_p; - size_t _n_Y, _n_g, _n_p; uint8 *data; int datasize; - uint8 *data_p; - uint8 *data_g; - uint8 *data_Y; - int ret = 0, i; + int ret = 0; #ifdef HARD_DEBUG fprintf(stderr, "Receiving Server KX message\n"); @@ -287,95 +162,28 @@ int _gnutls_recv_server_kx_message(int cd, GNUTLS_STATE state) algorithm = _gnutls_cipher_suite_get_kx_algo (state->gnutls_internals.current_cipher_suite); - /* Do key exchange only if the algorithm permits it */ if (_gnutls_kx_server_key_exchange(algorithm) != 0) { + ret = + _gnutls_recv_handshake(cd, state, &data, + &datasize, + GNUTLS_SERVER_KEY_EXCHANGE); + if (ret < 0) + return ret; - switch (_gnutls_cipher_suite_get_kx_algo - (state->gnutls_internals.current_cipher_suite)) { - case GNUTLS_KX_ANON_DH: - case GNUTLS_KX_DHE_DSS: - case GNUTLS_KX_DHE_RSA: - ret = - _gnutls_recv_handshake(cd, state, &data, - &datasize, - GNUTLS_SERVER_KEY_EXCHANGE); - if (ret < 0) - return ret; - - i = 0; - memmove(&n_p, &data[i], 2); - i += 2; -#ifndef WORDS_BIGENDIAN - n_p = byteswap16(n_p); -#endif - data_p = &data[i]; - i += n_p; - if (i > datasize) { - gnutls_assert(); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - memmove(&n_g, &data[i], 2); -#ifndef WORDS_BIGENDIAN - n_g = byteswap16(n_g); -#endif - i += 2; - data_g = &data[i]; - i += n_g; - if (i > datasize) { - gnutls_assert(); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - memmove(&n_Y, &data[i], 2); - i += 2; -#ifndef WORDS_BIGENDIAN - n_Y = byteswap16(n_Y); -#endif - - data_Y = &data[i]; - i += n_Y; - if (i > datasize) { - gnutls_assert(); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - _n_Y = n_Y; - _n_g = n_g; - _n_p = n_p; - - if (gcry_mpi_scan(&state->gnutls_internals.client_Y, - GCRYMPI_FMT_USG, data_Y, &_n_Y) != 0) { - gnutls_assert(); - return GNUTLS_E_MPI_SCAN_FAILED; - } - if (gcry_mpi_scan(&state->gnutls_internals.client_g, - GCRYMPI_FMT_USG, data_g, &_n_g) != 0) { - gnutls_assert(); - return GNUTLS_E_MPI_SCAN_FAILED; - } - if (gcry_mpi_scan(&state->gnutls_internals.client_p, - GCRYMPI_FMT_USG, data_p, &_n_p) != 0) { - gnutls_assert(); - return GNUTLS_E_MPI_SCAN_FAILED; - } - - /* FIXME: We need to check signature in non-anonymous KX */ - gnutls_free(data); - break; - default: - gnutls_assert(); - ret = GNUTLS_E_UNKNOWN_KX_ALGORITHM; - } + ret = state->gnutls_internals.auth_struct->gnutls_process_server_kx( state->gnutls_key, data, datasize); + gnutls_free(data); + if (ret < 0) + return ret; + } - return ret; } int _gnutls_recv_client_kx_message(int cd, GNUTLS_STATE state) { KXAlgorithm algorithm; - uint16 n_Y; - size_t _n_Y; uint8 *data; #ifdef HARD_DEBUG int i; @@ -385,74 +193,41 @@ int _gnutls_recv_client_kx_message(int cd, GNUTLS_STATE state) uint8 *premaster = NULL; int premaster_size = 0; svoid *master; - uint8 *random = gnutls_malloc(64); + uint8 random[64]; + #ifdef HARD_DEBUG fprintf(stderr, "Receiving client KX message\n"); #endif memmove(random, state->security_parameters.client_random, 32); memmove(&random[32], state->security_parameters.server_random, 32); + algorithm = _gnutls_cipher_suite_get_kx_algo (state->gnutls_internals.current_cipher_suite); + /* Do key exchange only if the algorithm permits it */ if (_gnutls_kx_server_key_exchange(algorithm) != 0) { - switch (_gnutls_cipher_suite_get_kx_algo - (state->gnutls_internals.current_cipher_suite)) { - case GNUTLS_KX_ANON_DH: - case GNUTLS_KX_DHE_DSS: - case GNUTLS_KX_DHE_RSA: - ret = - _gnutls_recv_handshake(cd, state, &data, - &datasize, - GNUTLS_CLIENT_KEY_EXCHANGE); - if (ret < 0) - return ret; -#if 0 /* removed. I do not know why - maybe I didn't get the protocol, - * but openssl does not use that byte - */ - if (data[0] != 1) { - gnutls_assert(); - return GNUTLS_E_UNIMPLEMENTED_FEATURE; - } -#endif - memmove(&n_Y, &data[0], 2); -#ifndef WORDS_BIGENDIAN - n_Y = byteswap16(n_Y); -#endif - _n_Y = n_Y; - if (gcry_mpi_scan(&state->gnutls_internals.client_Y, - GCRYMPI_FMT_USG, &data[2], &_n_Y)) { - gnutls_assert(); - return GNUTLS_E_MPI_SCAN_FAILED; - } - state->gnutls_internals.KEY = - gnutls_calc_dh_key(state-> - gnutls_internals.client_Y, - state-> - gnutls_internals.dh_secret); - gcry_mpi_print(GCRYMPI_FMT_USG, NULL, - &premaster_size, - state->gnutls_internals.KEY); - premaster = secure_malloc(premaster_size); - gcry_mpi_print(GCRYMPI_FMT_USG, premaster, - &premaster_size, - state->gnutls_internals.KEY); - /* THESE SHOULD BE DISCARDED */ - gnutls_mpi_release(state->gnutls_internals.KEY); - gnutls_mpi_release(state-> - gnutls_internals.client_Y); - gnutls_mpi_release(state-> - gnutls_internals.dh_secret); - state->gnutls_internals.KEY = NULL; - state->gnutls_internals.client_Y = NULL; - state->gnutls_internals.dh_secret = NULL; - gnutls_free(data); - break; - default: - gnutls_assert(); - ret = GNUTLS_E_UNKNOWN_KX_ALGORITHM; - } + ret = + _gnutls_recv_handshake(cd, state, &data, + &datasize, + GNUTLS_CLIENT_KEY_EXCHANGE); + if (ret < 0) + return ret; + + ret = state->gnutls_internals.auth_struct->gnutls_process_client_kx( state->gnutls_key, data, datasize); + gnutls_free(data); + if (ret < 0) + return ret; + + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &premaster_size, state->gnutls_key->KEY); + premaster = secure_malloc(premaster_size); + gcry_mpi_print(GCRYMPI_FMT_USG, premaster, &premaster_size, state->gnutls_key->KEY); + + /* THIS SHOULD BE DISCARDED */ + gnutls_mpi_release(state->gnutls_key->KEY); + state->gnutls_key->KEY = NULL; + } #ifdef HARD_DEBUG @@ -478,6 +253,5 @@ int _gnutls_recv_client_kx_message(int cd, GNUTLS_STATE state) #endif memmove(state->security_parameters.master_secret, master, 48); secure_free(master); - gnutls_free(random); return ret; } |