3488ed37f670c2ea42b1c2dfd0d6dfcdbd51b232
[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, 0,
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         {
564           curve->a = scanval (domain_parms[idx].a);
565           if (curve->a->sign)
566             mpi_add (curve->a, curve->p, curve->a);
567         }
568       if (!curve->b)
569         {
570           curve->b = scanval (domain_parms[idx].b);
571           if (curve->b->sign)
572             mpi_add (curve->b, curve->p, curve->b);
573         }
574       if (!curve->n)
575         curve->n = scanval (domain_parms[idx].n);
576       if (!curve->h)
577         curve->h = scanval (domain_parms[idx].h);
578       if (!curve->G.x)
579         curve->G.x = scanval (domain_parms[idx].g_x);
580       if (!curve->G.y)
581         curve->G.y = scanval (domain_parms[idx].g_y);
582       if (!curve->G.z)
583         curve->G.z = mpi_alloc_set_ui (1);
584       if (!curve->name)
585         curve->name = resname;
586     }
587
588   return 0;
589 }
590
591
592 /* Give the name of the curve NAME, store the curve parameters into P,
593    A, B, G, N, and H if they point to NULL value.  Note that G is returned
594    in standard uncompressed format.  Also update MODEL and DIALECT if
595    they are not NULL. */
596 gpg_err_code_t
597 _gcry_ecc_update_curve_param (const char *name,
598                               enum gcry_mpi_ec_models *model,
599                               enum ecc_dialects *dialect,
600                               gcry_mpi_t *p, gcry_mpi_t *a, gcry_mpi_t *b,
601                               gcry_mpi_t *g, gcry_mpi_t *n, gcry_mpi_t *h)
602 {
603   int idx;
604
605   idx = find_domain_parms_idx (name);
606   if (idx < 0)
607     return GPG_ERR_UNKNOWN_CURVE;
608
609   if (g)
610     {
611       char *buf;
612       size_t len;
613
614       len = 4;
615       len += strlen (domain_parms[idx].g_x+2);
616       len += strlen (domain_parms[idx].g_y+2);
617       len++;
618       buf = xtrymalloc (len);
619       if (!buf)
620         return gpg_err_code_from_syserror ();
621       strcpy (stpcpy (stpcpy (buf, "0x04"), domain_parms[idx].g_x+2),
622               domain_parms[idx].g_y+2);
623       _gcry_mpi_release (*g);
624       *g = scanval (buf);
625       xfree (buf);
626     }
627   if (model)
628     *model = domain_parms[idx].model;
629   if (dialect)
630     *dialect = domain_parms[idx].dialect;
631   if (p)
632     {
633       _gcry_mpi_release (*p);
634       *p = scanval (domain_parms[idx].p);
635     }
636   if (a)
637     {
638       _gcry_mpi_release (*a);
639       *a = scanval (domain_parms[idx].a);
640     }
641   if (b)
642     {
643       _gcry_mpi_release (*b);
644       *b = scanval (domain_parms[idx].b);
645     }
646   if (n)
647     {
648       _gcry_mpi_release (*n);
649       *n = scanval (domain_parms[idx].n);
650     }
651   if (h)
652     {
653       _gcry_mpi_release (*h);
654       *h = scanval (domain_parms[idx].h);
655     }
656   return 0;
657 }
658
659
660 /* Return the name matching the parameters in PKEY.  This works only
661    with curves described by the Weierstrass equation. */
662 const char *
663 _gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
664 {
665   gpg_err_code_t rc;
666   const char *result = NULL;
667   elliptic_curve_t E;
668   gcry_mpi_t mpi_g = NULL;
669   gcry_mpi_t tmp = NULL;
670   int idx;
671
672   memset (&E, 0, sizeof E);
673
674   if (r_nbits)
675     *r_nbits = 0;
676
677   if (!keyparms)
678     {
679       idx = iterator;
680       if (idx >= 0 && idx < DIM (domain_parms))
681         {
682           result = domain_parms[idx].desc;
683           if (r_nbits)
684             *r_nbits = domain_parms[idx].nbits;
685         }
686       return result;
687     }
688
689
690   /*
691    * Extract the curve parameters..
692    */
693   rc = gpg_err_code (sexp_extract_param (keyparms, NULL, "-pabgnh",
694                                          &E.p, &E.a, &E.b, &mpi_g, &E.n, &E.h,
695                                          NULL));
696   if (rc == GPG_ERR_NO_OBJ)
697     {
698       /* This might be the second use case of checking whether a
699          specific curve given by name is supported.  */
700       gcry_sexp_t l1;
701       char *name;
702
703       l1 = sexp_find_token (keyparms, "curve", 5);
704       if (!l1)
705         goto leave;  /* No curve name parameter.  */
706
707       name = sexp_nth_string (l1, 1);
708       sexp_release (l1);
709       if (!name)
710         goto leave;  /* Name missing or out of core. */
711
712       idx = find_domain_parms_idx (name);
713       xfree (name);
714       if (idx >= 0)  /* Curve found.  */
715         {
716           result = domain_parms[idx].desc;
717           if (r_nbits)
718             *r_nbits = domain_parms[idx].nbits;
719         }
720       return result;
721     }
722
723   if (rc)
724     goto leave;
725
726   if (mpi_g)
727     {
728       _gcry_mpi_point_init (&E.G);
729       if (_gcry_ecc_os2ec (&E.G, mpi_g))
730         goto leave;
731     }
732
733   for (idx = 0; domain_parms[idx].desc; idx++)
734     {
735       mpi_free (tmp);
736       tmp = scanval (domain_parms[idx].p);
737       if (!mpi_cmp (tmp, E.p))
738         {
739           mpi_free (tmp);
740           tmp = scanval (domain_parms[idx].a);
741           if (!mpi_cmp (tmp, E.a))
742             {
743               mpi_free (tmp);
744               tmp = scanval (domain_parms[idx].b);
745               if (!mpi_cmp (tmp, E.b))
746                 {
747                   mpi_free (tmp);
748                   tmp = scanval (domain_parms[idx].n);
749                   if (!mpi_cmp (tmp, E.n))
750                     {
751                       mpi_free (tmp);
752                       tmp = scanval (domain_parms[idx].h);
753                       if (!mpi_cmp (tmp, E.h))
754                         {
755                           mpi_free (tmp);
756                           tmp = scanval (domain_parms[idx].g_x);
757                           if (!mpi_cmp (tmp, E.G.x))
758                             {
759                               mpi_free (tmp);
760                               tmp = scanval (domain_parms[idx].g_y);
761                               if (!mpi_cmp (tmp, E.G.y))
762                                 {
763                                   result = domain_parms[idx].desc;
764                                   if (r_nbits)
765                                     *r_nbits = domain_parms[idx].nbits;
766                                   goto leave;
767                                 }
768                             }
769                         }
770                     }
771                 }
772             }
773         }
774     }
775
776  leave:
777   _gcry_mpi_release (tmp);
778   _gcry_mpi_release (E.p);
779   _gcry_mpi_release (E.a);
780   _gcry_mpi_release (E.b);
781   _gcry_mpi_release (mpi_g);
782   _gcry_mpi_point_free_parts (&E.G);
783   _gcry_mpi_release (E.n);
784   _gcry_mpi_release (E.h);
785   return result;
786 }
787
788
789 /* Helper to extract an MPI from key parameters.  */
790 static gpg_err_code_t
791 mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name)
792 {
793   gcry_err_code_t ec = 0;
794   gcry_sexp_t l1;
795
796   l1 = sexp_find_token (keyparam, name, 0);
797   if (l1)
798     {
799       *r_a = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
800       sexp_release (l1);
801       if (!*r_a)
802         ec = GPG_ERR_INV_OBJ;
803     }
804   return ec;
805 }
806
807 /* Helper to extract a point from key parameters.  If no parameter
808    with NAME is found, the functions tries to find a non-encoded point
809    by appending ".x", ".y" and ".z" to NAME.  ".z" is in this case
810    optional and defaults to 1.  EC is the context which at this point
811    may not be fully initialized. */
812 static gpg_err_code_t
813 point_from_keyparam (gcry_mpi_point_t *r_a,
814                      gcry_sexp_t keyparam, const char *name, mpi_ec_t ec)
815 {
816   gcry_err_code_t rc;
817   gcry_sexp_t l1;
818   gcry_mpi_point_t point;
819
820   l1 = sexp_find_token (keyparam, name, 0);
821   if (l1)
822     {
823       gcry_mpi_t a;
824
825       a = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
826       sexp_release (l1);
827       if (!a)
828         return GPG_ERR_INV_OBJ;
829
830       point = mpi_point_new (0);
831       if (ec && ec->dialect == ECC_DIALECT_ED25519)
832         rc = _gcry_ecc_eddsa_decodepoint (a, ec, point, NULL, NULL);
833       else
834         rc = _gcry_ecc_os2ec (point, a);
835       mpi_free (a);
836       if (rc)
837         {
838           mpi_point_release (point);
839           return rc;
840         }
841     }
842   else
843     {
844       char *tmpname;
845       gcry_mpi_t x = NULL;
846       gcry_mpi_t y = NULL;
847       gcry_mpi_t z = NULL;
848
849       tmpname = xtrymalloc (strlen (name) + 2 + 1);
850       if (!tmpname)
851         return gpg_err_code_from_syserror ();
852       strcpy (stpcpy (tmpname, name), ".x");
853       rc = mpi_from_keyparam (&x, keyparam, tmpname);
854       if (rc)
855         {
856           xfree (tmpname);
857           return rc;
858         }
859       strcpy (stpcpy (tmpname, name), ".y");
860       rc = mpi_from_keyparam (&y, keyparam, tmpname);
861       if (rc)
862         {
863           mpi_free (x);
864           xfree (tmpname);
865           return rc;
866         }
867       strcpy (stpcpy (tmpname, name), ".z");
868       rc = mpi_from_keyparam (&z, keyparam, tmpname);
869       if (rc)
870         {
871           mpi_free (y);
872           mpi_free (x);
873           xfree (tmpname);
874           return rc;
875         }
876       if (!z)
877         z = mpi_set_ui (NULL, 1);
878       if (x && y)
879         point = mpi_point_snatch_set (NULL, x, y, z);
880       else
881         {
882           mpi_free (x);
883           mpi_free (y);
884           mpi_free (z);
885           point = NULL;
886         }
887       xfree (tmpname);
888     }
889
890   if (point)
891     *r_a = point;
892   return 0;
893 }
894
895
896 /* This function creates a new context for elliptic curve operations.
897    Either KEYPARAM or CURVENAME must be given.  If both are given and
898    KEYPARAM has no curve parameter, CURVENAME is used to add missing
899    parameters.  On success 0 is returned and the new context stored at
900    R_CTX.  On error NULL is stored at R_CTX and an error code is
901    returned.  The context needs to be released using
902    gcry_ctx_release.  */
903 gpg_err_code_t
904 _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
905                   gcry_sexp_t keyparam, const char *curvename)
906 {
907   gpg_err_code_t errc;
908   gcry_ctx_t ctx = NULL;
909   enum gcry_mpi_ec_models model = MPI_EC_WEIERSTRASS;
910   enum ecc_dialects dialect = ECC_DIALECT_STANDARD;
911   gcry_mpi_t p = NULL;
912   gcry_mpi_t a = NULL;
913   gcry_mpi_t b = NULL;
914   gcry_mpi_point_t G = NULL;
915   gcry_mpi_t n = NULL;
916   gcry_mpi_t h = NULL;
917   gcry_mpi_point_t Q = NULL;
918   gcry_mpi_t d = NULL;
919   int flags = 0;
920   gcry_sexp_t l1;
921
922   *r_ctx = NULL;
923
924   if (keyparam)
925     {
926       /* Parse an optional flags list.  */
927       l1 = sexp_find_token (keyparam, "flags", 0);
928       if (l1)
929         {
930           errc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
931           sexp_release (l1);
932           l1 = NULL;
933           if (errc)
934             goto leave;
935         }
936
937       /* Check whether a curve name was given.  */
938       l1 = sexp_find_token (keyparam, "curve", 5);
939
940       /* If we don't have a curve name or if override parameters have
941          explicitly been requested, parse them.  */
942       if (!l1 || (flags & PUBKEY_FLAG_PARAM))
943         {
944           errc = mpi_from_keyparam (&p, keyparam, "p");
945           if (errc)
946             goto leave;
947           errc = mpi_from_keyparam (&a, keyparam, "a");
948           if (errc)
949             goto leave;
950           errc = mpi_from_keyparam (&b, keyparam, "b");
951           if (errc)
952             goto leave;
953           errc = point_from_keyparam (&G, keyparam, "g", NULL);
954           if (errc)
955             goto leave;
956           errc = mpi_from_keyparam (&n, keyparam, "n");
957           if (errc)
958             goto leave;
959           errc = mpi_from_keyparam (&h, keyparam, "h");
960           if (errc)
961             goto leave;
962         }
963     }
964   else
965     l1 = NULL; /* No curvename.  */
966
967   /* Check whether a curve parameter is available and use that to fill
968      in missing values.  If no curve parameter is available try an
969      optional provided curvename.  If only the curvename has been
970      given use that one. */
971   if (l1 || curvename)
972     {
973       char *name;
974       elliptic_curve_t *E;
975
976       if (l1)
977         {
978           name = sexp_nth_string (l1, 1);
979           sexp_release (l1);
980           if (!name)
981             {
982               errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
983               goto leave;
984             }
985         }
986       else
987         name = NULL;
988
989       E = xtrycalloc (1, sizeof *E);
990       if (!E)
991         {
992           errc = gpg_err_code_from_syserror ();
993           xfree (name);
994           goto leave;
995         }
996
997       errc = _gcry_ecc_fill_in_curve (0, name? name : curvename, E, NULL);
998       xfree (name);
999       if (errc)
1000         {
1001           xfree (E);
1002           goto leave;
1003         }
1004
1005       model = E->model;
1006       dialect = E->dialect;
1007
1008       if (!p)
1009         {
1010           p = E->p;
1011           E->p = NULL;
1012         }
1013       if (!a)
1014         {
1015           a = E->a;
1016           E->a = NULL;
1017         }
1018       if (!b)
1019         {
1020           b = E->b;
1021           E->b = NULL;
1022         }
1023       if (!G)
1024         {
1025           G = mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
1026           E->G.x = NULL;
1027           E->G.y = NULL;
1028           E->G.z = NULL;
1029         }
1030       if (!n)
1031         {
1032           n = E->n;
1033           E->n = NULL;
1034         }
1035       if (!h)
1036         {
1037           h = E->h;
1038           E->h = NULL;
1039         }
1040       _gcry_ecc_curve_free (E);
1041       xfree (E);
1042     }
1043
1044
1045   errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, flags, p, a, b);
1046   if (!errc)
1047     {
1048       mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
1049
1050       if (b)
1051         {
1052           mpi_free (ec->b);
1053           ec->b = b;
1054           b = NULL;
1055         }
1056       if (G)
1057         {
1058           ec->G = G;
1059           G = NULL;
1060         }
1061       if (n)
1062         {
1063           ec->n = n;
1064           n = NULL;
1065         }
1066       if (h)
1067         {
1068           ec->h = h;
1069           h = NULL;
1070         }
1071
1072       /* Now that we know the curve name we can look for the public key
1073          Q.  point_from_keyparam needs to know the curve parameters so
1074          that it is able to use the correct decompression.  Parsing
1075          the private key D could have been done earlier but it is less
1076          surprising if we do it here as well.  */
1077       if (keyparam)
1078         {
1079           errc = point_from_keyparam (&Q, keyparam, "q", ec);
1080           if (errc)
1081             goto leave;
1082           errc = mpi_from_keyparam (&d, keyparam, "d");
1083           if (errc)
1084             goto leave;
1085         }
1086
1087       if (Q)
1088         {
1089           ec->Q = Q;
1090           Q = NULL;
1091         }
1092       if (d)
1093         {
1094           ec->d = d;
1095           d = NULL;
1096         }
1097
1098       *r_ctx = ctx;
1099       ctx = NULL;
1100     }
1101
1102  leave:
1103   _gcry_ctx_release (ctx);
1104   mpi_free (p);
1105   mpi_free (a);
1106   mpi_free (b);
1107   _gcry_mpi_point_release (G);
1108   mpi_free (n);
1109   mpi_free (h);
1110   _gcry_mpi_point_release (Q);
1111   mpi_free (d);
1112   return errc;
1113 }
1114
1115
1116 /* Return the parameters of the curve NAME as an S-expression.  */
1117 gcry_sexp_t
1118 _gcry_ecc_get_param_sexp (const char *name)
1119 {
1120   unsigned int nbits;
1121   elliptic_curve_t E;
1122   mpi_ec_t ctx;
1123   gcry_mpi_t g_x, g_y;
1124   gcry_mpi_t pkey[7];
1125   gcry_sexp_t result;
1126   int i;
1127
1128   memset (&E, 0, sizeof E);
1129   if (_gcry_ecc_fill_in_curve (0, name, &E, &nbits))
1130     return NULL;
1131
1132   g_x = mpi_new (0);
1133   g_y = mpi_new (0);
1134   ctx = _gcry_mpi_ec_p_internal_new (MPI_EC_WEIERSTRASS,
1135                                      ECC_DIALECT_STANDARD,
1136                                      0,
1137                                      E.p, E.a, NULL);
1138   if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
1139     log_fatal ("ecc get param: Failed to get affine coordinates\n");
1140   _gcry_mpi_ec_free (ctx);
1141   _gcry_mpi_point_free_parts (&E.G);
1142
1143   pkey[0] = E.p;
1144   pkey[1] = E.a;
1145   pkey[2] = E.b;
1146   pkey[3] = _gcry_ecc_ec2os (g_x, g_y, E.p);
1147   pkey[4] = E.n;
1148   pkey[5] = E.h;
1149   pkey[6] = NULL;
1150
1151   mpi_free (g_x);
1152   mpi_free (g_y);
1153
1154   if (sexp_build (&result, NULL,
1155                   "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)))",
1156                   pkey[0], pkey[1], pkey[2], pkey[3], pkey[4], pkey[5]))
1157     result = NULL;
1158
1159   for (i=0; pkey[i]; i++)
1160     _gcry_mpi_release (pkey[i]);
1161
1162   return result;
1163 }
1164
1165
1166 /* Return an MPI (or opaque MPI) described by NAME and the context EC.
1167    If COPY is true a copy is returned, if not a const MPI may be
1168    returned.  In any case mpi_free must be used.  */
1169 gcry_mpi_t
1170 _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy)
1171 {
1172   if (!*name)
1173     return NULL;
1174
1175   if (!strcmp (name, "p") && ec->p)
1176     return mpi_is_const (ec->p) && !copy? ec->p : mpi_copy (ec->p);
1177   if (!strcmp (name, "a") && ec->a)
1178     return mpi_is_const (ec->a) && !copy? ec->a : mpi_copy (ec->a);
1179   if (!strcmp (name, "b") && ec->b)
1180     return mpi_is_const (ec->b) && !copy? ec->b : mpi_copy (ec->b);
1181   if (!strcmp (name, "n") && ec->n)
1182     return mpi_is_const (ec->n) && !copy? ec->n : mpi_copy (ec->n);
1183   if (!strcmp (name, "h") && ec->h)
1184     return mpi_is_const (ec->h) && !copy? ec->h : mpi_copy (ec->h);
1185   if (!strcmp (name, "d") && ec->d)
1186     return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d);
1187
1188   /* Return a requested point coordinate.  */
1189   if (!strcmp (name, "g.x") && ec->G && ec->G->x)
1190     return mpi_is_const (ec->G->x) && !copy? ec->G->x : mpi_copy (ec->G->x);
1191   if (!strcmp (name, "g.y") && ec->G && ec->G->y)
1192     return mpi_is_const (ec->G->y) && !copy? ec->G->y : mpi_copy (ec->G->y);
1193   if (!strcmp (name, "q.x") && ec->Q && ec->Q->x)
1194     return mpi_is_const (ec->Q->x) && !copy? ec->Q->x : mpi_copy (ec->Q->x);
1195   if (!strcmp (name, "q.y") && ec->Q && ec->Q->y)
1196     return mpi_is_const (ec->G->y) && !copy? ec->Q->y : mpi_copy (ec->Q->y);
1197
1198   /* If the base point has been requested, return it in standard
1199      encoding.  */
1200   if (!strcmp (name, "g") && ec->G)
1201     return _gcry_mpi_ec_ec2os (ec->G, ec);
1202
1203   /* If the public key has been requested, return it by default in
1204      standard uncompressed encoding or if requested in other
1205      encodings.  */
1206   if (*name == 'q' && (!name[1] || name[1] == '@'))
1207     {
1208       /* If only the private key is given, compute the public key.  */
1209       if (!ec->Q)
1210         ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
1211
1212       if (!ec->Q)
1213         return NULL;
1214
1215       if (name[1] != '@')
1216         return _gcry_mpi_ec_ec2os (ec->Q, ec);
1217
1218       if (!strcmp (name+2, "eddsa") && ec->model == MPI_EC_EDWARDS)
1219         {
1220           unsigned char *encpk;
1221           unsigned int encpklen;
1222
1223           if (!_gcry_ecc_eddsa_encodepoint (ec->Q, ec, NULL, NULL, 0,
1224                                             &encpk, &encpklen))
1225             return mpi_set_opaque (NULL, encpk, encpklen*8);
1226         }
1227     }
1228
1229   return NULL;
1230 }
1231
1232
1233 /* Return a point described by NAME and the context EC.  */
1234 gcry_mpi_point_t
1235 _gcry_ecc_get_point (const char *name, mpi_ec_t ec)
1236 {
1237   if (!strcmp (name, "g") && ec->G)
1238     return point_copy (ec->G);
1239   if (!strcmp (name, "q"))
1240     {
1241       /* If only the private key is given, compute the public key.  */
1242       if (!ec->Q)
1243         ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
1244
1245       if (ec->Q)
1246         return point_copy (ec->Q);
1247     }
1248
1249   return NULL;
1250 }
1251
1252
1253 /* Store the MPI NEWVALUE into the context EC under NAME. */
1254 gpg_err_code_t
1255 _gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec)
1256 {
1257   gpg_err_code_t rc = 0;
1258
1259   if (!*name)
1260     ;
1261   else if (!strcmp (name, "p"))
1262     {
1263       mpi_free (ec->p);
1264       ec->p = mpi_copy (newvalue);
1265       _gcry_mpi_ec_get_reset (ec);
1266     }
1267   else if (!strcmp (name, "a"))
1268     {
1269       mpi_free (ec->a);
1270       ec->a = mpi_copy (newvalue);
1271       _gcry_mpi_ec_get_reset (ec);
1272     }
1273   else if (!strcmp (name, "b"))
1274     {
1275       mpi_free (ec->b);
1276       ec->b = mpi_copy (newvalue);
1277     }
1278   else if (!strcmp (name, "n"))
1279     {
1280       mpi_free (ec->n);
1281       ec->n = mpi_copy (newvalue);
1282     }
1283   else if (!strcmp (name, "h"))
1284     {
1285       mpi_free (ec->h);
1286       ec->h = mpi_copy (newvalue);
1287     }
1288   else if (*name == 'q' && (!name[1] || name[1] == '@'))
1289     {
1290       if (newvalue)
1291         {
1292           if (!ec->Q)
1293             ec->Q = mpi_point_new (0);
1294           if (ec->dialect == ECC_DIALECT_ED25519)
1295             rc = _gcry_ecc_eddsa_decodepoint (newvalue, ec, ec->Q, NULL, NULL);
1296           else
1297             rc = _gcry_ecc_os2ec (ec->Q, newvalue);
1298         }
1299       if (rc || !newvalue)
1300         {
1301           _gcry_mpi_point_release (ec->Q);
1302           ec->Q = NULL;
1303         }
1304       /* Note: We assume that Q matches d and thus do not reset d.  */
1305     }
1306   else if (!strcmp (name, "d"))
1307     {
1308       mpi_free (ec->d);
1309       ec->d = mpi_copy (newvalue);
1310       if (ec->d)
1311         {
1312           /* We need to reset the public key because it may not
1313              anymore match.  */
1314           _gcry_mpi_point_release (ec->Q);
1315           ec->Q = NULL;
1316         }
1317     }
1318   else
1319    rc = GPG_ERR_UNKNOWN_NAME;
1320
1321   return rc;
1322 }
1323
1324
1325 /* Store the point NEWVALUE into the context EC under NAME.  */
1326 gpg_err_code_t
1327 _gcry_ecc_set_point (const char *name, gcry_mpi_point_t newvalue, mpi_ec_t ec)
1328 {
1329   if (!strcmp (name, "g"))
1330     {
1331       _gcry_mpi_point_release (ec->G);
1332       ec->G = point_copy (newvalue);
1333     }
1334   else if (!strcmp (name, "q"))
1335     {
1336       _gcry_mpi_point_release (ec->Q);
1337       ec->Q = point_copy (newvalue);
1338     }
1339   else
1340     return GPG_ERR_UNKNOWN_NAME;
1341
1342   return 0;
1343 }