gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls_2_99_1-37-g78b9114


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_2_99_1-37-g78b9114
Date: Fri, 20 May 2011 10:31:31 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=78b9114c2c025090262e5b365fc199ce2f88334b

The branch, master has been updated
       via  78b9114c2c025090262e5b365fc199ce2f88334b (commit)
      from  f90470a7b4c672a916c4513cecf4b9a6bce0eb67 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 78b9114c2c025090262e5b365fc199ce2f88334b
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Mon May 16 22:20:17 2011 +0200

    Initial ecc support. Adds support for anonymous ECDH ciphersuites.

-----------------------------------------------------------------------

Summary of changes:
 lib/Makefile.am                           |    2 +-
 lib/auth/Makefile.am                      |    3 +-
 lib/auth/anon.h                           |    1 +
 lib/auth/{anon.c => anon_ecdh.c}          |   77 +++-----
 lib/auth/ecdh_common.c                    |  203 +++++++++++++++++++
 lib/auth/{anon.h => ecdh_common.h}        |   34 ++--
 lib/ext/Makefile.am                       |    2 +-
 lib/ext/ecc.c                             |  302 +++++++++++++++++++++++++++++
 lib/ext/{max_record.h => ecc.h}           |   16 +-
 lib/gnutls_algorithms.c                   |  126 ++++++++++++-
 lib/gnutls_algorithms.h                   |   24 +++
 lib/gnutls_dh.c                           |    1 +
 lib/gnutls_ecc.c                          |  101 ++++++++++
 lib/gnutls_ecc.h                          |    2 +
 lib/gnutls_errors.c                       |    2 +
 lib/gnutls_extensions.c                   |    9 +
 lib/gnutls_global.c                       |    5 +
 lib/gnutls_int.h                          |   16 ++
 lib/gnutls_pk.c                           |    2 +-
 lib/gnutls_pk.h                           |    2 +
 lib/gnutls_priority.c                     |    8 +
 lib/gnutls_state.c                        |   12 ++
 lib/gnutls_state.h                        |   10 +
 lib/includes/gnutls/crypto.h              |   15 ++-
 lib/includes/gnutls/gnutls.h.in           |   16 ++-
 lib/nettle/Makefile.am                    |    7 +-
 lib/nettle/ecc.h                          |  123 ++++++++++++
 lib/nettle/ecc_free.c                     |   40 ++++
 lib/nettle/ecc_make_key.c                 |  125 ++++++++++++
 lib/nettle/ecc_shared_secret.c            |   80 ++++++++
 lib/nettle/ecc_sign_hash.c                |  103 ++++++++++
 lib/nettle/ecc_test.c                     |  125 ++++++++++++
 lib/nettle/ecc_verify_hash.c              |  135 +++++++++++++
 lib/nettle/gnettle.h                      |    2 +
 lib/nettle/ltc_ecc_map.c                  |   73 +++++++
 lib/nettle/ltc_ecc_mulmod.c               |  141 ++++++++++++++
 lib/nettle/ltc_ecc_points.c               |   60 ++++++
 lib/nettle/ltc_ecc_projective_add_point.c |  195 +++++++++++++++++++
 lib/nettle/ltc_ecc_projective_dbl_point.c |  146 ++++++++++++++
 lib/nettle/mp_unsigned_bin.c              |   28 +++
 lib/nettle/mpi.c                          |    2 +-
 lib/nettle/multi.c                        |   46 +++++
 lib/nettle/pk.c                           |  131 ++++++++++++-
 lib/nettle/rnd.c                          |   10 +-
 lib/nettle/rnd.h                          |    2 +
 lib/x509/x509_int.h                       |    5 +-
 46 files changed, 2475 insertions(+), 95 deletions(-)
 copy lib/auth/{anon.c => anon_ecdh.c} (62%)
 create mode 100644 lib/auth/ecdh_common.c
 copy lib/auth/{anon.h => ecdh_common.h} (56%)
 create mode 100644 lib/ext/ecc.c
 copy lib/ext/{max_record.h => ecc.h} (71%)
 create mode 100644 lib/gnutls_ecc.c
 create mode 100644 lib/gnutls_ecc.h
 create mode 100644 lib/nettle/ecc.h
 create mode 100644 lib/nettle/ecc_free.c
 create mode 100644 lib/nettle/ecc_make_key.c
 create mode 100644 lib/nettle/ecc_shared_secret.c
 create mode 100644 lib/nettle/ecc_sign_hash.c
 create mode 100644 lib/nettle/ecc_test.c
 create mode 100644 lib/nettle/ecc_verify_hash.c
 create mode 100644 lib/nettle/gnettle.h
 create mode 100644 lib/nettle/ltc_ecc_map.c
 create mode 100644 lib/nettle/ltc_ecc_mulmod.c
 create mode 100644 lib/nettle/ltc_ecc_points.c
 create mode 100644 lib/nettle/ltc_ecc_projective_add_point.c
 create mode 100644 lib/nettle/ltc_ecc_projective_dbl_point.c
 create mode 100644 lib/nettle/mp_unsigned_bin.c
 create mode 100644 lib/nettle/multi.c
 create mode 100644 lib/nettle/rnd.h

