[git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-93-g5e743bc

by Werner Koch cvs at cvs.gnupg.org
Mon Mar 11 16:09:58 CET 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  5e743bc72e3fee3d550d0d7ae98596b7de6b46f8 (commit)
       via  8ac9e756d3ca545a9b97e61ad3d42fc2e877d788 (commit)
       via  7cce620acddac2df024ca421ed3abc32a88f3738 (commit)
       via  6c4767637c512127a4362732b3ec51068554d328 (commit)
      from  6782b2d7817c449fb2cf122cacd792b594f89d7c (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 5e743bc72e3fee3d550d0d7ae98596b7de6b46f8
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Mar 11 15:54:47 2013 +0100

    Document the new point and EC functions
    
    --

diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 8bfcbfd..c986ec7 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -12,8 +12,9 @@ This manual is for Libgcrypt
 (version @value{VERSION}, @value{UPDATED}),
 which is GNU's library of cryptographic building blocks.
 
-Copyright @copyright{} 2000, 2002, 2003, 2004, 2006, 2007, 2008, 2009,
-2011, 2012 Free Software Foundation, Inc.
+ at noindent
+Copyright @copyright{} 2000, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2011, 2012 Free Software Foundation, Inc. @*
+Copyright @copyright{} 2012, 2013 g10 Code GmbH
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -91,7 +92,7 @@ section entitled ``GNU General Public License''.
 * S-expressions::                How to manage S-expressions.
 * MPI library::                  How to work with multi-precision-integers.
 * Prime numbers::                How to use the Prime number related functions.
-* Utilities::                    Utility functions.
+* Utilities::                   Utility functions.
 * Tools::                        Utility tools
 * Architecture::                 How Libgcrypt works internally.
 
@@ -3523,6 +3524,7 @@ likely want to use @code{GCRYMPI_FMT_USG}.
 * Calculations::                Performing MPI calculations.
 * Comparisons::                 How to compare MPI values.
 * Bit manipulations::           How to access single bits of MPI values.
+* EC functions::                Elliptic curve related functions.
 * Miscellaneous::               Miscellaneous MPI functions.
 @end menu
 
@@ -3540,6 +3542,10 @@ numbers are called MPIs (multi-precision-integers).
 This type represents an object to hold an MPI.
 @end deftp
 
+ at deftp {Data type} {gcry_mpi_point_t}
+This type represents an object to hold a point for elliptic curve math.
+ at end deftp
+
 @node Basic functions
 @section Basic functions
 
@@ -3843,6 +3849,124 @@ Shift the value of @var{a} by @var{n} bits to the left and store the
 result in @var{x}.
 @end deftypefun
 
+ at node EC functions
+ at section EC functions
+
+ at noindent
+Libgcrypt provides an API to access low level functions used by its
+elliptic curve implementation.  These functions allow to implement
+elliptic curve methods for which no explicit support is available.
+
+ at deftypefun gcry_mpi_point_t gcry_mpi_point_new (@w{unsigned int @var{nbits}})
+
+Allocate a new point object, initialize it to 0, and allocate enough
+memory for a points of at least @var{nbits}.  This pre-allocation
+yields only a small performance win and is not really necessary
+because Libgcrypt automatically re-allocates the required memory.
+Using 0 for @var{nbits} is usually the right thing to do.
+ at end deftypefun
+
+ at deftypefun void gcry_mpi_point_release (@w{gcry_mpi_point_t @var{point}})
+
+Release @var{point} and free all associated resources.  Passing
+ at code{NULL} is allowed and ignored.
+ at end deftypefun
+
+ at deftypefun void gcry_mpi_point_get (@w{gcry_mpi_t @var{x}}, @
+ @w{gcry_mpi_t @var{y}}, @w{gcry_mpi_t @var{z}}, @
+ @w{gcry_mpi_point_t @var{point}})
+
+Store the projective coordinates from @var{point} into the MPIs
+ at var{x}, @var{y}, and @var{z}.  If a coordinate is not required,
+ at code{NULL} may be used for @var{x}, @var{y}, or @var{z}.
+ at end deftypefun
+
+ at deftypefun void gcry_mpi_point_snatch_get (@w{gcry_mpi_t @var{x}}, @
+ @w{gcry_mpi_t @var{y}}, @w{gcry_mpi_t @var{z}}, @
+ @w{gcry_mpi_point_t @var{point}})
+
+Store the projective coordinates from @var{point} into the MPIs
+ at var{x}, @var{y}, and @var{z}.  If a coordinate is not required,
+ at code{NULL} may be used for @var{x}, @var{y}, or @var{z}.  The object
+ at var{point} is then released.  Using this function instead of
+ at code{gcry_mpi_point_get} and @code{gcry_mpi_point_release} has the
+advantage of avoiding some extra memory allocations and copies.
+ at end deftypefun
+
+ at deftypefun gcry_mpi_point_t gcry_mpi_point_set ( @
+ @w{gcry_mpi_point_t @var{point}}, @
+ @w{gcry_mpi_t @var{x}}, @w{gcry_mpi_t @var{y}}, @w{gcry_mpi_t @var{z}})
+
+Store the projective coordinates from @var{x}, @var{y}, and @var{z}
+into @var{point}.  If a coordinate is given as @code{NULL}, the value
+0 is used.  If @code{NULL} is used for @var{point} a new point object
+is allocated and returned.  Returns @var{point} or the newly allocated
+point object.
+ at end deftypefun
+
+ at deftypefun gcry_mpi_point_t gcry_mpi_point_snatch_set ( @
+ @w{gcry_mpi_point_t @var{point}}, @
+ @w{gcry_mpi_t @var{x}}, @w{gcry_mpi_t @var{y}}, @w{gcry_mpi_t @var{z}})
+
+Store the projective coordinates from @var{x}, @var{y}, and @var{z}
+into @var{point}.  If a coordinate is given as @code{NULL}, the value
+0 is used.  If @code{NULL} is used for @var{point} a new point object
+is allocated and returned.  The MPIs @var{x}, @var{y}, and @var{z} are
+released.  Using this function instead of @code{gcry_mpi_point_set}
+and 3 calls to @code{gcry_mpi_release} has the advantage of avoiding
+some extra memory allocations and copies.  Returns @var{point} or the
+newly allocated point object.
+ at end deftypefun
+
+ at anchor{gcry_mpi_ec_p_new}
+ at deftypefun gcry_ctx_t gcry_mpi_ec_p_new (@w{gcry_mpi_t @var{p}}, @
+ @w{gcry_mpi_t @var{a}}
+
+Allocate a new context for elliptic curve operations based on the
+field GF(p).  @var{p} is the prime specifying this field, @var{a} is
+the first coefficient of the Weierstrass equation.  The function
+returns a context object which eventually needs to be released using
+ at ref{gcry_ctx_release}.  On error this function returns @code{NULL}
+and sets @code{errno}.
+ at end deftypefun
+
+ at deftypefun int gcry_mpi_ec_get_affine ( @
+ @w{gcry_mpi_t @var{x}}, @w{gcry_mpi_t @var{y}}, @
+ @w{gcry_mpi_point_t @var{point}}, @w{gcry_ctx_t @var{ctx}})
+
+Compute the affine coordinates from the projective coordinates in
+ at var{point} and store them into @var{x} and @var{y}.  If one
+coordinate is not required, @code{NULL} may be passed to @var{x} or
+ at var{y}.  @var{ctx} is the context object which for example may have
+been created using @ref{gcry_mpi_ec_p_new}. Returns 0 on success or
+not 0 if @var{point} is at infinity.
+ at end deftypefun
+
+ at deftypefun void gcry_mpi_ec_dup ( @
+ @w{gcry_mpi_point_t @var{w}}, @w{gcry_mpi_point_t @var{u}}, @
+ @w{gcry_ctx_t @var{ctx}})
+
+Double the point @var{u} of the elliptic curve described by @var{ctx}
+and store the result into @var{w}.
+ at end deftypefun
+
+ at deftypefun void gcry_mpi_ec_add ( @
+ @w{gcry_mpi_point_t @var{w}}, @w{gcry_mpi_point_t @var{u}}, @
+ @w{gcry_mpi_point_t @var{v}}, @w{gcry_ctx_t @var{ctx}})
+
+Add the points @var{u} and @var{v} of the elliptic curve described by
+ at var{ctx} and store the result into @var{w}.
+ at end deftypefun
+
+ at deftypefun void gcry_mpi_ec_mul ( @
+ @w{gcry_mpi_point_t @var{w}}, @w{gcry_mpi_t @var{n}}, @
+ @w{gcry_mpi_point_t @var{u}}, @w{gcry_ctx_t @var{ctx}})
+
+Multiply the point @var{u} of the elliptic curve described by
+ at var{ctx} by @var{n} and store the result into @var{w}.
+ at end deftypefun
+
+
 @node Miscellaneous
 @section Miscellaneous
 
@@ -3950,7 +4074,8 @@ wrong.
 @chapter Utilities
 
 @menu
-* Memory allocation:: Functions related with memory allocation.
+* Memory allocation::   Functions related with memory allocation.
+* Context management::  Functions related with context management.
 @end menu
 
 @node Memory allocation
@@ -3992,6 +4117,25 @@ gcry_realloc tries to use secure memory as well.
 Release the memory area pointed to by @var{p}.
 @end deftypefun
 
+
+ at node Context management
+ at section Context management
+
+Some function make use of a context object.  As of now there are only
+a few math functions. However, future versions of Libgcrypt may make
+more use of this context object.
+
+ at deftp {Data type} {gcry_ctx_t}
+This type is used to refer to the general purpose context object.
+ at end deftp
+
+ at anchor{gcry_ctx_release}
+ at deftypefun void gcry_ctx_release (gcry_ctx_t @var{ctx})
+Release the context object @var{ctx} and all associated resources.  A
+ at code{NULL} passed as @var{ctx} is ignored.
+ at end deftypefun
+
+
 @c **********************************************************
 @c *********************  Tools  ****************************
 @c **********************************************************

commit 8ac9e756d3ca545a9b97e61ad3d42fc2e877d788
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Mar 8 22:10:23 2013 +0100

    mpi: Add an API for EC math.
    
    * src/context.c, src/context.h: New.
    * src/Makefile.am (libgcrypt_la_SOURCES): Add new files.
    * src/gcrypt.h.in (struct gcry_context, gcry_ctx_t): New types.
    (gcry_ctx_release): New prototype.
    (gcry_mpi_ec_p_new, gcry_mpi_ec_get_affine, gcry_mpi_ec_dup)
    (gcry_mpi_ec_add, gcry_mpi_ec_mul): New prototypes.
    * mpi/ec.c: Include errno.h and context.h.
    (_gcry_mpi_ec_init): Rename to ..
    (ec_p_init): this, make static, remove allocation and add arg CTX.
    (_gcry_mpi_ec_p_internal_new): New; to replace _gcry_mpi_ec_init.
    Change all callers to use this func.
    (_gcry_mpi_ec_free): Factor code out to ..
    (ec_deinit): New func.
    (gcry_mpi_ec_p_new): New.
    * src/visibility.c: Include context.h and mpi.h.
    (gcry_mpi_ec_p_new, gcry_mpi_ec_get_affine, gcry_mpi_ec_dup)
    (gcry_mpi_ec_add, gcry_mpi_ec_mul)
    (gcry_ctx_release): New wrapper functions.
    * src/visibility.h: Mark new wrapper functions visible.
    * src/libgcrypt.def, src/libgcrypt.vers: Add new symbols.
    * tests/t-mpi-point.c (print_mpi, hex2mpi, cmp_mpihex): New.
    (context_alloc): New.
    (make_point, basic_ec_math): New.
    --
    
    This part finishes the basic API to do EC math.  It provides a wrapper
    around all internal functions.  tests/t-mpi-point.c may be useful as
    sample code.  Eventually we will add function to retrieve curve
    parameters etc.

diff --git a/NEWS b/NEWS
index e0ba536..733dd88 100644
--- a/NEWS
+++ b/NEWS
@@ -44,6 +44,12 @@ Noteworthy changes in version 1.6.0 (unreleased)
  gcry_mpi_point_snatch_get       NEW.
  gcry_mpi_point_set              NEW.
  gcry_mpi_point_snatch_set       NEW.
+ gcry_ctx_t                      NEW.
+ gcry_ctx_release                NEW.
+ gcry_mpi_ec_p_new               NEW.
+ gcry_mpi_ec_dup                 NEW.
+ gcry_mpi_ec_add                 NEW.
+ gcry_mpi_ec_mul                 NEW.
 
 
 Noteworthy changes in version 1.5.0 (2011-06-29)
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 789fc6c..4efbef4 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -547,7 +547,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
 
   /* Compute Q.  */
   point_init (&Q);
-  ctx = _gcry_mpi_ec_init (E.p, E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (E.p, E.a);
   _gcry_mpi_ec_mul_point (&Q, d, &E.G, ctx);
 
   /* Copy the stuff to the key structures. */
@@ -672,7 +672,7 @@ check_secret_key (ECC_secret_key * sk)
       goto leave;
     }
 
-  ctx = _gcry_mpi_ec_init (sk->E.p, sk->E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (sk->E.p, sk->E.a);
 
   _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx);
   if (mpi_cmp_ui (Q.z, 0))
@@ -733,7 +733,7 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s)
   mpi_set_ui (s, 0);
   mpi_set_ui (r, 0);
 
-  ctx = _gcry_mpi_ec_init (skey->E.p, skey->E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (skey->E.p, skey->E.a);
 
   while (!mpi_cmp_ui (s, 0)) /* s == 0 */
     {
@@ -805,7 +805,7 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s)
   point_init (&Q1);
   point_init (&Q2);
 
-  ctx = _gcry_mpi_ec_init (pkey->E.p, pkey->E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (pkey->E.p, pkey->E.a);
 
   /* h  = s^(-1) (mod n) */
   mpi_invm (h, s, pkey->E.n);
@@ -1095,7 +1095,7 @@ ecc_get_param (const char *name, gcry_mpi_t *pkey)
 
   g_x = mpi_new (0);
   g_y = mpi_new (0);
-  ctx = _gcry_mpi_ec_init (E.p, E.a);
+  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);
@@ -1424,7 +1424,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
       return err;
     }
 
-  ctx = _gcry_mpi_ec_init (pk.E.p, pk.E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (pk.E.p, pk.E.a);
 
   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
   {
@@ -1536,7 +1536,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
     }
   sk.d = skey[6];
 
-  ctx = _gcry_mpi_ec_init (sk.E.p, sk.E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (sk.E.p, sk.E.a);
 
   /* R = dkG */
   point_init (&R);
diff --git a/mpi/ec.c b/mpi/ec.c
index bb9bea4..e85ec04 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -21,10 +21,12 @@
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <errno.h>
 
 #include "mpi-internal.h"
 #include "longlong.h"
 #include "g10lib.h"
+#include "context.h"
 
 
 #define point_init(a)  _gcry_mpi_point_init ((a))
@@ -348,16 +350,13 @@ ec_invm (gcry_mpi_t x, gcry_mpi_t a, mpi_ec_t ctx)
 
 
 
-/* This function returns a new context for elliptic curve based on the
-   field GF(p).  P is the prime specifying thuis field, A is the first
-   coefficient.
-
-   This context needs to be released using _gcry_mpi_ec_free.  */
-mpi_ec_t
-_gcry_mpi_ec_init (gcry_mpi_t p, gcry_mpi_t a)
+/* This function initialized a context for elliptic curve based on the
+   field GF(p).  P is the prime specifying this field, A is the first
+   coefficient.  CTX is expected to be zeroized.  */
+static void
+ec_p_init (mpi_ec_t ctx, gcry_mpi_t p, gcry_mpi_t a)
 {
   int i;
-  mpi_ec_t ctx;
   gcry_mpi_t tmp;
 
   mpi_normalize (p);
@@ -367,8 +366,6 @@ _gcry_mpi_ec_init (gcry_mpi_t p, gcry_mpi_t a)
      a < p
   */
 
-  ctx = gcry_xcalloc (1, sizeof *ctx);
-
   ctx->p = mpi_copy (p);
   ctx->a = mpi_copy (a);
 
@@ -408,18 +405,15 @@ _gcry_mpi_ec_init (gcry_mpi_t p, gcry_mpi_t a)
 /*         ctx->s[i] = mpi_new (384); */
 /*       ctx->c    = mpi_new (384*2); */
 /*     } */
-
-  return ctx;
 }
 
-void
-_gcry_mpi_ec_free (mpi_ec_t ctx)
+
+static void
+ec_deinit (void *opaque)
 {
+  mpi_ec_t ctx = opaque;
   int i;
 
-  if (!ctx)
-    return;
-
   mpi_free (ctx->p);
   mpi_free (ctx->a);
 
@@ -446,8 +440,62 @@ _gcry_mpi_ec_free (mpi_ec_t ctx)
 /*         mpi_free (ctx->s[i]); */
 /*       mpi_free (ctx->c); */
 /*     } */
+}
+
 
-  gcry_free (ctx);
+/* This function returns a new context for elliptic curve based on the
+   field GF(p).  P is the prime specifying this field, A is the first
+   coefficient.  This function is only used within Libgcrypt and not
+   part of the public API.
+
+   This context needs to be released using _gcry_mpi_ec_free.  */
+mpi_ec_t
+_gcry_mpi_ec_p_internal_new (gcry_mpi_t p, gcry_mpi_t a)
+{
+  mpi_ec_t ctx;
+
+  ctx = gcry_xcalloc (1, sizeof *ctx);
+  ec_p_init (ctx, p, a);
+
+  return ctx;
+}
+
+
+void
+_gcry_mpi_ec_free (mpi_ec_t ctx)
+{
+  if (ctx)
+    {
+      ec_deinit (ctx);
+      gcry_free (ctx);
+    }
+}
+
+
+/* This function returns a new context for elliptic curve operations
+   based on the field GF(p).  P is the prime specifying this field, A
+   is the first coefficient.  This function is part of the public API.
+   On error this function returns NULL and sets ERRNO.
+   The context needs to be released using gcry_ctx_release.  */
+gcry_ctx_t
+gcry_mpi_ec_p_new (gcry_mpi_t p, gcry_mpi_t a)
+{
+  gcry_ctx_t ctx;
+  mpi_ec_t ec;
+
+  if (!p || !a || !mpi_cmp_ui (a, 0))
+    {
+      gpg_err_set_errno (EINVAL);
+      return NULL;
+    }
+
+  ctx = _gcry_ctx_alloc (CONTEXT_TYPE_EC, sizeof *ec, ec_deinit);
+  if (!ctx)
+    return NULL;
+  ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
+  ec_p_init (ec, p, a);
+
+  return ctx;
 }
 
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 9e7dcd5..1869ad3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,7 +59,7 @@ libgcrypt_la_SOURCES = g10lib.h visibility.c visibility.h types.h \
 	misc.c global.c sexp.c hwfeatures.c hwf-common.h \
 	stdmem.c stdmem.h secmem.c secmem.h \
 	mpi.h missing-string.c module.c fips.c \
-	hmac256.c hmac256.h \
+	hmac256.c hmac256.h context.c context.h \
 	ath.h ath.c
 
 EXTRA_libgcrypt_la_SOURCES = hwf-x86.c
diff --git a/src/context.c b/src/context.c
new file mode 100644
index 0000000..ae991c5
--- /dev/null
+++ b/src/context.c
@@ -0,0 +1,118 @@
+/* context.c - Context management
+ * 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 <stdarg.h>
+#include <unistd.h>
+
+#include "g10lib.h"
+#include "mpi.h"
+#include "context.h"
+
+#define CTX_MAGIC "cTx"
+#define CTX_MAGIC_LEN 3
+
+
+/* The definition of the generic context object.  The public typedef
+   gcry_ctx_t is used to access it.  */
+struct gcry_context
+{
+  char magic[CTX_MAGIC_LEN]; /* Magic value to cross check that this
+                                is really a context object. */
+  char type;     /* The type of the context (CONTEXT_TYPE_foo).  */
+
+  void (*deinit)(void*); /* Function used to free the private part. */
+  PROPERLY_ALIGNED_TYPE u;
+};
+
+
+/* Allocate a fresh generic context of contect TYPE and allocate
+   LENGTH extra bytes for private use of the type handler. DEINIT is a
+   fucntion used called to deinitialize the private part; it may be
+   NULL if de-initialization is not required.  Returns NULL and sets
+   ERRNO if memory allocation failed.  */
+gcry_ctx_t
+_gcry_ctx_alloc (int type, size_t length, void (*deinit)(void*))
+{
+  gcry_ctx_t ctx;
+
+  switch (type)
+    {
+    case CONTEXT_TYPE_EC:
+      break;
+    default:
+      log_bug ("bad context type %d given to _gcry_ctx_alloc\n", type);
+      break;
+    }
+
+  if (length < sizeof (PROPERLY_ALIGNED_TYPE))
+    length = sizeof (PROPERLY_ALIGNED_TYPE);
+
+  ctx = gcry_calloc (1, sizeof *ctx - sizeof (PROPERLY_ALIGNED_TYPE) + length);
+  if (!ctx)
+    return NULL;
+  memcpy (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN);
+  ctx->type = type;
+  ctx->deinit = deinit;
+
+  return ctx;
+}
+
+
+/* Return a pointer to the private part of the context CTX.  TYPE is
+   the requested context type.  Using an explicit type allows to cross
+   check the type and eventually allows to store several private
+   contexts in one context object.  The function does not return an
+   error but aborts if the provided CTX is not valid.  */
+void *
+_gcry_ctx_get_pointer (gcry_ctx_t ctx, int type)
+{
+  if (memcmp (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN))
+    log_fatal ("bad pointer %p passed to _gcry_ctx_get_pointer\n", ctx);
+  if (ctx->type != type)
+    log_fatal ("wrong context type %d request for context %p of type %d\n",
+               type, ctx, ctx->type);
+  return &ctx->u;
+}
+
+
+/* Release the generic context CTX.  */
+void
+gcry_ctx_release (gcry_ctx_t ctx)
+{
+  if (!ctx)
+    return;
+  if (memcmp (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN))
+    log_fatal ("bad pointer %p passed to gcry_ctx_relase\n", ctx);
+  switch (ctx->type)
+    {
+    case CONTEXT_TYPE_EC:
+      break;
+    default:
+      log_fatal ("bad context type %d detected in gcry_ctx_relase\n",
+                 ctx->type);
+      break;
+    }
+  if (ctx->deinit)
+    ctx->deinit (&ctx->u);
+  gcry_free (ctx);
+}
diff --git a/src/context.h b/src/context.h
new file mode 100644
index 0000000..72f14d4
--- /dev/null
+++ b/src/context.h
@@ -0,0 +1,31 @@
+/* context.h - Declarations for the context management
+ * 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_CONTEXT_H
+#define GCRY_CONTEXT_H
+
+/* Context types as used in struct gcry_context.  */
+#define CONTEXT_TYPE_EC 1  /* The context is used with EC functions.  */
+
+
+gcry_ctx_t _gcry_ctx_alloc (int type, size_t length, void (*deinit)(void*));
+void *_gcry_ctx_get_pointer (gcry_ctx_t ctx, int type);
+
+
+#endif /*GCRY_CONTEXT_H*/
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 5d2a779..57b841e 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -212,6 +212,10 @@ struct gcry_thread_cbs
 
 
 
+/* A generic context object as used by some functions.  */
+struct gcry_context;
+typedef struct gcry_context *gcry_ctx_t;
+
 /* The data objects used to hold multi precision integers.  */
 struct gcry_mpi;
 typedef struct gcry_mpi *gcry_mpi_t;
@@ -599,6 +603,26 @@ gcry_mpi_point_t gcry_mpi_point_snatch_set (gcry_mpi_point_t point,
                                             gcry_mpi_t x, gcry_mpi_t y,
                                             gcry_mpi_t z);
 
+/* Allocate a new context for elliptic curve operations based on the
+   field GF(p).  P is the prime specifying this field, A is the first
+   coefficient.  Returns NULL on error.  */
+gcry_ctx_t gcry_mpi_ec_p_new (gcry_mpi_t p, gcry_mpi_t a);
+
+/* Store the affine coordinates of POINT into X and Y.  */
+int gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_point_t point,
+                            gcry_ctx_t ctx);
+
+/* W = 2 * U.  */
+void gcry_mpi_ec_dup (gcry_mpi_point_t w, gcry_mpi_point_t u, gcry_ctx_t ctx);
+
+/* W = U + V.  */
+void gcry_mpi_ec_add (gcry_mpi_point_t w,
+                      gcry_mpi_point_t u, gcry_mpi_point_t v, gcry_ctx_t ctx);
+
+/* W = N * U.  */
+void gcry_mpi_ec_mul (gcry_mpi_point_t w, gcry_mpi_t n, gcry_mpi_point_t u,
+                      gcry_ctx_t ctx);
+
 
 /* Return the number of bits required to represent A. */
 unsigned int gcry_mpi_get_nbits (gcry_mpi_t a);
@@ -1294,6 +1318,9 @@ gcry_error_t gcry_prime_check (gcry_mpi_t x, unsigned int flags);
  *                                  *
  ************************************/
 
+/* Release the context object CTX.  */
+void gcry_ctx_release (gcry_ctx_t ctx);
+
 /* Log levels used by the internal logging facility. */
 enum gcry_log_levels
   {
diff --git a/src/libgcrypt.def b/src/libgcrypt.def
index 8f14dff..611f10f 100644
--- a/src/libgcrypt.def
+++ b/src/libgcrypt.def
@@ -220,3 +220,11 @@ EXPORTS
       gcry_mpi_point_snatch_get @199
       gcry_mpi_point_set        @200
       gcry_mpi_point_snatch_set @201
+
+      gcry_ctx_release          @202
+
+      gcry_mpi_ec_p_new         @203
+      gcry_mpi_ec_get_affine    @204
+      gcry_mpi_ec_dup           @205
+      gcry_mpi_ec_add           @206
+      gcry_mpi_ec_mul           @207
diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers
index 5c43b95..4a375b2 100644
--- a/src/libgcrypt.vers
+++ b/src/libgcrypt.vers
@@ -90,7 +90,11 @@ GCRYPT_1.6 {
     gcry_mpi_point_new; gcry_mpi_point_release;
     gcry_mpi_point_get; gcry_mpi_point_snatch_get;
     gcry_mpi_point_set; gcry_mpi_point_snatch_set;
+    gcry_mpi_ec_p_new;
+    gcry_mpi_ec_get_affine;
+    gcry_mpi_ec_dup; gcry_mpi_ec_add; gcry_mpi_ec_mul;
 
+    gcry_ctx_release;
 
   local:
     *;
diff --git a/src/mpi.h b/src/mpi.h
index b3f19e5..23afa68 100644
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -251,7 +251,7 @@ void _gcry_mpi_snatch_point (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
 struct mpi_ec_ctx_s;
 typedef struct mpi_ec_ctx_s *mpi_ec_t;
 
-mpi_ec_t _gcry_mpi_ec_init (gcry_mpi_t p, gcry_mpi_t a);
+mpi_ec_t _gcry_mpi_ec_p_internal_new (gcry_mpi_t p, gcry_mpi_t a);
 void _gcry_mpi_ec_free (mpi_ec_t ctx);
 int _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point,
                              mpi_ec_t ctx);
diff --git a/src/visibility.c b/src/visibility.c
index 1fb29f2..5c3216d 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -24,8 +24,8 @@
 #define _GCRY_INCLUDED_BY_VISIBILITY_C
 #include "g10lib.h"
 #include "cipher-proto.h"
-
-
+#include "context.h"
+#include "mpi.h"
 
 const char *
 gcry_strerror (gcry_error_t err)
@@ -461,6 +461,42 @@ gcry_mpi_point_snatch_set (gcry_mpi_point_t point,
   return _gcry_mpi_point_snatch_set (point, x, y, z);
 }
 
+gcry_ctx_t
+gcry_mpi_ec_p_new (gcry_mpi_t p, gcry_mpi_t a)
+{
+  return _gcry_mpi_ec_p_new (p, a);
+}
+
+int
+gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_point_t point,
+                        gcry_ctx_t ctx)
+{
+  return _gcry_mpi_ec_get_affine (x, y, point,
+                                  _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC));
+}
+
+void
+gcry_mpi_ec_dup (gcry_mpi_point_t w, gcry_mpi_point_t u, gcry_ctx_t ctx)
+{
+  _gcry_mpi_ec_dup_point (w, u, _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC));
+}
+
+void
+gcry_mpi_ec_add (gcry_mpi_point_t w,
+                 gcry_mpi_point_t u, gcry_mpi_point_t v, gcry_ctx_t ctx)
+{
+  _gcry_mpi_ec_add_points (w, u, v,
+                           _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC));
+}
+
+void
+gcry_mpi_ec_mul (gcry_mpi_point_t w, gcry_mpi_t n, gcry_mpi_point_t u,
+                 gcry_ctx_t ctx)
+{
+  _gcry_mpi_ec_mul_point (w, n, u,
+                          _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC));
+}
+
 unsigned int
 gcry_mpi_get_nbits (gcry_mpi_t a)
 {
@@ -1067,6 +1103,12 @@ gcry_prime_check (gcry_mpi_t x, unsigned int flags)
 }
 
 void
