GRUB-1.98 changes
[grub2/jjazz.git] / lib / libgcrypt / cipher / ecc.c
blobfcbd8e3a9d6d7ee695f0361fef3b2b17aaa33241
1 /* ecc.c - Elliptic Curve Cryptography
2 Copyright (C) 2007, 2008 Free Software Foundation, Inc.
4 This file is part of Libgcrypt.
6 Libgcrypt is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of
9 the License, or (at your option) any later version.
11 Libgcrypt is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19 USA. */
21 /* This code is originally based on the Patch 0.1.6 for the gnupg
22 1.4.x branch as retrieved on 2007-03-21 from
23 http://www.calcurco.cat/eccGnuPG/src/gnupg-1.4.6-ecc0.2.0beta1.diff.bz2
24 The original authors are:
25 Written by
26 Sergi Blanch i Torne <d4372211 at alumnes.eup.udl.es>,
27 Ramiro Moreno Chiral <ramiro at eup.udl.es>
28 Maintainers
29 Sergi Blanch i Torne
30 Ramiro Moreno Chiral
31 Mikael Mylnikov (mmr)
32 For use in Libgcrypt the code has been heavily modified and cleaned
33 up. In fact there is not much left of the orginally code except for
34 some variable names and the text book implementaion of the sign and
35 verification algorithms. The arithmetic functions have entirely
36 been rewritten and moved to mpi/ec.c. */
39 /* TODO:
41 - If we support point compression we need to decide how to compute
42 the keygrip - it should not change due to compression.
44 - In mpi/ec.c we use mpi_powm for x^2 mod p: Either implement a
45 special case in mpi_powm or check whether mpi_mulm is faster.
47 - Decide whether we should hide the mpi_point_t definition.
49 - Support more than just ECDSA.
53 #include <config.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
58 #include "g10lib.h"
59 #include "mpi.h"
60 #include "cipher.h"
63 /* Definition of a curve. */
64 typedef struct
66 gcry_mpi_t p; /* Prime specifying the field GF(p). */
67 gcry_mpi_t a; /* First coefficient of the Weierstrass equation. */
68 gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. */
69 mpi_point_t G; /* Base point (generator). */
70 gcry_mpi_t n; /* Order of G. */
71 } elliptic_curve_t;
74 typedef struct
76 elliptic_curve_t E;
77 mpi_point_t Q; /* Q = [d]G */
78 } ECC_public_key;
80 typedef struct
82 elliptic_curve_t E;
83 mpi_point_t Q;
84 gcry_mpi_t d;
85 } ECC_secret_key;
88 /* This tables defines aliases for curve names. */
89 static const struct
91 const char *name; /* Our name. */
92 const char *other; /* Other name. */
93 } curve_aliases[] =
95 { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID */
96 { "NIST P-192", "prime192v1" }, /* X9.62 name. */
97 { "NIST P-192", "secp192r1" }, /* SECP name. */
99 { "NIST P-224", "secp224r1" },
100 { "NIST P-224", "1.3.132.0.33" }, /* SECP OID. */
102 { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1. */
103 { "NIST P-256", "prime256v1" },
104 { "NIST P-256", "secp256r1" },
106 { "NIST P-384", "secp384r1" },
107 { "NIST P-384", "1.3.132.0.34" },
109 { "NIST P-521", "secp521r1" },
110 { "NIST P-521", "1.3.132.0.35" },
112 { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" },
113 { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" },
114 { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" },
115 { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" },
116 { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" },
117 { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"},
118 { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"},
120 { NULL, NULL}
125 /* This static table defines all available curves. */
126 static const struct
128 const char *desc; /* Description of the curve. */
129 unsigned int nbits; /* Number of bits. */
130 unsigned int fips:1; /* True if this is a FIPS140-2 approved curve. */
131 const char *p; /* Order of the prime field. */
132 const char *a, *b; /* The coefficients. */
133 const char *n; /* The order of the base point. */
134 const char *g_x, *g_y; /* Base point. */
135 } domain_parms[] =
138 "NIST P-192", 192, 1,
139 "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
140 "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
141 "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
142 "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
144 "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
145 "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
148 "NIST P-224", 224, 1,
149 "0xffffffffffffffffffffffffffffffff000000000000000000000001",
150 "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
151 "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
152 "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
154 "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
155 "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
158 "NIST P-256", 256, 1,
159 "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
160 "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
161 "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
162 "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
164 "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
165 "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
168 "NIST P-384", 384, 1,
169 "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
170 "ffffffff0000000000000000ffffffff",
171 "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
172 "ffffffff0000000000000000fffffffc",
173 "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
174 "c656398d8a2ed19d2a85c8edd3ec2aef",
175 "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
176 "581a0db248b0a77aecec196accc52973",
178 "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
179 "5502f25dbf55296c3a545e3872760ab7",
180 "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
181 "0a60b1ce1d7e819d7a431d7c90ea0e5f"
184 "NIST P-521", 521, 1,
185 "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
186 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
187 "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
188 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
189 "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
190 "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
191 "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
192 "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
194 "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
195 "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
196 "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
197 "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
200 { "brainpoolP160r1", 160, 0,
201 "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
202 "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
203 "0x1e589a8595423412134faa2dbdec95c8d8675e58",
204 "0xe95e4a5f737059dc60df5991d45029409e60fc09",
205 "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
206 "0x1667cb477a1a8ec338f94741669c976316da6321"
209 { "brainpoolP192r1", 192, 0,
210 "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
211 "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
212 "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
213 "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
214 "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
215 "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
218 { "brainpoolP224r1", 224, 0,
219 "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
220 "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
221 "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
222 "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
223 "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
224 "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
227 { "brainpoolP256r1", 256, 0,
228 "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
229 "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
230 "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
231 "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
232 "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
233 "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
236 { "brainpoolP320r1", 320, 0,
237 "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
238 "fcd412b1f1b32e27",
239 "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
240 "92f375a97d860eb4",
241 "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981"
242 "6f5eb4ac8fb1f1a6",
243 "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9"
244 "8691555b44c59311",
245 "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
246 "10af8d0d39e20611",
247 "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
248 "d35245d1692e8ee1"
251 { "brainpoolP384r1", 384, 0,
252 "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
253 "acd3a729901d1a71874700133107ec53",
254 "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
255 "8aa5814a503ad4eb04a8c7dd22ce2826",
256 "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5"
257 "7cb4390295dbc9943ab78696fa504c11",
258 "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7"
259 "cf3ab6af6b7fc3103b883202e9046565",
260 "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
261 "e826e03436d646aaef87b2e247d4af1e",
262 "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
263 "0e4646217791811142820341263c5315"
266 { "brainpoolP512r1", 512, 0,
267 "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
268 "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
269 "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
270 "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca",
271 "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7"
272 "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723",
273 "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870"
274 "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
275 "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
276 "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
277 "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
278 "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
281 { NULL, 0, 0, NULL, NULL, NULL, NULL }
285 /* Registered progress function and its callback value. */
286 static void (*progress_cb) (void *, const char*, int, int, int);
287 static void *progress_cb_data;
290 #define point_init(a) _gcry_mpi_ec_point_init ((a))
291 #define point_free(a) _gcry_mpi_ec_point_free ((a))
295 /* Local prototypes. */
296 static gcry_mpi_t gen_k (gcry_mpi_t p, int security_level);
297 static void test_keys (ECC_secret_key * sk, unsigned int nbits);
298 static int check_secret_key (ECC_secret_key * sk);
299 static gpg_err_code_t sign (gcry_mpi_t input, ECC_secret_key *skey,
300 gcry_mpi_t r, gcry_mpi_t s);
301 static gpg_err_code_t verify (gcry_mpi_t input, ECC_public_key *pkey,
302 gcry_mpi_t r, gcry_mpi_t s);
305 static gcry_mpi_t gen_y_2 (gcry_mpi_t x, elliptic_curve_t * base);
310 void
311 _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
312 int, int, int),
313 void *cb_data)
315 progress_cb = cb;
316 progress_cb_data = cb_data;
319 /* static void */
320 /* progress (int c) */
321 /* { */
322 /* if (progress_cb) */
323 /* progress_cb (progress_cb_data, "pk_ecc", c, 0, 0); */
324 /* } */
329 /* Set the value from S into D. */
330 static void
331 point_set (mpi_point_t *d, mpi_point_t *s)
333 mpi_set (d->x, s->x);
334 mpi_set (d->y, s->y);
335 mpi_set (d->z, s->z);
340 * Release a curve object.
342 static void
343 curve_free (elliptic_curve_t *E)
345 mpi_free (E->p); E->p = NULL;
346 mpi_free (E->a); E->a = NULL;
347 mpi_free (E->b); E->b = NULL;
348 point_free (&E->G);
349 mpi_free (E->n); E->n = NULL;
354 * Return a copy of a curve object.
356 static elliptic_curve_t
357 curve_copy (elliptic_curve_t E)
359 elliptic_curve_t R;
361 R.p = mpi_copy (E.p);
362 R.a = mpi_copy (E.a);
363 R.b = mpi_copy (E.b);
364 point_init (&R.G);
365 point_set (&R.G, &E.G);
366 R.n = mpi_copy (E.n);
368 return R;
373 /* Helper to scan a hex string. */
374 static gcry_mpi_t
375 scanval (const char *string)
377 gpg_error_t err;
378 gcry_mpi_t val;
380 err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
381 if (err)
382 log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err));
383 return val;
390 /****************
391 * Solve the right side of the equation that defines a curve.
393 static gcry_mpi_t
394 gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base)
396 gcry_mpi_t three, x_3, axb, y;
398 three = mpi_alloc_set_ui (3);
399 x_3 = mpi_new (0);
400 axb = mpi_new (0);
401 y = mpi_new (0);
403 mpi_powm (x_3, x, three, base->p);
404 mpi_mulm (axb, base->a, x, base->p);
405 mpi_addm (axb, axb, base->b, base->p);
406 mpi_addm (y, x_3, axb, base->p);
408 mpi_free (x_3);
409 mpi_free (axb);
410 mpi_free (three);
411 return y; /* The quadratic value of the coordinate if it exist. */
418 /* Generate a random secret scalar k with an order of p
420 At the beginning this was identical to the code is in elgamal.c.
421 Later imporved by mmr. Further simplified by wk. */
422 static gcry_mpi_t
423 gen_k (gcry_mpi_t p, int security_level)
425 gcry_mpi_t k;
426 unsigned int nbits;
428 nbits = mpi_get_nbits (p);
429 k = mpi_snew (nbits);
430 if (DBG_CIPHER)
431 log_debug ("choosing a random k of %u bits\n", nbits);
433 gcry_mpi_randomize (k, nbits, security_level);
435 mpi_mod (k, k, p); /* k = k mod p */
437 return k;
440 /****************
441 * Generate the crypto system setup.
442 * As of now the fix NIST recommended values are used.
443 * The subgroup generator point is in another function: gen_big_point.
445 static gpg_err_code_t
446 generate_curve (unsigned int nbits, const char *name,
447 elliptic_curve_t *curve, unsigned int *r_nbits)
449 int idx, aliasno;
451 if (name)
453 /* First check nor native curves. */
454 for (idx = 0; domain_parms[idx].desc; idx++)
455 if (!strcmp (name, domain_parms[idx].desc))
456 break;
457 /* If not found consult the alias table. */
458 if (!domain_parms[idx].desc)
460 for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
461 if (!strcmp (name, curve_aliases[aliasno].other))
462 break;
463 if (curve_aliases[aliasno].name)
465 for (idx = 0; domain_parms[idx].desc; idx++)
466 if (!strcmp (curve_aliases[aliasno].name,
467 domain_parms[idx].desc))
468 break;
472 else
474 for (idx = 0; domain_parms[idx].desc; idx++)
475 if (nbits == domain_parms[idx].nbits)
476 break;
478 if (!domain_parms[idx].desc)
479 return GPG_ERR_INV_VALUE;
481 /* In fips mode we only support NIST curves. Note that it is
482 possible to bypass this check by specifying the curve parameters
483 directly. */
484 if (fips_mode () && !domain_parms[idx].fips )
485 return GPG_ERR_NOT_SUPPORTED;
488 *r_nbits = domain_parms[idx].nbits;
489 curve->p = scanval (domain_parms[idx].p);
490 curve->a = scanval (domain_parms[idx].a);
491 curve->b = scanval (domain_parms[idx].b);
492 curve->n = scanval (domain_parms[idx].n);
493 curve->G.x = scanval (domain_parms[idx].g_x);
494 curve->G.y = scanval (domain_parms[idx].g_y);
495 curve->G.z = mpi_alloc_set_ui (1);
497 return 0;
502 * First obtain the setup. Over the finite field randomize an scalar
503 * secret value, and calculate the public point.
505 static gpg_err_code_t
506 generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
507 gcry_mpi_t g_x, gcry_mpi_t g_y,
508 gcry_mpi_t q_x, gcry_mpi_t q_y)
510 gpg_err_code_t err;
511 elliptic_curve_t E;
512 gcry_mpi_t d;
513 mpi_point_t Q;
514 mpi_ec_t ctx;
516 err = generate_curve (nbits, name, &E, &nbits);
517 if (err)
518 return err;
520 if (DBG_CIPHER)
522 log_mpidump ("ecc generation p", E.p);
523 log_mpidump ("ecc generation a", E.a);
524 log_mpidump ("ecc generation b", E.b);
525 log_mpidump ("ecc generation n", E.n);
526 log_mpidump ("ecc generation Gx", E.G.x);
527 log_mpidump ("ecc generation Gy", E.G.y);
528 log_mpidump ("ecc generation Gz", E.G.z);
531 if (DBG_CIPHER)
532 log_debug ("choosing a random x of size %u\n", nbits);
533 d = gen_k (E.n, GCRY_VERY_STRONG_RANDOM);
535 /* Compute Q. */
536 point_init (&Q);
537 ctx = _gcry_mpi_ec_init (E.p, E.a);
538 _gcry_mpi_ec_mul_point (&Q, d, &E.G, ctx);
540 /* Copy the stuff to the key structures. */
541 sk->E.p = mpi_copy (E.p);
542 sk->E.a = mpi_copy (E.a);
543 sk->E.b = mpi_copy (E.b);
544 point_init (&sk->E.G);
545 point_set (&sk->E.G, &E.G);
546 sk->E.n = mpi_copy (E.n);
547 point_init (&sk->Q);
548 point_set (&sk->Q, &Q);
549 sk->d = mpi_copy (d);
550 /* We also return copies of G and Q in affine coordinates if
551 requested. */
552 if (g_x && g_y)
554 if (_gcry_mpi_ec_get_affine (g_x, g_y, &sk->E.G, ctx))
555 log_fatal ("ecc generate: Failed to get affine coordinates\n");
557 if (q_x && q_y)
559 if (_gcry_mpi_ec_get_affine (q_x, q_y, &sk->Q, ctx))
560 log_fatal ("ecc generate: Failed to get affine coordinates\n");
562 _gcry_mpi_ec_free (ctx);
564 point_free (&Q);
565 mpi_free (d);
566 curve_free (&E);
568 /* Now we can test our keys (this should never fail!). */
569 test_keys (sk, nbits - 64);
571 return 0;
575 /****************
576 * To verify correct skey it use a random information.
577 * First, encrypt and decrypt this dummy value,
578 * test if the information is recuperated.
579 * Second, test with the sign and verify functions.
581 static void
582 test_keys (ECC_secret_key *sk, unsigned int nbits)
584 ECC_public_key pk;
585 gcry_mpi_t test = mpi_new (nbits);
586 mpi_point_t R_;
587 gcry_mpi_t c = mpi_new (nbits);
588 gcry_mpi_t out = mpi_new (nbits);
589 gcry_mpi_t r = mpi_new (nbits);
590 gcry_mpi_t s = mpi_new (nbits);
592 if (DBG_CIPHER)
593 log_debug ("Testing key.\n");
595 point_init (&R_);
597 pk.E = curve_copy (sk->E);
598 point_init (&pk.Q);
599 point_set (&pk.Q, &sk->Q);
601 gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
603 if (sign (test, sk, r, s) )
604 log_fatal ("ECDSA operation: sign failed\n");
606 if (verify (test, &pk, r, s))
608 log_fatal ("ECDSA operation: sign, verify failed\n");
611 if (DBG_CIPHER)
612 log_debug ("ECDSA operation: sign, verify ok.\n");
614 point_free (&pk.Q);
615 curve_free (&pk.E);
617 point_free (&R_);
618 mpi_free (s);
619 mpi_free (r);
620 mpi_free (out);
621 mpi_free (c);
622 mpi_free (test);
625 /****************
626 * To check the validity of the value, recalculate the correspondence
627 * between the public value and the secret one.
629 static int
630 check_secret_key (ECC_secret_key * sk)
632 mpi_point_t Q;
633 gcry_mpi_t y_2, y2 = mpi_alloc (0);
634 mpi_ec_t ctx;
636 /* ?primarity test of 'p' */
637 /* (...) //!! */
638 /* G in E(F_p) */
639 y_2 = gen_y_2 (sk->E.G.x, &sk->E); /* y^2=x^3+a*x+b */
640 mpi_mulm (y2, sk->E.G.y, sk->E.G.y, sk->E.p); /* y^2=y*y */
641 if (mpi_cmp (y_2, y2))
643 if (DBG_CIPHER)
644 log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n");
645 return (1);
647 /* G != PaI */
648 if (!mpi_cmp_ui (sk->E.G.z, 0))
650 if (DBG_CIPHER)
651 log_debug ("Bad check: 'G' cannot be Point at Infinity!\n");
652 return (1);
655 point_init (&Q);
656 ctx = _gcry_mpi_ec_init (sk->E.p, sk->E.a);
657 _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx);
658 if (mpi_cmp_ui (Q.z, 0))
660 if (DBG_CIPHER)
661 log_debug ("check_secret_key: E is not a curve of order n\n");
662 point_free (&Q);
663 _gcry_mpi_ec_free (ctx);
664 return 1;
666 /* pubkey cannot be PaI */
667 if (!mpi_cmp_ui (sk->Q.z, 0))
669 if (DBG_CIPHER)
670 log_debug ("Bad check: Q can not be a Point at Infinity!\n");
671 _gcry_mpi_ec_free (ctx);
672 return (1);
674 /* pubkey = [d]G over E */
675 _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx);
676 if ((Q.x == sk->Q.x) && (Q.y == sk->Q.y) && (Q.z == sk->Q.z))
678 if (DBG_CIPHER)
679 log_debug
680 ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
681 _gcry_mpi_ec_free (ctx);
682 return (1);
684 _gcry_mpi_ec_free (ctx);
685 point_free (&Q);
686 return 0;
691 * Return the signature struct (r,s) from the message hash. The caller
692 * must have allocated R and S.
694 static gpg_err_code_t
695 sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s)
697 gpg_err_code_t err = 0;
698 gcry_mpi_t k, dr, sum, k_1, x;
699 mpi_point_t I;
700 mpi_ec_t ctx;
702 k = NULL;
703 dr = mpi_alloc (0);
704 sum = mpi_alloc (0);
705 k_1 = mpi_alloc (0);
706 x = mpi_alloc (0);
707 point_init (&I);
709 mpi_set_ui (s, 0);
710 mpi_set_ui (r, 0);
712 ctx = _gcry_mpi_ec_init (skey->E.p, skey->E.a);
714 while (!mpi_cmp_ui (s, 0)) /* s == 0 */
716 while (!mpi_cmp_ui (r, 0)) /* r == 0 */
718 /* Note, that we are guaranteed to enter this loop at least
719 once because r has been intialized to 0. We can't use a
720 do_while because we want to keep the value of R even if S
721 has to be recomputed. */
722 mpi_free (k);
723 k = gen_k (skey->E.n, GCRY_STRONG_RANDOM);
724 _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx);
725 if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx))
727 if (DBG_CIPHER)
728 log_debug ("ecc sign: Failed to get affine coordinates\n");
729 err = GPG_ERR_BAD_SIGNATURE;
730 goto leave;
732 mpi_mod (r, x, skey->E.n); /* r = x mod n */
734 mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n */
735 mpi_addm (sum, input, dr, skey->E.n); /* sum = hash + (d*r) mod n */
736 mpi_invm (k_1, k, skey->E.n); /* k_1 = k^(-1) mod n */
737 mpi_mulm (s, k_1, sum, skey->E.n); /* s = k^(-1)*(hash+(d*r)) mod n */
740 leave:
741 _gcry_mpi_ec_free (ctx);
742 point_free (&I);
743 mpi_free (x);
744 mpi_free (k_1);
745 mpi_free (sum);
746 mpi_free (dr);
747 mpi_free (k);
749 return err;
753 * Check if R and S verifies INPUT.
755 static gpg_err_code_t
756 verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s)
758 gpg_err_code_t err = 0;
759 gcry_mpi_t h, h1, h2, x, y;
760 mpi_point_t Q, Q1, Q2;
761 mpi_ec_t ctx;
763 if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) )
764 return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < r < n failed. */
765 if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, pkey->E.n) < 0) )
766 return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < s < n failed. */
768 h = mpi_alloc (0);
769 h1 = mpi_alloc (0);
770 h2 = mpi_alloc (0);
771 x = mpi_alloc (0);
772 y = mpi_alloc (0);
773 point_init (&Q);
774 point_init (&Q1);
775 point_init (&Q2);
777 ctx = _gcry_mpi_ec_init (pkey->E.p, pkey->E.a);
779 /* h = s^(-1) (mod n) */
780 mpi_invm (h, s, pkey->E.n);
781 /* log_mpidump (" h", h); */
782 /* h1 = hash * s^(-1) (mod n) */
783 mpi_mulm (h1, input, h, pkey->E.n);
784 /* log_mpidump (" h1", h1); */
785 /* Q1 = [ hash * s^(-1) ]G */
786 _gcry_mpi_ec_mul_point (&Q1, h1, &pkey->E.G, ctx);
787 /* log_mpidump ("Q1.x", Q1.x); */
788 /* log_mpidump ("Q1.y", Q1.y); */
789 /* log_mpidump ("Q1.z", Q1.z); */
790 /* h2 = r * s^(-1) (mod n) */
791 mpi_mulm (h2, r, h, pkey->E.n);
792 /* log_mpidump (" h2", h2); */
793 /* Q2 = [ r * s^(-1) ]Q */
794 _gcry_mpi_ec_mul_point (&Q2, h2, &pkey->Q, ctx);
795 /* log_mpidump ("Q2.x", Q2.x); */
796 /* log_mpidump ("Q2.y", Q2.y); */
797 /* log_mpidump ("Q2.z", Q2.z); */
798 /* Q = ([hash * s^(-1)]G) + ([r * s^(-1)]Q) */
799 _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ctx);
800 /* log_mpidump (" Q.x", Q.x); */
801 /* log_mpidump (" Q.y", Q.y); */
802 /* log_mpidump (" Q.z", Q.z); */
804 if (!mpi_cmp_ui (Q.z, 0))
806 if (DBG_CIPHER)
807 log_debug ("ecc verify: Rejected\n");
808 err = GPG_ERR_BAD_SIGNATURE;
809 goto leave;
811 if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx))
813 if (DBG_CIPHER)
814 log_debug ("ecc verify: Failed to get affine coordinates\n");
815 err = GPG_ERR_BAD_SIGNATURE;
816 goto leave;
818 mpi_mod (x, x, pkey->E.n); /* x = x mod E_n */
819 if (mpi_cmp (x, r)) /* x != r */
821 if (DBG_CIPHER)
823 log_mpidump (" x", x);
824 log_mpidump (" y", y);
825 log_mpidump (" r", r);
826 log_mpidump (" s", s);
827 log_debug ("ecc verify: Not verified\n");
829 err = GPG_ERR_BAD_SIGNATURE;
830 goto leave;
832 if (DBG_CIPHER)
833 log_debug ("ecc verify: Accepted\n");
835 leave:
836 _gcry_mpi_ec_free (ctx);
837 point_free (&Q2);
838 point_free (&Q1);
839 point_free (&Q);
840 mpi_free (y);
841 mpi_free (x);
842 mpi_free (h2);
843 mpi_free (h1);
844 mpi_free (h);
845 return err;
850 /*********************************************
851 ************** interface ******************
852 *********************************************/
853 static gcry_mpi_t
854 ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p)
856 gpg_error_t err;
857 int pbytes = (mpi_get_nbits (p)+7)/8;
858 size_t n;
859 unsigned char *buf, *ptr;
860 gcry_mpi_t result;
862 buf = gcry_xmalloc ( 1 + 2*pbytes );
863 *buf = 04; /* Uncompressed point. */
864 ptr = buf+1;
865 err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x);
866 if (err)
867 log_fatal ("mpi_print failed: %s\n", gpg_strerror (err));
868 if (n < pbytes)
870 memmove (ptr+(pbytes-n), ptr, n);
871 memset (ptr, 0, (pbytes-n));
873 ptr += pbytes;
874 err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y);
875 if (err)
876 log_fatal ("mpi_print failed: %s\n", gpg_strerror (err));
877 if (n < pbytes)
879 memmove (ptr+(pbytes-n), ptr, n);
880 memset (ptr, 0, (pbytes-n));
883 err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL);
884 if (err)
885 log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err));
886 gcry_free (buf);
888 mpi_free (x);
889 mpi_free (y);
891 return result;
894 /* RESULT must have been initialized and is set on success to the
895 point given by VALUE. */
896 static gcry_error_t
897 os2ec (mpi_point_t *result, gcry_mpi_t value)
899 gcry_error_t err;
900 size_t n;
901 unsigned char *buf;
902 gcry_mpi_t x, y;
904 n = (mpi_get_nbits (value)+7)/8;
905 buf = gcry_xmalloc (n);
906 err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, n, &n, value);
907 if (err)
909 gcry_free (buf);
910 return err;
912 if (n < 1)
914 gcry_free (buf);
915 return GPG_ERR_INV_OBJ;
917 if (*buf != 4)
919 gcry_free (buf);
920 return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression. */
922 if ( ((n-1)%2) )
924 gcry_free (buf);
925 return GPG_ERR_INV_OBJ;
927 n = (n-1)/2;
928 err = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL);
929 if (err)
931 gcry_free (buf);
932 return err;
934 err = gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL);
935 gcry_free (buf);
936 if (err)
938 mpi_free (x);
939 return err;
942 mpi_set (result->x, x);
943 mpi_set (result->y, y);
944 mpi_set_ui (result->z, 1);
946 mpi_free (x);
947 mpi_free (y);
949 return 0;
953 /* Extended version of ecc_generate. */
954 static gcry_err_code_t
955 ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
956 const gcry_sexp_t genparms,
957 gcry_mpi_t *skey, gcry_mpi_t **retfactors,
958 gcry_sexp_t *r_extrainfo)
960 gpg_err_code_t ec;
961 ECC_secret_key sk;
962 gcry_mpi_t g_x, g_y, q_x, q_y;
963 char *curve_name = NULL;
964 gcry_sexp_t l1;
966 (void)algo;
967 (void)evalue;
968 (void)r_extrainfo;
970 if (genparms)
972 /* Parse the optional "curve" parameter. */
973 l1 = gcry_sexp_find_token (genparms, "curve", 0);
974 if (l1)
976 curve_name = _gcry_sexp_nth_string (l1, 1);
977 gcry_sexp_release (l1);
978 if (!curve_name)
979 return GPG_ERR_INV_OBJ; /* No curve name or value too large. */
983 /* NBITS is required if no curve name has been given. */
984 if (!nbits && !curve_name)
985 return GPG_ERR_NO_OBJ; /* No NBITS parameter. */
987 g_x = mpi_new (0);
988 g_y = mpi_new (0);
989 q_x = mpi_new (0);
990 q_y = mpi_new (0);
991 ec = generate_key (&sk, nbits, curve_name, g_x, g_y, q_x, q_y);
992 gcry_free (curve_name);
993 if (ec)
994 return ec;
996 skey[0] = sk.E.p;
997 skey[1] = sk.E.a;
998 skey[2] = sk.E.b;
999 /* The function ec2os releases g_x and g_y. */
1000 skey[3] = ec2os (g_x, g_y, sk.E.p);
1001 skey[4] = sk.E.n;
1002 /* The function ec2os releases g_x and g_y. */
1003 skey[5] = ec2os (q_x, q_y, sk.E.p);
1004 skey[6] = sk.d;
1006 point_free (&sk.E.G);
1007 point_free (&sk.Q);
1009 /* Make an empty list of factors. */
1010 *retfactors = gcry_calloc ( 1, sizeof **retfactors );
1011 if (!*retfactors)
1012 return gpg_err_code_from_syserror ();
1014 return 0;
1018 static gcry_err_code_t
1019 ecc_generate (int algo, unsigned int nbits, unsigned long evalue,
1020 gcry_mpi_t *skey, gcry_mpi_t **retfactors)
1022 (void)evalue;
1023 return ecc_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL);
1027 /* Return the parameters of the curve NAME. */
1028 static gcry_err_code_t
1029 ecc_get_param (const char *name, gcry_mpi_t *pkey)
1031 gpg_err_code_t err;
1032 unsigned int nbits;
1033 elliptic_curve_t E;
1034 mpi_ec_t ctx;
1035 gcry_mpi_t g_x, g_y;
1037 err = generate_curve (0, name, &E, &nbits);
1038 if (err)
1039 return err;
1041 g_x = mpi_new (0);
1042 g_y = mpi_new (0);
1043 ctx = _gcry_mpi_ec_init (E.p, E.a);
1044 if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
1045 log_fatal ("ecc get param: Failed to get affine coordinates\n");
1046 _gcry_mpi_ec_free (ctx);
1047 point_free (&E.G);
1049 pkey[0] = E.p;
1050 pkey[1] = E.a;
1051 pkey[2] = E.b;
1052 pkey[3] = ec2os (g_x, g_y, E.p);
1053 pkey[4] = E.n;
1054 pkey[5] = NULL;
1056 return 0;
1060 static gcry_err_code_t
1061 ecc_check_secret_key (int algo, gcry_mpi_t *skey)
1063 gpg_err_code_t err;
1064 ECC_secret_key sk;
1066 (void)algo;
1068 if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5]
1069 || !skey[6] || !skey[7] || !skey[8] || !skey[9] || !skey[10])
1070 return GPG_ERR_BAD_MPI;
1072 sk.E.p = skey[0];
1073 sk.E.a = skey[1];
1074 sk.E.b = skey[2];
1075 point_init (&sk.E.G);
1076 err = os2ec (&sk.E.G, skey[3]);
1077 if (err)
1079 point_free (&sk.E.G);
1080 return err;
1082 sk.E.n = skey[4];
1083 point_init (&sk.Q);
1084 err = os2ec (&sk.Q, skey[5]);
1085 if (err)
1087 point_free (&sk.E.G);
1088 point_free (&sk.Q);
1089 return err;
1092 sk.d = skey[6];
1094 if (check_secret_key (&sk))
1096 point_free (&sk.E.G);
1097 point_free (&sk.Q);
1098 return GPG_ERR_BAD_SECKEY;
1100 point_free (&sk.E.G);
1101 point_free (&sk.Q);
1102 return 0;
1106 static gcry_err_code_t
1107 ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
1109 gpg_err_code_t err;
1110 ECC_secret_key sk;
1112 (void)algo;
1114 if (!data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4]
1115 || !skey[5] || !skey[6] )
1116 return GPG_ERR_BAD_MPI;
1118 sk.E.p = skey[0];
1119 sk.E.a = skey[1];
1120 sk.E.b = skey[2];
1121 point_init (&sk.E.G);
1122 err = os2ec (&sk.E.G, skey[3]);
1123 if (err)
1125 point_free (&sk.E.G);
1126 return err;
1128 sk.E.n = skey[4];
1129 point_init (&sk.Q);
1130 err = os2ec (&sk.Q, skey[5]);
1131 if (err)
1133 point_free (&sk.E.G);
1134 point_free (&sk.Q);
1135 return err;
1137 sk.d = skey[6];
1139 resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
1140 resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
1141 err = sign (data, &sk, resarr[0], resarr[1]);
1142 if (err)
1144 mpi_free (resarr[0]);
1145 mpi_free (resarr[1]);
1146 resarr[0] = NULL; /* Mark array as released. */
1148 point_free (&sk.E.G);
1149 point_free (&sk.Q);
1150 return err;
1153 static gcry_err_code_t
1154 ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
1155 int (*cmp)(void *, gcry_mpi_t), void *opaquev)
1157 gpg_err_code_t err;
1158 ECC_public_key pk;
1160 (void)algo;
1161 (void)cmp;
1162 (void)opaquev;
1164 if (!data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] || !pkey[2]
1165 || !pkey[3] || !pkey[4] || !pkey[5] )
1166 return GPG_ERR_BAD_MPI;
1168 pk.E.p = pkey[0];
1169 pk.E.a = pkey[1];
1170 pk.E.b = pkey[2];
1171 point_init (&pk.E.G);
1172 err = os2ec (&pk.E.G, pkey[3]);
1173 if (err)
1175 point_free (&pk.E.G);
1176 return err;
1178 pk.E.n = pkey[4];
1179 point_init (&pk.Q);
1180 err = os2ec (&pk.Q, pkey[5]);
1181 if (err)
1183 point_free (&pk.E.G);
1184 point_free (&pk.Q);
1185 return err;
1188 err = verify (hash, &pk, data[0], data[1]);
1190 point_free (&pk.E.G);
1191 point_free (&pk.Q);
1192 return err;
1197 static unsigned int
1198 ecc_get_nbits (int algo, gcry_mpi_t *pkey)
1200 (void)algo;
1202 return mpi_get_nbits (pkey[0]);
1207 /* See rsa.c for a description of this function. */
1208 static gpg_err_code_t
1209 compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
1211 static const char names[] = "pabgnq";
1212 gpg_err_code_t ec = 0;
1213 gcry_sexp_t l1;
1214 gcry_mpi_t values[6];
1215 int idx;
1217 /* Clear the values for easier error cleanup. */
1218 for (idx=0; idx < 6; idx++)
1219 values[idx] = NULL;
1221 /* Fill values with all available parameters. */
1222 for (idx=0; idx < 6; idx++)
1224 l1 = gcry_sexp_find_token (keyparam, names+idx, 1);
1225 if (l1)
1227 values[idx] = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
1228 gcry_sexp_release (l1);
1229 if (!values[idx])
1231 ec = GPG_ERR_INV_OBJ;
1232 goto leave;
1237 /* Check whether a curve parameter is available and use that to fill
1238 in missing values. */
1239 l1 = gcry_sexp_find_token (keyparam, "curve", 5);
1240 if (l1)
1242 char *curve;
1243 gcry_mpi_t tmpvalues[6];
1245 for (idx = 0; idx < 6; idx++)
1246 tmpvalues[idx] = NULL;
1248 curve = _gcry_sexp_nth_string (l1, 1);
1249 if (!curve)
1251 ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
1252 goto leave;
1254 ec = ecc_get_param (curve, tmpvalues);
1255 gcry_free (curve);
1256 if (ec)
1257 goto leave;
1259 for (idx = 0; idx < 6; idx++)
1261 if (!values[idx])
1262 values[idx] = tmpvalues[idx];
1263 else
1264 mpi_free (tmpvalues[idx]);
1268 /* Check that all parameters are known and normalize all MPIs (that
1269 should not be required but we use an internal fucntion later and
1270 thus we better make 100% sure that they are normalized). */
1271 for (idx = 0; idx < 6; idx++)
1272 if (!values[idx])
1274 ec = GPG_ERR_NO_OBJ;
1275 goto leave;
1277 else
1278 _gcry_mpi_normalize (values[idx]);
1280 /* Hash them all. */
1281 for (idx = 0; idx < 6; idx++)
1283 char buf[30];
1284 unsigned char *rawmpi;
1285 unsigned int rawmpilen;
1287 rawmpi = _gcry_mpi_get_buffer (values[idx], &rawmpilen, NULL);
1288 if (!rawmpi)
1290 ec = gpg_err_code_from_syserror ();
1291 goto leave;
1293 snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], rawmpilen);
1294 gcry_md_write (md, buf, strlen (buf));
1295 gcry_md_write (md, rawmpi, rawmpilen);
1296 gcry_md_write (md, ")", 1);
1297 gcry_free (rawmpi);
1300 leave:
1301 for (idx = 0; idx < 6; idx++)
1302 _gcry_mpi_release (values[idx]);
1304 return ec;
1312 Self-test section.
1316 static gpg_err_code_t
1317 selftests_ecdsa (selftest_report_func_t report)
1319 const char *what;
1320 const char *errtxt;
1322 what = "low-level";
1323 errtxt = NULL; /*selftest ();*/
1324 if (errtxt)
1325 goto failed;
1327 /* FIXME: need more tests. */
1329 return 0; /* Succeeded. */
1331 failed:
1332 if (report)
1333 report ("pubkey", GCRY_PK_ECDSA, what, errtxt);
1334 return GPG_ERR_SELFTEST_FAILED;
1338 /* Run a full self-test for ALGO and return 0 on success. */
1339 static gpg_err_code_t
1340 run_selftests (int algo, int extended, selftest_report_func_t report)
1342 gpg_err_code_t ec;
1344 (void)extended;
1346 switch (algo)
1348 case GCRY_PK_ECDSA:
1349 ec = selftests_ecdsa (report);
1350 break;
1351 default:
1352 ec = GPG_ERR_PUBKEY_ALGO;
1353 break;
1356 return ec;
1362 static const char *ecdsa_names[] =
1364 "ecdsa",
1365 "ecc",
1366 NULL,
1369 gcry_pk_spec_t _gcry_pubkey_spec_ecdsa =
1371 "ECDSA", ecdsa_names,
1372 "pabgnq", "pabgnqd", "", "rs", "pabgnq",
1373 GCRY_PK_USAGE_SIGN,
1374 ecc_generate,
1375 ecc_check_secret_key,
1376 NULL,
1377 NULL,
1378 ecc_sign,
1379 ecc_verify,
1380 ecc_get_nbits
1383 pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa =
1385 run_selftests,
1386 ecc_generate_ext,
1387 compute_keygrip,
1388 ecc_get_param