Coverage Report

Created: 2022-12-08 06:10

/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
136
{
570
136
  gpg_err_code_t rc;
571
136
  gcry_mpi_t val;
572
573
136
  rc = _gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
574
136
  if (rc)
575
0
    log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (rc));
576
136
  return val;
577
136
}
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
40
{
585
40
  int idx, aliasno;
586
587
  /* First check our native curves.  */
588
1.12k
  for (idx = 0; domain_parms[idx].desc; idx++)
589
1.08k
    if (!strcmp (name, domain_parms[idx].desc))
590
0
      return idx;
591
592
  /* If not found consult the alias table.  */
593
40
  if (!domain_parms[idx].desc)
594
40
    {
595
600
      for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
596
600
        if (!strcmp (name, curve_aliases[aliasno].other))
597
40
          break;
598
40
      if (curve_aliases[aliasno].name)
599
40
        {
600
280
          for (idx = 0; domain_parms[idx].desc; idx++)
601
280
            if (!strcmp (curve_aliases[aliasno].name, domain_parms[idx].desc))
602
40
              return idx;
603
40
        }
604
40
    }
605
606
0
  return -1;
607
40
}
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
32
{
622
32
  int idx;
623
32
  const char *resname = NULL; /* Set to a found curve name.  */
624
625
32
  if (name)
626
32
    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
32
  if (idx < 0)
637
0
    return GPG_ERR_UNKNOWN_CURVE;
638
639
32
  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
32
  if (fips_mode () && !domain_parms[idx].fips )
645
0
    return GPG_ERR_NOT_SUPPORTED;
646
647
32
  switch (domain_parms[idx].model)
648
32
    {
649
32
    case MPI_EC_WEIERSTRASS:
650
32
    case MPI_EC_EDWARDS:
651
32
    case MPI_EC_MONTGOMERY:
652
32
      break;
653
0
    default:
654
0
      return GPG_ERR_BUG;
655
32
    }
656
657
658
32
  if (r_nbits)
659
16
    *r_nbits = domain_parms[idx].nbits;
660
661
32
  if (curve)
662
16
    {
663
16
      curve->model = domain_parms[idx].model;
664
16
      curve->dialect = domain_parms[idx].dialect;
665
16
      if (!curve->p)
666
16
        curve->p = scanval (domain_parms[idx].p);
667
16
      if (!curve->a)
668
16
        {
669
16
          curve->a = scanval (domain_parms[idx].a);
670
16
          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
16
        }
679
16
      if (!curve->b)
680
16
        {
681
16
          curve->b = scanval (domain_parms[idx].b);
682
16
          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
16
        }
691
16
      if (!curve->n)
692
16
        curve->n = scanval (domain_parms[idx].n);
693
16
      if (!curve->G.x)
694
16
        curve->G.x = scanval (domain_parms[idx].g_x);
695
16
      if (!curve->G.y)
696
16
        curve->G.y = scanval (domain_parms[idx].g_y);
697
16
      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
16
      if (!strcmp (resname, "Curve25519"))
706
0
        mpi_sub (curve->G.y, curve->p, curve->G.y);
707
708
16
      if (!curve->G.z)
709
16
        curve->G.z = mpi_alloc_set_ui (1);
710
16
      if (!curve->name)
711
16
        curve->name = resname;
712
16
    }
713
714
32
  return 0;
715
32
}
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
8
{
729
8
  int idx;
730
731
8
  idx = find_domain_parms_idx (name);
732
8
  if (idx < 0)
733
0
    return GPG_ERR_UNKNOWN_CURVE;
734
735
8
  if (g)
736
8
    {
737
8
      char *buf;
738
8
      size_t len;
739
740
8
      len = 4;
741
8
      len += strlen (domain_parms[idx].g_x+2);
742
8
      len += strlen (domain_parms[idx].g_y+2);
743
8
      len++;
744
8
      buf = xtrymalloc (len);
745
8
      if (!buf)
746
0
        return gpg_err_code_from_syserror ();
747
8
      strcpy (stpcpy (stpcpy (buf, "0x04"), domain_parms[idx].g_x+2),
748
8
              domain_parms[idx].g_y+2);
749
8
      _gcry_mpi_release (*g);
750
8
      *g = scanval (buf);
751
8
      xfree (buf);
752
8
    }
753
8
  if (model)
754
8
    *model = domain_parms[idx].model;
755
8
  if (dialect)
756
8
    *dialect = domain_parms[idx].dialect;
757
8
  if (p)
758
8
    {
759
8
      _gcry_mpi_release (*p);
760
8
      *p = scanval (domain_parms[idx].p);
761
8
    }
762
8
  if (a)
763
8
    {
764
8
      _gcry_mpi_release (*a);
765
8
      *a = scanval (domain_parms[idx].a);
766
8
    }
767
8
  if (b)
768
8
    {
769
8
      _gcry_mpi_release (*b);
770
8
      *b = scanval (domain_parms[idx].b);
771
8
    }
772
8
  if (n)
773
8
    {
774
8
      _gcry_mpi_release (*n);
775
8
      *n = scanval (domain_parms[idx].n);
776
8
    }
777
8
  return 0;
778
8
}
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
16
{
941
16
  gcry_err_code_t ec = 0;
942
16
  gcry_sexp_t l1;
943
944
16
  l1 = sexp_find_token (keyparam, name, 0);
945
16
  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
16
  return ec;
953
16
}
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
16
{
964
16
  gcry_err_code_t rc;
965
16
  gcry_sexp_t l1;
966
16
  gcry_mpi_point_t point;
967
968
16
  l1 = sexp_find_token (keyparam, name, 0);
969
16
  if (l1)
970
16
    {
971
16
      gcry_mpi_t a;
972
973
16
      a = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
974
16
      sexp_release (l1);
975
16
      if (!a)
976
0
        return GPG_ERR_INV_OBJ;
977
978
16
      point = mpi_point_new (0);
979
16
      rc = _gcry_mpi_ec_decode_point (point, a, ec);
980
16
      mpi_free (a);
981
16
      if (rc)
982
0
        {
983
0
          mpi_point_release (point);
984
0
          return rc;
985
0
        }
986
16
    }
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
16
  if (point)
1036
16
    *r_a = point;
1037
16
  return 0;
1038
16
}
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
16
{
1046
16
  gpg_err_code_t errc;
1047
16
  unsigned int nbits;
1048
16
  gcry_sexp_t l1;
1049
1050
16
  errc = _gcry_pk_util_get_nbits (keyparam, &nbits);
1051
16
  if (errc)
1052
0
    return errc;
1053
1054
16
  E->model = MPI_EC_WEIERSTRASS;
1055
16
  E->dialect = ECC_DIALECT_STANDARD;
1056
16
  E->h = 1;
1057
1058
16
  if (keyparam)
1059
16
    {
1060
      /* Parse an optional flags list.  */
1061
16
      l1 = sexp_find_token (keyparam, "flags", 0);
1062
16
      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
16
      l1 = sexp_find_token (keyparam, "transient-key", 0);
1077
16
      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
16
      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
16
      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
16
    }
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
16
  if (l1 || curvename || nbits)
1133
16
    {
1134
16
      char *name;
1135
1136
16
      if (l1)
1137
16
        {
1138
16
          name = sexp_nth_string (l1, 1);
1139
16
          sexp_release (l1);
1140
16
          if (!name)
1141
0
            {
1142
0
              errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
1143
0
              goto leave;
1144
0
            }
1145
16
        }
1146
0
      else
1147
0
        name = NULL;
1148
1149
16
      errc = _gcry_ecc_fill_in_curve (nbits, name? name : curvename, E, NULL);
1150
16
      xfree (name);
1151
16
      if (errc)
1152
0
        goto leave;
1153
16
    }
1154
1155
16
 leave:
1156
16
  return errc;
1157
16
}
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
16
{
1163
16
  gpg_err_code_t errc = 0;
1164
1165
16
  ec->G = mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
1166
16
  E->G.x = NULL;
1167
16
  E->G.y = NULL;
1168
16
  E->G.z = NULL;
1169
16
  ec->n = E->n;
1170
16
  E->n = NULL;
1171
16
  ec->h = E->h;
1172
16
  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
16
  if (keyparam)
1180
16
    {
1181
16
      int is_opaque_bytes = ((ec->dialect == ECC_DIALECT_ED25519
1182
16
                              && (flags & PUBKEY_FLAG_EDDSA))
1183
16
                             || (ec->dialect == ECC_DIALECT_SAFECURVE));
1184
1185
16
      errc = point_from_keyparam (&ec->Q, keyparam, "q", ec);
1186
16
      if (errc)
1187
0
        return errc;
1188
16
      errc = mpi_from_keyparam (&ec->d, keyparam, "d", is_opaque_bytes);
1189
1190
      /* Size of opaque bytes should match size of P.  */
1191
16
      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
16
    }
1254
1255
16
  return errc;
1256
16
}
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
16
{
1262
16
  gpg_err_code_t errc;
1263
16
  elliptic_curve_t E;
1264
16
  mpi_ec_t ec;
1265
1266
16
  *r_ec = NULL;
1267
1268
16
  memset (&E, 0, sizeof E);
1269
16
  errc = mpi_ec_get_elliptic_curve (&E, r_flags, keyparam, curvename);
1270
16
  if (errc)
1271
0
    goto leave;
1272
1273
16
  ec = _gcry_mpi_ec_p_internal_new (E.model, E.dialect, *r_flags,
1274
16
                                    E.p, E.a, E.b);
1275
16
  if (!ec)
1276
0
    goto leave;
1277
1278
16
  errc = mpi_ec_setup_elliptic_curve (ec, *r_flags, &E, keyparam);
1279
16
  if (errc)
1280
0
    {
1281
0
      _gcry_mpi_ec_free (ec);
1282
0
      goto leave;
1283
0
    }
1284
16
  else
1285
16
    *r_ec = ec;
1286
1287
16
  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
16
 leave:
1331
16
  _gcry_ecc_curve_free (&E);
1332
16
  return errc;
1333
16
}
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
}