+gcry_ctx_release (gcry_ctx_t ctx)
+{
+  _gcry_ctx_release (ctx);
+}
+
+void
 gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data)
 {
   _gcry_set_progress_handler (cb, cb_data);
diff --git a/src/visibility.h b/src/visibility.h
index f4507ce..90c6ad1 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -154,6 +154,7 @@
 #define gcry_mpi_copy               _gcry_mpi_copy
 #define gcry_mpi_div                _gcry_mpi_div
 #define gcry_mpi_dump               _gcry_mpi_dump
+#define gcry_mpi_ec_p_new           _gcry_mpi_ec_p_new
 #define gcry_mpi_gcd                _gcry_mpi_gcd
 #define gcry_mpi_get_flag           _gcry_mpi_get_flag
 #define gcry_mpi_get_nbits          _gcry_mpi_get_nbits
@@ -192,6 +193,8 @@
 #define gcry_mpi_swap               _gcry_mpi_swap
 #define gcry_mpi_test_bit           _gcry_mpi_test_bit
 
+#define gcry_ctx_release            _gcry_ctx_release
+
 
 /* Include the main header here so that public symbols are mapped to
    the internal underscored ones.  */
@@ -367,6 +370,7 @@ gcry_err_code_t gcry_md_get (gcry_md_hd_t hd, int algo,
 #undef gcry_mpi_copy
 #undef gcry_mpi_div
 #undef gcry_mpi_dump
+#undef gcry_mpi_ec_p_new
 #undef gcry_mpi_gcd
 #undef gcry_mpi_get_flag
 #undef gcry_mpi_get_nbits
@@ -405,6 +409,8 @@ gcry_err_code_t gcry_md_get (gcry_md_hd_t hd, int algo,
 #undef gcry_mpi_swap
 #undef gcry_mpi_test_bit
 
+#undef gcry_ctx_release
+
 
 /* Now mark all symbols.  */
 
@@ -540,6 +546,11 @@ MARK_VISIBLE (gcry_mpi_cmp_ui)
 MARK_VISIBLE (gcry_mpi_copy)
 MARK_VISIBLE (gcry_mpi_div)
 MARK_VISIBLE (gcry_mpi_dump)
+MARK_VISIBLEX(gcry_mpi_ec_add)
+MARK_VISIBLEX(gcry_mpi_ec_dup)
+MARK_VISIBLEX(gcry_mpi_ec_get_affine)
+MARK_VISIBLEX(gcry_mpi_ec_mul)
+MARK_VISIBLE (gcry_mpi_ec_p_new)
 MARK_VISIBLE (gcry_mpi_gcd)
 MARK_VISIBLE (gcry_mpi_get_flag)
 MARK_VISIBLE (gcry_mpi_get_nbits)
@@ -578,6 +589,7 @@ MARK_VISIBLE (gcry_mpi_subm)
 MARK_VISIBLE (gcry_mpi_swap)
 MARK_VISIBLE (gcry_mpi_test_bit)
 
+MARK_VISIBLE (gcry_ctx_release)
 
 
 #undef MARK_VISIBLE
diff --git a/tests/t-mpi-point.c b/tests/t-mpi-point.c
index 548d6c7..8714d38 100644
--- a/tests/t-mpi-point.c
+++ b/tests/t-mpi-point.c
@@ -32,8 +32,10 @@
 
 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))
@@ -83,6 +85,52 @@ die (const char *format, ...)
 }
 
 
