[git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-198-ge9b711e

by Werner Koch cvs at cvs.gnupg.org
Fri Aug 30 17:34:10 CEST 2013


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 "The GNU crypto library".

The branch, master has been updated
       via  e9b711e6ddb480a71d2996465074e436c752c005 (commit)
       via  800d4e01376d52a94a157b53978c7c3f957fc476 (commit)
      from  040aa7688296e93659cb32ca31e9a001a6ab1edd (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 e9b711e6ddb480a71d2996465074e436c752c005
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Aug 30 17:04:21 2013 +0200

    mpi: Make gcry_mpi_print work with negative zeroes.
    
    * mpi/mpicoder.c (gcry_mpi_print): Take care of negative zero.
    (gcry_mpi_aprint): Allocate at least 1 byte.
    * tests/t-convert.c: New.
    * tests/Makefile.am (TESTS): Add t-convert.
    --
    
    Reported-by: Christian Fuchs
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c
index aca3710..a925922 100644
--- a/mpi/mpicoder.c
+++ b/mpi/mpicoder.c
@@ -1,6 +1,7 @@
 /* mpicoder.c  -  Coder for the external representation of MPIs
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
  *               2008 Free Software Foundation, Inc.
+ * Copyright (C) 2013 g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -178,7 +179,8 @@ mpi_fromstr (gcry_mpi_t val, const char *str)
 /* Dump the value of A in a format suitable for debugging to
    Libgcrypt's logging stream.  Note that one leading space but no
    trailing space or linefeed will be printed.  It is okay to pass
-   NULL for A. */
+   NULL for A.  Note that this function prints the sign as it is used
+   internally and won't map -0 to 0. */
 void
 gcry_mpi_dump (const gcry_mpi_t a)
 {
@@ -548,10 +550,21 @@ gcry_mpi_print (enum gcry_mpi_format format,
   unsigned int nbits = mpi_get_nbits (a);
   size_t len;
   size_t dummy_nwritten;
+  int negative;
 
   if (!nwritten)
     nwritten = &dummy_nwritten;
 
+  /* Libgcrypt does no always care to set clear the sign if the value
+     is 0.  For printing this is a bit of a surprise, in particular
+     because if some of the formats don't support negative numbers but
+     should be able to print a zero.  Thus we need this extra test
+     for a negative number.  */
+  if (a->sign && _gcry_mpi_cmp_ui (a, 0))
+    negative = 1;
+  else
+    negative = 0;
+
   len = buflen;
   *nwritten = 0;
   if (format == GCRYMPI_FMT_STD)
@@ -560,16 +573,20 @@ gcry_mpi_print (enum gcry_mpi_format format,
       int extra = 0;
       unsigned int n;
 
-      if (a->sign)
+      if (negative)
         return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */
 
       tmp = _gcry_mpi_get_buffer (a, &n, NULL);
       if (!tmp)
         return gpg_error_from_syserror ();
+
+      /* If the high bit of the returned buffer is set, we need to
+         print an extra leading 0x00 so that the output is interpreted
+         as a positive number.  */
       if (n && (*tmp & 0x80))
         {
           n++;
-          extra=1;
+          extra = 1;
 	}
 
       if (buffer && n > len)
@@ -597,6 +614,7 @@ gcry_mpi_print (enum gcry_mpi_format format,
       /* Note:  We ignore the sign for this format.  */
       /* FIXME: for performance reasons we should put this into
 	 mpi_aprint because we can then use the buffer directly.  */
+
       if (buffer && n > len)
         return gcry_error (GPG_ERR_TOO_SHORT);
       if (buffer)
@@ -617,7 +635,7 @@ gcry_mpi_print (enum gcry_mpi_format format,
       unsigned int n = (nbits + 7)/8;
 
       /* The PGP format can only handle unsigned integers.  */
-      if( a->sign )
+      if (negative)
         return gcry_error (GPG_ERR_INV_ARG);
 
       if (buffer && n+2 > len)
@@ -646,7 +664,7 @@ gcry_mpi_print (enum gcry_mpi_format format,
       int extra = 0;
       unsigned int n;
 
-      if (a->sign)
+      if (negative)
         return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet.  */
 
       tmp = _gcry_mpi_get_buffer (a, &n, NULL);
@@ -694,7 +712,7 @@ gcry_mpi_print (enum gcry_mpi_format format,
       if (!n || (*tmp & 0x80))
         extra = 2;
 
-      if (buffer && 2*n + extra + !!a->sign + 1 > len)
+      if (buffer && 2*n + extra + negative + 1 > len)
         {
           gcry_free(tmp);
           return gcry_error (GPG_ERR_TOO_SHORT);
@@ -703,7 +721,7 @@ gcry_mpi_print (enum gcry_mpi_format format,
         {
           unsigned char *s = buffer;
 
-          if (a->sign)
+          if (negative)
             *s++ = '-';
           if (extra)
             {
@@ -724,7 +742,7 @@ gcry_mpi_print (enum gcry_mpi_format format,
 	}
       else
         {
-          *nwritten = 2*n + extra + !!a->sign + 1;
+          *nwritten = 2*n + extra + negative + 1;
 	}
       gcry_free (tmp);
       return 0;
@@ -752,7 +770,7 @@ gcry_mpi_aprint (enum gcry_mpi_format format,
   if (rc)
     return rc;
 
-  *buffer = mpi_is_secure(a) ? gcry_malloc_secure (n) : gcry_malloc (n);
+  *buffer = mpi_is_secure(a) ? gcry_malloc_secure (n?n:1) : gcry_malloc (n?n:1);
   if (!*buffer)
     return gpg_error_from_syserror ();
   rc = gcry_mpi_print( format, *buffer, n, &n, a );
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 871e32b..35bcd60 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -18,7 +18,7 @@
 
 ## Process this file with automake to produce Makefile.in
 
-TESTS = version t-mpi-bit t-mpi-point prime basic \
+TESTS = version t-convert t-mpi-bit t-mpi-point prime basic \
         mpitests tsexp keygen pubkey hmac keygrip fips186-dsa aeswrap \
 	curves t-kdf pkcs1v2 random dsa-rfc6979
 
diff --git a/tests/t-convert.c b/tests/t-convert.c
new file mode 100644
index 0000000..b7f97fa
--- /dev/null
+++ b/tests/t-convert.c
@@ -0,0 +1,160 @@
+/* t-convert.c  - Tests for mpi print and scna functions
+ * Copyright (C) 2013 g10 Code GmbH
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt 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.
+ *
+ * Libgcrypt 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 program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+
+#include "../src/gcrypt-int.h"
+
+#define PGM "t-mpi-point"
+
+static const char *wherestr;
+static int verbose;
+static int debug;
+static int error_count;
+
+
+#define xmalloc(a)    gcry_xmalloc ((a))
+#define xcalloc(a,b)  gcry_xcalloc ((a),(b))
+#define xfree(a)      gcry_free ((a))
+#define pass() do { ; } while (0)
+
+static void
+show (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  if (!verbose)
+    return;
+  fprintf (stderr, "%s: ", PGM);
+  va_start (arg_ptr, format);
+  vfprintf (stderr, format, arg_ptr);
+  va_end (arg_ptr);
+}
+
+static void
+fail (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  fflush (stdout);
+  fprintf (stderr, "%s: ", PGM);
+  if (wherestr)
+    fprintf (stderr, "%s: ", wherestr);
+  va_start (arg_ptr, format);
+  vfprintf (stderr, format, arg_ptr);
+  va_end (arg_ptr);
+  error_count++;
+}
+
+static void
+die (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  fflush (stdout);
+  fprintf (stderr, "%s: ", PGM);
+  if (wherestr)
+    fprintf (stderr, "%s: ", wherestr);
+  va_start (arg_ptr, format);
+  vfprintf (stderr, format, arg_ptr);
+  va_end (arg_ptr);
+  exit (1);
+}
+
+
+/* Check that mpi_print does not return a negative zero.  */
+static void
+negative_zero (void)
+{
+  gpg_error_t err;
+  gcry_mpi_t a;
+  char *buf;
+  void *bufaddr = &buf;
+  struct { const char *name; enum gcry_mpi_format format; } fmts[] =
+    {
+      { "STD", GCRYMPI_FMT_STD },
+      { "PGP", GCRYMPI_FMT_PGP },
+      { "SSH", GCRYMPI_FMT_SSH },
+      { "HEX", GCRYMPI_FMT_HEX },
+      { "USG", GCRYMPI_FMT_USG },
+      { NULL, 0 }
+    };
+  int i;
+
+  a = gcry_mpi_new (0);
+  for (i=0; fmts[i].name; i++)
+    {
+      err = gcry_mpi_aprint (fmts[i].format, bufaddr, NULL, a);
+      if (err)
+        fail ("error printing a zero as %s: %s\n",
+              fmts[i].name,gpg_strerror (err) );
+      else
+        gcry_free (buf);
+    }
+
+  /* With the current version of libgcrypt the next two statements
+     should set a to -0. */
+  gcry_mpi_sub_ui (a, a, 1);
+  gcry_mpi_add_ui (a, a, 1);
+
+  for (i=0; fmts[i].name; i++)
+    {
+      err = gcry_mpi_aprint (fmts[i].format, bufaddr, NULL, a);
+      if (err)
+        fail ("error printing a negative zero as %s: %s\n",
+              fmts[i].name,gpg_strerror (err) );
+      else
+        gcry_free (buf);
+    }
+
+  gcry_mpi_release (a);
+}
+
+
+
+
+int
+main (int argc, char **argv)
+{
+  if (argc > 1 && !strcmp (argv[1], "--verbose"))
+    verbose = 1;
+  else if (argc > 1 && !strcmp (argv[1], "--debug"))
+    verbose = debug = 1;
+
+  if (!gcry_check_version (GCRYPT_VERSION))
+    die ("version mismatch\n");
+
+  gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+  if (debug)
+    gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+
+  negative_zero ();
+
+  show ("All tests completed. Errors: %d\n", error_count);
+  return error_count ? 1 : 0;
+}

commit 800d4e01376d52a94a157b53978c7c3f957fc476
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Aug 29 21:37:30 2013 +0200

    Refactor the ECC code into 3 files.
    
    * cipher/ecc-common.h, cipher/ecc-curves.c, cipher/ecc-misc.c: New.
    * cipher/Makefile.am (EXTRA_libcipher_la_SOURCES): Add new files.
    * configure.ac (GCRYPT_PUBKEY_CIPHERS): Add new .c files.
    * cipher/ecc.c (curve_aliases, ecc_domain_parms_t, domain_parms)
    (scanval): Move to ecc-curves.c.
    (fill_in_curve): Move to ecc-curve.c as _gcry_ecc_fill_in_curve.
    (ecc_get_curve): Move to ecc-curve.c as _gcry_ecc_get_curve.
    (_gcry_mpi_ec_ec2os): Move to ecc-misc.c.
    (ec2os): Move to ecc-misc.c as _gcry_ecc_ec2os.
    (os2ec): Move to ecc-misc.c as _gcry_ecc_os2ec.
    (point_set): Move as inline function to ecc-common.h.
    (_gcry_ecc_curve_free): Move to ecc-misc.c as _gcry_ecc_curve_free.
    (_gcry_ecc_curve_copy): Move to ecc-misc.c as _gcry_ecc_curve_copy.
    (mpi_from_keyparam, point_from_keyparam): Move to ecc-curves.c.
    (_gcry_mpi_ec_new): Move to ecc-curves.c.
    (ecc_get_param): Move to ecc-curves.c as _gcry_ecc_get_param.
    (ecc_get_param_sexp): Move to ecc-curves.c as _gcry_ecc_get_param_sexp.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/cipher/Makefile.am b/cipher/Makefile.am
index c0f21fa..e233e79 100644
--- a/cipher/Makefile.am
+++ b/cipher/Makefile.am
@@ -60,7 +60,7 @@ crc.c \
 des.c \
 dsa.c \
 elgamal.c \
-ecc.c \
+ecc.c ecc-curves.c ecc-misc.c ecc-common.h \
 idea.c \
 md4.c \
 md5.c \
diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h
new file mode 100644
index 0000000..94da73e
--- /dev/null
+++ b/cipher/ecc-common.h
@@ -0,0 +1,80 @@
+/* ecc-common.h - Declarations of common ECC code
+ * Copyright (C) 2013 g10 Code GmbH
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt 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.
+ *
+ * Libgcrypt 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 program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GCRY_ECC_COMMON_H
+#define GCRY_ECC_COMMON_H
+
+/* Definition of a curve.  */
+typedef struct
+{
+  gcry_mpi_t p;         /* Prime specifying the field GF(p).  */
+  gcry_mpi_t a;         /* First coefficient of the Weierstrass equation.  */
+  gcry_mpi_t b;         /* Second coefficient of the Weierstrass equation.  */
+  mpi_point_struct G;   /* Base point (generator).  */
+  gcry_mpi_t n;         /* Order of G.  */
+  const char *name;     /* Name of the curve or NULL.  */
+} elliptic_curve_t;
+
+
+typedef struct
+{
+  elliptic_curve_t E;
+  mpi_point_struct Q; /* Q = [d]G  */
+} ECC_public_key;
+
+
+typedef struct
+{
+  elliptic_curve_t E;
+  mpi_point_struct Q;
+  gcry_mpi_t d;
+} ECC_secret_key;
+
+
+
+/* Set the value from S into D.  */
+static inline void
+point_set (mpi_point_t d, mpi_point_t s)
+{
+  mpi_set (d->x, s->x);
+  mpi_set (d->y, s->y);
+  mpi_set (d->z, s->z);
+}
+
+
+/*-- ecc-curves.c --*/
+gpg_err_code_t _gcry_ecc_fill_in_curve (unsigned int nbits,
+                                        const char *name,
+                                        elliptic_curve_t *curve,
+                                        unsigned int *r_nbits);
+
+const char *_gcry_ecc_get_curve (gcry_mpi_t *pkey,
+                                 int iterator,
+                                 unsigned int *r_nbits);
+gcry_err_code_t _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey);
+gcry_sexp_t     _gcry_ecc_get_param_sexp (const char *name);
+
+/*-- ecc-misc.c --*/
+void _gcry_ecc_curve_free (elliptic_curve_t *E);
+elliptic_curve_t _gcry_ecc_curve_copy (elliptic_curve_t E);
+gcry_mpi_t   _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p);
+gcry_error_t _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value);
+
+
+#endif /*GCRY_ECC_COMMON_H*/
diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
new file mode 100644
index 0000000..e813b6b
--- /dev/null
+++ b/cipher/ecc-curves.c
@@ -0,0 +1,731 @@
+/* ecc-curves.c  -  Elliptic Curve parameter mangement
+ * Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2013 g10 Code GmbH
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt 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.
+ *
+ * Libgcrypt 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 program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "mpi.h"
+#include "context.h"
+#include "ec-context.h"
+#include "ecc-common.h"
+
+
+/* This tables defines aliases for curve names.  */
+static const struct
+{
+  const char *name;  /* Our name.  */
+  const char *other; /* Other name. */
+} curve_aliases[] =
+  {
+    { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID  */
+    { "NIST P-192", "prime192v1" },          /* X9.62 name.  */
+    { "NIST P-192", "secp192r1"  },          /* SECP name.  */
+    { "NIST P-192", "nistp192"   },          /* rfc5656.  */
+
+    { "NIST P-224", "secp224r1" },
+    { "NIST P-224", "1.3.132.0.33" },        /* SECP OID.  */
+    { "NIST P-224", "nistp224"   },          /* rfc5656.  */
+
+    { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1.  */
+    { "NIST P-256", "prime256v1" },
+    { "NIST P-256", "secp256r1"  },
+    { "NIST P-256", "nistp256"   },          /* rfc5656.  */
+
+    { "NIST P-384", "secp384r1" },
+    { "NIST P-384", "1.3.132.0.34" },
+    { "NIST P-384", "nistp384"   },          /* rfc5656.  */
+
+    { "NIST P-521", "secp521r1" },
+    { "NIST P-521", "1.3.132.0.35" },
+    { "NIST P-521", "nistp521"   },          /* rfc5656.  */
+
+    { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" },
+    { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" },
+    { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" },
+    { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" },
+    { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" },
+    { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"},
+    { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"},
+
+    { NULL, NULL}
+  };
+
+
+typedef struct
+{
+  const char *desc;           /* Description of the curve.  */
+  unsigned int nbits;         /* Number of bits.  */
+  unsigned int fips:1;        /* True if this is a FIPS140-2 approved curve. */
+  const char *p;              /* Order of the prime field.  */
+  const char *a, *b;          /* The coefficients. */
+  const char *n;              /* The order of the base point.  */
+  const char *g_x, *g_y;      /* Base point.  */
+} ecc_domain_parms_t;
+
+
+/* This static table defines all available curves.  */
+static const ecc_domain_parms_t domain_parms[] =
+  {
+    {
+      "NIST P-192", 192, 1,
+      "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
+      "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
+      "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
+      "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
+
+      "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
+      "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+    },
+    {
+      "NIST P-224", 224, 1,
+      "0xffffffffffffffffffffffffffffffff000000000000000000000001",
+      "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
+      "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
+      "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
+
+      "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
+      "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
+    },
+    {
+      "NIST P-256", 256, 1,
+      "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
+      "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
+      "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
+      "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
+
+      "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
+      "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
+    },
+    {
+      "NIST P-384", 384, 1,
+      "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
+      "ffffffff0000000000000000ffffffff",
+      "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
+      "ffffffff0000000000000000fffffffc",
+      "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
+      "c656398d8a2ed19d2a85c8edd3ec2aef",
+      "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
+      "581a0db248b0a77aecec196accc52973",
+
+      "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
+      "5502f25dbf55296c3a545e3872760ab7",
+      "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
+      "0a60b1ce1d7e819d7a431d7c90ea0e5f"
+    },
+    {
+      "NIST P-521", 521, 1,
+      "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+      "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
+      "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
+      "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
+      "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
+
+      "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
+      "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
+      "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
+      "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
+    },
+
+    { "brainpoolP160r1", 160, 0,
+      "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
+      "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
+      "0x1e589a8595423412134faa2dbdec95c8d8675e58",
+      "0xe95e4a5f737059dc60df5991d45029409e60fc09",
+      "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
+      "0x1667cb477a1a8ec338f94741669c976316da6321"
+    },
+
+    { "brainpoolP192r1", 192, 0,
+      "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
+      "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
+      "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
+      "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
+      "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
+      "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
+    },
+
+    { "brainpoolP224r1", 224, 0,
+      "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
+      "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
+      "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
+      "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
+      "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
+      "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
+    },
+
+    { "brainpoolP256r1", 256, 0,
+      "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
+      "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
+      "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
+      "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
+      "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
+      "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
+    },
+
+    { "brainpoolP320r1", 320, 0,
+      "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
+      "fcd412b1f1b32e27",
+      "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
+      "92f375a97d860eb4",
+      "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981"
+      "6f5eb4ac8fb1f1a6",
+      "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9"
+      "8691555b44c59311",
+      "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
+      "10af8d0d39e20611",
+      "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
+      "d35245d1692e8ee1"
+    },
+
+    { "brainpoolP384r1", 384, 0,
+      "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
+      "acd3a729901d1a71874700133107ec53",
+      "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
+      "8aa5814a503ad4eb04a8c7dd22ce2826",
+      "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5"
+      "7cb4390295dbc9943ab78696fa504c11",
+      "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7"
+      "cf3ab6af6b7fc3103b883202e9046565",
+      "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
+      "e826e03436d646aaef87b2e247d4af1e",
+      "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
+      "0e4646217791811142820341263c5315"
+    },
+
+    { "brainpoolP512r1", 512, 0,
+      "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
+      "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
+      "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
+      "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca",
+      "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7"
+      "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723",
+      "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870"
+      "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
+      "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
+      "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
+      "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
+      "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
+    },
+
+    { NULL, 0, 0, NULL, NULL, NULL, NULL }
+  };
+
+
+
+

+/* Helper to scan a hex string. */
+static gcry_mpi_t
+scanval (const char *string)
+{
+  gpg_error_t err;
+  gcry_mpi_t val;
+
+  err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
+  if (err)
+    log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err));
+  return val;
+}
+
+
+/* Generate the crypto system setup.  This function takes the NAME of
+   a curve or the desired number of bits and stores at R_CURVE the
+   parameters of the named curve or those of a suitable curve.  If
+   R_NBITS is not NULL, the chosen number of bits is stored there.  */
+gpg_err_code_t
+_gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
+                         elliptic_curve_t *curve, unsigned int *r_nbits)
+{
+  int idx, aliasno;
+  const char *resname = NULL; /* Set to a found curve name.  */
+
+  if (name)
+    {
+      /* First check our native curves.  */
+      for (idx = 0; domain_parms[idx].desc; idx++)
+        if (!strcmp (name, domain_parms[idx].desc))
+          {
+            resname = domain_parms[idx].desc;
+            break;
+          }
+      /* If not found consult the alias table.  */
+      if (!domain_parms[idx].desc)
+        {
+          for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
+            if (!strcmp (name, curve_aliases[aliasno].other))
+              break;
+          if (curve_aliases[aliasno].name)
+            {
+              for (idx = 0; domain_parms[idx].desc; idx++)
+                if (!strcmp (curve_aliases[aliasno].name,
+                             domain_parms[idx].desc))
+                  {
+                    resname = domain_parms[idx].desc;
+                    break;
+                  }
+            }
+        }
+    }
+  else
+    {
+      for (idx = 0; domain_parms[idx].desc; idx++)
+        if (nbits == domain_parms[idx].nbits)
+          break;
+    }
+  if (!domain_parms[idx].desc)
+    return GPG_ERR_INV_VALUE;
+
+  /* In fips mode we only support NIST curves.  Note that it is
+     possible to bypass this check by specifying the curve parameters
+     directly.  */
+  if (fips_mode () && !domain_parms[idx].fips )
+    return GPG_ERR_NOT_SUPPORTED;
+
+  if (r_nbits)
+    *r_nbits = domain_parms[idx].nbits;
+  curve->p = scanval (domain_parms[idx].p);
+  curve->a = scanval (domain_parms[idx].a);
+  curve->b = scanval (domain_parms[idx].b);
+  curve->n = scanval (domain_parms[idx].n);
+  curve->G.x = scanval (domain_parms[idx].g_x);
+  curve->G.y = scanval (domain_parms[idx].g_y);
+  curve->G.z = mpi_alloc_set_ui (1);
+  curve->name = resname;
+
+  return 0;
+}
+
+
+/* Return the name matching the parameters in PKEY.  */
+const char *
+_gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
+{
+  gpg_err_code_t err;
+  elliptic_curve_t E;
+  int idx;
+  gcry_mpi_t tmp;
+  const char *result = NULL;
+
+  if (r_nbits)
+    *r_nbits = 0;
+
+  if (!pkey)
+    {
+      idx = iterator;
+      if (idx >= 0 && idx < DIM (domain_parms))
+        {
+          result = domain_parms[idx].desc;
+          if (r_nbits)
+            *r_nbits = domain_parms[idx].nbits;
+        }
+      return result;
+    }
+
+  if (!pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4])
+    return NULL;
+
+  E.p = pkey[0];
+  E.a = pkey[1];
+  E.b = pkey[2];
+  _gcry_mpi_point_init (&E.G);
+  err = _gcry_ecc_os2ec (&E.G, pkey[3]);
+  if (err)
+    {
+      _gcry_mpi_point_free_parts (&E.G);
+      return NULL;
+    }
+  E.n = pkey[4];
+
+  for (idx = 0; domain_parms[idx].desc; idx++)
+    {
+      tmp = scanval (domain_parms[idx].p);
+      if (!mpi_cmp (tmp, E.p))
+        {
+          mpi_free (tmp);
+          tmp = scanval (domain_parms[idx].a);
+          if (!mpi_cmp (tmp, E.a))
+            {
+              mpi_free (tmp);
+              tmp = scanval (domain_parms[idx].b);
+              if (!mpi_cmp (tmp, E.b))
+                {
+                  mpi_free (tmp);
+                  tmp = scanval (domain_parms[idx].n);
+                  if (!mpi_cmp (tmp, E.n))
+                    {
+                      mpi_free (tmp);
+                      tmp = scanval (domain_parms[idx].g_x);
+                      if (!mpi_cmp (tmp, E.G.x))
+                        {
+                          mpi_free (tmp);
+                          tmp = scanval (domain_parms[idx].g_y);
+                          if (!mpi_cmp (tmp, E.G.y))
+                            {
+                              mpi_free (tmp);
+                              result = domain_parms[idx].desc;
+                              if (r_nbits)
+                                *r_nbits = domain_parms[idx].nbits;
+                              break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+      mpi_free (tmp);
+    }
+
+  _gcry_mpi_point_free_parts (&E.G);
+
+  return result;
+}
+
+
+/* Helper to extract an MPI from key parameters.  */
+static gpg_err_code_t
+mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name)
+{
+  gcry_err_code_t ec = 0;
+  gcry_sexp_t l1;
+
+  l1 = gcry_sexp_find_token (keyparam, name, 0);
+  if (l1)
+    {
+      *r_a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
+      gcry_sexp_release (l1);
+      if (!*r_a)
+        ec = GPG_ERR_INV_OBJ;
+    }
+  return ec;
+}
+
+/* Helper to extract a point from key parameters.  If no parameter
+   with NAME is found, the functions tries to find a non-encoded point
+   by appending ".x", ".y" and ".z" to NAME.  ".z" is in this case
+   optional and defaults to 1.  */
+static gpg_err_code_t
+point_from_keyparam (gcry_mpi_point_t *r_a,
+                     gcry_sexp_t keyparam, const char *name)
+{
+  gcry_err_code_t ec;
+  gcry_mpi_t a = NULL;
+  gcry_mpi_point_t point;
+
+  ec = mpi_from_keyparam (&a, keyparam, name);
+  if (ec)
+    return ec;
+
+  if (a)
+    {
+      point = gcry_mpi_point_new (0);
+      ec = _gcry_ecc_os2ec (point, a);
+      mpi_free (a);
+      if (ec)
+        {
+          gcry_mpi_point_release (point);
+          return ec;
+        }
+    }
+  else
+    {
+      char *tmpname;
+      gcry_mpi_t x = NULL;
+      gcry_mpi_t y = NULL;
+      gcry_mpi_t z = NULL;
+
+      tmpname = gcry_malloc (strlen (name) + 2 + 1);
+      if (!tmpname)
+        return gpg_err_code_from_syserror ();
+      strcpy (stpcpy (tmpname, name), ".x");
+      ec = mpi_from_keyparam (&x, keyparam, tmpname);
+      if (ec)
+        {
+          gcry_free (tmpname);
+          return ec;
+        }
+      strcpy (stpcpy (tmpname, name), ".y");
+      ec = mpi_from_keyparam (&y, keyparam, tmpname);
+      if (ec)
+        {
+          mpi_free (x);
+          gcry_free (tmpname);
+          return ec;
+        }
+      strcpy (stpcpy (tmpname, name), ".z");
+      ec = mpi_from_keyparam (&z, keyparam, tmpname);
+      if (ec)
+        {
+          mpi_free (y);
+          mpi_free (x);
+          gcry_free (tmpname);
+          return ec;
+        }
+      if (!z)
+        z = mpi_set_ui (NULL, 1);
+      if (x && y)
+        point = gcry_mpi_point_snatch_set (NULL, x, y, z);
+      else
+        {
+          mpi_free (x);
+          mpi_free (y);
+          mpi_free (z);
+          point = NULL;
+        }
+      gcry_free (tmpname);
+    }
+
+  if (point)
+    *r_a = point;
+  return 0;
+}
+
+
+/* This function creates a new context for elliptic curve operations.
+   Either KEYPARAM or CURVENAME must be given.  If both are given and
+   KEYPARAM has no curve parameter CURVENAME is used to add missing
+   parameters.  On success 0 is returned and the new context stored at
+   R_CTX.  On error NULL is stored at R_CTX and an error code is
+   returned.  The context needs to be released using
+   gcry_ctx_release.  */
+gpg_err_code_t
+_gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
+                  gcry_sexp_t keyparam, const char *curvename)
+{
+  gpg_err_code_t errc;
+  gcry_ctx_t ctx = NULL;
+  gcry_mpi_t p = NULL;
+  gcry_mpi_t a = NULL;
+  gcry_mpi_t b = NULL;
+  gcry_mpi_point_t G = NULL;
+  gcry_mpi_t n = NULL;
+  gcry_mpi_point_t Q = NULL;
+  gcry_mpi_t d = NULL;
+  gcry_sexp_t l1;
+
+  *r_ctx = NULL;
+
+  if (keyparam)
+    {
+      errc = mpi_from_keyparam (&p, keyparam, "p");
+      if (errc)
+        goto leave;
+      errc = mpi_from_keyparam (&a, keyparam, "a");
+      if (errc)
+        goto leave;
+      errc = mpi_from_keyparam (&b, keyparam, "b");
+      if (errc)
+        goto leave;
+      errc = point_from_keyparam (&G, keyparam, "g");
+      if (errc)
+        goto leave;
+      errc = mpi_from_keyparam (&n, keyparam, "n");
+      if (errc)
+        goto leave;
+      errc = point_from_keyparam (&Q, keyparam, "q");
+      if (errc)
+        goto leave;
+      errc = mpi_from_keyparam (&d, keyparam, "d");
+      if (errc)
+        goto leave;
+    }
+
+
+  /* Check whether a curve parameter is available and use that to fill
+     in missing values.  If no curve parameter is available try an
+     optional provided curvename.  If only the curvename has been
+     given use that one. */
+  if (keyparam)
+    l1 = gcry_sexp_find_token (keyparam, "curve", 5);
+  else
+    l1 = NULL;
+  if (l1 || curvename)
+    {
+      char *name;
+      elliptic_curve_t *E;
+
+      if (l1)
+        {
+          name = _gcry_sexp_nth_string (l1, 1);
+          gcry_sexp_release (l1);
+          if (!name)
+            {
+              errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
+              goto leave;
+            }
+        }
+      else
+        name = NULL;
+
+      E = gcry_calloc (1, sizeof *E);
+      if (!E)
+        {
+          errc = gpg_err_code_from_syserror ();
+          gcry_free (name);
+          goto leave;
+        }
+
+      errc = _gcry_ecc_fill_in_curve (0, name? name : curvename, E, NULL);
+      gcry_free (name);
+      if (errc)
+        {
+          gcry_free (E);
+          goto leave;
+        }
+
+      if (!p)
+        {
+          p = E->p;
+          E->p = NULL;
+        }
+      if (!a)
+        {
+          a = E->a;
+          E->a = NULL;
+        }
+      if (!b)
+        {
+          b = E->b;
+          E->b = NULL;
+        }
+      if (!G)
+        {
+          G = gcry_mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
+          E->G.x = NULL;
+          E->G.y = NULL;
+          E->G.z = NULL;
+        }
+      if (!n)
+        {
+          n = E->n;
+          E->n = NULL;
+        }
+      _gcry_ecc_curve_free (E);
+      gcry_free (E);
+    }
+
+  errc = _gcry_mpi_ec_p_new (&ctx, p, a);
+  if (!errc)
+    {
+      mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
+
+      if (b)
+        {
+          ec->b = b;
+          b = NULL;
+        }
+      if (G)
+        {
+          ec->G = G;
+          G = NULL;
+        }
+      if (n)
+        {
+          ec->n = n;
+          n = NULL;
+        }
+      if (Q)
+        {
+          ec->Q = Q;
+          Q = NULL;
+        }
+      if (d)
+        {
+          ec->d = d;
+          d = NULL;
+        }
+
+      *r_ctx = ctx;
+    }
+
+ leave:
+  mpi_free (p);
+  mpi_free (a);
+  mpi_free (b);
+  gcry_mpi_point_release (G);
+  mpi_free (n);
+  gcry_mpi_point_release (Q);
+  mpi_free (d);
+  return errc;
+}
+
+
+/* Return the parameters of the curve NAME in an MPI array.  */
+gcry_err_code_t
+_gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey)
+{
+  gpg_err_code_t err;
+  unsigned int nbits;
+  elliptic_curve_t E;
+  mpi_ec_t ctx;
+  gcry_mpi_t g_x, g_y;
+
+  err = _gcry_ecc_fill_in_curve (0, name, &E, &nbits);
+  if (err)
+    return err;
+
+  g_x = mpi_new (0);
+  g_y = mpi_new (0);
+  ctx = _gcry_mpi_ec_p_internal_new (E.p, E.a);
+  if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
+    log_fatal ("ecc get param: Failed to get affine coordinates\n");
+  _gcry_mpi_ec_free (ctx);
+  _gcry_mpi_point_free_parts (&E.G);
+
+  pkey[0] = E.p;
+  pkey[1] = E.a;
+  pkey[2] = E.b;
+  pkey[3] = _gcry_ecc_ec2os (g_x, g_y, E.p);
+  pkey[4] = E.n;
+  pkey[5] = NULL;
+
+  mpi_free (g_x);
+  mpi_free (g_y);
+
+  return 0;
+}
+
+
+/* Return the parameters of the curve NAME as an S-expression.  */
+gcry_sexp_t
+_gcry_ecc_get_param_sexp (const char *name)
+{
+  gcry_mpi_t pkey[6];
+  gcry_sexp_t result;
+  int i;
+
+  if (_gcry_ecc_get_param (name, pkey))
+    return NULL;
+
+  if (gcry_sexp_build (&result, NULL,
+                       "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))",
+                       pkey[0], pkey[1], pkey[2], pkey[3], pkey[4]))
+    result = NULL;
+
+  for (i=0; pkey[i]; i++)
+    gcry_mpi_release (pkey[i]);
+
+  return result;
+}
diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c
new file mode 100644
index 0000000..5e06bef
--- /dev/null
+++ b/cipher/ecc-misc.c
@@ -0,0 +1,183 @@
+/* ecc-misc.c  -  Elliptic Curve miscellaneous functions
+ * Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2013 g10 Code GmbH
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt 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.
+ *
+ * Libgcrypt 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 program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "mpi.h"
+#include "context.h"
+#include "ec-context.h"
+#include "ecc-common.h"
+
+
+/*
+ * Release a curve object.
+ */
+void
+_gcry_ecc_curve_free (elliptic_curve_t *E)
+{
+  mpi_free (E->p); E->p = NULL;
+  mpi_free (E->a); E->a = NULL;
+  mpi_free (E->b);  E->b = NULL;
+  _gcry_mpi_point_free_parts (&E->G);
+  mpi_free (E->n);  E->n = NULL;
+}
+
+
+/*
+ * Return a copy of a curve object.
+ */
+elliptic_curve_t
+_gcry_ecc_curve_copy (elliptic_curve_t E)
+{
+  elliptic_curve_t R;
+
+  R.p = mpi_copy (E.p);
+  R.a = mpi_copy (E.a);
+  R.b = mpi_copy (E.b);
+  _gcry_mpi_point_init (&R.G);
+  point_set (&R.G, &E.G);
+  R.n = mpi_copy (E.n);
+
+  return R;
+}
+
+
+gcry_mpi_t
+_gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p)
+{
+  gpg_error_t err;
+  int pbytes = (mpi_get_nbits (p)+7)/8;
+  size_t n;
+  unsigned char *buf, *ptr;
+  gcry_mpi_t result;
+
+  buf = gcry_xmalloc ( 1 + 2*pbytes );
+  *buf = 04; /* Uncompressed point.  */
+  ptr = buf+1;
+  err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x);
+  if (err)
+    log_fatal ("mpi_print failed: %s\n", gpg_strerror (err));
+  if (n < pbytes)
+    {
+      memmove (ptr+(pbytes-n), ptr, n);
+      memset (ptr, 0, (pbytes-n));
+    }
+  ptr += pbytes;
+  err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y);
+  if (err)
+    log_fatal ("mpi_print failed: %s\n", gpg_strerror (err));
+  if (n < pbytes)
+    {
+      memmove (ptr+(pbytes-n), ptr, n);
+      memset (ptr, 0, (pbytes-n));
+    }
+
+  err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL);
+  if (err)
+    log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err));
+  gcry_free (buf);
+
+  return result;
+}
+
+
+/* Convert POINT into affine coordinates using the context CTX and
+   return a newly allocated MPI.  If the conversion is not possible
+   NULL is returned.  This function won't print an error message.  */
+gcry_mpi_t
+_gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ectx)
+{
+  gcry_mpi_t g_x, g_y, result;
+
+  g_x = mpi_new (0);
+  g_y = mpi_new (0);
+  if (_gcry_mpi_ec_get_affine (g_x, g_y, point, ectx))
+    result = NULL;
+  else
+    result = _gcry_ecc_ec2os (g_x, g_y, ectx->p);
+  mpi_free (g_x);
+  mpi_free (g_y);
+
+  return result;
+}
+
+
+/* RESULT must have been initialized and is set on success to the
+   point given by VALUE.  */
+gcry_error_t
+_gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value)
+{
+  gcry_error_t err;
+  size_t n;
+  unsigned char *buf;
+  gcry_mpi_t x, y;
+
+  n = (mpi_get_nbits (value)+7)/8;
+  buf = gcry_xmalloc (n);
+  err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, n, &n, value);
+  if (err)
+    {
+      gcry_free (buf);
+      return err;
+    }
+  if (n < 1)
+    {
+      gcry_free (buf);
+      return GPG_ERR_INV_OBJ;
+    }
+  if (*buf != 4)
+    {
+      gcry_free (buf);
+      return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression.  */
+    }
+  if ( ((n-1)%2) )
+    {
+      gcry_free (buf);
+      return GPG_ERR_INV_OBJ;
+    }
+  n = (n-1)/2;
+  err = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL);
+  if (err)
+    {
+      gcry_free (buf);
+      return err;
+    }
+  err = gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL);
+  gcry_free (buf);
+  if (err)
+    {
+      mpi_free (x);
+      return err;
+    }
+
+  mpi_set (result->x, x);
+  mpi_set (result->y, y);
+  mpi_set_ui (result->z, 1);
+
+  mpi_free (x);
+  mpi_free (y);
+
+  return 0;
+}
diff --git a/cipher/ecc.c b/cipher/ecc.c
index b694d76..9174f9b 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -47,11 +47,6 @@
   - In mpi/ec.c we use mpi_powm for x^2 mod p: Either implement a
     special case in mpi_powm or check whether mpi_mulm is faster.
 
-  - Split this up into several files.  For example the curve
-    management and gcry_mpi_ec_new are independent of the actual ECDSA
-    implementation.  This will also help to support optimized versions
-    of some curves.
-
 */
 
 
@@ -67,232 +62,7 @@
 #include "context.h"
 #include "ec-context.h"
 #include "pubkey-internal.h"
-
-/* Definition of a curve.  */
-typedef struct
-{
-  gcry_mpi_t p;         /* Prime specifying the field GF(p).  */
-  gcry_mpi_t a;         /* First coefficient of the Weierstrass equation.  */
-  gcry_mpi_t b;         /* Second coefficient of the Weierstrass equation.  */
-  mpi_point_struct G;   /* Base point (generator).  */
-  gcry_mpi_t n;         /* Order of G.  */
-  const char *name;     /* Name of the curve or NULL.  */
-} elliptic_curve_t;
-
-
-typedef struct
-{
-  elliptic_curve_t E;
-  mpi_point_struct Q; /* Q = [d]G  */
-} ECC_public_key;
-
-typedef struct
-{
-  elliptic_curve_t E;
-  mpi_point_struct Q;
-  gcry_mpi_t d;
-} ECC_secret_key;
-
-
-/* This tables defines aliases for curve names.  */
-static const struct
-{
-  const char *name;  /* Our name.  */
-  const char *other; /* Other name. */
-} curve_aliases[] =
-  {
-    { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID  */
-    { "NIST P-192", "prime192v1" },          /* X9.62 name.  */
-    { "NIST P-192", "secp192r1"  },          /* SECP name.  */
-    { "NIST P-192", "nistp192"   },          /* rfc5656.  */
-
-    { "NIST P-224", "secp224r1" },
-    { "NIST P-224", "1.3.132.0.33" },        /* SECP OID.  */
-    { "NIST P-224", "nistp224"   },          /* rfc5656.  */
-
-    { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1.  */
-    { "NIST P-256", "prime256v1" },
-    { "NIST P-256", "secp256r1"  },
-    { "NIST P-256", "nistp256"   },          /* rfc5656.  */
-
-    { "NIST P-384", "secp384r1" },
-    { "NIST P-384", "1.3.132.0.34" },
-    { "NIST P-384", "nistp384"   },          /* rfc5656.  */
-
-    { "NIST P-521", "secp521r1" },
-    { "NIST P-521", "1.3.132.0.35" },
-    { "NIST P-521", "nistp521"   },          /* rfc5656.  */
-
-    { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" },
-    { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" },
-    { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" },
-    { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" },
-    { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" },
-    { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"},
-    { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"},
-
-    { NULL, NULL}
-  };
-
-typedef struct   {
-  const char *desc;           /* Description of the curve.  */
-  unsigned int nbits;         /* Number of bits.  */
-  unsigned int fips:1;        /* True if this is a FIPS140-2 approved curve. */
-  const char  *p;             /* Order of the prime field.  */
-  const char *a, *b;          /* The coefficients. */
-  const char *n;              /* The order of the base point.  */
-  const char *g_x, *g_y;      /* Base point.  */
-} ecc_domain_parms_t;
-
-/* This static table defines all available curves.  */
-static const ecc_domain_parms_t domain_parms[] =
-  {
-    {
-      "NIST P-192", 192, 1,
-      "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
-      "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
-      "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
-      "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
-
-      "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
-      "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
-    },
-    {
-      "NIST P-224", 224, 1,
-      "0xffffffffffffffffffffffffffffffff000000000000000000000001",
-      "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
-      "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
-      "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
-
-      "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
-      "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
-    },
-    {
-      "NIST P-256", 256, 1,
-      "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
-      "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
-      "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
-      "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
-
-      "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
-      "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
-    },
-    {
-      "NIST P-384", 384, 1,
-      "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
-      "ffffffff0000000000000000ffffffff",
-      "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
-      "ffffffff0000000000000000fffffffc",
-      "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
-      "c656398d8a2ed19d2a85c8edd3ec2aef",
-      "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
-      "581a0db248b0a77aecec196accc52973",
-
-      "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
-      "5502f25dbf55296c3a545e3872760ab7",
-      "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
-      "0a60b1ce1d7e819d7a431d7c90ea0e5f"
-    },
-    {
-      "NIST P-521", 521, 1,
-      "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-      "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-      "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
-      "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
-      "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
-      "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-      "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
-
-      "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
-      "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
-      "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
-      "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
-    },
-
-    { "brainpoolP160r1", 160, 0,
-      "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
-      "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
-      "0x1e589a8595423412134faa2dbdec95c8d8675e58",
-      "0xe95e4a5f737059dc60df5991d45029409e60fc09",
-      "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
-      "0x1667cb477a1a8ec338f94741669c976316da6321"
-    },
-
-    { "brainpoolP192r1", 192, 0,
-      "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
-      "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
-      "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
-      "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
-      "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
-      "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
-    },
-
-    { "brainpoolP224r1", 224, 0,
-      "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
-      "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
-      "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
-      "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
-      "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
-      "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
-    },
-
-    { "brainpoolP256r1", 256, 0,
-      "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
-      "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
-      "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
-      "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
-      "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
-      "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
-    },
-
-    { "brainpoolP320r1", 320, 0,
-      "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
-      "fcd412b1f1b32e27",
-      "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
-      "92f375a97d860eb4",
-      "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981"
-      "6f5eb4ac8fb1f1a6",
-      "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9"
-      "8691555b44c59311",
-      "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
-      "10af8d0d39e20611",
-      "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
-      "d35245d1692e8ee1"
-    },
-
-    { "brainpoolP384r1", 384, 0,
-      "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
-      "acd3a729901d1a71874700133107ec53",
-      "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
-      "8aa5814a503ad4eb04a8c7dd22ce2826",
-      "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5"
-      "7cb4390295dbc9943ab78696fa504c11",
-      "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7"
-      "cf3ab6af6b7fc3103b883202e9046565",
-      "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
-      "e826e03436d646aaef87b2e247d4af1e",
-      "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
-      "0e4646217791811142820341263c5315"
-    },
-
-    { "brainpoolP512r1", 512, 0,
-      "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
-      "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
-      "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
-      "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca",
-      "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7"
-      "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723",
-      "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870"
-      "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
-      "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
-      "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
-      "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
-      "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
-    },
-
-    { NULL, 0, 0, NULL, NULL, NULL, NULL }
-  };
+#include "ecc-common.h"
 
 
 /* Registered progress function and its callback value. */
@@ -303,7 +73,6 @@ static void *progress_cb_data;
 #define point_init(a)  _gcry_mpi_point_init ((a))
 #define point_free(a)  _gcry_mpi_point_free_parts ((a))
 
-
 

 /* Local prototypes. */
 static void test_keys (ECC_secret_key * sk, unsigned int nbits);
@@ -339,66 +108,6 @@ _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
 
 

 
-/* Set the value from S into D.  */
-static void
-point_set (mpi_point_t d, mpi_point_t s)
-{
-  mpi_set (d->x, s->x);
-  mpi_set (d->y, s->y);
-  mpi_set (d->z, s->z);
-}
-
-
-/*
- * Release a curve object.
- */
-static void
-curve_free (elliptic_curve_t *E)
-{
-  mpi_free (E->p); E->p = NULL;
-  mpi_free (E->a); E->a = NULL;
-  mpi_free (E->b);  E->b = NULL;
-  point_free (&E->G);
-  mpi_free (E->n);  E->n = NULL;
-}
-
-
-/*
- * Return a copy of a curve object.
- */
-static elliptic_curve_t
-curve_copy (elliptic_curve_t E)
-{
-  elliptic_curve_t R;
-
-  R.p = mpi_copy (E.p);
-  R.a = mpi_copy (E.a);
-  R.b = mpi_copy (E.b);
-  point_init (&R.G);
-  point_set (&R.G, &E.G);
-  R.n = mpi_copy (E.n);
-
-  return R;
-}
-
-
-/* Helper to scan a hex string. */
-static gcry_mpi_t
-scanval (const char *string)
-{
-  gpg_error_t err;
-  gcry_mpi_t val;
-
-  err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
-  if (err)
-    log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err));
-  return val;
-}
-
-
-
-

-
 /****************
  * Solve the right side of the equation that defines a curve.
  */
@@ -424,74 +133,6 @@ gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base)
 }
 
 
-/* Generate the crypto system setup.  This function takes the NAME of
-   a curve or the desired number of bits and stores at R_CURVE the
-   parameters of the named curve or those of a suitable curve.  If
-   R_NBITS is not NULL, the chosen number of bits is stored there.  */
-static gpg_err_code_t
-fill_in_curve (unsigned int nbits, const char *name,
-               elliptic_curve_t *curve, unsigned int *r_nbits)
-{
-  int idx, aliasno;
-  const char *resname = NULL; /* Set to a found curve name.  */
-
-  if (name)
-    {
-      /* First check our native curves.  */
-      for (idx = 0; domain_parms[idx].desc; idx++)
-        if (!strcmp (name, domain_parms[idx].desc))
-          {
-            resname = domain_parms[idx].desc;
-            break;
-          }
-      /* If not found consult the alias table.  */
-      if (!domain_parms[idx].desc)
-        {
-          for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
-            if (!strcmp (name, curve_aliases[aliasno].other))
-              break;
-          if (curve_aliases[aliasno].name)
-            {
-              for (idx = 0; domain_parms[idx].desc; idx++)
-                if (!strcmp (curve_aliases[aliasno].name,
-                             domain_parms[idx].desc))
-                  {
-                    resname = domain_parms[idx].desc;
-                    break;
-                  }
-            }
-        }
-    }
-  else
-    {
-      for (idx = 0; domain_parms[idx].desc; idx++)
-        if (nbits == domain_parms[idx].nbits)
-          break;
-    }
-  if (!domain_parms[idx].desc)
-    return GPG_ERR_INV_VALUE;
-
-  /* In fips mode we only support NIST curves.  Note that it is
-     possible to bypass this check by specifying the curve parameters
-     directly.  */
-  if (fips_mode () && !domain_parms[idx].fips )
-    return GPG_ERR_NOT_SUPPORTED;
-
-  if (r_nbits)
-    *r_nbits = domain_parms[idx].nbits;
-  curve->p = scanval (domain_parms[idx].p);
-  curve->a = scanval (domain_parms[idx].a);
-  curve->b = scanval (domain_parms[idx].b);
-  curve->n = scanval (domain_parms[idx].n);
-  curve->G.x = scanval (domain_parms[idx].g_x);
-  curve->G.y = scanval (domain_parms[idx].g_y);
-  curve->G.z = mpi_alloc_set_ui (1);
-  curve->name = resname;
-
-  return 0;
-}
-
-
 /*
  * First obtain the setup.  Over the finite field randomize an scalar
  * secret value, and calculate the public point.
@@ -511,7 +152,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
 
   *r_usedcurve = NULL;
 
-  err = fill_in_curve (nbits, name, &E, &nbits);
+  err = _gcry_ecc_fill_in_curve (nbits, name, &E, &nbits);
   if (err)
     return err;
 
@@ -605,7 +246,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
   point_free (&Q);
 
   *r_usedcurve = E.name;
-  curve_free (&E);
+  _gcry_ecc_curve_free (&E);
 
   /* Now we can test our keys (this should never fail!).  */
   test_keys (sk, nbits - 64);
@@ -636,7 +277,7 @@ test_keys (ECC_secret_key *sk, unsigned int nbits)
 
   point_init (&R_);
 
-  pk.E = curve_copy (sk->E);
+  pk.E = _gcry_ecc_curve_copy (sk->E);
   point_init (&pk.Q);
   point_set (&pk.Q, &sk->Q);
 
@@ -654,7 +295,7 @@ test_keys (ECC_secret_key *sk, unsigned int nbits)
     log_debug ("ECDSA operation: sign, verify ok.\n");
 
   point_free (&pk.Q);
-  curve_free (&pk.E);
+  _gcry_ecc_curve_free (&pk.E);
 
   point_free (&R_);
   mpi_free (s);
@@ -728,7 +369,7 @@ check_secret_key (ECC_secret_key * sk)
       goto leave;
     }
 
-  /* Fast path for loaded secret keys - sk->Q is already in affine coordinates */
+  /* Fast path for loaded secret keys - Q is already in affine coordinates */
   if (!mpi_cmp_ui (sk->Q.z, 1))
     {
       if (mpi_cmp (x1, sk->Q.x) || mpi_cmp (y_2, sk->Q.y))
@@ -976,124 +617,6 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s)
 /*********************************************
  **************  interface  ******************
  *********************************************/
-static gcry_mpi_t
-ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p)
-{
-  gpg_error_t err;
-  int pbytes = (mpi_get_nbits (p)+7)/8;
-  size_t n;
-  unsigned char *buf, *ptr;
-  gcry_mpi_t result;
-
-  buf = gcry_xmalloc ( 1 + 2*pbytes );
-  *buf = 04; /* Uncompressed point.  */
-  ptr = buf+1;
-  err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x);
-  if (err)
-    log_fatal ("mpi_print failed: %s\n", gpg_strerror (err));
-  if (n < pbytes)
-    {
-      memmove (ptr+(pbytes-n), ptr, n);
-      memset (ptr, 0, (pbytes-n));
-    }
-  ptr += pbytes;
-  err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y);
-  if (err)
-    log_fatal ("mpi_print failed: %s\n", gpg_strerror (err));
-  if (n < pbytes)
-    {
-      memmove (ptr+(pbytes-n), ptr, n);
-      memset (ptr, 0, (pbytes-n));
-    }
-
-  err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL);
-  if (err)
-    log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err));
-  gcry_free (buf);
-
-  return result;
-}
-
-
-/* Convert POINT into affine coordinates using the context CTX and
-   return a newly allocated MPI.  If the conversion is not possible
-   NULL is returned.  This function won't print an error message.  */
-gcry_mpi_t
-_gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ectx)
-{
-  gcry_mpi_t g_x, g_y, result;
-
-  g_x = mpi_new (0);
-  g_y = mpi_new (0);
-  if (_gcry_mpi_ec_get_affine (g_x, g_y, point, ectx))
-    result = NULL;
-  else
-    result = ec2os (g_x, g_y, ectx->p);
-  mpi_free (g_x);
-  mpi_free (g_y);
-
-  return result;
-}
-
-
-/* RESULT must have been initialized and is set on success to the
-   point given by VALUE.  */
-static gcry_error_t
-os2ec (mpi_point_t result, gcry_mpi_t value)
-{
-  gcry_error_t err;
-  size_t n;
-  unsigned char *buf;
-  gcry_mpi_t x, y;
-
-  n = (mpi_get_nbits (value)+7)/8;
-  buf = gcry_xmalloc (n);
-  err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, n, &n, value);
-  if (err)
-    {
-      gcry_free (buf);
-      return err;
-    }
-  if (n < 1)
-    {
-      gcry_free (buf);
-      return GPG_ERR_INV_OBJ;
-    }
-  if (*buf != 4)
-    {
-      gcry_free (buf);
-      return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression.  */
-    }
-  if ( ((n-1)%2) )
-    {
-      gcry_free (buf);
-      return GPG_ERR_INV_OBJ;
-    }
-  n = (n-1)/2;
-  err = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL);
-  if (err)
-    {
-      gcry_free (buf);
-      return err;
-    }
-  err = gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL);
-  gcry_free (buf);
-  if (err)
-    {
-      mpi_free (x);
-      return err;
-    }
-
-  mpi_set (result->x, x);
-  mpi_set (result->y, y);
-  mpi_set_ui (result->z, 1);
-
-  mpi_free (x);
-  mpi_free (y);
-
-  return 0;
-}
-
 
 /* Extended version of ecc_generate.  */
 static gcry_err_code_t
@@ -1153,9 +676,9 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
   skey[0] = sk.E.p;
   skey[1] = sk.E.a;
   skey[2] = sk.E.b;
-  skey[3] = ec2os (g_x, g_y, sk.E.p);
+  skey[3] = _gcry_ecc_ec2os (g_x, g_y, sk.E.p);
   skey[4] = sk.E.n;
-  skey[5] = ec2os (q_x, q_y, sk.E.p);
+  skey[5] = _gcry_ecc_ec2os (q_x, q_y, sk.E.p);
   skey[6] = sk.d;
 
   mpi_free (g_x);
@@ -1195,150 +718,6 @@ ecc_generate (int algo, unsigned int nbits, unsigned long evalue,
 }
 
 
-/* Return the parameters of the curve NAME in an MPI array.  */
-static gcry_err_code_t
-ecc_get_param (const char *name, gcry_mpi_t *pkey)
-{
-  gpg_err_code_t err;
-  unsigned int nbits;
-  elliptic_curve_t E;
-  mpi_ec_t ctx;
-  gcry_mpi_t g_x, g_y;
-
-  err = fill_in_curve (0, name, &E, &nbits);
-  if (err)
-    return err;
-
-  g_x = mpi_new (0);
-  g_y = mpi_new (0);
-  ctx = _gcry_mpi_ec_p_internal_new (E.p, E.a);
-  if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
-    log_fatal ("ecc get param: Failed to get affine coordinates\n");
-  _gcry_mpi_ec_free (ctx);
-  point_free (&E.G);
-
-  pkey[0] = E.p;
-  pkey[1] = E.a;
-  pkey[2] = E.b;
-  pkey[3] = ec2os (g_x, g_y, E.p);
-  pkey[4] = E.n;
-  pkey[5] = NULL;
-
-  mpi_free (g_x);
-  mpi_free (g_y);
-
-  return 0;
-}
-
-
-/* Return the parameters of the curve NAME as an S-expression.  */
-static gcry_sexp_t
-ecc_get_param_sexp (const char *name)
-{
-  gcry_mpi_t pkey[6];
-  gcry_sexp_t result;
-  int i;
-
-  if (ecc_get_param (name, pkey))
-    return NULL;
-
-  if (gcry_sexp_build (&result, NULL,
-                       "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))",
-                       pkey[0], pkey[1], pkey[2], pkey[3], pkey[4]))
-    result = NULL;
-
-  for (i=0; pkey[i]; i++)
-    gcry_mpi_release (pkey[i]);
-
-  return result;
-}
-
-
-/* Return the name matching the parameters in PKEY.  */
-static const char *
-ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
-{
-  gpg_err_code_t err;
-  elliptic_curve_t E;
-  int idx;
-  gcry_mpi_t tmp;
-  const char *result = NULL;
-
-  if (r_nbits)
-    *r_nbits = 0;
-
-  if (!pkey)
-    {
-      idx = iterator;
-      if (idx >= 0 && idx < DIM (domain_parms))
-        {
-          result = domain_parms[idx].desc;
-          if (r_nbits)
-            *r_nbits = domain_parms[idx].nbits;
-        }
-      return result;
-    }
-
-  if (!pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4])
-    return NULL;
-
-  E.p = pkey[0];
-  E.a = pkey[1];
-  E.b = pkey[2];
-  point_init (&E.G);
-  err = os2ec (&E.G, pkey[3]);
-  if (err)
-    {
-      point_free (&E.G);
-      return NULL;
-    }
-  E.n = pkey[4];
-
-  for (idx = 0; domain_parms[idx].desc; idx++)
-    {
-      tmp = scanval (domain_parms[idx].p);
-      if (!mpi_cmp (tmp, E.p))
-        {
-          mpi_free (tmp);
-          tmp = scanval (domain_parms[idx].a);
-          if (!mpi_cmp (tmp, E.a))
-            {
-              mpi_free (tmp);
-              tmp = scanval (domain_parms[idx].b);
-              if (!mpi_cmp (tmp, E.b))
-                {
-                  mpi_free (tmp);
-                  tmp = scanval (domain_parms[idx].n);
-                  if (!mpi_cmp (tmp, E.n))
-                    {
-                      mpi_free (tmp);
-                      tmp = scanval (domain_parms[idx].g_x);
-                      if (!mpi_cmp (tmp, E.G.x))
-                        {
-                          mpi_free (tmp);
-                          tmp = scanval (domain_parms[idx].g_y);
-                          if (!mpi_cmp (tmp, E.G.y))
-                            {
-                              mpi_free (tmp);
-                              result = domain_parms[idx].desc;
-                              if (r_nbits)
-                                *r_nbits = domain_parms[idx].nbits;
-                              break;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-      mpi_free (tmp);
-    }
-
-  point_free (&E.G);
-
-  return result;
-}
-
-
 static gcry_err_code_t
 ecc_check_secret_key (int algo, gcry_mpi_t *skey)
 {
@@ -1356,7 +735,7 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey)
   sk.E.a = skey[1];
   sk.E.b = skey[2];
   point_init (&sk.E.G);
-  err = os2ec (&sk.E.G, skey[3]);
+  err = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
   if (err)
     {
       point_free (&sk.E.G);
@@ -1364,7 +743,7 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey)
     }
   sk.E.n = skey[4];
   point_init (&sk.Q);
-  err = os2ec (&sk.Q, skey[5]);
+  err = _gcry_ecc_os2ec (&sk.Q, skey[5]);
   if (err)
     {
       point_free (&sk.E.G);
@@ -1403,7 +782,7 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
   sk.E.a = skey[1];
   sk.E.b = skey[2];
   point_init (&sk.E.G);
-  err = os2ec (&sk.E.G, skey[3]);
+  err = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
   if (err)
     {
       point_free (&sk.E.G);
@@ -1446,7 +825,7 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
   pk.E.a = pkey[1];
   pk.E.b = pkey[2];
   point_init (&pk.E.G);
-  err = os2ec (&pk.E.G, pkey[3]);
+  err = _gcry_ecc_os2ec (&pk.E.G, pkey[3]);
   if (err)
     {
       point_free (&pk.E.G);
@@ -1454,7 +833,7 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
     }
   pk.E.n = pkey[4];
   point_init (&pk.Q);
-  err = os2ec (&pk.Q, pkey[5]);
+  err = _gcry_ecc_os2ec (&pk.Q, pkey[5]);
   if (err)
     {
       point_free (&pk.E.G);
@@ -1538,7 +917,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
   pk.E.a = pkey[1];
   pk.E.b = pkey[2];
   point_init (&pk.E.G);
-  err = os2ec (&pk.E.G, pkey[3]);
+  err = _gcry_ecc_os2ec (&pk.E.G, pkey[3]);
   if (err)
     {
       point_free (&pk.E.G);
@@ -1546,7 +925,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
     }
   pk.E.n = pkey[4];
   point_init (&pk.Q);
-  err = os2ec (&pk.Q, pkey[5]);
+  err = _gcry_ecc_os2ec (&pk.Q, pkey[5]);
   if (err)
     {
       point_free (&pk.E.G);
@@ -1572,7 +951,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
       log_fatal ("ecdh: Failed to get affine coordinates for kdG\n");
 
-    result[0] = ec2os (x, y, pk.E.p);
+    result[0] = _gcry_ecc_ec2os (x, y, pk.E.p);
 
     /* R = kG */
     _gcry_mpi_ec_mul_point (&R, k, &pk.E.G, ctx);
@@ -1580,7 +959,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
       log_fatal ("ecdh: Failed to get affine coordinates for kG\n");
 
-    result[1] = ec2os (x, y, pk.E.p);
+    result[1] = _gcry_ecc_ec2os (x, y, pk.E.p);
 
     mpi_free (x);
     mpi_free (y);
@@ -1635,7 +1014,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
     return GPG_ERR_BAD_MPI;
 
   point_init (&kG);
-  err = os2ec (&kG, data[0]);
+  err = _gcry_ecc_os2ec (&kG, data[0]);
   if (err)
     {
       point_free (&kG);
@@ -1647,7 +1026,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
   sk.E.a = skey[1];
   sk.E.b = skey[2];
   point_init (&sk.E.G);
-  err = os2ec (&sk.E.G, skey[3]);
+  err = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
   if (err)
     {
       point_free (&kG);
@@ -1656,7 +1035,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
     }
   sk.E.n = skey[4];
   point_init (&sk.Q);
-  err = os2ec (&sk.Q, skey[5]);
+  err = _gcry_ecc_os2ec (&sk.Q, skey[5]);
   if (err)
     {
       point_free (&kG);
@@ -1684,7 +1063,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
       log_fatal ("ecdh: Failed to get affine coordinates\n");
 
-    r = ec2os (x, y, sk.E.p);
+    r = _gcry_ecc_ec2os (x, y, sk.E.p);
     mpi_free (x);
     mpi_free (y);
   }
@@ -1764,7 +1143,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
           ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
           goto leave;
         }
-      ec = ecc_get_param (curve, tmpvalues);
+      ec = _gcry_ecc_get_param (curve, tmpvalues);
       gcry_free (curve);
       if (ec)
         goto leave;
@@ -1824,274 +1203,6 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
    Low-level API helper functions.
  */
 
-/* Helper to extract an MPI from key parameters.  */
-static gpg_err_code_t
-mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name)
-{
-  gcry_err_code_t ec = 0;
-  gcry_sexp_t l1;
-
-  l1 = gcry_sexp_find_token (keyparam, name, 0);
-  if (l1)
-    {
-      *r_a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
-      gcry_sexp_release (l1);
-      if (!*r_a)
-        ec = GPG_ERR_INV_OBJ;
-    }
-  return ec;
-}
-
-/* Helper to extract a point from key parameters.  If no parameter
-   with NAME is found, the functions tries to find a non-encoded point
-   by appending ".x", ".y" and ".z" to NAME.  ".z" is in this case
-   optional and defaults to 1.  */
-static gpg_err_code_t
-point_from_keyparam (gcry_mpi_point_t *r_a,
-                     gcry_sexp_t keyparam, const char *name)
-{
-  gcry_err_code_t ec;
-  gcry_mpi_t a = NULL;
-  gcry_mpi_point_t point;
-
-  ec = mpi_from_keyparam (&a, keyparam, name);
-  if (ec)
-    return ec;
-
-  if (a)
-    {
-      point = gcry_mpi_point_new (0);
-      ec = os2ec (point, a);
-      mpi_free (a);
-      if (ec)
-        {
-          gcry_mpi_point_release (point);
-          return ec;
-        }
-    }
-  else
-    {
-      char *tmpname;
-      gcry_mpi_t x = NULL;
-      gcry_mpi_t y = NULL;
-      gcry_mpi_t z = NULL;
-
-      tmpname = gcry_malloc (strlen (name) + 2 + 1);
-      if (!tmpname)
-        return gpg_err_code_from_syserror ();
-      strcpy (stpcpy (tmpname, name), ".x");
-      ec = mpi_from_keyparam (&x, keyparam, tmpname);
-      if (ec)
-        {
-          gcry_free (tmpname);
-          return ec;
-        }
-      strcpy (stpcpy (tmpname, name), ".y");
-      ec = mpi_from_keyparam (&y, keyparam, tmpname);
-      if (ec)
-        {
-          mpi_free (x);
-          gcry_free (tmpname);
-          return ec;
-        }
-      strcpy (stpcpy (tmpname, name), ".z");
-      ec = mpi_from_keyparam (&z, keyparam, tmpname);
-      if (ec)
-        {
-          mpi_free (y);
-          mpi_free (x);
-          gcry_free (tmpname);
-          return ec;
-        }
-      if (!z)
-        z = mpi_set_ui (NULL, 1);
-      if (x && y)
-        point = gcry_mpi_point_snatch_set (NULL, x, y, z);
-      else
-        {
-          mpi_free (x);
-          mpi_free (y);
-          mpi_free (z);
-          point = NULL;
-        }
-      gcry_free (tmpname);
-    }
-
-  if (point)
-    *r_a = point;
-  return 0;
-}
-
-
-/* This function creates a new context for elliptic curve operations.
-   Either KEYPARAM or CURVENAME must be given.  If both are given and
-   KEYPARAM has no curve parameter CURVENAME is used to add missing
-   parameters.  On success 0 is returned and the new context stored at
-   R_CTX.  On error NULL is stored at R_CTX and an error code is
-   returned.  The context needs to be released using
-   gcry_ctx_release.  */
-gpg_err_code_t
-_gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
-                  gcry_sexp_t keyparam, const char *curvename)
-{
-  gpg_err_code_t errc;
-  gcry_ctx_t ctx = NULL;
-  gcry_mpi_t p = NULL;
-  gcry_mpi_t a = NULL;
-  gcry_mpi_t b = NULL;
-  gcry_mpi_point_t G = NULL;
-  gcry_mpi_t n = NULL;
-  gcry_mpi_point_t Q = NULL;
-  gcry_mpi_t d = NULL;
-  gcry_sexp_t l1;
-
-  *r_ctx = NULL;
-
-  if (keyparam)
-    {
-      errc = mpi_from_keyparam (&p, keyparam, "p");
-      if (errc)
-        goto leave;
-      errc = mpi_from_keyparam (&a, keyparam, "a");
-      if (errc)
-        goto leave;
-      errc = mpi_from_keyparam (&b, keyparam, "b");
-      if (errc)
-        goto leave;
-      errc = point_from_keyparam (&G, keyparam, "g");
-      if (errc)
-        goto leave;
-      errc = mpi_from_keyparam (&n, keyparam, "n");
-      if (errc)
-        goto leave;
-      errc = point_from_keyparam (&Q, keyparam, "q");
-      if (errc)
-        goto leave;
-      errc = mpi_from_keyparam (&d, keyparam, "d");
-      if (errc)
-        goto leave;
-    }
-
-
-  /* Check whether a curve parameter is available and use that to fill
-     in missing values.  If no curve parameter is available try an
-     optional provided curvename.  If only the curvename has been
-     given use that one. */
-  if (keyparam)
-    l1 = gcry_sexp_find_token (keyparam, "curve", 5);
-  else
-    l1 = NULL;
-  if (l1 || curvename)
-    {
-      char *name;
-      elliptic_curve_t *E;
-
-      if (l1)
-        {
-          name = _gcry_sexp_nth_string (l1, 1);
-          gcry_sexp_release (l1);
-          if (!name)
-            {
-              errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
-              goto leave;
-            }
-        }
-      else
-        name = NULL;
-
-      E = gcry_calloc (1, sizeof *E);
-      if (!E)
-        {
-          errc = gpg_err_code_from_syserror ();
-          gcry_free (name);
-          goto leave;
-        }
-
-      errc = fill_in_curve (0, name? name : curvename, E, NULL);
-      gcry_free (name);
-      if (errc)
-        {
-          gcry_free (E);
-          goto leave;
-        }
-
-      if (!p)
-        {
-          p = E->p;
-          E->p = NULL;
-        }
-      if (!a)
-        {
-          a = E->a;
-          E->a = NULL;
-        }
-      if (!b)
-        {
-          b = E->b;
-          E->b = NULL;
-        }
-      if (!G)
-        {
-          G = gcry_mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
-          E->G.x = NULL;
-          E->G.y = NULL;
-          E->G.z = NULL;
-        }
-      if (!n)
-        {
-          n = E->n;
-          E->n = NULL;
-        }
-      curve_free (E);
-      gcry_free (E);
-    }
-
-  errc = _gcry_mpi_ec_p_new (&ctx, p, a);
-  if (!errc)
-    {
-      mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
-
-      if (b)
-        {
-          ec->b = b;
-          b = NULL;
-        }
-      if (G)
-        {
-          ec->G = G;
-          G = NULL;
-        }
-      if (n)
-        {
-          ec->n = n;
-          n = NULL;
-        }
-      if (Q)
-        {
-          ec->Q = Q;
-          Q = NULL;
-        }
-      if (d)
-        {
-          ec->d = d;
-          d = NULL;
-        }
-
-      *r_ctx = ctx;
-    }
-
- leave:
-  mpi_free (p);
-  mpi_free (a);
-  mpi_free (b);
-  gcry_mpi_point_release (G);
-  mpi_free (n);
-  gcry_mpi_point_release (Q);
-  mpi_free (d);
-  return errc;
-}
-
-
 /* This is the wroker function for gcry_pubkey_get_sexp for ECC
    algorithms.  Note that the caller has already stored NULL at
    R_SEXP.  */
@@ -2264,7 +1375,7 @@ pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa =
     run_selftests,
     ecc_generate_ext,
     compute_keygrip,
-    ecc_get_param,
-    ecc_get_curve,
-    ecc_get_param_sexp
+    _gcry_ecc_get_param,
+    _gcry_ecc_get_curve,
+    _gcry_ecc_get_param_sexp
   };
diff --git a/configure.ac b/configure.ac
index f20d0a1..b54b4d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1452,7 +1452,8 @@ fi
 
 LIST_MEMBER(ecc, $enabled_pubkey_ciphers)
 if test "$found" = "1" ; then
-   GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS ecc.lo"
+   GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS \
+                          ecc.lo ecc-curves.lo ecc-misc.lo"
    AC_DEFINE(USE_ECC, 1, [Defined if this module should be included])
 fi
 

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

Summary of changes:
 cipher/Makefile.am  |    2 +-
 cipher/ecc-common.h |   80 +++++
 cipher/ecc-curves.c |  731 +++++++++++++++++++++++++++++++++++++++
 cipher/ecc-misc.c   |  183 ++++++++++
 cipher/ecc.c        |  939 ++-------------------------------------------------
 configure.ac        |    3 +-
 mpi/mpicoder.c      |   36 ++-
 tests/Makefile.am   |    2 +-
 tests/t-convert.c   |  160 +++++++++
 9 files changed, 1210 insertions(+), 926 deletions(-)
 create mode 100644 cipher/ecc-common.h
 create mode 100644 cipher/ecc-curves.c
 create mode 100644 cipher/ecc-misc.c
 create mode 100644 tests/t-convert.c


hooks/post-receive
-- 
The GNU crypto library
http://git.gnupg.org




More information about the Gnupg-commits mailing list