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