+static void
+print_mpi (const char *text, gcry_mpi_t a)
+{
+  gcry_error_t err;
+  char *buf;
+  void *bufaddr = &buf;
+
+  err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
+  if (err)
+    fprintf (stderr, "%s: [error printing number: %s]\n",
+             text, gpg_strerror (err));
+  else
+    {
+      fprintf (stderr, "%s: %s\n", text, buf);
+      gcry_free (buf);
+    }
+}
+
+
+static gcry_mpi_t
+hex2mpi (const char *string)
+{
+  gpg_error_t err;
+  gcry_mpi_t val;
+
+  err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
+  if (err)
+    die ("hex2mpi '%s' failed: %s\n", gpg_strerror (err));
+  return val;
+}
+
+
+/* Compare A to B, where B is given as a hex string.  */
+static int
+cmp_mpihex (gcry_mpi_t a, const char *b)
+{
+  gcry_mpi_t bval;
+  int res;
+
+  bval = hex2mpi (b);
+  res = gcry_mpi_cmp (a, bval);
+  gcry_mpi_release (bval);
+  return res;
+}
+
+
 
 static void
 set_get_point (void)
@@ -138,10 +186,127 @@ set_get_point (void)
 }
 
 
+static void
+context_alloc (void)
+{
+  gcry_ctx_t ctx;
+  gcry_mpi_t p, a;
+
+  wherestr = "context_alloc";
+  show ("checking context functions\n");
+
+  p = gcry_mpi_set_ui (NULL, 1);
+  a = gcry_mpi_set_ui (NULL, 1);
+  ctx = gcry_mpi_ec_p_new (p, a);
+  if (!ctx)
+    die ("gcry_mpi_ec_p_new returned an error: %s\n",
+         gpg_strerror (gpg_error_from_syserror ()));
+  gcry_mpi_release (p);
+  gcry_mpi_release (a);
+  gcry_ctx_release (ctx);
+
+  p = gcry_mpi_set_ui (NULL, 0);
+  a = gcry_mpi_set_ui (NULL, 0);
+  ctx = gcry_mpi_ec_p_new (p, a);
+  if (ctx || gpg_err_code_from_syserror () != GPG_ERR_EINVAL)
+    fail ("gcry_mpi_ec_p_new: bad parameter detection failed (1)\n");
+
+  gcry_mpi_set_ui (p, 1);
+  ctx = gcry_mpi_ec_p_new (p, a);
+  if (ctx || gpg_err_code_from_syserror () != GPG_ERR_EINVAL)
+    fail ("gcry_mpi_ec_p_new: bad parameter detection failed (2)\n");
+
+  gcry_mpi_release (p);
+  p = NULL;
+  ctx = gcry_mpi_ec_p_new (p, a);
+  if (ctx || gpg_err_code_from_syserror () != GPG_ERR_EINVAL)
+    fail ("gcry_mpi_ec_p_new: bad parameter detection failed (3)\n");
+
+  gcry_mpi_release (a);
+  a = NULL;
+  ctx = gcry_mpi_ec_p_new (p, a);
+  if (ctx || gpg_err_code_from_syserror () != GPG_ERR_EINVAL)
+    fail ("gcry_mpi_ec_p_new: bad parameter detection failed (4)\n");
+
+}
+
+
+/* Create a new point from (X,Y,Z) given as hex strings.  */
+gcry_mpi_point_t
+make_point (const char *x, const char *y, const char *z)
+{
+  gcry_mpi_point_t point;
+
+  point = gcry_mpi_point_new (0);
+  gcry_mpi_point_snatch_set (point, hex2mpi (x), hex2mpi (y), hex2mpi (z));
+
+  return point;
+}
+
+
+static void
+basic_ec_math (void)
+{
+  gcry_ctx_t ctx;
+  gcry_mpi_t P, A;
+  gcry_mpi_point_t G, Q;
+  gcry_mpi_t d;
+  gcry_mpi_t x, y, z;
+
+  wherestr = "set_get_point";
+  show ("checking basic math functions for EC\n");
+
+  P = hex2mpi ("0xfffffffffffffffffffffffffffffffeffffffffffffffff");
+  A = hex2mpi ("0xfffffffffffffffffffffffffffffffefffffffffffffffc");
+  G = make_point ("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
+                  "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
+                  "1");
+  d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
+  Q = gcry_mpi_point_new (0);
+
+  ctx = gcry_mpi_ec_p_new (P, A);
+  gcry_mpi_ec_mul (Q, d, G, ctx);
+
+  x = gcry_mpi_new (0);
+  y = gcry_mpi_new (0);
+  z = gcry_mpi_new (0);
+  gcry_mpi_point_get (x, y, z, Q);
+  if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
+      || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
+      || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
+    fail ("computed public key does not match\n");
+  if (debug)
+    {
+      print_mpi ("Q.x", x);
+      print_mpi ("Q.y", y);
+      print_mpi ("Q.z", z);
+    }
+
+  if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
+    fail ("failed to get affine coordinates\n");
+  if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
+      || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
+    fail ("computed affine coordinates of public key do not match\n");
+  if (debug)
+    {
+      print_mpi ("q.x", x);
+      print_mpi ("q.y", y);
+    }
+
+  gcry_mpi_release (z);
+  gcry_mpi_release (y);
+  gcry_mpi_release (x);
+  gcry_mpi_point_release (Q);
+  gcry_mpi_release (d);
+  gcry_mpi_point_release (G);
+  gcry_mpi_release (A);
+  gcry_mpi_release (P);
+}
+
+
 int
 main (int argc, char **argv)
 {
-  int debug = 0;
 
   if (argc > 1 && !strcmp (argv[1], "--verbose"))
     verbose = 1;
@@ -158,7 +323,8 @@ main (int argc, char **argv)
   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
 
   set_get_point ();
-
+  context_alloc ();
+  basic_ec_math ();
 
   show ("All tests completed. Errors: %d\n", error_count);
   return error_count ? 1 : 0;

commit 7cce620acddac2df024ca421ed3abc32a88f3738
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Mar 8 15:06:20 2013 +0100

    mpi: Add an API for EC point operations.
    
    * mpi/ec.c (gcry_mpi_point_new, gcry_mpi_point_release): New.
    (gcry_mpi_point_get, gcry_mpi_point_snatch_get): New.
    (gcry_mpi_point_set, gcry_mpi_point_snatch_set): New.
    * src/visibility.h, src/visibility.c: Add corresponding macros and
    wrappers.
    * src/gcrypt.h.in (struct gcry_mpi_point, gcry_mpi_point_t): New.
    (gcry_mpi_point_new, gcry_mpi_point_release, gcry_mpi_point_get)
    (gcry_mpi_point_snatch_get, gcry_mpi_point_set)
    (gcry_mpi_point_snatch_set): New prototypes.
    (mpi_point_new, mpi_point_release, mpi_point_get, mpi_point_snatch_get)
    (mpi_point_set, mpi_point_snatch_set): New macros.
    * src/libgcrypt.vers (gcry_mpi_point_new, gcry_mpi_point_release)
    (gcry_mpi_point_get, gcry_mpi_point_snatch_get, gcry_mpi_point_set)
    (gcry_mpi_point_snatch_set): New symbols.
    * src/libgcrypt.def: Ditto.
    * tests/t-mpi-point.c: New.
    * tests/Makefile.am (TESTS): Add t-mpi-point

diff --git a/NEWS b/NEWS
index 1db71e9..e0ba536 100644
--- a/NEWS
+++ b/NEWS
@@ -37,6 +37,13 @@ Noteworthy changes in version 1.6.0 (unreleased)
  GCRY_RNG_TYPE_FIPS              NEW.
  GCRY_RNG_TYPE_SYSTEM            NEW.
  gcry_mpi_snatch                 NEW.
+ gcry_mpi_point_t                NEW.
+ gcry_mpi_point_new              NEW.
+ gcry_mpi_point_release          NEW.
+ gcry_mpi_point_get              NEW.
+ gcry_mpi_point_snatch_get       NEW.
+ gcry_mpi_point_set              NEW.
+ gcry_mpi_point_snatch_set       NEW.
 
 
 Noteworthy changes in version 1.5.0 (2011-06-29)
diff --git a/mpi/ec.c b/mpi/ec.c
index 7b1ef2b..bb9bea4 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -62,6 +62,33 @@ struct mpi_ec_ctx_s
 };
 
 
