diff options
author | Werner Koch <wk@gnupg.org> | 2013-03-08 22:10:23 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2013-03-08 22:13:52 +0100 |
commit | 8ac9e756d3ca545a9b97e61ad3d42fc2e877d788 (patch) | |
tree | 9c371da68f09dca2379381529f9d7810957260b2 | |
parent | 7cce620acddac2df024ca421ed3abc32a88f3738 (diff) | |
download | libgcrypt-8ac9e756d3ca545a9b97e61ad3d42fc2e877d788.tar.gz |
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.
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | cipher/ecc.c | 14 | ||||
-rw-r--r-- | mpi/ec.c | 84 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/context.c | 118 | ||||
-rw-r--r-- | src/context.h | 31 | ||||
-rw-r--r-- | src/gcrypt.h.in | 27 | ||||
-rw-r--r-- | src/libgcrypt.def | 8 | ||||
-rw-r--r-- | src/libgcrypt.vers | 4 | ||||
-rw-r--r-- | src/mpi.h | 2 | ||||
-rw-r--r-- | src/visibility.c | 46 | ||||
-rw-r--r-- | src/visibility.h | 12 | ||||
-rw-r--r-- | tests/t-mpi-point.c | 170 |
13 files changed, 493 insertions, 31 deletions
@@ -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 789fc6c3..4efbef45 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); @@ -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 9e7dcd5f..1869ad3c 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 00000000..ae991c52 --- /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 00000000..72f14d48 --- /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 5d2a7792..57b841eb 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 8f14dff6..611f10f9 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 5c43b959..4a375b22 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: *; @@ -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 1fb29f2b..5c3216d2 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 f4507ceb..90c6ad14 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 548d6c7c..8714d388 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; |