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