Coverage Report

Created: 2024-11-21 07:03

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