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