Coverage Report

Created: 2022-12-08 06:09

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