diff --git a/lib/Makefile.am b/lib/Makefile.am
index bb5975c..17a1b87 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 c459ffe..92519de 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 ab5063d..b2616df 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.c b/lib/auth/anon_ecdh.c
similarity index 62%
copy from lib/auth/anon.c
copy to lib/auth/anon_ecdh.c
index ef3b910..5e9932f 100644
--- a/lib/auth/anon.c
+++ b/lib/auth/anon_ecdh.c
@@ -39,36 +39,35 @@
 #include "gnutls_num.h"
 #include "gnutls_mpi.h"
 #include <gnutls_state.h>
-#include <auth/dh_common.h>
+#include <auth/ecdh_common.h>
+#include <ext/ecc.h>
 
-static int gen_anon_server_kx (gnutls_session_t, gnutls_buffer_st*);
-static int proc_anon_client_kx (gnutls_session_t, opaque *, size_t);
-static int proc_anon_server_kx (gnutls_session_t, opaque *, size_t);
+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_auth_struct = {
-  "ANON",
+const mod_auth_st anon_ecdh_auth_struct = {
+  "ANON ECDH",
   NULL,
   NULL,
-  gen_anon_server_kx,
-  _gnutls_gen_dh_common_client_kx,      /* this can be shared */
+  gen_anon_ecdh_server_kx,
+  _gnutls_gen_ecdh_common_client_kx,      /* this can be shared */
   NULL,
   NULL,
 
   NULL,
   NULL,                         /* certificate */
-  proc_anon_server_kx,
-  proc_anon_client_kx,
+  proc_anon_ecdh_server_kx,
+  proc_anon_ecdh_client_kx,
   NULL,
   NULL
 };
 
 static int
-gen_anon_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
+gen_anon_ecdh_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
 {
-  bigint_t g, p;
-  const bigint_t *mpis;
+  ecc_curve_t curve;
   int ret;
-  gnutls_dh_params_t dh_params;
   gnutls_anon_server_credentials_t cred;
 
   cred = (gnutls_anon_server_credentials_t)
@@ -79,18 +78,10 @@ gen_anon_server_kx (gnutls_session_t session, 
gnutls_buffer_st* data)
       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
     }
 
-  dh_params =
-    _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
-  mpis = _gnutls_dh_params_to_mpi (dh_params);
-  if (mpis == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
-    }
-
-  p = mpis[0];
-  g = mpis[1];
-
+  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)
@@ -99,9 +90,7 @@ gen_anon_server_kx (gnutls_session_t session, 
gnutls_buffer_st* data)
       return ret;
     }
 
-  _gnutls_dh_set_group (session, g, p);
-
-  ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 0);
+  ret = _gnutls_ecdh_common_print_server_kx (session, data, curve);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -112,14 +101,11 @@ gen_anon_server_kx (gnutls_session_t session, 
gnutls_buffer_st* data)
 
 
 static int
