diff options
author | Werner Koch <wk@gnupg.org> | 2011-02-01 10:40:50 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2011-02-01 10:40:50 +0100 |
commit | 5c4179860ef0b31b4c6ba957be9fa707a0ba7d9b (patch) | |
tree | 09caba0e0d855b9a16049dcde21305f922ed838e | |
parent | 7cb0d357f1564b2ba3fdde707bd9ee7272059d5b (diff) | |
download | libgcrypt-5c4179860ef0b31b4c6ba957be9fa707a0ba7d9b.tar.gz |
Add gcry_pk_get_curve.
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | cipher/ChangeLog | 5 | ||||
-rw-r--r-- | cipher/ecc.c | 87 | ||||
-rw-r--r-- | cipher/pubkey.c | 79 | ||||
-rw-r--r-- | src/ChangeLog | 7 | ||||
-rw-r--r-- | src/cipher-proto.h | 9 | ||||
-rw-r--r-- | src/gcrypt.h.in | 4 | ||||
-rw-r--r-- | src/libgcrypt.def | 5 | ||||
-rw-r--r-- | src/libgcrypt.vers | 1 | ||||
-rw-r--r-- | src/visibility.c | 13 | ||||
-rw-r--r-- | src/visibility.h | 3 | ||||
-rw-r--r-- | tests/ChangeLog | 4 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/curves.c | 175 |
14 files changed, 390 insertions, 8 deletions
@@ -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; +} |