mpi: Add an API for EC point operations.
authorWerner Koch <wk@gnupg.org>
Fri, 8 Mar 2013 14:06:20 +0000 (15:06 +0100)
committerWerner Koch <wk@gnupg.org>
Fri, 8 Mar 2013 14:06:20 +0000 (15:06 +0100)
* 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

NEWS
mpi/ec.c
src/gcrypt.h.in
src/libgcrypt.def
src/libgcrypt.vers
src/visibility.c
src/visibility.h
tests/Makefile.am
tests/t-mpi-point.c [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 1db71e9..e0ba536 100644 (file)
--- 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)
index 7b1ef2b..bb9bea4 100644 (file)
--- 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
index 7d2b89d..5d2a779 100644 (file)
@@ -212,9 +212,11 @@ struct gcry_thread_cbs
 
 
 \f
-/* 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))
index cc49e74..8f14dff 100644 (file)
@@ -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
index 200f04e..5c43b95 100644 (file)
@@ -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:
     *;
index 732f058..1fb29f2 100644 (file)
@@ -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)
index 429c246..f4507ce 100644 (file)
 #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
 #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)
index d337840..c18142e 100644 (file)
@@ -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 (file)
index 0000000..548d6c7
--- /dev/null
@@ -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);
+}
+
+
+\f
+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;
+}