-proc_anon_client_kx (gnutls_session_t session, opaque * data,
+proc_anon_ecdh_client_kx (gnutls_session_t session, opaque * data,
                      size_t _data_size)
 {
   gnutls_anon_server_credentials_t cred;
-  int ret;
-  bigint_t p, g;
-  gnutls_dh_params_t dh_params;
-  const bigint_t *mpis;
+  ecc_curve_t curve;
 
   cred = (gnutls_anon_server_credentials_t)
     _gnutls_get_cred (session->key, GNUTLS_CRD_ANON, NULL);
@@ -129,26 +115,15 @@ proc_anon_client_kx (gnutls_session_t session, opaque * 
data,
       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
     }
 
-  dh_params =
-    _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
-  mpis = _gnutls_dh_params_to_mpi (dh_params);
-  if (mpis == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
-    }
-
-  p = mpis[0];
-  g = mpis[1];
-
-  ret = _gnutls_proc_dh_common_client_kx (session, data, _data_size, g, p);
-
-  return ret;
+  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_server_kx (gnutls_session_t session, opaque * data,
+proc_anon_ecdh_server_kx (gnutls_session_t session, opaque * data,
                      size_t _data_size)
 {
 
@@ -163,7 +138,7 @@ proc_anon_server_kx (gnutls_session_t session, opaque * 
data,
       return ret;
     }
 
-  ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size, 0);
+  ret = _gnutls_proc_ecdh_common_server_kx (session, data, _data_size);
   if (ret < 0)
     {
       gnutls_assert ();
diff --git a/lib/auth/ecdh_common.c b/lib/auth/ecdh_common.c
new file mode 100644
index 0000000..e3d247e
--- /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/anon.h b/lib/auth/ecdh_common.h
similarity index 56%
copy from lib/auth/anon.h
copy to lib/auth/ecdh_common.h
index ab5063d..1fa6eba 100644
--- a/lib/auth/anon.h
+++ b/lib/auth/ecdh_common.h
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2010 Free Software
- * Foundation, Inc.
+ * Copyright (C) 2011 Free Software Foundation, Inc.
  *
  * Author: Nikos Mavrogiannopoulos
  *
@@ -23,27 +22,20 @@
  *
  */
 
-/* this is not to be included by gnutls_anon.c */
+#ifndef AUTH_ECDH_COMMON
+#define AUTH_ECDH_COMMON
+
 #include <gnutls_auth.h>
-#include <auth/dh_common.h>
 
-typedef struct gnutls_anon_server_credentials_st
-{
-  gnutls_dh_params_t dh_params;
-  /* this callback is used to retrieve the DH or RSA
-   * parameters.
-   */
-  gnutls_params_function *params_func;
-} anon_server_credentials_st;
+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);
 
-typedef struct gnutls_anon_client_credentials_st
-{
-  int dummy;
-} anon_client_credentials_st;
 
-typedef struct anon_auth_info_st
-{
-  dh_info_st dh;
-} *anon_auth_info_t;
 
-typedef struct anon_auth_info_st anon_auth_info_st;
+#endif
diff --git a/lib/ext/Makefile.am b/lib/ext/Makefile.am
index a949912..90dcb07 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 0000000..11c0071
--- /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/max_record.h b/lib/ext/ecc.h
similarity index 71%
copy from lib/ext/max_record.h
copy to lib/ext/ecc.h
index d159b27..745a000 100644
--- a/lib/ext/max_record.h
+++ b/lib/ext/ecc.h
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2010 Free Software
- * Foundation, Inc.
+ * Copyright (C) 2011 Free Software Foundation, Inc.
  *
  * Author: Nikos Mavrogiannopoulos
  *
@@ -22,12 +21,17 @@
  * USA
  *
  */
-
-#ifndef EXT_MAX_RECORD_H
-#define EXT_MAX_RECORD_H
+#ifndef EXT_ECC_H
+#define EXT_ECC_H
 
 #include <gnutls_extensions.h>
 
-extern extension_entry_st ext_mod_max_record_size;
+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 b54e5cd..295bb87 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 5c867b8..049c1e2 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 2c6a6c3..0badeec 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 0000000..c156008
--- /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 0000000..5f91ac5
--- /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 c540569..9f700b7 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 5f21167..2156851 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 c69adcf..0499002 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 ab9776e..d67bddb 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 f6284fd..5fc3aa2 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 f9b5174..07a1acd 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 ec3dee3..c06a22d 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 a8111ba..ab4d9d0 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 8132a2f..edd4b0d 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 a1cf4b5..0f37a6d 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 f85b6b3..053970f 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 e902e77..0516800 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 0000000..0ba3b0b
--- /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 0000000..7cc9774
--- /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, address@hidden, 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 0000000..3ca7571
--- /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, address@hidden, 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 0000000..a3eb46a
--- /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, address@hidden, 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 0000000..b2da7f2
--- /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, address@hidden, 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 0000000..4c74a9f
--- /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, address@hidden, 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 0000000..71315f3
--- /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, address@hidden, 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 0000000..768590c
--- /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 0000000..f224260
--- /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, address@hidden, 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 0000000..ab845ce
--- /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, address@hidden, 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 0000000..93ad85d
--- /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, address@hidden, 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 0000000..2b00836
--- /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, address@hidden, 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 0000000..d9b7ec6
--- /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, address@hidden, 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 0000000..0da8bba
--- /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 c76705c..eef8a2c 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 0000000..788c8e9
--- /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, address@hidden, 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 5ee9769..f1722be 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 8af0add..b503e10 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 0000000..5deefd3
--- /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 bde3aef..b35ecd2 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


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]