summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2011-05-16 22:20:17 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2011-05-20 12:31:22 +0200
commit78b9114c2c025090262e5b365fc199ce2f88334b (patch)
tree36e81a209054f87f404a5a768ef3253f614e2f02
parentf90470a7b4c672a916c4513cecf4b9a6bce0eb67 (diff)
downloadgnutls-78b9114c2c025090262e5b365fc199ce2f88334b.tar.gz
Initial ecc support. Adds support for anonymous ECDH ciphersuites.
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/auth/Makefile.am3
-rw-r--r--lib/auth/anon.h1
-rw-r--r--lib/auth/anon_ecdh.c151
-rw-r--r--lib/auth/ecdh_common.c203
-rw-r--r--lib/auth/ecdh_common.h41
-rw-r--r--lib/ext/Makefile.am2
-rw-r--r--lib/ext/ecc.c302
-rw-r--r--lib/ext/ecc.h37
-rw-r--r--lib/gnutls_algorithms.c126
-rw-r--r--lib/gnutls_algorithms.h24
-rw-r--r--lib/gnutls_dh.c1
-rw-r--r--lib/gnutls_ecc.c101
-rw-r--r--lib/gnutls_ecc.h2
-rw-r--r--lib/gnutls_errors.c2
-rw-r--r--lib/gnutls_extensions.c9
-rw-r--r--lib/gnutls_global.c5
-rw-r--r--lib/gnutls_int.h16
-rw-r--r--lib/gnutls_pk.c2
-rw-r--r--lib/gnutls_pk.h2
-rw-r--r--lib/gnutls_priority.c8
-rw-r--r--lib/gnutls_state.c12
-rw-r--r--lib/gnutls_state.h10
-rw-r--r--lib/includes/gnutls/crypto.h15
-rw-r--r--lib/includes/gnutls/gnutls.h.in16
-rw-r--r--lib/nettle/Makefile.am7
-rw-r--r--lib/nettle/ecc.h123
-rw-r--r--lib/nettle/ecc_free.c40
-rw-r--r--lib/nettle/ecc_make_key.c125
-rw-r--r--lib/nettle/ecc_shared_secret.c80
-rw-r--r--lib/nettle/ecc_sign_hash.c103
-rw-r--r--lib/nettle/ecc_test.c125
-rw-r--r--lib/nettle/ecc_verify_hash.c135
-rw-r--r--lib/nettle/gnettle.h2
-rw-r--r--lib/nettle/ltc_ecc_map.c73
-rw-r--r--lib/nettle/ltc_ecc_mulmod.c141
-rw-r--r--lib/nettle/ltc_ecc_points.c60
-rw-r--r--lib/nettle/ltc_ecc_projective_add_point.c195
-rw-r--r--lib/nettle/ltc_ecc_projective_dbl_point.c146
-rw-r--r--lib/nettle/mp_unsigned_bin.c28
-rw-r--r--lib/nettle/mpi.c2
-rw-r--r--lib/nettle/multi.c46
-rw-r--r--lib/nettle/pk.c131
-rw-r--r--lib/nettle/rnd.c10
-rw-r--r--lib/nettle/rnd.h2
-rw-r--r--lib/x509/x509_int.h5
46 files changed, 2655 insertions, 17 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index bb5975cd6f..17a1b8732b 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -68,7 +68,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c gnutls_cipher.c \
gnutls_datum.c gnutls_session_pack.c gnutls_mpi.c \
gnutls_pk.c gnutls_cert.c gnutls_global.c gnutls_constate.c \
gnutls_anon_cred.c pkix_asn1_tab.c gnutls_asn1_tab.c \
- gnutls_mem.c gnutls_ui.c gnutls_sig.c \
+ gnutls_mem.c gnutls_ui.c gnutls_sig.c gnutls_ecc.c \
gnutls_dh_primes.c gnutls_alert.c system.c \
gnutls_str.c gnutls_state.c gnutls_x509.c gnutls_rsa_export.c \
gnutls_helper.c gnutls_supplemental.c crypto.c random.c \
diff --git a/lib/auth/Makefile.am b/lib/auth/Makefile.am
index c459ffe25a..92519def81 100644
--- a/lib/auth/Makefile.am
+++ b/lib/auth/Makefile.am
@@ -38,4 +38,5 @@ noinst_LTLIBRARIES = libgnutls_auth.la
libgnutls_auth_la_SOURCES = anon.c cert.c dh_common.c dhe.c \
dhe_psk.c psk.c psk_passwd.c rsa.c rsa_export.c srp.c \
srp_passwd.c srp_rsa.c srp_sb64.c anon.h cert.h dh_common.h \
- psk.h psk_passwd.h srp.h srp_passwd.h
+ psk.h psk_passwd.h srp.h srp_passwd.h anon_ecdh.c \
+ ecdh_common.c
diff --git a/lib/auth/anon.h b/lib/auth/anon.h
index ab5063d5a0..b2616df247 100644
--- a/lib/auth/anon.h
+++ b/lib/auth/anon.h
@@ -44,6 +44,7 @@ typedef struct gnutls_anon_client_credentials_st
typedef struct anon_auth_info_st
{
dh_info_st dh;
+ ecc_curve_t curve;
} *anon_auth_info_t;
typedef struct anon_auth_info_st anon_auth_info_st;
diff --git a/lib/auth/anon_ecdh.c b/lib/auth/anon_ecdh.c
new file mode 100644
index 0000000000..5e9932faa3
--- /dev/null
+++ b/lib/auth/anon_ecdh.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2010 Free
+ * Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains the Anonymous Diffie-Hellman key exchange part of
+ * the anonymous authentication. The functions here are used in the
+ * handshake.
+ */
+
+#include <gnutls_int.h>
+
+#ifdef ENABLE_ANON
+
+#include "gnutls_auth.h"
+#include "gnutls_errors.h"
+#include "gnutls_dh.h"
+#include "auth/anon.h"
+#include "gnutls_num.h"
+#include "gnutls_mpi.h"
+#include <gnutls_state.h>
+#include <auth/ecdh_common.h>
+#include <ext/ecc.h>
+
+static int gen_anon_ecdh_server_kx (gnutls_session_t, gnutls_buffer_st*);
+static int proc_anon_ecdh_client_kx (gnutls_session_t, opaque *, size_t);
+static int proc_anon_ecdh_server_kx (gnutls_session_t, opaque *, size_t);
+
+const mod_auth_st anon_ecdh_auth_struct = {
+ "ANON ECDH",
+ NULL,
+ NULL,
+ gen_anon_ecdh_server_kx,
+ _gnutls_gen_ecdh_common_client_kx, /* this can be shared */
+ NULL,
+ NULL,
+
+ NULL,
+ NULL, /* certificate */
+ proc_anon_ecdh_server_kx,
+ proc_anon_ecdh_client_kx,
+ NULL,
+ NULL
+};
+
+static int
+gen_anon_ecdh_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
+{
+ ecc_curve_t curve;
+ int ret;
+ gnutls_anon_server_credentials_t cred;
+
+ cred = (gnutls_anon_server_credentials_t)
+ _gnutls_get_cred (session->key, GNUTLS_CRD_ANON, NULL);
+ if (cred == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ curve = _gnutls_session_ecc_curve_get(session);
+ if (curve == GNUTLS_ECC_CURVE_INVALID)
+ return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);
+
+ if ((ret =
+ _gnutls_auth_info_set (session, GNUTLS_CRD_ANON,
+ sizeof (anon_auth_info_st), 1)) < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ ret = _gnutls_ecdh_common_print_server_kx (session, data, curve);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ }
+
+ return ret;
+}
+
+
+static int
+proc_anon_ecdh_client_kx (gnutls_session_t session, opaque * data,
+ size_t _data_size)
+{
+ gnutls_anon_server_credentials_t cred;
+ ecc_curve_t curve;
+
+ cred = (gnutls_anon_server_credentials_t)
+ _gnutls_get_cred (session->key, GNUTLS_CRD_ANON, NULL);
+ if (cred == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ curve = _gnutls_session_ecc_curve_get(session);
+ if (curve == GNUTLS_ECC_CURVE_INVALID)
+ return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);
+
+ return _gnutls_proc_ecdh_common_client_kx (session, data, _data_size, curve);
+}
+
+int
+proc_anon_ecdh_server_kx (gnutls_session_t session, opaque * data,
+ size_t _data_size)
+{
+
+ int ret;
+
+ /* set auth_info */
+ if ((ret =
+ _gnutls_auth_info_set (session, GNUTLS_CRD_ANON,
+ sizeof (anon_auth_info_st), 1)) < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ ret = _gnutls_proc_ecdh_common_server_kx (session, data, _data_size);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ return 0;
+}
+
+#endif /* ENABLE_ANON */
diff --git a/lib/auth/ecdh_common.c b/lib/auth/ecdh_common.c
new file mode 100644
index 0000000000..e3d247e8c1
--- /dev/null
+++ b/lib/auth/ecdh_common.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains common stuff in Ephemeral Diffie-Hellman (DHE)
+ * and Anonymous DH key exchange(DHA). These are used in the handshake
+ * procedure of the certificate and anoymous authentication.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_auth.h"
+#include "gnutls_errors.h"
+#include "gnutls_dh.h"
+#include "gnutls_num.h"
+#include "gnutls_sig.h"
+#include <gnutls_datum.h>
+#include <gnutls_x509.h>
+#include <gnutls_state.h>
+#include <auth/ecdh_common.h>
+#include <gnutls_ecc.h>
+#include <ext/ecc.h>
+#include <gnutls_algorithms.h>
+#include <auth/psk.h>
+#include <gnutls_pk.h>
+
+static int calc_ecdh_key( gnutls_session_t session)
+{
+gnutls_pk_params_st pub;
+int ret;
+
+ pub.params[0] = session->key->ecdh_params.params[0];
+ pub.params[1] = session->key->ecdh_params.params[1];
+ pub.params[2] = session->key->ecdh_params.params[2];
+ pub.params[3] = session->key->ecdh_params.params[3];
+ pub.params[4] = session->key->ecdh_x;
+ pub.params[5] = session->key->ecdh_y;
+ pub.params[6] = _gnutls_mpi_new(1);
+ if (pub.params[6] == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ _gnutls_mpi_set_ui(pub.params[6], 1);
+
+ ret = _gnutls_pk_derive(GNUTLS_PK_ECDH, &session->key->key, &session->key->ecdh_params, &pub);
+
+ _gnutls_mpi_release(&pub.params[6]);
+
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return 0;
+}
+
+
+int
+_gnutls_proc_ecdh_common_client_kx (gnutls_session_t session,
+ opaque * data, size_t _data_size,
+ ecc_curve_t curve)
+{
+ ssize_t data_size = _data_size;
+ int ret, i = 0;
+ int point_size;
+
+ DECR_LEN (data_size, 1);
+ point_size = data[i];
+ i+=1;
+
+ DECR_LEN (data_size, point_size);
+ ret = _gnutls_ecc_ansi_x963_import(curve, &data[i], point_size, &session->key->ecdh_x, &session->key->ecdh_y);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ /* generate pre-shared key */
+ ret = calc_ecdh_key(session);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return 0;
+}
+
+int
+_gnutls_gen_ecdh_common_client_kx (gnutls_session_t session, gnutls_buffer_st* data)
+{
+ int ret;
+ gnutls_datum_t out;
+ int curve = _gnutls_session_ecc_curve_get(session);
+
+ /* generate temporal key */
+ ret = _gnutls_pk_generate(GNUTLS_PK_ECDH, curve, &session->key->ecdh_params);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_ecc_ansi_x963_export(curve, session->key->ecdh_params.params[4] /* x */,
+ session->key->ecdh_params.params[5] /* y */, &out);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size);
+
+ _gnutls_free_datum(&out);
+
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ /* generate pre-shared key */
+ ret = calc_ecdh_key(session);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return data->length;
+}
+
+int
+_gnutls_proc_ecdh_common_server_kx (gnutls_session_t session,
+ opaque * data, size_t _data_size)
+{
+ int i, ret, point_size;
+ ecc_curve_t curve;
+ ssize_t data_size = _data_size;
+
+ i = 0;
+ DECR_LEN (data_size, 1);
+ if (data[i++] != 3)
+ return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);
+
+ DECR_LEN (data_size, 2);
+ curve = _gnutls_num_to_ecc(_gnutls_read_uint16 (&data[i]));
+ i += 2;
+
+ ret = _gnutls_session_supports_ecc_curve(session, curve);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ DECR_LEN (data_size, 1);
+ point_size = data[i];
+ i+=1;
+
+ DECR_LEN (data_size, point_size);
+ ret = _gnutls_ecc_ansi_x963_import(curve, &data[i], point_size, &session->key->ecdh_x, &session->key->ecdh_y);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return ret;
+}
+
+/* If the psk flag is set, then an empty psk_identity_hint will
+ * be inserted */
+int _gnutls_ecdh_common_print_server_kx (gnutls_session_t session, gnutls_buffer_st* data,
+ ecc_curve_t curve)
+{
+ opaque p;
+ int ret;
+ gnutls_datum_t out;
+
+ /* curve type */
+ p = 3;
+
+ ret = _gnutls_buffer_append_data(data, &p, 1);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_buffer_append_prefix(data, 16, _gnutls_ecc_to_num(curve));
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ /* generate temporal key */
+ ret = _gnutls_pk_generate(GNUTLS_PK_ECDH, curve, &session->key->ecdh_params);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_ecc_ansi_x963_export(curve, session->key->ecdh_params.params[4] /* x */,
+ session->key->ecdh_params.params[5] /* y */, &out);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size);
+
+ _gnutls_free_datum(&out);
+
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return data->length;
+}
diff --git a/lib/auth/ecdh_common.h b/lib/auth/ecdh_common.h
new file mode 100644
index 0000000000..1fa6eba39a
--- /dev/null
+++ b/lib/auth/ecdh_common.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef AUTH_ECDH_COMMON
+#define AUTH_ECDH_COMMON
+
+#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,
+ ecc_curve_t curve);
+int _gnutls_ecdh_common_print_server_kx (gnutls_session_t, gnutls_buffer_st* data,
+ ecc_curve_t curve);
+int _gnutls_proc_ecdh_common_server_kx (gnutls_session_t session, opaque * data,
+ size_t _data_size);
+
+
+
+#endif
diff --git a/lib/ext/Makefile.am b/lib/ext/Makefile.am
index a949912125..90dcb072ab 100644
--- a/lib/ext/Makefile.am
+++ b/lib/ext/Makefile.am
@@ -39,4 +39,4 @@ libgnutls_ext_la_SOURCES = max_record.c cert_type.c \
server_name.c signature.c safe_renegotiation.c \
max_record.h cert_type.h server_name.h srp.h \
session_ticket.h signature.h safe_renegotiation.h \
- session_ticket.c srp.c
+ session_ticket.c srp.c ecc.c
diff --git a/lib/ext/ecc.c b/lib/ext/ecc.c
new file mode 100644
index 0000000000..11c00716e4
--- /dev/null
+++ b/lib/ext/ecc.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005, 2010 Free Software Foundation,
+ * Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains the code the Certificate Type TLS extension.
+ * This extension is currently gnutls specific.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_errors.h"
+#include "gnutls_num.h"
+#include <ext/ecc.h>
+#include <gnutls_state.h>
+#include <gnutls_num.h>
+
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
+
+static int _gnutls_supported_ecc_recv_params (gnutls_session_t session,
+ const opaque * data,
+ size_t data_size);
+static int _gnutls_supported_ecc_send_params (gnutls_session_t session,
+ gnutls_buffer_st * extdata);
+
+static int _gnutls_supported_ecc_pf_recv_params (gnutls_session_t session,
+ const opaque * data,
+ size_t data_size);
+static int _gnutls_supported_ecc_pf_send_params (gnutls_session_t session,
+ gnutls_buffer_st * extdata);
+
+extension_entry_st ext_mod_supported_ecc = {
+ .name = "SUPPORTED ECC",
+ .type = GNUTLS_EXTENSION_SUPPORTED_ECC,
+ .parse_type = GNUTLS_EXT_TLS,
+
+ .recv_func = _gnutls_supported_ecc_recv_params,
+ .send_func = _gnutls_supported_ecc_send_params,
+ .pack_func = NULL,
+ .unpack_func = NULL,
+ .deinit_func = NULL
+};
+
+extension_entry_st ext_mod_supported_ecc_pf = {
+ .name = "SUPPORTED ECC POINT FORMATS",
+ .type = GNUTLS_EXTENSION_SUPPORTED_ECC_PF,
+ .parse_type = GNUTLS_EXT_TLS,
+
+ .recv_func = _gnutls_supported_ecc_pf_recv_params,
+ .send_func = _gnutls_supported_ecc_pf_send_params,
+ .pack_func = NULL,
+ .unpack_func = NULL,
+ .deinit_func = NULL
+};
+
+/*
+ * In case of a server: if a SUPPORTED_ECC extension type is received then it stores
+ * into the session security parameters the new value. The server may use gnutls_session_certificate_type_get(),
+ * to access it.
+ *
+ * In case of a client: If a supported_eccs have been specified then we send the extension.
+ *
+ */
+static int
+_gnutls_supported_ecc_recv_params (gnutls_session_t session,
+ const opaque * data, size_t _data_size)
+{
+ int new_type = -1, ret, i;
+ ssize_t data_size = _data_size;
+ uint16_t len;
+ const opaque* p = data;
+
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+ /* A client shouldn't receive this extension */
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
+ }
+ else
+ { /* SERVER SIDE - we must check if the sent supported ecc type is the right one
+ */
+ if (data_size < 2)
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
+
+ DECR_LEN (data_size, 2);
+ len = _gnutls_read_uint16(p);
+ p += 2;
+
+ DECR_LEN (data_size, len);
+
+ for (i = 0; i < len; i+=2)
+ {
+ new_type = _gnutls_num_to_ecc (_gnutls_read_uint16(&p[i]));
+ if (new_type < 0)
+ continue;
+
+ /* Check if we support this supported_ecc */
+ if ((ret =
+ _gnutls_session_supports_ecc_curve (session, new_type)) < 0)
+ {
+ gnutls_assert ();
+ continue;
+ }
+ else
+ break;
+ /* new_type is ok */
+ }
+
+ if (new_type < 0)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+
+ if ((ret =
+ _gnutls_session_supports_ecc_curve (session, new_type)) < 0)
+ {
+ /* The peer has requested unsupported ecc
+ * types. Instead of failing, procceed normally.
+ * (the ciphersuite selection would fail, or a
+ * non certificate ciphersuite will be selected).
+ */
+ return gnutls_assert_val(0);
+ }
+
+ _gnutls_session_ecc_curve_set (session, new_type);
+ }
+
+ return 0;
+}
+
+
+/* returns data_size or a negative number on failure
+ */
+static int
+_gnutls_supported_ecc_send_params (gnutls_session_t session, gnutls_buffer_st* extdata)
+{
+ unsigned len, i;
+ int ret;
+ uint16_t p;
+
+ /* this extension is only being sent on client side */
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+
+ if (session->internals.priorities.supported_ecc.algorithms > 0)
+ {
+
+ len = session->internals.priorities.supported_ecc.algorithms;
+
+ /* this is a vector!
+ */
+ ret = _gnutls_buffer_append_prefix(extdata, 16, len*2);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ for (i = 0; i < len; i++)
+ {
+ p =
+ _gnutls_ecc_to_num (session->internals.priorities.
+ supported_ecc.priority[i]);
+ ret = _gnutls_buffer_append_prefix(extdata, 16, p);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ }
+ return (len + 1)*2;
+ }
+
+ }
+
+ return 0;
+}
+
+/*
+ * In case of a server: if a SUPPORTED_ECC extension type is received then it stores
+ * into the session security parameters the new value. The server may use gnutls_session_certificate_type_get(),
+ * to access it.
+ *
+ * In case of a client: If a supported_eccs have been specified then we send the extension.
+ *
+ */
+static int
+_gnutls_supported_ecc_pf_recv_params (gnutls_session_t session,
+ const opaque * data, size_t _data_size)
+{
+int len, i;
+int uncompressed = 0;
+int data_size = _data_size;
+
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ {
+ if (data_size < 1)
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
+
+ len = data[0];
+ DECR_LEN (data_size, len+1);
+
+ for (i=0;i<len;i++)
+ if (data[1+i] == 0) /* uncompressed */
+ uncompressed = 1;
+
+ if (uncompressed == 0)
+ return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+ }
+ else
+ {
+ /* only sanity check here. We only support uncompressed points
+ * and a client must support it thus nothing to check.
+ */
+ if (_data_size < 1)
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
+ }
+
+ return 0;
+}
+
+/* returns data_size or a negative number on failure
+ */
+static int
+_gnutls_supported_ecc_pf_send_params (gnutls_session_t session, gnutls_buffer_st* extdata)
+{
+ const opaque p[2] = {0x01, 0x00}; /* only support uncompressed point format */
+
+ /* this extension is only being sent on client and server side */
+ _gnutls_buffer_append_data(extdata, p, 2);
+ return 2;
+}
+
+/* Maps numbers to record sizes according to the
+ * extensions draft.
+ */
+int
+_gnutls_num_to_ecc (int num)
+{
+ switch (num)
+ {
+ case 23:
+ /* sec256r1 */
+ return GNUTLS_ECC_CURVE_SECP256R1;
+ case 24:
+ return GNUTLS_ECC_CURVE_SECP384R1;
+ default:
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+}
+
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
+int
+_gnutls_ecc_to_num (ecc_curve_t supported_ecc)
+{
+ switch (supported_ecc)
+ {
+ case GNUTLS_ECC_CURVE_SECP256R1:
+ return 23;
+ case GNUTLS_ECC_CURVE_SECP384R1:
+ return 24;
+ default:
+ return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ }
+}
+
+/* Returns 0 if the given ECC curve is allowed in the current
+ * session. A negative error value is returned otherwise.
+ */
+int
+_gnutls_session_supports_ecc_curve (gnutls_session_t session, int ecc_type)
+{
+ unsigned i;
+
+ if (session->internals.priorities.supported_ecc.algorithms > 0)
+ {
+ for (i = 0; i < session->internals.priorities.supported_ecc.algorithms; i++)
+ {
+ if (session->internals.priorities.supported_ecc.priority[i] == ecc_type)
+ return 0;
+ }
+ }
+
+ return GNUTLS_E_ECC_NO_SUPPORTED_CURVES;
+}
diff --git a/lib/ext/ecc.h b/lib/ext/ecc.h
new file mode 100644
index 0000000000..745a000815
--- /dev/null
+++ b/lib/ext/ecc.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+#ifndef EXT_ECC_H
+#define EXT_ECC_H
+
+#include <gnutls_extensions.h>
+
+extern extension_entry_st ext_mod_supported_ecc;
+extern extension_entry_st ext_mod_supported_ecc_pf;
+
+int _gnutls_num_to_ecc (int num);
+int _gnutls_ecc_to_num (ecc_curve_t);
+int
+_gnutls_session_supports_ecc_curve (gnutls_session_t session, int ecc_type);
+
+#endif
diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c
index b54e5cd9e4..295bb87e26 100644
--- a/lib/gnutls_algorithms.c
+++ b/lib/gnutls_algorithms.c
@@ -70,6 +70,7 @@ typedef struct
static const gnutls_cred_map cred_mappings[] = {
{GNUTLS_KX_ANON_DH, GNUTLS_CRD_ANON, GNUTLS_CRD_ANON},
+ {GNUTLS_KX_ANON_ECDH, GNUTLS_CRD_ANON, GNUTLS_CRD_ANON},
{GNUTLS_KX_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
{GNUTLS_KX_RSA_EXPORT, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
{GNUTLS_KX_DHE_DSS, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
@@ -260,6 +261,7 @@ extern mod_auth_st rsa_export_auth_struct;
extern mod_auth_st dhe_rsa_auth_struct;
extern mod_auth_st dhe_dss_auth_struct;
extern mod_auth_st anon_auth_struct;
+extern mod_auth_st anon_ecdh_auth_struct;
extern mod_auth_st srp_auth_struct;
extern mod_auth_st psk_auth_struct;
extern mod_auth_st dhe_psk_auth_struct;
@@ -279,6 +281,7 @@ typedef struct gnutls_kx_algo_entry gnutls_kx_algo_entry;
static const gnutls_kx_algo_entry _gnutls_kx_algorithms[] = {
#ifdef ENABLE_ANON
{"ANON-DH", GNUTLS_KX_ANON_DH, &anon_auth_struct, 1, 0},
+ {"ANON-ECDH", GNUTLS_KX_ANON_ECDH, &anon_ecdh_auth_struct, 0, 0},
#endif
{"RSA", GNUTLS_KX_RSA, &rsa_auth_struct, 0, 0},
{"RSA-EXPORT", GNUTLS_KX_RSA_EXPORT, &rsa_export_auth_struct, 0,
@@ -463,7 +466,11 @@ typedef struct
#define GNUTLS_PSK_NULL_SHA256 { 0x00, 0xB0 }
#define GNUTLS_DHE_PSK_NULL_SHA256 { 0x00, 0xB4 }
-/* Safe renegotiation */
+/* ECC */
+#define GNUTLS_ECDH_ANON_3DES_EDE_CBC_SHA { 0xC0, 0x17 }
+#define GNUTLS_ECDH_ANON_AES_128_CBC_SHA { 0xC0, 0x18 }
+#define GNUTLS_ECDH_ANON_AES_256_CBC_SHA { 0xC0, 0x19 }
+
#define CIPHER_SUITES_COUNT sizeof(cs_algorithms)/sizeof(gnutls_cipher_suite_entry)-1
@@ -761,6 +768,19 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_ANON_DH,
GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
GNUTLS_VERSION_MAX, 1),
+/* ECC-ANON */
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_3DES_EDE_CBC_SHA,
+ GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_ANON_ECDH,
+ GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+ GNUTLS_VERSION_MAX, 1),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_AES_128_CBC_SHA,
+ GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ANON_ECDH,
+ GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+ GNUTLS_VERSION_MAX, 1),
+ GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_AES_256_CBC_SHA,
+ GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ANON_ECDH,
+ GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+ GNUTLS_VERSION_MAX, 1),
{0, {{0, 0}}, 0, 0, 0, 0, 0, 0}
};
@@ -2174,6 +2194,109 @@ _gnutls_sign_to_tls_aid (gnutls_sign_algorithm_t sign)
return ret;
}
+/* ECC curves;
+ */
+
+static const gnutls_ecc_curve_entry_st ecc_curves[] = {
+ {
+ .name = "SECP256R1",
+ .id = GNUTLS_ECC_CURVE_SECP256R1,
+ .size = 32,
+ .prime = "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+ .B = "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
+ .order = "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+ .Gx = "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
+ .Gy = "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
+ },
+ {
+ .name = "SECP384R1",
+ .id = GNUTLS_ECC_CURVE_SECP384R1,
+ .size = 48,
+ .prime = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+ .B = "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+ .order = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+ .Gx = "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
+ .Gy = "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"
+ },
+ {0, 0, 0}
+};
+
+#define GNUTLS_ECC_CURVE_LOOP(b) \
+ { const gnutls_ecc_curve_entry_st *p; \
+ for(p = ecc_curves; p->name != NULL; p++) { b ; } }
+
+/*-
+ * _gnutls_ecc_curve_get_name:
+ * @curve: is an ECC curve
+ *
+ * Convert a #ecc_curve_t value to a string.
+ *
+ * Returns: a string that contains the name of the specified
+ * curve or %NULL.
+ -*/
+const char *
+_gnutls_ecc_curve_get_name (ecc_curve_t curve)
+{
+ const char *ret = NULL;
+
+ GNUTLS_ECC_CURVE_LOOP(
+ if (p->id == curve)
+ {
+ ret = p->name;
+ break;
+ }
+ );
+
+ return ret;
+}
+
+/*-
+ * _gnutls_ecc_curve_get_params:
+ * @curve: is an ECC curve
+ *
+ * Returns the information on a curve.
+ *
+ * Returns: a pointer to #gnutls_ecc_curve_entry_st or %NULL.
+ -*/
+const gnutls_ecc_curve_entry_st *
+_gnutls_ecc_curve_get_params (ecc_curve_t curve)
+{
+ const gnutls_ecc_curve_entry_st *ret = NULL;
+
+ GNUTLS_ECC_CURVE_LOOP(
+ if (p->id == curve)
+ {
+ ret = p;
+ break;
+ }
+ );
+
+ return ret;
+}
+
+/*-
+ * _gnutls_ecc_curve_get_size:
+ * @curve: is an ECC curve
+ *
+ * Returns the size in bytes of the curve.
+ *
+ * Returns: a the size or zero.
+ -*/
+int _gnutls_ecc_curve_get_size (ecc_curve_t curve)
+{
+ int ret = 0;
+
+ GNUTLS_ECC_CURVE_LOOP(
+ if (p->id == curve)
+ {
+ ret = p->size;
+ break;
+ }
+ );
+
+ return ret;
+}
+
/* pk algorithms;
@@ -2197,6 +2320,7 @@ static const gnutls_pk_entry pk_algorithms[] = {
{"DSA", PK_DSA_OID, GNUTLS_PK_DSA},
{"GOST R 34.10-2001", PK_GOST_R3410_2001_OID, GNUTLS_PK_UNKNOWN},
{"GOST R 34.10-94", PK_GOST_R3410_94_OID, GNUTLS_PK_UNKNOWN},
+ {"ECDH", "1.2.840.10045.2.1", GNUTLS_PK_ECDH},
{0, 0, 0}
};
diff --git a/lib/gnutls_algorithms.h b/lib/gnutls_algorithms.h
index 5c867b8dc6..049c1e218a 100644
--- a/lib/gnutls_algorithms.h
+++ b/lib/gnutls_algorithms.h
@@ -125,4 +125,28 @@ int _gnutls_kx_priority (gnutls_session_t session,
unsigned int _gnutls_pk_bits_to_subgroup_bits (unsigned int pk_bits);
+/* ECC */
+struct gnutls_ecc_curve_entry_st
+{
+ const char *name;
+ ecc_curve_t id;
+ int size; /* the size in bytes */
+
+ /** The prime that defines the field the curve is in (encoded in hex) */
+ const char *prime;
+ /** The fields B param (hex) */
+ const char *B;
+ /** The order of the curve (hex) */
+ const char *order;
+ /** The x co-ordinate of the base point on the curve (hex) */
+ const char *Gx;
+ /** The y co-ordinate of the base point on the curve (hex) */
+ const char *Gy;
+};
+typedef struct gnutls_ecc_curve_entry_st gnutls_ecc_curve_entry_st;
+
+const char * _gnutls_ecc_curve_get_name (ecc_curve_t curve);
+const gnutls_ecc_curve_entry_st * _gnutls_ecc_curve_get_params (ecc_curve_t curve);
+int _gnutls_ecc_curve_get_size (ecc_curve_t curve);
+
#endif
diff --git a/lib/gnutls_dh.c b/lib/gnutls_dh.c
index 2c6a6c32a2..0badeece14 100644
--- a/lib/gnutls_dh.c
+++ b/lib/gnutls_dh.c
@@ -147,3 +147,4 @@ _gnutls_get_dh_params (gnutls_dh_params_t dh_params,
return session->internals.params.dh_params;
}
+
diff --git a/lib/gnutls_ecc.c b/lib/gnutls_ecc.c
new file mode 100644
index 0000000000..c15600836c
--- /dev/null
+++ b/lib/gnutls_ecc.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Helper functions for ECC handling
+ * based on public domain code by Tom St. Dennis.
+ */
+#include <gnutls_int.h>
+#include <gnutls_mpi.h>
+#include <gnutls_ecc.h>
+#include <gnutls_algorithms.h>
+#include <gnutls_errors.h>
+
+int _gnutls_ecc_ansi_x963_export(ecc_curve_t curve, bigint_t x, bigint_t y, gnutls_datum_t * out)
+{
+ int numlen = _gnutls_ecc_curve_get_size(curve);
+ int byte_size, ret;
+ size_t size;
+
+ if (numlen == 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ out->size = 1 + 2*numlen;
+
+ out->data = gnutls_malloc(out->size);
+ if (out->data == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ memset(out->data, 0, out->size);
+
+ /* store byte 0x04 */
+ out->data[0] = 0x04;
+
+ /* pad and store x */
+ byte_size = (_gnutls_mpi_get_nbits(x)+7)/8;
+ size = out->size - (1+(numlen-byte_size));
+ ret = _gnutls_mpi_print(x, &out->data[1+(numlen-byte_size)], &size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ byte_size = (_gnutls_mpi_get_nbits(y)+7)/8;
+ size = out->size - (1+(numlen+numlen-byte_size));
+ ret = _gnutls_mpi_print(y, &out->data[1+numlen+numlen-byte_size], &size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ /* pad and store y */
+ return 0;
+}
+
+
+int _gnutls_ecc_ansi_x963_import(ecc_curve_t curve, const opaque *in, unsigned long inlen, bigint_t* x, bigint_t* y)
+{
+ int ret;
+ int numlen = _gnutls_ecc_curve_get_size(curve);
+
+ /* must be odd */
+ if ((inlen & 1) == 0 || numlen == 0)
+ {
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* check for 4, 6 or 7 */
+ if (in[0] != 4 && in[0] != 6 && in[0] != 7) {
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+ }
+
+ /* read data */
+ ret = _gnutls_mpi_scan(x, in+1, (inlen-1)>>1);
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ ret = _gnutls_mpi_scan(y, in+1+((inlen-1)>>1), (inlen-1)>>1);
+ if (ret < 0)
+ {
+ _gnutls_mpi_release(x);
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ }
+
+ return 0;
+}
diff --git a/lib/gnutls_ecc.h b/lib/gnutls_ecc.h
new file mode 100644
index 0000000000..5f91ac5800
--- /dev/null
+++ b/lib/gnutls_ecc.h
@@ -0,0 +1,2 @@
+int _gnutls_ecc_ansi_x963_import(ecc_curve_t curve, const opaque *in, unsigned long inlen, bigint_t* x, bigint_t* y);
+int _gnutls_ecc_ansi_x963_export(ecc_curve_t curve, bigint_t x, bigint_t y, gnutls_datum_t * out);
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index c5405694d1..9f700b7e08 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -328,6 +328,8 @@ static const gnutls_error_entry error_algorithms[] = {
GNUTLS_E_TIMEDOUT, 1),
ERROR_ENTRY (N_("The operation was cancelled due to user error"),
GNUTLS_E_USER_ERROR, 1),
+ ERROR_ENTRY (N_("No supported ECC curves were found"),
+ GNUTLS_E_ECC_NO_SUPPORTED_CURVES, 1),
{NULL, NULL, 0, 0}
};
diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c
index 5f2116729a..215685154b 100644
--- a/lib/gnutls_extensions.c
+++ b/lib/gnutls_extensions.c
@@ -39,6 +39,7 @@
#include <ext/safe_renegotiation.h>
#include <ext/signature.h>
#include <ext/safe_renegotiation.h>
+#include <ext/ecc.h>
#include <gnutls_num.h>
@@ -334,6 +335,14 @@ _gnutls_ext_init (void)
if (ret != GNUTLS_E_SUCCESS)
return ret;
+ ret = _gnutls_ext_register (&ext_mod_supported_ecc);
+ if (ret != GNUTLS_E_SUCCESS)
+ return ret;
+
+ ret = _gnutls_ext_register (&ext_mod_supported_ecc_pf);
+ if (ret != GNUTLS_E_SUCCESS)
+ return ret;
+
ret = _gnutls_ext_register (&ext_mod_sig);
if (ret != GNUTLS_E_SUCCESS)
return ret;
diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c
index c69adcf74d..0499002b68 100644
--- a/lib/gnutls_global.c
+++ b/lib/gnutls_global.c
@@ -186,6 +186,7 @@ static int _gnutls_init = 0;
* Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
* otherwise an error code is returned.
**/
+int ecc_test(void);
int
gnutls_global_init (void)
{
@@ -194,6 +195,10 @@ gnutls_global_init (void)
if (_gnutls_init++)
goto out;
+
+ res = ecc_test();
+ if (res != 0)
+ exit(1);
if (gl_sockets_startup (SOCKETS_1_1))
return GNUTLS_E_LIBRARY_VERSION_MISMATCH;
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index ab9776ec92..d67bddb0b3 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -217,6 +217,8 @@ typedef enum extensions_t
GNUTLS_EXTENSION_SERVER_NAME = 0,
GNUTLS_EXTENSION_MAX_RECORD_SIZE = 1,
GNUTLS_EXTENSION_CERT_TYPE = 9,
+ GNUTLS_EXTENSION_SUPPORTED_ECC = 10,
+ GNUTLS_EXTENSION_SUPPORTED_ECC_PF = 11,
GNUTLS_EXTENSION_SRP = 12,
GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS = 13,
GNUTLS_EXTENSION_SESSION_TICKET = 35,
@@ -224,6 +226,13 @@ typedef enum extensions_t
} extensions_t;
typedef enum
+{
+ GNUTLS_ECC_CURVE_INVALID=0,
+ GNUTLS_ECC_CURVE_SECP256R1,
+ GNUTLS_ECC_CURVE_SECP384R1,
+} ecc_curve_t;
+
+typedef enum
{ CIPHER_STREAM, CIPHER_BLOCK } cipher_type_t;
#define RESUME_TRUE 0
@@ -339,6 +348,11 @@ typedef struct auth_cred_st
struct gnutls_key_st
{
+ /* For ECDH KX */
+ gnutls_pk_params_st ecdh_params;
+ bigint_t ecdh_x;
+ bigint_t ecdh_y;
+
/* For DH KX */
gnutls_datum_t key;
bigint_t KEY;
@@ -470,6 +484,7 @@ typedef struct
uint16_t max_record_recv_size;
/* holds the negotiated certificate type */
gnutls_certificate_type_t cert_type;
+ ecc_curve_t ecc_curve; /* holds the first supported ECC curve requested by client */
gnutls_protocol_t version; /* moved here */
/* FIXME: The following are not saved in the session storage
@@ -543,6 +558,7 @@ struct gnutls_priority_st
priority_st protocol;
priority_st cert_type;
priority_st sign_algo;
+ priority_st supported_ecc;
/* to disable record padding */
int no_padding:1;
diff --git a/lib/gnutls_pk.c b/lib/gnutls_pk.c
index f6284fd1c4..5fc3aa216f 100644
--- a/lib/gnutls_pk.c
+++ b/lib/gnutls_pk.c
@@ -531,7 +531,7 @@ _generate_params (int algo, bigint_t * resarr, unsigned int *resarr_len,
int ret;
unsigned int i;
- ret = _gnutls_pk_ops.generate (algo, bits, &params);
+ ret = _gnutls_pk_generate (algo, bits, &params);
if (ret < 0)
{
diff --git a/lib/gnutls_pk.h b/lib/gnutls_pk.h
index f9b5174d56..07a1acd7e9 100644
--- a/lib/gnutls_pk.h
+++ b/lib/gnutls_pk.h
@@ -33,6 +33,8 @@ extern gnutls_crypto_pk_st _gnutls_pk_ops;
#define _gnutls_pk_decrypt( algo, ciphertext, plaintext, params) _gnutls_pk_ops.decrypt( algo, ciphertext, plaintext, params)
#define _gnutls_pk_sign( algo, sig, data, params) _gnutls_pk_ops.sign( algo, sig, data, params)
#define _gnutls_pk_verify( algo, data, sig, params) _gnutls_pk_ops.verify( algo, data, sig, params)
+#define _gnutls_pk_derive( algo, out, pub, priv) _gnutls_pk_ops.derive( algo, out, pub, priv)
+#define _gnutls_pk_generate( algo, bits, priv) _gnutls_pk_ops.generate( algo, bits, priv)
inline static int
_gnutls_pk_fixup (gnutls_pk_algorithm_t algo, gnutls_direction_t direction,
diff --git a/lib/gnutls_priority.c b/lib/gnutls_priority.c
index ec3dee3a4c..c06a22dc28 100644
--- a/lib/gnutls_priority.c
+++ b/lib/gnutls_priority.c
@@ -215,6 +215,12 @@ gnutls_certificate_type_set_priority (gnutls_session_t session,
#endif
}
+static const int supported_ecc_default[] = {
+ GNUTLS_ECC_CURVE_SECP256R1,
+ GNUTLS_ECC_CURVE_SECP384R1,
+ 0
+};
+
static const int protocol_priority[] = {
GNUTLS_TLS1_2,
GNUTLS_TLS1_1,
@@ -570,10 +576,12 @@ gnutls_priority_init (gnutls_priority_t * priority_cache,
_set_priority (&(*priority_cache)->compression, comp_priority);
_set_priority (&(*priority_cache)->cert_type, cert_type_priority);
_set_priority (&(*priority_cache)->sign_algo, sign_priority_default);
+ _set_priority (&(*priority_cache)->supported_ecc, supported_ecc_default);
i = 0;
}
else
{
+ _set_priority (&(*priority_cache)->supported_ecc, supported_ecc_default);
i = 1;
}
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
index a8111ba7a7..ab4d9d0793 100644
--- a/lib/gnutls_state.c
+++ b/lib/gnutls_state.c
@@ -65,6 +65,14 @@ _gnutls_session_cert_type_set (gnutls_session_t session,
session->security_parameters.cert_type = ct;
}
+void
+_gnutls_session_ecc_curve_set (gnutls_session_t session,
+ ecc_curve_t c)
+{
+ _gnutls_handshake_log("HSK[%p]: Selected ECC curve (%d)\n", session, c);
+ session->security_parameters.ecc_curve = c;
+}
+
/**
* gnutls_cipher_get:
* @session: is a #gnutls_session_t structure.
@@ -443,6 +451,10 @@ gnutls_deinit (gnutls_session_t session)
if (session->key != NULL)
{
+ gnutls_pk_params_release(&session->key->ecdh_params);
+ _gnutls_mpi_release (&session->key->ecdh_x);
+ _gnutls_mpi_release (&session->key->ecdh_y);
+
_gnutls_mpi_release (&session->key->KEY);
_gnutls_mpi_release (&session->key->client_Y);
_gnutls_mpi_release (&session->key->client_p);
diff --git a/lib/gnutls_state.h b/lib/gnutls_state.h
index 8132a2ffcd..edd4b0dab1 100644
--- a/lib/gnutls_state.h
+++ b/lib/gnutls_state.h
@@ -30,6 +30,16 @@
void _gnutls_session_cert_type_set (gnutls_session_t session,
gnutls_certificate_type_t);
+
+inline static ecc_curve_t _gnutls_session_ecc_curve_get(gnutls_session_t session)
+{
+ return session->security_parameters.ecc_curve;
+}
+
+void
+_gnutls_session_ecc_curve_set (gnutls_session_t session,
+ ecc_curve_t c);
+
void
_gnutls_record_set_default_version (gnutls_session_t session,
unsigned char major, unsigned char minor);
diff --git a/lib/includes/gnutls/crypto.h b/lib/includes/gnutls/crypto.h
index a1cf4b5ba8..0f37a6def0 100644
--- a/lib/includes/gnutls/crypto.h
+++ b/lib/includes/gnutls/crypto.h
@@ -278,6 +278,16 @@ extern "C"
* [2] is g
* [3] is y (public key)
* [4] is x (private key only)
+ *
+ * ECDH:
+ * [0] is prime
+ * [1] is order
+ * [2] is Gx
+ * [3] is Gy
+ * [4] is x
+ * [5] is y
+ * [6] is z
+ * [7] is k (private key)
*/
/**
@@ -311,7 +321,6 @@ extern "C"
int (*verify) (gnutls_pk_algorithm_t, const gnutls_datum_t * data,
const gnutls_datum_t * signature,
const gnutls_pk_params_st * pub);
-
int (*generate) (gnutls_pk_algorithm_t, unsigned int nbits,
gnutls_pk_params_st *);
/* this function should convert params to ones suitable
@@ -319,6 +328,10 @@ extern "C"
*/
int (*pk_fixup_private_params) (gnutls_pk_algorithm_t, gnutls_direction_t,
gnutls_pk_params_st *);
+ int (*derive) (gnutls_pk_algorithm_t, gnutls_datum_t * out,
+ const gnutls_pk_params_st * priv,
+ const gnutls_pk_params_st * pub);
+
} gnutls_crypto_pk_st;
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index f85b6b397b..053970f3b4 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -129,6 +129,7 @@ extern "C"
* @GNUTLS_KX_DHE_DSS: DHE-DSS key-exchange algorithm.
* @GNUTLS_KX_DHE_RSA: DHE-RSA key-exchange algorithm.
* @GNUTLS_KX_ANON_DH: Anon-DH key-exchange algorithm.
+ * @GNUTLS_KX_ANON_ECDH: Anon-ECDH key-exchange algorithm.
* @GNUTLS_KX_SRP: SRP key-exchange algorithm.
* @GNUTLS_KX_RSA_EXPORT: RSA-EXPORT key-exchange algorithm.
* @GNUTLS_KX_SRP_RSA: SRP-RSA key-exchange algorithm.
@@ -150,7 +151,8 @@ extern "C"
GNUTLS_KX_SRP_RSA = 7,
GNUTLS_KX_SRP_DSS = 8,
GNUTLS_KX_PSK = 9,
- GNUTLS_KX_DHE_PSK = 10
+ GNUTLS_KX_DHE_PSK = 10,
+ GNUTLS_KX_ANON_ECDH = 11,
} gnutls_kx_algorithm_t;
/**
@@ -163,7 +165,8 @@ extern "C"
typedef enum
{
GNUTLS_PARAMS_RSA_EXPORT = 1,
- GNUTLS_PARAMS_DH = 2
+ GNUTLS_PARAMS_DH = 2,
+ GNUTLS_PARAMS_ECDH = 3,
} gnutls_params_type_t;
/**
@@ -554,6 +557,7 @@ extern "C"
* @GNUTLS_PK_RSA: RSA public-key algorithm.
* @GNUTLS_PK_DSA: DSA public-key algorithm.
* @GNUTLS_PK_DH: Diffie-Hellman algorithm. Used to generate parameters.
+ * @GNUTLS_PK_ECDH: Elliptic curve Diffie-Hellman algorithm. Used to generate parameters.
*
* Enumeration of different public-key algorithms.
*/
@@ -562,7 +566,8 @@ extern "C"
GNUTLS_PK_UNKNOWN = 0,
GNUTLS_PK_RSA = 1,
GNUTLS_PK_DSA = 2,
- GNUTLS_PK_DH = 3
+ GNUTLS_PK_DH = 3,
+ GNUTLS_PK_ECDH = 4,
} gnutls_pk_algorithm_t;
const char *gnutls_pk_algorithm_get_name (gnutls_pk_algorithm_t algorithm);
@@ -647,6 +652,9 @@ extern "C"
struct gnutls_dh_params_int;
typedef struct gnutls_dh_params_int *gnutls_dh_params_t;
+ struct gnutls_ecdh_params_int;
+ typedef struct gnutls_ecdh_params_int *gnutls_ecdh_params_t;
+
/* XXX ugly. */
struct gnutls_x509_privkey_int;
typedef struct gnutls_x509_privkey_int *gnutls_rsa_params_t;
@@ -667,6 +675,7 @@ extern "C"
union params
{
gnutls_dh_params_t dh;
+ gnutls_ecdh_params_t ecdh;
gnutls_rsa_params_t rsa_export;
} params;
int deinit;
@@ -1750,6 +1759,7 @@ extern "C"
#define GNUTLS_E_CRYPTO_INIT_FAILED -318
#define GNUTLS_E_TIMEDOUT -319
#define GNUTLS_E_USER_ERROR -320
+#define GNUTLS_E_ECC_NO_SUPPORTED_CURVES -321
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250
diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am
index e902e774d5..0516800762 100644
--- a/lib/nettle/Makefile.am
+++ b/lib/nettle/Makefile.am
@@ -34,4 +34,9 @@ endif
noinst_LTLIBRARIES = libcrypto.la
-libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c rnd.c init.c egd.c egd.h
+libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c rnd.c init.c egd.c egd.h \
+ multi.c ecc_free.c ecc.h ecc_make_key.c ecc_shared_secret.c \
+ ecc_test.c ltc_ecc_map.c \
+ ltc_ecc_mulmod.c ltc_ecc_points.c \
+ ltc_ecc_projective_add_point.c ltc_ecc_projective_dbl_point.c \
+ mp_unsigned_bin.c ecc_sign_hash.c ecc_verify_hash.c
diff --git a/lib/nettle/ecc.h b/lib/nettle/ecc.h
new file mode 100644
index 0000000000..0ba3b0b08c
--- /dev/null
+++ b/lib/nettle/ecc.h
@@ -0,0 +1,123 @@
+#include <gmp.h>
+#include <nettle/nettle-types.h>
+#include <nettle/dsa.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#define LTC_MECC
+#define ECC256
+
+#define PK_PRIVATE 1
+#define PK_PUBLIC 2
+
+/* ---- ECC Routines ---- */
+/* size of our temp buffers for exported keys */
+#define ECC_BUF_SIZE 512
+
+/* max private key size */
+#define ECC_MAXSIZE 66
+
+/** Structure defines a NIST GF(p) curve */
+typedef struct {
+ /** The size of the curve in octets */
+ int size;
+
+ /** name of curve */
+ const char *name;
+
+ /** The prime that defines the field the curve is in (encoded in hex) */
+ const char *prime;
+
+ /** The fields B param (hex) */
+ const char *B;
+
+ /** The order of the curve (hex) */
+ const char *order;
+
+ /** The x co-ordinate of the base point on the curve (hex) */
+ const char *Gx;
+
+ /** The y co-ordinate of the base point on the curve (hex) */
+ const char *Gy;
+} ltc_ecc_set_type;
+
+/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */
+typedef struct {
+ /** The x co-ordinate */
+ mpz_t x;
+
+ /** The y co-ordinate */
+ mpz_t y;
+
+ /** The z co-ordinate */
+ mpz_t z;
+} ecc_point;
+
+/** An ECC key */
+typedef struct {
+ /** Type of key, PK_PRIVATE or PK_PUBLIC */
+ int type;
+
+ mpz_t prime;
+ mpz_t order;
+ mpz_t Gx;
+ mpz_t Gy;
+
+ /** The public key */
+ ecc_point pubkey;
+
+ /** The private key */
+ mpz_t k;
+} ecc_key;
+
+/** the ECC params provided */
+extern const ltc_ecc_set_type ltc_ecc_sets[];
+
+int ecc_test(void);
+void ecc_sizes(int *low, int *high);
+int ecc_get_size(ecc_key *key);
+
+int ecc_make_key(void *random_ctx, nettle_random_func random, ecc_key *key, const ltc_ecc_set_type *dp);
+int ecc_make_key_ex(void *random_ctx, nettle_random_func random, ecc_key *key, mpz_t prime, mpz_t order, mpz_t Gx, mpz_t Gy);
+void ecc_free(ecc_key *key);
+
+int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
+ unsigned char *out, unsigned long *outlen);
+
+int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
+ struct dsa_signature *signature,
+ void *random_ctx, nettle_random_func random, ecc_key *key);
+
+int ecc_verify_hash(struct dsa_signature * signature,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, ecc_key *key);
+
+/* low level functions */
+ecc_point *ltc_ecc_new_point(void);
+void ltc_ecc_del_point(ecc_point *p);
+int ltc_ecc_is_valid_idx(int n);
+
+/* point ops (mp == montgomery digit) */
+/* R = 2P */
+int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mpz_t modulus);
+
+/* R = P + Q */
+int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mpz_t modulus);
+
+/* R = kG */
+int ltc_ecc_mulmod(mpz_t k, ecc_point *G, ecc_point *R, mpz_t modulus, int map);
+
+/* map P to affine from projective */
+int ltc_ecc_map(ecc_point *P, mpz_t modulus);
+
+/* helper functions */
+int mp_init_multi(mpz_t *a, ...);
+void mp_clear_multi(mpz_t *a, ...);
+unsigned long mp_unsigned_bin_size(mpz_t a);
+int mp_to_unsigned_bin(mpz_t a, unsigned char *b);
+int mp_read_unsigned_bin(mpz_t a, unsigned char *b, unsigned long len);
+#define mp_isodd(a) (mpz_size(a) > 0 ? (mpz_getlimbn(a, 0) & 1 ? 1 : 0) : 0)
+
+#define MP_DIGIT_BIT (sizeof(mp_limb_t) * 8 - GMP_NAIL_BITS)
diff --git a/lib/nettle/ecc_free.c b/lib/nettle/ecc_free.c
new file mode 100644
index 0000000000..7cc9774db2
--- /dev/null
+++ b/lib/nettle/ecc_free.c
@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ecc_free.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Free an ECC key from memory
+ @param key The key you wish to free
+*/
+void ecc_free(ecc_key *key)
+{
+ assert(key != NULL);
+ mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &key->prime, &key->order, &key->Gx, &key->Gy, NULL);
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_free.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ecc_make_key.c b/lib/nettle/ecc_make_key.c
new file mode 100644
index 0000000000..3ca757115a
--- /dev/null
+++ b/lib/nettle/ecc_make_key.c
@@ -0,0 +1,125 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ecc_make_key.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Make a new ECC key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param keysize The keysize for the new key (in octets from 20 to 65 bytes)
+ @param key [out] Destination of the newly created key
+ @return 0 if successful, upon error all allocated memory will be freed
+*/
+
+int ecc_make_key_ex(void *random_ctx, nettle_random_func random, ecc_key *key, mpz_t prime, mpz_t order, mpz_t Gx, mpz_t Gy)
+{
+ int err;
+ ecc_point *base;
+ unsigned char *buf;
+ int keysize;
+
+ assert(key != NULL);
+ assert(random != NULL);
+
+ keysize = mp_unsigned_bin_size(order);
+
+ /* allocate ram */
+ base = NULL;
+ buf = malloc(keysize);
+ if (buf == NULL) {
+ return -1;
+ }
+
+ /* make up random string */
+ random(random_ctx, keysize, buf);
+
+ /* setup the key variables */
+ if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &key->prime, &key->order, &key->Gx, &key->Gy, NULL)) != 0) {
+ goto ERR_BUF;
+ }
+ base = ltc_ecc_new_point();
+ if (base == NULL) {
+ err = -1;
+ goto errkey;
+ }
+
+ /* read in the specs for this key */
+ mpz_set(key->prime, prime);
+ mpz_set(key->order, order);
+ mpz_set(key->Gx, Gx);
+ mpz_set(key->Gy, Gy);
+
+ mpz_set(base->x, key->Gx);
+ mpz_set(base->y, key->Gy);
+ mpz_set_ui(base->z, 1);
+ if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buf, keysize)) != 0) { goto errkey; }
+
+ /* the key should be smaller than the order of base point */
+ if (mpz_cmp(key->k, key->order) >= 0) {
+ mpz_mod(key->k, key->k, key->order);
+ }
+ /* make the public key */
+ if ((err = ltc_ecc_mulmod(key->k, base, &key->pubkey, key->prime, 1)) != 0) { goto errkey; }
+ key->type = PK_PRIVATE;
+
+ /* free up ram */
+ err = 0;
+ goto cleanup;
+errkey:
+ mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &key->order, &key->prime, &key->Gx, &key->Gy, NULL);
+cleanup:
+ ltc_ecc_del_point(base);
+ERR_BUF:
+ free(buf);
+ return err;
+}
+
+int ecc_make_key(void *random_ctx, nettle_random_func random, ecc_key *key, const ltc_ecc_set_type *dp)
+{
+ mpz_t prime, order, Gx, Gy;
+ int err;
+
+ /* setup the key variables */
+ if ((err = mp_init_multi(&prime, &order, &Gx, &Gy, NULL)) != 0) {
+ goto cleanup;
+ }
+
+ /* read in the specs for this key */
+ mpz_set_str(prime, (char *)dp->prime, 16);
+ mpz_set_str(order, (char *)dp->order, 16);
+ mpz_set_str(Gx, (char *)dp->Gx, 16);
+ mpz_set_str(Gy, (char *)dp->Gy, 16);
+
+ err = ecc_make_key_ex(random_ctx, random, key, prime, order, Gx, Gy);
+
+ mp_clear_multi(&prime, &order, &Gx, &Gy, NULL);
+cleanup:
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_make_key.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ecc_shared_secret.c b/lib/nettle/ecc_shared_secret.c
new file mode 100644
index 0000000000..a3eb46a868
--- /dev/null
+++ b/lib/nettle/ecc_shared_secret.c
@@ -0,0 +1,80 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+#include <string.h>
+
+/**
+ @file ecc_shared_secret.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Create an ECC shared secret between two keys
+ @param private_key The private ECC key
+ @param public_key The public key
+ @param out [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63)
+ @param outlen [in/out] The max size and resulting size of the shared secret
+ @return 0 if successful
+*/
+int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x;
+ ecc_point *result;
+ int err;
+
+ assert(private_key != NULL);
+ assert(public_key != NULL);
+ assert(out != NULL);
+ assert(outlen != NULL);
+
+ /* type valid? */
+ if (private_key->type != PK_PRIVATE) {
+ return -1;
+ }
+
+ /* make new point */
+ result = ltc_ecc_new_point();
+ if (result == NULL) {
+ return -1;
+ }
+
+ if ((err = ltc_ecc_mulmod(private_key->k, &public_key->pubkey, result, private_key->prime, 1)) != 0) { goto done; }
+
+ x = (unsigned long)mp_unsigned_bin_size(private_key->prime);
+ if (*outlen < x) {
+ *outlen = x;
+ err = -1;
+ goto done;
+ }
+ memset(out, 0, x);
+ if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != 0) { goto done; }
+
+ err = 0;
+ *outlen = x;
+done:
+ ltc_ecc_del_point(result);
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_shared_secret.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ecc_sign_hash.c b/lib/nettle/ecc_sign_hash.c
new file mode 100644
index 0000000000..b2da7f22c6
--- /dev/null
+++ b/lib/nettle/ecc_sign_hash.c
@@ -0,0 +1,103 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+#include <nettle/dsa.h>
+
+/**
+ @file ecc_sign_hash.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Sign a message digest
+ @param in The message digest to sign
+ @param inlen The length of the digest
+ @param signature The destination for the signature
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param key A private ECC key
+ @return 0 if successful
+*/
+int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
+ struct dsa_signature *signature,
+ void *random_ctx, nettle_random_func random, ecc_key *key)
+{
+ ecc_key pubkey;
+ mpz_t r, s, e;
+ int err;
+
+ assert(in != NULL);
+ assert(signature != NULL);
+ assert(key != NULL);
+
+ /* is this a private key? */
+ if (key->type != PK_PRIVATE) {
+ return -1;
+ }
+
+ /* get the hash and load it as a bignum into 'e' */
+ /* init the bignums */
+ if ((err = mp_init_multi(&r, &s, &e, NULL)) != 0) {
+ return err;
+ }
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, (int)inlen)) != 0) { goto errnokey; }
+
+ /* make up a key and export the public copy */
+ for (;;) {
+ if ((err = ecc_make_key_ex(random_ctx, random, &pubkey, key->prime, key->order, key->Gx, key->Gy)) != 0) {
+ goto errnokey;
+ }
+
+ /* find r = x1 mod n */
+ mpz_mod(r, pubkey.pubkey.x, pubkey.order);
+
+ if (mpz_cmp_ui(r, 0) == 0) {
+ ecc_free(&pubkey);
+ } else {
+ /* find s = (e + xr)/k */
+ mpz_invert(pubkey.k, pubkey.k, pubkey.order);
+
+ /* mulmod */
+ mpz_mul(s, key->k, r);
+ mpz_mod(s, s, pubkey.order);
+ mpz_add(s, e, s);
+ mpz_mod(s, s, pubkey.order);
+
+ mpz_mul(s, s, pubkey.k);
+ mpz_mod(s, s, pubkey.order);
+ ecc_free(&pubkey);
+ if (mpz_cmp_ui(s,0) != 0) {
+ break;
+ }
+ }
+ }
+
+ memcpy(&signature->r, &r, sizeof(signature->r));
+ memcpy(&signature->s, &s, sizeof(signature->s));
+
+errnokey:
+ mp_clear_multi(&e, NULL);
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_sign_hash.c,v $ */
+/* $Revision: 1.11 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ecc_test.c b/lib/nettle/ecc_test.c
new file mode 100644
index 0000000000..4c74a9f7a6
--- /dev/null
+++ b/lib/nettle/ecc_test.c
@@ -0,0 +1,125 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+#include "gnettle.h"
+#include <gnutls_int.h>
+#include <gnutls_algorithms.h>
+
+/**
+ @file ecc_test.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Perform on the ECC system
+ @return 0 if successful
+*/
+int ecc_test(void)
+{
+ mpz_t modulus, order;
+ ecc_point *G, *GG;
+ int i, err;
+
+ if ((err = mp_init_multi(&modulus, &order, NULL)) != 0) {
+ return err;
+ }
+
+ G = ltc_ecc_new_point();
+ GG = ltc_ecc_new_point();
+ if (G == NULL || GG == NULL) {
+ mp_clear_multi(&modulus,&order, NULL);
+ ltc_ecc_del_point(G);
+ ltc_ecc_del_point(GG);
+ return -1;
+ }
+
+ for (i = 1; i<=2; i++) {
+ const gnutls_ecc_curve_entry_st *st = _gnutls_ecc_curve_get_params (i);
+
+ printf("Testing %s (%d)\n", _gnutls_ecc_curve_get_name(i), i);
+
+ if (mpz_set_str(modulus, (char *)st->prime, 16) != 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ if (mpz_set_str(order, (char *)st->order, 16) != 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ /* is prime actually prime? */
+ if ((err = mpz_probab_prime_p(modulus, PRIME_CHECK_PARAM)) <= 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ if ((err = mpz_probab_prime_p(order, PRIME_CHECK_PARAM)) <= 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ if (mpz_set_str(G->x, (char *)st->Gx, 16) != 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ if (mpz_set_str(G->y, (char *)st->Gy, 16) != 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+ mpz_set_ui(G->z, 1);
+
+ /* then we should have G == (order + 1)G */
+ mpz_add_ui(order, order, 1);
+ if ((err = ltc_ecc_mulmod(order, G, GG, modulus, 1)) != 0) { goto done; }
+
+ if (mpz_cmp(G->y, GG->y) != 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ if (mpz_cmp(G->x, GG->x) != 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ }
+ err = 0;
+done:
+ ltc_ecc_del_point(GG);
+ ltc_ecc_del_point(G);
+ mp_clear_multi(&order, &modulus, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_test.c,v $ */
+/* $Revision: 1.12 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ecc_verify_hash.c b/lib/nettle/ecc_verify_hash.c
new file mode 100644
index 0000000000..71315f3795
--- /dev/null
+++ b/lib/nettle/ecc_verify_hash.c
@@ -0,0 +1,135 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ecc_verify_hash.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/* verify
+ *
+ * w = s^-1 mod n
+ * u1 = xw
+ * u2 = rw
+ * X = u1*G + u2*Q
+ * v = X_x1 mod n
+ * accept if v == r
+ */
+
+/**
+ Verify an ECC signature
+ @param signature The signature to verify
+ @param hash The hash (message digest) that was signed
+ @param hashlen The length of the hash (octets)
+ @param stat Result of signature, 1==valid, 0==invalid
+ @param key The corresponding public ECC key
+ @return 0 if successful (even if the signature is not valid)
+*/
+int ecc_verify_hash(struct dsa_signature * signature,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, ecc_key *key)
+{
+ ecc_point *mG, *mQ;
+ mpz_t v, w, u1, u2, e;
+ int err;
+
+ assert(signature != NULL);
+ assert(hash != NULL);
+ assert(stat != NULL);
+ assert(key != NULL);
+
+ /* default to invalid signature */
+ *stat = 0;
+
+ /* allocate ints */
+ if ((err = mp_init_multi(&v, &w, &u1, &u2, &e, NULL)) != 0) {
+ return -1;
+ }
+
+ /* allocate points */
+ mG = ltc_ecc_new_point();
+ mQ = ltc_ecc_new_point();
+ if (mQ == NULL || mG == NULL) {
+ err = -1;
+ goto error;
+ }
+
+ /* check for zero */
+ if (mpz_cmp_ui(signature->r,0) == 0 || mpz_cmp_ui(signature->s,0) == 0 ||
+ mpz_cmp(signature->r, key->order) >= 0 || mpz_cmp(signature->s, key->order) >= 0) {
+ err = -1;
+ goto error;
+ }
+
+ /* read hash */
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, (int)hashlen)) != 0) { goto error; }
+
+ /* w = s^-1 mod n */
+ mpz_invert(w, signature->s, key->order);
+
+ /* u1 = ew */
+ mpz_mul(u1, e, w);
+ mpz_mod(u1, u1, key->order);
+
+ /* u2 = rw */
+ mpz_mul(u2, signature->r, w);
+ mpz_mod(u2, u2, key->order);
+
+ /* find mG and mQ */
+ mpz_set(mG->x, key->Gx);
+ mpz_set(mG->y, key->Gy);
+ mpz_set_ui(mG->z, 1);
+
+ mpz_set(mQ->x, key->pubkey.x);
+ mpz_set(mQ->y, key->pubkey.y);
+ mpz_set(mQ->z, key->pubkey.z);
+
+ /* compute u1*mG + u2*mQ = mG */
+ if ((err = ltc_ecc_mulmod(u1, mG, mG, key->prime, 0)) != 0) { goto error; }
+ if ((err = ltc_ecc_mulmod(u2, mQ, mQ, key->prime, 0)) != 0) { goto error; }
+
+ /* add them */
+ if ((err = ltc_ecc_projective_add_point(mQ, mG, mG, key->prime)) != 0) { goto error; }
+
+ /* reduce */
+ if ((err = ltc_ecc_map(mG, key->prime)) != 0) { goto error; }
+
+ /* v = X_x1 mod n */
+ mpz_mod(v, mG->x, key->order);
+
+ /* does v == r */
+ if (mpz_cmp(v, signature->r) == 0) {
+ *stat = 1;
+ }
+
+ /* clear up and return */
+ err = 0;
+error:
+ ltc_ecc_del_point(mG);
+ ltc_ecc_del_point(mQ);
+ mp_clear_multi(&v, &w, &u1, &u2, &e, NULL);
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_verify_hash.c,v $ */
+/* $Revision: 1.14 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/gnettle.h b/lib/nettle/gnettle.h
new file mode 100644
index 0000000000..768590c73d
--- /dev/null
+++ b/lib/nettle/gnettle.h
@@ -0,0 +1,2 @@
+#define PRIME_CHECK_PARAM 8
+
diff --git a/lib/nettle/ltc_ecc_map.c b/lib/nettle/ltc_ecc_map.c
new file mode 100644
index 0000000000..f22426009d
--- /dev/null
+++ b/lib/nettle/ltc_ecc_map.c
@@ -0,0 +1,73 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ltc_ecc_map.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Map a projective jacbobian point back to affine space
+ @param P [in/out] The point to map
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return 0 on success
+*/
+int ltc_ecc_map(ecc_point *P, mpz_t modulus)
+{
+ mpz_t t1, t2;
+ int err;
+
+ assert(P != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, NULL)) != 0) {
+ return -1;
+ }
+
+ mpz_mod(P->z, P->z, modulus);
+
+ /* get 1/z */
+ mpz_invert(t1, P->z, modulus);
+
+ /* get 1/z^2 and 1/z^3 */
+ mpz_mul(t2, t1, t1);
+ mpz_mod(t2, t2, modulus);
+ mpz_mul(t1, t1, t2);
+ mpz_mod(t1, t1, modulus);
+
+ /* multiply against x/y */
+ mpz_mul(P->x, P->x, t2);
+ mpz_mod(P->x, P->x, modulus);
+ mpz_mul(P->y, P->y, t1);
+ mpz_mod(P->y, P->y, modulus);
+ mpz_set_ui(P->z, 1);
+
+ err = 0;
+
+ mp_clear_multi(&t1, &t2, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_map.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ltc_ecc_mulmod.c b/lib/nettle/ltc_ecc_mulmod.c
new file mode 100644
index 0000000000..ab845ce014
--- /dev/null
+++ b/lib/nettle/ltc_ecc_mulmod.c
@@ -0,0 +1,141 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ltc_ecc_mulmod_timing.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Perform a point multiplication (timing resistant)
+ @param k The scalar to multiply by
+ @param G The base point
+ @param R [out] Destination for kG
+ @param modulus The modulus of the field the ECC curve is in
+ @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
+ @return 0 on success
+*/
+int ltc_ecc_mulmod(mpz_t k, ecc_point *G, ecc_point *R, mpz_t modulus, int map)
+{
+ ecc_point *tG, *M[3];
+ int i, j, err;
+ unsigned long buf;
+ int first, bitbuf, bitcpy, bitcnt, mode, digidx;
+
+ assert(k != NULL);
+ assert(G != NULL);
+ assert(R != NULL);
+ assert(modulus != NULL);
+
+ /* alloc ram for window temps */
+ for (i = 0; i < 3; i++) {
+ M[i] = ltc_ecc_new_point();
+ if (M[i] == NULL) {
+ for (j = 0; j < i; j++) {
+ ltc_ecc_del_point(M[j]);
+ }
+ return -1;
+ }
+ }
+
+ /* make a copy of G incase R==G */
+ tG = ltc_ecc_new_point();
+ if (tG == NULL) { err = -1; goto done; }
+
+ /* tG = G and convert to montgomery */
+ mpz_set(tG->x, G->x);
+ mpz_set(tG->y, G->y);
+ mpz_set(tG->z, G->z);
+
+ /* calc the M tab */
+ /* M[0] == G */
+ mpz_set(M[0]->x, tG->x);
+ mpz_set(M[0]->y, tG->y);
+ mpz_set(M[0]->z, tG->z);
+ /* M[1] == 2G */
+ if ((err = ltc_ecc_projective_dbl_point(tG, M[1], modulus)) != 0) { goto done; }
+
+ /* setup sliding window */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = mpz_size(k) - 1;
+ bitcpy = bitbuf = 0;
+ first = 1;
+
+ /* perform ops */
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ if (digidx == -1) {
+ break;
+ }
+ buf = mpz_getlimbn(k, digidx);
+ bitcnt = (int) MP_DIGIT_BIT;
+ --digidx;
+ }
+
+ /* grab the next msb from the ltiplicand */
+ i = (buf >> (MP_DIGIT_BIT - 1)) & 1;
+ buf <<= 1;
+
+ if (mode == 0 && i == 0) {
+ /* dummy operations */
+ if ((err = ltc_ecc_projective_add_point(M[0], M[1], M[2], modulus)) != 0) { goto done; }
+ if ((err = ltc_ecc_projective_dbl_point(M[1], M[2], modulus)) != 0) { goto done; }
+ continue;
+ }
+
+ if (mode == 0 && i == 1) {
+ mode = 1;
+ /* dummy operations */
+ if ((err = ltc_ecc_projective_add_point(M[0], M[1], M[2], modulus)) != 0) { goto done; }
+ if ((err = ltc_ecc_projective_dbl_point(M[1], M[2], modulus)) != 0) { goto done; }
+ continue;
+ }
+
+ if ((err = ltc_ecc_projective_add_point(M[0], M[1], M[i^1], modulus)) != 0) { goto done; }
+ if ((err = ltc_ecc_projective_dbl_point(M[i], M[i], modulus)) != 0) { goto done; }
+ }
+
+ /* copy result out */
+ mpz_set(R->x, M[0]->x);
+ mpz_set(R->y, M[0]->y);
+ mpz_set(R->z, M[0]->z);
+
+ /* map R back from projective space */
+ if (map) {
+ err = ltc_ecc_map(R, modulus);
+ } else {
+ err = 0;
+ }
+done:
+ ltc_ecc_del_point(tG);
+ for (i = 0; i < 3; i++) {
+ ltc_ecc_del_point(M[i]);
+ }
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ltc_ecc_points.c b/lib/nettle/ltc_ecc_points.c
new file mode 100644
index 0000000000..93ad85d403
--- /dev/null
+++ b/lib/nettle/ltc_ecc_points.c
@@ -0,0 +1,60 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ltc_ecc_points.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Allocate a new ECC point
+ @return A newly allocated point or NULL on error
+*/
+ecc_point *ltc_ecc_new_point(void)
+{
+ ecc_point *p;
+ p = calloc(1, sizeof(*p));
+ if (p == NULL) {
+ return NULL;
+ }
+ if (mp_init_multi(&p->x, &p->y, &p->z, NULL) != 0) {
+ free(p);
+ return NULL;
+ }
+ return p;
+}
+
+/** Free an ECC point from memory
+ @param p The point to free
+*/
+void ltc_ecc_del_point(ecc_point *p)
+{
+ /* prevents free'ing null arguments */
+ if (p != NULL) {
+ mp_clear_multi(&p->x, &p->y, &p->z, NULL); /* note: p->z may be NULL but that's ok with this function anyways */
+ free(p);
+ }
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_points.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ltc_ecc_projective_add_point.c b/lib/nettle/ltc_ecc_projective_add_point.c
new file mode 100644
index 0000000000..2b008367c6
--- /dev/null
+++ b/lib/nettle/ltc_ecc_projective_add_point.c
@@ -0,0 +1,195 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ltc_ecc_projective_add_point.c
+ ECC Crypto, Tom St Denis
+*/
+
+#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC))
+
+/**
+ Add two ECC points
+ @param P The point to add
+ @param Q The point to add
+ @param R [out] The destination of the double
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return 0 on success
+*/
+int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mpz_t modulus)
+{
+ mpz_t t1, t2, x, y, z;
+ int err;
+
+ assert(P != NULL);
+ assert(Q != NULL);
+ assert(R != NULL);
+ assert(modulus != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != 0) {
+ return err;
+ }
+
+ /* should we dbl instead? */
+ mpz_sub(t1, modulus, Q->y);
+
+ if ( (mpz_cmp(P->x, Q->x) == 0) &&
+ (Q->z != NULL && mpz_cmp(P->z, Q->z) == 0) &&
+ (mpz_cmp(P->y, Q->y) == 0 || mpz_cmp(P->y, t1) == 0)) {
+ mp_clear_multi(&t1, &t2, &x, &y, &z, NULL);
+ return ltc_ecc_projective_dbl_point(P, R, modulus);
+ }
+
+ mpz_set(x, P->x);
+ mpz_set(y, P->y);
+ mpz_set(z, P->z);
+
+ /* if Z is one then these are no-operations */
+ if (mpz_cmp_ui(Q->z, 1) != 0) {
+ /* T1 = Z' * Z' */
+ mpz_mul(t1, Q->z, Q->z);
+ mpz_mod(t1, t1, modulus);
+ /* X = X * T1 */
+ mpz_mul(x, x, t1);
+ mpz_mod(x, x, modulus);
+ /* T1 = Z' * T1 */
+ mpz_mul(t1, t1, Q->z);
+ mpz_mod(t1, t1, modulus);
+ /* Y = Y * T1 */
+ mpz_mul(y, y, t1);
+ mpz_mod(y, y, modulus);
+ }
+
+ /* T1 = Z*Z */
+ mpz_mul(t1, z, z);
+ mpz_mod(t1, t1, modulus);
+ /* T2 = X' * T1 */
+ mpz_mul(t2, t1, Q->x);
+ mpz_mod(t2, t2, modulus);
+ /* T1 = Z * T1 */
+ mpz_mul(t1, t1, z);
+ mpz_mod(t1, t1, modulus);
+ /* T1 = Y' * T1 */
+ mpz_mul(t1, t1, Q->y);
+ mpz_mod(t1, t1, modulus);
+
+ /* Y = Y - T1 */
+ mpz_sub(y, y, t1);
+ if (mpz_cmp_ui(y, 0) < 0) {
+ mpz_add(y, y, modulus);
+ }
+ /* T1 = 2T1 */
+ mpz_add(t1, t1, t1);
+ if (mpz_cmp(t1, modulus) >= 0) {
+ mpz_sub(t1, t1, modulus);
+ }
+ /* T1 = Y + T1 */
+ mpz_add(t1, t1, y);
+ if (mpz_cmp(t1, modulus) >= 0) {
+ mpz_sub(t1, t1, modulus);
+ }
+ /* X = X - T2 */
+ mpz_sub(x, x, t2);
+ if (mpz_cmp_ui(x, 0) < 0) {
+ mpz_add(x, x, modulus);
+ }
+ /* T2 = 2T2 */
+ mpz_add(t2, t2, t2);
+ if (mpz_cmp(t2, modulus) >= 0) {
+ mpz_sub(t2, t2, modulus);
+ }
+ /* T2 = X + T2 */
+ mpz_add(t2, t2, x);
+ if (mpz_cmp(t2, modulus) >= 0) {
+ mpz_sub(t2, t2, modulus);
+ }
+
+ /* if Z' != 1 */
+ if (mpz_cmp_ui(Q->z, 1) != 0) {
+ /* Z = Z * Z' */
+ mpz_mul(z, z, Q->z);
+ mpz_mod(z, z, modulus);
+ }
+
+ /* Z = Z * X */
+ mpz_mul(z, z, x);
+ mpz_mod(z, z, modulus);
+
+ /* T1 = T1 * X */
+ mpz_mul(t1, t1, x);
+ mpz_mod(t1, t1, modulus);
+ /* X = X * X */
+ mpz_mul(x, x, x);
+ mpz_mod(x, x, modulus);
+ /* T2 = T2 * x */
+ mpz_mul(t2, t2, x);
+ mpz_mod(t2, t2, modulus);
+ /* T1 = T1 * X */
+ mpz_mul(t1, t1, x);
+ mpz_mod(t1, t1, modulus);
+
+ /* X = Y*Y */
+ mpz_mul(x, y, y);
+ mpz_mod(x, x, modulus);
+ /* X = X - T2 */
+ mpz_sub(x, x, t2);
+ if (mpz_cmp_ui(x, 0) < 0) {
+ mpz_add(x, x, modulus);
+ }
+
+ /* T2 = T2 - X */
+ mpz_sub(t2, t2, x);
+ if (mpz_cmp_ui(t2, 0) < 0) {
+ mpz_add(t2, t2, modulus);
+ }
+ /* T2 = T2 - X */
+ mpz_sub(t2, t2, x);
+ if (mpz_cmp_ui(t2, 0) < 0) {
+ mpz_add(t2, t2, modulus);
+ }
+ /* T2 = T2 * Y */
+ mpz_mul(t2, t2, y);
+ mpz_mod(t2, t2, modulus);
+ /* Y = T2 - T1 */
+ mpz_sub(y, t2, t1);
+ if (mpz_cmp_ui(y, 0) < 0) {
+ mpz_add(y, y, modulus);
+ }
+ /* Y = Y/2 */
+ if (mp_isodd(y)) {
+ mpz_add(y, y, modulus);
+ }
+ mpz_divexact_ui(y, y, 2);
+
+ mpz_set(R->x, x);
+ mpz_set(R->y, y);
+ mpz_set(R->z, z);
+
+ err = 0;
+
+ mp_clear_multi(&t1, &t2, &x, &y, &z, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c,v $ */
+/* $Revision: 1.16 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ltc_ecc_projective_dbl_point.c b/lib/nettle/ltc_ecc_projective_dbl_point.c
new file mode 100644
index 0000000000..d9b7ec6e6c
--- /dev/null
+++ b/lib/nettle/ltc_ecc_projective_dbl_point.c
@@ -0,0 +1,146 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ltc_ecc_projective_dbl_point.c
+ ECC Crypto, Tom St Denis
+*/
+
+#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC))
+
+/**
+ Double an ECC point
+ @param P The point to double
+ @param R [out] The destination of the double
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return 0 on success
+*/
+int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mpz_t modulus)
+{
+ mpz_t t1, t2;
+ int err;
+
+ assert(P != NULL);
+ assert(R != NULL);
+ assert(modulus != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, NULL)) != 0) {
+ return err;
+ }
+
+ if (P != R) {
+ mpz_set(R->x, P->x);
+ mpz_set(R->y, P->y);
+ mpz_set(R->z, P->z);
+ }
+
+ /* t1 = Z * Z */
+ mpz_mul(t1, R->z, R->z);
+ mpz_mod(t1, t1, modulus);
+ /* Z = Y * Z */
+ mpz_mul(R->z, R->y, R->z);
+ mpz_mod(R->z, R->z, modulus);
+ /* Z = 2Z */
+ mpz_add(R->z, R->z, R->z);
+ if (mpz_cmp(R->z, modulus) >= 0) {
+ mpz_sub(R->z, R->z, modulus);
+ }
+
+ /* T2 = X - T1 */
+ mpz_sub(t2, R->x, t1);
+ if (mpz_cmp_ui(t2, 0) < 0) {
+ mpz_add(t2, t2, modulus);
+ }
+ /* T1 = X + T1 */
+ mpz_add(t1, t1, R->x);
+ if (mpz_cmp(t1, modulus) >= 0) {
+ mpz_sub(t1, t1, modulus);
+ }
+ /* T2 = T1 * T2 */
+ mpz_mul(t2, t1, t2);
+ mpz_mod(t2, t2, modulus);
+ /* T1 = 2T2 */
+ mpz_add(t1, t2, t2);
+ if (mpz_cmp(t1, modulus) >= 0) {
+ mpz_sub(t1, t1, modulus);
+ }
+ /* T1 = T1 + T2 */
+ mpz_add(t1, t1, t2);
+ if (mpz_cmp(t1, modulus) >= 0) {
+ mpz_sub(t1, t1, modulus);
+ }
+
+ /* Y = 2Y */
+ mpz_add(R->y, R->y, R->y);
+ if (mpz_cmp(R->y, modulus) >= 0) {
+ mpz_sub(R->y, R->y, modulus);
+ }
+ /* Y = Y * Y */
+ mpz_mul(R->y, R->y, R->y);
+ mpz_mod(R->y, R->y, modulus);
+ /* T2 = Y * Y */
+ mpz_mul(t2, R->y, R->y);
+ mpz_mod(t2, t2, modulus);
+ /* T2 = T2/2 */
+ if (mp_isodd(t2)) {
+ mpz_add(t2, t2, modulus);
+ }
+ mpz_divexact_ui(t2, t2, 2);
+ /* Y = Y * X */
+ mpz_mul(R->y, R->y, R->x);
+ mpz_mod(R->y, R->y, modulus);
+
+ /* X = T1 * T1 */
+ mpz_mul(R->x, t1, t1);
+ mpz_mod(R->x, R->x, modulus);
+ /* X = X - Y */
+ mpz_sub(R->x, R->x, R->y);
+ if (mpz_cmp_ui(R->x, 0) < 0) {
+ mpz_add(R->x, R->x, modulus);
+ }
+ /* X = X - Y */
+ mpz_sub(R->x, R->x, R->y);
+ if (mpz_cmp_ui(R->x, 0) < 0) {
+ mpz_add(R->x, R->x, modulus);
+ }
+
+ /* Y = Y - X */
+ mpz_sub(R->y, R->y, R->x);
+ if (mpz_cmp_ui(R->y, 0) < 0) {
+ mpz_add(R->y, R->y, modulus);
+ }
+ /* Y = Y * T1 */
+ mpz_mul(R->y, R->y, t1);
+ mpz_mod(R->y, R->y, modulus);
+ /* Y = Y - T2 */
+ mpz_sub(R->y, R->y, t2);
+ if (mpz_cmp_ui(R->y, 0) < 0) {
+ mpz_add( R->y, R->y, modulus);
+ }
+
+ err = 0;
+
+ mp_clear_multi(&t1, &t2, NULL);
+ return err;
+}
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c,v $ */
+/* $Revision: 1.11 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/mp_unsigned_bin.c b/lib/nettle/mp_unsigned_bin.c
new file mode 100644
index 0000000000..0da8bba32e
--- /dev/null
+++ b/lib/nettle/mp_unsigned_bin.c
@@ -0,0 +1,28 @@
+#include "ecc.h"
+
+unsigned long mp_unsigned_bin_size(mpz_t a)
+{
+ unsigned long t;
+ assert(a != NULL);
+
+ t = mpz_sizeinbase(a, 2);
+ if (mpz_cmp_ui((a), 0) == 0) return 0;
+ return (t>>3) + ((t&7)?1:0);
+}
+
+int mp_to_unsigned_bin(mpz_t a, unsigned char *b)
+{
+ assert(a != NULL);
+ assert(b != NULL);
+ mpz_export(b, NULL, 1, 1, 1, 0, a);
+
+ return 0;
+}
+
+int mp_read_unsigned_bin(mpz_t a, unsigned char *b, unsigned long len)
+{
+ assert(a != NULL);
+ assert(b != NULL);
+ mpz_import(a, len, 1, 1, 1, 0, b);
+ return 0;
+}
diff --git a/lib/nettle/mpi.c b/lib/nettle/mpi.c
index c76705c18f..eef8a2cc36 100644
--- a/lib/nettle/mpi.c
+++ b/lib/nettle/mpi.c
@@ -33,6 +33,7 @@
#include <gnutls_mpi.h>
#include <gmp.h>
#include <nettle/bignum.h>
+#include <gnettle.h>
#include <random.h>
#define TOMPZ(x) (*((mpz_t*)(x)))
@@ -390,7 +391,6 @@ wrap_nettle_mpi_mul_ui (bigint_t w, const bigint_t a, unsigned long b)
}
-#define PRIME_CHECK_PARAM 8
static int
wrap_nettle_prime_check (bigint_t pp)
{
diff --git a/lib/nettle/multi.c b/lib/nettle/multi.c
new file mode 100644
index 0000000000..788c8e9a00
--- /dev/null
+++ b/lib/nettle/multi.c
@@ -0,0 +1,46 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include <gmp.h>
+#include <stdarg.h>
+#include <ecc.h>
+
+int mp_init_multi(mpz_t *a, ...)
+{
+ mpz_t *cur = a;
+ int np = 0;
+ va_list args;
+
+ va_start(args, a);
+ while (cur != NULL) {
+ mpz_init(*cur);
+ ++np;
+ cur = va_arg(args, mpz_t*);
+ }
+ va_end(args);
+ return 0;
+}
+
+void mp_clear_multi(mpz_t *a, ...)
+{
+ mpz_t *cur = a;
+ va_list args;
+
+ va_start(args, a);
+ while (cur != NULL) {
+ mpz_clear(*cur);
+ cur = va_arg(args, mpz_t*);
+ }
+ va_end(args);
+}
+
+/* $Source$ */
+/* $Revision$ */
+/* $Date$ */
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index 5ee9769d0d..f1722bede7 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2010
- * Free Software Foundation, Inc.
+ * Copyright (C) 2010 Free Software Foundation, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -42,9 +41,13 @@
#include <nettle/rsa.h>
#include <random.h>
#include <gnutls/crypto.h>
+#include "rnd.h"
+#include "ecc.h"
#define TOMPZ(x) (*((mpz_t*)(x)))
+static inline int is_supported_curve(int curve);
+
static void
rnd_func (void *_ctx, unsigned length, uint8_t * data)
{
@@ -81,6 +84,69 @@ _rsa_params_to_privkey (const gnutls_pk_params_st * pk_params,
}
+static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo, gnutls_datum_t * out,
+ const gnutls_pk_params_st * priv,
+ const gnutls_pk_params_st * pub)
+{
+ int ret;
+
+ switch (algo)
+ {
+ case GNUTLS_PK_ECDH:
+ {
+ ecc_key ecc_pub, ecc_priv;
+ int curve = priv->flags;
+ unsigned long sz;
+
+ if (is_supported_curve(curve) == 0)
+ return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);
+
+ ecc_pub.type = PK_PUBLIC;
+ memcpy(&ecc_pub.prime, pub->params[0], sizeof(mpz_t));
+ memcpy(&ecc_pub.order, pub->params[1], sizeof(mpz_t));
+ memcpy(&ecc_pub.Gx, pub->params[2], sizeof(mpz_t));
+ memcpy(&ecc_pub.Gy, pub->params[3], sizeof(mpz_t));
+ memcpy(&ecc_pub.pubkey.x, pub->params[4], sizeof(mpz_t));
+ memcpy(&ecc_pub.pubkey.y, pub->params[5], sizeof(mpz_t));
+ memcpy(&ecc_pub.pubkey.z, pub->params[6], sizeof(mpz_t));
+
+ ecc_priv.type = PK_PRIVATE;
+ memcpy(&ecc_priv.prime, priv->params[0], sizeof(mpz_t));
+ memcpy(&ecc_priv.order, priv->params[1], sizeof(mpz_t));
+ memcpy(&ecc_priv.Gx, priv->params[2], sizeof(mpz_t));
+ memcpy(&ecc_priv.Gy, priv->params[3], sizeof(mpz_t));
+ memcpy(&ecc_priv.pubkey.x, priv->params[4], sizeof(mpz_t));
+ memcpy(&ecc_priv.pubkey.y, priv->params[5], sizeof(mpz_t));
+ memcpy(&ecc_priv.pubkey.z, priv->params[6], sizeof(mpz_t));
+ memcpy(&ecc_priv.k, priv->params[7], sizeof(mpz_t));
+
+ sz = ECC_BUF_SIZE;
+ out->data = gnutls_malloc(sz);
+ if (out->data == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ ret = ecc_shared_secret(&ecc_priv, &ecc_pub, out->data, &sz);
+ if (ret != 0)
+ {
+ gnutls_free(out->data);
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ }
+ out->size = sz;
+ break;
+ }
+ default:
+ gnutls_assert ();
+ ret = GNUTLS_E_INTERNAL_ERROR;
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+
+ return ret;
+}
+
static int
_wrap_nettle_pk_encrypt (gnutls_pk_algorithm_t algo,
gnutls_datum_t * ciphertext,
@@ -89,7 +155,6 @@ _wrap_nettle_pk_encrypt (gnutls_pk_algorithm_t algo,
{
int ret;
- /* make a sexp from pkey */
switch (algo)
{
case GNUTLS_PK_RSA:
@@ -486,6 +551,15 @@ cleanup:
return ret;
}
+static inline int is_supported_curve(int curve)
+{
+ if (_gnutls_ecc_curve_get_name(curve) != NULL)
+ return 1;
+ else
+ return 0;
+}
+
+
static int
wrap_nettle_pk_generate_params (gnutls_pk_algorithm_t algo,
unsigned int level /*bits */ ,
@@ -605,6 +679,56 @@ rsa_fail:
break;
}
+ case GNUTLS_PK_ECDH:
+ {
+ ecc_key key;
+ ltc_ecc_set_type tls_ecc_set;
+ const gnutls_ecc_curve_entry_st *st;
+
+ st = _gnutls_ecc_curve_get_params(level);
+ if (st == NULL)
+ return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);
+
+ tls_ecc_set.size = st->size;
+ tls_ecc_set.prime = st->prime;
+ tls_ecc_set.order = st->order;
+ tls_ecc_set.Gx = st->Gx;
+ tls_ecc_set.Gy = st->Gy;
+
+ ret = ecc_make_key(NULL, _int_random_func, &key, &tls_ecc_set);
+ if (ret != 0)
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ params->params_nr = 0;
+ for (i = 0; i < ECDH_PRIVATE_PARAMS; i++)
+ {
+ params->params[i] = _gnutls_mpi_alloc_like(&key.prime);
+ if (params->params[i] == NULL)
+ {
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto ecc_fail;
+ }
+ params->params_nr++;
+ }
+ params->flags = level;
+
+ mpz_set(TOMPZ(params->params[0]), key.prime);
+ mpz_set(TOMPZ(params->params[1]), key.order);
+ mpz_set(TOMPZ(params->params[2]), key.Gx);
+ mpz_set(TOMPZ(params->params[3]), key.Gy);
+ mpz_set(TOMPZ(params->params[4]), key.pubkey.x);
+ mpz_set(TOMPZ(params->params[5]), key.pubkey.y);
+ mpz_set(TOMPZ(params->params[6]), key.pubkey.z);
+ mpz_set(TOMPZ(params->params[7]), key.k);
+
+ecc_fail:
+ ecc_free(&key);
+
+ if (ret < 0)
+ goto fail;
+
+ break;
+ }
default:
gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
@@ -666,4 +790,5 @@ gnutls_crypto_pk_st _gnutls_pk_ops = {
.verify = _wrap_nettle_pk_verify,
.generate = wrap_nettle_pk_generate_params,
.pk_fixup_private_params = wrap_nettle_pk_fixup,
+ .derive = _wrap_nettle_pk_derive,
};
diff --git a/lib/nettle/rnd.c b/lib/nettle/rnd.c
index 8af0adde57..b503e10e1d 100644
--- a/lib/nettle/rnd.c
+++ b/lib/nettle/rnd.c
@@ -33,6 +33,7 @@
#include <gnutls_errors.h>
#include <gnutls_num.h>
#include <nettle/yarrow.h>
+#include "rnd.h"
#define SOURCES 2
@@ -440,7 +441,6 @@ wrap_nettle_rnd_init (void **ctx)
}
-
static int
wrap_nettle_rnd (void *_ctx, int level, void *data, size_t datasize)
{
@@ -467,6 +467,14 @@ wrap_nettle_rnd (void *_ctx, int level, void *data, size_t datasize)
return 0;
}
+/* internal function to provide to nettle functions that
+ * require a nettle_random_func().
+ */
+void _int_random_func(void *ctx, unsigned length, uint8_t *dst)
+{
+ wrap_nettle_rnd(ctx, 0, dst, length);
+}
+
int crypto_rnd_prio = INT_MAX;
gnutls_crypto_rnd_st _gnutls_rnd_ops = {
diff --git a/lib/nettle/rnd.h b/lib/nettle/rnd.h
new file mode 100644
index 0000000000..5deefd392c
--- /dev/null
+++ b/lib/nettle/rnd.h
@@ -0,0 +1,2 @@
+void _int_random_func(void *ctx,
+ unsigned length, uint8_t *dst);
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index bde3aefa76..b35ecd2d00 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -78,14 +78,15 @@ typedef struct gnutls_pkcs7_int
/* parameters should not be larger than this limit */
#define DSA_PUBLIC_PARAMS 4
#define RSA_PUBLIC_PARAMS 2
+#define ECDH_PUBLIC_PARAMS 7
+
#define MAX_PRIV_PARAMS_SIZE GNUTLS_MAX_PK_PARAMS /* ok for RSA and DSA */
/* parameters should not be larger than this limit */
#define DSA_PRIVATE_PARAMS 5
-#define DSA_PUBLIC_PARAMS 4
#define RSA_PRIVATE_PARAMS 8
-#define RSA_PUBLIC_PARAMS 2
+#define ECDH_PRIVATE_PARAMS 8
#if MAX_PRIV_PARAMS_SIZE - RSA_PRIVATE_PARAMS < 0
#error INCREASE MAX_PRIV_PARAMS