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