mpi: Improve support for non-Weierstrass support.
[libgcrypt.git] / cipher / ecc.c
1 /* ecc.c  -  Elliptic Curve Cryptography
2  * Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
3  * Copyright (C) 2013 g10 Code GmbH
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
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   ECDH encrypt and decrypt code written by Andrey Jivsov,
39 */
40
41
42 /* TODO:
43
44   - If we support point compression we need to uncompress before
45     computing the keygrip
46
47   - In mpi/ec.c we use mpi_powm for x^2 mod p: Either implement a
48     special case in mpi_powm or check whether mpi_mulm is faster.
49
50 */
51
52
53 #include <config.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <errno.h>
58
59 #include "g10lib.h"
60 #include "mpi.h"
61 #include "cipher.h"
62 #include "context.h"
63 #include "ec-context.h"
64 #include "pubkey-internal.h"
65 #include "ecc-common.h"
66
67
68 /* Registered progress function and its callback value. */
69 static void (*progress_cb) (void *, const char*, int, int, int);
70 static void *progress_cb_data;
71
72
73 #define point_init(a)  _gcry_mpi_point_init ((a))
74 #define point_free(a)  _gcry_mpi_point_free_parts ((a))
75
76 \f
77 /* Local prototypes. */
78 static void test_keys (ECC_secret_key * sk, unsigned int nbits);
79 static int check_secret_key (ECC_secret_key * sk);
80 static gpg_err_code_t sign_ecdsa (gcry_mpi_t input, ECC_secret_key *skey,
81                                   gcry_mpi_t r, gcry_mpi_t s,
82                                   int flags, int hashalgo);
83 static gpg_err_code_t verify_ecdsa (gcry_mpi_t input, ECC_public_key *pkey,
84                                     gcry_mpi_t r, gcry_mpi_t s);
85
86 static gcry_mpi_t gen_y_2 (gcry_mpi_t x, elliptic_curve_t * base);
87
88
89
90 \f
91 void
92 _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
93                                             int, int, int),
94                                 void *cb_data)
95 {
96   progress_cb = cb;
97   progress_cb_data = cb_data;
98 }
99
100 /* static void */
101 /* progress (int c) */
102 /* { */
103 /*   if (progress_cb) */
104 /*     progress_cb (progress_cb_data, "pk_ecc", c, 0, 0); */
105 /* } */
106
107
108 \f
109
110 /*
111  * Solve the right side of the Weierstrass equation.
112  */
113 static gcry_mpi_t
114 gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base)
115 {
116   gcry_mpi_t three, x_3, axb, y;
117
118   three = mpi_alloc_set_ui (3);
119   x_3 = mpi_new (0);
120   axb = mpi_new (0);
121   y   = mpi_new (0);
122
123   mpi_powm (x_3, x, three, base->p);
124   mpi_mulm (axb, base->a, x, base->p);
125   mpi_addm (axb, axb, base->b, base->p);
126   mpi_addm (y, x_3, axb, base->p);
127
128   mpi_free (x_3);
129   mpi_free (axb);
130   mpi_free (three);
131   return y; /* The quadratic value of the coordinate if it exist. */
132 }
133
134
135 /*
136  * First obtain the setup.  Over the finite field randomize an scalar
137  * secret value, and calculate the public point.
138  */
139 static gpg_err_code_t
140 generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
141               int transient_key,
142               gcry_mpi_t g_x, gcry_mpi_t g_y,
143               gcry_mpi_t q_x, gcry_mpi_t q_y,
144               const char **r_usedcurve)
145 {
146   gpg_err_code_t err;
147   elliptic_curve_t E;
148   mpi_point_struct Q;
149   mpi_ec_t ctx;
150   gcry_random_level_t random_level;
151
152   *r_usedcurve = NULL;
153
154   err = _gcry_ecc_fill_in_curve (nbits, name, &E, &nbits);
155   if (err)
156     return err;
157
158   if (DBG_CIPHER)
159     {
160       log_debug ("ecgen curve model: %s\n", _gcry_ecc_model2str (E.model));
161       log_mpidump ("ecgen curve  p", E.p);
162       log_mpidump ("ecgen curve  a", E.a);
163       log_mpidump ("ecgen curve  b", E.b);
164       log_mpidump ("ecgen curve  n", E.n);
165       log_mpidump ("ecgen curve Gx", E.G.x);
166       log_mpidump ("ecgen curve Gy", E.G.y);
167       log_mpidump ("ecgen curve Gz", E.G.z);
168       if (E.name)
169         log_debug ("ecgen curve used: %s\n", E.name);
170     }
171
172   random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
173   sk->d = _gcry_dsa_gen_k (E.n, random_level);
174
175   /* Compute Q.  */
176   point_init (&Q);
177   ctx = _gcry_mpi_ec_p_internal_new (E.model, E.p, E.a, E.b);
178   _gcry_mpi_ec_mul_point (&Q, sk->d, &E.G, ctx);
179
180   /* Copy the stuff to the key structures. */
181   sk->E.model = E.model;
182   sk->E.p = mpi_copy (E.p);
183   sk->E.a = mpi_copy (E.a);
184   sk->E.b = mpi_copy (E.b);
185   point_init (&sk->E.G);
186   point_set (&sk->E.G, &E.G);
187   sk->E.n = mpi_copy (E.n);
188   point_init (&sk->Q);
189
190   /* We want the Q=(x,y) be a "compliant key" in terms of the
191    * http://tools.ietf.org/html/draft-jivsov-ecc-compact, which simply
192    * means that we choose either Q=(x,y) or -Q=(x,p-y) such that we
193    * end up with the min(y,p-y) as the y coordinate.  Such a public
194    * key allows the most efficient compression: y can simply be
195    * dropped because we know that it's a minimum of the two
196    * possibilities without any loss of security.  */
197   {
198     gcry_mpi_t x, y, p_y;
199     const unsigned int pbits = mpi_get_nbits (E.p);
200
201     x = mpi_new (pbits);
202     y = mpi_new (pbits);
203     p_y = mpi_new (pbits);
204
205     if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx))
206       log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
207
208     mpi_sub (p_y, E.p, y);      /* p_y = p - y */
209
210     if (mpi_cmp (p_y, y) < 0)   /* p - y < p */
211       {
212         /* We need to end up with -Q; this assures that new Q's y is
213            the smallest one */
214         mpi_sub (sk->d, E.n, sk->d);   /* d = order - d */
215         gcry_mpi_point_snatch_set (&sk->Q, x, p_y, mpi_alloc_set_ui (1));
216
217         if (DBG_CIPHER)
218           log_debug ("ecgen converted Q to a compliant point\n");
219       }
220     else /* p - y >= p */
221       {
222         /* No change is needed exactly 50% of the time: just copy. */
223         point_set (&sk->Q, &Q);
224         if (DBG_CIPHER)
225           log_debug ("ecgen didn't need to convert Q to a compliant point\n");
226
227         mpi_free (p_y);
228         mpi_free (x);
229       }
230     mpi_free (y);
231   }
232
233   /* We also return copies of G and Q in affine coordinates if
234      requested.  */
235   if (g_x && g_y)
236     {
237       if (_gcry_mpi_ec_get_affine (g_x, g_y, &sk->E.G, ctx))
238         log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "G");
239     }
240   if (q_x && q_y)
241     {
242       if (_gcry_mpi_ec_get_affine (q_x, q_y, &sk->Q, ctx))
243         log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
244     }
245   _gcry_mpi_ec_free (ctx);
246
247   point_free (&Q);
248
249   *r_usedcurve = E.name;
250   _gcry_ecc_curve_free (&E);
251
252   /* Now we can test our keys (this should never fail!).  */
253   test_keys (sk, nbits - 64);
254
255   return 0;
256 }
257
258
259 /*
260  * To verify correct skey it use a random information.
261  * First, encrypt and decrypt this dummy value,
262  * test if the information is recuperated.
263  * Second, test with the sign and verify functions.
264  */
265 static void
266 test_keys (ECC_secret_key *sk, unsigned int nbits)
267 {
268   ECC_public_key pk;
269   gcry_mpi_t test = mpi_new (nbits);
270   mpi_point_struct R_;
271   gcry_mpi_t c = mpi_new (nbits);
272   gcry_mpi_t out = mpi_new (nbits);
273   gcry_mpi_t r = mpi_new (nbits);
274   gcry_mpi_t s = mpi_new (nbits);
275
276   if (DBG_CIPHER)
277     log_debug ("Testing key.\n");
278
279   point_init (&R_);
280
281   pk.E = _gcry_ecc_curve_copy (sk->E);
282   point_init (&pk.Q);
283   point_set (&pk.Q, &sk->Q);
284
285   gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
286
287   if (sign_ecdsa (test, sk, r, s, 0, 0) )
288     log_fatal ("ECDSA operation: sign failed\n");
289
290   if (verify_ecdsa (test, &pk, r, s))
291     {
292       log_fatal ("ECDSA operation: sign, verify failed\n");
293     }
294
295   if (DBG_CIPHER)
296     log_debug ("ECDSA operation: sign, verify ok.\n");
297
298   point_free (&pk.Q);
299   _gcry_ecc_curve_free (&pk.E);
300
301   point_free (&R_);
302   mpi_free (s);
303   mpi_free (r);
304   mpi_free (out);
305   mpi_free (c);
306   mpi_free (test);
307 }
308
309
310 /*
311  * To check the validity of the value, recalculate the correspondence
312  * between the public value and the secret one.
313  */
314 static int
315 check_secret_key (ECC_secret_key * sk)
316 {
317   int rc = 1;
318   mpi_point_struct Q;
319   gcry_mpi_t y_2, y2;
320   gcry_mpi_t x1, x2;
321   mpi_ec_t ctx = NULL;
322
323   point_init (&Q);
324
325   /* ?primarity test of 'p' */
326   /*  (...) //!! */
327   /* G in E(F_p) */
328   y_2 = gen_y_2 (sk->E.G.x, &sk->E);   /*  y^2=x^3+a*x+b */
329   y2 = mpi_alloc (0);
330   x1 = mpi_alloc (0);
331   x2 = mpi_alloc (0);
332   mpi_mulm (y2, sk->E.G.y, sk->E.G.y, sk->E.p);      /*  y^2=y*y */
333   if (mpi_cmp (y_2, y2))
334     {
335       if (DBG_CIPHER)
336         log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n");
337       goto leave;
338     }
339   /* G != PaI */
340   if (!mpi_cmp_ui (sk->E.G.z, 0))
341     {
342       if (DBG_CIPHER)
343         log_debug ("Bad check: 'G' cannot be Point at Infinity!\n");
344       goto leave;
345     }
346
347   ctx = _gcry_mpi_ec_p_internal_new (sk->E.model, sk->E.p, sk->E.a, sk->E.b);
348
349   _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx);
350   if (mpi_cmp_ui (Q.z, 0))
351     {
352       if (DBG_CIPHER)
353         log_debug ("check_secret_key: E is not a curve of order n\n");
354       goto leave;
355     }
356   /* pubkey cannot be PaI */
357   if (!mpi_cmp_ui (sk->Q.z, 0))
358     {
359       if (DBG_CIPHER)
360         log_debug ("Bad check: Q can not be a Point at Infinity!\n");
361       goto leave;
362     }
363   /* pubkey = [d]G over E */
364   _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx);
365
366   if (_gcry_mpi_ec_get_affine (x1, y_2, &Q, ctx))
367     {
368       if (DBG_CIPHER)
369         log_debug ("Bad check: Q can not be a Point at Infinity!\n");
370       goto leave;
371     }
372
373   /* Fast path for loaded secret keys - Q is already in affine coordinates */
374   if (!mpi_cmp_ui (sk->Q.z, 1))
375     {
376       if (mpi_cmp (x1, sk->Q.x) || mpi_cmp (y_2, sk->Q.y))
377         {
378           if (DBG_CIPHER)
379             log_debug
380               ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
381           goto leave;
382         }
383     }
384   else
385     {
386       if (_gcry_mpi_ec_get_affine (x2, y2, &sk->Q, ctx))
387         {
388           if (DBG_CIPHER)
389             log_debug ("Bad check: Q can not be a Point at Infinity!\n");
390           goto leave;
391         }
392
393       if (mpi_cmp (x1, x2) || mpi_cmp (y_2, y2))
394         {
395           if (DBG_CIPHER)
396             log_debug
397               ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
398           goto leave;
399         }
400     }
401   rc = 0; /* Okay.  */
402
403  leave:
404   _gcry_mpi_ec_free (ctx);
405   mpi_free (x2);
406   mpi_free (x1);
407   mpi_free (y2);
408   mpi_free (y_2);
409   point_free (&Q);
410   return rc;
411 }
412
413
414 /* Compute an ECDSA signature.
415  * Return the signature struct (r,s) from the message hash.  The caller
416  * must have allocated R and S.
417  */
418 static gpg_err_code_t
419 sign_ecdsa (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s,
420             int flags, int hashalgo)
421 {
422   gpg_err_code_t err = 0;
423   int extraloops = 0;
424   gcry_mpi_t k, dr, sum, k_1, x;
425   mpi_point_struct I;
426   gcry_mpi_t hash;
427   const void *abuf;
428   unsigned int abits, qbits;
429   mpi_ec_t ctx;
430
431   if (DBG_CIPHER)
432     log_mpidump ("ecdsa sign hash  ", input );
433
434   qbits = mpi_get_nbits (skey->E.n);
435
436   /* Convert the INPUT into an MPI if needed.  */
437   if (mpi_is_opaque (input))
438     {
439       abuf = gcry_mpi_get_opaque (input, &abits);
440       err = gpg_err_code (gcry_mpi_scan (&hash, GCRYMPI_FMT_USG,
441                                          abuf, (abits+7)/8, NULL));
442       if (err)
443         return err;
444       if (abits > qbits)
445         gcry_mpi_rshift (hash, hash, abits - qbits);
446     }
447   else
448     hash = input;
449
450
451   k = NULL;
452   dr = mpi_alloc (0);
453   sum = mpi_alloc (0);
454   k_1 = mpi_alloc (0);
455   x = mpi_alloc (0);
456   point_init (&I);
457
458   mpi_set_ui (s, 0);
459   mpi_set_ui (r, 0);
460
461   ctx = _gcry_mpi_ec_p_internal_new (skey->E.model,
462                                      skey->E.p, skey->E.a, skey->E.b);
463
464   while (!mpi_cmp_ui (s, 0)) /* s == 0 */
465     {
466       while (!mpi_cmp_ui (r, 0)) /* r == 0 */
467         {
468           /* Note, that we are guaranteed to enter this loop at least
469              once because r has been intialized to 0.  We can't use a
470              do_while because we want to keep the value of R even if S
471              has to be recomputed.  */
472
473           mpi_free (k);
474           k = NULL;
475           if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo)
476             {
477               /* Use Pornin's method for deterministic DSA.  If this
478                  flag is set, it is expected that HASH is an opaque
479                  MPI with the to be signed hash.  That hash is also
480                  used as h1 from 3.2.a.  */
481               if (!mpi_is_opaque (input))
482                 {
483                   err = GPG_ERR_CONFLICT;
484                   goto leave;
485                 }
486
487               abuf = gcry_mpi_get_opaque (input, &abits);
488               err = _gcry_dsa_gen_rfc6979_k (&k, skey->E.n, skey->d,
489                                              abuf, (abits+7)/8,
490                                              hashalgo, extraloops);
491               if (err)
492                 goto leave;
493               extraloops++;
494             }
495           else
496             k = _gcry_dsa_gen_k (skey->E.n, GCRY_STRONG_RANDOM);
497
498           _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx);
499           if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx))
500             {
501               if (DBG_CIPHER)
502                 log_debug ("ecc sign: Failed to get affine coordinates\n");
503               err = GPG_ERR_BAD_SIGNATURE;
504               goto leave;
505             }
506           mpi_mod (r, x, skey->E.n);  /* r = x mod n */
507         }
508       mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n  */
509       mpi_addm (sum, hash, dr, skey->E.n);  /* sum = hash + (d*r) mod n  */
510       mpi_invm (k_1, k, skey->E.n);         /* k_1 = k^(-1) mod n  */
511       mpi_mulm (s, k_1, sum, skey->E.n);    /* s = k^(-1)*(hash+(d*r)) mod n */
512     }
513
514   if (DBG_CIPHER)
515     {
516       log_mpidump ("ecdsa sign result r ", r);
517       log_mpidump ("ecdsa sign result s ", s);
518     }
519
520  leave:
521   _gcry_mpi_ec_free (ctx);
522   point_free (&I);
523   mpi_free (x);
524   mpi_free (k_1);
525   mpi_free (sum);
526   mpi_free (dr);
527   mpi_free (k);
528
529   if (hash != input)
530     mpi_free (hash);
531
532   return err;
533 }
534
535
536 /* Verify an ECDSA signature.
537  * Check if R and S verifies INPUT.
538  */
539 static gpg_err_code_t
540 verify_ecdsa (gcry_mpi_t input, ECC_public_key *pkey,
541               gcry_mpi_t r, gcry_mpi_t s)
542 {
543   gpg_err_code_t err = 0;
544   gcry_mpi_t h, h1, h2, x;
545   mpi_point_struct Q, Q1, Q2;
546   mpi_ec_t ctx;
547
548   if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) )
549     return GPG_ERR_BAD_SIGNATURE; /* Assertion  0 < r < n  failed.  */
550   if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, pkey->E.n) < 0) )
551     return GPG_ERR_BAD_SIGNATURE; /* Assertion  0 < s < n  failed.  */
552
553   h  = mpi_alloc (0);
554   h1 = mpi_alloc (0);
555   h2 = mpi_alloc (0);
556   x = mpi_alloc (0);
557   point_init (&Q);
558   point_init (&Q1);
559   point_init (&Q2);
560
561   ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model,
562                                      pkey->E.p, pkey->E.a, pkey->E.b);
563
564   /* h  = s^(-1) (mod n) */
565   mpi_invm (h, s, pkey->E.n);
566   /* h1 = hash * s^(-1) (mod n) */
567   mpi_mulm (h1, input, h, pkey->E.n);
568   /* Q1 = [ hash * s^(-1) ]G  */
569   _gcry_mpi_ec_mul_point (&Q1, h1, &pkey->E.G, ctx);
570   /* h2 = r * s^(-1) (mod n) */
571   mpi_mulm (h2, r, h, pkey->E.n);
572   /* Q2 = [ r * s^(-1) ]Q */
573   _gcry_mpi_ec_mul_point (&Q2, h2, &pkey->Q, ctx);
574   /* Q  = ([hash * s^(-1)]G) + ([r * s^(-1)]Q) */
575   _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ctx);
576
577   if (!mpi_cmp_ui (Q.z, 0))
578     {
579       if (DBG_CIPHER)
580           log_debug ("ecc verify: Rejected\n");
581       err = GPG_ERR_BAD_SIGNATURE;
582       goto leave;
583     }
584   if (_gcry_mpi_ec_get_affine (x, NULL, &Q, ctx))
585     {
586       if (DBG_CIPHER)
587         log_debug ("ecc verify: Failed to get affine coordinates\n");
588       err = GPG_ERR_BAD_SIGNATURE;
589       goto leave;
590     }
591   mpi_mod (x, x, pkey->E.n); /* x = x mod E_n */
592   if (mpi_cmp (x, r))   /* x != r */
593     {
594       if (DBG_CIPHER)
595         {
596           log_mpidump ("     x", x);
597           log_mpidump ("     r", r);
598           log_mpidump ("     s", s);
599           log_debug ("ecc verify: Not verified\n");
600         }
601       err = GPG_ERR_BAD_SIGNATURE;
602       goto leave;
603     }
604   if (DBG_CIPHER)
605     log_debug ("ecc verify: Accepted\n");
606
607  leave:
608   _gcry_mpi_ec_free (ctx);
609   point_free (&Q2);
610   point_free (&Q1);
611   point_free (&Q);
612   mpi_free (x);
613   mpi_free (h2);
614   mpi_free (h1);
615   mpi_free (h);
616   return err;
617 }
618
619
620 \f
621 /* Compute an EdDSA signature. See:
622  *   [ed25519] 23pp. (PDF) Daniel J. Bernstein, Niels Duif, Tanja
623  *   Lange, Peter Schwabe, Bo-Yin Yang. High-speed high-security
624  *   signatures.  Journal of Cryptographic Engineering 2 (2012), 77-89.
625  *   Document ID: a1a62a2f76d23f65d622484ddd09caf8.
626  *   URL: http://cr.yp.to/papers.html#ed25519. Date: 2011.09.26.
627  *
628  * Despite that this function requires the specification of a hash
629  * algorithm, we only support what has been specified by the paper.
630  * This may change in the future.  Note that we don't check the used
631  * curve; the user is responsible to use Ed25519.
632  *
633  * Return the signature struct (r,s) from the message hash.  The caller
634  * must have allocated R and S.
635  */
636 static gpg_err_code_t
637 sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey,
638             gcry_mpi_t r, gcry_mpi_t s, int hashalgo)
639 {
640   (void)skey;
641   (void)r;
642   (void)s;
643
644   if (!mpi_is_opaque (input))
645     return GPG_ERR_INV_DATA;
646   if (hashalgo != GCRY_MD_SHA512)
647     return GPG_ERR_DIGEST_ALGO;
648
649   return GPG_ERR_NOT_IMPLEMENTED;
650 }
651
652
653 /* Verify an EdDSA signature.  See sign_eddsa for the reference.
654  * Check if R and S verifies INPUT.
655  */
656 static gpg_err_code_t
657 verify_eddsa (gcry_mpi_t input, ECC_public_key *pkey,
658               gcry_mpi_t r, gcry_mpi_t s, int hashalgo)
659 {
660   (void)pkey;
661   (void)r;
662   (void)s;
663
664   if (!mpi_is_opaque (input))
665     return GPG_ERR_INV_DATA;
666   if (hashalgo != GCRY_MD_SHA512)
667     return GPG_ERR_DIGEST_ALGO;
668
669   return GPG_ERR_NOT_IMPLEMENTED;
670 }
671
672
673 \f
674 /*********************************************
675  **************  interface  ******************
676  *********************************************/
677
678 /* Extended version of ecc_generate.  */
679 static gcry_err_code_t
680 ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
681                   const gcry_sexp_t genparms,
682                   gcry_mpi_t *skey, gcry_mpi_t **retfactors,
683                   gcry_sexp_t *r_extrainfo)
684 {
685   gpg_err_code_t ec;
686   ECC_secret_key sk;
687   gcry_mpi_t g_x, g_y, q_x, q_y;
688   char *curve_name = NULL;
689   gcry_sexp_t l1;
690   int transient_key = 0;
691   const char *usedcurve = NULL;
692
693   (void)algo;
694   (void)evalue;
695
696   if (genparms)
697     {
698       /* Parse the optional "curve" parameter. */
699       l1 = gcry_sexp_find_token (genparms, "curve", 0);
700       if (l1)
701         {
702           curve_name = _gcry_sexp_nth_string (l1, 1);
703           gcry_sexp_release (l1);
704           if (!curve_name)
705             return GPG_ERR_INV_OBJ; /* No curve name or value too large. */
706         }
707
708       /* Parse the optional transient-key flag.  */
709       l1 = gcry_sexp_find_token (genparms, "transient-key", 0);
710       if (l1)
711         {
712           transient_key = 1;
713           gcry_sexp_release (l1);
714         }
715     }
716
717   /* NBITS is required if no curve name has been given.  */
718   if (!nbits && !curve_name)
719     return GPG_ERR_NO_OBJ; /* No NBITS parameter. */
720
721   g_x = mpi_new (0);
722   g_y = mpi_new (0);
723   q_x = mpi_new (0);
724   q_y = mpi_new (0);
725   ec = generate_key (&sk, nbits, curve_name, transient_key, g_x, g_y, q_x, q_y,
726                      &usedcurve);
727   gcry_free (curve_name);
728   if (ec)
729     return ec;
730   if (usedcurve)  /* Fixme: No error return checking.  */
731     gcry_sexp_build (r_extrainfo, NULL, "(curve %s)", usedcurve);
732
733   skey[0] = sk.E.p;
734   skey[1] = sk.E.a;
735   skey[2] = sk.E.b;
736   skey[3] = _gcry_ecc_ec2os (g_x, g_y, sk.E.p);
737   skey[4] = sk.E.n;
738   skey[5] = _gcry_ecc_ec2os (q_x, q_y, sk.E.p);
739   skey[6] = sk.d;
740
741   mpi_free (g_x);
742   mpi_free (g_y);
743   mpi_free (q_x);
744   mpi_free (q_y);
745
746   point_free (&sk.E.G);
747   point_free (&sk.Q);
748
749   /* Make an empty list of factors.  */
750   *retfactors = gcry_calloc ( 1, sizeof **retfactors );
751   if (!*retfactors)
752     return gpg_err_code_from_syserror ();  /* Fixme: relase mem?  */
753
754   if (DBG_CIPHER)
755     {
756       log_debug ("ecgen result model: %s\n", _gcry_ecc_model2str (sk.E.model));
757       log_mpidump ("ecgen result p", skey[0]);
758       log_mpidump ("ecgen result a", skey[1]);
759       log_mpidump ("ecgen result b", skey[2]);
760       log_mpidump ("ecgen result G", skey[3]);
761       log_mpidump ("ecgen result n", skey[4]);
762       log_mpidump ("ecgen result Q", skey[5]);
763       log_mpidump ("ecgen result d", skey[6]);
764     }
765
766   return 0;
767 }
768
769
770 static gcry_err_code_t
771 ecc_generate (int algo, unsigned int nbits, unsigned long evalue,
772               gcry_mpi_t *skey, gcry_mpi_t **retfactors)
773 {
774   (void)evalue;
775   return ecc_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL);
776 }
777
778
779 static gcry_err_code_t
780 ecc_check_secret_key (int algo, gcry_mpi_t *skey)
781 {
782   gpg_err_code_t err;
783   ECC_secret_key sk;
784
785   (void)algo;
786
787   /* FIXME:  This check looks a bit fishy:  Now long is the array?  */
788   if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5]
789       || !skey[6])
790     return GPG_ERR_BAD_MPI;
791
792   sk.E.model = MPI_EC_WEIERSTRASS;
793   sk.E.p = skey[0];
794   sk.E.a = skey[1];
795   sk.E.b = skey[2];
796   point_init (&sk.E.G);
797   err = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
798   if (err)
799     {
800       point_free (&sk.E.G);
801       return err;
802     }
803   sk.E.n = skey[4];
804   point_init (&sk.Q);
805   err = _gcry_ecc_os2ec (&sk.Q, skey[5]);
806   if (err)
807     {
808       point_free (&sk.E.G);
809       point_free (&sk.Q);
810       return err;
811     }
812
813   sk.d = skey[6];
814
815   if (check_secret_key (&sk))
816     {
817       point_free (&sk.E.G);
818       point_free (&sk.Q);
819       return GPG_ERR_BAD_SECKEY;
820     }
821   point_free (&sk.E.G);
822   point_free (&sk.Q);
823   return 0;
824 }
825
826
827 static gcry_err_code_t
828 ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
829           int flags, int hashalgo)
830 {
831   gpg_err_code_t err;
832   ECC_secret_key sk;
833
834   (void)algo;
835
836   if (!data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4]
837       || !skey[6] )
838     return GPG_ERR_BAD_MPI;
839
840   sk.E.model = ((flags & PUBKEY_FLAG_EDDSA)
841                 ? MPI_EC_TWISTEDEDWARDS
842                 : MPI_EC_WEIERSTRASS);
843   sk.E.p = skey[0];
844   sk.E.a = skey[1];
845   sk.E.b = skey[2];
846   point_init (&sk.E.G);
847   err = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
848   if (err)
849     {
850       point_free (&sk.E.G);
851       return err;
852     }
853   sk.E.n = skey[4];
854   /* Note: We don't have any need for Q here.  */
855   sk.d = skey[6];
856
857   resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
858   resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
859   if ((flags & PUBKEY_FLAG_EDDSA))
860     err = sign_eddsa (data, &sk, resarr[0], resarr[1], hashalgo);
861   else
862     err = sign_ecdsa (data, &sk, resarr[0], resarr[1], flags, hashalgo);
863   if (err)
864     {
865       mpi_free (resarr[0]);
866       mpi_free (resarr[1]);
867       resarr[0] = NULL; /* Mark array as released.  */
868     }
869   point_free (&sk.E.G);
870   return err;
871 }
872
873
874 static gcry_err_code_t
875 ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
876             int (*cmp)(void *, gcry_mpi_t), void *opaquev,
877             int flags, int hashalgo)
878 {
879   gpg_err_code_t err;
880   ECC_public_key pk;
881
882   (void)algo;
883   (void)cmp;
884   (void)opaquev;
885
886   if (!data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] || !pkey[2]
887       || !pkey[3] || !pkey[4] || !pkey[5] )
888     return GPG_ERR_BAD_MPI;
889
890   pk.E.model = ((flags & PUBKEY_FLAG_EDDSA)
891                 ? MPI_EC_TWISTEDEDWARDS
892                 : MPI_EC_WEIERSTRASS);
893   pk.E.p = pkey[0];
894   pk.E.a = pkey[1];
895   pk.E.b = pkey[2];
896   point_init (&pk.E.G);
897   err = _gcry_ecc_os2ec (&pk.E.G, pkey[3]);
898   if (err)
899     {
900       point_free (&pk.E.G);
901       return err;
902     }
903   pk.E.n = pkey[4];
904   point_init (&pk.Q);
905   err = _gcry_ecc_os2ec (&pk.Q, pkey[5]);
906   if (err)
907     {
908       point_free (&pk.E.G);
909       point_free (&pk.Q);
910       return err;
911     }
912
913   if ((flags & PUBKEY_FLAG_EDDSA))
914     {
915       err = verify_eddsa (hash, &pk, data[0], data[1], hashalgo);
916     }
917   else if (mpi_is_opaque (hash))
918     {
919       const void *abuf;
920       unsigned int abits, qbits;
921       gcry_mpi_t a;
922
923       qbits = mpi_get_nbits (pk.E.n);
924
925       abuf = gcry_mpi_get_opaque (hash, &abits);
926       err = gcry_mpi_scan (&a, GCRYMPI_FMT_USG, abuf, (abits+7)/8, NULL);
927       if (!err)
928         {
929           if (abits > qbits)
930             gcry_mpi_rshift (a, a, abits - qbits);
931
932           err = verify_ecdsa (a, &pk, data[0], data[1]);
933           gcry_mpi_release (a);
934         }
935     }
936   else
937     err = verify_ecdsa (hash, &pk, data[0], data[1]);
938
939   point_free (&pk.E.G);
940   point_free (&pk.Q);
941   return err;
942 }
943
944
945 /* ecdh raw is classic 2-round DH protocol published in 1976.
946  *
947  * Overview of ecc_encrypt_raw and ecc_decrypt_raw.
948  *
949  * As with any PK operation, encrypt version uses a public key and
950  * decrypt -- private.
951  *
952  * Symbols used below:
953  *     G - field generator point
954  *     d - private long-term scalar
955  *    dG - public long-term key
956  *     k - ephemeral scalar
957  *    kG - ephemeral public key
958  *   dkG - shared secret
959  *
960  * ecc_encrypt_raw description:
961  *   input:
962  *     data[0] : private scalar (k)
963  *   output:
964  *     result[0] : shared point (kdG)
965  *     result[1] : generated ephemeral public key (kG)
966  *
967  * ecc_decrypt_raw description:
968  *   input:
969  *     data[0] : a point kG (ephemeral public key)
970  *   output:
971  *     result[0] : shared point (kdG)
972  */
973 static gcry_err_code_t
974 ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
975                  gcry_mpi_t *pkey, int flags)
976 {
977   ECC_public_key pk;
978   mpi_ec_t ctx;
979   gcry_mpi_t result[2];
980   int err;
981
982   (void)algo;
983   (void)flags;
984
985   if (!k
986       || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4] || !pkey[5])
987     return GPG_ERR_BAD_MPI;
988
989   pk.E.model = MPI_EC_WEIERSTRASS;
990   pk.E.p = pkey[0];
991   pk.E.a = pkey[1];
992   pk.E.b = pkey[2];
993   point_init (&pk.E.G);
994   err = _gcry_ecc_os2ec (&pk.E.G, pkey[3]);
995   if (err)
996     {
997       point_free (&pk.E.G);
998       return err;
999     }
1000   pk.E.n = pkey[4];
1001   point_init (&pk.Q);
1002   err = _gcry_ecc_os2ec (&pk.Q, pkey[5]);
1003   if (err)
1004     {
1005       point_free (&pk.E.G);
1006       point_free (&pk.Q);
1007       return err;
1008     }
1009
1010   ctx = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.p, pk.E.a, pk.E.b);
1011
1012   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
1013   {
1014     mpi_point_struct R;  /* Result that we return.  */
1015     gcry_mpi_t x, y;
1016
1017     x = mpi_new (0);
1018     y = mpi_new (0);
1019
1020     point_init (&R);
1021
1022     /* R = kQ  <=>  R = kdG  */
1023     _gcry_mpi_ec_mul_point (&R, k, &pk.Q, ctx);
1024
1025     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
1026       log_fatal ("ecdh: Failed to get affine coordinates for kdG\n");
1027
1028     result[0] = _gcry_ecc_ec2os (x, y, pk.E.p);
1029
1030     /* R = kG */
1031     _gcry_mpi_ec_mul_point (&R, k, &pk.E.G, ctx);
1032
1033     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
1034       log_fatal ("ecdh: Failed to get affine coordinates for kG\n");
1035
1036     result[1] = _gcry_ecc_ec2os (x, y, pk.E.p);
1037
1038     mpi_free (x);
1039     mpi_free (y);
1040
1041     point_free (&R);
1042   }
1043
1044   _gcry_mpi_ec_free (ctx);
1045   point_free (&pk.E.G);
1046   point_free (&pk.Q);
1047
1048   if (!result[0] || !result[1])
1049     {
1050       mpi_free (result[0]);
1051       mpi_free (result[1]);
1052       return GPG_ERR_ENOMEM;
1053     }
1054
1055   /* Success.  */
1056   resarr[0] = result[0];
1057   resarr[1] = result[1];
1058
1059   return 0;
1060 }
1061
1062 /*  input:
1063  *     data[0] : a point kG (ephemeral public key)
1064  *   output:
1065  *     resaddr[0] : shared point kdG
1066  *
1067  *  see ecc_encrypt_raw for details.
1068  */
1069 static gcry_err_code_t
1070 ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
1071                  gcry_mpi_t *skey, int flags)
1072 {
1073   ECC_secret_key sk;
1074   mpi_point_struct R;   /* Result that we return.  */
1075   mpi_point_struct kG;
1076   mpi_ec_t ctx;
1077   gcry_mpi_t r;
1078   int err;
1079
1080   (void)algo;
1081   (void)flags;
1082
1083   *result = NULL;
1084
1085   if (!data || !data[0]
1086       || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4]
1087       || !skey[5] || !skey[6] )
1088     return GPG_ERR_BAD_MPI;
1089
1090   point_init (&kG);
1091   err = _gcry_ecc_os2ec (&kG, data[0]);
1092   if (err)
1093     {
1094       point_free (&kG);
1095       return err;
1096     }
1097
1098   sk.E.model = MPI_EC_WEIERSTRASS;
1099   sk.E.p = skey[0];
1100   sk.E.a = skey[1];
1101   sk.E.b = skey[2];
1102   point_init (&sk.E.G);
1103   err = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
1104   if (err)
1105     {
1106       point_free (&kG);
1107       point_free (&sk.E.G);
1108       return err;
1109     }
1110   sk.E.n = skey[4];
1111   point_init (&sk.Q);
1112   err = _gcry_ecc_os2ec (&sk.Q, skey[5]);
1113   if (err)
1114     {
1115       point_free (&kG);
1116       point_free (&sk.E.G);
1117       point_free (&sk.Q);
1118       return err;
1119     }
1120   sk.d = skey[6];
1121
1122   ctx = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.p, sk.E.a, sk.E.b);
1123
1124   /* R = dkG */
1125   point_init (&R);
1126   _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ctx);
1127
1128   point_free (&kG);
1129
1130   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so:  */
1131   {
1132     gcry_mpi_t x, y;
1133
1134     x = mpi_new (0);
1135     y = mpi_new (0);
1136
1137     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
1138       log_fatal ("ecdh: Failed to get affine coordinates\n");
1139
1140     r = _gcry_ecc_ec2os (x, y, sk.E.p);
1141     mpi_free (x);
1142     mpi_free (y);
1143   }
1144
1145   point_free (&R);
1146   _gcry_mpi_ec_free (ctx);
1147   point_free (&kG);
1148   point_free (&sk.E.G);
1149   point_free (&sk.Q);
1150
1151   if (!r)
1152     return GPG_ERR_ENOMEM;
1153
1154   /* Success.  */
1155
1156   *result = r;
1157
1158   return 0;
1159 }
1160
1161
1162 static unsigned int
1163 ecc_get_nbits (int algo, gcry_mpi_t *pkey)
1164 {
1165   (void)algo;
1166
1167   return mpi_get_nbits (pkey[0]);
1168 }
1169
1170
1171 /* See rsa.c for a description of this function.  */
1172 static gpg_err_code_t
1173 compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
1174 {
1175 #define N_COMPONENTS 6
1176   static const char names[N_COMPONENTS+1] = "pabgnq";
1177   gpg_err_code_t ec = 0;
1178   gcry_sexp_t l1;
1179   gcry_mpi_t values[N_COMPONENTS];
1180   int idx;
1181
1182   /* Clear the values for easier error cleanup.  */
1183   for (idx=0; idx < N_COMPONENTS; idx++)
1184     values[idx] = NULL;
1185
1186   /* Fill values with all provided parameters.  */
1187   for (idx=0; idx < N_COMPONENTS; idx++)
1188     {
1189       l1 = gcry_sexp_find_token (keyparam, names+idx, 1);
1190       if (l1)
1191         {
1192           values[idx] = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
1193           gcry_sexp_release (l1);
1194           if (!values[idx])
1195             {
1196               ec = GPG_ERR_INV_OBJ;
1197               goto leave;
1198             }
1199         }
1200     }
1201
1202   /* Check whether a curve parameter is available and use that to fill
1203      in missing values.  */
1204   l1 = gcry_sexp_find_token (keyparam, "curve", 5);
1205   if (l1)
1206     {
1207       char *curve;
1208       gcry_mpi_t tmpvalues[N_COMPONENTS];
1209
1210       for (idx = 0; idx < N_COMPONENTS; idx++)
1211         tmpvalues[idx] = NULL;
1212
1213       curve = _gcry_sexp_nth_string (l1, 1);
1214       gcry_sexp_release (l1);
1215       if (!curve)
1216         {
1217           ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
1218           goto leave;
1219         }
1220       ec = _gcry_ecc_get_param (curve, tmpvalues);
1221       gcry_free (curve);
1222       if (ec)
1223         goto leave;
1224
1225       for (idx = 0; idx < N_COMPONENTS; idx++)
1226         {
1227           if (!values[idx])
1228             values[idx] = tmpvalues[idx];
1229           else
1230             mpi_free (tmpvalues[idx]);
1231         }
1232     }
1233
1234   /* Check that all parameters are known and normalize all MPIs (that
1235      should not be required but we use an internal function later and
1236      thus we better make 100% sure that they are normalized). */
1237   for (idx = 0; idx < N_COMPONENTS; idx++)
1238     if (!values[idx])
1239       {
1240         ec = GPG_ERR_NO_OBJ;
1241         goto leave;
1242       }
1243     else
1244       _gcry_mpi_normalize (values[idx]);
1245
1246   /* Hash them all.  */
1247   for (idx = 0; idx < N_COMPONENTS; idx++)
1248     {
1249       char buf[30];
1250       unsigned char *rawmpi;
1251       unsigned int rawmpilen;
1252
1253       rawmpi = _gcry_mpi_get_buffer (values[idx], &rawmpilen, NULL);
1254       if (!rawmpi)
1255         {
1256           ec = gpg_err_code_from_syserror ();
1257           goto leave;
1258         }
1259       snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], rawmpilen);
1260       gcry_md_write (md, buf, strlen (buf));
1261       gcry_md_write (md, rawmpi, rawmpilen);
1262       gcry_md_write (md, ")", 1);
1263       gcry_free (rawmpi);
1264     }
1265
1266  leave:
1267   for (idx = 0; idx < N_COMPONENTS; idx++)
1268     _gcry_mpi_release (values[idx]);
1269
1270   return ec;
1271 #undef N_COMPONENTS
1272 }
1273
1274
1275 \f
1276 /*
1277    Low-level API helper functions.
1278  */
1279
1280 /* This is the wroker function for gcry_pubkey_get_sexp for ECC
1281    algorithms.  Note that the caller has already stored NULL at
1282    R_SEXP.  */
1283 gpg_err_code_t
1284 _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
1285 {
1286   gpg_err_code_t rc;
1287   gcry_mpi_t mpi_G = NULL;
1288   gcry_mpi_t mpi_Q = NULL;
1289
1290   if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n)
1291     return GPG_ERR_BAD_CRYPT_CTX;
1292
1293   if (mode == GCRY_PK_GET_SECKEY && !ec->d)
1294     return GPG_ERR_NO_SECKEY;
1295
1296   /* Compute the public point if it is missing.  */
1297   if (!ec->Q && ec->d)
1298     {
1299       ec->Q = gcry_mpi_point_new (0);
1300       _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec);
1301     }
1302
1303   /* Encode G and Q.  */
1304   mpi_G = _gcry_mpi_ec_ec2os (ec->G, ec);
1305   if (!mpi_G)
1306     {
1307       rc = GPG_ERR_BROKEN_PUBKEY;
1308       goto leave;
1309     }
1310   if (!ec->Q)
1311     {
1312       rc = GPG_ERR_BAD_CRYPT_CTX;
1313       goto leave;
1314     }
1315   mpi_Q = _gcry_mpi_ec_ec2os (ec->Q, ec);
1316   if (!mpi_Q)
1317     {
1318       rc = GPG_ERR_BROKEN_PUBKEY;
1319       goto leave;
1320     }
1321
1322   /* Fixme: We should return a curve name instead of the parameters if
1323      if know that they match a curve.  */
1324
1325   if (ec->d && (!mode || mode == GCRY_PK_GET_SECKEY))
1326     {
1327       /* Let's return a private key. */
1328       rc = gpg_err_code
1329         (gcry_sexp_build
1330          (r_sexp, NULL,
1331           "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))",
1332           ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q, ec->d));
1333     }
1334   else if (ec->Q)
1335     {
1336       /* Let's return a public key.  */
1337       rc = gpg_err_code
1338         (gcry_sexp_build
1339          (r_sexp, NULL,
1340           "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))",
1341           ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q));
1342     }
1343   else
1344     rc = GPG_ERR_BAD_CRYPT_CTX;
1345
1346  leave:
1347   mpi_free (mpi_Q);
1348   mpi_free (mpi_G);
1349   return rc;
1350 }
1351
1352
1353 \f
1354 /*
1355      Self-test section.
1356  */
1357
1358
1359 static gpg_err_code_t
1360 selftests_ecdsa (selftest_report_func_t report)
1361 {
1362   const char *what;
1363   const char *errtxt;
1364
1365   what = "low-level";
1366   errtxt = NULL; /*selftest ();*/
1367   if (errtxt)
1368     goto failed;
1369
1370   /* FIXME:  need more tests.  */
1371
1372   return 0; /* Succeeded. */
1373
1374  failed:
1375   if (report)
1376     report ("pubkey", GCRY_PK_ECDSA, what, errtxt);
1377   return GPG_ERR_SELFTEST_FAILED;
1378 }
1379
1380
1381 /* Run a full self-test for ALGO and return 0 on success.  */
1382 static gpg_err_code_t
1383 run_selftests (int algo, int extended, selftest_report_func_t report)
1384 {
1385   gpg_err_code_t ec;
1386
1387   (void)extended;
1388
1389   switch (algo)
1390     {
1391     case GCRY_PK_ECDSA:
1392       ec = selftests_ecdsa (report);
1393       break;
1394     default:
1395       ec = GPG_ERR_PUBKEY_ALGO;
1396       break;
1397
1398     }
1399   return ec;
1400 }
1401
1402
1403
1404 \f
1405 static const char *ecdsa_names[] =
1406   {
1407     "ecdsa",
1408     "ecc",
1409     NULL,
1410   };
1411 static const char *ecdh_names[] =
1412   {
1413     "ecdh",
1414     "ecc",
1415     NULL,
1416   };
1417
1418 gcry_pk_spec_t _gcry_pubkey_spec_ecdsa =
1419   {
1420     "ECDSA", ecdsa_names,
1421     "pabgnq", "pabgnqd", "", "rs", "pabgnq",
1422     GCRY_PK_USAGE_SIGN,
1423     ecc_generate,
1424     ecc_check_secret_key,
1425     NULL,
1426     NULL,
1427     ecc_sign,
1428     ecc_verify,
1429     ecc_get_nbits
1430   };
1431
1432 gcry_pk_spec_t _gcry_pubkey_spec_ecdh =
1433   {
1434     "ECDH", ecdh_names,
1435     "pabgnq", "pabgnqd", "se", "", "pabgnq",
1436     GCRY_PK_USAGE_ENCR,
1437     ecc_generate,
1438     ecc_check_secret_key,
1439     ecc_encrypt_raw,
1440     ecc_decrypt_raw,
1441     NULL,
1442     NULL,
1443     ecc_get_nbits
1444   };
1445
1446
1447 pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa =
1448   {
1449     run_selftests,
1450     ecc_generate_ext,
1451     compute_keygrip,
1452     _gcry_ecc_get_param,
1453     _gcry_ecc_get_curve,
1454     _gcry_ecc_get_param_sexp
1455   };