+/* Create a new point option.  NBITS gives the size in bits of one
+   coordinate; it is only used to pre-allocate some resources and
+   might also be passed as 0 to use a default value.  */
+mpi_point_t
+gcry_mpi_point_new (unsigned int nbits)
+{
+  mpi_point_t p;
+
+  (void)nbits;  /* Currently not used.  */
+
+  p = gcry_xmalloc (sizeof *p);
+  _gcry_mpi_point_init (p);
+  return p;
+}
+
+
+/* Release the point object P.  P may be NULL. */
+void
+gcry_mpi_point_release (mpi_point_t p)
+{
+  if (p)
+    {
+      _gcry_mpi_point_free_parts (p);
+      gcry_free (p);
+    }
+}
+
 
 /* Initialize the fields of a point object.  gcry_mpi_point_free_parts
    may be used to release the fields.  */
@@ -93,6 +120,90 @@ point_set (mpi_point_t d, mpi_point_t s)
   mpi_set (d->z, s->z);
 }
 
+/* Set the projective coordinates from POINT into X, Y, and Z.  If a
+   coordinate is not required, X, Y, or Z may be passed as NULL.  */
+void
+gcry_mpi_point_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
+                    mpi_point_t point)
+{
+  if (x)
+    mpi_set (x, point->x);
+  if (y)
+    mpi_set (y, point->y);
+  if (z)
+    mpi_set (z, point->z);
+}
+
+
+/* Set the projective coordinates from POINT into X, Y, and Z and
+   release POINT.  If a coordinate is not required, X, Y, or Z may be
+   passed as NULL.  */
+void
+gcry_mpi_point_snatch_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
+                           mpi_point_t point)
+{
+  mpi_snatch (x, point->x);
+  mpi_snatch (y, point->y);
+  mpi_snatch (z, point->z);
+  gcry_free (point);
+}
+
+
+/* Set the projective coordinates from X, Y, and Z into POINT.  If a
+   coordinate is given as NULL, the value 0 is stored into point.  If
+   POINT is given as NULL a new point object is allocated.  Returns
+   POINT or the newly allocated point object. */
+mpi_point_t
+gcry_mpi_point_set (mpi_point_t point,
+                    gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z)
+{
+  if (!point)
+    point = gcry_mpi_point_new (0);
+
+  if (x)
+    mpi_set (point->x, x);
+  else
+    mpi_clear (point->x);
+  if (y)
+    mpi_set (point->y, y);
+  else
+    mpi_clear (point->y);
+  if (z)
+    mpi_set (point->z, z);
+  else
+    mpi_clear (point->z);
+
+  return point;
+}
+
+
+/* Set the projective coordinates from X, Y, and Z into POINT.  If a
+   coordinate is given as NULL, the value 0 is stored into point.  If
+   POINT is given as NULL a new point object is allocated.  The
+   coordinates X, Y, and Z are released.  Returns POINT or the newly
+   allocated point object. */
+mpi_point_t
+gcry_mpi_point_snatch_set (mpi_point_t point,
+                           gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z)
+{
+  if (!point)
+    point = gcry_mpi_point_new (0);
+
+  if (x)
+    mpi_snatch (point->x, x);
+  else
+    mpi_clear (point->x);
+  if (y)
+    mpi_snatch (point->y, y);
+  else
+    mpi_clear (point->y);
+  if (z)
+    mpi_snatch (point->z, z);
+  else
+    mpi_clear (point->z);
+
+  return point;
+}
 
 
 static void
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 7d2b89d..5d2a779 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -212,9 +212,11 @@ struct gcry_thread_cbs
 
 
 
