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