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
5 * This file is part of Libgcrypt.
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.
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.
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/>.
31 #include "ec-context.h"
32 #include "pubkey-internal.h"
33 #include "ecc-common.h"
36 /* This tables defines aliases for curve names. */
39 const char *name; /* Our name. */
40 const char *other; /* Other name. */
43 { "Curve25519", "1.3.6.1.4.1.3029.1.5.1" },
44 { "Ed25519", "1.3.6.1.4.1.11591.15.1" },
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. */
51 { "NIST P-224", "secp224r1" },
52 { "NIST P-224", "1.3.132.0.33" }, /* SECP OID. */
53 { "NIST P-224", "nistp224" }, /* rfc5656. */
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. */
60 { "NIST P-384", "secp384r1" },
61 { "NIST P-384", "1.3.132.0.34" },
62 { "NIST P-384", "nistp384" }, /* rfc5656. */
64 { "NIST P-521", "secp521r1" },
65 { "NIST P-521", "1.3.132.0.35" },
66 { "NIST P-521", "nistp521" }, /* rfc5656. */
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"},
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" },
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" },
88 { "secp256k1", "1.3.132.0.10" },
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. */
100 /* The model describing this curve. This is mainly used to select
101 the group equation. */
102 enum gcry_mpi_ec_models model;
104 /* The actual ECC dialect used. This is used for curve specific
105 optimizations and to select encodings etc. */
106 enum ecc_dialects dialect;
108 const char *p; /* The prime defining the field. */
109 const char *a, *b; /* The coefficients. For Twisted Edwards
110 Curves b is used for d. For Montgomery
111 Curves (a,b) has ((A-2)/4,B^-1). */
112 const char *n; /* The order of the base point. */
113 const char *g_x, *g_y; /* Base point. */
114 const char *h; /* Cofactor. */
115 } ecc_domain_parms_t;
118 /* This static table defines all available curves. */
119 static const ecc_domain_parms_t domain_parms[] =
122 /* (-x^2 + y^2 = 1 + dx^2y^2) */
124 MPI_EC_EDWARDS, ECC_DIALECT_ED25519,
125 "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
127 "-0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A",
128 "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
129 "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
130 "0x6666666666666666666666666666666666666666666666666666666666666658",
134 /* (y^2 = x^3 + 486662*x^2 + x) */
135 "Curve25519", 256, 0,
136 MPI_EC_MONTGOMERY, ECC_DIALECT_STANDARD,
137 "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
140 "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
141 "0x0000000000000000000000000000000000000000000000000000000000000009",
142 "0x20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9",
145 #if 0 /* No real specs yet found. */
147 /* x^2 + y^2 = 1 + 3617x^2y^2 mod 2^414 - 17 */
149 "0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
150 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF",
154 "0x07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB3CC92414CF"
155 "706022B36F1C0338AD63CF181B0E71A5E106AF79",
156 "0x1A334905141443300218C0631C326E5FCD46369F44C03EC7F57FF35498A4AB4D"
157 "6D6BA111301A73FAA8537C64C4FD3812F3CBC595",
163 "NIST P-192", 192, 0,
164 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
165 "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
166 "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
167 "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
168 "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
170 "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
171 "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
175 "NIST P-224", 224, 1,
176 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
177 "0xffffffffffffffffffffffffffffffff000000000000000000000001",
178 "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
179 "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
180 "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
182 "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
183 "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
187 "NIST P-256", 256, 1,
188 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
189 "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
190 "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
191 "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
192 "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
194 "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
195 "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
199 "NIST P-384", 384, 1,
200 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
201 "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
202 "ffffffff0000000000000000ffffffff",
203 "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
204 "ffffffff0000000000000000fffffffc",
205 "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
206 "c656398d8a2ed19d2a85c8edd3ec2aef",
207 "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
208 "581a0db248b0a77aecec196accc52973",
210 "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
211 "5502f25dbf55296c3a545e3872760ab7",
212 "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
213 "0a60b1ce1d7e819d7a431d7c90ea0e5f",
217 "NIST P-521", 521, 1,
218 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
219 "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
220 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
221 "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
222 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
223 "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
224 "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
225 "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
226 "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
228 "0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d"
229 "3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
230 "0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e"
231 "662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
235 { "brainpoolP160r1", 160, 0,
236 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
237 "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
238 "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
239 "0x1e589a8595423412134faa2dbdec95c8d8675e58",
240 "0xe95e4a5f737059dc60df5991d45029409e60fc09",
241 "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
242 "0x1667cb477a1a8ec338f94741669c976316da6321",
246 { "brainpoolP192r1", 192, 0,
247 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
248 "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
249 "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
250 "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
251 "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
252 "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
253 "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f",
257 { "brainpoolP224r1", 224, 0,
258 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
259 "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
260 "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
261 "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
262 "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
263 "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
264 "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd",
268 { "brainpoolP256r1", 256, 0,
269 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
270 "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
271 "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
272 "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
273 "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
274 "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
275 "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997",
279 { "brainpoolP320r1", 320, 0,
280 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
281 "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
283 "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
285 "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981"
287 "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9"
289 "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
291 "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
296 { "brainpoolP384r1", 384, 0,
297 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
298 "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
299 "acd3a729901d1a71874700133107ec53",
300 "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
301 "8aa5814a503ad4eb04a8c7dd22ce2826",
302 "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5"
303 "7cb4390295dbc9943ab78696fa504c11",
304 "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7"
305 "cf3ab6af6b7fc3103b883202e9046565",
306 "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
307 "e826e03436d646aaef87b2e247d4af1e",
308 "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
309 "0e4646217791811142820341263c5315",
313 { "brainpoolP512r1", 512, 0,
314 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
315 "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
316 "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
317 "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
318 "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca",
319 "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7"
320 "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723",
321 "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870"
322 "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
323 "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
324 "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
325 "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
326 "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892",
330 "GOST2001-test", 256, 0,
331 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
332 "0x8000000000000000000000000000000000000000000000000000000000000431",
333 "0x0000000000000000000000000000000000000000000000000000000000000007",
334 "0x5fbff498aa938ce739b8e022fbafef40563f6e6a3472fc2a514c0ce9dae23b7e",
335 "0x8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3",
337 "0x0000000000000000000000000000000000000000000000000000000000000002",
338 "0x08e2a8a0e65147d4bd6316030e16d19c85c97f0a9ca267122b96abbcea7e8fc8",
342 "GOST2001-CryptoPro-A", 256, 0,
343 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
344 "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd97",
345 "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd94",
346 "0x00000000000000000000000000000000000000000000000000000000000000a6",
347 "0xffffffffffffffffffffffffffffffff6c611070995ad10045841b09b761b893",
348 "0x0000000000000000000000000000000000000000000000000000000000000001",
349 "0x8d91e471e0989cda27df505a453f2b7635294f2ddf23e3b122acc99c9e9f1e14",
353 "GOST2001-CryptoPro-B", 256, 0,
354 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
355 "0x8000000000000000000000000000000000000000000000000000000000000c99",
356 "0x8000000000000000000000000000000000000000000000000000000000000c96",
357 "0x3e1af419a269a5f866a7d3c25c3df80ae979259373ff2b182f49d4ce7e1bbc8b",
358 "0x800000000000000000000000000000015f700cfff1a624e5e497161bcc8a198f",
359 "0x0000000000000000000000000000000000000000000000000000000000000001",
360 "0x3fa8124359f96680b83d1c3eb2c070e5c545c9858d03ecfb744bf8d717717efc",
364 "GOST2001-CryptoPro-C", 256, 0,
365 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
366 "0x9b9f605f5a858107ab1ec85e6b41c8aacf846e86789051d37998f7b9022d759b",
367 "0x9b9f605f5a858107ab1ec85e6b41c8aacf846e86789051d37998f7b9022d7598",
368 "0x000000000000000000000000000000000000000000000000000000000000805a",
369 "0x9b9f605f5a858107ab1ec85e6b41c8aa582ca3511eddfb74f02f3a6598980bb9",
370 "0x0000000000000000000000000000000000000000000000000000000000000000",
371 "0x41ece55743711a8c3cbf3783cd08c0ee4d4dc440d4641a8f366e550dfdb3bb67",
375 "GOST2012-test", 511, 0,
376 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
377 "0x4531acd1fe0023c7550d267b6b2fee80922b14b2ffb90f04d4eb7c09b5d2d15d"
378 "f1d852741af4704a0458047e80e4546d35b8336fac224dd81664bbf528be6373",
379 "0x0000000000000000000000000000000000000000000000000000000000000007",
380 "0x1cff0806a31116da29d8cfa54e57eb748bc5f377e49400fdd788b649eca1ac4"
381 "361834013b2ad7322480a89ca58e0cf74bc9e540c2add6897fad0a3084f302adc",
382 "0x4531acd1fe0023c7550d267b6b2fee80922b14b2ffb90f04d4eb7c09b5d2d15d"
383 "a82f2d7ecb1dbac719905c5eecc423f1d86e25edbe23c595d644aaf187e6e6df",
385 "0x24d19cc64572ee30f396bf6ebbfd7a6c5213b3b3d7057cc825f91093a68cd762"
386 "fd60611262cd838dc6b60aa7eee804e28bc849977fac33b4b530f1b120248a9a",
387 "0x2bb312a43bd2ce6e0d020613c857acddcfbf061e91e5f2c3f32447c259f39b2"
388 "c83ab156d77f1496bf7eb3351e1ee4e43dc1a18b91b24640b6dbb92cb1add371e",
392 "GOST2012-tc26-A", 512, 0,
393 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
394 "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
395 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc7",
396 "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
397 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc4",
398 "0xe8c2505dedfc86ddc1bd0b2b6667f1da34b82574761cb0e879bd081cfd0b6265"
399 "ee3cb090f30d27614cb4574010da90dd862ef9d4ebee4761503190785a71c760",
400 "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
401 "27e69532f48d89116ff22b8d4e0560609b4b38abfad2b85dcacdb1411f10b275",
402 "0x0000000000000000000000000000000000000000000000000000000000000000"
403 "0000000000000000000000000000000000000000000000000000000000000003",
404 "0x7503cfe87a836ae3a61b8816e25450e6ce5e1c93acf1abc1778064fdcbefa921"
405 "df1626be4fd036e93d75e6a50e3a41e98028fe5fc235f5b889a589cb5215f2a4",
409 "GOST2012-tc26-B", 512, 0,
410 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
411 "0x8000000000000000000000000000000000000000000000000000000000000000"
412 "000000000000000000000000000000000000000000000000000000000000006f",
413 "0x8000000000000000000000000000000000000000000000000000000000000000"
414 "000000000000000000000000000000000000000000000000000000000000006c",
415 "0x687d1b459dc841457e3e06cf6f5e2517b97c7d614af138bcbf85dc806c4b289f"
416 "3e965d2db1416d217f8b276fad1ab69c50f78bee1fa3106efb8ccbc7c5140116",
417 "0x8000000000000000000000000000000000000000000000000000000000000001"
418 "49a1ec142565a545acfdb77bd9d40cfa8b996712101bea0ec6346c54374f25bd",
419 "0x0000000000000000000000000000000000000000000000000000000000000000"
420 "0000000000000000000000000000000000000000000000000000000000000002",
421 "0x1a8f7eda389b094c2c071e3647a8940f3c123b697578c213be6dd9e6c8ec7335"
422 "dcb228fd1edf4a39152cbcaaf8c0398828041055f94ceeec7e21340780fe41bd",
428 MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
429 "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
430 "0x0000000000000000000000000000000000000000000000000000000000000000",
431 "0x0000000000000000000000000000000000000000000000000000000000000007",
432 "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
433 "0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
434 "0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
438 { NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }
444 /* Return a copy of POINT. */
445 static gcry_mpi_point_t
446 point_copy (gcry_mpi_point_t point)
448 gcry_mpi_point_t newpoint;
452 newpoint = mpi_point_new (0);
453 point_set (newpoint, point);
461 /* Helper to scan a hex string. */
463 scanval (const char *string)
468 rc = _gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
470 log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (rc));
475 /* Return the index of the domain_parms table for a curve with NAME.
476 Return -1 if not found. */
478 find_domain_parms_idx (const char *name)
482 /* First check our native curves. */
483 for (idx = 0; domain_parms[idx].desc; idx++)
484 if (!strcmp (name, domain_parms[idx].desc))
487 /* If not found consult the alias table. */
488 if (!domain_parms[idx].desc)
490 for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
491 if (!strcmp (name, curve_aliases[aliasno].other))
493 if (curve_aliases[aliasno].name)
495 for (idx = 0; domain_parms[idx].desc; idx++)
496 if (!strcmp (curve_aliases[aliasno].name, domain_parms[idx].desc))
505 /* Generate the crypto system setup. This function takes the NAME of
506 a curve or the desired number of bits and stores at R_CURVE the
507 parameters of the named curve or those of a suitable curve. If
508 R_NBITS is not NULL, the chosen number of bits is stored there.
509 NULL may be given for R_CURVE, if the value is not required and for
510 example only a quick test for availability is desired. Note that
511 the curve fields should be initialized to zero because fields which
512 are not NULL are skipped. */
514 _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
515 elliptic_curve_t *curve, unsigned int *r_nbits)
518 const char *resname = NULL; /* Set to a found curve name. */
521 idx = find_domain_parms_idx (name);
524 for (idx = 0; domain_parms[idx].desc; idx++)
525 if (nbits == domain_parms[idx].nbits
526 && domain_parms[idx].model == MPI_EC_WEIERSTRASS)
528 if (!domain_parms[idx].desc)
532 return GPG_ERR_UNKNOWN_CURVE;
534 resname = domain_parms[idx].desc;
536 /* In fips mode we only support NIST curves. Note that it is
537 possible to bypass this check by specifying the curve parameters
539 if (fips_mode () && !domain_parms[idx].fips )
540 return GPG_ERR_NOT_SUPPORTED;
542 switch (domain_parms[idx].model)
544 case MPI_EC_WEIERSTRASS:
546 case MPI_EC_MONTGOMERY:
554 *r_nbits = domain_parms[idx].nbits;
558 curve->model = domain_parms[idx].model;
559 curve->dialect = domain_parms[idx].dialect;
561 curve->p = scanval (domain_parms[idx].p);
564 curve->a = scanval (domain_parms[idx].a);
566 mpi_add (curve->a, curve->p, curve->a);
570 curve->b = scanval (domain_parms[idx].b);
572 mpi_add (curve->b, curve->p, curve->b);
575 curve->n = scanval (domain_parms[idx].n);
577 curve->h = scanval (domain_parms[idx].h);
579 curve->G.x = scanval (domain_parms[idx].g_x);
581 curve->G.y = scanval (domain_parms[idx].g_y);
583 curve->G.z = mpi_alloc_set_ui (1);
585 curve->name = resname;
592 /* Give the name of the curve NAME, store the curve parameters into P,
593 A, B, G, N, and H if they point to NULL value. Note that G is returned
594 in standard uncompressed format. Also update MODEL and DIALECT if
595 they are not NULL. */
597 _gcry_ecc_update_curve_param (const char *name,
598 enum gcry_mpi_ec_models *model,
599 enum ecc_dialects *dialect,
600 gcry_mpi_t *p, gcry_mpi_t *a, gcry_mpi_t *b,
601 gcry_mpi_t *g, gcry_mpi_t *n, gcry_mpi_t *h)
605 idx = find_domain_parms_idx (name);
607 return GPG_ERR_UNKNOWN_CURVE;
615 len += strlen (domain_parms[idx].g_x+2);
616 len += strlen (domain_parms[idx].g_y+2);
618 buf = xtrymalloc (len);
620 return gpg_err_code_from_syserror ();
621 strcpy (stpcpy (stpcpy (buf, "0x04"), domain_parms[idx].g_x+2),
622 domain_parms[idx].g_y+2);
623 _gcry_mpi_release (*g);
628 *model = domain_parms[idx].model;
630 *dialect = domain_parms[idx].dialect;
633 _gcry_mpi_release (*p);
634 *p = scanval (domain_parms[idx].p);
638 _gcry_mpi_release (*a);
639 *a = scanval (domain_parms[idx].a);
643 _gcry_mpi_release (*b);
644 *b = scanval (domain_parms[idx].b);
648 _gcry_mpi_release (*n);
649 *n = scanval (domain_parms[idx].n);
653 _gcry_mpi_release (*h);
654 *h = scanval (domain_parms[idx].h);
660 /* Return the name matching the parameters in PKEY. This works only
661 with curves described by the Weierstrass equation. */
663 _gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
666 const char *result = NULL;
668 gcry_mpi_t mpi_g = NULL;
669 gcry_mpi_t tmp = NULL;
672 memset (&E, 0, sizeof E);
680 if (idx >= 0 && idx < DIM (domain_parms))
682 result = domain_parms[idx].desc;
684 *r_nbits = domain_parms[idx].nbits;
691 * Extract the curve parameters..
693 rc = gpg_err_code (sexp_extract_param (keyparms, NULL, "-pabgnh",
694 &E.p, &E.a, &E.b, &mpi_g, &E.n, &E.h,
696 if (rc == GPG_ERR_NO_OBJ)
698 /* This might be the second use case of checking whether a
699 specific curve given by name is supported. */
703 l1 = sexp_find_token (keyparms, "curve", 5);
705 goto leave; /* No curve name parameter. */
707 name = sexp_nth_string (l1, 1);
710 goto leave; /* Name missing or out of core. */
712 idx = find_domain_parms_idx (name);
714 if (idx >= 0) /* Curve found. */
716 result = domain_parms[idx].desc;
718 *r_nbits = domain_parms[idx].nbits;
728 _gcry_mpi_point_init (&E.G);
729 if (_gcry_ecc_os2ec (&E.G, mpi_g))
733 for (idx = 0; domain_parms[idx].desc; idx++)
736 tmp = scanval (domain_parms[idx].p);
737 if (!mpi_cmp (tmp, E.p))
740 tmp = scanval (domain_parms[idx].a);
741 if (!mpi_cmp (tmp, E.a))
744 tmp = scanval (domain_parms[idx].b);
745 if (!mpi_cmp (tmp, E.b))
748 tmp = scanval (domain_parms[idx].n);
749 if (!mpi_cmp (tmp, E.n))
752 tmp = scanval (domain_parms[idx].h);
753 if (!mpi_cmp (tmp, E.h))
756 tmp = scanval (domain_parms[idx].g_x);
757 if (!mpi_cmp (tmp, E.G.x))
760 tmp = scanval (domain_parms[idx].g_y);
761 if (!mpi_cmp (tmp, E.G.y))
763 result = domain_parms[idx].desc;
765 *r_nbits = domain_parms[idx].nbits;
777 _gcry_mpi_release (tmp);
778 _gcry_mpi_release (E.p);
779 _gcry_mpi_release (E.a);
780 _gcry_mpi_release (E.b);
781 _gcry_mpi_release (mpi_g);
782 _gcry_mpi_point_free_parts (&E.G);
783 _gcry_mpi_release (E.n);
784 _gcry_mpi_release (E.h);
789 /* Helper to extract an MPI from key parameters. */
790 static gpg_err_code_t
791 mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name)
793 gcry_err_code_t ec = 0;
796 l1 = sexp_find_token (keyparam, name, 0);
799 *r_a = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
802 ec = GPG_ERR_INV_OBJ;
807 /* Helper to extract a point from key parameters. If no parameter
808 with NAME is found, the functions tries to find a non-encoded point
809 by appending ".x", ".y" and ".z" to NAME. ".z" is in this case
810 optional and defaults to 1. EC is the context which at this point
811 may not be fully initialized. */
812 static gpg_err_code_t
813 point_from_keyparam (gcry_mpi_point_t *r_a,
814 gcry_sexp_t keyparam, const char *name, mpi_ec_t ec)
818 gcry_mpi_point_t point;
820 l1 = sexp_find_token (keyparam, name, 0);
825 a = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
828 return GPG_ERR_INV_OBJ;
830 point = mpi_point_new (0);
831 if (ec && ec->dialect == ECC_DIALECT_ED25519)
832 rc = _gcry_ecc_eddsa_decodepoint (a, ec, point, NULL, NULL);
834 rc = _gcry_ecc_os2ec (point, a);
838 mpi_point_release (point);
849 tmpname = xtrymalloc (strlen (name) + 2 + 1);
851 return gpg_err_code_from_syserror ();
852 strcpy (stpcpy (tmpname, name), ".x");
853 rc = mpi_from_keyparam (&x, keyparam, tmpname);
859 strcpy (stpcpy (tmpname, name), ".y");
860 rc = mpi_from_keyparam (&y, keyparam, tmpname);
867 strcpy (stpcpy (tmpname, name), ".z");
868 rc = mpi_from_keyparam (&z, keyparam, tmpname);
877 z = mpi_set_ui (NULL, 1);
879 point = mpi_point_snatch_set (NULL, x, y, z);
896 /* This function creates a new context for elliptic curve operations.
897 Either KEYPARAM or CURVENAME must be given. If both are given and
898 KEYPARAM has no curve parameter, CURVENAME is used to add missing
899 parameters. On success 0 is returned and the new context stored at
900 R_CTX. On error NULL is stored at R_CTX and an error code is
901 returned. The context needs to be released using
904 _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
905 gcry_sexp_t keyparam, const char *curvename)
908 gcry_ctx_t ctx = NULL;
909 enum gcry_mpi_ec_models model = MPI_EC_WEIERSTRASS;
910 enum ecc_dialects dialect = ECC_DIALECT_STANDARD;
914 gcry_mpi_point_t G = NULL;
917 gcry_mpi_point_t Q = NULL;
926 /* Parse an optional flags list. */
927 l1 = sexp_find_token (keyparam, "flags", 0);
930 errc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
937 /* Check whether a curve name was given. */
938 l1 = sexp_find_token (keyparam, "curve", 5);
940 /* If we don't have a curve name or if override parameters have
941 explicitly been requested, parse them. */
942 if (!l1 || (flags & PUBKEY_FLAG_PARAM))
944 errc = mpi_from_keyparam (&p, keyparam, "p");
947 errc = mpi_from_keyparam (&a, keyparam, "a");
950 errc = mpi_from_keyparam (&b, keyparam, "b");
953 errc = point_from_keyparam (&G, keyparam, "g", NULL);
956 errc = mpi_from_keyparam (&n, keyparam, "n");
959 errc = mpi_from_keyparam (&h, keyparam, "h");
965 l1 = NULL; /* No curvename. */
967 /* Check whether a curve parameter is available and use that to fill
968 in missing values. If no curve parameter is available try an
969 optional provided curvename. If only the curvename has been
970 given use that one. */
978 name = sexp_nth_string (l1, 1);
982 errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
989 E = xtrycalloc (1, sizeof *E);
992 errc = gpg_err_code_from_syserror ();
997 errc = _gcry_ecc_fill_in_curve (0, name? name : curvename, E, NULL);
1006 dialect = E->dialect;
1025 G = mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
1040 _gcry_ecc_curve_free (E);
1045 errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, flags, p, a, b);
1048 mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
1072 /* Now that we know the curve name we can look for the public key
1073 Q. point_from_keyparam needs to know the curve parameters so
1074 that it is able to use the correct decompression. Parsing
1075 the private key D could have been done earlier but it is less
1076 surprising if we do it here as well. */
1079 errc = point_from_keyparam (&Q, keyparam, "q", ec);
1082 errc = mpi_from_keyparam (&d, keyparam, "d");
1103 _gcry_ctx_release (ctx);
1107 _gcry_mpi_point_release (G);
1110 _gcry_mpi_point_release (Q);
1116 /* Return the parameters of the curve NAME as an S-expression. */
1118 _gcry_ecc_get_param_sexp (const char *name)
1123 gcry_mpi_t g_x, g_y;
1128 memset (&E, 0, sizeof E);
1129 if (_gcry_ecc_fill_in_curve (0, name, &E, &nbits))
1134 ctx = _gcry_mpi_ec_p_internal_new (MPI_EC_WEIERSTRASS,
1135 ECC_DIALECT_STANDARD,
1138 if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
1139 log_fatal ("ecc get param: Failed to get affine coordinates\n");
1140 _gcry_mpi_ec_free (ctx);
1141 _gcry_mpi_point_free_parts (&E.G);
1146 pkey[3] = _gcry_ecc_ec2os (g_x, g_y, E.p);
1154 if (sexp_build (&result, NULL,
1155 "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)))",
1156 pkey[0], pkey[1], pkey[2], pkey[3], pkey[4], pkey[5]))
1159 for (i=0; pkey[i]; i++)
1160 _gcry_mpi_release (pkey[i]);
1166 /* Return an MPI (or opaque MPI) described by NAME and the context EC.
1167 If COPY is true a copy is returned, if not a const MPI may be
1168 returned. In any case mpi_free must be used. */
1170 _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy)
1175 if (!strcmp (name, "p") && ec->p)
1176 return mpi_is_const (ec->p) && !copy? ec->p : mpi_copy (ec->p);
1177 if (!strcmp (name, "a") && ec->a)
1178 return mpi_is_const (ec->a) && !copy? ec->a : mpi_copy (ec->a);
1179 if (!strcmp (name, "b") && ec->b)
1180 return mpi_is_const (ec->b) && !copy? ec->b : mpi_copy (ec->b);
1181 if (!strcmp (name, "n") && ec->n)
1182 return mpi_is_const (ec->n) && !copy? ec->n : mpi_copy (ec->n);
1183 if (!strcmp (name, "h") && ec->h)
1184 return mpi_is_const (ec->h) && !copy? ec->h : mpi_copy (ec->h);
1185 if (!strcmp (name, "d") && ec->d)
1186 return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d);
1188 /* Return a requested point coordinate. */
1189 if (!strcmp (name, "g.x") && ec->G && ec->G->x)
1190 return mpi_is_const (ec->G->x) && !copy? ec->G->x : mpi_copy (ec->G->x);
1191 if (!strcmp (name, "g.y") && ec->G && ec->G->y)
1192 return mpi_is_const (ec->G->y) && !copy? ec->G->y : mpi_copy (ec->G->y);
1193 if (!strcmp (name, "q.x") && ec->Q && ec->Q->x)
1194 return mpi_is_const (ec->Q->x) && !copy? ec->Q->x : mpi_copy (ec->Q->x);
1195 if (!strcmp (name, "q.y") && ec->Q && ec->Q->y)
1196 return mpi_is_const (ec->G->y) && !copy? ec->Q->y : mpi_copy (ec->Q->y);
1198 /* If the base point has been requested, return it in standard
1200 if (!strcmp (name, "g") && ec->G)
1201 return _gcry_mpi_ec_ec2os (ec->G, ec);
1203 /* If the public key has been requested, return it by default in
1204 standard uncompressed encoding or if requested in other
1206 if (*name == 'q' && (!name[1] || name[1] == '@'))
1208 /* If only the private key is given, compute the public key. */
1210 ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
1216 return _gcry_mpi_ec_ec2os (ec->Q, ec);
1218 if (!strcmp (name+2, "eddsa") && ec->model == MPI_EC_EDWARDS)
1220 unsigned char *encpk;
1221 unsigned int encpklen;
1223 if (!_gcry_ecc_eddsa_encodepoint (ec->Q, ec, NULL, NULL, 0,
1225 return mpi_set_opaque (NULL, encpk, encpklen*8);
1233 /* Return a point described by NAME and the context EC. */
1235 _gcry_ecc_get_point (const char *name, mpi_ec_t ec)
1237 if (!strcmp (name, "g") && ec->G)
1238 return point_copy (ec->G);
1239 if (!strcmp (name, "q"))
1241 /* If only the private key is given, compute the public key. */
1243 ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
1246 return point_copy (ec->Q);
1253 /* Store the MPI NEWVALUE into the context EC under NAME. */
1255 _gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec)
1257 gpg_err_code_t rc = 0;
1261 else if (!strcmp (name, "p"))
1264 ec->p = mpi_copy (newvalue);
1265 _gcry_mpi_ec_get_reset (ec);
1267 else if (!strcmp (name, "a"))
1270 ec->a = mpi_copy (newvalue);
1271 _gcry_mpi_ec_get_reset (ec);
1273 else if (!strcmp (name, "b"))
1276 ec->b = mpi_copy (newvalue);
1278 else if (!strcmp (name, "n"))
1281 ec->n = mpi_copy (newvalue);
1283 else if (!strcmp (name, "h"))
1286 ec->h = mpi_copy (newvalue);
1288 else if (*name == 'q' && (!name[1] || name[1] == '@'))
1293 ec->Q = mpi_point_new (0);
1294 if (ec->dialect == ECC_DIALECT_ED25519)
1295 rc = _gcry_ecc_eddsa_decodepoint (newvalue, ec, ec->Q, NULL, NULL);
1297 rc = _gcry_ecc_os2ec (ec->Q, newvalue);
1299 if (rc || !newvalue)
1301 _gcry_mpi_point_release (ec->Q);
1304 /* Note: We assume that Q matches d and thus do not reset d. */
1306 else if (!strcmp (name, "d"))
1309 ec->d = mpi_copy (newvalue);
1312 /* We need to reset the public key because it may not
1314 _gcry_mpi_point_release (ec->Q);
1319 rc = GPG_ERR_UNKNOWN_NAME;
1325 /* Store the point NEWVALUE into the context EC under NAME. */
1327 _gcry_ecc_set_point (const char *name, gcry_mpi_point_t newvalue, mpi_ec_t ec)
1329 if (!strcmp (name, "g"))
1331 _gcry_mpi_point_release (ec->G);
1332 ec->G = point_copy (newvalue);
1334 else if (!strcmp (name, "q"))
1336 _gcry_mpi_point_release (ec->Q);
1337 ec->Q = point_copy (newvalue);
1340 return GPG_ERR_UNKNOWN_NAME;