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