ecc: Add Ed25519 key generation and prepare for optimizations.
[libgcrypt.git] / cipher / ecc-curves.c
1 /* ecc-curves.c  -  Elliptic Curve parameter mangement
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 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26
27 #include "g10lib.h"
28 #include "mpi.h"
29 #include "context.h"
30 #include "ec-context.h"
31 #include "ecc-common.h"
32
33
34 /* This tables defines aliases for curve names.  */
35 static const struct
36 {
37   const char *name;  /* Our name.  */
38   const char *other; /* Other name. */
39 } curve_aliases[] =
40   {
41     { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID  */
42     { "NIST P-192", "prime192v1" },          /* X9.62 name.  */
43     { "NIST P-192", "secp192r1"  },          /* SECP name.  */
44     { "NIST P-192", "nistp192"   },          /* rfc5656.  */
45
46     { "NIST P-224", "secp224r1" },
47     { "NIST P-224", "1.3.132.0.33" },        /* SECP OID.  */
48     { "NIST P-224", "nistp224"   },          /* rfc5656.  */
49
50     { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1.  */
51     { "NIST P-256", "prime256v1" },
52     { "NIST P-256", "secp256r1"  },
53     { "NIST P-256", "nistp256"   },          /* rfc5656.  */
54
55     { "NIST P-384", "secp384r1" },
56     { "NIST P-384", "1.3.132.0.34" },
57     { "NIST P-384", "nistp384"   },          /* rfc5656.  */
58
59     { "NIST P-521", "secp521r1" },
60     { "NIST P-521", "1.3.132.0.35" },
61     { "NIST P-521", "nistp521"   },          /* rfc5656.  */
62
63     { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" },
64     { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" },
65     { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" },
66     { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" },
67     { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" },
68     { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"},
69     { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"},
70
71     { NULL, NULL}
72   };
73
74
75 typedef struct
76 {
77   const char *desc;           /* Description of the curve.  */
78   unsigned int nbits;         /* Number of bits.  */
79   unsigned int fips:1;        /* True if this is a FIPS140-2 approved curve. */
80
81   /* The model describing this curve.  This is mainly used to select
82      the group equation. */
83   enum gcry_mpi_ec_models model;
84
85   /* The actual ECC dialect used.  This is used for curve specific
86      optimizations and to select encodings etc. */
87   enum ecc_dialects dialect;
88
89   const char *p;              /* The prime defining the field.  */
90   const char *a, *b;          /* The coefficients.  For Twisted Edwards
91                                  Curves b is used for d.  */
92   const char *n;              /* The order of the base point.  */
93   const char *g_x, *g_y;      /* Base point.  */
94 } ecc_domain_parms_t;
95
96
97 /* This static table defines all available curves.  */
98 static const ecc_domain_parms_t domain_parms[] =
99   {
100     {
101       /* (-x^2 + y^2 = 1 + dx^2y^2) */
102       "Ed25519", 256, 0,
103       MPI_EC_TWISTEDEDWARDS, ECC_DIALECT_ED25519,
104       "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
105       "-0x01",
106       "-0x98412DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235EC8FEDA4",
107       "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
108       "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
109       "0x6666666666666666666666666666666666666666666666666666666666666658"
110     },
111     {
112       "NIST P-192", 192, 1,
113       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
114       "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
115       "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
116       "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
117       "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
118
119       "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
120       "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
121     },
122     {
123       "NIST P-224", 224, 1,
124       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
125       "0xffffffffffffffffffffffffffffffff000000000000000000000001",
126       "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
127       "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
128       "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
129
130       "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
131       "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
132     },
133     {
134       "NIST P-256", 256, 1,
135       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
136       "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
137       "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
138       "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
139       "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
140
141       "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
142       "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
143     },
144     {
145       "NIST P-384", 384, 1,
146       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
147       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
148       "ffffffff0000000000000000ffffffff",
149       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
150       "ffffffff0000000000000000fffffffc",
151       "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
152       "c656398d8a2ed19d2a85c8edd3ec2aef",
153       "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
154       "581a0db248b0a77aecec196accc52973",
155
156       "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
157       "5502f25dbf55296c3a545e3872760ab7",
158       "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
159       "0a60b1ce1d7e819d7a431d7c90ea0e5f"
160     },
161     {
162       "NIST P-521", 521, 1,
163       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
164       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
165       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
166       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
167       "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
168       "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
169       "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
170       "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
171       "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
172
173       "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
174       "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
175       "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
176       "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
177     },
178
179     { "brainpoolP160r1", 160, 0,
180       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
181       "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
182       "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
183       "0x1e589a8595423412134faa2dbdec95c8d8675e58",
184       "0xe95e4a5f737059dc60df5991d45029409e60fc09",
185       "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
186       "0x1667cb477a1a8ec338f94741669c976316da6321"
187     },
188
189     { "brainpoolP192r1", 192, 0,
190       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
191       "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
192       "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
193       "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
194       "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
195       "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
196       "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
197     },
198
199     { "brainpoolP224r1", 224, 0,
200       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
201       "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
202       "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
203       "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
204       "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
205       "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
206       "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
207     },
208
209     { "brainpoolP256r1", 256, 0,
210       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
211       "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
212       "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
213       "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
214       "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
215       "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
216       "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
217     },
218
219     { "brainpoolP320r1", 320, 0,
220       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
221       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
222       "fcd412b1f1b32e27",
223       "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
224       "92f375a97d860eb4",
225       "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981"
226       "6f5eb4ac8fb1f1a6",
227       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9"
228       "8691555b44c59311",
229       "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
230       "10af8d0d39e20611",
231       "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
232       "d35245d1692e8ee1"
233     },
234
235     { "brainpoolP384r1", 384, 0,
236       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
237       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
238       "acd3a729901d1a71874700133107ec53",
239       "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
240       "8aa5814a503ad4eb04a8c7dd22ce2826",
241       "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5"
242       "7cb4390295dbc9943ab78696fa504c11",
243       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7"
244       "cf3ab6af6b7fc3103b883202e9046565",
245       "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
246       "e826e03436d646aaef87b2e247d4af1e",
247       "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
248       "0e4646217791811142820341263c5315"
249     },
250
251     { "brainpoolP512r1", 512, 0,
252       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
253       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
254       "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
255       "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
256       "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca",
257       "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7"
258       "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723",
259       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870"
260       "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
261       "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
262       "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
263       "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
264       "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
265     },
266
267     { NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
268   };
269
270
271
272 \f
273 /* Helper to scan a hex string. */
274 static gcry_mpi_t
275 scanval (const char *string)
276 {
277   gpg_error_t err;
278   gcry_mpi_t val;
279
280   err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
281   if (err)
282     log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err));
283   return val;
284 }
285
286
287 /* Generate the crypto system setup.  This function takes the NAME of
288    a curve or the desired number of bits and stores at R_CURVE the
289    parameters of the named curve or those of a suitable curve.  If
290    R_NBITS is not NULL, the chosen number of bits is stored there.  */
291 gpg_err_code_t
292 _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
293                          elliptic_curve_t *curve, unsigned int *r_nbits)
294 {
295   int idx, aliasno;
296   const char *resname = NULL; /* Set to a found curve name.  */
297
298   if (name)
299     {
300       /* First check our native curves.  */
301       for (idx = 0; domain_parms[idx].desc; idx++)
302         if (!strcmp (name, domain_parms[idx].desc))
303           {
304             resname = domain_parms[idx].desc;
305             break;
306           }
307       /* If not found consult the alias table.  */
308       if (!domain_parms[idx].desc)
309         {
310           for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
311             if (!strcmp (name, curve_aliases[aliasno].other))
312               break;
313           if (curve_aliases[aliasno].name)
314             {
315               for (idx = 0; domain_parms[idx].desc; idx++)
316                 if (!strcmp (curve_aliases[aliasno].name,
317                              domain_parms[idx].desc))
318                   {
319                     resname = domain_parms[idx].desc;
320                     break;
321                   }
322             }
323         }
324     }
325   else
326     {
327       for (idx = 0; domain_parms[idx].desc; idx++)
328         if (nbits == domain_parms[idx].nbits
329             && domain_parms[idx].model == MPI_EC_WEIERSTRASS)
330           break;
331     }
332   if (!domain_parms[idx].desc)
333     return GPG_ERR_UNKNOWN_CURVE;
334
335   /* In fips mode we only support NIST curves.  Note that it is
336      possible to bypass this check by specifying the curve parameters
337      directly.  */
338   if (fips_mode () && !domain_parms[idx].fips )
339     return GPG_ERR_NOT_SUPPORTED;
340
341   switch (domain_parms[idx].model)
342     {
343     case MPI_EC_WEIERSTRASS:
344     case MPI_EC_TWISTEDEDWARDS:
345       break;
346     case MPI_EC_MONTGOMERY:
347       return GPG_ERR_NOT_SUPPORTED;
348     default:
349       return GPG_ERR_BUG;
350     }
351
352
353   if (r_nbits)
354     *r_nbits = domain_parms[idx].nbits;
355
356   curve->model = domain_parms[idx].model;
357   curve->dialect = domain_parms[idx].dialect;
358   curve->p = scanval (domain_parms[idx].p);
359   curve->a = scanval (domain_parms[idx].a);
360   curve->b = scanval (domain_parms[idx].b);
361   curve->n = scanval (domain_parms[idx].n);
362   curve->G.x = scanval (domain_parms[idx].g_x);
363   curve->G.y = scanval (domain_parms[idx].g_y);
364   curve->G.z = mpi_alloc_set_ui (1);
365   curve->name = resname;
366
367   return 0;
368 }
369
370
371 /* Return the name matching the parameters in PKEY.  This works only
372    with curves described by the Weierstrass equation. */
373 const char *
374 _gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
375 {
376   gpg_err_code_t err;
377   elliptic_curve_t E;
378   int idx;
379   gcry_mpi_t tmp;
380   const char *result = NULL;
381
382   if (r_nbits)
383     *r_nbits = 0;
384
385   if (!pkey)
386     {
387       idx = iterator;
388       if (idx >= 0 && idx < DIM (domain_parms))
389         {
390           result = domain_parms[idx].desc;
391           if (r_nbits)
392             *r_nbits = domain_parms[idx].nbits;
393         }
394       return result;
395     }
396
397   if (!pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4])
398     return NULL;
399
400   E.model = MPI_EC_WEIERSTRASS;
401   E.dialect = ECC_DIALECT_STANDARD;
402   E.name = NULL;
403   E.p = pkey[0];
404   E.a = pkey[1];
405   E.b = pkey[2];
406   _gcry_mpi_point_init (&E.G);
407   err = _gcry_ecc_os2ec (&E.G, pkey[3]);
408   if (err)
409     {
410       _gcry_mpi_point_free_parts (&E.G);
411       return NULL;
412     }
413   E.n = pkey[4];
414
415   for (idx = 0; domain_parms[idx].desc; idx++)
416     {
417       tmp = scanval (domain_parms[idx].p);
418       if (!mpi_cmp (tmp, E.p))
419         {
420           mpi_free (tmp);
421           tmp = scanval (domain_parms[idx].a);
422           if (!mpi_cmp (tmp, E.a))
423             {
424               mpi_free (tmp);
425               tmp = scanval (domain_parms[idx].b);
426               if (!mpi_cmp (tmp, E.b))
427                 {
428                   mpi_free (tmp);
429                   tmp = scanval (domain_parms[idx].n);
430                   if (!mpi_cmp (tmp, E.n))
431                     {
432                       mpi_free (tmp);
433                       tmp = scanval (domain_parms[idx].g_x);
434                       if (!mpi_cmp (tmp, E.G.x))
435                         {
436                           mpi_free (tmp);
437                           tmp = scanval (domain_parms[idx].g_y);
438                           if (!mpi_cmp (tmp, E.G.y))
439                             {
440                               mpi_free (tmp);
441                               result = domain_parms[idx].desc;
442                               if (r_nbits)
443                                 *r_nbits = domain_parms[idx].nbits;
444                               break;
445                             }
446                         }
447                     }
448                 }
449             }
450         }
451       mpi_free (tmp);
452     }
453
454   _gcry_mpi_point_free_parts (&E.G);
455
456   return result;
457 }
458
459
460 /* Helper to extract an MPI from key parameters.  */
461 static gpg_err_code_t
462 mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name)
463 {
464   gcry_err_code_t ec = 0;
465   gcry_sexp_t l1;
466
467   l1 = gcry_sexp_find_token (keyparam, name, 0);
468   if (l1)
469     {
470       *r_a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
471       gcry_sexp_release (l1);
472       if (!*r_a)
473         ec = GPG_ERR_INV_OBJ;
474     }
475   return ec;
476 }
477
478 /* Helper to extract a point from key parameters.  If no parameter
479    with NAME is found, the functions tries to find a non-encoded point
480    by appending ".x", ".y" and ".z" to NAME.  ".z" is in this case
481    optional and defaults to 1.  */
482 static gpg_err_code_t
483 point_from_keyparam (gcry_mpi_point_t *r_a,
484                      gcry_sexp_t keyparam, const char *name)
485 {
486   gcry_err_code_t ec;
487   gcry_mpi_t a = NULL;
488   gcry_mpi_point_t point;
489
490   ec = mpi_from_keyparam (&a, keyparam, name);
491   if (ec)
492     return ec;
493
494   if (a)
495     {
496       point = gcry_mpi_point_new (0);
497       ec = _gcry_ecc_os2ec (point, a);
498       mpi_free (a);
499       if (ec)
500         {
501           gcry_mpi_point_release (point);
502           return ec;
503         }
504     }
505   else
506     {
507       char *tmpname;
508       gcry_mpi_t x = NULL;
509       gcry_mpi_t y = NULL;
510       gcry_mpi_t z = NULL;
511
512       tmpname = gcry_malloc (strlen (name) + 2 + 1);
513       if (!tmpname)
514         return gpg_err_code_from_syserror ();
515       strcpy (stpcpy (tmpname, name), ".x");
516       ec = mpi_from_keyparam (&x, keyparam, tmpname);
517       if (ec)
518         {
519           gcry_free (tmpname);
520           return ec;
521         }
522       strcpy (stpcpy (tmpname, name), ".y");
523       ec = mpi_from_keyparam (&y, keyparam, tmpname);
524       if (ec)
525         {
526           mpi_free (x);
527           gcry_free (tmpname);
528           return ec;
529         }
530       strcpy (stpcpy (tmpname, name), ".z");
531       ec = mpi_from_keyparam (&z, keyparam, tmpname);
532       if (ec)
533         {
534           mpi_free (y);
535           mpi_free (x);
536           gcry_free (tmpname);
537           return ec;
538         }
539       if (!z)
540         z = mpi_set_ui (NULL, 1);
541       if (x && y)
542         point = gcry_mpi_point_snatch_set (NULL, x, y, z);
543       else
544         {
545           mpi_free (x);
546           mpi_free (y);
547           mpi_free (z);
548           point = NULL;
549         }
550       gcry_free (tmpname);
551     }
552
553   if (point)
554     *r_a = point;
555   return 0;
556 }
557
558
559 /* This function creates a new context for elliptic curve operations.
560    Either KEYPARAM or CURVENAME must be given.  If both are given and
561    KEYPARAM has no curve parameter, CURVENAME is used to add missing
562    parameters.  On success 0 is returned and the new context stored at
563    R_CTX.  On error NULL is stored at R_CTX and an error code is
564    returned.  The context needs to be released using
565    gcry_ctx_release.  */
566 gpg_err_code_t
567 _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
568                   gcry_sexp_t keyparam, const char *curvename)
569 {
570   gpg_err_code_t errc;
571   gcry_ctx_t ctx = NULL;
572   enum gcry_mpi_ec_models model = MPI_EC_WEIERSTRASS;
573   enum ecc_dialects dialect = ECC_DIALECT_STANDARD;
574   gcry_mpi_t p = NULL;
575   gcry_mpi_t a = NULL;
576   gcry_mpi_t b = NULL;
577   gcry_mpi_point_t G = NULL;
578   gcry_mpi_t n = NULL;
579   gcry_mpi_point_t Q = NULL;
580   gcry_mpi_t d = NULL;
581   gcry_sexp_t l1;
582
583   *r_ctx = NULL;
584
585   if (keyparam)
586     {
587       errc = mpi_from_keyparam (&p, keyparam, "p");
588       if (errc)
589         goto leave;
590       errc = mpi_from_keyparam (&a, keyparam, "a");
591       if (errc)
592         goto leave;
593       errc = mpi_from_keyparam (&b, keyparam, "b");
594       if (errc)
595         goto leave;
596       errc = point_from_keyparam (&G, keyparam, "g");
597       if (errc)
598         goto leave;
599       errc = mpi_from_keyparam (&n, keyparam, "n");
600       if (errc)
601         goto leave;
602       errc = point_from_keyparam (&Q, keyparam, "q");
603       if (errc)
604         goto leave;
605       errc = mpi_from_keyparam (&d, keyparam, "d");
606       if (errc)
607         goto leave;
608     }
609
610
611   /* Check whether a curve parameter is available and use that to fill
612      in missing values.  If no curve parameter is available try an
613      optional provided curvename.  If only the curvename has been
614      given use that one. */
615   if (keyparam)
616     l1 = gcry_sexp_find_token (keyparam, "curve", 5);
617   else
618     l1 = NULL;
619   if (l1 || curvename)
620     {
621       char *name;
622       elliptic_curve_t *E;
623
624       if (l1)
625         {
626           name = _gcry_sexp_nth_string (l1, 1);
627           gcry_sexp_release (l1);
628           if (!name)
629             {
630               errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
631               goto leave;
632             }
633         }
634       else
635         name = NULL;
636
637       E = gcry_calloc (1, sizeof *E);
638       if (!E)
639         {
640           errc = gpg_err_code_from_syserror ();
641           gcry_free (name);
642           goto leave;
643         }
644
645       errc = _gcry_ecc_fill_in_curve (0, name? name : curvename, E, NULL);
646       gcry_free (name);
647       if (errc)
648         {
649           gcry_free (E);
650           goto leave;
651         }
652
653       model = E->model;
654       dialect = E->dialect;
655
656       if (!p)
657         {
658           p = E->p;
659           E->p = NULL;
660         }
661       if (!a)
662         {
663           a = E->a;
664           E->a = NULL;
665         }
666       if (!b)
667         {
668           b = E->b;
669           E->b = NULL;
670         }
671       if (!G)
672         {
673           G = gcry_mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
674           E->G.x = NULL;
675           E->G.y = NULL;
676           E->G.z = NULL;
677         }
678       if (!n)
679         {
680           n = E->n;
681           E->n = NULL;
682         }
683       _gcry_ecc_curve_free (E);
684       gcry_free (E);
685     }
686
687   errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, p, a, b);
688   if (!errc)
689     {
690       mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
691
692       if (b)
693         {
694           ec->b = b;
695           b = NULL;
696         }
697       if (G)
698         {
699           ec->G = G;
700           G = NULL;
701         }
702       if (n)
703         {
704           ec->n = n;
705           n = NULL;
706         }
707       if (Q)
708         {
709           ec->Q = Q;
710           Q = NULL;
711         }
712       if (d)
713         {
714           ec->d = d;
715           d = NULL;
716         }
717
718       *r_ctx = ctx;
719     }
720
721  leave:
722   mpi_free (p);
723   mpi_free (a);
724   mpi_free (b);
725   gcry_mpi_point_release (G);
726   mpi_free (n);
727   gcry_mpi_point_release (Q);
728   mpi_free (d);
729   return errc;
730 }
731
732
733 /* Return the parameters of the curve NAME in an MPI array.  */
734 gcry_err_code_t
735 _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey)
736 {
737   gpg_err_code_t err;
738   unsigned int nbits;
739   elliptic_curve_t E;
740   mpi_ec_t ctx;
741   gcry_mpi_t g_x, g_y;
742
743   err = _gcry_ecc_fill_in_curve (0, name, &E, &nbits);
744   if (err)
745     return err;
746
747   g_x = mpi_new (0);
748   g_y = mpi_new (0);
749   ctx = _gcry_mpi_ec_p_internal_new (0, ECC_DIALECT_STANDARD, E.p, E.a, NULL);
750   if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
751     log_fatal ("ecc get param: Failed to get affine coordinates\n");
752   _gcry_mpi_ec_free (ctx);
753   _gcry_mpi_point_free_parts (&E.G);
754
755   pkey[0] = E.p;
756   pkey[1] = E.a;
757   pkey[2] = E.b;
758   pkey[3] = _gcry_ecc_ec2os (g_x, g_y, E.p);
759   pkey[4] = E.n;
760   pkey[5] = NULL;
761
762   mpi_free (g_x);
763   mpi_free (g_y);
764
765   return 0;
766 }
767
768
769 /* Return the parameters of the curve NAME as an S-expression.  */
770 gcry_sexp_t
771 _gcry_ecc_get_param_sexp (const char *name)
772 {
773   gcry_mpi_t pkey[6];
774   gcry_sexp_t result;
775   int i;
776
777   if (_gcry_ecc_get_param (name, pkey))
778     return NULL;
779
780   if (gcry_sexp_build (&result, NULL,
781                        "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))",
782                        pkey[0], pkey[1], pkey[2], pkey[3], pkey[4]))
783     result = NULL;
784
785   for (i=0; pkey[i]; i++)
786     gcry_mpi_release (pkey[i]);
787
788   return result;
789 }