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