-/* The data object used to hold a multi precision integer.  */
+/* The data objects used to hold multi precision integers.  */
 struct gcry_mpi;
 typedef struct gcry_mpi *gcry_mpi_t;
+struct gcry_mpi_point;
+typedef struct gcry_mpi_point *gcry_mpi_point_t;
 
 #ifndef GCRYPT_NO_DEPRECATED
 typedef struct gcry_mpi *GCRY_MPI _GCRY_GCC_ATTR_DEPRECATED;
@@ -572,6 +574,31 @@ int gcry_mpi_gcd (gcry_mpi_t g, gcry_mpi_t a, gcry_mpi_t b);
    Return true if the value exists. */
 int gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t m);
 
+/* Create a new point object.  NBITS is usually 0.  */
+gcry_mpi_point_t gcry_mpi_point_new (unsigned int nbits);
+
+/* Release the object POINT.  POINT may be NULL. */
+void gcry_mpi_point_release (gcry_mpi_point_t point);
+
+/* Store the projective coordinates from POINT into X, Y, and Z.  */
+void gcry_mpi_point_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
+                         gcry_mpi_point_t point);
+
+/* Store the projective coordinates from POINT into X, Y, and Z and
+   release POINT.  */
+void gcry_mpi_point_snatch_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
+                                gcry_mpi_point_t point);
+
+/* Store the projective coordinates X, Y, and Z into POINT.  */
+gcry_mpi_point_t gcry_mpi_point_set (gcry_mpi_point_t point,
+                                     gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z);
+
+/* Store the projective coordinates X, Y, and Z into POINT and release
+   X, Y, and Z.  */
+gcry_mpi_point_t gcry_mpi_point_snatch_set (gcry_mpi_point_t point,
+                                            gcry_mpi_t x, gcry_mpi_t y,
+                                            gcry_mpi_t z);
+
 
 /* Return the number of bits required to represent A. */
 unsigned int gcry_mpi_get_nbits (gcry_mpi_t a);
@@ -656,6 +683,19 @@ int gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
 #define mpi_gcd(g,a,b)         gcry_mpi_gcd ( (g), (a), (b) )
 #define mpi_invm(g,a,b)        gcry_mpi_invm ( (g), (a), (b) )
 
+#define mpi_point_new(n)              gcry_mpi_point_new((n))
+#define mpi_point_release(p)                    \
+  do                                            \
+    {                                           \
+      gcry_mpi_point_release ((p));             \
+      (p) = NULL;                               \
+    }                                           \
+  while (0)
+#define mpi_point_get(x,y,z,p)        gcry_mpi_point_get((x),(y),(z),(p))
+#define mpi_point_snatch_get(x,y,z,p) gcry_mpi_point_snatch_get((x),(y),(z),(p))
+#define mpi_point_set(p,x,y,z)        gcry_mpi_point_set((p),(x),(y),(z))
+#define mpi_point_snatch_set(p,x,y,z) gcry_mpi_point_snatch_set((p),(x),(y),(z))
+
 #define mpi_get_nbits(a)       gcry_mpi_get_nbits ((a))
 #define mpi_test_bit(a,b)      gcry_mpi_test_bit ((a),(b))
 #define mpi_set_bit(a,b)       gcry_mpi_set_bit ((a),(b))
diff --git a/src/libgcrypt.def b/src/libgcrypt.def
index cc49e74..8f14dff 100644
--- a/src/libgcrypt.def
+++ b/src/libgcrypt.def
@@ -213,3 +213,10 @@ EXPORTS
       gcry_kdf_derive       @194
 
       gcry_mpi_snatch       @195
