diff options
-rw-r--r-- | cipher/Makefile.am | 2 | ||||
-rw-r--r-- | cipher/ecc-common.h | 80 | ||||
-rw-r--r-- | cipher/ecc-curves.c | 731 | ||||
-rw-r--r-- | cipher/ecc-misc.c | 183 | ||||
-rw-r--r-- | cipher/ecc.c | 939 | ||||
-rw-r--r-- | configure.ac | 3 |
6 files changed, 1022 insertions, 916 deletions
diff --git a/cipher/Makefile.am b/cipher/Makefile.am index c0f21fa1..e233e79f 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -60,7 +60,7 @@ crc.c \ des.c \ dsa.c \ elgamal.c \ -ecc.c \ +ecc.c ecc-curves.c ecc-misc.c ecc-common.h \ idea.c \ md4.c \ md5.c \ diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h new file mode 100644 index 00000000..94da73e1 --- /dev/null +++ b/cipher/ecc-common.h @@ -0,0 +1,80 @@ +/* ecc-common.h - Declarations of common ECC code + * 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_ECC_COMMON_H +#define GCRY_ECC_COMMON_H + +/* Definition of a curve. */ +typedef struct +{ + gcry_mpi_t p; /* Prime specifying the field GF(p). */ + gcry_mpi_t a; /* First coefficient of the Weierstrass equation. */ + gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. */ + mpi_point_struct G; /* Base point (generator). */ + gcry_mpi_t n; /* Order of G. */ + const char *name; /* Name of the curve or NULL. */ +} elliptic_curve_t; + + +typedef struct +{ + elliptic_curve_t E; + mpi_point_struct Q; /* Q = [d]G */ +} ECC_public_key; + + +typedef struct +{ + elliptic_curve_t E; + mpi_point_struct Q; + gcry_mpi_t d; +} ECC_secret_key; + + + +/* Set the value from S into D. */ +static inline void +point_set (mpi_point_t d, mpi_point_t s) +{ + mpi_set (d->x, s->x); + mpi_set (d->y, s->y); + mpi_set (d->z, s->z); +} + + +/*-- ecc-curves.c --*/ +gpg_err_code_t _gcry_ecc_fill_in_curve (unsigned int nbits, + const char *name, + elliptic_curve_t *curve, + unsigned int *r_nbits); + +const char *_gcry_ecc_get_curve (gcry_mpi_t *pkey, + int iterator, + unsigned int *r_nbits); +gcry_err_code_t _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey); +gcry_sexp_t _gcry_ecc_get_param_sexp (const char *name); + +/*-- ecc-misc.c --*/ +void _gcry_ecc_curve_free (elliptic_curve_t *E); +elliptic_curve_t _gcry_ecc_curve_copy (elliptic_curve_t E); +gcry_mpi_t _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p); +gcry_error_t _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value); + + +#endif /*GCRY_ECC_COMMON_H*/ diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c new file mode 100644 index 00000000..e813b6b4 --- /dev/null +++ b/cipher/ecc-curves.c @@ -0,0 +1,731 @@ +/* ecc-curves.c - Elliptic Curve parameter mangement + * Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc. + * 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 <errno.h> + +#include "g10lib.h" +#include "mpi.h" +#include "context.h" +#include "ec-context.h" +#include "ecc-common.h" + + +/* This tables defines aliases for curve names. */ +static const struct +{ + const char *name; /* Our name. */ + const char *other; /* Other name. */ +} curve_aliases[] = + { + { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID */ + { "NIST P-192", "prime192v1" }, /* X9.62 name. */ + { "NIST P-192", "secp192r1" }, /* SECP name. */ + { "NIST P-192", "nistp192" }, /* rfc5656. */ + + { "NIST P-224", "secp224r1" }, + { "NIST P-224", "1.3.132.0.33" }, /* SECP OID. */ + { "NIST P-224", "nistp224" }, /* rfc5656. */ + + { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1. */ + { "NIST P-256", "prime256v1" }, + { "NIST P-256", "secp256r1" }, + { "NIST P-256", "nistp256" }, /* rfc5656. */ + + { "NIST P-384", "secp384r1" }, + { "NIST P-384", "1.3.132.0.34" }, + { "NIST P-384", "nistp384" }, /* rfc5656. */ + + { "NIST P-521", "secp521r1" }, + { "NIST P-521", "1.3.132.0.35" }, + { "NIST P-521", "nistp521" }, /* rfc5656. */ + + { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" }, + { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" }, + { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" }, + { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" }, + { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" }, + { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"}, + { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"}, + + { NULL, NULL} + }; + + +typedef struct +{ + const char *desc; /* Description of the curve. */ + unsigned int nbits; /* Number of bits. */ + unsigned int fips:1; /* True if this is a FIPS140-2 approved curve. */ + const char *p; /* Order of the prime field. */ + const char *a, *b; /* The coefficients. */ + const char *n; /* The order of the base point. */ + const char *g_x, *g_y; /* Base point. */ +} ecc_domain_parms_t; + + +/* This static table defines all available curves. */ +static const ecc_domain_parms_t domain_parms[] = + { + { + "NIST P-192", 192, 1, + "0xfffffffffffffffffffffffffffffffeffffffffffffffff", + "0xfffffffffffffffffffffffffffffffefffffffffffffffc", + "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", + "0xffffffffffffffffffffffff99def836146bc9b1b4d22831", + + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", + "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + }, + { + "NIST P-224", 224, 1, + "0xffffffffffffffffffffffffffffffff000000000000000000000001", + "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe", + "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", + "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" , + + "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", + "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" + }, + { + "NIST P-256", 256, 1, + "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc", + "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", + "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + + "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", + "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" + }, + { + "NIST P-384", 384, 1, + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" + "ffffffff0000000000000000ffffffff", + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" + "ffffffff0000000000000000fffffffc", + "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a" + "c656398d8a2ed19d2a85c8edd3ec2aef", + "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf" + "581a0db248b0a77aecec196accc52973", + + "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38" + "5502f25dbf55296c3a545e3872760ab7", + "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0" + "0a60b1ce1d7e819d7a431d7c90ea0e5f" + }, + { + "NIST P-521", 521, 1, + "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc", + "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10" + "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", + "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", + + "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d" + "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", + "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6" + "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650" + }, + + { "brainpoolP160r1", 160, 0, + "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f", + "0x340e7be2a280eb74e2be61bada745d97e8f7c300", + "0x1e589a8595423412134faa2dbdec95c8d8675e58", + "0xe95e4a5f737059dc60df5991d45029409e60fc09", + "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3", + "0x1667cb477a1a8ec338f94741669c976316da6321" + }, + + { "brainpoolP192r1", 192, 0, + "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297", + "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef", + "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9", + "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1", + "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6", + "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f" + }, + + { "brainpoolP224r1", 224, 0, + "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff", + "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43", + "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b", + "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f", + "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d", + "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd" + }, + + { "brainpoolP256r1", 256, 0, + "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377", + "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9", + "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6", + "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7", + "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262", + "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997" + }, + + { "brainpoolP320r1", 320, 0, + "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28" + "fcd412b1f1b32e27", + "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4" + "92f375a97d860eb4", + "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981" + "6f5eb4ac8fb1f1a6", + "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9" + "8691555b44c59311", + "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7" + "10af8d0d39e20611", + "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7" + "d35245d1692e8ee1" + }, + + { "brainpoolP384r1", 384, 0, + "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123" + "acd3a729901d1a71874700133107ec53", + "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f" + "8aa5814a503ad4eb04a8c7dd22ce2826", + "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5" + "7cb4390295dbc9943ab78696fa504c11", + "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7" + "cf3ab6af6b7fc3103b883202e9046565", + "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8" + "e826e03436d646aaef87b2e247d4af1e", + "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928" + "0e4646217791811142820341263c5315" + }, + + { "brainpoolP512r1", 512, 0, + "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871" + "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3", + "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc" + "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca", + "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7" + "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723", + "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870" + "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069", + "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e" + "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822", + "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111" + "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892" + }, + + { NULL, 0, 0, NULL, NULL, NULL, NULL } + }; + + + + +/* Helper to scan a hex string. */ +static gcry_mpi_t +scanval (const char *string) +{ + gpg_error_t err; + gcry_mpi_t val; + + err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL); + if (err) + log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err)); + return val; +} + + +/* Generate the crypto system setup. This function takes the NAME of + a curve or the desired number of bits and stores at R_CURVE the + parameters of the named curve or those of a suitable curve. If + R_NBITS is not NULL, the chosen number of bits is stored there. */ +gpg_err_code_t +_gcry_ecc_fill_in_curve (unsigned int nbits, const char *name, + elliptic_curve_t *curve, unsigned int *r_nbits) +{ + int idx, aliasno; + const char *resname = NULL; /* Set to a found curve name. */ + + if (name) + { + /* First check our native curves. */ + for (idx = 0; domain_parms[idx].desc; idx++) + if (!strcmp (name, domain_parms[idx].desc)) + { + resname = domain_parms[idx].desc; + break; + } + /* If not found consult the alias table. */ + if (!domain_parms[idx].desc) + { + for (aliasno = 0; curve_aliases[aliasno].name; aliasno++) + if (!strcmp (name, curve_aliases[aliasno].other)) + break; + if (curve_aliases[aliasno].name) + { + for (idx = 0; domain_parms[idx].desc; idx++) + if (!strcmp (curve_aliases[aliasno].name, + domain_parms[idx].desc)) + { + resname = domain_parms[idx].desc; + break; + } + } + } + } + else + { + for (idx = 0; domain_parms[idx].desc; idx++) + if (nbits == domain_parms[idx].nbits) + break; + } + if (!domain_parms[idx].desc) + return GPG_ERR_INV_VALUE; + + /* In fips mode we only support NIST curves. Note that it is + possible to bypass this check by specifying the curve parameters + directly. */ + if (fips_mode () && !domain_parms[idx].fips ) + return GPG_ERR_NOT_SUPPORTED; + + if (r_nbits) + *r_nbits = domain_parms[idx].nbits; + curve->p = scanval (domain_parms[idx].p); + curve->a = scanval (domain_parms[idx].a); + curve->b = scanval (domain_parms[idx].b); + curve->n = scanval (domain_parms[idx].n); + curve->G.x = scanval (domain_parms[idx].g_x); + curve->G.y = scanval (domain_parms[idx].g_y); + curve->G.z = mpi_alloc_set_ui (1); + curve->name = resname; + + return 0; +} + + +/* Return the name matching the parameters in PKEY. */ +const char * +_gcry_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]; + _gcry_mpi_point_init (&E.G); + err = _gcry_ecc_os2ec (&E.G, pkey[3]); + if (err) + { + _gcry_mpi_point_free_parts (&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)) + { + mpi_free (tmp); + result = domain_parms[idx].desc; + if (r_nbits) + *r_nbits = domain_parms[idx].nbits; + break; + } + } + } + } + } + } + mpi_free (tmp); + } + + _gcry_mpi_point_free_parts (&E.G); + + return result; +} + + +/* Helper to extract an MPI from key parameters. */ +static gpg_err_code_t +mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name) +{ + gcry_err_code_t ec = 0; + gcry_sexp_t l1; + + l1 = gcry_sexp_find_token (keyparam, name, 0); + if (l1) + { + *r_a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l1); + if (!*r_a) + ec = GPG_ERR_INV_OBJ; + } + return ec; +} + +/* Helper to extract a point from key parameters. If no parameter + with NAME is found, the functions tries to find a non-encoded point + by appending ".x", ".y" and ".z" to NAME. ".z" is in this case + optional and defaults to 1. */ +static gpg_err_code_t +point_from_keyparam (gcry_mpi_point_t *r_a, + gcry_sexp_t keyparam, const char *name) +{ + gcry_err_code_t ec; + gcry_mpi_t a = NULL; + gcry_mpi_point_t point; + + ec = mpi_from_keyparam (&a, keyparam, name); + if (ec) + return ec; + + if (a) + { + point = gcry_mpi_point_new (0); + ec = _gcry_ecc_os2ec (point, a); + mpi_free (a); + if (ec) + { + gcry_mpi_point_release (point); + return ec; + } + } + else + { + char *tmpname; + gcry_mpi_t x = NULL; + gcry_mpi_t y = NULL; + gcry_mpi_t z = NULL; + + tmpname = gcry_malloc (strlen (name) + 2 + 1); + if (!tmpname) + return gpg_err_code_from_syserror (); + strcpy (stpcpy (tmpname, name), ".x"); + ec = mpi_from_keyparam (&x, keyparam, tmpname); + if (ec) + { + gcry_free (tmpname); + return ec; + } + strcpy (stpcpy (tmpname, name), ".y"); + ec = mpi_from_keyparam (&y, keyparam, tmpname); + if (ec) + { + mpi_free (x); + gcry_free (tmpname); + return ec; + } + strcpy (stpcpy (tmpname, name), ".z"); + ec = mpi_from_keyparam (&z, keyparam, tmpname); + if (ec) + { + mpi_free (y); + mpi_free (x); + gcry_free (tmpname); + return ec; + } + if (!z) + z = mpi_set_ui (NULL, 1); + if (x && y) + point = gcry_mpi_point_snatch_set (NULL, x, y, z); + else + { + mpi_free (x); + mpi_free (y); + mpi_free (z); + point = NULL; + } + gcry_free (tmpname); + } + + if (point) + *r_a = point; + return 0; +} + + +/* This function creates a new context for elliptic curve operations. + Either KEYPARAM or CURVENAME must be given. If both are given and + KEYPARAM has no curve parameter CURVENAME is used to add missing + parameters. On success 0 is returned and the new context stored at + R_CTX. On error NULL is stored at R_CTX and an error code is + returned. The context needs to be released using + gcry_ctx_release. */ +gpg_err_code_t +_gcry_mpi_ec_new (gcry_ctx_t *r_ctx, + gcry_sexp_t keyparam, const char *curvename) +{ + gpg_err_code_t errc; + gcry_ctx_t ctx = NULL; + gcry_mpi_t p = NULL; + gcry_mpi_t a = NULL; + gcry_mpi_t b = NULL; + gcry_mpi_point_t G = NULL; + gcry_mpi_t n = NULL; + gcry_mpi_point_t Q = NULL; + gcry_mpi_t d = NULL; + gcry_sexp_t l1; + + *r_ctx = NULL; + + if (keyparam) + { + errc = mpi_from_keyparam (&p, keyparam, "p"); + if (errc) + goto leave; + errc = mpi_from_keyparam (&a, keyparam, "a"); + if (errc) + goto leave; + errc = mpi_from_keyparam (&b, keyparam, "b"); + if (errc) + goto leave; + errc = point_from_keyparam (&G, keyparam, "g"); + if (errc) + goto leave; + errc = mpi_from_keyparam (&n, keyparam, "n"); + if (errc) + goto leave; + errc = point_from_keyparam (&Q, keyparam, "q"); + if (errc) + goto leave; + errc = mpi_from_keyparam (&d, keyparam, "d"); + if (errc) + goto leave; + } + + + /* Check whether a curve parameter is available and use that to fill + in missing values. If no curve parameter is available try an + optional provided curvename. If only the curvename has been + given use that one. */ + if (keyparam) + l1 = gcry_sexp_find_token (keyparam, "curve", 5); + else + l1 = NULL; + if (l1 || curvename) + { + char *name; + elliptic_curve_t *E; + + if (l1) + { + name = _gcry_sexp_nth_string (l1, 1); + gcry_sexp_release (l1); + if (!name) + { + errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */ + goto leave; + } + } + else + name = NULL; + + E = gcry_calloc (1, sizeof *E); + if (!E) + { + errc = gpg_err_code_from_syserror (); + gcry_free (name); + goto leave; + } + + errc = _gcry_ecc_fill_in_curve (0, name? name : curvename, E, NULL); + gcry_free (name); + if (errc) + { + gcry_free (E); + goto leave; + } + + if (!p) + { + p = E->p; + E->p = NULL; + } + if (!a) + { + a = E->a; + E->a = NULL; + } + if (!b) + { + b = E->b; + E->b = NULL; + } + if (!G) + { + G = gcry_mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z); + E->G.x = NULL; + E->G.y = NULL; + E->G.z = NULL; + } + if (!n) + { + n = E->n; + E->n = NULL; + } + _gcry_ecc_curve_free (E); + gcry_free (E); + } + + errc = _gcry_mpi_ec_p_new (&ctx, p, a); + if (!errc) + { + mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); + + if (b) + { + ec->b = b; + b = NULL; + } + if (G) + { + ec->G = G; + G = NULL; + } + if (n) + { + ec->n = n; + n = NULL; + } + if (Q) + { + ec->Q = Q; + Q = NULL; + } + if (d) + { + ec->d = d; + d = NULL; + } + + *r_ctx = ctx; + } + + leave: + mpi_free (p); + mpi_free (a); + mpi_free (b); + gcry_mpi_point_release (G); + mpi_free (n); + gcry_mpi_point_release (Q); + mpi_free (d); + return errc; +} + + +/* Return the parameters of the curve NAME in an MPI array. */ +gcry_err_code_t +_gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey) +{ + gpg_err_code_t err; + unsigned int nbits; + elliptic_curve_t E; + mpi_ec_t ctx; + gcry_mpi_t g_x, g_y; + + err = _gcry_ecc_fill_in_curve (0, name, &E, &nbits); + if (err) + return err; + + g_x = mpi_new (0); + g_y = mpi_new (0); + 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); + _gcry_mpi_point_free_parts (&E.G); + + pkey[0] = E.p; + pkey[1] = E.a; + pkey[2] = E.b; + pkey[3] = _gcry_ecc_ec2os (g_x, g_y, E.p); + pkey[4] = E.n; + pkey[5] = NULL; + + mpi_free (g_x); + mpi_free (g_y); + + return 0; +} + + +/* Return the parameters of the curve NAME as an S-expression. */ +gcry_sexp_t +_gcry_ecc_get_param_sexp (const char *name) +{ + gcry_mpi_t pkey[6]; + gcry_sexp_t result; + int i; + + if (_gcry_ecc_get_param (name, pkey)) + return NULL; + + if (gcry_sexp_build (&result, NULL, + "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))", + pkey[0], pkey[1], pkey[2], pkey[3], pkey[4])) + result = NULL; + + for (i=0; pkey[i]; i++) + gcry_mpi_release (pkey[i]); + + return result; +} diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c new file mode 100644 index 00000000..5e06bef9 --- /dev/null +++ b/cipher/ecc-misc.c @@ -0,0 +1,183 @@ +/* ecc-misc.c - Elliptic Curve miscellaneous functions + * Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc. + * 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 <errno.h> + +#include "g10lib.h" +#include "mpi.h" +#include "context.h" +#include "ec-context.h" +#include "ecc-common.h" + + +/* + * Release a curve object. + */ +void +_gcry_ecc_curve_free (elliptic_curve_t *E) +{ + mpi_free (E->p); E->p = NULL; + mpi_free (E->a); E->a = NULL; + mpi_free (E->b); E->b = NULL; + _gcry_mpi_point_free_parts (&E->G); + mpi_free (E->n); E->n = NULL; +} + + +/* + * Return a copy of a curve object. + */ +elliptic_curve_t +_gcry_ecc_curve_copy (elliptic_curve_t E) +{ + elliptic_curve_t R; + + R.p = mpi_copy (E.p); + R.a = mpi_copy (E.a); + R.b = mpi_copy (E.b); + _gcry_mpi_point_init (&R.G); + point_set (&R.G, &E.G); + R.n = mpi_copy (E.n); + + return R; +} + + +gcry_mpi_t +_gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p) +{ + gpg_error_t err; + int pbytes = (mpi_get_nbits (p)+7)/8; + size_t n; + unsigned char *buf, *ptr; + gcry_mpi_t result; + + buf = gcry_xmalloc ( 1 + 2*pbytes ); + *buf = 04; /* Uncompressed point. */ + ptr = buf+1; + err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x); + if (err) + log_fatal ("mpi_print failed: %s\n", gpg_strerror (err)); + if (n < pbytes) + { + memmove (ptr+(pbytes-n), ptr, n); + memset (ptr, 0, (pbytes-n)); + } + ptr += pbytes; + err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y); + if (err) + log_fatal ("mpi_print failed: %s\n", gpg_strerror (err)); + if (n < pbytes) + { + memmove (ptr+(pbytes-n), ptr, n); + memset (ptr, 0, (pbytes-n)); + } + + err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL); + if (err) + log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); + gcry_free (buf); + + return result; +} + + +/* Convert POINT into affine coordinates using the context CTX and + return a newly allocated MPI. If the conversion is not possible + NULL is returned. This function won't print an error message. */ +gcry_mpi_t +_gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ectx) +{ + gcry_mpi_t g_x, g_y, result; + + g_x = mpi_new (0); + g_y = mpi_new (0); + if (_gcry_mpi_ec_get_affine (g_x, g_y, point, ectx)) + result = NULL; + else + result = _gcry_ecc_ec2os (g_x, g_y, ectx->p); + mpi_free (g_x); + mpi_free (g_y); + + return result; +} + + +/* RESULT must have been initialized and is set on success to the + point given by VALUE. */ +gcry_error_t +_gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value) +{ + gcry_error_t err; + size_t n; + unsigned char *buf; + gcry_mpi_t x, y; + + n = (mpi_get_nbits (value)+7)/8; + buf = gcry_xmalloc (n); + err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, n, &n, value); + if (err) + { + gcry_free (buf); + return err; + } + if (n < 1) + { + gcry_free (buf); + return GPG_ERR_INV_OBJ; + } + if (*buf != 4) + { + gcry_free (buf); + return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression. */ + } + if ( ((n-1)%2) ) + { + gcry_free (buf); + return GPG_ERR_INV_OBJ; + } + n = (n-1)/2; + err = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL); + if (err) + { + gcry_free (buf); + return err; + } + err = gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL); + gcry_free (buf); + if (err) + { + mpi_free (x); + return err; + } + + mpi_set (result->x, x); + mpi_set (result->y, y); + mpi_set_ui (result->z, 1); + + mpi_free (x); + mpi_free (y); + + return 0; +} diff --git a/cipher/ecc.c b/cipher/ecc.c index b694d761..9174f9bc 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -47,11 +47,6 @@ - In mpi/ec.c we use mpi_powm for x^2 mod p: Either implement a special case in mpi_powm or check whether mpi_mulm is faster. - - Split this up into several files. For example the curve - management and gcry_mpi_ec_new are independent of the actual ECDSA - implementation. This will also help to support optimized versions - of some curves. - */ @@ -67,232 +62,7 @@ #include "context.h" #include "ec-context.h" #include "pubkey-internal.h" - -/* Definition of a curve. */ -typedef struct -{ - gcry_mpi_t p; /* Prime specifying the field GF(p). */ - gcry_mpi_t a; /* First coefficient of the Weierstrass equation. */ - gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. */ - mpi_point_struct G; /* Base point (generator). */ - gcry_mpi_t n; /* Order of G. */ - const char *name; /* Name of the curve or NULL. */ -} elliptic_curve_t; - - -typedef struct -{ - elliptic_curve_t E; - mpi_point_struct Q; /* Q = [d]G */ -} ECC_public_key; - -typedef struct -{ - elliptic_curve_t E; - mpi_point_struct Q; - gcry_mpi_t d; -} ECC_secret_key; - - -/* This tables defines aliases for curve names. */ -static const struct -{ - const char *name; /* Our name. */ - const char *other; /* Other name. */ -} curve_aliases[] = - { - { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID */ - { "NIST P-192", "prime192v1" }, /* X9.62 name. */ - { "NIST P-192", "secp192r1" }, /* SECP name. */ - { "NIST P-192", "nistp192" }, /* rfc5656. */ - - { "NIST P-224", "secp224r1" }, - { "NIST P-224", "1.3.132.0.33" }, /* SECP OID. */ - { "NIST P-224", "nistp224" }, /* rfc5656. */ - - { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1. */ - { "NIST P-256", "prime256v1" }, - { "NIST P-256", "secp256r1" }, - { "NIST P-256", "nistp256" }, /* rfc5656. */ - - { "NIST P-384", "secp384r1" }, - { "NIST P-384", "1.3.132.0.34" }, - { "NIST P-384", "nistp384" }, /* rfc5656. */ - - { "NIST P-521", "secp521r1" }, - { "NIST P-521", "1.3.132.0.35" }, - { "NIST P-521", "nistp521" }, /* rfc5656. */ - - { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" }, - { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" }, - { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" }, - { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" }, - { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" }, - { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"}, - { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"}, - - { NULL, NULL} - }; - -typedef struct { - const char *desc; /* Description of the curve. */ - unsigned int nbits; /* Number of bits. */ - unsigned int fips:1; /* True if this is a FIPS140-2 approved curve. */ - const char *p; /* Order of the prime field. */ - const char *a, *b; /* The coefficients. */ - const char *n; /* The order of the base point. */ - const char *g_x, *g_y; /* Base point. */ -} ecc_domain_parms_t; - -/* This static table defines all available curves. */ -static const ecc_domain_parms_t domain_parms[] = - { - { - "NIST P-192", 192, 1, - "0xfffffffffffffffffffffffffffffffeffffffffffffffff", - "0xfffffffffffffffffffffffffffffffefffffffffffffffc", - "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", - "0xffffffffffffffffffffffff99def836146bc9b1b4d22831", - - "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", - "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" - }, - { - "NIST P-224", 224, 1, - "0xffffffffffffffffffffffffffffffff000000000000000000000001", - "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe", - "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", - "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" , - - "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", - "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" - }, - { - "NIST P-256", 256, 1, - "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff", - "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc", - "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", - "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", - - "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", - "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" - }, - { - "NIST P-384", 384, 1, - "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" - "ffffffff0000000000000000ffffffff", - "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" - "ffffffff0000000000000000fffffffc", - "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a" - "c656398d8a2ed19d2a85c8edd3ec2aef", - "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf" - "581a0db248b0a77aecec196accc52973", - - "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38" - "5502f25dbf55296c3a545e3872760ab7", - "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0" - "0a60b1ce1d7e819d7a431d7c90ea0e5f" - }, - { - "NIST P-521", 521, 1, - "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc", - "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10" - "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", - "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", - - "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d" - "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", - "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6" - "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650" - }, - - { "brainpoolP160r1", 160, 0, - "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f", - "0x340e7be2a280eb74e2be61bada745d97e8f7c300", - "0x1e589a8595423412134faa2dbdec95c8d8675e58", - "0xe95e4a5f737059dc60df5991d45029409e60fc09", - "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3", - "0x1667cb477a1a8ec338f94741669c976316da6321" - }, - - { "brainpoolP192r1", 192, 0, - "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297", - "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef", - "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9", - "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1", - "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6", - "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f" - }, - - { "brainpoolP224r1", 224, 0, - "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff", - "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43", - "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b", - "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f", - "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d", - "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd" - }, - - { "brainpoolP256r1", 256, 0, - "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377", - "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9", - "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6", - "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7", - "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262", - "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997" - }, - - { "brainpoolP320r1", 320, 0, - "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28" - "fcd412b1f1b32e27", - "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4" - "92f375a97d860eb4", - "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981" - "6f5eb4ac8fb1f1a6", - "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9" - "8691555b44c59311", - "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7" - "10af8d0d39e20611", - "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7" - "d35245d1692e8ee1" - }, - - { "brainpoolP384r1", 384, 0, - "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123" - "acd3a729901d1a71874700133107ec53", - "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f" - "8aa5814a503ad4eb04a8c7dd22ce2826", - "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5" - "7cb4390295dbc9943ab78696fa504c11", - "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7" - "cf3ab6af6b7fc3103b883202e9046565", - "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8" - "e826e03436d646aaef87b2e247d4af1e", - "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928" - "0e4646217791811142820341263c5315" - }, - - { "brainpoolP512r1", 512, 0, - "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871" - "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3", - "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc" - "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca", - "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7" - "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723", - "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870" - "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069", - "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e" - "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822", - "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111" - "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892" - }, - - { NULL, 0, 0, NULL, NULL, NULL, NULL } - }; +#include "ecc-common.h" /* Registered progress function and its callback value. */ @@ -303,7 +73,6 @@ static void *progress_cb_data; #define point_init(a) _gcry_mpi_point_init ((a)) #define point_free(a) _gcry_mpi_point_free_parts ((a)) - /* Local prototypes. */ static void test_keys (ECC_secret_key * sk, unsigned int nbits); @@ -339,66 +108,6 @@ _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *, -/* Set the value from S into D. */ -static void -point_set (mpi_point_t d, mpi_point_t s) -{ - mpi_set (d->x, s->x); - mpi_set (d->y, s->y); - mpi_set (d->z, s->z); -} - - -/* - * Release a curve object. - */ -static void -curve_free (elliptic_curve_t *E) -{ - mpi_free (E->p); E->p = NULL; - mpi_free (E->a); E->a = NULL; - mpi_free (E->b); E->b = NULL; - point_free (&E->G); - mpi_free (E->n); E->n = NULL; -} - - -/* - * Return a copy of a curve object. - */ -static elliptic_curve_t -curve_copy (elliptic_curve_t E) -{ - elliptic_curve_t R; - - R.p = mpi_copy (E.p); - R.a = mpi_copy (E.a); - R.b = mpi_copy (E.b); - point_init (&R.G); - point_set (&R.G, &E.G); - R.n = mpi_copy (E.n); - - return R; -} - - -/* Helper to scan a hex string. */ -static gcry_mpi_t -scanval (const char *string) -{ - gpg_error_t err; - gcry_mpi_t val; - - err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL); - if (err) - log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err)); - return val; -} - - - - - /**************** * Solve the right side of the equation that defines a curve. */ @@ -424,74 +133,6 @@ gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base) } -/* Generate the crypto system setup. This function takes the NAME of - a curve or the desired number of bits and stores at R_CURVE the - parameters of the named curve or those of a suitable curve. If - R_NBITS is not NULL, the chosen number of bits is stored there. */ -static gpg_err_code_t -fill_in_curve (unsigned int nbits, const char *name, - elliptic_curve_t *curve, unsigned int *r_nbits) -{ - int idx, aliasno; - const char *resname = NULL; /* Set to a found curve name. */ - - if (name) - { - /* First check our native curves. */ - for (idx = 0; domain_parms[idx].desc; idx++) - if (!strcmp (name, domain_parms[idx].desc)) - { - resname = domain_parms[idx].desc; - break; - } - /* If not found consult the alias table. */ - if (!domain_parms[idx].desc) - { - for (aliasno = 0; curve_aliases[aliasno].name; aliasno++) - if (!strcmp (name, curve_aliases[aliasno].other)) - break; - if (curve_aliases[aliasno].name) - { - for (idx = 0; domain_parms[idx].desc; idx++) - if (!strcmp (curve_aliases[aliasno].name, - domain_parms[idx].desc)) - { - resname = domain_parms[idx].desc; - break; - } - } - } - } - else - { - for (idx = 0; domain_parms[idx].desc; idx++) - if (nbits == domain_parms[idx].nbits) - break; - } - if (!domain_parms[idx].desc) - return GPG_ERR_INV_VALUE; - - /* In fips mode we only support NIST curves. Note that it is - possible to bypass this check by specifying the curve parameters - directly. */ - if (fips_mode () && !domain_parms[idx].fips ) - return GPG_ERR_NOT_SUPPORTED; - - if (r_nbits) - *r_nbits = domain_parms[idx].nbits; - curve->p = scanval (domain_parms[idx].p); - curve->a = scanval (domain_parms[idx].a); - curve->b = scanval (domain_parms[idx].b); - curve->n = scanval (domain_parms[idx].n); - curve->G.x = scanval (domain_parms[idx].g_x); - curve->G.y = scanval (domain_parms[idx].g_y); - curve->G.z = mpi_alloc_set_ui (1); - curve->name = resname; - - return 0; -} - - /* * First obtain the setup. Over the finite field randomize an scalar * secret value, and calculate the public point. @@ -511,7 +152,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, *r_usedcurve = NULL; - err = fill_in_curve (nbits, name, &E, &nbits); + err = _gcry_ecc_fill_in_curve (nbits, name, &E, &nbits); if (err) return err; @@ -605,7 +246,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, point_free (&Q); *r_usedcurve = E.name; - curve_free (&E); + _gcry_ecc_curve_free (&E); /* Now we can test our keys (this should never fail!). */ test_keys (sk, nbits - 64); @@ -636,7 +277,7 @@ test_keys (ECC_secret_key *sk, unsigned int nbits) point_init (&R_); - pk.E = curve_copy (sk->E); + pk.E = _gcry_ecc_curve_copy (sk->E); point_init (&pk.Q); point_set (&pk.Q, &sk->Q); @@ -654,7 +295,7 @@ test_keys (ECC_secret_key *sk, unsigned int nbits) log_debug ("ECDSA operation: sign, verify ok.\n"); point_free (&pk.Q); - curve_free (&pk.E); + _gcry_ecc_curve_free (&pk.E); point_free (&R_); mpi_free (s); @@ -728,7 +369,7 @@ check_secret_key (ECC_secret_key * sk) goto leave; } - /* Fast path for loaded secret keys - sk->Q is already in affine coordinates */ + /* Fast path for loaded secret keys - Q is already in affine coordinates */ if (!mpi_cmp_ui (sk->Q.z, 1)) { if (mpi_cmp (x1, sk->Q.x) || mpi_cmp (y_2, sk->Q.y)) @@ -976,124 +617,6 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) /********************************************* ************** interface ****************** *********************************************/ -static gcry_mpi_t -ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p) -{ - gpg_error_t err; - int pbytes = (mpi_get_nbits (p)+7)/8; - size_t n; - unsigned char *buf, *ptr; - gcry_mpi_t result; - - buf = gcry_xmalloc ( 1 + 2*pbytes ); - *buf = 04; /* Uncompressed point. */ - ptr = buf+1; - err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x); - if (err) - log_fatal ("mpi_print failed: %s\n", gpg_strerror (err)); - if (n < pbytes) - { - memmove (ptr+(pbytes-n), ptr, n); - memset (ptr, 0, (pbytes-n)); - } - ptr += pbytes; - err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y); - if (err) - log_fatal ("mpi_print failed: %s\n", gpg_strerror (err)); - if (n < pbytes) - { - memmove (ptr+(pbytes-n), ptr, n); - memset (ptr, 0, (pbytes-n)); - } - - err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL); - if (err) - log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); - gcry_free (buf); - - return result; -} - - -/* Convert POINT into affine coordinates using the context CTX and - return a newly allocated MPI. If the conversion is not possible - NULL is returned. This function won't print an error message. */ -gcry_mpi_t -_gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ectx) -{ - gcry_mpi_t g_x, g_y, result; - - g_x = mpi_new (0); - g_y = mpi_new (0); - if (_gcry_mpi_ec_get_affine (g_x, g_y, point, ectx)) - result = NULL; - else - result = ec2os (g_x, g_y, ectx->p); - mpi_free (g_x); - mpi_free (g_y); - - return result; -} - - -/* RESULT must have been initialized and is set on success to the - point given by VALUE. */ -static gcry_error_t -os2ec (mpi_point_t result, gcry_mpi_t value) -{ - gcry_error_t err; - size_t n; - unsigned char *buf; - gcry_mpi_t x, y; - - n = (mpi_get_nbits (value)+7)/8; - buf = gcry_xmalloc (n); - err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, n, &n, value); - if (err) - { - gcry_free (buf); - return err; - } - if (n < 1) - { - gcry_free (buf); - return GPG_ERR_INV_OBJ; - } - if (*buf != 4) - { - gcry_free (buf); - return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression. */ - } - if ( ((n-1)%2) ) - { - gcry_free (buf); - return GPG_ERR_INV_OBJ; - } - n = (n-1)/2; - err = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL); - if (err) - { - gcry_free (buf); - return err; - } - err = gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL); - gcry_free (buf); - if (err) - { - mpi_free (x); - return err; - } - - mpi_set (result->x, x); - mpi_set (result->y, y); - mpi_set_ui (result->z, 1); - - mpi_free (x); - mpi_free (y); - - return 0; -} - /* Extended version of ecc_generate. */ static gcry_err_code_t @@ -1153,9 +676,9 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, skey[0] = sk.E.p; skey[1] = sk.E.a; skey[2] = sk.E.b; - skey[3] = ec2os (g_x, g_y, sk.E.p); + skey[3] = _gcry_ecc_ec2os (g_x, g_y, sk.E.p); skey[4] = sk.E.n; - skey[5] = ec2os (q_x, q_y, sk.E.p); + skey[5] = _gcry_ecc_ec2os (q_x, q_y, sk.E.p); skey[6] = sk.d; mpi_free (g_x); @@ -1195,150 +718,6 @@ ecc_generate (int algo, unsigned int nbits, unsigned long evalue, } -/* Return the parameters of the curve NAME in an MPI array. */ -static gcry_err_code_t -ecc_get_param (const char *name, gcry_mpi_t *pkey) -{ - gpg_err_code_t err; - unsigned int nbits; - elliptic_curve_t E; - mpi_ec_t ctx; - gcry_mpi_t g_x, g_y; - - err = fill_in_curve (0, name, &E, &nbits); - if (err) - return err; - - g_x = mpi_new (0); - g_y = mpi_new (0); - 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); - point_free (&E.G); - - pkey[0] = E.p; - pkey[1] = E.a; - pkey[2] = E.b; - pkey[3] = ec2os (g_x, g_y, E.p); - pkey[4] = E.n; - pkey[5] = NULL; - - mpi_free (g_x); - mpi_free (g_y); - - return 0; -} - - -/* Return the parameters of the curve NAME as an S-expression. */ -static gcry_sexp_t -ecc_get_param_sexp (const char *name) -{ - gcry_mpi_t pkey[6]; - gcry_sexp_t result; - int i; - - if (ecc_get_param (name, pkey)) - return NULL; - - if (gcry_sexp_build (&result, NULL, - "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))", - pkey[0], pkey[1], pkey[2], pkey[3], pkey[4])) - result = NULL; - - for (i=0; pkey[i]; i++) - gcry_mpi_release (pkey[i]); - - return result; -} - - -/* 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)) - { - mpi_free (tmp); - 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) { @@ -1356,7 +735,7 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey) sk.E.a = skey[1]; sk.E.b = skey[2]; point_init (&sk.E.G); - err = os2ec (&sk.E.G, skey[3]); + err = _gcry_ecc_os2ec (&sk.E.G, skey[3]); if (err) { point_free (&sk.E.G); @@ -1364,7 +743,7 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey) } sk.E.n = skey[4]; point_init (&sk.Q); - err = os2ec (&sk.Q, skey[5]); + err = _gcry_ecc_os2ec (&sk.Q, skey[5]); if (err) { point_free (&sk.E.G); @@ -1403,7 +782,7 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey, sk.E.a = skey[1]; sk.E.b = skey[2]; point_init (&sk.E.G); - err = os2ec (&sk.E.G, skey[3]); + err = _gcry_ecc_os2ec (&sk.E.G, skey[3]); if (err) { point_free (&sk.E.G); @@ -1446,7 +825,7 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, pk.E.a = pkey[1]; pk.E.b = pkey[2]; point_init (&pk.E.G); - err = os2ec (&pk.E.G, pkey[3]); + err = _gcry_ecc_os2ec (&pk.E.G, pkey[3]); if (err) { point_free (&pk.E.G); @@ -1454,7 +833,7 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, } pk.E.n = pkey[4]; point_init (&pk.Q); - err = os2ec (&pk.Q, pkey[5]); + err = _gcry_ecc_os2ec (&pk.Q, pkey[5]); if (err) { point_free (&pk.E.G); @@ -1538,7 +917,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k, pk.E.a = pkey[1]; pk.E.b = pkey[2]; point_init (&pk.E.G); - err = os2ec (&pk.E.G, pkey[3]); + err = _gcry_ecc_os2ec (&pk.E.G, pkey[3]); if (err) { point_free (&pk.E.G); @@ -1546,7 +925,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k, } pk.E.n = pkey[4]; point_init (&pk.Q); - err = os2ec (&pk.Q, pkey[5]); + err = _gcry_ecc_os2ec (&pk.Q, pkey[5]); if (err) { point_free (&pk.E.G); @@ -1572,7 +951,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k, if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) log_fatal ("ecdh: Failed to get affine coordinates for kdG\n"); - result[0] = ec2os (x, y, pk.E.p); + result[0] = _gcry_ecc_ec2os (x, y, pk.E.p); /* R = kG */ _gcry_mpi_ec_mul_point (&R, k, &pk.E.G, ctx); @@ -1580,7 +959,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k, if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) log_fatal ("ecdh: Failed to get affine coordinates for kG\n"); - result[1] = ec2os (x, y, pk.E.p); + result[1] = _gcry_ecc_ec2os (x, y, pk.E.p); mpi_free (x); mpi_free (y); @@ -1635,7 +1014,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, return GPG_ERR_BAD_MPI; point_init (&kG); - err = os2ec (&kG, data[0]); + err = _gcry_ecc_os2ec (&kG, data[0]); if (err) { point_free (&kG); @@ -1647,7 +1026,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, sk.E.a = skey[1]; sk.E.b = skey[2]; point_init (&sk.E.G); - err = os2ec (&sk.E.G, skey[3]); + err = _gcry_ecc_os2ec (&sk.E.G, skey[3]); if (err) { point_free (&kG); @@ -1656,7 +1035,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, } sk.E.n = skey[4]; point_init (&sk.Q); - err = os2ec (&sk.Q, skey[5]); + err = _gcry_ecc_os2ec (&sk.Q, skey[5]); if (err) { point_free (&kG); @@ -1684,7 +1063,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) log_fatal ("ecdh: Failed to get affine coordinates\n"); - r = ec2os (x, y, sk.E.p); + r = _gcry_ecc_ec2os (x, y, sk.E.p); mpi_free (x); mpi_free (y); } @@ -1764,7 +1143,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */ goto leave; } - ec = ecc_get_param (curve, tmpvalues); + ec = _gcry_ecc_get_param (curve, tmpvalues); gcry_free (curve); if (ec) goto leave; @@ -1824,274 +1203,6 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) Low-level API helper functions. */ -/* Helper to extract an MPI from key parameters. */ -static gpg_err_code_t -mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name) -{ - gcry_err_code_t ec = 0; - gcry_sexp_t l1; - - l1 = gcry_sexp_find_token (keyparam, name, 0); - if (l1) - { - *r_a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); - gcry_sexp_release (l1); - if (!*r_a) - ec = GPG_ERR_INV_OBJ; - } - return ec; -} - -/* Helper to extract a point from key parameters. If no parameter - with NAME is found, the functions tries to find a non-encoded point - by appending ".x", ".y" and ".z" to NAME. ".z" is in this case - optional and defaults to 1. */ -static gpg_err_code_t -point_from_keyparam (gcry_mpi_point_t *r_a, - gcry_sexp_t keyparam, const char *name) -{ - gcry_err_code_t ec; - gcry_mpi_t a = NULL; - gcry_mpi_point_t point; - - ec = mpi_from_keyparam (&a, keyparam, name); - if (ec) - return ec; - - if (a) - { - point = gcry_mpi_point_new (0); - ec = os2ec (point, a); - mpi_free (a); - if (ec) - { - gcry_mpi_point_release (point); - return ec; - } - } - else - { - char *tmpname; - gcry_mpi_t x = NULL; - gcry_mpi_t y = NULL; - gcry_mpi_t z = NULL; - - tmpname = gcry_malloc (strlen (name) + 2 + 1); - if (!tmpname) - return gpg_err_code_from_syserror (); - strcpy (stpcpy (tmpname, name), ".x"); - ec = mpi_from_keyparam (&x, keyparam, tmpname); - if (ec) - { - gcry_free (tmpname); - return ec; - } - strcpy (stpcpy (tmpname, name), ".y"); - ec = mpi_from_keyparam (&y, keyparam, tmpname); - if (ec) - { - mpi_free (x); - gcry_free (tmpname); - return ec; - } - strcpy (stpcpy (tmpname, name), ".z"); - ec = mpi_from_keyparam (&z, keyparam, tmpname); - if (ec) - { - mpi_free (y); - mpi_free (x); - gcry_free (tmpname); - return ec; - } - if (!z) - z = mpi_set_ui (NULL, 1); - if (x && y) - point = gcry_mpi_point_snatch_set (NULL, x, y, z); - else - { - mpi_free (x); - mpi_free (y); - mpi_free (z); - point = NULL; - } - gcry_free (tmpname); - } - - if (point) - *r_a = point; - return 0; -} - - -/* This function creates a new context for elliptic curve operations. - Either KEYPARAM or CURVENAME must be given. If both are given and - KEYPARAM has no curve parameter CURVENAME is used to add missing - parameters. On success 0 is returned and the new context stored at - R_CTX. On error NULL is stored at R_CTX and an error code is - returned. The context needs to be released using - gcry_ctx_release. */ -gpg_err_code_t -_gcry_mpi_ec_new (gcry_ctx_t *r_ctx, - gcry_sexp_t keyparam, const char *curvename) -{ - gpg_err_code_t errc; - gcry_ctx_t ctx = NULL; - gcry_mpi_t p = NULL; - gcry_mpi_t a = NULL; - gcry_mpi_t b = NULL; - gcry_mpi_point_t G = NULL; - gcry_mpi_t n = NULL; - gcry_mpi_point_t Q = NULL; - gcry_mpi_t d = NULL; - gcry_sexp_t l1; - - *r_ctx = NULL; - - if (keyparam) - { - errc = mpi_from_keyparam (&p, keyparam, "p"); - if (errc) - goto leave; - errc = mpi_from_keyparam (&a, keyparam, "a"); - if (errc) - goto leave; - errc = mpi_from_keyparam (&b, keyparam, "b"); - if (errc) - goto leave; - errc = point_from_keyparam (&G, keyparam, "g"); - if (errc) - goto leave; - errc = mpi_from_keyparam (&n, keyparam, "n"); - if (errc) - goto leave; - errc = point_from_keyparam (&Q, keyparam, "q"); - if (errc) - goto leave; - errc = mpi_from_keyparam (&d, keyparam, "d"); - if (errc) - goto leave; - } - - - /* Check whether a curve parameter is available and use that to fill - in missing values. If no curve parameter is available try an - optional provided curvename. If only the curvename has been - given use that one. */ - if (keyparam) - l1 = gcry_sexp_find_token (keyparam, "curve", 5); - else - l1 = NULL; - if (l1 || curvename) - { - char *name; - elliptic_curve_t *E; - - if (l1) - { - name = _gcry_sexp_nth_string (l1, 1); - gcry_sexp_release (l1); - if (!name) - { - errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */ - goto leave; - } - } - else - name = NULL; - - E = gcry_calloc (1, sizeof *E); - if (!E) - { - errc = gpg_err_code_from_syserror (); - gcry_free (name); - goto leave; - } - - errc = fill_in_curve (0, name? name : curvename, E, NULL); - gcry_free (name); - if (errc) - { - gcry_free (E); - goto leave; - } - - if (!p) - { - p = E->p; - E->p = NULL; - } - if (!a) - { - a = E->a; - E->a = NULL; - } - if (!b) - { - b = E->b; - E->b = NULL; - } - if (!G) - { - G = gcry_mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z); - E->G.x = NULL; - E->G.y = NULL; - E->G.z = NULL; - } - if (!n) - { - n = E->n; - E->n = NULL; - } - curve_free (E); - gcry_free (E); - } - - errc = _gcry_mpi_ec_p_new (&ctx, p, a); - if (!errc) - { - mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); - - if (b) - { - ec->b = b; - b = NULL; - } - if (G) - { - ec->G = G; - G = NULL; - } - if (n) - { - ec->n = n; - n = NULL; - } - if (Q) - { - ec->Q = Q; - Q = NULL; - } - if (d) - { - ec->d = d; - d = NULL; - } - - *r_ctx = ctx; - } - - leave: - mpi_free (p); - mpi_free (a); - mpi_free (b); - gcry_mpi_point_release (G); - mpi_free (n); - gcry_mpi_point_release (Q); - mpi_free (d); - return errc; -} - - /* This is the wroker function for gcry_pubkey_get_sexp for ECC algorithms. Note that the caller has already stored NULL at R_SEXP. */ @@ -2264,7 +1375,7 @@ pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = run_selftests, ecc_generate_ext, compute_keygrip, - ecc_get_param, - ecc_get_curve, - ecc_get_param_sexp + _gcry_ecc_get_param, + _gcry_ecc_get_curve, + _gcry_ecc_get_param_sexp }; diff --git a/configure.ac b/configure.ac index f20d0a13..b54b4d61 100644 --- a/configure.ac +++ b/configure.ac @@ -1452,7 +1452,8 @@ fi LIST_MEMBER(ecc, $enabled_pubkey_ciphers) if test "$found" = "1" ; then - GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS ecc.lo" + GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS \ + ecc.lo ecc-curves.lo ecc-misc.lo" AC_DEFINE(USE_ECC, 1, [Defined if this module should be included]) fi |