A whole bunch of changes to eventually support
[libgcrypt.git] / cipher / ecc.c
1 /* ecc.c  -  Elliptic Curve Cryptography
2    Copyright (C) 2007, 2008 Free Software Foundation, Inc.
3
4    This file is part of Libgcrypt.
5   
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.
10   
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.
15   
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.  */
20
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.  */
37
38
39 /* TODO:
40
41   - If we support point compression we need to decide how to compute
42     the keygrip - it should not change due to compression.
43
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.
46
47   - Decide whether we should hide the mpi_point_t definition.
48
49   - Support more than just ECDSA.
50 */
51
52
53 #include <config.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <assert.h>
58
59 #include "g10lib.h"
60 #include "mpi.h"
61 #include "cipher.h"
62
63
64 /* Definition of a curve.  */
65 typedef struct
66 {
67   gcry_mpi_t p;   /* Prime specifying the field GF(p).  */
68   gcry_mpi_t a;   /* First coefficient of the Weierstrass equation.  */
69   gcry_mpi_t b;   /* Second coefficient of the Weierstrass equation.  */
70   mpi_point_t G;  /* Base point (generator).  */
71   gcry_mpi_t n;   /* Order of G.  */
72 } elliptic_curve_t; 
73
74
75 typedef struct
76 {
77   elliptic_curve_t E;
78   mpi_point_t Q;  /* Q = [d]G  */
79 } ECC_public_key;
80
81 typedef struct
82 {
83   elliptic_curve_t E;
84   mpi_point_t Q;
85   gcry_mpi_t d;
86 } ECC_secret_key;
87
88
89 /* This tables defines aliases for curve names.  */
90 static const struct
91 {
92   const char *name;  /* Our name.  */
93   const char *other; /* Other name. */
94 } curve_aliases[] = 
95   {
96     { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID  */
97     { "NIST P-192", "prime192v1" },          /* X9.62 name.  */
98     { "NIST P-192", "secp192r1"  },          /* SECP name.  */
99
100     { "NIST P-224", "secp224r1" },
101     { "NIST P-224", "1.3.132.0.33" },        /* SECP OID.  */
102
103     { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1.  */
104     { "NIST P-256", "prime256v1" },          
105     { "NIST P-256", "secp256r1"  },
106
107     { "NIST P-384", "secp384r1" },
108     { "NIST P-384", "1.3.132.0.34" },       
109
110     { "NIST P-521", "secp521r1" },
111     { "NIST P-521", "1.3.132.0.35" },
112
113     { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" },
114     { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" },
115     { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" },
116     { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" },
117     { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" },
118     { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"},
119     { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"},
120
121     { NULL, NULL}
122   };
123
124
125
126 /* This static table defines all available curves.  */
127 static const struct
128 {
129   const char *desc;           /* Description of the curve.  */
130   unsigned int nbits;         /* Number of bits.  */
131   unsigned int fips:1;        /* True if this is a FIPS140-2 approved curve. */
132   const char  *p;             /* Order of the prime field.  */
133   const char *a, *b;          /* The coefficients. */
134   const char *n;              /* The order of the base point.  */
135   const char *g_x, *g_y;      /* Base point.  */
136 } domain_parms[] =
137   {
138     {
139       "NIST P-192", 192, 1,
140       "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
141       "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
142       "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
143       "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
144
145       "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
146       "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
147     },
148     {
149       "NIST P-224", 224, 1,
150       "0xffffffffffffffffffffffffffffffff000000000000000000000001",
151       "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
152       "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
153       "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
154
155       "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
156       "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
157     },
158     {
159       "NIST P-256", 256, 1,
160       "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
161       "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
162       "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
163       "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
164
165       "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
166       "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
167     },
168     {
169       "NIST P-384", 384, 1,
170       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
171       "ffffffff0000000000000000ffffffff",
172       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
173       "ffffffff0000000000000000fffffffc",
174       "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
175       "c656398d8a2ed19d2a85c8edd3ec2aef",
176       "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
177       "581a0db248b0a77aecec196accc52973",
178
179       "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
180       "5502f25dbf55296c3a545e3872760ab7",
181       "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
182       "0a60b1ce1d7e819d7a431d7c90ea0e5f"
183     },
184     {
185       "NIST P-521", 521, 1,
186       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
187       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
188       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
189       "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
190       "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
191       "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
192       "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
193       "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
194
195       "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
196       "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
197       "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
198       "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
199     },
200
201     { "brainpoolP160r1", 160, 0, 
202       "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
203       "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
204       "0x1e589a8595423412134faa2dbdec95c8d8675e58",
205       "0xe95e4a5f737059dc60df5991d45029409e60fc09",
206       "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
207       "0x1667cb477a1a8ec338f94741669c976316da6321"
208     },
209
210     { "brainpoolP192r1", 192, 0, 
211       "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
212       "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
213       "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
214       "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
215       "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
216       "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
217     },
218
219     { "brainpoolP224r1", 224, 0,
220       "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
221       "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
222       "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
223       "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
224       "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
225       "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
226     },
227
228     { "brainpoolP256r1", 256, 0,
229       "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
230       "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
231       "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
232       "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
233       "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
234       "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
235     },
236
237     { "brainpoolP320r1", 320, 0,
238       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
239       "fcd412b1f1b32e27",
240       "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
241       "92f375a97d860eb4",
242       "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981"
243       "6f5eb4ac8fb1f1a6",
244       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9"
245       "8691555b44c59311",
246       "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
247       "10af8d0d39e20611",
248       "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
249       "d35245d1692e8ee1"
250     },
251
252     { "brainpoolP384r1", 384, 0,
253       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
254       "acd3a729901d1a71874700133107ec53",
255       "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
256       "8aa5814a503ad4eb04a8c7dd22ce2826",
257       "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5"
258       "7cb4390295dbc9943ab78696fa504c11",
259       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7"
260       "cf3ab6af6b7fc3103b883202e9046565",
261       "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
262       "e826e03436d646aaef87b2e247d4af1e",
263       "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
264       "0e4646217791811142820341263c5315"
265     },
266
267     { "brainpoolP512r1", 512, 0,
268       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
269       "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
270       "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
271       "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca",
272       "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7"
273       "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723",
274       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870"
275       "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
276       "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
277       "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
278       "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
279       "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
280     },
281
282     { NULL, 0, 0, NULL, NULL, NULL, NULL }
283   };
284
285
286 /* Registered progress function and its callback value. */
287 static void (*progress_cb) (void *, const char*, int, int, int);
288 static void *progress_cb_data;
289
290
291 #define point_init(a)  _gcry_mpi_ec_point_init ((a))
292 #define point_free(a)  _gcry_mpi_ec_point_free ((a))
293
294
295 \f
296 /* Local prototypes. */
297 static gcry_mpi_t gen_k (gcry_mpi_t p, int security_level);
298 static void test_keys (ECC_secret_key * sk, unsigned int nbits);
299 static int check_secret_key (ECC_secret_key * sk);
300 static gpg_err_code_t sign (gcry_mpi_t input, ECC_secret_key *skey,
301                             gcry_mpi_t r, gcry_mpi_t s);
302 static gpg_err_code_t verify (gcry_mpi_t input, ECC_public_key *pkey,
303                               gcry_mpi_t r, gcry_mpi_t s);
304
305
306 static gcry_mpi_t gen_y_2 (gcry_mpi_t x, elliptic_curve_t * base);
307
308
309
310 \f
311 void
312 _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
313                                             int, int, int),
314                                 void *cb_data)
315 {
316   progress_cb = cb;
317   progress_cb_data = cb_data;
318 }
319
320 /* static void */
321 /* progress (int c) */
322 /* { */
323 /*   if (progress_cb) */
324 /*     progress_cb (progress_cb_data, "pk_ecc", c, 0, 0); */
325 /* } */
326
327
328 \f
329
330 /* Set the value from S into D.  */
331 static void
332 point_set (mpi_point_t *d, mpi_point_t *s)
333 {
334   mpi_set (d->x, s->x);
335   mpi_set (d->y, s->y);
336   mpi_set (d->z, s->z);
337 }
338
339
340 /*
341  * Release a curve object.
342  */
343 static void
344 curve_free (elliptic_curve_t *E)
345 {
346   mpi_free (E->p); E->p = NULL;
347   mpi_free (E->a); E->a = NULL;
348   mpi_free (E->b);  E->b = NULL;
349   point_free (&E->G);
350   mpi_free (E->n);  E->n = NULL;
351 }
352
353
354 /*
355  * Return a copy of a curve object.
356  */
357 static elliptic_curve_t
358 curve_copy (elliptic_curve_t E)
359 {
360   elliptic_curve_t R;
361
362   R.p = mpi_copy (E.p);
363   R.a = mpi_copy (E.a);
364   R.b = mpi_copy (E.b);
365   point_init (&R.G);
366   point_set (&R.G, &E.G);
367   R.n = mpi_copy (E.n);
368
369   return R;
370 }
371
372
373
374 /* Helper to scan a hex string. */
375 static gcry_mpi_t
376 scanval (const char *string)
377 {
378   gpg_error_t err;
379   gcry_mpi_t val;
380
381   err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
382   if (err)
383     log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err));
384   return val;
385 }
386
387
388
389 \f
390
391 /****************
392  * Solve the right side of the equation that defines a curve.
393  */
394 static gcry_mpi_t
395 gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base)
396 {
397   gcry_mpi_t three, x_3, axb, y;
398
399   three = mpi_alloc_set_ui (3);
400   x_3 = mpi_new (0);
401   axb = mpi_new (0);
402   y   = mpi_new (0);
403
404   mpi_powm (x_3, x, three, base->p);  
405   mpi_mulm (axb, base->a, x, base->p); 
406   mpi_addm (axb, axb, base->b, base->p);     
407   mpi_addm (y, x_3, axb, base->p);    
408
409   mpi_free (x_3);
410   mpi_free (axb);
411   mpi_free (three);
412   return y; /* The quadratic value of the coordinate if it exist. */
413 }
414
415
416
417
418
419 /* Generate a random secret scalar k with an order of p
420
421    At the beginning this was identical to the code is in elgamal.c.
422    Later imporved by mmr.   Further simplified by wk.  */
423 static gcry_mpi_t
424 gen_k (gcry_mpi_t p, int security_level)
425 {
426   gcry_mpi_t k;
427   unsigned int nbits;
428
429   nbits = mpi_get_nbits (p);
430   k = mpi_snew (nbits);
431   if (DBG_CIPHER)
432     log_debug ("choosing a random k of %u bits\n", nbits);
433
434   gcry_mpi_randomize (k, nbits, security_level);
435
436   mpi_mod (k, k, p);  /*  k = k mod p  */
437
438   return k;
439 }
440
441 /****************
442  * Generate the crypto system setup.
443  * As of now the fix NIST recommended values are used.
444  * The subgroup generator point is in another function: gen_big_point.
445  */
446 static gpg_err_code_t
447 generate_curve (unsigned int nbits, const char *name, 
448                 elliptic_curve_t *curve, unsigned int *r_nbits)
449 {
450   int idx, aliasno;
451
452   if (name)
453     {
454       /* First check nor native curves.  */
455       for (idx = 0; domain_parms[idx].desc; idx++)
456         if (!strcmp (name, domain_parms[idx].desc))
457           break;
458       /* If not found consult the alias table.  */
459       if (!domain_parms[idx].desc)
460         {
461           for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
462             if (!strcmp (name, curve_aliases[aliasno].other))
463               break;
464           if (curve_aliases[aliasno].name)
465             {
466               for (idx = 0; domain_parms[idx].desc; idx++)
467                 if (!strcmp (curve_aliases[aliasno].name,
468                              domain_parms[idx].desc))
469                   break;
470             }
471         }
472     }
473   else
474     {
475       for (idx = 0; domain_parms[idx].desc; idx++)
476         if (nbits == domain_parms[idx].nbits)
477           break;
478     }
479   if (!domain_parms[idx].desc)
480     return GPG_ERR_INV_VALUE;
481
482   /* In fips mode we only support NIST curves.  Note that it is
483      possible to bypass this check by specifying the curve parameters
484      directly.  */
485   if (fips_mode () && !domain_parms[idx].fips )
486     return GPG_ERR_NOT_SUPPORTED; 
487   
488
489   *r_nbits = domain_parms[idx].nbits;
490   curve->p = scanval (domain_parms[idx].p);
491   curve->a = scanval (domain_parms[idx].a);
492   curve->b = scanval (domain_parms[idx].b);
493   curve->n = scanval (domain_parms[idx].n);
494   curve->G.x = scanval (domain_parms[idx].g_x);
495   curve->G.y = scanval (domain_parms[idx].g_y);
496   curve->G.z = mpi_alloc_set_ui (1);
497
498   return 0;
499 }
500
501
502 /*
503  * First obtain the setup.  Over the finite field randomize an scalar
504  * secret value, and calculate the public point.
505  */
506 static gpg_err_code_t
507 generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
508               gcry_mpi_t g_x, gcry_mpi_t g_y,
509               gcry_mpi_t q_x, gcry_mpi_t q_y)
510 {
511   gpg_err_code_t err;
512   elliptic_curve_t E;
513   gcry_mpi_t d;
514   mpi_point_t Q;
515   mpi_ec_t ctx;
516
517   err = generate_curve (nbits, name, &E, &nbits);
518   if (err)
519     return err;
520
521   if (DBG_CIPHER)
522     {
523       log_mpidump ("ecc generation   p", E.p);
524       log_mpidump ("ecc generation   a", E.a);
525       log_mpidump ("ecc generation   b", E.b);
526       log_mpidump ("ecc generation   n", E.n);
527       log_mpidump ("ecc generation  Gx", E.G.x);
528       log_mpidump ("ecc generation  Gy", E.G.y);
529       log_mpidump ("ecc generation  Gz", E.G.z);
530     }
531
532   if (DBG_CIPHER)
533     log_debug ("choosing a random x of size %u\n", nbits);
534   d = gen_k (E.n, GCRY_VERY_STRONG_RANDOM); 
535
536   /* Compute Q.  */
537   point_init (&Q);
538   ctx = _gcry_mpi_ec_init (E.p, E.a);
539   _gcry_mpi_ec_mul_point (&Q, d, &E.G, ctx);
540
541   /* Copy the stuff to the key structures. */
542   sk->E.p = mpi_copy (E.p);
543   sk->E.a = mpi_copy (E.a);
544   sk->E.b = mpi_copy (E.b);
545   point_init (&sk->E.G);
546   point_set (&sk->E.G, &E.G);
547   sk->E.n = mpi_copy (E.n);
548   point_init (&sk->Q);
549   point_set (&sk->Q, &Q);
550   sk->d    = mpi_copy (d);
551   /* We also return copies of G and Q in affine coordinates if
552      requested.  */
553   if (g_x && g_y)
554     {
555       if (_gcry_mpi_ec_get_affine (g_x, g_y, &sk->E.G, ctx))
556         log_fatal ("ecc generate: Failed to get affine coordinates\n");
557     }
558   if (q_x && q_y)
559     {
560       if (_gcry_mpi_ec_get_affine (q_x, q_y, &sk->Q, ctx))
561         log_fatal ("ecc generate: Failed to get affine coordinates\n");
562     }
563   _gcry_mpi_ec_free (ctx);
564
565   point_free (&Q);
566   mpi_free (d);
567   curve_free (&E);
568
569   /* Now we can test our keys (this should never fail!). */
570   test_keys (sk, nbits - 64);
571
572   return 0;
573 }
574
575
576 /****************
577  * To verify correct skey it use a random information.
578  * First, encrypt and decrypt this dummy value,
579  * test if the information is recuperated.
580  * Second, test with the sign and verify functions.
581  */
582 static void
583 test_keys (ECC_secret_key *sk, unsigned int nbits)
584 {
585   ECC_public_key pk;
586   gcry_mpi_t test = mpi_new (nbits);
587   mpi_point_t R_;
588   gcry_mpi_t c = mpi_new (nbits);
589   gcry_mpi_t out = mpi_new (nbits);
590   gcry_mpi_t r = mpi_new (nbits);
591   gcry_mpi_t s = mpi_new (nbits);
592
593   if (DBG_CIPHER)
594     log_debug ("Testing key.\n");
595
596   point_init (&R_);
597
598   pk.E = curve_copy (sk->E);
599   point_init (&pk.Q);
600   point_set (&pk.Q, &sk->Q);
601
602   gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
603
604   if (sign (test, sk, r, s) )
605     log_fatal ("ECDSA operation: sign failed\n");
606
607   if (verify (test, &pk, r, s))
608     {
609       log_fatal ("ECDSA operation: sign, verify failed\n");
610     }
611
612   if (DBG_CIPHER)
613     log_debug ("ECDSA operation: sign, verify ok.\n");
614
615   point_free (&pk.Q);
616   curve_free (&pk.E);
617
618   point_free (&R_);
619   mpi_free (s);
620   mpi_free (r);
621   mpi_free (out);
622   mpi_free (c);
623   mpi_free (test);
624 }
625
626 /****************
627  * To check the validity of the value, recalculate the correspondence
628  * between the public value and the secret one.
629  */
630 static int
631 check_secret_key (ECC_secret_key * sk)
632 {
633   mpi_point_t Q;
634   gcry_mpi_t y_2, y2 = mpi_alloc (0);
635   mpi_ec_t ctx;
636
637   /* ?primarity test of 'p' */
638   /*  (...) //!! */
639   /* G in E(F_p) */
640   y_2 = gen_y_2 (sk->E.G.x, &sk->E);   /*  y^2=x^3+a*x+b */
641   mpi_mulm (y2, sk->E.G.y, sk->E.G.y, sk->E.p);      /*  y^2=y*y */
642   if (mpi_cmp (y_2, y2))
643     {
644       if (DBG_CIPHER)
645         log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n");
646       return (1);
647     }
648   /* G != PaI */
649   if (!mpi_cmp_ui (sk->E.G.z, 0))
650     {
651       if (DBG_CIPHER)
652         log_debug ("Bad check: 'G' cannot be Point at Infinity!\n");
653       return (1);
654     }
655
656   point_init (&Q);
657   ctx = _gcry_mpi_ec_init (sk->E.p, sk->E.a);
658   _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx);
659   if (mpi_cmp_ui (Q.z, 0))
660     {
661       if (DBG_CIPHER)
662         log_debug ("check_secret_key: E is not a curve of order n\n");
663       point_free (&Q);
664       _gcry_mpi_ec_free (ctx);
665       return 1;
666     }
667   /* pubkey cannot be PaI */
668   if (!mpi_cmp_ui (sk->Q.z, 0))
669     {
670       if (DBG_CIPHER)
671         log_debug ("Bad check: Q can not be a Point at Infinity!\n");
672       _gcry_mpi_ec_free (ctx);
673       return (1);
674     }
675   /* pubkey = [d]G over E */
676   _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx);
677   if ((Q.x == sk->Q.x) && (Q.y == sk->Q.y) && (Q.z == sk->Q.z))
678     {
679       if (DBG_CIPHER)
680         log_debug
681           ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
682       _gcry_mpi_ec_free (ctx);
683       return (1);
684     }
685   _gcry_mpi_ec_free (ctx);
686   point_free (&Q);
687   return 0;
688 }
689
690
691 /*
692  * Return the signature struct (r,s) from the message hash.  The caller
693  * must have allocated R and S.
694  */
695 static gpg_err_code_t
696 sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s)
697 {
698   gpg_err_code_t err = 0;
699   gcry_mpi_t k, dr, sum, k_1, x;
700   mpi_point_t I;
701   mpi_ec_t ctx;
702
703   k = NULL;
704   dr = mpi_alloc (0);
705   sum = mpi_alloc (0);
706   k_1 = mpi_alloc (0);
707   x = mpi_alloc (0);
708   point_init (&I);
709
710   mpi_set_ui (s, 0);
711   mpi_set_ui (r, 0);
712
713   ctx = _gcry_mpi_ec_init (skey->E.p, skey->E.a);
714
715   while (!mpi_cmp_ui (s, 0)) /* s == 0 */
716     {
717       while (!mpi_cmp_ui (r, 0)) /* r == 0 */
718         {
719           /* Note, that we are guaranteed to enter this loop at least
720              once because r has been intialized to 0.  We can't use a
721              do_while because we want to keep the value of R even if S
722              has to be recomputed.  */
723           mpi_free (k);
724           k = gen_k (skey->E.n, GCRY_STRONG_RANDOM);
725           _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx); 
726           if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx))
727             {
728               if (DBG_CIPHER)
729                 log_debug ("ecc sign: Failed to get affine coordinates\n");
730               err = GPG_ERR_BAD_SIGNATURE;
731               goto leave;
732             }
733           mpi_mod (r, x, skey->E.n);  /* r = x mod n */
734         }
735       mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n  */
736       mpi_addm (sum, input, dr, skey->E.n); /* sum = hash + (d*r) mod n  */
737       mpi_invm (k_1, k, skey->E.n);         /* k_1 = k^(-1) mod n  */
738       mpi_mulm (s, k_1, sum, skey->E.n);    /* s = k^(-1)*(hash+(d*r)) mod n */
739     }
740
741  leave:
742   _gcry_mpi_ec_free (ctx);
743   point_free (&I);
744   mpi_free (x);
745   mpi_free (k_1);
746   mpi_free (sum);
747   mpi_free (dr);
748   mpi_free (k);
749
750   return err;
751 }
752
753 /*
754  * Check if R and S verifies INPUT.
755  */
756 static gpg_err_code_t
757 verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s)
758 {
759   gpg_err_code_t err = 0;
760   gcry_mpi_t h, h1, h2, x, y;
761   mpi_point_t Q, Q1, Q2;
762   mpi_ec_t ctx;
763
764   if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) )
765     return GPG_ERR_BAD_SIGNATURE; /* Assertion  0 < r < n  failed.  */
766   if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, pkey->E.n) < 0) )
767     return GPG_ERR_BAD_SIGNATURE; /* Assertion  0 < s < n  failed.  */
768
769   h  = mpi_alloc (0);
770   h1 = mpi_alloc (0);
771   h2 = mpi_alloc (0);
772   x = mpi_alloc (0);
773   y = mpi_alloc (0);
774   point_init (&Q);
775   point_init (&Q1);
776   point_init (&Q2);
777
778   ctx = _gcry_mpi_ec_init (pkey->E.p, pkey->E.a);
779
780   /* h  = s^(-1) (mod n) */
781   mpi_invm (h, s, pkey->E.n);
782 /*   log_mpidump ("   h", h); */
783   /* h1 = hash * s^(-1) (mod n) */
784   mpi_mulm (h1, input, h, pkey->E.n);
785 /*   log_mpidump ("  h1", h1); */
786   /* Q1 = [ hash * s^(-1) ]G  */
787   _gcry_mpi_ec_mul_point (&Q1, h1, &pkey->E.G, ctx);
788 /*   log_mpidump ("Q1.x", Q1.x); */
789 /*   log_mpidump ("Q1.y", Q1.y); */
790 /*   log_mpidump ("Q1.z", Q1.z); */
791   /* h2 = r * s^(-1) (mod n) */
792   mpi_mulm (h2, r, h, pkey->E.n);
793 /*   log_mpidump ("  h2", h2); */
794   /* Q2 = [ r * s^(-1) ]Q */
795   _gcry_mpi_ec_mul_point (&Q2, h2, &pkey->Q, ctx);
796 /*   log_mpidump ("Q2.x", Q2.x); */
797 /*   log_mpidump ("Q2.y", Q2.y); */
798 /*   log_mpidump ("Q2.z", Q2.z); */
799   /* Q  = ([hash * s^(-1)]G) + ([r * s^(-1)]Q) */
800   _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ctx);
801 /*   log_mpidump (" Q.x", Q.x); */
802 /*   log_mpidump (" Q.y", Q.y); */
803 /*   log_mpidump (" Q.z", Q.z); */
804
805   if (!mpi_cmp_ui (Q.z, 0))
806     {
807       if (DBG_CIPHER)
808           log_debug ("ecc verify: Rejected\n");
809       err = GPG_ERR_BAD_SIGNATURE;
810       goto leave;
811     }
812   if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx))
813     {
814       if (DBG_CIPHER)
815         log_debug ("ecc verify: Failed to get affine coordinates\n");
816       err = GPG_ERR_BAD_SIGNATURE;
817       goto leave;
818     }
819   mpi_mod (x, x, pkey->E.n); /* x = x mod E_n */
820   if (mpi_cmp (x, r))   /* x != r */
821     {
822       if (DBG_CIPHER)
823         {
824           log_mpidump ("   x", x);
825           log_mpidump ("   y", y);
826           log_mpidump ("   r", r);
827           log_mpidump ("   s", s);
828           log_debug ("ecc verify: Not verified\n");
829         }
830       err = GPG_ERR_BAD_SIGNATURE;
831       goto leave;
832     }
833   if (DBG_CIPHER)
834     log_debug ("ecc verify: Accepted\n");
835
836  leave:
837   _gcry_mpi_ec_free (ctx);
838   point_free (&Q2);
839   point_free (&Q1);
840   point_free (&Q);
841   mpi_free (y);
842   mpi_free (x);
843   mpi_free (h2);
844   mpi_free (h1);
845   mpi_free (h);
846   return err;
847 }
848
849
850
851 /*********************************************
852  **************  interface  ******************
853  *********************************************/
854 static gcry_mpi_t
855 ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p)
856 {
857   gpg_error_t err;
858   int pbytes = (mpi_get_nbits (p)+7)/8;
859   size_t n;
860   unsigned char *buf, *ptr;
861   gcry_mpi_t result;
862
863   buf = gcry_xmalloc ( 1 + 2*pbytes );
864   *buf = 04; /* Uncompressed point.  */
865   ptr = buf+1;
866   err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x);
867   if (err)
868     log_fatal ("mpi_print failed: %s\n", gpg_strerror (err));
869   if (n < pbytes)
870     {
871       memmove (ptr+(pbytes-n), ptr, n);
872       memset (ptr, 0, (pbytes-n));
873     }
874   ptr += pbytes;
875   err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y);
876   if (err)
877     log_fatal ("mpi_print failed: %s\n", gpg_strerror (err));
878   if (n < pbytes)
879     {
880       memmove (ptr+(pbytes-n), ptr, n);
881       memset (ptr, 0, (pbytes-n));
882     }
883   
884   err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL);
885   if (err)
886     log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err));
887   gcry_free (buf);
888
889   mpi_free (x);
890   mpi_free (y);
891
892   return result;
893 }
894
895 /* RESULT must have been initialized and is set on success to the
896    point given by VALUE.  */
897 static gcry_error_t
898 os2ec (mpi_point_t *result, gcry_mpi_t value)
899 {
900   gcry_error_t err;
901   size_t n;
902   unsigned char *buf;
903   gcry_mpi_t x, y;
904
905   n = (mpi_get_nbits (value)+7)/8;
906   buf = gcry_xmalloc (n);
907   err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, n, &n, value);
908   if (err)
909     {
910       gcry_free (buf);
911       return err;
912     }
913   if (n < 1) 
914     {
915       gcry_free (buf);
916       return GPG_ERR_INV_OBJ;
917     }
918   if (*buf != 4)
919     {
920       gcry_free (buf);
921       return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression.  */
922     }
923   if ( ((n-1)%2) ) 
924     {
925       gcry_free (buf);
926       return GPG_ERR_INV_OBJ;
927     }
928   n = (n-1)/2;
929   err = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL);
930   if (err)
931     {
932       gcry_free (buf);
933       return err;
934     }
935   err = gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL);
936   gcry_free (buf);
937   if (err)
938     {
939       mpi_free (x);
940       return err;
941     }
942
943   mpi_set (result->x, x);
944   mpi_set (result->y, y);
945   mpi_set_ui (result->z, 1);
946
947   mpi_free (x);
948   mpi_free (y);
949   
950   return 0;
951 }
952
953 /* Extended version of ecc_generate which is called directly by
954    pubkey.c.  If CURVE is not NULL, that name will be used to select
955    the domain parameters.  NBITS is not used in this case.  */
956 gcry_err_code_t
957 _gcry_ecc_generate (int algo, unsigned int nbits, const char *curve,
958                     gcry_mpi_t *skey, gcry_mpi_t **retfactors)
959 {
960   gpg_err_code_t err;
961   ECC_secret_key sk;
962   gcry_mpi_t g_x, g_y, q_x, q_y;
963
964   (void)algo;
965
966   /* Make an empty list of factors.  */
967   *retfactors = gcry_calloc ( 1, sizeof **retfactors );
968   if (!*retfactors)
969     return gpg_err_code_from_syserror ();
970
971   g_x = mpi_new (0);
972   g_y = mpi_new (0);
973   q_x = mpi_new (0);
974   q_y = mpi_new (0);
975   err = generate_key (&sk, nbits, curve, g_x, g_y, q_x, q_y);
976   if (err)
977     {
978       gcry_free (*retfactors);
979       *retfactors = NULL;
980       return err;
981     }
982
983   skey[0] = sk.E.p;
984   skey[1] = sk.E.a;
985   skey[2] = sk.E.b;
986   /* The function ec2os releases g_x and g_y.  */
987   skey[3] = ec2os (g_x, g_y, sk.E.p);
988   skey[4] = sk.E.n;
989   /* The function ec2os releases g_x and g_y.  */
990   skey[5] = ec2os (q_x, q_y, sk.E.p);
991   skey[6] = sk.d;
992
993   point_free (&sk.E.G);
994   point_free (&sk.Q);
995
996   return 0;
997 }
998
999 /* Return the parameters of the curve NAME.  */
1000 gcry_err_code_t
1001 _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey)
1002 {
1003   gpg_err_code_t err;
1004   unsigned int nbits;
1005   elliptic_curve_t E;
1006   mpi_ec_t ctx;
1007   gcry_mpi_t g_x, g_y;
1008   
1009   err = generate_curve (0, name, &E, &nbits);
1010   if (err)
1011     return err;
1012
1013   g_x = mpi_new (0);
1014   g_y = mpi_new (0);
1015   ctx = _gcry_mpi_ec_init (E.p, E.a);
1016   if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
1017     log_fatal ("ecc get param: Failed to get affine coordinates\n");
1018   _gcry_mpi_ec_free (ctx);
1019   point_free (&E.G);
1020
1021   pkey[0] = E.p;
1022   pkey[1] = E.a;
1023   pkey[2] = E.b;
1024   pkey[3] = ec2os (g_x, g_y, E.p);
1025   pkey[4] = E.n;
1026   pkey[5] = NULL;
1027
1028   return 0;
1029 }
1030
1031 static gcry_err_code_t
1032 ecc_generate (int algo, unsigned int nbits, unsigned long dummy,
1033               gcry_mpi_t *skey, gcry_mpi_t **retfactors)
1034 {
1035   (void)dummy;
1036   return _gcry_ecc_generate (algo, nbits, NULL, skey, retfactors);
1037 }
1038
1039
1040 static gcry_err_code_t
1041 ecc_check_secret_key (int algo, gcry_mpi_t *skey)
1042 {
1043   gpg_err_code_t err;
1044   ECC_secret_key sk;
1045
1046   (void)algo;
1047
1048   if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5]
1049       || !skey[6] || !skey[7] || !skey[8] || !skey[9] || !skey[10])
1050     return GPG_ERR_BAD_MPI;
1051
1052   sk.E.p = skey[0];
1053   sk.E.a = skey[1];
1054   sk.E.b = skey[2];
1055   point_init (&sk.E.G);
1056   err = os2ec (&sk.E.G, skey[3]);
1057   if (err)
1058     {
1059       point_free (&sk.E.G);
1060       return err;
1061     }
1062   sk.E.n = skey[4];
1063   point_init (&sk.Q);
1064   err = os2ec (&sk.Q, skey[5]);
1065   if (err)
1066     {
1067       point_free (&sk.E.G);
1068       point_free (&sk.Q);
1069       return err;
1070     }
1071
1072   sk.d = skey[6];
1073
1074   if (check_secret_key (&sk))
1075     {
1076       point_free (&sk.E.G);
1077       point_free (&sk.Q);
1078       return GPG_ERR_BAD_SECKEY;
1079     }
1080   point_free (&sk.E.G);
1081   point_free (&sk.Q);
1082   return 0;
1083 }
1084
1085
1086 static gcry_err_code_t
1087 ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
1088 {
1089   gpg_err_code_t err;
1090   ECC_secret_key sk;
1091
1092   (void)algo;
1093
1094   if (!data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4]
1095       || !skey[5] || !skey[6] )
1096     return GPG_ERR_BAD_MPI;
1097
1098   sk.E.p = skey[0];
1099   sk.E.a = skey[1];
1100   sk.E.b = skey[2];
1101   point_init (&sk.E.G);
1102   err = os2ec (&sk.E.G, skey[3]);
1103   if (err)
1104     {
1105       point_free (&sk.E.G);
1106       return err;
1107     }
1108   sk.E.n = skey[4];
1109   point_init (&sk.Q);
1110   err = os2ec (&sk.Q, skey[5]);
1111   if (err)
1112     {
1113       point_free (&sk.E.G);
1114       point_free (&sk.Q);
1115       return err;
1116     }
1117   sk.d = skey[6];
1118
1119   resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
1120   resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
1121   err = sign (data, &sk, resarr[0], resarr[1]);
1122   if (err)
1123     {
1124       mpi_free (resarr[0]);
1125       mpi_free (resarr[1]);
1126       resarr[0] = NULL; /* Mark array as released.  */
1127     }
1128   point_free (&sk.E.G);
1129   point_free (&sk.Q);
1130   return err;
1131 }
1132
1133 static gcry_err_code_t
1134 ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
1135             int (*cmp)(void *, gcry_mpi_t), void *opaquev)
1136 {
1137   gpg_err_code_t err;
1138   ECC_public_key pk;
1139
1140   (void)algo;
1141   (void)cmp;
1142   (void)opaquev;
1143
1144   if (!data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] || !pkey[2]
1145       || !pkey[3] || !pkey[4] || !pkey[5] )
1146     return GPG_ERR_BAD_MPI;
1147
1148   pk.E.p = pkey[0];
1149   pk.E.a = pkey[1];
1150   pk.E.b = pkey[2];
1151   point_init (&pk.E.G);
1152   err = os2ec (&pk.E.G, pkey[3]);
1153   if (err)
1154     {
1155       point_free (&pk.E.G);
1156       return err;
1157     }
1158   pk.E.n = pkey[4];
1159   point_init (&pk.Q);
1160   err = os2ec (&pk.Q, pkey[5]);
1161   if (err)
1162     {
1163       point_free (&pk.E.G);
1164       point_free (&pk.Q);
1165       return err;
1166     }
1167
1168   err = verify (hash, &pk, data[0], data[1]);
1169
1170   point_free (&pk.E.G);
1171   point_free (&pk.Q);
1172   return err;
1173 }
1174
1175
1176
1177 static unsigned int
1178 ecc_get_nbits (int algo, gcry_mpi_t *pkey)
1179 {
1180   (void)algo;
1181
1182   return mpi_get_nbits (pkey[0]);
1183 }
1184
1185
1186 \f
1187 /* 
1188      Self-test section.
1189  */
1190
1191
1192 static gpg_err_code_t
1193 selftests_ecdsa (selftest_report_func_t report)
1194 {
1195   const char *what;
1196   const char *errtxt;
1197   
1198   what = "low-level";
1199   errtxt = NULL; /*selftest ();*/
1200   if (errtxt)
1201     goto failed;
1202
1203   /* FIXME:  need more tests.  */
1204
1205   return 0; /* Succeeded. */
1206
1207  failed:
1208   if (report)
1209     report ("pubkey", GCRY_PK_ECDSA, what, errtxt);
1210   return GPG_ERR_SELFTEST_FAILED;
1211 }
1212
1213
1214 /* Run a full self-test for ALGO and return 0 on success.  */
1215 static gpg_err_code_t
1216 run_selftests (int algo, selftest_report_func_t report)
1217 {
1218   gpg_err_code_t ec;
1219
1220   switch (algo)
1221     {
1222     case GCRY_PK_ECDSA:
1223       ec = selftests_ecdsa (report);
1224       break;
1225     default:
1226       ec = GPG_ERR_PUBKEY_ALGO;
1227       break;
1228         
1229     }
1230   return ec;
1231 }
1232
1233
1234
1235 \f
1236 static const char *ecdsa_names[] =
1237   {
1238     "ecdsa",
1239     "ecc",
1240     NULL,
1241   };
1242
1243 gcry_pk_spec_t _gcry_pubkey_spec_ecdsa =
1244   {
1245     "ECDSA", ecdsa_names,
1246     "pabgnq", "pabgnqd", "", "rs", "pabgnq",
1247     GCRY_PK_USAGE_SIGN,
1248     ecc_generate,
1249     ecc_check_secret_key,
1250     NULL,
1251     NULL,
1252     ecc_sign,
1253     ecc_verify,
1254     ecc_get_nbits
1255   };
1256 pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = 
1257   {
1258     run_selftests
1259   };
1260