summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2001-03-11 19:46:59 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2001-03-11 19:46:59 +0000
commitd3e5848bfde0598b806607302d35079a19bf0e42 (patch)
tree47456fb4ae8a83c1b7f7f3c64c6fb4ebbebbde89
parentccef91a9aff47be28e14139bd71f559f9b602a64 (diff)
downloadgnutls-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.am6
-rw-r--r--lib/gnutls.c25
-rw-r--r--lib/gnutls_algorithms.c29
-rw-r--r--lib/gnutls_algorithms.h3
-rw-r--r--lib/gnutls_anon.c261
-rw-r--r--lib/gnutls_anon.h2
-rw-r--r--lib/gnutls_auth.h15
-rw-r--r--lib/gnutls_dhe_dss.c266
-rw-r--r--lib/gnutls_dhe_dss.h1
-rw-r--r--lib/gnutls_handshake.c28
-rw-r--r--lib/gnutls_int.h20
-rw-r--r--lib/gnutls_kx.c376
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;
}