12f539a495b867565def0c388b998900636ea200
[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 "cipher.h"
30 #include "context.h"
31 #include "ec-context.h"
32 #include "pubkey-internal.h"
33 #include "ecc-common.h"
34
35
36 /* This tables defines aliases for curve names.  */
37 static const struct
38 {
39   const char *name;  /* Our name.  */
40   const char *other; /* Other name. */
41 } curve_aliases[] =
42   {
43     { "Ed25519",    "1.3.6.1.4.1.3029.1.5.1" },
44
45     { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID  */
46     { "NIST P-192", "prime192v1" },          /* X9.62 name.  */
47     { "NIST P-192", "secp192r1"  },          /* SECP name.  */
48     { "NIST P-192", "nistp192"   },          /* rfc5656.  */
49
50     { "NIST P-224", "secp224r1" },
51     { "NIST P-224", "1.3.132.0.33" },        /* SECP OID.  */
52     { "NIST P-224", "nistp224"   },          /* rfc5656.  */
53
54     { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1.  */
55     { "NIST P-256", "prime256v1" },
56     { "NIST P-256", "secp256r1"  },
57     { "NIST P-256", "nistp256"   },          /* rfc5656.  */
58
59     { "NIST P-384", "secp384r1" },
60     { "NIST P-384", "1.3.132.0.34" },
61     { "NIST P-384", "nistp384"   },          /* rfc5656.  */
62
63     { "NIST P-521", "secp521r1" },
64     { "NIST P-521", "1.3.132.0.35" },
65     { "NIST P-521", "nistp521"   },          /* rfc5656.  */
66
67     { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" },
68     { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" },
69     { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" },
70     { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" },
71     { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" },
72     { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"},
73     { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"},
74
75     { NULL, NULL}
76   };
77
78
79 typedef struct
80 {
81   const char *desc;           /* Description of the curve.  */
82   unsigned int nbits;         /* Number of bits.  */
83   unsigned int fips:1;        /* True if this is a FIPS140-2 approved curve. */
84
85   /* The model describing this curve.  This is mainly used to select
86      the group equation. */
87   enum gcry_mpi_ec_models model;
88
89   /* The actual ECC dialect used.  This is used for curve specific
90      optimizations and to select encodings etc. */
91   enum ecc_dialects dialect;
92
93   const char *p;              /* The prime defining the field.  */
94   const char *a, *b;          /* The coefficients.  For Twisted Edwards
95                                  Curves b is used for d.  */
96   const char *n;              /* The order of the base point.  */
97   const char *g_x, *g_y;      /* Base point.  */
98 } ecc_domain_parms_t;
99
100
101 /* This static table defines all available curves.  */
102 static const ecc_domain_parms_t domain_parms[] =
103   {
104     {
105       /* (-x^2 + y^2 = 1 + dx^2y^2) */
106       "Ed25519", 256, 0,
107       MPI_EC_TWISTEDEDWARDS, ECC_DIALECT_ED25519,
108       "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
109       "-0x01",
110       "-0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A",
111       "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
112       "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
113       "0x6666666666666666666666666666666666666666666666666666666666666658"
114     },
115     {
116       "NIST P-192", 192, 1,
117       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
118       "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
119       "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
120       "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
121       "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
122
123       "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
124       "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
125     },
126     {
127       "NIST P-224", 224, 1,
128       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
129       "0xffffffffffffffffffffffffffffffff000000000000000000000001",
130       "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
131       "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
132       "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
133
134       "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
135       "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
136     },
137     {
138       "NIST P-256", 256, 1,
139       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
140       "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
141       "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
142       "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
143       "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
144
145       "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
146       "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
147     },
148     {
149       "NIST P-384", 384, 1,
150       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
151       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
152       "ffffffff0000000000000000ffffffff",
153       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
154       "ffffffff0000000000000000fffffffc",
155       "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
156       "c656398d8a2ed19d2a85c8edd3ec2aef",
157       "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
158       "581a0db248b0a77aecec196accc52973",
159
160       "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
161       "5502f25dbf55296c3a545e3872760ab7",
162       "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
163       "0a60b1ce1d7e819d7a431d7c90ea0e5f"
164     },
165     {
166       "NIST P-521", 521, 1,
167       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
168       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
169       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
170       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
171       "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
172       "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
173       "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
174       "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
175       "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
176
177       "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
178       "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
179       "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
180       "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
181     },
182
183     { "brainpoolP160r1", 160, 0,
184       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
185       "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
186       "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
187       "0x1e589a8595423412134faa2dbdec95c8d8675e58",
188       "0xe95e4a5f737059dc60df5991d45029409e60fc09",
189       "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
190       "0x1667cb477a1a8ec338f94741669c976316da6321"
191     },
192
193     { "brainpoolP192r1", 192, 0,
194       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
195       "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
196       "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
197       "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
198       "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
199       "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
200       "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
201     },
202
203     { "brainpoolP224r1", 224, 0,
204       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
205       "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
206       "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
207       "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
208       "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
209       "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
210       "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
211     },
212
213     { "brainpoolP256r1", 256, 0,
214       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
215       "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
216       "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
217       "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
218       "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
219       "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
220       "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
221     },
222
223     { "brainpoolP320r1", 320, 0,
224       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
225       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
226       "fcd412b1f1b32e27",
227       "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
228       "92f375a97d860eb4",
229       "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981"
230       "6f5eb4ac8fb1f1a6",
231       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9"
232       "8691555b44c59311",
233       "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
234       "10af8d0d39e20611",
235       "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
236       "d35245d1692e8ee1"
237     },
238
239     { "brainpoolP384r1", 384, 0,
240       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
241       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
242       "acd3a729901d1a71874700133107ec53",
243       "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
244       "8aa5814a503ad4eb04a8c7dd22ce2826",
245       "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5"
246       "7cb4390295dbc9943ab78696fa504c11",
247       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7"
248       "cf3ab6af6b7fc3103b883202e9046565",
249       "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
250       "e826e03436d646aaef87b2e247d4af1e",
251       "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
252       "0e4646217791811142820341263c5315"
253     },
254
255     { "brainpoolP512r1", 512, 0,
256       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
257       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
258       "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
259       "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
260       "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca",
261       "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7"
262       "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723",
263       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870"
264       "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
265       "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
266       "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
267       "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
268       "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
269     },
270     {
271       "GOST2001-test", 256, 0,
272       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
273       "0x8000000000000000000000000000000000000000000000000000000000000431",
274       "0x0000000000000000000000000000000000000000000000000000000000000007",
275       "0x5fbff498aa938ce739b8e022fbafef40563f6e6a3472fc2a514c0ce9dae23b7e",
276       "0x8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3",
277
278       "0x0000000000000000000000000000000000000000000000000000000000000002",
279       "0x08e2a8a0e65147d4bd6316030e16d19c85c97f0a9ca267122b96abbcea7e8fc8",
280     },
281
282     {
283       "GOST2012-test", 511, 0,
284       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
285       "0x4531acd1fe0023c7550d267b6b2fee80922b14b2ffb90f04d4eb7c09b5d2d15d"
286       "f1d852741af4704a0458047e80e4546d35b8336fac224dd81664bbf528be6373",
287       "0x0000000000000000000000000000000000000000000000000000000000000007",
288       "0x1cff0806a31116da29d8cfa54e57eb748bc5f377e49400fdd788b649eca1ac4"
289       "361834013b2ad7322480a89ca58e0cf74bc9e540c2add6897fad0a3084f302adc",
290       "0x4531acd1fe0023c7550d267b6b2fee80922b14b2ffb90f04d4eb7c09b5d2d15d"
291       "a82f2d7ecb1dbac719905c5eecc423f1d86e25edbe23c595d644aaf187e6e6df",
292
293       "0x24d19cc64572ee30f396bf6ebbfd7a6c5213b3b3d7057cc825f91093a68cd762"
294       "fd60611262cd838dc6b60aa7eee804e28bc849977fac33b4b530f1b120248a9a",
295       "0x2bb312a43bd2ce6e0d020613c857acddcfbf061e91e5f2c3f32447c259f39b2"
296       "c83ab156d77f1496bf7eb3351e1ee4e43dc1a18b91b24640b6dbb92cb1add371e",
297     },
298
299     { NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
300   };
301
302
303
304 \f
305 /* Return a copy of POINT.  */
306 static gcry_mpi_point_t
307 point_copy (gcry_mpi_point_t point)
308 {
309   gcry_mpi_point_t newpoint;
310
311   if (point)
312     {
313       newpoint = gcry_mpi_point_new (0);
314       point_set (newpoint, point);
315     }
316   else
317     newpoint = NULL;
318   return newpoint;
319 }
320
321
322 /* Helper to scan a hex string. */
323 static gcry_mpi_t
324 scanval (const char *string)
325 {
326   gpg_error_t err;
327   gcry_mpi_t val;
328
329   err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
330   if (err)
331     log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err));
332   return val;
333 }
334
335
336 /* Return the index of the domain_parms table for a curve with NAME.
337    Return -1 if not found.  */
338 static int
339 find_domain_parms_idx (const char *name)
340 {
341   int idx, aliasno;
342
343   /* First check our native curves.  */
344   for (idx = 0; domain_parms[idx].desc; idx++)
345     if (!strcmp (name, domain_parms[idx].desc))
346       return idx;
347
348   /* If not found consult the alias table.  */
349   if (!domain_parms[idx].desc)
350     {
351       for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
352         if (!strcmp (name, curve_aliases[aliasno].other))
353           break;
354       if (curve_aliases[aliasno].name)
355         {
356           for (idx = 0; domain_parms[idx].desc; idx++)
357             if (!strcmp (curve_aliases[aliasno].name, domain_parms[idx].desc))
358               return idx;
359         }
360     }
361
362   return -1;
363 }
364
365
366 /* Generate the crypto system setup.  This function takes the NAME of
367    a curve or the desired number of bits and stores at R_CURVE the
368    parameters of the named curve or those of a suitable curve.  If
369    R_NBITS is not NULL, the chosen number of bits is stored there.
370    NULL may be given for R_CURVE, if the value is not required and for
371    example only a quick test for availability is desired.  Note that
372    the curve fields should be initialized to zero because fields which
373    are not NULL are skipped.  */
374 gpg_err_code_t
375 _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
376                          elliptic_curve_t *curve, unsigned int *r_nbits)
377 {
378   int idx;
379   const char *resname = NULL; /* Set to a found curve name.  */
380
381   if (name)
382     idx = find_domain_parms_idx (name);
383   else
384     {
385       for (idx = 0; domain_parms[idx].desc; idx++)
386         if (nbits == domain_parms[idx].nbits
387             && domain_parms[idx].model == MPI_EC_WEIERSTRASS)
388           break;
389       if (!domain_parms[idx].desc)
390         idx = -1;
391     }
392   if (idx < 0)
393     return GPG_ERR_UNKNOWN_CURVE;
394
395   resname = domain_parms[idx].desc;
396
397   /* In fips mode we only support NIST curves.  Note that it is
398      possible to bypass this check by specifying the curve parameters
399      directly.  */
400   if (fips_mode () && !domain_parms[idx].fips )
401     return GPG_ERR_NOT_SUPPORTED;
402
403   switch (domain_parms[idx].model)
404     {
405     case MPI_EC_WEIERSTRASS:
406     case MPI_EC_TWISTEDEDWARDS:
407       break;
408     case MPI_EC_MONTGOMERY:
409       return GPG_ERR_NOT_SUPPORTED;
410     default:
411       return GPG_ERR_BUG;
412     }
413
414
415   if (r_nbits)
416     *r_nbits = domain_parms[idx].nbits;
417
418   if (curve)
419     {
420       curve->model = domain_parms[idx].model;
421       curve->dialect = domain_parms[idx].dialect;
422       if (!curve->p)
423         curve->p = scanval (domain_parms[idx].p);
424       if (!curve->a)
425         curve->a = scanval (domain_parms[idx].a);
426       if (!curve->b)
427         curve->b = scanval (domain_parms[idx].b);
428       if (!curve->n)
429         curve->n = scanval (domain_parms[idx].n);
430       if (!curve->G.x)
431         curve->G.x = scanval (domain_parms[idx].g_x);
432       if (!curve->G.y)
433         curve->G.y = scanval (domain_parms[idx].g_y);
434       if (!curve->G.z)
435         curve->G.z = mpi_alloc_set_ui (1);
436       if (!curve->name)
437         curve->name = resname;
438     }
439
440   return 0;
441 }
442
443
444 /* Return the name matching the parameters in PKEY.  This works only
445    with curves described by the Weierstrass equation. */
446 const char *
447 _gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
448 {
449   gpg_err_code_t rc;
450   const char *result = NULL;
451   elliptic_curve_t E;
452   gcry_mpi_t mpi_g = NULL;
453   gcry_mpi_t tmp = NULL;
454   int idx;
455
456   memset (&E, 0, sizeof E);
457
458   if (r_nbits)
459     *r_nbits = 0;
460
461   if (!keyparms)
462     {
463       idx = iterator;
464       if (idx >= 0 && idx < DIM (domain_parms))
465         {
466           result = domain_parms[idx].desc;
467           if (r_nbits)
468             *r_nbits = domain_parms[idx].nbits;
469         }
470       return result;
471     }
472
473
474   /*
475    * Extract the curve parameters..
476    */
477   rc = gpg_err_code (_gcry_sexp_extract_param (keyparms, NULL, "-pabgn",
478                                                &E.p, &E.a, &E.b, &mpi_g, &E.n,
479                                                NULL));
480   if (rc == GPG_ERR_NO_OBJ)
481     {
482       /* This might be the second use case of checking whether a
483          specific curve given by name is supported.  */
484       gcry_sexp_t l1;
485       char *name;
486
487       l1 = gcry_sexp_find_token (keyparms, "curve", 5);
488       if (!l1)
489         goto leave;  /* No curve name parameter.  */
490
491       name = _gcry_sexp_nth_string (l1, 1);
492       gcry_sexp_release (l1);
493       if (!name)
494         goto leave;  /* Name missing or out of core. */
495
496       idx = find_domain_parms_idx (name);
497       gcry_free (name);
498       if (idx >= 0)  /* Curve found.  */
499         {
500           result = domain_parms[idx].desc;
501           if (r_nbits)
502             *r_nbits = domain_parms[idx].nbits;
503         }
504       return result;
505     }
506
507   if (rc)
508     goto leave;
509
510   if (mpi_g)
511     {
512       _gcry_mpi_point_init (&E.G);
513       if (_gcry_ecc_os2ec (&E.G, mpi_g))
514         goto leave;
515     }
516
517   for (idx = 0; domain_parms[idx].desc; idx++)
518     {
519       tmp = scanval (domain_parms[idx].p);
520       if (!mpi_cmp (tmp, E.p))
521         {
522           mpi_free (tmp);
523           tmp = scanval (domain_parms[idx].a);
524           if (!mpi_cmp (tmp, E.a))
525             {
526               mpi_free (tmp);
527               tmp = scanval (domain_parms[idx].b);
528               if (!mpi_cmp (tmp, E.b))
529                 {
530                   mpi_free (tmp);
531                   tmp = scanval (domain_parms[idx].n);
532                   if (!mpi_cmp (tmp, E.n))
533                     {
534                       mpi_free (tmp);
535                       tmp = scanval (domain_parms[idx].g_x);
536                       if (!mpi_cmp (tmp, E.G.x))
537                         {
538                           mpi_free (tmp);
539                           tmp = scanval (domain_parms[idx].g_y);
540                           if (!mpi_cmp (tmp, E.G.y))
541                             {
542                               result = domain_parms[idx].desc;
543                               if (r_nbits)
544                                 *r_nbits = domain_parms[idx].nbits;
545                               goto leave;
546                             }
547                         }
548                     }
549                 }
550             }
551         }
552     }
553
554  leave:
555   gcry_mpi_release (tmp);
556   gcry_mpi_release (E.p);
557   gcry_mpi_release (E.a);
558   gcry_mpi_release (E.b);
559   gcry_mpi_release (mpi_g);
560   _gcry_mpi_point_free_parts (&E.G);
561   gcry_mpi_release (E.n);
562   return result;
563 }
564
565
566 /* Helper to extract an MPI from key parameters.  */
567 static gpg_err_code_t
568 mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name)
569 {
570   gcry_err_code_t ec = 0;
571   gcry_sexp_t l1;
572
573   l1 = gcry_sexp_find_token (keyparam, name, 0);
574   if (l1)
575     {
576       *r_a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
577       gcry_sexp_release (l1);
578       if (!*r_a)
579         ec = GPG_ERR_INV_OBJ;
580     }
581   return ec;
582 }
583
584 /* Helper to extract a point from key parameters.  If no parameter
585    with NAME is found, the functions tries to find a non-encoded point
586    by appending ".x", ".y" and ".z" to NAME.  ".z" is in this case
587    optional and defaults to 1.  EC is the context which at this point
588    may not be fully initialized. */
589 static gpg_err_code_t
590 point_from_keyparam (gcry_mpi_point_t *r_a,
591                      gcry_sexp_t keyparam, const char *name, mpi_ec_t ec)
592 {
593   gcry_err_code_t rc;
594   gcry_sexp_t l1;
595   gcry_mpi_point_t point;
596
597   l1 = gcry_sexp_find_token (keyparam, name, 0);
598   if (l1)
599     {
600       gcry_mpi_t a;
601
602       a = _gcry_sexp_nth_opaque_mpi (l1, 1);
603       gcry_sexp_release (l1);
604       if (!a)
605         return GPG_ERR_INV_OBJ;
606
607       point = gcry_mpi_point_new (0);
608       if (ec && ec->dialect == ECC_DIALECT_ED25519)
609         rc = _gcry_ecc_eddsa_decodepoint (a, ec, point, NULL, NULL);
610       else
611         rc = _gcry_ecc_os2ec (point, a);
612       mpi_free (a);
613       if (rc)
614         {
615           gcry_mpi_point_release (point);
616           return rc;
617         }
618     }
619   else
620     {
621       char *tmpname;
622       gcry_mpi_t x = NULL;
623       gcry_mpi_t y = NULL;
624       gcry_mpi_t z = NULL;
625
626       tmpname = gcry_malloc (strlen (name) + 2 + 1);
627       if (!tmpname)
628         return gpg_err_code_from_syserror ();
629       strcpy (stpcpy (tmpname, name), ".x");
630       rc = mpi_from_keyparam (&x, keyparam, tmpname);
631       if (rc)
632         {
633           gcry_free (tmpname);
634           return rc;
635         }
636       strcpy (stpcpy (tmpname, name), ".y");
637       rc = mpi_from_keyparam (&y, keyparam, tmpname);
638       if (rc)
639         {
640           mpi_free (x);
641           gcry_free (tmpname);
642           return rc;
643         }
644       strcpy (stpcpy (tmpname, name), ".z");
645       rc = mpi_from_keyparam (&z, keyparam, tmpname);
646       if (rc)
647         {
648           mpi_free (y);
649           mpi_free (x);
650           gcry_free (tmpname);
651           return rc;
652         }
653       if (!z)
654         z = mpi_set_ui (NULL, 1);
655       if (x && y)
656         point = gcry_mpi_point_snatch_set (NULL, x, y, z);
657       else
658         {
659           mpi_free (x);
660           mpi_free (y);
661           mpi_free (z);
662           point = NULL;
663         }
664       gcry_free (tmpname);
665     }
666
667   if (point)
668     *r_a = point;
669   return 0;
670 }
671
672
673 /* This function creates a new context for elliptic curve operations.
674    Either KEYPARAM or CURVENAME must be given.  If both are given and
675    KEYPARAM has no curve parameter, CURVENAME is used to add missing
676    parameters.  On success 0 is returned and the new context stored at
677    R_CTX.  On error NULL is stored at R_CTX and an error code is
678    returned.  The context needs to be released using
679    gcry_ctx_release.  */
680 gpg_err_code_t
681 _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
682                   gcry_sexp_t keyparam, const char *curvename)
683 {
684   gpg_err_code_t errc;
685   gcry_ctx_t ctx = NULL;
686   enum gcry_mpi_ec_models model = MPI_EC_WEIERSTRASS;
687   enum ecc_dialects dialect = ECC_DIALECT_STANDARD;
688   gcry_mpi_t p = NULL;
689   gcry_mpi_t a = NULL;
690   gcry_mpi_t b = NULL;
691   gcry_mpi_point_t G = NULL;
692   gcry_mpi_t n = NULL;
693   gcry_mpi_point_t Q = NULL;
694   gcry_mpi_t d = NULL;
695   int flags = 0;
696   gcry_sexp_t l1;
697
698   *r_ctx = NULL;
699
700   if (keyparam)
701     {
702       /* Parse an optional flags list.  */
703       l1 = gcry_sexp_find_token (keyparam, "flags", 0);
704       if (l1)
705         {
706           errc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
707           gcry_sexp_release (l1);
708           l1 = NULL;
709           if (errc)
710             goto leave;
711         }
712
713       /* Check whether a curve name was given.  */
714       l1 = gcry_sexp_find_token (keyparam, "curve", 5);
715
716       /* If we don't have a curve name or if override parameters have
717          explicitly been requested, parse them.  */
718       if (!l1 || (flags & PUBKEY_FLAG_PARAM))
719         {
720           errc = mpi_from_keyparam (&p, keyparam, "p");
721           if (errc)
722             goto leave;
723           errc = mpi_from_keyparam (&a, keyparam, "a");
724           if (errc)
725             goto leave;
726           errc = mpi_from_keyparam (&b, keyparam, "b");
727           if (errc)
728             goto leave;
729           errc = point_from_keyparam (&G, keyparam, "g", NULL);
730           if (errc)
731             goto leave;
732           errc = mpi_from_keyparam (&n, keyparam, "n");
733           if (errc)
734             goto leave;
735         }
736     }
737   else
738     l1 = NULL; /* No curvename.  */
739
740   /* Check whether a curve parameter is available and use that to fill
741      in missing values.  If no curve parameter is available try an
742      optional provided curvename.  If only the curvename has been
743      given use that one. */
744   if (l1 || curvename)
745     {
746       char *name;
747       elliptic_curve_t *E;
748
749       if (l1)
750         {
751           name = _gcry_sexp_nth_string (l1, 1);
752           gcry_sexp_release (l1);
753           if (!name)
754             {
755               errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
756               goto leave;
757             }
758         }
759       else
760         name = NULL;
761
762       E = gcry_calloc (1, sizeof *E);
763       if (!E)
764         {
765           errc = gpg_err_code_from_syserror ();
766           gcry_free (name);
767           goto leave;
768         }
769
770       errc = _gcry_ecc_fill_in_curve (0, name? name : curvename, E, NULL);
771       gcry_free (name);
772       if (errc)
773         {
774           gcry_free (E);
775           goto leave;
776         }
777
778       model = E->model;
779       dialect = E->dialect;
780
781       if (!p)
782         {
783           p = E->p;
784           E->p = NULL;
785         }
786       if (!a)
787         {
788           a = E->a;
789           E->a = NULL;
790         }
791       if (!b)
792         {
793           b = E->b;
794           E->b = NULL;
795         }
796       if (!G)
797         {
798           G = gcry_mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
799           E->G.x = NULL;
800           E->G.y = NULL;
801           E->G.z = NULL;
802         }
803       if (!n)
804         {
805           n = E->n;
806           E->n = NULL;
807         }
808       _gcry_ecc_curve_free (E);
809       gcry_free (E);
810     }
811
812
813   errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, flags, p, a, b);
814   if (!errc)
815     {
816       mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
817
818       if (b)
819         {
820           ec->b = b;
821           b = NULL;
822         }
823       if (G)
824         {
825           ec->G = G;
826           G = NULL;
827         }
828       if (n)
829         {
830           ec->n = n;
831           n = NULL;
832         }
833
834       /* Now that we now the curve name we can look for the public key
835          Q.  point_from_keyparam needs to know the curve parameters so
836          that it is able to use the correct decompression.  Parsing
837          the private key D could have been done earlier but it is less
838          surprising if we do it here as well.  */
839       if (keyparam)
840         {
841           errc = point_from_keyparam (&Q, keyparam, "q", ec);
842           if (errc)
843             goto leave;
844           errc = mpi_from_keyparam (&d, keyparam, "d");
845           if (errc)
846             goto leave;
847         }
848
849       if (Q)
850         {
851           ec->Q = Q;
852           Q = NULL;
853         }
854       if (d)
855         {
856           ec->d = d;
857           d = NULL;
858         }
859
860       *r_ctx = ctx;
861       ctx = NULL;
862     }
863
864  leave:
865   gcry_ctx_release (ctx);
866   mpi_free (p);
867   mpi_free (a);
868   mpi_free (b);
869   gcry_mpi_point_release (G);
870   mpi_free (n);
871   gcry_mpi_point_release (Q);
872   mpi_free (d);
873   return errc;
874 }
875
876
877 /* Return the parameters of the curve NAME in an MPI array.  */
878 gcry_err_code_t
879 _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey)
880 {
881   gpg_err_code_t err;
882   unsigned int nbits;
883   elliptic_curve_t E;
884   mpi_ec_t ctx;
885   gcry_mpi_t g_x, g_y;
886
887   memset (&E, 0, sizeof E);
888   err = _gcry_ecc_fill_in_curve (0, name, &E, &nbits);
889   if (err)
890     return err;
891
892   g_x = mpi_new (0);
893   g_y = mpi_new (0);
894   ctx = _gcry_mpi_ec_p_internal_new (MPI_EC_WEIERSTRASS,
895                                      ECC_DIALECT_STANDARD,
896                                      0,
897                                      E.p, E.a, NULL);
898   if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
899     log_fatal ("ecc get param: Failed to get affine coordinates\n");
900   _gcry_mpi_ec_free (ctx);
901   _gcry_mpi_point_free_parts (&E.G);
902
903   pkey[0] = E.p;
904   pkey[1] = E.a;
905   pkey[2] = E.b;
906   pkey[3] = _gcry_ecc_ec2os (g_x, g_y, E.p);
907   pkey[4] = E.n;
908   pkey[5] = NULL;
909
910   mpi_free (g_x);
911   mpi_free (g_y);
912
913   return 0;
914 }
915
916
917 /* Return the parameters of the curve NAME as an S-expression.  */
918 gcry_sexp_t
919 _gcry_ecc_get_param_sexp (const char *name)
920 {
921   gcry_mpi_t pkey[6];
922   gcry_sexp_t result;
923   int i;
924
925   if (_gcry_ecc_get_param (name, pkey))
926     return NULL;
927
928   if (gcry_sexp_build (&result, NULL,
929                        "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))",
930                        pkey[0], pkey[1], pkey[2], pkey[3], pkey[4]))
931     result = NULL;
932
933   for (i=0; pkey[i]; i++)
934     gcry_mpi_release (pkey[i]);
935
936   return result;
937 }
938
939
940 /* Return an MPI (or opaque MPI) described by NAME and the context EC.
941    If COPY is true a copy is returned, if not a const MPI may be
942    returned.  In any case mpi_free must be used.  */
943 gcry_mpi_t
944 _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy)
945 {
946   if (!*name)
947     return NULL;
948
949   if (!strcmp (name, "p") && ec->p)
950     return mpi_is_const (ec->p) && !copy? ec->p : mpi_copy (ec->p);
951   if (!strcmp (name, "a") && ec->a)
952     return mpi_is_const (ec->a) && !copy? ec->a : mpi_copy (ec->a);
953   if (!strcmp (name, "b") && ec->b)
954     return mpi_is_const (ec->b) && !copy? ec->b : mpi_copy (ec->b);
955   if (!strcmp (name, "n") && ec->n)
956     return mpi_is_const (ec->n) && !copy? ec->n : mpi_copy (ec->n);
957   if (!strcmp (name, "d") && ec->d)
958     return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d);
959
960   /* Return a requested point coordinate.  */
961   if (!strcmp (name, "g.x") && ec->G && ec->G->x)
962     return mpi_is_const (ec->G->x) && !copy? ec->G->x : mpi_copy (ec->G->x);
963   if (!strcmp (name, "g.y") && ec->G && ec->G->y)
964     return mpi_is_const (ec->G->y) && !copy? ec->G->y : mpi_copy (ec->G->y);
965   if (!strcmp (name, "q.x") && ec->Q && ec->Q->x)
966     return mpi_is_const (ec->Q->x) && !copy? ec->Q->x : mpi_copy (ec->Q->x);
967   if (!strcmp (name, "q.y") && ec->Q && ec->Q->y)
968     return mpi_is_const (ec->G->y) && !copy? ec->Q->y : mpi_copy (ec->Q->y);
969
970   /* If the base point has been requested, return it in standard
971      encoding.  */
972   if (!strcmp (name, "g") && ec->G)
973     return _gcry_mpi_ec_ec2os (ec->G, ec);
974
975   /* If the public key has been requested, return it by default in
976      standard uncompressed encoding or if requested in other
977      encodings.  */
978   if (*name == 'q' && (!name[1] || name[1] == '@'))
979     {
980       /* If only the private key is given, compute the public key.  */
981       if (!ec->Q)
982         ec->Q = _gcry_ecc_compute_public (NULL, ec);
983
984       if (!ec->Q)
985         return NULL;
986
987       if (name[1] != '@')
988         return _gcry_mpi_ec_ec2os (ec->Q, ec);
989
990       if (!strcmp (name+2, "eddsa") && ec->model == MPI_EC_TWISTEDEDWARDS)
991         {
992           unsigned char *encpk;
993           unsigned int encpklen;
994
995           if (!_gcry_ecc_eddsa_encodepoint (ec->Q, ec, NULL, NULL,
996                                             &encpk, &encpklen))
997             return gcry_mpi_set_opaque (NULL, encpk, encpklen*8);
998         }
999     }
1000
1001   return NULL;
1002 }
1003
1004
1005 /* Return a point described by NAME and the context EC.  */
1006 gcry_mpi_point_t
1007 _gcry_ecc_get_point (const char *name, mpi_ec_t ec)
1008 {
1009   if (!strcmp (name, "g") && ec->G)
1010     return point_copy (ec->G);
1011   if (!strcmp (name, "q"))
1012     {
1013       /* If only the private key is given, compute the public key.  */
1014       if (!ec->Q)
1015         ec->Q = _gcry_ecc_compute_public (NULL, ec);
1016
1017       if (ec->Q)
1018         return point_copy (ec->Q);
1019     }
1020
1021   return NULL;
1022 }
1023
1024
1025 /* Store the MPI NEWVALUE into the context EC under NAME. */
1026 gpg_err_code_t
1027 _gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec)
1028 {
1029   gpg_err_code_t rc = 0;
1030
1031   if (!*name)
1032     ;
1033   else if (!strcmp (name, "p"))
1034     {
1035       mpi_free (ec->p);
1036       ec->p = mpi_copy (newvalue);
1037       _gcry_mpi_ec_get_reset (ec);
1038     }
1039   else if (!strcmp (name, "a"))
1040     {
1041       mpi_free (ec->a);
1042       ec->a = mpi_copy (newvalue);
1043       _gcry_mpi_ec_get_reset (ec);
1044     }
1045   else if (!strcmp (name, "b"))
1046     {
1047       mpi_free (ec->b);
1048       ec->b = mpi_copy (newvalue);
1049     }
1050   else if (!strcmp (name, "n"))
1051     {
1052       mpi_free (ec->n);
1053       ec->n = mpi_copy (newvalue);
1054     }
1055   else if (*name == 'q' && (!name[1] || name[1] == '@'))
1056     {
1057       if (newvalue)
1058         {
1059           if (!ec->Q)
1060             ec->Q = gcry_mpi_point_new (0);
1061           if (ec->dialect == ECC_DIALECT_ED25519)
1062             rc = _gcry_ecc_eddsa_decodepoint (newvalue, ec, ec->Q, NULL, NULL);
1063           else
1064             rc = _gcry_ecc_os2ec (ec->Q, newvalue);
1065         }
1066       if (rc || !newvalue)
1067         {
1068           gcry_mpi_point_release (ec->Q);
1069           ec->Q = NULL;
1070         }
1071       /* Note: We assume that Q matches d and thus do not reset d.  */
1072     }
1073   else if (!strcmp (name, "d"))
1074     {
1075       mpi_free (ec->d);
1076       ec->d = mpi_copy (newvalue);
1077       if (ec->d)
1078         {
1079           /* We need to reset the public key because it may not
1080              anymore match.  */
1081           gcry_mpi_point_release (ec->Q);
1082           ec->Q = NULL;
1083         }
1084     }
1085   else
1086    rc = GPG_ERR_UNKNOWN_NAME;
1087
1088   return rc;
1089 }
1090
1091
1092 /* Store the point NEWVALUE into the context EC under NAME.  */
1093 gpg_err_code_t
1094 _gcry_ecc_set_point (const char *name, gcry_mpi_point_t newvalue, mpi_ec_t ec)
1095 {
1096   if (!strcmp (name, "g"))
1097     {
1098       gcry_mpi_point_release (ec->G);
1099       ec->G = point_copy (newvalue);
1100     }
1101   else if (!strcmp (name, "q"))
1102     {
1103       gcry_mpi_point_release (ec->Q);
1104       ec->Q = point_copy (newvalue);
1105     }
1106   else
1107     return GPG_ERR_UNKNOWN_NAME;
1108
1109   return 0;
1110 }