[PATCH 3/3] mpi: Add an API for EC math.
Werner Koch
wk at gnupg.org
Fri Mar 8 22:48:33 CET 2013
* 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.
---
NEWS | 6 ++
cipher/ecc.c | 14 ++--
mpi/ec.c | 84 ++++++++++++++++++++------
src/Makefile.am | 2 +-
src/context.c | 118 +++++++++++++++++++++++++++++++++++
src/context.h | 31 +++++++++
src/gcrypt.h.in | 27 ++++++++
src/libgcrypt.def | 8 +++
src/libgcrypt.vers | 4 +
src/mpi.h | 2 +-
src/visibility.c | 46 +++++++++++++-
src/visibility.h | 12 ++++
tests/t-mpi-point.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++-
13 files changed, 493 insertions(+), 31 deletions(-)
create mode 100644 src/context.c
create mode 100644 src/context.h
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;
--
1.7.7.1
--
Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz.
More information about the Gcrypt-devel
mailing list