+
+      gcry_mpi_point_new        @196
+      gcry_mpi_point_release    @197
+      gcry_mpi_point_get        @198
+      gcry_mpi_point_snatch_get @199
+      gcry_mpi_point_set        @200
+      gcry_mpi_point_snatch_set @201
diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers
index 200f04e..5c43b95 100644
--- a/src/libgcrypt.vers
+++ b/src/libgcrypt.vers
@@ -87,6 +87,10 @@ GCRYPT_1.6 {
     gcry_mpi_set_ui; gcry_mpi_snew; gcry_mpi_sub; gcry_mpi_sub_ui;
     gcry_mpi_subm; gcry_mpi_swap; gcry_mpi_test_bit;
     gcry_mpi_lshift; gcry_mpi_snatch;
+    gcry_mpi_point_new; gcry_mpi_point_release;
+    gcry_mpi_point_get; gcry_mpi_point_snatch_get;
+    gcry_mpi_point_set; gcry_mpi_point_snatch_set;
+
 
   local:
     *;
diff --git a/src/visibility.c b/src/visibility.c
index 732f058..1fb29f2 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -421,6 +421,45 @@ gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t m)
   return _gcry_mpi_invm (x, a, m);
 }
 
+gcry_mpi_point_t
+gcry_mpi_point_new (unsigned int nbits)
+{
+  return _gcry_mpi_point_new (nbits);
+}
+
+void
+gcry_mpi_point_release (gcry_mpi_point_t point)
+{
+  _gcry_mpi_point_release (point);
+}
+
+void
+gcry_mpi_point_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
+                    gcry_mpi_point_t point)
+{
+  _gcry_mpi_point_get (x, y, z, point);
+}
+
+void
+gcry_mpi_point_snatch_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
+                           gcry_mpi_point_t point)
+{
+  _gcry_mpi_point_snatch_get (x, y, z, point);
+}
+
+gcry_mpi_point_t
+gcry_mpi_point_set (gcry_mpi_point_t point,
+                    gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z)
+{
+  return _gcry_mpi_point_set (point, x, y, z);
+}
+
+gcry_mpi_point_t
+gcry_mpi_point_snatch_set (gcry_mpi_point_t point,
+                           gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z)
+{
+  return _gcry_mpi_point_snatch_set (point, x, y, z);
+}
 
 unsigned int
 gcry_mpi_get_nbits (gcry_mpi_t a)
diff --git a/src/visibility.h b/src/visibility.h
index 429c246..f4507ce 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -165,6 +165,12 @@
 #define gcry_mpi_mul_ui             _gcry_mpi_mul_ui
 #define gcry_mpi_mulm               _gcry_mpi_mulm
 #define gcry_mpi_new                _gcry_mpi_new
+#define gcry_mpi_point_get          _gcry_mpi_point_get
+#define gcry_mpi_point_new          _gcry_mpi_point_new
+#define gcry_mpi_point_release      _gcry_mpi_point_release
+#define gcry_mpi_point_set          _gcry_mpi_point_set
+#define gcry_mpi_point_snatch_get   _gcry_mpi_point_snatch_get
+#define gcry_mpi_point_snatch_set   _gcry_mpi_point_snatch_set
 #define gcry_mpi_powm               _gcry_mpi_powm
 #define gcry_mpi_print              _gcry_mpi_print
 #define gcry_mpi_randomize          _gcry_mpi_randomize
@@ -172,13 +178,13 @@
 #define gcry_mpi_rshift             _gcry_mpi_rshift
 #define gcry_mpi_lshift             _gcry_mpi_lshift
 #define gcry_mpi_scan               _gcry_mpi_scan
-#define gcry_mpi_snatch             _gcry_mpi_snatch
 #define gcry_mpi_set                _gcry_mpi_set
 #define gcry_mpi_set_bit            _gcry_mpi_set_bit
 #define gcry_mpi_set_flag           _gcry_mpi_set_flag
 #define gcry_mpi_set_highbit        _gcry_mpi_set_highbit
 #define gcry_mpi_set_opaque         _gcry_mpi_set_opaque
 #define gcry_mpi_set_ui             _gcry_mpi_set_ui
+#define gcry_mpi_snatch             _gcry_mpi_snatch
 #define gcry_mpi_snew               _gcry_mpi_snew
 #define gcry_mpi_sub                _gcry_mpi_sub
 #define gcry_mpi_sub_ui             _gcry_mpi_sub_ui
@@ -372,6 +378,12 @@ gcry_err_code_t gcry_md_get (gcry_md_hd_t hd, int algo,
 #undef gcry_mpi_mul_ui
 #undef gcry_mpi_mulm
 #undef gcry_mpi_new
+#undef gcry_mpi_point_get
+#undef gcry_mpi_point_new
+#undef gcry_mpi_point_release
+#undef gcry_mpi_point_set
+#undef gcry_mpi_point_snatch_get
+#undef gcry_mpi_point_snatch_set
 #undef gcry_mpi_powm
 #undef gcry_mpi_print
 #undef gcry_mpi_randomize
@@ -539,6 +551,12 @@ MARK_VISIBLE (gcry_mpi_mul_2exp)
 MARK_VISIBLE (gcry_mpi_mul_ui)
 MARK_VISIBLE (gcry_mpi_mulm)
 MARK_VISIBLE (gcry_mpi_new)
+MARK_VISIBLE (gcry_mpi_point_get)
+MARK_VISIBLE (gcry_mpi_point_new)
+MARK_VISIBLE (gcry_mpi_point_release)
+MARK_VISIBLE (gcry_mpi_point_set)
+MARK_VISIBLE (gcry_mpi_point_snatch_get)
+MARK_VISIBLE (gcry_mpi_point_snatch_set)
 MARK_VISIBLE (gcry_mpi_powm)
 MARK_VISIBLE (gcry_mpi_print)
 MARK_VISIBLE (gcry_mpi_randomize)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d337840..c18142e 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 prime basic \
+TESTS = version t-mpi-bit t-mpi-point prime basic \
         mpitests tsexp keygen pubkey hmac keygrip fips186-dsa aeswrap \
 	curves t-kdf pkcs1v2 random
 
diff --git a/tests/t-mpi-point.c b/tests/t-mpi-point.c
new file mode 100644
index 0000000..548d6c7
--- /dev/null
+++ b/tests/t-mpi-point.c
@@ -0,0 +1,165 @@
+/* t-mpi-point.c  - Tests for mpi point 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.h"
+
+#define PGM "t-mpi-point"
+
+static const char *wherestr;
+static int verbose;
+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);
+}
+
+
+
+static void
+set_get_point (void)
+{
+  gcry_mpi_point_t point;
+  gcry_mpi_t x, y, z;
+
+  wherestr = "set_get_point";
+  show ("checking point setting functions\n");
+
+  point = gcry_mpi_point_new (0);
+  x = gcry_mpi_set_ui (NULL, 17);
+  y = gcry_mpi_set_ui (NULL, 42);
+  z = gcry_mpi_set_ui (NULL, 11371);
+  gcry_mpi_point_get (x, y, z, point);
+  if (gcry_mpi_cmp_ui (x, 0)
+      || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0))
+    fail ("new point not initialized to (0,0,0)\n");
+  gcry_mpi_point_snatch_get (x, y, z, point);
+  point = NULL;
+  if (gcry_mpi_cmp_ui (x, 0)
+      || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0))
+    fail ("snatch_get failed\n");
+  gcry_mpi_release (x);
+  gcry_mpi_release (y);
+  gcry_mpi_release (z);
+
+  point = gcry_mpi_point_new (0);
+  x = gcry_mpi_set_ui (NULL, 17);
+  y = gcry_mpi_set_ui (NULL, 42);
+  z = gcry_mpi_set_ui (NULL, 11371);
+  gcry_mpi_point_set (point, x, y, z);
+  gcry_mpi_set_ui (x, 23);
+  gcry_mpi_set_ui (y, 24);
+  gcry_mpi_set_ui (z, 25);
+  gcry_mpi_point_get (x, y, z, point);
+  if (gcry_mpi_cmp_ui (x, 17)
+      || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
+    fail ("point_set/point_get failed\n");
+  gcry_mpi_point_snatch_set (point, x, y, z);
+  x = gcry_mpi_new (0);
+  y = gcry_mpi_new (0);
+  z = gcry_mpi_new (0);
+  gcry_mpi_point_get (x, y, z, point);
+  if (gcry_mpi_cmp_ui (x, 17)
+      || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
+    fail ("point_snatch_set/point_get failed\n");
+
+  gcry_mpi_point_release (point);
+  gcry_mpi_release (x);
+  gcry_mpi_release (y);
+  gcry_mpi_release (z);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int debug = 0;
+
+  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);
+
+  set_get_point ();
+
+
+  show ("All tests completed. Errors: %d\n", error_count);
+  return error_count ? 1 : 0;
+}

commit 6c4767637c512127a4362732b3ec51068554d328
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Mar 7 19:04:10 2013 +0100

    mpi: Add mpi_snatch and change an internal typedef.
    
    * src/mpi.h (struct mpi_point_s): Rename to struct gcry_mpi_point.
    (mpi_point_struct): New typedef.
    (mpi_point_t): Change typedef to a pointer.  Replace all occurrences
    to use mpi_point_struct.
    * mpi/ec.c (_gcry_mpi_ec_point_init): Rename to ..
    (_gcry_mpi_point_init): this.  Change all callers.
    (_gcry_mpi_ec_point_free): Rename to ..
    (_gcry_mpi_point_free_parts): this.  Change all callers.
    
    * mpi/mpiutil.c (gcry_mpi_snatch): New function.
    * src/gcrypt.h.in (gcry_mpi_snatch, mpi_snatch): Add protoype and
    macro.
    * src/visibility.c (gcry_mpi_snatch): Add wrapper.
    * src/visibility.h (gcry_mpi_snatch): Add macro magic.
    * src/libgcrypt.def, src/libgcrypt.vers: Add new function.
    --
    
    This patch is a prerequisite to implement a public point API.  The new
    function gcry_mpi_snatch is actually not needed for this but is useful
    anyway and will be used to implement the point API.

diff --git a/NEWS b/NEWS
index 45b892f..1db71e9 100644
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,7 @@ Noteworthy changes in version 1.6.0 (unreleased)
  GCRY_RNG_TYPE_STANDARD          NEW.
  GCRY_RNG_TYPE_FIPS              NEW.
  GCRY_RNG_TYPE_SYSTEM            NEW.
+ gcry_mpi_snatch                 NEW.
 
 
 Noteworthy changes in version 1.5.0 (2011-06-29)
@@ -705,6 +706,7 @@ Noteworthy changes in version 1.1.3 (2001-05-31)
 
 Copyright 2001, 2002, 2003, 2004, 2007, 2008,
           2009, 2011 Free Software Foundation, Inc.
+Copyright 2013 g10 Code GmbH
 
 This file is free software; as a special exception the author gives
 unlimited permission to copy and/or distribute it, with or without
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 22de3d8..789fc6c 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -1,22 +1,22 @@
 /* ecc.c  -  Elliptic Curve Cryptography
-   Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
-
-   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, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-   USA.  */
+ * 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/>.
+ */
 
 /* This code is originally based on the Patch 0.1.6 for the gnupg
    1.4.x branch as retrieved on 2007-03-21 from
@@ -46,8 +46,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.
-
-  - Decide whether we should hide the mpi_point_t definition.
 */
 
 
@@ -63,25 +61,25 @@
 /* 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_t G;  /* Base point (generator).  */
-  gcry_mpi_t n;   /* Order of G.  */
-  const char *name;  /* Name of curve or NULL.  */
+  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_t Q;  /* Q = [d]G  */
+  mpi_point_struct Q; /* Q = [d]G  */
 } ECC_public_key;
 
 typedef struct
 {
   elliptic_curve_t E;
-  mpi_point_t Q;
+  mpi_point_struct Q;
   gcry_mpi_t d;
 } ECC_secret_key;
 
