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