e4b1799e5ac9cd5b2d801b22b32841ca930d6389
[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           int flags, int hashalgo)
1322 {
1323   gpg_err_code_t err;
1324   ECC_secret_key sk;
1325
1326   (void)algo;
1327   (void)flags;
1328   (void)hashalgo;
1329
1330   if (!data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4]
1331       || !skey[6] )
1332     return GPG_ERR_BAD_MPI;
1333
1334   sk.E.p = skey[0];
1335   sk.E.a = skey[1];
1336   sk.E.b = skey[2];
1337   point_init (&sk.E.G);
1338   err = os2ec (&sk.E.G, skey[3]);
1339   if (err)
1340     {
1341       point_free (&sk.E.G);
1342       return err;
1343     }
1344   sk.E.n = skey[4];
1345   /* Note: We don't have any need for Q here.  */
1346   sk.d = skey[6];
1347
1348   resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
1349   resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
1350   err = sign (data, &sk, resarr[0], resarr[1]);
1351   if (err)
1352     {
1353       mpi_free (resarr[0]);
1354       mpi_free (resarr[1]);
1355       resarr[0] = NULL; /* Mark array as released.  */
1356     }
1357   point_free (&sk.E.G);
1358   return err;
1359 }
1360
1361
1362 static gcry_err_code_t
1363 ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
1364             int (*cmp)(void *, gcry_mpi_t), void *opaquev)
1365 {
1366   gpg_err_code_t err;
1367   ECC_public_key pk;
1368
1369   (void)algo;
1370   (void)cmp;
1371   (void)opaquev;
1372
1373   if (!data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] || !pkey[2]
1374       || !pkey[3] || !pkey[4] || !pkey[5] )
1375     return GPG_ERR_BAD_MPI;
1376
1377   pk.E.p = pkey[0];
1378   pk.E.a = pkey[1];
1379   pk.E.b = pkey[2];
1380   point_init (&pk.E.G);
1381   err = os2ec (&pk.E.G, pkey[3]);
1382   if (err)
1383     {
1384       point_free (&pk.E.G);
1385       return err;
1386     }
1387   pk.E.n = pkey[4];
1388   point_init (&pk.Q);
1389   err = os2ec (&pk.Q, pkey[5]);
1390   if (err)
1391     {
1392       point_free (&pk.E.G);
1393       point_free (&pk.Q);
1394       return err;
1395     }
1396
1397   err = verify (hash, &pk, data[0], data[1]);
1398
1399   point_free (&pk.E.G);
1400   point_free (&pk.Q);
1401   return err;
1402 }
1403
1404
1405 /* ecdh raw is classic 2-round DH protocol published in 1976.
1406  *
1407  * Overview of ecc_encrypt_raw and ecc_decrypt_raw.
1408  *
1409  * As with any PK operation, encrypt version uses a public key and
1410  * decrypt -- private.
1411  *
1412  * Symbols used below:
1413  *     G - field generator point
1414  *     d - private long-term scalar
1415  *    dG - public long-term key
1416  *     k - ephemeral scalar
1417  *    kG - ephemeral public key
1418  *   dkG - shared secret
1419  *
1420  * ecc_encrypt_raw description:
1421  *   input:
1422  *     data[0] : private scalar (k)
1423  *   output:
1424  *     result[0] : shared point (kdG)
1425  *     result[1] : generated ephemeral public key (kG)
1426  *
1427  * ecc_decrypt_raw description:
1428  *   input:
1429  *     data[0] : a point kG (ephemeral public key)
1430  *   output:
1431  *     result[0] : shared point (kdG)
1432  */
1433 static gcry_err_code_t
1434 ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
1435                  gcry_mpi_t *pkey, int flags)
1436 {
1437   ECC_public_key pk;
1438   mpi_ec_t ctx;
1439   gcry_mpi_t result[2];
1440   int err;
1441
1442   (void)algo;
1443   (void)flags;
1444
1445   if (!k
1446       || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4] || !pkey[5])
1447     return GPG_ERR_BAD_MPI;
1448
1449   pk.E.p = pkey[0];
1450   pk.E.a = pkey[1];
1451   pk.E.b = pkey[2];
1452   point_init (&pk.E.G);
1453   err = os2ec (&pk.E.G, pkey[3]);
1454   if (err)
1455     {
1456       point_free (&pk.E.G);
1457       return err;
1458     }
1459   pk.E.n = pkey[4];
1460   point_init (&pk.Q);
1461   err = os2ec (&pk.Q, pkey[5]);
1462   if (err)
1463     {
1464       point_free (&pk.E.G);
1465       point_free (&pk.Q);
1466       return err;
1467     }
1468
1469   ctx = _gcry_mpi_ec_p_internal_new (pk.E.p, pk.E.a);
1470
1471   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
1472   {
1473     mpi_point_struct R;  /* Result that we return.  */
1474     gcry_mpi_t x, y;
1475
1476     x = mpi_new (0);
1477     y = mpi_new (0);
1478
1479     point_init (&R);
1480
1481     /* R = kQ  <=>  R = kdG  */
1482     _gcry_mpi_ec_mul_point (&R, k, &pk.Q, ctx);
1483
1484     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
1485       log_fatal ("ecdh: Failed to get affine coordinates for kdG\n");
1486
1487     result[0] = ec2os (x, y, pk.E.p);
1488
1489     /* R = kG */
1490     _gcry_mpi_ec_mul_point (&R, k, &pk.E.G, ctx);
1491
1492     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
1493       log_fatal ("ecdh: Failed to get affine coordinates for kG\n");
1494
1495     result[1] = ec2os (x, y, pk.E.p);
1496
1497     mpi_free (x);
1498     mpi_free (y);
1499
1500     point_free (&R);
1501   }
1502
1503   _gcry_mpi_ec_free (ctx);
1504   point_free (&pk.E.G);
1505   point_free (&pk.Q);
1506
1507   if (!result[0] || !result[1])
1508     {
1509       mpi_free (result[0]);
1510       mpi_free (result[1]);
1511       return GPG_ERR_ENOMEM;
1512     }
1513
1514   /* Success.  */
1515   resarr[0] = result[0];
1516   resarr[1] = result[1];
1517
1518   return 0;
1519 }
1520
1521 /*  input:
1522  *     data[0] : a point kG (ephemeral public key)
1523  *   output:
1524  *     resaddr[0] : shared point kdG
1525  *
1526  *  see ecc_encrypt_raw for details.
1527  */
1528 static gcry_err_code_t
1529 ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
1530                  gcry_mpi_t *skey, int flags)
1531 {
1532   ECC_secret_key sk;
1533   mpi_point_struct R;   /* Result that we return.  */
1534   mpi_point_struct kG;
1535   mpi_ec_t ctx;
1536   gcry_mpi_t r;
1537   int err;
1538
1539   (void)algo;
1540   (void)flags;
1541
1542   *result = NULL;
1543
1544   if (!data || !data[0]
1545       || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4]
1546       || !skey[5] || !skey[6] )
1547     return GPG_ERR_BAD_MPI;
1548
1549   point_init (&kG);
1550   err = os2ec (&kG, data[0]);
1551   if (err)
1552     {
1553       point_free (&kG);
1554       return err;
1555     }
1556
1557
1558   sk.E.p = skey[0];
1559   sk.E.a = skey[1];
1560   sk.E.b = skey[2];
1561   point_init (&sk.E.G);
1562   err = os2ec (&sk.E.G, skey[3]);
1563   if (err)
1564     {
1565       point_free (&kG);
1566       point_free (&sk.E.G);
1567       return err;
1568     }
1569   sk.E.n = skey[4];
1570   point_init (&sk.Q);
1571   err = os2ec (&sk.Q, skey[5]);
1572   if (err)
1573     {
1574       point_free (&kG);
1575       point_free (&sk.E.G);
1576       point_free (&sk.Q);
1577       return err;
1578     }
1579   sk.d = skey[6];
1580
1581   ctx = _gcry_mpi_ec_p_internal_new (sk.E.p, sk.E.a);
1582
1583   /* R = dkG */
1584   point_init (&R);
1585   _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ctx);
1586
1587   point_free (&kG);
1588
1589   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so:  */
1590   {
1591     gcry_mpi_t x, y;
1592
1593     x = mpi_new (0);
1594     y = mpi_new (0);
1595
1596     if (_gcry_mpi_ec_get_affine (x, y, &R, ctx))
1597       log_fatal ("ecdh: Failed to get affine coordinates\n");
1598
1599     r = ec2os (x, y, sk.E.p);
1600     mpi_free (x);
1601     mpi_free (y);
1602   }
1603
1604   point_free (&R);
1605   _gcry_mpi_ec_free (ctx);
1606   point_free (&kG);
1607   point_free (&sk.E.G);
1608   point_free (&sk.Q);
1609
1610   if (!r)
1611     return GPG_ERR_ENOMEM;
1612
1613   /* Success.  */
1614
1615   *result = r;
1616
1617   return 0;
1618 }
1619
1620
1621 static unsigned int
1622 ecc_get_nbits (int algo, gcry_mpi_t *pkey)
1623 {
1624   (void)algo;
1625
1626   return mpi_get_nbits (pkey[0]);
1627 }
1628
1629
1630 /* See rsa.c for a description of this function.  */
1631 static gpg_err_code_t
1632 compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
1633 {
1634 #define N_COMPONENTS 6
1635   static const char names[N_COMPONENTS+1] = "pabgnq";
1636   gpg_err_code_t ec = 0;
1637   gcry_sexp_t l1;
1638   gcry_mpi_t values[N_COMPONENTS];
1639   int idx;
1640
1641   /* Clear the values for easier error cleanup.  */
1642   for (idx=0; idx < N_COMPONENTS; idx++)
1643     values[idx] = NULL;
1644
1645   /* Fill values with all provided parameters.  */
1646   for (idx=0; idx < N_COMPONENTS; idx++)
1647     {
1648       l1 = gcry_sexp_find_token (keyparam, names+idx, 1);
1649       if (l1)
1650         {
1651           values[idx] = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
1652           gcry_sexp_release (l1);
1653           if (!values[idx])
1654             {
1655               ec = GPG_ERR_INV_OBJ;
1656               goto leave;
1657             }
1658         }
1659     }
1660
1661   /* Check whether a curve parameter is available and use that to fill
1662      in missing values.  */
1663   l1 = gcry_sexp_find_token (keyparam, "curve", 5);
1664   if (l1)
1665     {
1666       char *curve;
1667       gcry_mpi_t tmpvalues[N_COMPONENTS];
1668
1669       for (idx = 0; idx < N_COMPONENTS; idx++)
1670         tmpvalues[idx] = NULL;
1671
1672       curve = _gcry_sexp_nth_string (l1, 1);
1673       gcry_sexp_release (l1);
1674       if (!curve)
1675         {
1676           ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
1677           goto leave;
1678         }
1679       ec = ecc_get_param (curve, tmpvalues);
1680       gcry_free (curve);
1681       if (ec)
1682         goto leave;
1683
1684       for (idx = 0; idx < N_COMPONENTS; idx++)
1685         {
1686           if (!values[idx])
1687             values[idx] = tmpvalues[idx];
1688           else
1689             mpi_free (tmpvalues[idx]);
1690         }
1691     }
1692
1693   /* Check that all parameters are known and normalize all MPIs (that
1694      should not be required but we use an internal function later and
1695      thus we better make 100% sure that they are normalized). */
1696   for (idx = 0; idx < N_COMPONENTS; idx++)
1697     if (!values[idx])
1698       {
1699         ec = GPG_ERR_NO_OBJ;
1700         goto leave;
1701       }
1702     else
1703       _gcry_mpi_normalize (values[idx]);
1704
1705   /* Hash them all.  */
1706   for (idx = 0; idx < N_COMPONENTS; idx++)
1707     {
1708       char buf[30];
1709       unsigned char *rawmpi;
1710       unsigned int rawmpilen;
1711
1712       rawmpi = _gcry_mpi_get_buffer (values[idx], &rawmpilen, NULL);
1713       if (!rawmpi)
1714         {
1715           ec = gpg_err_code_from_syserror ();
1716           goto leave;
1717         }
1718       snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], rawmpilen);
1719       gcry_md_write (md, buf, strlen (buf));
1720       gcry_md_write (md, rawmpi, rawmpilen);
1721       gcry_md_write (md, ")", 1);
1722       gcry_free (rawmpi);
1723     }
1724
1725  leave:
1726   for (idx = 0; idx < N_COMPONENTS; idx++)
1727     _gcry_mpi_release (values[idx]);
1728
1729   return ec;
1730 #undef N_COMPONENTS
1731 }
1732
1733
1734 \f
1735 /*
1736    Low-level API helper functions.
1737  */
1738
1739 /* Helper to extract an MPI from key parameters.  */
1740 static gpg_err_code_t
1741 mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name)
1742 {
1743   gcry_err_code_t ec = 0;
1744   gcry_sexp_t l1;
1745
1746   l1 = gcry_sexp_find_token (keyparam, name, 0);
1747   if (l1)
1748     {
1749       *r_a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
1750       gcry_sexp_release (l1);
1751       if (!*r_a)
1752         ec = GPG_ERR_INV_OBJ;
1753     }
1754   return ec;
1755 }
1756
1757 /* Helper to extract a point from key parameters.  If no parameter
1758    with NAME is found, the functions tries to find a non-encoded point
1759    by appending ".x", ".y" and ".z" to NAME.  ".z" is in this case
1760    optional and defaults to 1.  */
1761 static gpg_err_code_t
1762 point_from_keyparam (gcry_mpi_point_t *r_a,
1763                      gcry_sexp_t keyparam, const char *name)
1764 {
1765   gcry_err_code_t ec;
1766   gcry_mpi_t a = NULL;
1767   gcry_mpi_point_t point;
1768
1769   ec = mpi_from_keyparam (&a, keyparam, name);
1770   if (ec)
1771     return ec;
1772
1773   if (a)
1774     {
1775       point = gcry_mpi_point_new (0);
1776       ec = os2ec (point, a);
1777       mpi_free (a);
1778       if (ec)
1779         {
1780           gcry_mpi_point_release (point);
1781           return ec;
1782         }
1783     }
1784   else
1785     {
1786       char *tmpname;
1787       gcry_mpi_t x = NULL;
1788       gcry_mpi_t y = NULL;
1789       gcry_mpi_t z = NULL;
1790
1791       tmpname = gcry_malloc (strlen (name) + 2 + 1);
1792       if (!tmpname)
1793         return gpg_err_code_from_syserror ();
1794       strcpy (stpcpy (tmpname, name), ".x");
1795       ec = mpi_from_keyparam (&x, keyparam, tmpname);
1796       if (ec)
1797         {
1798           gcry_free (tmpname);
1799           return ec;
1800         }
1801       strcpy (stpcpy (tmpname, name), ".y");
1802       ec = mpi_from_keyparam (&y, keyparam, tmpname);
1803       if (ec)
1804         {
1805           mpi_free (x);
1806           gcry_free (tmpname);
1807           return ec;
1808         }
1809       strcpy (stpcpy (tmpname, name), ".z");
1810       ec = mpi_from_keyparam (&z, keyparam, tmpname);
1811       if (ec)
1812         {
1813           mpi_free (y);
1814           mpi_free (x);
1815           gcry_free (tmpname);
1816           return ec;
1817         }
1818       if (!z)
1819         z = mpi_set_ui (NULL, 1);
1820       if (x && y)
1821         point = gcry_mpi_point_snatch_set (NULL, x, y, z);
1822       else
1823         {
1824           mpi_free (x);
1825           mpi_free (y);
1826           mpi_free (z);
1827           point = NULL;
1828         }
1829       gcry_free (tmpname);
1830     }
1831
1832   if (point)
1833     *r_a = point;
1834   return 0;
1835 }
1836
1837
1838 /* This function creates a new context for elliptic curve operations.
1839    Either KEYPARAM or CURVENAME must be given.  If both are given and
1840    KEYPARAM has no curve parameter CURVENAME is used to add missing
1841    parameters.  On success 0 is returned and the new context stored at
1842    R_CTX.  On error NULL is stored at R_CTX and an error code is
1843    returned.  The context needs to be released using
1844    gcry_ctx_release.  */
1845 gpg_err_code_t
1846 _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
1847                   gcry_sexp_t keyparam, const char *curvename)
1848 {
1849   gpg_err_code_t errc;
1850   gcry_ctx_t ctx = NULL;
1851   gcry_mpi_t p = NULL;
1852   gcry_mpi_t a = NULL;
1853   gcry_mpi_t b = NULL;
1854   gcry_mpi_point_t G = NULL;
1855   gcry_mpi_t n = NULL;
1856   gcry_mpi_point_t Q = NULL;
1857   gcry_mpi_t d = NULL;
1858   gcry_sexp_t l1;
1859
1860   *r_ctx = NULL;
1861
1862   if (keyparam)
1863     {
1864       errc = mpi_from_keyparam (&p, keyparam, "p");
1865       if (errc)
1866         goto leave;
1867       errc = mpi_from_keyparam (&a, keyparam, "a");
1868       if (errc)
1869         goto leave;
1870       errc = mpi_from_keyparam (&b, keyparam, "b");
1871       if (errc)
1872         goto leave;
1873       errc = point_from_keyparam (&G, keyparam, "g");
1874       if (errc)
1875         goto leave;
1876       errc = mpi_from_keyparam (&n, keyparam, "n");
1877       if (errc)
1878         goto leave;
1879       errc = point_from_keyparam (&Q, keyparam, "q");
1880       if (errc)
1881         goto leave;
1882       errc = mpi_from_keyparam (&d, keyparam, "d");
1883       if (errc)
1884         goto leave;
1885     }
1886
1887
1888   /* Check whether a curve parameter is available and use that to fill
1889      in missing values.  If no curve parameter is available try an
1890      optional provided curvename.  If only the curvename has been
1891      given use that one. */
1892   if (keyparam)
1893     l1 = gcry_sexp_find_token (keyparam, "curve", 5);
1894   else
1895     l1 = NULL;
1896   if (l1 || curvename)
1897     {
1898       char *name;
1899       elliptic_curve_t *E;
1900
1901       if (l1)
1902         {
1903           name = _gcry_sexp_nth_string (l1, 1);
1904           gcry_sexp_release (l1);
1905           if (!name)
1906             {
1907               errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
1908               goto leave;
1909             }
1910         }
1911       else
1912         name = NULL;
1913
1914       E = gcry_calloc (1, sizeof *E);
1915       if (!E)
1916         {
1917           errc = gpg_err_code_from_syserror ();
1918           gcry_free (name);
1919           goto leave;
1920         }
1921
1922       errc = fill_in_curve (0, name? name : curvename, E, NULL);
1923       gcry_free (name);
1924       if (errc)
1925         {
1926           gcry_free (E);
1927           goto leave;
1928         }
1929
1930       if (!p)
1931         {
1932           p = E->p;
1933           E->p = NULL;
1934         }
1935       if (!a)
1936         {
1937           a = E->a;
1938           E->a = NULL;
1939         }
1940       if (!b)
1941         {
1942           b = E->b;
1943           E->b = NULL;
1944         }
1945       if (!G)
1946         {
1947           G = gcry_mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
1948           E->G.x = NULL;
1949           E->G.y = NULL;
1950           E->G.z = NULL;
1951         }
1952       if (!n)
1953         {
1954           n = E->n;
1955           E->n = NULL;
1956         }
1957       curve_free (E);
1958       gcry_free (E);
1959     }
1960
1961   errc = _gcry_mpi_ec_p_new (&ctx, p, a);
1962   if (!errc)
1963     {
1964       mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
1965
1966       if (b)
1967         {
1968           ec->b = b;
1969           b = NULL;
1970         }
1971       if (G)
1972         {
1973           ec->G = G;
1974           G = NULL;
1975         }
1976       if (n)
1977         {
1978           ec->n = n;
1979           n = NULL;
1980         }
1981       if (Q)
1982         {
1983           ec->Q = Q;
1984           Q = NULL;
1985         }
1986       if (d)
1987         {
1988           ec->d = d;
1989           d = NULL;
1990         }
1991
1992       *r_ctx = ctx;
1993     }
1994
1995  leave:
1996   mpi_free (p);
1997   mpi_free (a);
1998   mpi_free (b);
1999   gcry_mpi_point_release (G);
2000   mpi_free (n);
2001   gcry_mpi_point_release (Q);
2002   mpi_free (d);
2003   return errc;
2004 }
2005
2006
2007 /* This is the wroker function for gcry_pubkey_get_sexp for ECC
2008    algorithms.  Note that the caller has already stored NULL at
2009    R_SEXP.  */
2010 gpg_err_code_t
2011 _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
2012 {
2013   gpg_err_code_t rc;
2014   gcry_mpi_t mpi_G = NULL;
2015   gcry_mpi_t mpi_Q = NULL;
2016
2017   if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n)
2018     return GPG_ERR_BAD_CRYPT_CTX;
2019
2020   if (mode == GCRY_PK_GET_SECKEY && !ec->d)
2021     return GPG_ERR_NO_SECKEY;
2022
2023   /* Compute the public point if it is missing.  */
2024   if (!ec->Q && ec->d)
2025     {
2026       ec->Q = gcry_mpi_point_new (0);
2027       _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec);
2028     }
2029
2030   /* Encode G and Q.  */
2031   mpi_G = _gcry_mpi_ec_ec2os (ec->G, ec);
2032   if (!mpi_G)
2033     {
2034       rc = GPG_ERR_BROKEN_PUBKEY;
2035       goto leave;
2036     }
2037   if (!ec->Q)
2038     {
2039       rc = GPG_ERR_BAD_CRYPT_CTX;
2040       goto leave;
2041     }
2042   mpi_Q = _gcry_mpi_ec_ec2os (ec->Q, ec);
2043   if (!mpi_Q)
2044     {
2045       rc = GPG_ERR_BROKEN_PUBKEY;
2046       goto leave;
2047     }
2048
2049   /* Fixme: We should return a curve name instead of the parameters if
2050      if know that they match a curve.  */
2051
2052   if (ec->d && (!mode || mode == GCRY_PK_GET_SECKEY))
2053     {
2054       /* Let's return a private key. */
2055       rc = gpg_err_code
2056         (gcry_sexp_build
2057          (r_sexp, NULL,
2058           "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))",
2059           ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q, ec->d));
2060     }
2061   else if (ec->Q)
2062     {
2063       /* Let's return a public key.  */
2064       rc = gpg_err_code
2065         (gcry_sexp_build
2066          (r_sexp, NULL,
2067           "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))",
2068           ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q));
2069     }
2070   else
2071     rc = GPG_ERR_BAD_CRYPT_CTX;
2072
2073  leave:
2074   mpi_free (mpi_Q);
2075   mpi_free (mpi_G);
2076   return rc;
2077 }
2078
2079
2080 \f
2081 /*
2082      Self-test section.
2083  */
2084
2085
2086 static gpg_err_code_t
2087 selftests_ecdsa (selftest_report_func_t report)
2088 {
2089   const char *what;
2090   const char *errtxt;
2091
2092   what = "low-level";
2093   errtxt = NULL; /*selftest ();*/
2094   if (errtxt)
2095     goto failed;
2096
2097   /* FIXME:  need more tests.  */
2098
2099   return 0; /* Succeeded. */
2100
2101  failed:
2102   if (report)
2103     report ("pubkey", GCRY_PK_ECDSA, what, errtxt);
2104   return GPG_ERR_SELFTEST_FAILED;
2105 }
2106
2107
2108 /* Run a full self-test for ALGO and return 0 on success.  */
2109 static gpg_err_code_t
2110 run_selftests (int algo, int extended, selftest_report_func_t report)
2111 {
2112   gpg_err_code_t ec;
2113
2114   (void)extended;
2115
2116   switch (algo)
2117     {
2118     case GCRY_PK_ECDSA:
2119       ec = selftests_ecdsa (report);
2120       break;
2121     default:
2122       ec = GPG_ERR_PUBKEY_ALGO;
2123       break;
2124
2125     }
2126   return ec;
2127 }
2128
2129
2130
2131 \f
2132 static const char *ecdsa_names[] =
2133   {
2134     "ecdsa",
2135     "ecc",
2136     NULL,
2137   };
2138 static const char *ecdh_names[] =
2139   {
2140     "ecdh",
2141     "ecc",
2142     NULL,
2143   };
2144
2145 gcry_pk_spec_t _gcry_pubkey_spec_ecdsa =
2146   {
2147     "ECDSA", ecdsa_names,
2148     "pabgnq", "pabgnqd", "", "rs", "pabgnq",
2149     GCRY_PK_USAGE_SIGN,
2150     ecc_generate,
2151     ecc_check_secret_key,
2152     NULL,
2153     NULL,
2154     ecc_sign,
2155     ecc_verify,
2156     ecc_get_nbits
2157   };
2158
2159 gcry_pk_spec_t _gcry_pubkey_spec_ecdh =
2160   {
2161     "ECDH", ecdh_names,
2162     "pabgnq", "pabgnqd", "se", "", "pabgnq",
2163     GCRY_PK_USAGE_ENCR,
2164     ecc_generate,
2165     ecc_check_secret_key,
2166     ecc_encrypt_raw,
2167     ecc_decrypt_raw,
2168     NULL,
2169     NULL,
2170     ecc_get_nbits
2171   };
2172
2173
2174 pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa =
2175   {
2176     run_selftests,
2177     ecc_generate_ext,
2178     compute_keygrip,
2179     ecc_get_param,
2180     ecc_get_curve,
2181     ecc_get_param_sexp
2182   };