@@ -292,8 +290,8 @@ static void (*progress_cb) (void *, const char*, int, int, int);
 static void *progress_cb_data;
 
 
-#define point_init(a)  _gcry_mpi_ec_point_init ((a))
-#define point_free(a)  _gcry_mpi_ec_point_free ((a))
+#define point_init(a)  _gcry_mpi_point_init ((a))
+#define point_free(a)  _gcry_mpi_point_free_parts ((a))
 
 
 
@@ -333,7 +331,7 @@ _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)
+point_set (mpi_point_t d, mpi_point_t s)
 {
   mpi_set (d->x, s->x);
   mpi_set (d->y, s->y);
@@ -521,7 +519,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
   gpg_err_code_t err;
   elliptic_curve_t E;
   gcry_mpi_t d;
-  mpi_point_t Q;
+  mpi_point_struct Q;
   mpi_ec_t ctx;
   gcry_random_level_t random_level;
 
@@ -600,7 +598,7 @@ test_keys (ECC_secret_key *sk, unsigned int nbits)
 {
   ECC_public_key pk;
   gcry_mpi_t test = mpi_new (nbits);
-  mpi_point_t R_;
+  mpi_point_struct R_;
   gcry_mpi_t c = mpi_new (nbits);
   gcry_mpi_t out = mpi_new (nbits);
   gcry_mpi_t r = mpi_new (nbits);
@@ -648,7 +646,7 @@ static int
 check_secret_key (ECC_secret_key * sk)
 {
   int rc = 1;
-  mpi_point_t Q;
+  mpi_point_struct Q;
   gcry_mpi_t y_2, y2;
   mpi_ec_t ctx = NULL;
 
@@ -719,7 +717,7 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s)
 {
   gpg_err_code_t err = 0;
   gcry_mpi_t k, dr, sum, k_1, x;
-  mpi_point_t I;
+  mpi_point_struct I;
   mpi_ec_t ctx;
 
   if (DBG_CIPHER)
@@ -790,7 +788,7 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s)
 {
   gpg_err_code_t err = 0;
   gcry_mpi_t h, h1, h2, x, y;
-  mpi_point_t Q, Q1, Q2;
+  mpi_point_struct Q, Q1, Q2;
   mpi_ec_t ctx;
 
   if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) )
@@ -925,7 +923,7 @@ ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p)
 /* 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)
+os2ec (mpi_point_t result, gcry_mpi_t value)
 {
   gcry_error_t err;
   size_t n;
@@ -1430,7 +1428,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
 
   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
   {
-    mpi_point_t R;	/* Result that we return.  */
+    mpi_point_struct R;  /* Result that we return.  */
     gcry_mpi_t x, y;
 
     x = mpi_new (0);
@@ -1490,8 +1488,8 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
                  gcry_mpi_t *skey, int flags)
 {
   ECC_secret_key sk;
-  mpi_point_t R;	/* Result that we return.  */
-  mpi_point_t kG;
+  mpi_point_struct R;	/* Result that we return.  */
+  mpi_point_struct kG;
   mpi_ec_t ctx;
   gcry_mpi_t r;
   int err;
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index fa24def..8bfcbfd 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -3600,6 +3600,13 @@ small values (usually up to the word size of the CPU).
 Swap the values of @var{a} and @var{b}.
 @end deftypefun
 
+ at deftypefun void gcry_mpi_snatch (@w{gcry_mpi_t @var{w}}, @
+                                  @w{const gcry_mpi_t @var{u}})
+
+Set @var{u} into @var{w} and release @var{u}.  If @var{w} is
+ at code{NULL} only @var{u} will be released.
+ at end deftypefun
+
 @node MPI formats
 @section MPI formats
 
diff --git a/mpi/ec.c b/mpi/ec.c
index e325358..7b1ef2b 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -1,23 +1,22 @@
 /* ec.c -  Elliptic Curve functions
-   Copyright (C) 2007 Free Software Foundation, Inc.
-
-   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, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-   USA.  */
-
+ * Copyright (C) 2007 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>
@@ -28,8 +27,8 @@
 #include "g10lib.h"
 
 
-#define point_init(a)  _gcry_mpi_ec_point_init ((a))
-#define point_free(a)  _gcry_mpi_ec_point_free ((a))
+#define point_init(a)  _gcry_mpi_point_init ((a))
+#define point_free(a)  _gcry_mpi_point_free_parts ((a))
 
 
 /* Object to represent a point in projective coordinates. */
@@ -64,10 +63,10 @@ struct mpi_ec_ctx_s
 
 
 
-/* Initialized a point object.  gcry_mpi_ec_point_free shall be used
-   to release this object.  */
+/* Initialize the fields of a point object.  gcry_mpi_point_free_parts
+   may be used to release the fields.  */
 void
-_gcry_mpi_ec_point_init (mpi_point_t *p)
+_gcry_mpi_point_init (mpi_point_t p)
 {
   p->x = mpi_new (0);
   p->y = mpi_new (0);
@@ -75,18 +74,19 @@ _gcry_mpi_ec_point_init (mpi_point_t *p)
 }
 
 
-/* Release a point object. */
+/* Release the parts of a point object. */
 void
-_gcry_mpi_ec_point_free (mpi_point_t *p)
+_gcry_mpi_point_free_parts (mpi_point_t p)
 {
   mpi_free (p->x); p->x = NULL;
   mpi_free (p->y); p->y = NULL;
   mpi_free (p->z); p->z = NULL;
 }
 
+
 /* Set the value from S into D.  */
 static void
-point_set (mpi_point_t *d, mpi_point_t *s)
+point_set (mpi_point_t d, mpi_point_t s)
 {
   mpi_set (d->x, s->x);
   mpi_set (d->y, s->y);
@@ -339,12 +339,13 @@ _gcry_mpi_ec_free (mpi_ec_t ctx)
   gcry_free (ctx);
 }
 
+
 /* Compute the affine coordinates from the projective coordinates in
    POINT.  Set them into X and Y.  If one coordinate is not required,
    X or Y may be passed as NULL.  CTX is the usual context. Returns: 0
    on success or !0 if POINT is at infinity.  */
 int
-_gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t *point,
+_gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point,
                          mpi_ec_t ctx)
 {
   gcry_mpi_t z1, z2, z3;
@@ -374,12 +375,10 @@ _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t *point,
 }
 
 
-
-
 
 /*  RESULT = 2 * POINT  */
 void
