ecc: Simplify the compliant point generation.
[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   - Split this up into several files.  For example the curve
51     management and gcry_mpi_ec_new are independent of the actual ECDSA
52     implementation.  This will also help to support optimized versions
53     of some curves.
54
55 */
56
57
58 #include <config.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <errno.h>
63
64 #include "g10lib.h"
65 #include "mpi.h"
66 #include "cipher.h"
67 #include "context.h"
68 #include "ec-context.h"
69 #include "pubkey-internal.h"
70
71 /* Definition of a curve.  */
72 typedef struct
73 {
74   gcry_mpi_t p;         /* Prime specifying the field GF(p).  */
75   gcry_mpi_t a;         /* First coefficient of the Weierstrass equation.  */
76   gcry_mpi_t b;         /* Second coefficient of the Weierstrass equation.  */
77   mpi_point_struct G;   /* Base point (generator).  */
78   gcry_mpi_t n;         /* Order of G.  */
79   const char *name;     /* Name of the curve or NULL.  */
80 } elliptic_curve_t;
81
82
83 typedef struct
84 {
85   elliptic_curve_t E;
86   mpi_point_struct Q; /* Q = [d]G  */
87 } ECC_public_key;
88
89 typedef struct
90 {
91   elliptic_curve_t E;
92   mpi_point_struct Q;
93   gcry_mpi_t d;
94 } ECC_secret_key;
95
96
97 /* This tables defines aliases for curve names.  */
98 static const struct
99 {
100   const char *name;  /* Our name.  */
101   const char *other; /* Other name. */
102 } curve_aliases[] =
103   {
104     { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID  */
105     { "NIST P-192", "prime192v1" },          /* X9.62 name.  */
106     { "NIST P-192", "secp192r1"  },          /* SECP name.  */
107     { "NIST P-192", "nistp192"   },          /* rfc5656.  */
108
109     { "NIST P-224", "secp224r1" },
110     { "NIST P-224", "1.3.132.0.33" },        /* SECP OID.  */
111     { "NIST P-224", "nistp224"   },          /* rfc5656.  */
112
113     { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1.  */
114     { "NIST P-256", "prime256v1" },
115     { "NIST P-256", "secp256r1"  },
116     { "NIST P-256", "nistp256"   },          /* rfc5656.  */
117
118     { "NIST P-384", "secp384r1" },
119     { "NIST P-384", "1.3.132.0.34" },
120     { "NIST P-384", "nistp384"   },          /* rfc5656.  */
121
122     { "NIST P-521", "secp521r1" },
123     { "NIST P-521", "1.3.132.0.35" },
124     { "NIST P-521", "nistp521"   },          /* rfc5656.  */
125
126     { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" },
127     { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" },
128     { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" },
129     { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" },
130     { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" },
131     { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"},
132     { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"},
133
134     { NULL, NULL}
135   };
136
137 typedef struct   {
138   const char *desc;           /* Description of the curve.  */
139   unsigned int nbits;         /* Number of bits.  */
140   unsigned int fips:1;        /* True if this is a FIPS140-2 approved curve. */
141   const char  *p;             /* Order of the prime field.  */
142   const char *a, *b;          /* The coefficients. */
143   const char *n;              /* The order of the base point.  */
144   const char *g_x, *g_y;      /* Base point.  */
145 } ecc_domain_parms_t;
146
147 /* This static table defines all available curves.  */
148 static const ecc_domain_parms_t domain_parms[] =
149   {
150     {
151       "NIST P-192", 192, 1,
152       "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
153       "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
154       "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
155       "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
156
157       "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
158       "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
159     },
160     {
161       "NIST P-224", 224, 1,
162       "0xffffffffffffffffffffffffffffffff000000000000000000000001",
163       "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
164       "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
165       "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
166
167       "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
168       "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
169     },
170     {
171       "NIST P-256", 256, 1,
172       "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
173       "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
174       "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
175       "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
176
177       "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
178       "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
179     },
180     {
181       "NIST P-384", 384, 1,
182       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
183       "ffffffff0000000000000000ffffffff",
184       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
185       "ffffffff0000000000000000fffffffc",
186       "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
187       "c656398d8a2ed19d2a85c8edd3ec2aef",
188       "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
189       "581a0db248b0a77aecec196accc52973",
190
191       "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
192       "5502f25dbf55296c3a545e3872760ab7",
193       "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
194       "0a60b1ce1d7e819d7a431d7c90ea0e5f"
195     },
196     {
197       "NIST P-521", 521, 1,
198       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
199       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
200       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
201       "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
202       "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
203       "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
204       "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
205       "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
206
207       "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
208       "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
209       "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
210       "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
211     },
212
213     { "brainpoolP160r1", 160, 0,
214       "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
215       "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
216       "0x1e589a8595423412134faa2dbdec95c8d8675e58",
217       "0xe95e4a5f737059dc60df5991d45029409e60fc09",
218       "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
219       "0x1667cb477a1a8ec338f94741669c976316da6321"
220     },
221
222     { "brainpoolP192r1", 192, 0,
223       "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
224       "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
225       "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
226       "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
227       "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
228       "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
229     },
230
231     { "brainpoolP224r1", 224, 0,
232       "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
233       "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
234       "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
235       "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
236       "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
237       "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
238     },
239
240     { "brainpoolP256r1", 256, 0,
241       "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
242       "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
243       "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
244       "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
245       "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
246       "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
247     },
248
249     { "brainpoolP320r1", 320, 0,
250       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
251       "fcd412b1f1b32e27",
252       "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
253       "92f375a97d860eb4",
254       "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981"
255       "6f5eb4ac8fb1f1a6",
256       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9"
257       "8691555b44c59311",
258       "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
259       "10af8d0d39e20611",
260       "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
261       "d35245d1692e8ee1"
262     },
263
264     { "brainpoolP384r1", 384, 0,
265       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
266       "acd3a729901d1a71874700133107ec53",
267       "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
268       "8aa5814a503ad4eb04a8c7dd22ce2826",
269       "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5"
270       "7cb4390295dbc9943ab78696fa504c11",
271       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7"
272       "cf3ab6af6b7fc3103b883202e9046565",
273       "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
274       "e826e03436d646aaef87b2e247d4af1e",
275       "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
276       "0e4646217791811142820341263c5315"
277     },
278
279     { "brainpoolP512r1", 512, 0,
280       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
281       "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
282       "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
283       "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca",
284       "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7"
285       "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723",
286       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870"
287       "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
288       "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
289       "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
290       "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
291       "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
292     },
293
294     { NULL, 0, 0, NULL, NULL, NULL, NULL }
295   };
296
297
298 /* Registered progress function and its callback value. */
299 static void (*progress_cb) (void *, const char*, int, int, int);
300 static void *progress_cb_data;
301
302
303 #define point_init(a)  _gcry_mpi_point_init ((a))
304 #define point_free(a)  _gcry_mpi_point_free_parts ((a))
305
306
307 \f
308 /* Local prototypes. */
309 static void test_keys (ECC_secret_key * sk, unsigned int nbits);
310 static int check_secret_key (ECC_secret_key * sk);
311 static gpg_err_code_t sign (gcry_mpi_t input, ECC_secret_key *skey,
312                             gcry_mpi_t r, gcry_mpi_t s);
313 static gpg_err_code_t verify (gcry_mpi_t input, ECC_public_key *pkey,
314                               gcry_mpi_t r, gcry_mpi_t s);
315
316
317 static gcry_mpi_t gen_y_2 (gcry_mpi_t x, elliptic_curve_t * base);
318
319
320
321 \f
322 void
323 _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
324                                             int, int, int),
325                                 void *cb_data)
326 {
327   progress_cb = cb;
328   progress_cb_data = cb_data;
329 }
330
331 /* static void */
332 /* progress (int c) */
333 /* { */
334 /*   if (progress_cb) */
335 /*     progress_cb (progress_cb_data, "pk_ecc", c, 0, 0); */
336 /* } */
337
338
339 \f
340
341 /* Set the value from S into D.  */
342 static void
343 point_set (mpi_point_t d, mpi_point_t s)
344 {
345   mpi_set (d->x, s->x);
346   mpi_set (d->y, s->y);
347   mpi_set (d->z, s->z);
348 }
349
350
351 /*
352  * Release a curve object.
353  */
354 static void
355 curve_free (elliptic_curve_t *E)
356 {
357   mpi_free (E->p); E->p = NULL;
358   mpi_free (E->a); E->a = NULL;
359   mpi_free (E->b);  E->b = NULL;
360   point_free (&E->G);
361   mpi_free (E->n);  E->n = NULL;
362 }
363
364
365 /*
366  * Return a copy of a curve object.
367  */
368 static elliptic_curve_t
369 curve_copy (elliptic_curve_t E)
370 {
371   elliptic_curve_t R;
372
373   R.p = mpi_copy (E.p);
374   R.a = mpi_copy (E.a);
375   R.b = mpi_copy (E.b);
376   point_init (&R.G);
377   point_set (&R.G, &E.G);
378   R.n = mpi_copy (E.n);
379
380   return R;
381 }
382
383
384 /* Helper to scan a hex string. */
385 static gcry_mpi_t
386 scanval (const char *string)
387 {
388   gpg_error_t err;
389   gcry_mpi_t val;
390
391   err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
392   if (err)
393     log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err));
394   return val;
395 }
396
397
398
399 \f
400
401 /****************
402  * Solve the right side of the equation that defines a curve.
403  */
404 static gcry_mpi_t
405 gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base)
406 {
407   gcry_mpi_t three, x_3, axb, y;
408
409   three = mpi_alloc_set_ui (3);
410   x_3 = mpi_new (0);
411   axb = mpi_new (0);
412   y   = mpi_new (0);
413
414   mpi_powm (x_3, x, three, base->p);
415   mpi_mulm (axb, base->a, x, base->p);
416   mpi_addm (axb, axb, base->b, base->p);
417   mpi_addm (y, x_3, axb, base->p);
418
419   mpi_free (x_3);
420   mpi_free (axb);
421   mpi_free (three);
422   return y; /* The quadratic value of the coordinate if it exist. */
423 }
424
425
426 /* Generate the crypto system setup.  This function takes the NAME of
427    a curve or the desired number of bits and stores at R_CURVE the
428    parameters of the named curve or those of a suitable curve.  If
429    R_NBITS is not NULL, the chosen number of bits is stored there.  */
430 static gpg_err_code_t
431 fill_in_curve (unsigned int nbits, const char *name,
432                elliptic_curve_t *curve, unsigned int *r_nbits)
433 {
434   int idx, aliasno;
435   const char *resname = NULL; /* Set to a found curve name.  */
436
437   if (name)
438     {
439       /* First check our native curves.  */
440       for (idx = 0; domain_parms[idx].desc; idx++)
441         if (!strcmp (name, domain_parms[idx].desc))
442           {
443             resname = domain_parms[idx].desc;
444             break;
445           }
446       /* If not found consult the alias table.  */
447       if (!domain_parms[idx].desc)
448         {
449           for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
450             if (!strcmp (name, curve_aliases[aliasno].other))
451               break;
452           if (curve_aliases[aliasno].name)
453             {
454               for (idx = 0; domain_parms[idx].desc; idx++)
455                 if (!strcmp (curve_aliases[aliasno].name,
456                              domain_parms[idx].desc))
457                   {
458                     resname = domain_parms[idx].desc;
459                     break;
460                   }
461             }
462         }
463     }
464   else
465     {
466       for (idx = 0; domain_parms[idx].desc; idx++)
467         if (nbits == domain_parms[idx].nbits)
468           break;
469     }
470   if (!domain_parms[idx].desc)
471     return GPG_ERR_INV_VALUE;
472
473   /* In fips mode we only support NIST curves.  Note that it is
474      possible to bypass this check by specifying the curve parameters
475      directly.  */
476   if (fips_mode () && !domain_parms[idx].fips )
477     return GPG_ERR_NOT_SUPPORTED;
478
479   if (r_nbits)
480     *r_nbits = domain_parms[idx].nbits;
481   curve->p = scanval (domain_parms[idx].p);
482   curve->a = scanval (domain_parms[idx].a);
483   curve->b = scanval (domain_parms[idx].b);
484   curve->n = scanval (domain_parms[idx].n);
485   curve->G.x = scanval (domain_parms[idx].g_x);
486   curve->G.y = scanval (domain_parms[idx].g_y);
487   curve->G.z = mpi_alloc_set_ui (1);
488   curve->name = resname;
489
490   return 0;
491 }
492
493
494 /*
495  * First obtain the setup.  Over the finite field randomize an scalar
496  * secret value, and calculate the public point.
497  */
498 static gpg_err_code_t
499 generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
500               int transient_key,
501               gcry_mpi_t g_x, gcry_mpi_t g_y,
502               gcry_mpi_t q_x, gcry_mpi_t q_y,
503               const char **r_usedcurve)
504 {
505   gpg_err_code_t err;
506   elliptic_curve_t E;
507   mpi_point_struct Q;
508   mpi_ec_t ctx;
509   gcry_random_level_t random_level;
510
511   *r_usedcurve = NULL;
512
513   err = fill_in_curve (nbits, name, &E, &nbits);
514   if (err)
515     return err;
516
517   if (DBG_CIPHER)
518     {
519       log_mpidump ("ecgen curve  p", E.p);
520       log_mpidump ("ecgen curve  a", E.a);
521       log_mpidump ("ecgen curve  b", E.b);
522       log_mpidump ("ecgen curve  n", E.n);
523       log_mpidump ("ecgen curve Gx", E.G.x);
524       log_mpidump ("ecgen curve Gy", E.G.y);
525       log_mpidump ("ecgen curve Gz", E.G.z);
526       if (E.name)
527         log_debug   ("ecgen curve used: %s\n", E.name);
528     }
529
530   random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
531   sk->d = _gcry_dsa_gen_k (E.n, random_level);
532
533   /* Compute Q.  */
534   point_init (&Q);
535   ctx = _gcry_mpi_ec_p_internal_new (E.p, E.a);
536   _gcry_mpi_ec_mul_point (&Q, sk->d, &E.G, ctx);
537
538   /* Copy the stuff to the key structures. */
539   sk->E.p = mpi_copy (E.p);
540   sk->E.a = mpi_copy (E.a);
541   sk->E.b = mpi_copy (E.b);
542   point_init (&sk->E.G);
543   point_set (&sk->E.G, &E.G);
544   sk->E.n = mpi_copy (E.n);
545   point_init (&sk->Q);
546
547   /* We want the Q=(x,y) be a "compliant key" in terms of the
548    * http://tools.ietf.org/html/draft-jivsov-ecc-compact, which simply
549    * means that we choose either Q=(x,y) or -Q=(x,p-y) such that we
550    * end up with the min(y,p-y) as the y coordinate.  Such a public
551    * key allows the most efficient compression: y can simply be
552    * dropped because we know that it's a minimum of the two
553    * possibilities without any loss of security.  */
554   {
555     gcry_mpi_t x, y, p_y;
556     const unsigned int pbits = mpi_get_nbits (E.p);
557
558     x = mpi_new (pbits);
559     y = mpi_new (pbits);
560     p_y = mpi_new (pbits);
561
562     if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx))
563       log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
564
565     mpi_sub (p_y, E.p, y);      /* p_y = p - y */
566
567     if (mpi_cmp (p_y, y) < 0)   /* p - y < p */
568       {
569         /* We need to end up with -Q; this assures that new Q's y is
570            the smallest one */
571         mpi_sub (sk->d, E.n, sk->d);   /* d = order - d */
572         gcry_mpi_point_snatch_set (&sk->Q, x, p_y, mpi_alloc_set_ui (1));
573
574         if (DBG_CIPHER)
575           log_debug ("ecgen converted Q to a compliant point\n");
576       }
577     else /* p - y >= p */
578       {
579         /* No change is needed exactly 50% of the time: just copy. */
580         point_set (&sk->Q, &Q);
581         if (DBG_CIPHER)
582           log_debug ("ecgen didn't need to convert Q to a compliant point\n");
583
584         mpi_free (p_y);
585         mpi_free (x);
586       }
587     mpi_free (y);
588   }
589
590   /* We also return copies of G and Q in affine coordinates if
591      requested.  */
592   if (g_x && g_y)
593     {
594       if (_gcry_mpi_ec_get_affine (g_x, g_y, &sk->E.G, ctx))
595         log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "G");
596     }
597   if (q_x && q_y)
598     {
599       if (_gcry_mpi_ec_get_affine (q_x, q_y, &sk->Q, ctx))
600         log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
601     }
602   _gcry_mpi_ec_free (ctx);
603
604   point_free (&Q);
605
606   *r_usedcurve = E.name;
607   curve_free (&E);
608
609   /* Now we can test our keys (this should never fail!).  */
610   test_keys (sk, nbits - 64);
611
612   return 0;
613 }
614
615
616 /*
617  * To verify correct skey it use a random information.
618  * First, encrypt and decrypt this dummy value,
619  * test if the information is recuperated.
620  * Second, test with the sign and verify functions.
621  */
622 static void
623 test_keys (ECC_secret_key *sk, unsigned int nbits)
624 {
625   ECC_public_key pk;
626   gcry_mpi_t test = mpi_new (nbits);
627   mpi_point_struct R_;
628   gcry_mpi_t c = mpi_new (nbits);
629   gcry_mpi_t out = mpi_new (nbits);
630   gcry_mpi_t r = mpi_new (nbits);
631   gcry_mpi_t s = mpi_new (nbits);
632
633   if (DBG_CIPHER)
634     log_debug ("Testing key.\n");
635
636   point_init (&R_);
637
638   pk.E = curve_copy (sk->E);
639   point_init (&pk.Q);
640   point_set (&pk.Q, &sk->Q);
641
642   gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
643
644   if (sign (test, sk, r, s) )
645     log_fatal ("ECDSA operation: sign failed\n");
646
647   if (verify (test, &pk, r, s))
648     {
649       log_fatal ("ECDSA operation: sign, verify failed\n");
650     }
651
652   if (DBG_CIPHER)
653     log_debug ("ECDSA operation: sign, verify ok.\n");
654
655   point_free (&pk.Q);
656   curve_free (&pk.E);
657
658   point_free (&R_);
659   mpi_free (s);
660   mpi_free (r);
661   mpi_free (out);
662   mpi_free (c);
663   mpi_free (test);
664 }
665
666
667 /*
668  * To check the validity of the value, recalculate the correspondence
669  * between the public value and the secret one.
670  */
671 static int
672 check_secret_key (ECC_secret_key * sk)
673 {
674   int rc = 1;
675   mpi_point_struct Q;
676   gcry_mpi_t y_2, y2;
677   mpi_ec_t ctx = NULL;
678
679   point_init (&Q);
680
681   /* ?primarity test of 'p' */
682   /*  (...) //!! */
683   /* G in E(F_p) */
684   y_2 = gen_y_2 (sk->E.G.x, &sk->E);   /*  y^2=x^3+a*x+b */
685   y2 = mpi_alloc (0);
686   mpi_mulm (y2, sk->E.G.y, sk->E.G.y, sk->E.p);      /*  y^2=y*y */
687   if (mpi_cmp (y_2, y2))
688     {
689       if (DBG_CIPHER)
690         log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n");
691       goto leave;
692     }
693   /* G != PaI */
694   if (!mpi_cmp_ui (sk->E.G.z, 0))
695     {
696       if (DBG_CIPHER)
697         log_debug ("Bad check: 'G' cannot be Point at Infinity!\n");
698       goto leave;
699     }
700
701   ctx = _gcry_mpi_ec_p_internal_new (sk->E.p, sk->E.a);
702
703   _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx);
704   if (mpi_cmp_ui (Q.z, 0))
705     {
706       if (DBG_CIPHER)
707         log_debug ("check_secret_key: E is not a curve of order n\n");
708       goto leave;
709     }
710   /* pubkey cannot be PaI */
711   if (!mpi_cmp_ui (sk->Q.z, 0))
712     {
713       if (DBG_CIPHER)
714         log_debug ("Bad check: Q can not be a Point at Infinity!\n");
715       goto leave;
716     }
717   /* pubkey = [d]G over E */
718   _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx);
719   if ((Q.x == sk->Q.x) && (Q.y == sk->Q.y) && (Q.z == sk->Q.z))
720     {
721       if (DBG_CIPHER)
722         log_debug
723           ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
724       goto leave;
725     }
726   rc = 0; /* Okay.  */
727
728  leave:
729   _gcry_mpi_ec_free (ctx);
730   mpi_free (y2);
731   mpi_free (y_2);
732   point_free (&Q);
733   return rc;
734 }
735
736
737 /*
738  * Return the signature struct (r,s) from the message hash.  The caller
739  * must have allocated R and S.
740  */
741 static gpg_err_code_t
742 sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s)
743 {
744   gpg_err_code_t err = 0;
745   gcry_mpi_t k, dr, sum, k_1, x;
746   mpi_point_struct I;
747   mpi_ec_t ctx;
748
749   if (DBG_CIPHER)
750     log_mpidump ("ecdsa sign hash  ", input );
751
752   k = NULL;
753   dr = mpi_alloc (0);
754   sum = mpi_alloc (0);
755   k_1 = mpi_alloc (0);
756   x = mpi_alloc (0);
757   point_init (&I);
758
759   mpi_set_ui (s, 0);
760   mpi_set_ui (r, 0);
761
762   ctx = _gcry_mpi_ec_p_internal_new (skey->E.p, skey->E.a);
763
764   while (!mpi_cmp_ui (s, 0)) /* s == 0 */
765     {
766       while (!mpi_cmp_ui (r, 0)) /* r == 0 */
767         {
768           /* Note, that we are guaranteed to enter this loop at least
769              once because r has been intialized to 0.  We can't use a
770              do_while because we want to keep the value of R even if S
771              has to be recomputed.  */
772           mpi_free (k);
773           k = _gcry_dsa_gen_k (skey->E.n, GCRY_STRONG_RANDOM);
774           _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx);
775           if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx))
776             {
777               if (DBG_CIPHER)
778                 log_debug ("ecc sign: Failed to get affine coordinates\n");
779               err = GPG_ERR_BAD_SIGNATURE;
780               goto leave;
781             }
782           mpi_mod (r, x, skey->E.n);  /* r = x mod n */
783         }
784       mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n  */
785       mpi_addm (sum, input, dr, skey->E.n); /* sum = hash + (d*r) mod n  */
786       mpi_invm (k_1, k, skey->E.n);         /* k_1 = k^(-1) mod n  */
787       mpi_mulm (s, k_1, sum, skey->E.n);    /* s = k^(-1)*(hash+(d*r)) mod n */
788     }
789
790   if (DBG_CIPHER)
791     {
792       log_mpidump ("ecdsa sign result r ", r);
793       log_mpidump ("ecdsa sign result s ", s);
794     }
795
796  leave:
797   _gcry_mpi_ec_free (ctx);
798   point_free (&I);
799   mpi_free (x);
800   mpi_free (k_1);
801   mpi_free (sum);
802   mpi_free (dr);
803   mpi_free (k);
804
805   return err;
806 }
807
808
809 /*
810  * Check if R and S verifies INPUT.
811  */
812 static gpg_err_code_t
813 verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s)
814 {
815   gpg_err_code_t err = 0;
816   gcry_mpi_t h, h1, h2, x, y;
817   mpi_point_struct Q, Q1, Q2;
818   mpi_ec_t ctx;
819
820   if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) )
821     return GPG_ERR_BAD_SIGNATURE; /* Assertion  0 < r < n  failed.  */
822   if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, pkey->E.n) < 0) )
823     return GPG_ERR_BAD_SIGNATURE; /* Assertion  0 < s < n  failed.  */
824
825   h  = mpi_alloc (0);
826   h1 = mpi_alloc (0);
827   h2 = mpi_alloc (0);
828   x = mpi_alloc (0);
829   y = mpi_alloc (0);
830   point_init (&Q);
831   point_init (&Q1);
832   point_init (&Q2);
833
834   ctx = _gcry_mpi_ec_p_internal_new (pkey->E.p, pkey->E.a);
835
836   /* h  = s^(-1) (mod n) */
837   mpi_invm (h, s, pkey->E.n);
838 /*   log_mpidump ("   h", h); */
839   /* h1 = hash * s^(-1) (mod n) */
840   mpi_mulm (h1, input, h, pkey->E.n);
841 /*   log_mpidump ("  h1", h1); */
842   /* Q1 = [ hash * s^(-1) ]G  */
843   _gcry_mpi_ec_mul_point (&Q1, h1, &pkey->E.G, ctx);
844 /*   log_mpidump ("Q1.x", Q1.x); */
845 /*   log_mpidump ("Q1.y", Q1.y); */
846 /*   log_mpidump ("Q1.z", Q1.z); */
847   /* h2 = r * s^(-1) (mod n) */
848   mpi_mulm (h2, r, h, pkey->E.n);
849 /*   log_mpidump ("  h2", h2); */
850   /* Q2 = [ r * s^(-1) ]Q */
851   _gcry_mpi_ec_mul_point (&Q2, h2, &pkey->Q, ctx);
852 /*   log_mpidump ("Q2.x", Q2.x); */
853 /*   log_mpidump ("Q2.y", Q2.y); */
854 /*   log_mpidump ("Q2.z", Q2.z); */
855   /* Q  = ([hash * s^(-1)]G) + ([r * s^(-1)]Q) */
856   _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ctx);
857 /*   log_mpidump (" Q.x", Q.x); */
858 /*   log_mpidump (" Q.y", Q.y); */
859 /*   log_mpidump (" Q.z", Q.z); */
860
861   if (!mpi_cmp_ui (Q.z, 0))
862     {
863       if (DBG_CIPHER)
864           log_debug ("ecc verify: Rejected\n");
865       err = GPG_ERR_BAD_SIGNATURE;
866       goto leave;
867     }
868   if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx))
869     {
870       if (DBG_CIPHER)
871         log_debug ("ecc verify: Failed to get affine coordinates\n");
872       err = GPG_ERR_BAD_SIGNATURE;
873       goto leave;
874     }
875   mpi_mod (x, x, pkey->E.n); /* x = x mod E_n */
876   if (mpi_cmp (x, r))   /* x != r */
877     {
878       if (DBG_CIPHER)
879         {
880           log_mpidump ("     x", x);
881           log_mpidump ("     y", y);
882           log_mpidump ("     r", r);
883           log_mpidump ("     s", s);
884           log_debug ("ecc verify: Not verified\n");
885         }
886       err = GPG_ERR_BAD_SIGNATURE;
887       goto leave;
888     }
889   if (DBG_CIPHER)
890     log_debug ("ecc verify: Accepted\n");
891
892  leave:
893   _gcry_mpi_ec_free (ctx);
894   point_free (&Q2);
895   point_free (&Q1);
896   point_free (&Q);
897   mpi_free (y);
898   mpi_free (x);
899   mpi_free (h2);
900   mpi_free (h1);
901   mpi_free (h);
902   return err;
903 }
904
905
906 \f
907 /*********************************************
908  **************  interface  ******************
909  *********************************************/
910 static gcry_mpi_t
911 ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p)
912 {
913   gpg_error_t err;
914   int pbytes = (mpi_get_nbits (p)+7)/8;
915   size_t n;
916   unsigned char *buf, *ptr;
917   gcry_mpi_t result;
918
919   buf = gcry_xmalloc ( 1 + 2*pbytes );
920   *buf = 04; /* Uncompressed point.  */
921   ptr = buf+1;
922   err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x);
923   if (err)
924     log_fatal ("mpi_print failed: %s\n", gpg_strerror (err));
925   if (n < pbytes)
926     {
927       memmove (ptr+(pbytes-n), ptr, n);
928       memset (ptr, 0, (pbytes-n));
929     }
930   ptr += pbytes;
931   err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y);
932   if (err)
933     log_fatal ("mpi_print failed: %s\n", gpg_strerror (err));
934   if (n < pbytes)
935     {
936       memmove (ptr+(pbytes-n), ptr, n);
937       memset (ptr, 0, (pbytes-n));
938     }
939
940   err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL);
941   if (err)
942     log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err));
943   gcry_free (buf);
944
945   return result;
946 }
947
948
949 /* Convert POINT into affine coordinates using the context CTX and
950    return a newly allocated MPI.  If the conversion is not possible
951    NULL is returned.  This function won't print an error message.  */
952 gcry_mpi_t
953 _gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ectx)
954 {
955   gcry_mpi_t g_x, g_y, result;
956
957   g_x = mpi_new (0);
958   g_y = mpi_new (0);
959   if (_gcry_mpi_ec_get_affine (g_x, g_y, point, ectx))
960     result = NULL;
961   else
962     result = ec2os (g_x, g_y, ectx->p);
963   mpi_free (g_x);
964   mpi_free (g_y);
965
966   return result;
967 }
968
969
970 /* RESULT must have been initialized and is set on success to the
971    point given by VALUE.  */
972 static gcry_error_t
973 os2ec (mpi_point_t result, gcry_mpi_t value)
974 {
975   gcry_error_t err;
976   size_t n;
977   unsigned char *buf;
978   gcry_mpi_t x, y;
979
980   n = (mpi_get_nbits (value)+7)/8;
981   buf = gcry_xmalloc (n);
982   err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, n, &n, value);
983   if (err)
984     {
985       gcry_free (buf);
986       return err;
987     }
988   if (n < 1)
989     {
990       gcry_free (buf);
991       return GPG_ERR_INV_OBJ;
992     }
993   if (*buf != 4)
994     {
995       gcry_free (buf);
996       return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression.  */
997     }
998   if ( ((n-1)%2) )
999     {
1000       gcry_free (buf);
1001       return GPG_ERR_INV_OBJ;
1002     }
1003   n = (n-1)/2;
1004   err = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL);
1005   if (err)
1006     {
1007       gcry_free (buf);
1008       return err;
1009     }
1010   err = gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL);
1011   gcry_free (buf);
1012   if (err)
1013     {
1014       mpi_free (x);
1015       return err;
1016     }
1017
1018   mpi_set (result->x, x);
1019   mpi_set (result->y, y);
1020   mpi_set_ui (result->z, 1);
1021
1022   mpi_free (x);
1023   mpi_free (y);
1024
1025   return 0;
1026 }
1027
1028
1029 /* Extended version of ecc_generate.  */
1030 static gcry_err_code_t
1031 ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
1032                   const gcry_sexp_t genparms,
1033                   gcry_mpi_t *skey, gcry_mpi_t **retfactors,
1034                   gcry_sexp_t *r_extrainfo)
1035 {
1036   gpg_err_code_t ec;
1037   ECC_secret_key sk;
1038   gcry_mpi_t g_x, g_y, q_x, q_y;
1039   char *curve_name = NULL;
1040   gcry_sexp_t l1;
1041   int transient_key = 0;
1042   const char *usedcurve = NULL;
1043
1044   (void)algo;
1045   (void)evalue;
1046
1047   if (genparms)
1048     {
1049       /* Parse the optional "curve" parameter. */
1050       l1 = gcry_sexp_find_token (genparms, "curve", 0);
1051       if (l1)
1052         {
1053           curve_name = _gcry_sexp_nth_string (l1, 1);
1054           gcry_sexp_release (l1);
1055           if (!curve_name)
1056             return GPG_ERR_INV_OBJ; /* No curve name or value too large. */
1057         }
1058
1059       /* Parse the optional transient-key flag.  */
1060       l1 = gcry_sexp_find_token (genparms, "transient-key", 0);
1061       if (l1)
1062         {
1063           transient_key = 1;
1064           gcry_sexp_release (l1);
1065         }
1066     }
1067
1068   /* NBITS is required if no curve name has been given.  */
1069   if (!nbits && !curve_name)
1070     return GPG_ERR_NO_OBJ; /* No NBITS parameter. */
1071
1072   g_x = mpi_new (0);
1073   g_y = mpi_new (0);
1074   q_x = mpi_new (0);
1075   q_y = mpi_new (0);
1076   ec = generate_key (&sk, nbits, curve_name, transient_key, g_x, g_y, q_x, q_y,
1077                      &usedcurve);
1078   gcry_free (curve_name);
1079   if (ec)
1080     return ec;
1081   if (usedcurve)  /* Fixme: No error return checking.  */
1082     gcry_sexp_build (r_extrainfo, NULL, "(curve %s)", usedcurve);
1083
1084   skey[0] = sk.E.p;
1085   skey[1] = sk.E.a;
1086   skey[2] = sk.E.b;
1087   skey[3] = ec2os (g_x, g_y, sk.E.p);
1088   skey[4] = sk.E.n;
1089   skey[5] = ec2os (q_x, q_y, sk.E.p);
1090   skey[6] = sk.d;
1091
1092   mpi_free (g_x);
1093   mpi_free (g_y);
1094   mpi_free (q_x);
1095   mpi_free (q_y);
1096
1097   point_free (&sk.E.G);
1098   point_free (&sk.Q);
1099
1100   /* Make an empty list of factors.  */
1101   *retfactors = gcry_calloc ( 1, sizeof **retfactors );
1102   if (!*retfactors)
1103     return gpg_err_code_from_syserror ();  /* Fixme: relase mem?  */
1104
1105   if (DBG_CIPHER)
1106     {
1107       log_mpidump ("ecgen result p", skey[0]);
1108       log_mpidump ("ecgen result a", skey[1]);
1109       log_mpidump ("ecgen result b", skey[2]);
1110       log_mpidump ("ecgen result G", skey[3]);
1111       log_mpidump ("ecgen result n", skey[4]);
1112       log_mpidump ("ecgen result Q", skey[5]);
1113       log_mpidump ("ecgen result d", skey[6]);
1114     }
1115
1116   return 0;
1117 }
1118
1119
1120 static gcry_err_code_t
1121 ecc_generate (int algo, unsigned int nbits, unsigned long evalue,
1122               gcry_mpi_t *skey, gcry_mpi_t **retfactors)
1123 {
1124   (void)evalue;
1125   return ecc_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL);
1126 }
1127
1128
1129 /* Return the parameters of the curve NAME in an MPI array.  */
1130 static gcry_err_code_t
1131 ecc_get_param (const char *name, gcry_mpi_t *pkey)
1132 {
1133   gpg_err_code_t err;
1134   unsigned int nbits;
1135   elliptic_curve_t E;
1136   mpi_ec_t ctx;
1137   gcry_mpi_t g_x, g_y;
1138
1139   err = fill_in_curve (0, name, &E, &nbits);
1140   if (err)
1141     return err;
1142
1143   g_x = mpi_new (0);
1144   g_y = mpi_new (0);
1145   ctx = _gcry_mpi_ec_p_internal_new (E.p, E.a);
1146   if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
1147     log_fatal ("ecc get param: Failed to get affine coordinates\n");
1148   _gcry_mpi_ec_free (ctx);
1149   point_free (&E.G);
1150
1151   pkey[0] = E.p;
1152   pkey[1] = E.a;
1153   pkey[2] = E.b;
1154   pkey[3] = ec2os (g_x, g_y, E.p);
1155   pkey[4] = E.n;
1156   pkey[5] = NULL;
1157
1158   mpi_free (g_x);
1159   mpi_free (g_y);
1160
1161   return 0;
1162 }
1163
1164
1165 /* Return the parameters of the curve NAME as an S-expression.  */
1166 static gcry_sexp_t
1167 ecc_get_param_sexp (const char *name)
1168 {
1169   gcry_mpi_t pkey[6];
1170   gcry_sexp_t result;
1171   int i;
1172
1173   if (ecc_get_param (name, pkey))
1174     return NULL;
1175
1176   if (gcry_sexp_build (&result, NULL,
1177                        "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))",
1178                        pkey[0], pkey[1], pkey[2], pkey[3], pkey[4]))
1179     result = NULL;
1180
1181   for (i=0; pkey[i]; i++)
1182     gcry_mpi_release (pkey[i]);
1183
1184   return result;
1185 }
1186
1187
1188 /* Return the name matching the parameters in PKEY.  */
1189 static const char *
1190 ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
1191 {
1192   gpg_err_code_t err;
1193   elliptic_curve_t E;
1194   int idx;
1195   gcry_mpi_t tmp;
1196   const char *result = NULL;
1197
1198   if (r_nbits)
1199     *r_nbits = 0;
1200
1201   if (!pkey)
1202     {
1203       idx = iterator;
1204       if (idx >= 0 && idx < DIM (domain_parms))
1205         {
1206           result = domain_parms[idx].desc;
1207           if (r_nbits)
1208             *r_nbits = domain_parms[idx].nbits;
1209         }
1210       return result;
1211     }
1212
1213   if (!pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4])
1214     return NULL;
1215
1216   E.p = pkey[0];
1217   E.a = pkey[1];
1218   E.b = pkey[2];
1219   point_init (&E.G);
1220   err = os2ec (&E.G, pkey[3]);
1221   if (err)
1222     {
1223       point_free (&E.G);
1224       return NULL;
1225     }
1226   E.n = pkey[4];
1227
1228   for (idx = 0; domain_parms[idx].desc; idx++)
1229     {
1230       tmp = scanval (domain_parms[idx].p);
1231       if (!mpi_cmp (tmp, E.p))
1232         {
1233           mpi_free (tmp);
1234           tmp = scanval (domain_parms[idx].a);
1235           if (!mpi_cmp (tmp, E.a))
1236             {
1237               mpi_free (tmp);
1238               tmp = scanval (domain_parms[idx].b);
1239               if (!mpi_cmp (tmp, E.b))
1240                 {
1241                   mpi_free (tmp);
1242                   tmp = scanval (domain_parms[idx].n);
1243                   if (!mpi_cmp (tmp, E.n))
1244                     {
1245                       mpi_free (tmp);
1246                       tmp = scanval (domain_parms[idx].g_x);
1247                       if (!mpi_cmp (tmp, E.G.x))
1248                         {
1249                           mpi_free (tmp);
1250                           tmp = scanval (domain_parms[idx].g_y);
1251                           if (!mpi_cmp (tmp, E.G.y))
1252                             {
1253                               result = domain_parms[idx].desc;
1254                               if (r_nbits)
1255                                 *r_nbits = domain_parms[idx].nbits;
1256                               break;
1257                             }
1258                         }
1259                     }
1260                 }
1261             }
1262         }
1263       mpi_free (tmp);
1264     }
1265
1266   point_free (&E.G);
1267
1268   return result;
1269 }
1270
1271
1272 static gcry_err_code_t
1273 ecc_check_secret_key (int algo, gcry_mpi_t *skey)
1274 {
1275   gpg_err_code_t err;
1276   ECC_secret_key sk;
1277
1278   (void)algo;
1279
1280   /* FIXME:  This check looks a bit fishy:  Now long is the array?  */
1281   if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5]
1282       || !skey[6])
1283     return GPG_ERR_BAD_MPI;
1284
1285   sk.E.p = skey[0];
1286   sk.E.a = skey[1];
1287   sk.E.b = skey[2];
1288   point_init (&sk.E.G);
1289   err = os2ec (&sk.E.G, skey[3]);
1290   if (err)
1291     {
1292       point_free (&sk.E.G);
1293       return err;
1294     }
1295   sk.E.n = skey[4];
1296   point_init (&sk.Q);
1297   err = os2ec (&sk.Q, skey[5]);
1298   if (err)
1299     {
1300       point_free (&sk.E.G);
1301       point_free (&sk.Q);
1302       return err;
1303     }
1304
1305   sk.d = skey[6];
1306
1307   if (check_secret_key (&sk))
1308     {
1309       point_free (&sk.E.G);
1310       point_free (&sk.Q);
1311       return GPG_ERR_BAD_SECKEY;
1312     }
1313   point_free (&sk.E.G);
1314   point_free (&sk.Q);
1315   return 0;
1316 }
1317
1318
1319 static gcry_err_code_t
1320 ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
1321 {
1322   gpg_err_code_t err;
1323   ECC_secret_key sk;
1324
1325   (void)algo;
1326
1327   if (!data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4]
1328       || !skey[6] )
1329     return GPG_ERR_BAD_MPI;
1330
1331   sk.E.p = skey[0];
1332   sk.E.a = skey[1];
1333   sk.E.b = skey[2];
1334   point_init (&sk.E.G);
1335   err = os2ec (&sk.E.G, skey[3]);
1336   if (err)
1337     {
1338       point_free (&sk.E.G);
1339       return err;
1340     }
1341   sk.E.n = skey[4];
1342   /* Note: We don't have any need for Q here.  */
1343   sk.d = skey[6];
1344
1345   resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
1346   resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
1347   err = sign (data, &sk, resarr[0], resarr[1]);
1348   if (err)
1349     {
1350       mpi_free (resarr[0]);
1351       mpi_free (resarr[1]);
1352       resarr[0] = NULL; /* Mark array as released.  */
1353     }
1354   point_free (&sk.E.G);
1355   return err;
1356 }
1357
1358
1359 static gcry_err_code_t
1360 ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
1361             int (*cmp)(void *, gcry_mpi_t), void *opaquev)
1362 {
1363   gpg_err_code_t err;
1364   ECC_public_key pk;
1365
1366   (void)algo;
1367   (void)cmp;
1368   (void)opaquev;
1369
1370   if (!data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] || !pkey[2]
1371       || !pkey[3] || !pkey[4] || !pkey[5] )
1372     return GPG_ERR_BAD_MPI;
1373
1374   pk.E.p = pkey[0];
1375   pk.E.a = pkey[1];
1376   pk.E.b = pkey[2];
1377   point_init (&pk.E.G);
1378   err = os2ec (&pk.E.G, pkey[3]);
1379   if (err)
1380     {
1381       point_free (&pk.E.G);
1382       return err;
1383     }
1384   pk.E.n = pkey[4];
1385   point_init (&pk.Q);
1386   err = os2ec (&pk.Q, pkey[5]);
1387   if (err)
1388     {
1389       point_free (&pk.E.G);
1390       point_free (&pk.Q);
1391       return err;
1392     }
1393
1394   err = verify (hash, &pk, data[0], data[1]);
1395
1396   point_free (&pk.E.G);
1397   point_free (&pk.Q);
1398   return err;
1399 }
1400
1401
1402 /* ecdh raw is classic 2-round DH protocol published in 1976.
1403  *
1404  * Overview of ecc_encrypt_raw and ecc_decrypt_raw.
1405  *
1406  * As with any PK operation, encrypt version uses a public key and
1407  * decrypt -- private.
1408  *
1409  * Symbols used below:
1410  *     G - field generator point
1411  *     d - private long-term scalar
1412  *    dG - public long-term key
1413  *     k - ephemeral scalar
1414  *    kG - ephemeral public key
1415  *   dkG - shared secret
1416  *
1417  * ecc_encrypt_raw description:
1418  *   input:
1419  *     data[0] : private scalar (k)
1420  *   output:
1421  *     result[0] : shared point (kdG)
1422  *     result[1] : generated ephemeral public key (kG)
1423  *
1424  * ecc_decrypt_raw description:
1425  *   input:
1426  *     data[0] : a point kG (ephemeral public key)
1427  *   output:
1428  *     result[0] : shared point (kdG)
1429  */
1430 static gcry_err_code_t
1431 ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
1432                  gcry_mpi_t *pkey, int flags)
1433 {
1434   ECC_public_key pk;
1435   mpi_ec_t ctx;
1436   gcry_mpi_t result[2];
1437   int err;
1438
1439   (void)algo;
1440   (void)flags;
1441
1442   if (!k
1443       || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4] || !pkey[5])
1444     return GPG_ERR_BAD_MPI;
1445
1446   pk.E.p = pkey[0];
1447   pk.E.a = pkey[1];
1448   pk.E.b = pkey[2];
1449   point_init (&pk.E.G);
1450   err = os2ec (&pk.E.G, pkey[3]);
1451   if (err)
1452     {
1453       point_free (&pk.E.G);
1454       return err;
1455     }
1456   pk.E.n = pkey[4];
1457   point_init (&pk.Q);
1458   err = os2ec (&pk.Q, pkey[5]);
1459   if (err)
1460     {
1461       point_free (&pk.E.G);
1462       point_free (&pk.Q);
1463       return err;
1464     }
1465
1466   ctx = _gcry_mpi_ec_p_internal_new (pk.E.p, pk.E.a);
1467
1468   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
1469   {
1470     mpi_point_struct R;  /* Result that we return.  */
1471     gcry_mpi_t x, y;
1472
1473     x = mpi_new (0);
1474     y = mpi_new (0);
1475
1476     point_init (&R);
1477
1478     /* R = kQ  <=>  R = kdG  */
1479     _gcry_mpi_ec_mul_point (&R, k, &pk.Q, ctx);
1480
1481     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
1482       log_fatal ("ecdh: Failed to get affine coordinates for kdG\n");
1483
1484     result[0] = ec2os (x, y, pk.E.p);
1485
1486     /* R = kG */
1487     _gcry_mpi_ec_mul_point (&R, k, &pk.E.G, ctx);
1488
1489     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
1490       log_fatal ("ecdh: Failed to get affine coordinates for kG\n");
1491
1492     result[1] = ec2os (x, y, pk.E.p);
1493
1494     mpi_free (x);
1495     mpi_free (y);
1496
1497     point_free (&R);
1498   }
1499
1500   _gcry_mpi_ec_free (ctx);
1501   point_free (&pk.E.G);
1502   point_free (&pk.Q);
1503
1504   if (!result[0] || !result[1])
1505     {
1506       mpi_free (result[0]);
1507       mpi_free (result[1]);
1508       return GPG_ERR_ENOMEM;
1509     }
1510
1511   /* Success.  */
1512   resarr[0] = result[0];
1513   resarr[1] = result[1];
1514
1515   return 0;
1516 }
1517
1518 /*  input:
1519  *     data[0] : a point kG (ephemeral public key)
1520  *   output:
1521  *     resaddr[0] : shared point kdG
1522  *
1523  *  see ecc_encrypt_raw for details.
1524  */
1525 static gcry_err_code_t
1526 ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
1527                  gcry_mpi_t *skey, int flags)
1528 {
1529   ECC_secret_key sk;
1530   mpi_point_struct R;   /* Result that we return.  */
1531   mpi_point_struct kG;
1532   mpi_ec_t ctx;
1533   gcry_mpi_t r;
1534   int err;
1535
1536   (void)algo;
1537   (void)flags;
1538
1539   *result = NULL;
1540
1541   if (!data || !data[0]
1542       || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4]
1543       || !skey[5] || !skey[6] )
1544     return GPG_ERR_BAD_MPI;
1545
1546   point_init (&kG);
1547   err = os2ec (&kG, data[0]);
1548   if (err)
1549     {
1550       point_free (&kG);
1551       return err;
1552     }
1553
1554
1555   sk.E.p = skey[0];
1556   sk.E.a = skey[1];
1557   sk.E.b = skey[2];
1558   point_init (&sk.E.G);
1559   err = os2ec (&sk.E.G, skey[3]);
1560   if (err)
1561     {
1562       point_free (&kG);
1563       point_free (&sk.E.G);
1564       return err;
1565     }
1566   sk.E.n = skey[4];
1567   point_init (&sk.Q);
1568   err = os2ec (&sk.Q, skey[5]);
1569   if (err)
1570     {
1571       point_free (&kG);
1572       point_free (&sk.E.G);
1573       point_free (&sk.Q);
1574       return err;
1575     }
1576   sk.d = skey[6];
1577
1578   ctx = _gcry_mpi_ec_p_internal_new (sk.E.p, sk.E.a);
1579
1580   /* R = dkG */
1581   point_init (&R);
1582   _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ctx);
1583
1584   point_free (&kG);
1585
1586   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so:  */
1587   {
1588     gcry_mpi_t x, y;
1589
1590     x = mpi_new (0);
1591     y = mpi_new (0);
1592
1593     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
1594       log_fatal ("ecdh: Failed to get affine coordinates\n");
1595
1596     r = ec2os (x, y, sk.E.p);
1597     mpi_free (x);
1598     mpi_free (y);
1599   }
1600
1601   point_free (&R);
1602   _gcry_mpi_ec_free (ctx);
1603   point_free (&kG);
1604   point_free (&sk.E.G);
1605   point_free (&sk.Q);
1606
1607   if (!r)
1608     return GPG_ERR_ENOMEM;
1609
1610   /* Success.  */
1611
1612   *result = r;
1613
1614   return 0;
1615 }
1616
1617
1618 static unsigned int
1619 ecc_get_nbits (int algo, gcry_mpi_t *pkey)
1620 {
1621   (void)algo;
1622
1623   return mpi_get_nbits (pkey[0]);
1624 }
1625
1626
1627 /* See rsa.c for a description of this function.  */
1628 static gpg_err_code_t
1629 compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
1630 {
1631 #define N_COMPONENTS 6
1632   static const char names[N_COMPONENTS+1] = "pabgnq";
1633   gpg_err_code_t ec = 0;
1634   gcry_sexp_t l1;
1635   gcry_mpi_t values[N_COMPONENTS];
1636   int idx;
1637
1638   /* Clear the values for easier error cleanup.  */
1639   for (idx=0; idx < N_COMPONENTS; idx++)
1640     values[idx] = NULL;
1641
1642   /* Fill values with all provided parameters.  */
1643   for (idx=0; idx < N_COMPONENTS; idx++)
1644     {
1645       l1 = gcry_sexp_find_token (keyparam, names+idx, 1);
1646       if (l1)
1647         {
1648           values[idx] = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
1649           gcry_sexp_release (l1);
1650           if (!values[idx])
1651             {
1652               ec = GPG_ERR_INV_OBJ;
1653               goto leave;
1654             }
1655         }
1656     }
1657
1658   /* Check whether a curve parameter is available and use that to fill
1659      in missing values.  */
1660   l1 = gcry_sexp_find_token (keyparam, "curve", 5);
1661   if (l1)
1662     {
1663       char *curve;
1664       gcry_mpi_t tmpvalues[N_COMPONENTS];
1665
1666       for (idx = 0; idx < N_COMPONENTS; idx++)
1667         tmpvalues[idx] = NULL;
1668
1669       curve = _gcry_sexp_nth_string (l1, 1);
1670       gcry_sexp_release (l1);
1671       if (!curve)
1672         {
1673           ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
1674           goto leave;
1675         }
1676       ec = ecc_get_param (curve, tmpvalues);
1677       gcry_free (curve);
1678       if (ec)
1679         goto leave;
1680
1681       for (idx = 0; idx < N_COMPONENTS; idx++)
1682         {
1683           if (!values[idx])
1684             values[idx] = tmpvalues[idx];
1685           else
1686             mpi_free (tmpvalues[idx]);
1687         }
1688     }
1689
1690   /* Check that all parameters are known and normalize all MPIs (that
1691      should not be required but we use an internal function later and
1692      thus we better make 100% sure that they are normalized). */
1693   for (idx = 0; idx < N_COMPONENTS; idx++)
1694     if (!values[idx])
1695       {
1696         ec = GPG_ERR_NO_OBJ;
1697         goto leave;
1698       }
1699     else
1700       _gcry_mpi_normalize (values[idx]);
1701
1702   /* Hash them all.  */
1703   for (idx = 0; idx < N_COMPONENTS; idx++)
1704     {
1705       char buf[30];
1706       unsigned char *rawmpi;
1707       unsigned int rawmpilen;
1708
1709       rawmpi = _gcry_mpi_get_buffer (values[idx], &rawmpilen, NULL);
1710       if (!rawmpi)
1711         {
1712           ec = gpg_err_code_from_syserror ();
1713           goto leave;
1714         }
1715       snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], rawmpilen);
1716       gcry_md_write (md, buf, strlen (buf));
1717       gcry_md_write (md, rawmpi, rawmpilen);
1718       gcry_md_write (md, ")", 1);
1719       gcry_free (rawmpi);
1720     }
1721
1722  leave:
1723   for (idx = 0; idx < N_COMPONENTS; idx++)
1724     _gcry_mpi_release (values[idx]);
1725
1726   return ec;
1727 #undef N_COMPONENTS
1728 }
1729
1730
1731 \f
1732 /*
1733    Low-level API helper functions.
1734  */
1735
1736 /* Helper to extract an MPI from key parameters.  */
1737 static gpg_err_code_t
1738 mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name)
1739 {
1740   gcry_err_code_t ec = 0;
1741   gcry_sexp_t l1;
1742
1743   l1 = gcry_sexp_find_token (keyparam, name, 0);
1744   if (l1)
1745     {
1746       *r_a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
1747       gcry_sexp_release (l1);
1748       if (!*r_a)
1749         ec = GPG_ERR_INV_OBJ;
1750     }
1751   return ec;
1752 }
1753
1754 /* Helper to extract a point from key parameters.  If no parameter
1755    with NAME is found, the functions tries to find a non-encoded point
1756    by appending ".x", ".y" and ".z" to NAME.  ".z" is in this case
1757    optional and defaults to 1.  */
1758 static gpg_err_code_t
1759 point_from_keyparam (gcry_mpi_point_t *r_a,
1760                      gcry_sexp_t keyparam, const char *name)
1761 {
1762   gcry_err_code_t ec;
1763   gcry_mpi_t a = NULL;
1764   gcry_mpi_point_t point;
1765
1766   ec = mpi_from_keyparam (&a, keyparam, name);
1767   if (ec)
1768     return ec;
1769
1770   if (a)
1771     {
1772       point = gcry_mpi_point_new (0);
1773       ec = os2ec (point, a);
1774       mpi_free (a);
1775       if (ec)
1776         {
1777           gcry_mpi_point_release (point);
1778           return ec;
1779         }
1780     }
1781   else
1782     {
1783       char *tmpname;
1784       gcry_mpi_t x = NULL;
1785       gcry_mpi_t y = NULL;
1786       gcry_mpi_t z = NULL;
1787
1788       tmpname = gcry_malloc (strlen (name) + 2 + 1);
1789       if (!tmpname)
1790         return gpg_err_code_from_syserror ();
1791       strcpy (stpcpy (tmpname, name), ".x");
1792       ec = mpi_from_keyparam (&x, keyparam, tmpname);
1793       if (ec)
1794         {
1795           gcry_free (tmpname);
1796           return ec;
1797         }
1798       strcpy (stpcpy (tmpname, name), ".y");
1799       ec = mpi_from_keyparam (&y, keyparam, tmpname);
1800       if (ec)
1801         {
1802           mpi_free (x);
1803           gcry_free (tmpname);
1804           return ec;
1805         }
1806       strcpy (stpcpy (tmpname, name), ".z");
1807       ec = mpi_from_keyparam (&z, keyparam, tmpname);
1808       if (ec)
1809         {
1810           mpi_free (y);
1811           mpi_free (x);
1812           gcry_free (tmpname);
1813           return ec;
1814         }
1815       if (!z)
1816         z = mpi_set_ui (NULL, 1);
1817       if (x && y)
1818         point = gcry_mpi_point_snatch_set (NULL, x, y, z);
1819       else
1820         {
1821           mpi_free (x);
1822           mpi_free (y);
1823           mpi_free (z);
1824           point = NULL;
1825         }
1826       gcry_free (tmpname);
1827     }
1828
1829   if (point)
1830     *r_a = point;
1831   return 0;
1832 }
1833
1834
1835 /* This function creates a new context for elliptic curve operations.
1836    Either KEYPARAM or CURVENAME must be given.  If both are given and
1837    KEYPARAM has no curve parameter CURVENAME is used to add missing
1838    parameters.  On success 0 is returned and the new context stored at
1839    R_CTX.  On error NULL is stored at R_CTX and an error code is
1840    returned.  The context needs to be released using
1841    gcry_ctx_release.  */
1842 gpg_err_code_t
1843 _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
1844                   gcry_sexp_t keyparam, const char *curvename)
1845 {
1846   gpg_err_code_t errc;
1847   gcry_ctx_t ctx = NULL;
1848   gcry_mpi_t p = NULL;
1849   gcry_mpi_t a = NULL;
1850   gcry_mpi_t b = NULL;
1851   gcry_mpi_point_t G = NULL;
1852   gcry_mpi_t n = NULL;
1853   gcry_mpi_point_t Q = NULL;
1854   gcry_mpi_t d = NULL;
1855   gcry_sexp_t l1;
1856
1857   *r_ctx = NULL;
1858
1859   if (keyparam)
1860     {
1861       errc = mpi_from_keyparam (&p, keyparam, "p");
1862       if (errc)
1863         goto leave;
1864       errc = mpi_from_keyparam (&a, keyparam, "a");
1865       if (errc)
1866         goto leave;
1867       errc = mpi_from_keyparam (&b, keyparam, "b");
1868       if (errc)
1869         goto leave;
1870       errc = point_from_keyparam (&G, keyparam, "g");
1871       if (errc)
1872         goto leave;
1873       errc = mpi_from_keyparam (&n, keyparam, "n");
1874       if (errc)
1875         goto leave;
1876       errc = point_from_keyparam (&Q, keyparam, "q");
1877       if (errc)
1878         goto leave;
1879       errc = mpi_from_keyparam (&d, keyparam, "d");
1880       if (errc)
1881         goto leave;
1882     }
1883
1884
1885   /* Check whether a curve parameter is available and use that to fill
1886      in missing values.  If no curve parameter is available try an
1887      optional provided curvename.  If only the curvename has been
1888      given use that one. */
1889   if (keyparam)
1890     l1 = gcry_sexp_find_token (keyparam, "curve", 5);
1891   else
1892     l1 = NULL;
1893   if (l1 || curvename)
1894     {
1895       char *name;
1896       elliptic_curve_t *E;
1897
1898       if (l1)
1899         {
1900           name = _gcry_sexp_nth_string (l1, 1);
1901           gcry_sexp_release (l1);
1902           if (!name)
1903             {
1904               errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
1905               goto leave;
1906             }
1907         }
1908       else
1909         name = NULL;
1910
1911       E = gcry_calloc (1, sizeof *E);
1912       if (!E)
1913         {
1914           errc = gpg_err_code_from_syserror ();
1915           gcry_free (name);
1916           goto leave;
1917         }
1918
1919       errc = fill_in_curve (0, name? name : curvename, E, NULL);
1920       gcry_free (name);
1921       if (errc)
1922         {
1923           gcry_free (E);
1924           goto leave;
1925         }
1926
1927       if (!p)
1928         {
1929           p = E->p;
1930           E->p = NULL;
1931         }
1932       if (!a)
1933         {
1934           a = E->a;
1935           E->a = NULL;
1936         }
1937       if (!b)
1938         {
1939           b = E->b;
1940           E->b = NULL;
1941         }
1942       if (!G)
1943         {
1944           G = gcry_mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
1945           E->G.x = NULL;
1946           E->G.y = NULL;
1947           E->G.z = NULL;
1948         }
1949       if (!n)
1950         {
1951           n = E->n;
1952           E->n = NULL;
1953         }
1954       curve_free (E);
1955       gcry_free (E);
1956     }
1957
1958   errc = _gcry_mpi_ec_p_new (&ctx, p, a);
1959   if (!errc)
1960     {
1961       mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
1962
1963       if (b)
1964         {
1965           ec->b = b;
1966           b = NULL;
1967         }
1968       if (G)
1969         {
1970           ec->G = G;
1971           G = NULL;
1972         }
1973       if (n)
1974         {
1975           ec->n = n;
1976           n = NULL;
1977         }
1978       if (Q)
1979         {
1980           ec->Q = Q;
1981           Q = NULL;
1982         }
1983       if (d)
1984         {
1985           ec->d = d;
1986           d = NULL;
1987         }
1988
1989       *r_ctx = ctx;
1990     }
1991
1992  leave:
1993   mpi_free (p);
1994   mpi_free (a);
1995   mpi_free (b);
1996   gcry_mpi_point_release (G);
1997   mpi_free (n);
1998   gcry_mpi_point_release (Q);
1999   mpi_free (d);
2000   return errc;
2001 }
2002
2003
2004 /* This is the wroker function for gcry_pubkey_get_sexp for ECC
2005    algorithms.  Note that the caller has already stored NULL at
2006    R_SEXP.  */
2007 gpg_err_code_t
2008 _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
2009 {
2010   gpg_err_code_t rc;
2011   gcry_mpi_t mpi_G = NULL;
2012   gcry_mpi_t mpi_Q = NULL;
2013
2014   if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n)
2015     return GPG_ERR_BAD_CRYPT_CTX;
2016
2017   if (mode == GCRY_PK_GET_SECKEY && !ec->d)
2018     return GPG_ERR_NO_SECKEY;
2019
2020   /* Compute the public point if it is missing.  */
2021   if (!ec->Q && ec->d)
2022     {
2023       ec->Q = gcry_mpi_point_new (0);
2024       _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec);
2025     }
2026
2027   /* Encode G and Q.  */
2028   mpi_G = _gcry_mpi_ec_ec2os (ec->G, ec);
2029   if (!mpi_G)
2030     {
2031       rc = GPG_ERR_BROKEN_PUBKEY;
2032       goto leave;
2033     }
2034   if (!ec->Q)
2035     {
2036       rc = GPG_ERR_BAD_CRYPT_CTX;
2037       goto leave;
2038     }
2039   mpi_Q = _gcry_mpi_ec_ec2os (ec->Q, ec);
2040   if (!mpi_Q)
2041     {
2042       rc = GPG_ERR_BROKEN_PUBKEY;
2043       goto leave;
2044     }
2045
2046   /* Fixme: We should return a curve name instead of the parameters if
2047      if know that they match a curve.  */
2048
2049   if (ec->d && (!mode || mode == GCRY_PK_GET_SECKEY))
2050     {
2051       /* Let's return a private key. */
2052       rc = gpg_err_code
2053         (gcry_sexp_build
2054          (r_sexp, NULL,
2055           "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))",
2056           ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q, ec->d));
2057     }
2058   else if (ec->Q)
2059     {
2060       /* Let's return a public key.  */
2061       rc = gpg_err_code
2062         (gcry_sexp_build
2063          (r_sexp, NULL,
2064           "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))",
2065           ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q));
2066     }
2067   else
2068     rc = GPG_ERR_BAD_CRYPT_CTX;
2069
2070  leave:
2071   mpi_free (mpi_Q);
2072   mpi_free (mpi_G);
2073   return rc;
2074 }
2075
2076
2077 \f
2078 /*
2079      Self-test section.
2080  */
2081
2082
2083 static gpg_err_code_t
2084 selftests_ecdsa (selftest_report_func_t report)
2085 {
2086   const char *what;
2087   const char *errtxt;
2088
2089   what = "low-level";
2090   errtxt = NULL; /*selftest ();*/
2091   if (errtxt)
2092     goto failed;
2093
2094   /* FIXME:  need more tests.  */
2095
2096   return 0; /* Succeeded. */
2097
2098  failed:
2099   if (report)
2100     report ("pubkey", GCRY_PK_ECDSA, what, errtxt);
2101   return GPG_ERR_SELFTEST_FAILED;
2102 }
2103
2104
2105 /* Run a full self-test for ALGO and return 0 on success.  */
2106 static gpg_err_code_t
2107 run_selftests (int algo, int extended, selftest_report_func_t report)
2108 {
2109   gpg_err_code_t ec;
2110
2111   (void)extended;
2112
2113   switch (algo)
2114     {
2115     case GCRY_PK_ECDSA:
2116       ec = selftests_ecdsa (report);
2117       break;
2118     default:
2119       ec = GPG_ERR_PUBKEY_ALGO;
2120       break;
2121
2122     }
2123   return ec;
2124 }
2125
2126
2127
2128 \f
2129 static const char *ecdsa_names[] =
2130   {
2131     "ecdsa",
2132     "ecc",
2133     NULL,
2134   };
2135 static const char *ecdh_names[] =
2136   {
2137     "ecdh",
2138     "ecc",
2139     NULL,
2140   };
2141
2142 gcry_pk_spec_t _gcry_pubkey_spec_ecdsa =
2143   {
2144     "ECDSA", ecdsa_names,
2145     "pabgnq", "pabgnqd", "", "rs", "pabgnq",
2146     GCRY_PK_USAGE_SIGN,
2147     ecc_generate,
2148     ecc_check_secret_key,
2149     NULL,
2150     NULL,
2151     ecc_sign,
2152     ecc_verify,
2153     ecc_get_nbits
2154   };
2155
2156 gcry_pk_spec_t _gcry_pubkey_spec_ecdh =
2157   {
2158     "ECDH", ecdh_names,
2159     "pabgnq", "pabgnqd", "se", "", "pabgnq",
2160     GCRY_PK_USAGE_ENCR,
2161     ecc_generate,
2162     ecc_check_secret_key,
2163     ecc_encrypt_raw,
2164     ecc_decrypt_raw,
2165     NULL,
2166     NULL,
2167     ecc_get_nbits
2168   };
2169
2170
2171 pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa =
2172   {
2173     run_selftests,
2174     ecc_generate_ext,
2175     compute_keygrip,
2176     ecc_get_param,
2177     ecc_get_curve,
2178     ecc_get_param_sexp
2179   };