summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--cipher/ChangeLog5
-rw-r--r--cipher/ecc.c87
-rw-r--r--cipher/pubkey.c79
-rw-r--r--src/ChangeLog7
-rw-r--r--src/cipher-proto.h9
-rw-r--r--src/gcrypt.h.in4
-rw-r--r--src/libgcrypt.def5
-rw-r--r--src/libgcrypt.vers1
-rw-r--r--src/visibility.c13
-rw-r--r--src/visibility.h3
-rw-r--r--tests/ChangeLog4
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/curves.c175
14 files changed, 390 insertions, 8 deletions
diff --git a/NEWS b/NEWS
index 48b2e06b..382927ea 100644
--- a/NEWS
+++ b/NEWS
@@ -22,12 +22,15 @@ Noteworthy changes in version 1.5.x (unreleased)
* gcry_sexp_build does now support opaque MPIs with "%m".
+ * New function gcry_pk_get_curve to map ECC parameters to a curve name.
+
* Interface changes relative to the 1.4.2 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GCRY_CIPHER_MODE_AESWRAP NEW.
GCRY_PK_ECDH NEW.
GCRY_MD_TIGER1 NEW.
GCRY_MD_TIGER2 NEW.
+ gcry_pk_get_curve NEW.
Noteworthy changes in version 1.4.4 (2009-01-22)
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 0f33f7a5..a32d5432 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,8 @@
+2011-02-01 Werner Koch <wk@g10code.com>
+
+ * pubkey.c (gcry_pk_get_curve): New.
+ * ecc.c (ecc_get_curve): New.
+
2011-01-31 Werner Koch <wk@g10code.com>
* ecc.c (ecc_encrypt_raw, ecc_decrypt_raw): Do not free passed
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 8b608955..215fcfb7 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -1107,6 +1107,90 @@ ecc_get_param (const char *name, gcry_mpi_t *pkey)
}
+/* Return the name matching the parameters in PKEY. */
+static const char *
+ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
+{
+ gpg_err_code_t err;
+ elliptic_curve_t E;
+ int idx;
+ gcry_mpi_t tmp;
+ const char *result = NULL;
+
+ if (r_nbits)
+ *r_nbits = 0;
+
+ if (!pkey)
+ {
+ idx = iterator;
+ if (idx >= 0 && idx < DIM (domain_parms))
+ {
+ result = domain_parms[idx].desc;
+ if (r_nbits)
+ *r_nbits = domain_parms[idx].nbits;
+ }
+ return result;
+ }
+
+ if (!pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4])
+ return NULL;
+
+ E.p = pkey[0];
+ E.a = pkey[1];
+ E.b = pkey[2];
+ point_init (&E.G);
+ err = os2ec (&E.G, pkey[3]);
+ if (err)
+ {
+ point_free (&E.G);
+ return NULL;
+ }
+ E.n = pkey[4];
+
+ for (idx = 0; domain_parms[idx].desc; idx++)
+ {
+ tmp = scanval (domain_parms[idx].p);
+ if (!mpi_cmp (tmp, E.p))
+ {
+ mpi_free (tmp);
+ tmp = scanval (domain_parms[idx].a);
+ if (!mpi_cmp (tmp, E.a))
+ {
+ mpi_free (tmp);
+ tmp = scanval (domain_parms[idx].b);
+ if (!mpi_cmp (tmp, E.b))
+ {
+ mpi_free (tmp);
+ tmp = scanval (domain_parms[idx].n);
+ if (!mpi_cmp (tmp, E.n))
+ {
+ mpi_free (tmp);
+ tmp = scanval (domain_parms[idx].g_x);
+ if (!mpi_cmp (tmp, E.G.x))
+ {
+ mpi_free (tmp);
+ tmp = scanval (domain_parms[idx].g_y);
+ if (!mpi_cmp (tmp, E.G.y))
+ {
+ result = domain_parms[idx].desc;
+ if (r_nbits)
+ *r_nbits = domain_parms[idx].nbits;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ mpi_free (tmp);
+ }
+
+ point_free (&E.G);
+
+ return result;
+}
+
+
static gcry_err_code_t
ecc_check_secret_key (int algo, gcry_mpi_t *skey)
{
@@ -1674,5 +1758,6 @@ pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa =
run_selftests,
ecc_generate_ext,
compute_keygrip,
- ecc_get_param
+ ecc_get_param,
+ ecc_get_curve
};
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index b2de4e60..b4ac214e 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -2482,6 +2482,85 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
}
+
+const char *
+gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
+{
+ gcry_mpi_t *pkey = NULL;
+ gcry_sexp_t list = NULL;
+ gcry_sexp_t l2;
+ gcry_module_t module = NULL;
+ pk_extra_spec_t *extraspec;
+ char *name = NULL;
+ const char *result = NULL;
+ int want_private = 1;
+
+ if (r_nbits)
+ *r_nbits = 0;
+
+ REGISTER_DEFAULT_PUBKEYS;
+
+ if (key)
+ {
+ iterator = 0;
+
+ /* Check that the first element is valid. */
+ list = gcry_sexp_find_token (key, "public-key", 0);
+ if (list)
+ want_private = 0;
+ if (!list)
+ list = gcry_sexp_find_token (key, "private-key", 0);
+ if (!list)
+ return NULL; /* No public- or private-key object. */
+
+ l2 = gcry_sexp_cadr (list);
+ gcry_sexp_release (list);
+ list = l2;
+ l2 = NULL;
+
+ name = _gcry_sexp_nth_string (list, 0);
+ if (!name)
+ goto leave; /* Invalid structure of object. */
+
+ /* Get the key. */
+ if (sexp_to_key (key, want_private, &pkey, &module))
+ goto leave;
+ }
+ else
+ {
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = gcry_pk_lookup_name ("ecc");
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ if (!module)
+ goto leave;
+ }
+
+ extraspec = module->extraspec;
+ if (!extraspec || !extraspec->get_curve)
+ goto leave;
+
+ result = extraspec->get_curve (pkey, iterator, r_nbits);
+
+ leave:
+ if (pkey)
+ {
+ release_mpi_array (pkey);
+ gcry_free (pkey);
+ }
+ if (module)
+ {
+ ath_mutex_lock (&pubkeys_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ }
+ gcry_free (name);
+ gcry_sexp_release (list);
+ return result;
+}
+
+
+
+
gcry_error_t
gcry_pk_ctl (int cmd, void *buffer, size_t buflen)
{
diff --git a/src/ChangeLog b/src/ChangeLog
index f2fbb327..b59f1c19 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
+2011-02-01 Werner Koch <wk@g10code.com>
+
+ * libgcrypt.vers (gcry_pk_get_curve): Add.
+ * libgcrypt.def (gcry_pk_get_curve): Add.
+ * visibility.c (gcry_pk_get_curve): New.
+ * cipher-proto.h (pk_extra_spec): Add field GET_CURVE.
+
2011-01-31 Werner Koch <wk@g10code.com>
* sexp.c (vsexp_sscan): Allow opaque MPIs in "%m".
diff --git a/src/cipher-proto.h b/src/cipher-proto.h
index 21532367..ea7a70de 100644
--- a/src/cipher-proto.h
+++ b/src/cipher-proto.h
@@ -1,5 +1,5 @@
/* cipher-proto.h - Internal declarations
- * Copyright (C) 2008 Free Software Foundation, Inc.
+ * Copyright (C) 2008, 2011 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
@@ -53,10 +53,14 @@ typedef gcry_err_code_t (*pk_ext_generate_t)
typedef gpg_err_code_t (*pk_comp_keygrip_t)
(gcry_md_hd_t md, gcry_sexp_t keyparm);
-/* The type used to quert ECC curve parameters. */
+/* The type used to query ECC curve parameters. */
typedef gcry_err_code_t (*pk_get_param_t)
(const char *name, gcry_mpi_t *pkey);
+/* The type used to query an ECC curve name. */
+typedef const char *(*pk_get_curve_t)(gcry_mpi_t *pkey, int iterator,
+ unsigned int *r_nbits);
+
/* The type used to convey additional information to a cipher. */
typedef gpg_err_code_t (*cipher_set_extra_info_t)
(void *c, int what, const void *buffer, size_t buflen);
@@ -82,6 +86,7 @@ typedef struct pk_extra_spec
pk_ext_generate_t ext_generate;
pk_comp_keygrip_t comp_keygrip;
pk_get_param_t get_param;
+ pk_get_curve_t get_curve;
} pk_extra_spec_t;
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 9c58b989..25099788 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -1037,6 +1037,10 @@ unsigned int gcry_pk_get_nbits (gcry_sexp_t key) _GCRY_GCC_ATTR_PURE;
used without contacting the author. */
unsigned char *gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array);
+/* Return the name of the curve matching KEY. */
+const char *gcry_pk_get_curve (gcry_sexp_t key, int iterator,
+ unsigned int *r_nbits);
+
/* Return 0 if the public key algorithm A is available for use. */
#define gcry_pk_test_algo(a) \
gcry_pk_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
diff --git a/src/libgcrypt.def b/src/libgcrypt.def
index 8fc4d329..55ff8775 100644
--- a/src/libgcrypt.def
+++ b/src/libgcrypt.def
@@ -230,8 +230,7 @@ EXPORTS
gcry_cipher_setkey @188
gcry_cipher_setiv @189
gcry_cipher_setctr @190
-
- gcry_mpi_lshift @191
-
+ gcry_mpi_lshift @191
+ gcry_pk_get_curve @192
diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers
index ef9fcee1..46704365 100644
--- a/src/libgcrypt.vers
+++ b/src/libgcrypt.vers
@@ -57,6 +57,7 @@ GCRYPT_1.2 {
gcry_pk_get_keygrip; gcry_pk_get_nbits; gcry_pk_list;
gcry_pk_map_name; gcry_pk_register; gcry_pk_sign;
gcry_pk_testkey; gcry_pk_unregister; gcry_pk_verify;
+ gcry_pk_get_curve;
gcry_ac_data_new; gcry_ac_data_destroy; gcry_ac_data_copy;
gcry_ac_data_length; gcry_ac_data_clear; gcry_ac_data_set;
diff --git a/src/visibility.c b/src/visibility.c
index f187a65e..fe6d9bdd 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -1,5 +1,5 @@
/* visibility.c - Wrapper for all public functions.
- * Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+ * Copyright (C) 2007, 2008, 2011 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
@@ -737,6 +737,17 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
return _gcry_pk_get_keygrip (key, array);
}
+const char *
+gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
+{
+ if (!fips_is_operational ())
+ {
+ (void)fips_not_operational ();
+ return NULL;
+ }
+ return _gcry_pk_get_curve (key, iterator, r_nbits);
+}
+
gcry_error_t
gcry_pk_list (int *list, int *list_length)
{
diff --git a/src/visibility.h b/src/visibility.h
index a11e5474..0b0219d3 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -103,6 +103,7 @@
#define gcry_pk_encrypt _gcry_pk_encrypt
#define gcry_pk_genkey _gcry_pk_genkey
#define gcry_pk_get_keygrip _gcry_pk_get_keygrip
+#define gcry_pk_get_curve _gcry_pk_get_curve
#define gcry_pk_get_nbits _gcry_pk_get_nbits
#define gcry_pk_list _gcry_pk_list
#define gcry_pk_map_name _gcry_pk_map_name
@@ -358,6 +359,7 @@ void gcry_ac_os_to_mpi (gcry_mpi_t mpi, unsigned char *os, size_t os_n);
#undef gcry_pk_encrypt
#undef gcry_pk_genkey
#undef gcry_pk_get_keygrip
+#undef gcry_pk_get_curve
#undef gcry_pk_get_nbits
#undef gcry_pk_list
#undef gcry_pk_map_name
@@ -568,6 +570,7 @@ MARK_VISIBLE (gcry_pk_decrypt)
MARK_VISIBLE (gcry_pk_encrypt)
MARK_VISIBLE (gcry_pk_genkey)
MARK_VISIBLE (gcry_pk_get_keygrip)
+MARK_VISIBLE (gcry_pk_get_curve)
MARK_VISIBLE (gcry_pk_get_nbits)
MARK_VISIBLE (gcry_pk_list)
MARK_VISIBLE (gcry_pk_map_name)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 64bad3e6..1836d0e0 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2011-02-01 Werner Koch <wk@g10code.com>
+
+ * curves.c: New.
+
2011-01-04 Werner Koch <wk@g10code.com>
* Makefile.am (LDADD): Fix typo in last change. Reported by
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 59cc5c47..bf26f680 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -19,7 +19,8 @@
## Process this file with automake to produce Makefile.in
TESTS = version t-mpi-bit prime register ac ac-schemes ac-data basic \
- mpitests tsexp keygen pubkey hmac keygrip fips186-dsa aeswrap
+ mpitests tsexp keygen pubkey hmac keygrip fips186-dsa aeswrap \
+ curves
# random.c uses fork() thus a test for W32 does not make any sense.
diff --git a/tests/curves.c b/tests/curves.c
new file mode 100644
index 00000000..dcf501a4
--- /dev/null
+++ b/tests/curves.c
@@ -0,0 +1,175 @@
+/* curves.c - ECC curves regression tests
+ * Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "../src/gcrypt.h"
+
+/* Number of curves defined in ../cipger/ecc.c */
+#define N_CURVES 12
+
+/* A real world sample public key. */
+static char const sample_key_1[] =
+"(public-key\n"
+" (ecdsa\n"
+" (p #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF#)\n"
+" (a #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC#)\n"
+" (b #5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B#)\n"
+" (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
+ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)\n"
+" (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)\n"
+" (q #0442B927242237639A36CE9221B340DB1A9AB76DF2FE3E171277F6A4023DED146EE"
+ "86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E#)\n"
+" ))";
+static char const sample_key_1_curve[] = "NIST P-256";
+static unsigned int sample_key_1_nbits = 256;
+
+/* A made up sample public key. */
+static char const sample_key_2[] =
+"(public-key\n"
+" (ecdh\n"
+" (p #e95e4a5f737059dc60dfc7ad95b3d8139515620f#)\n"
+" (a #340e7be2a280eb74e2be61bada745d97e8f7c300#)\n"
+" (b #1e589a8595423412134faa2dbdec95c8d8675e58#)\n"
+" (g #04bed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3"
+ "1667cb477a1a8ec338f94741669c976316da6321#)\n"
+" (n #e95e4a5f737059dc60df5991d45029409e60fc09#)\n"
+" (q #041111111111111111111111111111111111111111"
+ "2222222222222222222222222222222222222222#)\n"
+" ))";
+static char const sample_key_2_curve[] = "brainpoolP160r1";
+static unsigned int sample_key_2_nbits = 160;
+
+
+/* Program option flags. */
+static int verbose;
+static int error_count;
+
+static void
+fail (const char *format, ...)
+{
+ va_list arg_ptr;
+
+ 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;
+
+ va_start (arg_ptr, format);
+ vfprintf (stderr, format, arg_ptr);
+ va_end (arg_ptr);
+ exit (1);
+}
+
+
+static void
+list_curves (void)
+{
+ int idx;
+ const char *name;
+ unsigned int nbits;
+
+ for (idx=0; (name = gcry_pk_get_curve (NULL, idx, &nbits)); idx++)
+ {
+ if (verbose)
+ printf ("%s - %u bits\n", name, nbits);
+ }
+ if (idx != N_CURVES)
+ fail ("expected %d curves but got %d\n", N_CURVES, idx);
+ if (gcry_pk_get_curve (NULL, -1, NULL))
+ fail ("curve iteration failed\n");
+}
+
+
+static void
+check_matching (void)
+{
+ gpg_error_t err;
+ gcry_sexp_t key;
+ const char *name;
+ unsigned int nbits;
+
+ err = gcry_sexp_new (&key, sample_key_1, 0, 1);
+ if (err)
+ die ("parsing s-expression string failed: %s\n", gpg_strerror (err));
+ name = gcry_pk_get_curve (key, 0, &nbits);
+ if (!name)
+ fail ("curve name not found for sample_key_1\n");
+ else if (strcmp (name, sample_key_1_curve))
+ fail ("expected curve name %s but got %s for sample_key_1\n",
+ sample_key_1_curve, name);
+ else if (nbits != sample_key_1_nbits)
+ fail ("expected curve size %u but got %u for sample_key_1\n",
+ sample_key_1_nbits, nbits);
+
+ gcry_sexp_release (key);
+
+ err = gcry_sexp_new (&key, sample_key_2, 0, 1);
+ if (err)
+ die ("parsing s-expression string failed: %s\n", gpg_strerror (err));
+ name = gcry_pk_get_curve (key, 0, &nbits);
+ if (!name)
+ fail ("curve name not found for sample_key_2\n");
+ else if (strcmp (name, sample_key_2_curve))
+ fail ("expected curve name %s but got %s for sample_key_2\n",
+ sample_key_2_curve, name);
+ else if (nbits != sample_key_2_nbits)
+ fail ("expected curve size %u but got %u for sample_key_2\n",
+ sample_key_2_nbits, nbits);
+
+ gcry_sexp_release (key);
+}
+
+
+
+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_INITIALIZATION_FINISHED, 0);
+ if (debug)
+ gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+ list_curves ();
+ check_matching ();
+
+ return error_count ? 1 : 0;
+}