-_gcry_mpi_ec_dup_point (mpi_point_t *result, mpi_point_t *point, mpi_ec_t ctx)
+_gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
 {
 #define x3 (result->x)
 #define y3 (result->y)
@@ -463,8 +462,8 @@ _gcry_mpi_ec_dup_point (mpi_point_t *result, mpi_point_t *point, mpi_ec_t ctx)
 
 /* RESULT = P1 + P2 */
 void
-_gcry_mpi_ec_add_points (mpi_point_t *result,
-                         mpi_point_t *p1, mpi_point_t *p2,
+_gcry_mpi_ec_add_points (mpi_point_t result,
+                         mpi_point_t p1, mpi_point_t p2,
                          mpi_ec_t ctx)
 {
 #define x1 (p1->x    )
@@ -608,8 +607,8 @@ _gcry_mpi_ec_add_points (mpi_point_t *result,
    an integer SCALAR and a POINT as well as the usual context CTX.
    RESULT will be set to the resulting point. */
 void
-_gcry_mpi_ec_mul_point (mpi_point_t *result,
-                        gcry_mpi_t scalar, mpi_point_t *point,
+_gcry_mpi_ec_mul_point (mpi_point_t result,
+                        gcry_mpi_t scalar, mpi_point_t point,
                         mpi_ec_t ctx)
 {
 #if 0
@@ -632,7 +631,7 @@ _gcry_mpi_ec_mul_point (mpi_point_t *result,
 #else
   gcry_mpi_t x1, y1, z1, k, h, yy;
   unsigned int i, loops;
-  mpi_point_t p1, p2, p1inv;
+  mpi_point_struct p1, p2, p1inv;
 
   x1 = mpi_alloc_like (ctx->p);
   y1 = mpi_alloc_like (ctx->p);
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index 76630a6..d410d90 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -1,6 +1,7 @@
 /* mpiutil.ac  -  Utility functions for MPI
  * Copyright (C) 1998, 2000, 2001, 2002, 2003,
  *               2007  Free Software Foundation, Inc.
+ * Copyright (C) 2013  g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -296,6 +297,24 @@ _gcry_mpi_alloc_like( gcry_mpi_t a )
 }
 
 
+/* Set U into W and release U.  If W is NULL only U will be released. */
+void
+gcry_mpi_snatch (gcry_mpi_t w, gcry_mpi_t u)
+{
+  if (w)
+    {
+      _gcry_mpi_assign_limb_space (w, u->d, u->alloced);
+      w->nlimbs = u->nlimbs;
+      w->sign   = u->sign;
+      w->flags  = u->flags;
+      u->alloced = 0;
+      u->nlimbs = 0;
+      u->d = NULL;
+    }
+  _gcry_mpi_free (u);
+}
+
+
 gcry_mpi_t
 gcry_mpi_set( gcry_mpi_t w, gcry_mpi_t u)
 {
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index dae8d1c..7d2b89d 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -2,6 +2,7 @@
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
  *               2006, 2007, 2008, 2009, 2010, 2011,
  *               2012  Free Software Foundation, Inc.
+ * Copyright (C) 2012, 2013  g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -466,6 +467,9 @@ void gcry_mpi_release (gcry_mpi_t a);
 /* Create a new number with the same value as A. */
 gcry_mpi_t gcry_mpi_copy (const gcry_mpi_t a);
 
+/* Store the big integer value U in W and release U.  */
+void gcry_mpi_snatch (gcry_mpi_t w, gcry_mpi_t u);
+
 /* Store the big integer value U in W. */
 gcry_mpi_t gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u);
 
@@ -629,6 +633,7 @@ int gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
   while (0)
 
 #define mpi_copy( a )          gcry_mpi_copy( (a) )
+#define mpi_snatch( w, u)      gcry_mpi_snatch( (w), (u) )
 #define mpi_set( w, u)         gcry_mpi_set( (w), (u) )
 #define mpi_set_ui( w, u)      gcry_mpi_set_ui( (w), (u) )
 #define mpi_cmp( u, v )        gcry_mpi_cmp( (u), (v) )
diff --git a/src/libgcrypt.def b/src/libgcrypt.def
index 9bf0167..cc49e74 100644
--- a/src/libgcrypt.def
+++ b/src/libgcrypt.def
@@ -211,3 +211,5 @@ EXPORTS
       gcry_pk_get_param     @193
 
       gcry_kdf_derive       @194
+
+      gcry_mpi_snatch       @195
diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers
index dcb3749..200f04e 100644
--- a/src/libgcrypt.vers
+++ b/src/libgcrypt.vers
@@ -86,7 +86,7 @@ GCRYPT_1.6 {
     gcry_mpi_set_flag; gcry_mpi_set_highbit; gcry_mpi_set_opaque;
     gcry_mpi_set_ui; gcry_mpi_snew; gcry_mpi_sub; gcry_mpi_sub_ui;
     gcry_mpi_subm; gcry_mpi_swap; gcry_mpi_test_bit;
-    gcry_mpi_lshift;
+    gcry_mpi_lshift; gcry_mpi_snatch;
 
   local:
     *;
diff --git a/src/mpi.h b/src/mpi.h
index 65a4f97..b3f19e5 100644
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -108,6 +108,7 @@ struct gcry_mpi
 #define mpi_is_secure(a) ((a) && ((a)->flags&1))
 #define mpi_clear(a)          _gcry_mpi_clear ((a))
 #define mpi_alloc_like(a)     _gcry_mpi_alloc_like((a))
+#define mpi_snatch(a,b)       _gcry_mpi_snatch ((a),(b))
 #define mpi_set(a,b)          _gcry_mpi_set ((a),(b))
 #define mpi_set_ui(a,b)       _gcry_mpi_set_ui ((a),(b))
 #define mpi_get_ui(a,b)       _gcry_mpi_get_ui ((a),(b))
@@ -230,32 +231,37 @@ void _gcry_mpi_normalize( gcry_mpi_t a );
 /*-- ec.c --*/
 
 /* Object to represent a point in projective coordinates. */
-struct mpi_point_s;
-typedef struct mpi_point_s mpi_point_t;
-struct mpi_point_s
+struct gcry_mpi_point
 {
   gcry_mpi_t x;
   gcry_mpi_t y;
   gcry_mpi_t z;
 };
+typedef struct gcry_mpi_point mpi_point_struct;
+typedef struct gcry_mpi_point *mpi_point_t;
+
+void _gcry_mpi_point_init (mpi_point_t p);
+void _gcry_mpi_point_free_parts (mpi_point_t p);
+void _gcry_mpi_get_point (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
+                          mpi_point_t point);
+void _gcry_mpi_snatch_point (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
+                             mpi_point_t point);
 
 /* Context used with elliptic curve functions.  */
 struct mpi_ec_ctx_s;
 typedef struct mpi_ec_ctx_s *mpi_ec_t;
 
-void _gcry_mpi_ec_point_init (mpi_point_t *p);
-void _gcry_mpi_ec_point_free (mpi_point_t *p);
 mpi_ec_t _gcry_mpi_ec_init (gcry_mpi_t p, gcry_mpi_t a);
 void _gcry_mpi_ec_free (mpi_ec_t ctx);
-int _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t *point,
+int _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point,
                              mpi_ec_t ctx);
-void _gcry_mpi_ec_dup_point (mpi_point_t *result,
-                             mpi_point_t *point, mpi_ec_t ctx);
-void _gcry_mpi_ec_add_points (mpi_point_t *result,
-                              mpi_point_t *p1, mpi_point_t *p2,
+void _gcry_mpi_ec_dup_point (mpi_point_t result,
+                             mpi_point_t point, mpi_ec_t ctx);
+void _gcry_mpi_ec_add_points (mpi_point_t result,
+                              mpi_point_t p1, mpi_point_t p2,
                               mpi_ec_t ctx);
-void _gcry_mpi_ec_mul_point (mpi_point_t *result,
-                             gcry_mpi_t scalar, mpi_point_t *point,
+void _gcry_mpi_ec_mul_point (mpi_point_t result,
+                             gcry_mpi_t scalar, mpi_point_t point,
                              mpi_ec_t ctx);
 
 
diff --git a/src/visibility.c b/src/visibility.c
index 2d3edbc..732f058 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -1,5 +1,6 @@
 /* visibility.c - Wrapper for all public functions.
  * Copyright (C) 2007, 2008, 2011  Free Software Foundation, Inc.
+ * Copyright (C) 2013  g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -261,6 +262,12 @@ gcry_mpi_copy (const gcry_mpi_t a)
   return _gcry_mpi_copy (a);
 }
 
+void
+gcry_mpi_snatch (gcry_mpi_t w, const gcry_mpi_t u)
+{
+  return _gcry_mpi_snatch (w, u);
+}
+
 gcry_mpi_t
 gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u)
 {
diff --git a/src/visibility.h b/src/visibility.h
index 4606a20..429c246 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -172,6 +172,7 @@
 #define gcry_mpi_rshift             _gcry_mpi_rshift
 #define gcry_mpi_lshift             _gcry_mpi_lshift
 #define gcry_mpi_scan               _gcry_mpi_scan
+#define gcry_mpi_snatch             _gcry_mpi_snatch
 #define gcry_mpi_set                _gcry_mpi_set
 #define gcry_mpi_set_bit            _gcry_mpi_set_bit
 #define gcry_mpi_set_flag           _gcry_mpi_set_flag
@@ -378,6 +379,7 @@ gcry_err_code_t gcry_md_get (gcry_md_hd_t hd, int algo,
 #undef gcry_mpi_rshift
 #undef gcry_mpi_lshift
 #undef gcry_mpi_scan
+#undef gcry_mpi_snatch
 #undef gcry_mpi_set
 #undef gcry_mpi_set_bit
 #undef gcry_mpi_set_flag
@@ -544,6 +546,7 @@ MARK_VISIBLE (gcry_mpi_release)
 MARK_VISIBLE (gcry_mpi_rshift)
 MARK_VISIBLE (gcry_mpi_lshift)
 MARK_VISIBLE (gcry_mpi_scan)
+MARK_VISIBLE (gcry_mpi_snatch)
 MARK_VISIBLE (gcry_mpi_set)
 MARK_VISIBLE (gcry_mpi_set_bit)
 MARK_VISIBLE (gcry_mpi_set_flag)

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

Summary of changes:
 NEWS                                |   15 ++
 cipher/ecc.c                        |   92 +++++-----
 doc/gcrypt.texi                     |  159 ++++++++++++++++-
 mpi/ec.c                            |  266 ++++++++++++++++++++++------
 mpi/mpiutil.c                       |   19 ++
 src/Makefile.am                     |    2 +-
 src/context.c                       |  118 +++++++++++++
 compat/libcompat.h => src/context.h |   24 +--
 src/gcrypt.h.in                     |   74 ++++++++-
 src/libgcrypt.def                   |   17 ++
 src/libgcrypt.vers                  |   10 +-
 src/mpi.h                           |   32 ++--
 src/visibility.c                    |   92 ++++++++++-
 src/visibility.h                    |   33 ++++
 tests/Makefile.am                   |    2 +-
 tests/t-mpi-point.c                 |  331 +++++++++++++++++++++++++++++++++++
 16 files changed, 1147 insertions(+), 139 deletions(-)
 create mode 100644 src/context.c
 copy compat/libcompat.h => src/context.h (62%)
 create mode 100644 tests/t-mpi-point.c


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




More information about the Gnupg-commits mailing list