~ilya-yanok/ubuntu/precise/grub2/fix-for-948716

« back to all changes in this revision

Viewing changes to grub-core/lib/libgcrypt-grub/cipher/ecc.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2011-01-17 13:43:06 UTC
  • mto: (17.6.26 experimental)
  • mto: This revision was merged to the branch mainline in revision 102.
  • Revision ID: james.westby@ubuntu.com-20110117134306-fy7qewn4s3qdx2pl
Tags: upstream-1.99~rc1
ImportĀ upstreamĀ versionĀ 1.99~rc1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file was automatically imported with 
 
2
   import_gcry.py. Please don't modify it */
 
3
/* ecc.c  -  Elliptic Curve Cryptography
 
4
   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
 
5
 
 
6
   This file is part of Libgcrypt.
 
7
  
 
8
   Libgcrypt is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU Lesser General Public License as
 
10
   published by the Free Software Foundation; either version 2.1 of
 
11
   the License, or (at your option) any later version.
 
12
  
 
13
   Libgcrypt is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU Lesser General Public License for more details.
 
17
  
 
18
   You should have received a copy of the GNU Lesser General Public
 
19
   License along with this program; if not, write to the Free Software
 
20
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 
21
   USA.  */
 
22
 
 
23
/* This code is originally based on the Patch 0.1.6 for the gnupg
 
24
   1.4.x branch as retrieved on 2007-03-21 from
 
25
   http://www.calcurco.cat/eccGnuPG/src/gnupg-1.4.6-ecc0.2.0beta1.diff.bz2
 
26
   The original authors are:
 
27
     Written by
 
28
      Sergi Blanch i Torne <d4372211 at alumnes.eup.udl.es>,
 
29
      Ramiro Moreno Chiral <ramiro at eup.udl.es>
 
30
     Maintainers
 
31
      Sergi Blanch i Torne
 
32
      Ramiro Moreno Chiral
 
33
      Mikael Mylnikov (mmr)
 
34
  For use in Libgcrypt the code has been heavily modified and cleaned
 
35
  up. In fact there is not much left of the orginally code except for
 
36
  some variable names and the text book implementaion of the sign and
 
37
  verification algorithms.  The arithmetic functions have entirely
 
38
  been rewritten and moved to mpi/ec.c.  */
 
39
 
 
40
 
 
41
/* TODO:
 
42
 
 
43
  - If we support point compression we need to decide how to compute
 
44
    the keygrip - it should not change due to compression.
 
45
 
 
46
  - In mpi/ec.c we use mpi_powm for x^2 mod p: Either implement a
 
47
    special case in mpi_powm or check whether mpi_mulm is faster.
 
48
 
 
49
  - Decide whether we should hide the mpi_point_t definition.
 
50
 
 
51
  - Support more than just ECDSA.
 
52
*/
 
53
 
 
54
 
 
55
 
 
56
#include "g10lib.h"
 
57
#include "mpi.h"
 
58
#include "cipher.h"
 
59
 
 
60
 
 
61
/* Definition of a curve.  */
 
62
typedef struct
 
63
{
 
64
  gcry_mpi_t p;   /* Prime specifying the field GF(p).  */
 
65
  gcry_mpi_t a;   /* First coefficient of the Weierstrass equation.  */
 
66
  gcry_mpi_t b;   /* Second coefficient of the Weierstrass equation.  */
 
67
  mpi_point_t G;  /* Base point (generator).  */
 
68
  gcry_mpi_t n;   /* Order of G.  */
 
69
} elliptic_curve_t; 
 
70
 
 
71
 
 
72
typedef struct
 
73
{
 
74
  elliptic_curve_t E;
 
75
  mpi_point_t Q;  /* Q = [d]G  */
 
76
} ECC_public_key;
 
77
 
 
78
typedef struct
 
79
{
 
80
  elliptic_curve_t E;
 
81
  mpi_point_t Q;
 
82
  gcry_mpi_t d;
 
83
} ECC_secret_key;
 
84
 
 
85
 
 
86
/* This tables defines aliases for curve names.  */
 
87
static const struct
 
88
{
 
89
  const char *name;  /* Our name.  */
 
90
  const char *other; /* Other name. */
 
91
} curve_aliases[] = 
 
92
  {
 
93
    { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID  */
 
94
    { "NIST P-192", "prime192v1" },          /* X9.62 name.  */
 
95
    { "NIST P-192", "secp192r1"  },          /* SECP name.  */
 
96
 
 
97
    { "NIST P-224", "secp224r1" },
 
98
    { "NIST P-224", "1.3.132.0.33" },        /* SECP OID.  */
 
99
 
 
100
    { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1.  */
 
101
    { "NIST P-256", "prime256v1" },          
 
102
    { "NIST P-256", "secp256r1"  },
 
103
 
 
104
    { "NIST P-384", "secp384r1" },
 
105
    { "NIST P-384", "1.3.132.0.34" },       
 
106
 
 
107
    { "NIST P-521", "secp521r1" },
 
108
    { "NIST P-521", "1.3.132.0.35" },
 
109
 
 
110
    { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" },
 
111
    { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" },
 
112
    { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" },
 
113
    { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" },
 
114
    { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" },
 
115
    { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"},
 
116
    { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"},
 
117
 
 
118
    { NULL, NULL}
 
119
  };
 
120
 
 
121
 
 
122
 
 
123
/* This static table defines all available curves.  */
 
124
static const struct
 
125
{
 
126
  const char *desc;           /* Description of the curve.  */
 
127
  unsigned int nbits;         /* Number of bits.  */
 
128
  unsigned int fips:1;        /* True if this is a FIPS140-2 approved curve. */
 
129
  const char  *p;             /* Order of the prime field.  */
 
130
  const char *a, *b;          /* The coefficients. */
 
131
  const char *n;              /* The order of the base point.  */
 
132
  const char *g_x, *g_y;      /* Base point.  */
 
133
} domain_parms[] =
 
134
  {
 
135
    {
 
136
      "NIST P-192", 192, 1,
 
137
      "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
 
138
      "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
 
139
      "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
 
140
      "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
 
141
 
 
142
      "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
 
143
      "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
 
144
    },
 
145
    {
 
146
      "NIST P-224", 224, 1,
 
147
      "0xffffffffffffffffffffffffffffffff000000000000000000000001",
 
148
      "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
 
149
      "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
 
150
      "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
 
151
 
 
152
      "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
 
153
      "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
 
154
    },
 
155
    {
 
156
      "NIST P-256", 256, 1,
 
157
      "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
 
158
      "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
 
159
      "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
 
160
      "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
 
161
 
 
162
      "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
 
163
      "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
 
164
    },
 
165
    {
 
166
      "NIST P-384", 384, 1,
 
167
      "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
 
168
      "ffffffff0000000000000000ffffffff",
 
169
      "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
 
170
      "ffffffff0000000000000000fffffffc",
 
171
      "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
 
172
      "c656398d8a2ed19d2a85c8edd3ec2aef",
 
173
      "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
 
174
      "581a0db248b0a77aecec196accc52973",
 
175
 
 
176
      "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
 
177
      "5502f25dbf55296c3a545e3872760ab7",
 
178
      "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
 
179
      "0a60b1ce1d7e819d7a431d7c90ea0e5f"
 
180
    },
 
181
    {
 
182
      "NIST P-521", 521, 1,
 
183
      "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
 
184
      "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
 
185
      "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
 
186
      "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
 
187
      "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
 
188
      "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
 
189
      "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
 
190
      "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
 
191
 
 
192
      "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
 
193
      "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
 
194
      "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
 
195
      "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
 
196
    },
 
197
 
 
198
    { "brainpoolP160r1", 160, 0, 
 
199
      "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
 
200
      "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
 
201
      "0x1e589a8595423412134faa2dbdec95c8d8675e58",
 
202
      "0xe95e4a5f737059dc60df5991d45029409e60fc09",
 
203
      "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
 
204
      "0x1667cb477a1a8ec338f94741669c976316da6321"
 
205
    },
 
206
 
 
207
    { "brainpoolP192r1", 192, 0, 
 
208
      "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
 
209
      "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
 
210
      "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
 
211
      "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
 
212
      "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
 
213
      "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
 
214
    },
 
215
 
 
216
    { "brainpoolP224r1", 224, 0,
 
217
      "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
 
218
      "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
 
219
      "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
 
220
      "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
 
221
      "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
 
222
      "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
 
223
    },
 
224
 
 
225
    { "brainpoolP256r1", 256, 0,
 
226
      "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
 
227
      "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
 
228
      "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
 
229
      "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
 
230
      "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
 
231
      "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
 
232
    },
 
233
 
 
234
    { "brainpoolP320r1", 320, 0,
 
235
      "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
 
236
      "fcd412b1f1b32e27",
 
237
      "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
 
238
      "92f375a97d860eb4",
 
239
      "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981"
 
240
      "6f5eb4ac8fb1f1a6",
 
241
      "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9"
 
242
      "8691555b44c59311",
 
243
      "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
 
244
      "10af8d0d39e20611",
 
245
      "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
 
246
      "d35245d1692e8ee1"
 
247
    },
 
248
 
 
249
    { "brainpoolP384r1", 384, 0,
 
250
      "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
 
251
      "acd3a729901d1a71874700133107ec53",
 
252
      "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
 
253
      "8aa5814a503ad4eb04a8c7dd22ce2826",
 
254
      "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5"
 
255
      "7cb4390295dbc9943ab78696fa504c11",
 
256
      "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7"
 
257
      "cf3ab6af6b7fc3103b883202e9046565",
 
258
      "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
 
259
      "e826e03436d646aaef87b2e247d4af1e",
 
260
      "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
 
261
      "0e4646217791811142820341263c5315"
 
262
    },
 
263
 
 
264
    { "brainpoolP512r1", 512, 0,
 
265
      "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
 
266
      "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
 
267
      "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
 
268
      "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca",
 
269
      "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7"
 
270
      "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723",
 
271
      "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870"
 
272
      "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
 
273
      "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
 
274
      "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
 
275
      "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
 
276
      "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
 
277
    },
 
278
 
 
279
    { NULL, 0, 0, NULL, NULL, NULL, NULL }
 
280
  };
 
281
 
 
282
 
 
283
/* Registered progress function and its callback value. */
 
284
static void (*progress_cb) (void *, const char*, int, int, int);
 
285
static void *progress_cb_data;
 
286
 
 
287
 
 
288
#define point_init(a)  _gcry_mpi_ec_point_init ((a))
 
289
#define point_free(a)  _gcry_mpi_ec_point_free ((a))
 
290
 
 
291
 
 
292
 
 
293
/* Local prototypes. */
 
294
static gcry_mpi_t gen_k (gcry_mpi_t p, int security_level);
 
295
static void test_keys (ECC_secret_key * sk, unsigned int nbits);
 
296
static int check_secret_key (ECC_secret_key * sk);
 
297
static gpg_err_code_t sign (gcry_mpi_t input, ECC_secret_key *skey,
 
298
                            gcry_mpi_t r, gcry_mpi_t s);
 
299
static gpg_err_code_t verify (gcry_mpi_t input, ECC_public_key *pkey,
 
300
                              gcry_mpi_t r, gcry_mpi_t s);
 
301
 
 
302
 
 
303
static gcry_mpi_t gen_y_2 (gcry_mpi_t x, elliptic_curve_t * base);
 
304
 
 
305
 
 
306
 
 
307
 
 
308
void
 
309
_gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
 
310
                                            int, int, int),
 
311
                                void *cb_data)
 
312
{
 
313
  progress_cb = cb;
 
314
  progress_cb_data = cb_data;
 
315
}
 
316
 
 
317
/* static void */
 
318
/* progress (int c) */
 
319
/* { */
 
320
/*   if (progress_cb) */
 
321
/*     progress_cb (progress_cb_data, "pk_ecc", c, 0, 0); */
 
322
/* } */
 
323
 
 
324
 
 
325
 
 
326
 
 
327
/* Set the value from S into D.  */
 
328
static void
 
329
point_set (mpi_point_t *d, mpi_point_t *s)
 
330
{
 
331
  mpi_set (d->x, s->x);
 
332
  mpi_set (d->y, s->y);
 
333
  mpi_set (d->z, s->z);
 
334
}
 
335
 
 
336
 
 
337
/*
 
338
 * Release a curve object.
 
339
 */
 
340
static void
 
341
curve_free (elliptic_curve_t *E)
 
342
{
 
343
  mpi_free (E->p); E->p = NULL;
 
344
  mpi_free (E->a); E->a = NULL;
 
345
  mpi_free (E->b);  E->b = NULL;
 
346
  point_free (&E->G);
 
347
  mpi_free (E->n);  E->n = NULL;
 
348
}
 
349
 
 
350
 
 
351
/*
 
352
 * Return a copy of a curve object.
 
353
 */
 
354
static elliptic_curve_t
 
355
curve_copy (elliptic_curve_t E)
 
356
{
 
357
  elliptic_curve_t R;
 
358
 
 
359
  R.p = mpi_copy (E.p);
 
360
  R.a = mpi_copy (E.a);
 
361
  R.b = mpi_copy (E.b);
 
362
  point_init (&R.G);
 
363
  point_set (&R.G, &E.G);
 
364
  R.n = mpi_copy (E.n);
 
365
 
 
366
  return R;
 
367
}
 
368
 
 
369
 
 
370
 
 
371
/* Helper to scan a hex string. */
 
372
static gcry_mpi_t
 
373
scanval (const char *string)
 
374
{
 
375
  gpg_error_t err;
 
376
  gcry_mpi_t val;
 
377
 
 
378
  err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
 
379
  if (err)
 
380
    log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err));
 
381
  return val;
 
382
}
 
383
 
 
384
 
 
385
 
 
386
 
 
387
 
 
388
/****************
 
389
 * Solve the right side of the equation that defines a curve.
 
390
 */
 
391
static gcry_mpi_t
 
392
gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base)
 
393
{
 
394
  gcry_mpi_t three, x_3, axb, y;
 
395
 
 
396
  three = mpi_alloc_set_ui (3);
 
397
  x_3 = mpi_new (0);
 
398
  axb = mpi_new (0);
 
399
  y   = mpi_new (0);
 
400
 
 
401
  mpi_powm (x_3, x, three, base->p);  
 
402
  mpi_mulm (axb, base->a, x, base->p); 
 
403
  mpi_addm (axb, axb, base->b, base->p);     
 
404
  mpi_addm (y, x_3, axb, base->p);    
 
405
 
 
406
  mpi_free (x_3);
 
407
  mpi_free (axb);
 
408
  mpi_free (three);
 
409
  return y; /* The quadratic value of the coordinate if it exist. */
 
410
}
 
411
 
 
412
 
 
413
 
 
414
 
 
415
 
 
416
/* Generate a random secret scalar k with an order of p
 
417
 
 
418
   At the beginning this was identical to the code is in elgamal.c.
 
419
   Later imporved by mmr.   Further simplified by wk.  */
 
420
static gcry_mpi_t
 
421
gen_k (gcry_mpi_t p, int security_level)
 
422
{
 
423
  gcry_mpi_t k;
 
424
  unsigned int nbits;
 
425
 
 
426
  nbits = mpi_get_nbits (p);
 
427
  k = mpi_snew (nbits);
 
428
  if (DBG_CIPHER)
 
429
    log_debug ("choosing a random k of %u bits\n", nbits);
 
430
 
 
431
  gcry_mpi_randomize (k, nbits, security_level);
 
432
 
 
433
  mpi_mod (k, k, p);  /*  k = k mod p  */
 
434
 
 
435
  return k;
 
436
}
 
437
 
 
438
/****************
 
439
 * Generate the crypto system setup.
 
440
 * As of now the fix NIST recommended values are used.
 
441
 * The subgroup generator point is in another function: gen_big_point.
 
442
 */
 
443
static gpg_err_code_t
 
444
generate_curve (unsigned int nbits, const char *name, 
 
445
                elliptic_curve_t *curve, unsigned int *r_nbits)
 
446
{
 
447
  int idx, aliasno;
 
448
 
 
449
  if (name)
 
450
    {
 
451
      /* First check nor native curves.  */
 
452
      for (idx = 0; domain_parms[idx].desc; idx++)
 
453
        if (!strcmp (name, domain_parms[idx].desc))
 
454
          break;
 
455
      /* If not found consult the alias table.  */
 
456
      if (!domain_parms[idx].desc)
 
457
        {
 
458
          for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
 
459
            if (!strcmp (name, curve_aliases[aliasno].other))
 
460
              break;
 
461
          if (curve_aliases[aliasno].name)
 
462
            {
 
463
              for (idx = 0; domain_parms[idx].desc; idx++)
 
464
                if (!strcmp (curve_aliases[aliasno].name,
 
465
                             domain_parms[idx].desc))
 
466
                  break;
 
467
            }
 
468
        }
 
469
    }
 
470
  else
 
471
    {
 
472
      for (idx = 0; domain_parms[idx].desc; idx++)
 
473
        if (nbits == domain_parms[idx].nbits)
 
474
          break;
 
475
    }
 
476
  if (!domain_parms[idx].desc)
 
477
    return GPG_ERR_INV_VALUE;
 
478
 
 
479
  /* In fips mode we only support NIST curves.  Note that it is
 
480
     possible to bypass this check by specifying the curve parameters
 
481
     directly.  */
 
482
  if (fips_mode () && !domain_parms[idx].fips )
 
483
    return GPG_ERR_NOT_SUPPORTED; 
 
484
  
 
485
 
 
486
  *r_nbits = domain_parms[idx].nbits;
 
487
  curve->p = scanval (domain_parms[idx].p);
 
488
  curve->a = scanval (domain_parms[idx].a);
 
489
  curve->b = scanval (domain_parms[idx].b);
 
490
  curve->n = scanval (domain_parms[idx].n);
 
491
  curve->G.x = scanval (domain_parms[idx].g_x);
 
492
  curve->G.y = scanval (domain_parms[idx].g_y);
 
493
  curve->G.z = mpi_alloc_set_ui (1);
 
494
 
 
495
  return 0;
 
496
}
 
497
 
 
498
 
 
499
/*
 
500
 * First obtain the setup.  Over the finite field randomize an scalar
 
501
 * secret value, and calculate the public point.
 
502
 */
 
503
static gpg_err_code_t
 
504
generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
 
505
              gcry_mpi_t g_x, gcry_mpi_t g_y,
 
506
              gcry_mpi_t q_x, gcry_mpi_t q_y)
 
507
{
 
508
  gpg_err_code_t err;
 
509
  elliptic_curve_t E;
 
510
  gcry_mpi_t d;
 
511
  mpi_point_t Q;
 
512
  mpi_ec_t ctx;
 
513
 
 
514
  err = generate_curve (nbits, name, &E, &nbits);
 
515
  if (err)
 
516
    return err;
 
517
 
 
518
  if (DBG_CIPHER)
 
519
    {
 
520
      log_mpidump ("ecc generation   p", E.p);
 
521
      log_mpidump ("ecc generation   a", E.a);
 
522
      log_mpidump ("ecc generation   b", E.b);
 
523
      log_mpidump ("ecc generation   n", E.n);
 
524
      log_mpidump ("ecc generation  Gx", E.G.x);
 
525
      log_mpidump ("ecc generation  Gy", E.G.y);
 
526
      log_mpidump ("ecc generation  Gz", E.G.z);
 
527
    }
 
528
 
 
529
  if (DBG_CIPHER)
 
530
    log_debug ("choosing a random x of size %u\n", nbits);
 
531
  d = gen_k (E.n, GCRY_VERY_STRONG_RANDOM); 
 
532
 
 
533
  /* Compute Q.  */
 
534
  point_init (&Q);
 
535
  ctx = _gcry_mpi_ec_init (E.p, E.a);
 
536
  _gcry_mpi_ec_mul_point (&Q, d, &E.G, ctx);
 
537
 
 
538
  /* Copy the stuff to the key structures. */
 
539
  sk->E.p = mpi_copy (E.p);
 
540
  sk->E.a = mpi_copy (E.a);
 
541
  sk->E.b = mpi_copy (E.b);
 
542
  point_init (&sk->E.G);
 
543
  point_set (&sk->E.G, &E.G);
 
544
  sk->E.n = mpi_copy (E.n);
 
545
  point_init (&sk->Q);
 
546
  point_set (&sk->Q, &Q);
 
547
  sk->d    = mpi_copy (d);
 
548
  /* We also return copies of G and Q in affine coordinates if
 
549
     requested.  */
 
550
  if (g_x && g_y)
 
551
    {
 
552
      if (_gcry_mpi_ec_get_affine (g_x, g_y, &sk->E.G, ctx))
 
553
        log_fatal ("ecc generate: Failed to get affine coordinates\n");
 
554
    }
 
555
  if (q_x && q_y)
 
556
    {
 
557
      if (_gcry_mpi_ec_get_affine (q_x, q_y, &sk->Q, ctx))
 
558
        log_fatal ("ecc generate: Failed to get affine coordinates\n");
 
559
    }
 
560
  _gcry_mpi_ec_free (ctx);
 
561
 
 
562
  point_free (&Q);
 
563
  mpi_free (d);
 
564
  curve_free (&E);
 
565
 
 
566
  /* Now we can test our keys (this should never fail!). */
 
567
  test_keys (sk, nbits - 64);
 
568
 
 
569
  return 0;
 
570
}
 
571
 
 
572
 
 
573
/****************
 
574
 * To verify correct skey it use a random information.
 
575
 * First, encrypt and decrypt this dummy value,
 
576
 * test if the information is recuperated.
 
577
 * Second, test with the sign and verify functions.
 
578
 */
 
579
static void
 
580
test_keys (ECC_secret_key *sk, unsigned int nbits)
 
581
{
 
582
  ECC_public_key pk;
 
583
  gcry_mpi_t test = mpi_new (nbits);
 
584
  mpi_point_t R_;
 
585
  gcry_mpi_t c = mpi_new (nbits);
 
586
  gcry_mpi_t out = mpi_new (nbits);
 
587
  gcry_mpi_t r = mpi_new (nbits);
 
588
  gcry_mpi_t s = mpi_new (nbits);
 
589
 
 
590
  if (DBG_CIPHER)
 
591
    log_debug ("Testing key.\n");
 
592
 
 
593
  point_init (&R_);
 
594
 
 
595
  pk.E = curve_copy (sk->E);
 
596
  point_init (&pk.Q);
 
597
  point_set (&pk.Q, &sk->Q);
 
598
 
 
599
  gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
 
600
 
 
601
  if (sign (test, sk, r, s) )
 
602
    log_fatal ("ECDSA operation: sign failed\n");
 
603
 
 
604
  if (verify (test, &pk, r, s))
 
605
    {
 
606
      log_fatal ("ECDSA operation: sign, verify failed\n");
 
607
    }
 
608
 
 
609
  if (DBG_CIPHER)
 
610
    log_debug ("ECDSA operation: sign, verify ok.\n");
 
611
 
 
612
  point_free (&pk.Q);
 
613
  curve_free (&pk.E);
 
614
 
 
615
  point_free (&R_);
 
616
  mpi_free (s);
 
617
  mpi_free (r);
 
618
  mpi_free (out);
 
619
  mpi_free (c);
 
620
  mpi_free (test);
 
621
}
 
622
 
 
623
/****************
 
624
 * To check the validity of the value, recalculate the correspondence
 
625
 * between the public value and the secret one.
 
626
 */
 
627
static int
 
628
check_secret_key (ECC_secret_key * sk)
 
629
{
 
630
  mpi_point_t Q;
 
631
  gcry_mpi_t y_2, y2 = mpi_alloc (0);
 
632
  mpi_ec_t ctx;
 
633
 
 
634
  /* ?primarity test of 'p' */
 
635
  /*  (...) //!! */
 
636
  /* G in E(F_p) */
 
637
  y_2 = gen_y_2 (sk->E.G.x, &sk->E);   /*  y^2=x^3+a*x+b */
 
638
  mpi_mulm (y2, sk->E.G.y, sk->E.G.y, sk->E.p);      /*  y^2=y*y */
 
639
  if (mpi_cmp (y_2, y2))
 
640
    {
 
641
      if (DBG_CIPHER)
 
642
        log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n");
 
643
      return (1);
 
644
    }
 
645
  /* G != PaI */
 
646
  if (!mpi_cmp_ui (sk->E.G.z, 0))
 
647
    {
 
648
      if (DBG_CIPHER)
 
649
        log_debug ("Bad check: 'G' cannot be Point at Infinity!\n");
 
650
      return (1);
 
651
    }
 
652
 
 
653
  point_init (&Q);
 
654
  ctx = _gcry_mpi_ec_init (sk->E.p, sk->E.a);
 
655
  _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx);
 
656
  if (mpi_cmp_ui (Q.z, 0))
 
657
    {
 
658
      if (DBG_CIPHER)
 
659
        log_debug ("check_secret_key: E is not a curve of order n\n");
 
660
      point_free (&Q);
 
661
      _gcry_mpi_ec_free (ctx);
 
662
      return 1;
 
663
    }
 
664
  /* pubkey cannot be PaI */
 
665
  if (!mpi_cmp_ui (sk->Q.z, 0))
 
666
    {
 
667
      if (DBG_CIPHER)
 
668
        log_debug ("Bad check: Q can not be a Point at Infinity!\n");
 
669
      _gcry_mpi_ec_free (ctx);
 
670
      return (1);
 
671
    }
 
672
  /* pubkey = [d]G over E */
 
673
  _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx);
 
674
  if ((Q.x == sk->Q.x) && (Q.y == sk->Q.y) && (Q.z == sk->Q.z))
 
675
    {
 
676
      if (DBG_CIPHER)
 
677
        log_debug
 
678
          ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
 
679
      _gcry_mpi_ec_free (ctx);
 
680
      return (1);
 
681
    }
 
682
  _gcry_mpi_ec_free (ctx);
 
683
  point_free (&Q);
 
684
  return 0;
 
685
}
 
686
 
 
687
 
 
688
/*
 
689
 * Return the signature struct (r,s) from the message hash.  The caller
 
690
 * must have allocated R and S.
 
691
 */
 
692
static gpg_err_code_t
 
693
sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s)
 
694
{
 
695
  gpg_err_code_t err = 0;
 
696
  gcry_mpi_t k, dr, sum, k_1, x;
 
697
  mpi_point_t I;
 
698
  mpi_ec_t ctx;
 
699
 
 
700
  k = NULL;
 
701
  dr = mpi_alloc (0);
 
702
  sum = mpi_alloc (0);
 
703
  k_1 = mpi_alloc (0);
 
704
  x = mpi_alloc (0);
 
705
  point_init (&I);
 
706
 
 
707
  mpi_set_ui (s, 0);
 
708
  mpi_set_ui (r, 0);
 
709
 
 
710
  ctx = _gcry_mpi_ec_init (skey->E.p, skey->E.a);
 
711
 
 
712
  while (!mpi_cmp_ui (s, 0)) /* s == 0 */
 
713
    {
 
714
      while (!mpi_cmp_ui (r, 0)) /* r == 0 */
 
715
        {
 
716
          /* Note, that we are guaranteed to enter this loop at least
 
717
             once because r has been intialized to 0.  We can't use a
 
718
             do_while because we want to keep the value of R even if S
 
719
             has to be recomputed.  */
 
720
          mpi_free (k);
 
721
          k = gen_k (skey->E.n, GCRY_STRONG_RANDOM);
 
722
          _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx); 
 
723
          if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx))
 
724
            {
 
725
              if (DBG_CIPHER)
 
726
                log_debug ("ecc sign: Failed to get affine coordinates\n");
 
727
              err = GPG_ERR_BAD_SIGNATURE;
 
728
              goto leave;
 
729
            }
 
730
          mpi_mod (r, x, skey->E.n);  /* r = x mod n */
 
731
        }
 
732
      mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n  */
 
733
      mpi_addm (sum, input, dr, skey->E.n); /* sum = hash + (d*r) mod n  */
 
734
      mpi_invm (k_1, k, skey->E.n);         /* k_1 = k^(-1) mod n  */
 
735
      mpi_mulm (s, k_1, sum, skey->E.n);    /* s = k^(-1)*(hash+(d*r)) mod n */
 
736
    }
 
737
 
 
738
 leave:
 
739
  _gcry_mpi_ec_free (ctx);
 
740
  point_free (&I);
 
741
  mpi_free (x);
 
742
  mpi_free (k_1);
 
743
  mpi_free (sum);
 
744
  mpi_free (dr);
 
745
  mpi_free (k);
 
746
 
 
747
  return err;
 
748
}
 
749
 
 
750
/*
 
751
 * Check if R and S verifies INPUT.
 
752
 */
 
753
static gpg_err_code_t
 
754
verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s)
 
755
{
 
756
  gpg_err_code_t err = 0;
 
757
  gcry_mpi_t h, h1, h2, x, y;
 
758
  mpi_point_t Q, Q1, Q2;
 
759
  mpi_ec_t ctx;
 
760
 
 
761
  if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) )
 
762
    return GPG_ERR_BAD_SIGNATURE; /* Assertion  0 < r < n  failed.  */
 
763
  if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, pkey->E.n) < 0) )
 
764
    return GPG_ERR_BAD_SIGNATURE; /* Assertion  0 < s < n  failed.  */
 
765
 
 
766
  h  = mpi_alloc (0);
 
767
  h1 = mpi_alloc (0);
 
768
  h2 = mpi_alloc (0);
 
769
  x = mpi_alloc (0);
 
770
  y = mpi_alloc (0);
 
771
  point_init (&Q);
 
772
  point_init (&Q1);
 
773
  point_init (&Q2);
 
774
 
 
775
  ctx = _gcry_mpi_ec_init (pkey->E.p, pkey->E.a);
 
776
 
 
777
  /* h  = s^(-1) (mod n) */
 
778
  mpi_invm (h, s, pkey->E.n);
 
779
/*   log_mpidump ("   h", h); */
 
780
  /* h1 = hash * s^(-1) (mod n) */
 
781
  mpi_mulm (h1, input, h, pkey->E.n);
 
782
/*   log_mpidump ("  h1", h1); */
 
783
  /* Q1 = [ hash * s^(-1) ]G  */
 
784
  _gcry_mpi_ec_mul_point (&Q1, h1, &pkey->E.G, ctx);
 
785
/*   log_mpidump ("Q1.x", Q1.x); */
 
786
/*   log_mpidump ("Q1.y", Q1.y); */
 
787
/*   log_mpidump ("Q1.z", Q1.z); */
 
788
  /* h2 = r * s^(-1) (mod n) */
 
789
  mpi_mulm (h2, r, h, pkey->E.n);
 
790
/*   log_mpidump ("  h2", h2); */
 
791
  /* Q2 = [ r * s^(-1) ]Q */
 
792
  _gcry_mpi_ec_mul_point (&Q2, h2, &pkey->Q, ctx);
 
793
/*   log_mpidump ("Q2.x", Q2.x); */
 
794
/*   log_mpidump ("Q2.y", Q2.y); */
 
795
/*   log_mpidump ("Q2.z", Q2.z); */
 
796
  /* Q  = ([hash * s^(-1)]G) + ([r * s^(-1)]Q) */
 
797
  _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ctx);
 
798
/*   log_mpidump (" Q.x", Q.x); */
 
799
/*   log_mpidump (" Q.y", Q.y); */
 
800
/*   log_mpidump (" Q.z", Q.z); */
 
801
 
 
802
  if (!mpi_cmp_ui (Q.z, 0))
 
803
    {
 
804
      if (DBG_CIPHER)
 
805
          log_debug ("ecc verify: Rejected\n");
 
806
      err = GPG_ERR_BAD_SIGNATURE;
 
807
      goto leave;
 
808
    }
 
809
  if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx))
 
810
    {
 
811
      if (DBG_CIPHER)
 
812
        log_debug ("ecc verify: Failed to get affine coordinates\n");
 
813
      err = GPG_ERR_BAD_SIGNATURE;
 
814
      goto leave;
 
815
    }
 
816
  mpi_mod (x, x, pkey->E.n); /* x = x mod E_n */
 
817
  if (mpi_cmp (x, r))   /* x != r */
 
818
    {
 
819
      if (DBG_CIPHER)
 
820
        {
 
821
          log_mpidump ("   x", x);
 
822
          log_mpidump ("   y", y);
 
823
          log_mpidump ("   r", r);
 
824
          log_mpidump ("   s", s);
 
825
          log_debug ("ecc verify: Not verified\n");
 
826
        }
 
827
      err = GPG_ERR_BAD_SIGNATURE;
 
828
      goto leave;
 
829
    }
 
830
  if (DBG_CIPHER)
 
831
    log_debug ("ecc verify: Accepted\n");
 
832
 
 
833
 leave:
 
834
  _gcry_mpi_ec_free (ctx);
 
835
  point_free (&Q2);
 
836
  point_free (&Q1);
 
837
  point_free (&Q);
 
838
  mpi_free (y);
 
839
  mpi_free (x);
 
840
  mpi_free (h2);
 
841
  mpi_free (h1);
 
842
  mpi_free (h);
 
843
  return err;
 
844
}
 
845
 
 
846
 
 
847
 
 
848
/*********************************************
 
849
 **************  interface  ******************
 
850
 *********************************************/
 
851
static gcry_mpi_t
 
852
ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p)
 
853
{
 
854
  gpg_error_t err;
 
855
  int pbytes = (mpi_get_nbits (p)+7)/8;
 
856
  size_t n;
 
857
  unsigned char *buf, *ptr;
 
858
  gcry_mpi_t result;
 
859
 
 
860
  buf = gcry_xmalloc ( 1 + 2*pbytes );
 
861
  *buf = 04; /* Uncompressed point.  */
 
862
  ptr = buf+1;
 
863
  err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x);
 
864
  if (err)
 
865
    log_fatal ("mpi_print failed: %s\n", gpg_strerror (err));
 
866
  if (n < pbytes)
 
867
    {
 
868
      memmove (ptr+(pbytes-n), ptr, n);
 
869
      memset (ptr, 0, (pbytes-n));
 
870
    }
 
871
  ptr += pbytes;
 
872
  err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y);
 
873
  if (err)
 
874
    log_fatal ("mpi_print failed: %s\n", gpg_strerror (err));
 
875
  if (n < pbytes)
 
876
    {
 
877
      memmove (ptr+(pbytes-n), ptr, n);
 
878
      memset (ptr, 0, (pbytes-n));
 
879
    }
 
880
  
 
881
  err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL);
 
882
  if (err)
 
883
    log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err));
 
884
  gcry_free (buf);
 
885
 
 
886
  mpi_free (x);
 
887
  mpi_free (y);
 
888
 
 
889
  return result;
 
890
}
 
891
 
 
892
/* RESULT must have been initialized and is set on success to the
 
893
   point given by VALUE.  */
 
894
static gcry_error_t
 
895
os2ec (mpi_point_t *result, gcry_mpi_t value)
 
896
{
 
897
  gcry_error_t err;
 
898
  size_t n;
 
899
  unsigned char *buf;
 
900
  gcry_mpi_t x, y;
 
901
 
 
902
  n = (mpi_get_nbits (value)+7)/8;
 
903
  buf = gcry_xmalloc (n);
 
904
  err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, n, &n, value);
 
905
  if (err)
 
906
    {
 
907
      gcry_free (buf);
 
908
      return err;
 
909
    }
 
910
  if (n < 1) 
 
911
    {
 
912
      gcry_free (buf);
 
913
      return GPG_ERR_INV_OBJ;
 
914
    }
 
915
  if (*buf != 4)
 
916
    {
 
917
      gcry_free (buf);
 
918
      return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression.  */
 
919
    }
 
920
  if ( ((n-1)%2) ) 
 
921
    {
 
922
      gcry_free (buf);
 
923
      return GPG_ERR_INV_OBJ;
 
924
    }
 
925
  n = (n-1)/2;
 
926
  err = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL);
 
927
  if (err)
 
928
    {
 
929
      gcry_free (buf);
 
930
      return err;
 
931
    }
 
932
  err = gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL);
 
933
  gcry_free (buf);
 
934
  if (err)
 
935
    {
 
936
      mpi_free (x);
 
937
      return err;
 
938
    }
 
939
 
 
940
  mpi_set (result->x, x);
 
941
  mpi_set (result->y, y);
 
942
  mpi_set_ui (result->z, 1);
 
943
 
 
944
  mpi_free (x);
 
945
  mpi_free (y);
 
946
  
 
947
  return 0;
 
948
}
 
949
 
 
950
 
 
951
/* Extended version of ecc_generate.  */
 
952
static gcry_err_code_t
 
953
ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
 
954
                  const gcry_sexp_t genparms,
 
955
                  gcry_mpi_t *skey, gcry_mpi_t **retfactors,
 
956
                  gcry_sexp_t *r_extrainfo)
 
957
{
 
958
  gpg_err_code_t ec;
 
959
  ECC_secret_key sk;
 
960
  gcry_mpi_t g_x, g_y, q_x, q_y;
 
961
  char *curve_name = NULL;
 
962
  gcry_sexp_t l1;
 
963
 
 
964
  (void)algo;
 
965
  (void)evalue;
 
966
  (void)r_extrainfo;
 
967
 
 
968
  if (genparms)
 
969
    {
 
970
      /* Parse the optional "curve" parameter. */
 
971
      l1 = gcry_sexp_find_token (genparms, "curve", 0);
 
972
      if (l1)
 
973
        {
 
974
          curve_name = _gcry_sexp_nth_string (l1, 1);
 
975
          gcry_sexp_release (l1);
 
976
          if (!curve_name)
 
977
            return GPG_ERR_INV_OBJ; /* No curve name or value too large. */
 
978
        }
 
979
    }
 
980
 
 
981
  /* NBITS is required if no curve name has been given.  */
 
982
  if (!nbits && !curve_name)
 
983
    return GPG_ERR_NO_OBJ; /* No NBITS parameter. */
 
984
 
 
985
  g_x = mpi_new (0);
 
986
  g_y = mpi_new (0);
 
987
  q_x = mpi_new (0);
 
988
  q_y = mpi_new (0);
 
989
  ec = generate_key (&sk, nbits, curve_name, g_x, g_y, q_x, q_y);
 
990
  gcry_free (curve_name);
 
991
  if (ec)
 
992
    return ec;
 
993
 
 
994
  skey[0] = sk.E.p;
 
995
  skey[1] = sk.E.a;
 
996
  skey[2] = sk.E.b;
 
997
  /* The function ec2os releases g_x and g_y.  */
 
998
  skey[3] = ec2os (g_x, g_y, sk.E.p);
 
999
  skey[4] = sk.E.n;
 
1000
  /* The function ec2os releases g_x and g_y.  */
 
1001
  skey[5] = ec2os (q_x, q_y, sk.E.p);
 
1002
  skey[6] = sk.d;
 
1003
 
 
1004
  point_free (&sk.E.G);
 
1005
  point_free (&sk.Q);
 
1006
 
 
1007
  /* Make an empty list of factors.  */
 
1008
  *retfactors = gcry_calloc ( 1, sizeof **retfactors );
 
1009
  if (!*retfactors)
 
1010
    return gpg_err_code_from_syserror ();
 
1011
 
 
1012
  return 0;
 
1013
}
 
1014
 
 
1015
 
 
1016
static gcry_err_code_t
 
1017
ecc_generate (int algo, unsigned int nbits, unsigned long evalue,
 
1018
              gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 
1019
{
 
1020
  (void)evalue;
 
1021
  return ecc_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL);
 
1022
}
 
1023
 
 
1024
 
 
1025
/* Return the parameters of the curve NAME.  */
 
1026
static gcry_err_code_t
 
1027
ecc_get_param (const char *name, gcry_mpi_t *pkey)
 
1028
{
 
1029
  gpg_err_code_t err;
 
1030
  unsigned int nbits;
 
1031
  elliptic_curve_t E;
 
1032
  mpi_ec_t ctx;
 
1033
  gcry_mpi_t g_x, g_y;
 
1034
  
 
1035
  err = generate_curve (0, name, &E, &nbits);
 
1036
  if (err)
 
1037
    return err;
 
1038
 
 
1039
  g_x = mpi_new (0);
 
1040
  g_y = mpi_new (0);
 
1041
  ctx = _gcry_mpi_ec_init (E.p, E.a);
 
1042
  if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
 
1043
    log_fatal ("ecc get param: Failed to get affine coordinates\n");
 
1044
  _gcry_mpi_ec_free (ctx);
 
1045
  point_free (&E.G);
 
1046
 
 
1047
  pkey[0] = E.p;
 
1048
  pkey[1] = E.a;
 
1049
  pkey[2] = E.b;
 
1050
  pkey[3] = ec2os (g_x, g_y, E.p);
 
1051
  pkey[4] = E.n;
 
1052
  pkey[5] = NULL;
 
1053
 
 
1054
  return 0;
 
1055
}
 
1056
 
 
1057
 
 
1058
static gcry_err_code_t
 
1059
ecc_check_secret_key (int algo, gcry_mpi_t *skey)
 
1060
{
 
1061
  gpg_err_code_t err;
 
1062
  ECC_secret_key sk;
 
1063
 
 
1064
  (void)algo;
 
1065
 
 
1066
  if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5]
 
1067
      || !skey[6] || !skey[7] || !skey[8] || !skey[9] || !skey[10])
 
1068
    return GPG_ERR_BAD_MPI;
 
1069
 
 
1070
  sk.E.p = skey[0];
 
1071
  sk.E.a = skey[1];
 
1072
  sk.E.b = skey[2];
 
1073
  point_init (&sk.E.G);
 
1074
  err = os2ec (&sk.E.G, skey[3]);
 
1075
  if (err)
 
1076
    {
 
1077
      point_free (&sk.E.G);
 
1078
      return err;
 
1079
    }
 
1080
  sk.E.n = skey[4];
 
1081
  point_init (&sk.Q);
 
1082
  err = os2ec (&sk.Q, skey[5]);
 
1083
  if (err)
 
1084
    {
 
1085
      point_free (&sk.E.G);
 
1086
      point_free (&sk.Q);
 
1087
      return err;
 
1088
    }
 
1089
 
 
1090
  sk.d = skey[6];
 
1091
 
 
1092
  if (check_secret_key (&sk))
 
1093
    {
 
1094
      point_free (&sk.E.G);
 
1095
      point_free (&sk.Q);
 
1096
      return GPG_ERR_BAD_SECKEY;
 
1097
    }
 
1098
  point_free (&sk.E.G);
 
1099
  point_free (&sk.Q);
 
1100
  return 0;
 
1101
}
 
1102
 
 
1103
 
 
1104
static gcry_err_code_t
 
1105
ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
 
1106
{
 
1107
  gpg_err_code_t err;
 
1108
  ECC_secret_key sk;
 
1109
 
 
1110
  (void)algo;
 
1111
 
 
1112
  if (!data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4]
 
1113
      || !skey[5] || !skey[6] )
 
1114
    return GPG_ERR_BAD_MPI;
 
1115
 
 
1116
  sk.E.p = skey[0];
 
1117
  sk.E.a = skey[1];
 
1118
  sk.E.b = skey[2];
 
1119
  point_init (&sk.E.G);
 
1120
  err = os2ec (&sk.E.G, skey[3]);
 
1121
  if (err)
 
1122
    {
 
1123
      point_free (&sk.E.G);
 
1124
      return err;
 
1125
    }
 
1126
  sk.E.n = skey[4];
 
1127
  point_init (&sk.Q);
 
1128
  err = os2ec (&sk.Q, skey[5]);
 
1129
  if (err)
 
1130
    {
 
1131
      point_free (&sk.E.G);
 
1132
      point_free (&sk.Q);
 
1133
      return err;
 
1134
    }
 
1135
  sk.d = skey[6];
 
1136
 
 
1137
  resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
 
1138
  resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
 
1139
  err = sign (data, &sk, resarr[0], resarr[1]);
 
1140
  if (err)
 
1141
    {
 
1142
      mpi_free (resarr[0]);
 
1143
      mpi_free (resarr[1]);
 
1144
      resarr[0] = NULL; /* Mark array as released.  */
 
1145
    }
 
1146
  point_free (&sk.E.G);
 
1147
  point_free (&sk.Q);
 
1148
  return err;
 
1149
}
 
1150
 
 
1151
static gcry_err_code_t
 
1152
ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
 
1153
            int (*cmp)(void *, gcry_mpi_t), void *opaquev)
 
1154
{
 
1155
  gpg_err_code_t err;
 
1156
  ECC_public_key pk;
 
1157
 
 
1158
  (void)algo;
 
1159
  (void)cmp;
 
1160
  (void)opaquev;
 
1161
 
 
1162
  if (!data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] || !pkey[2]
 
1163
      || !pkey[3] || !pkey[4] || !pkey[5] )
 
1164
    return GPG_ERR_BAD_MPI;
 
1165
 
 
1166
  pk.E.p = pkey[0];
 
1167
  pk.E.a = pkey[1];
 
1168
  pk.E.b = pkey[2];
 
1169
  point_init (&pk.E.G);
 
1170
  err = os2ec (&pk.E.G, pkey[3]);
 
1171
  if (err)
 
1172
    {
 
1173
      point_free (&pk.E.G);
 
1174
      return err;
 
1175
    }
 
1176
  pk.E.n = pkey[4];
 
1177
  point_init (&pk.Q);
 
1178
  err = os2ec (&pk.Q, pkey[5]);
 
1179
  if (err)
 
1180
    {
 
1181
      point_free (&pk.E.G);
 
1182
      point_free (&pk.Q);
 
1183
      return err;
 
1184
    }
 
1185
 
 
1186
  err = verify (hash, &pk, data[0], data[1]);
 
1187
 
 
1188
  point_free (&pk.E.G);
 
1189
  point_free (&pk.Q);
 
1190
  return err;
 
1191
}
 
1192
 
 
1193
 
 
1194
 
 
1195
static unsigned int
 
1196
ecc_get_nbits (int algo, gcry_mpi_t *pkey)
 
1197
{
 
1198
  (void)algo;
 
1199
 
 
1200
  return mpi_get_nbits (pkey[0]);
 
1201
}
 
1202
 
 
1203
 
 
1204
 
 
1205
/* See rsa.c for a description of this function.  */
 
1206
static gpg_err_code_t
 
1207
compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
 
1208
{
 
1209
  static const char names[] = "pabgnq";
 
1210
  gpg_err_code_t ec = 0;
 
1211
  gcry_sexp_t l1;
 
1212
  gcry_mpi_t values[6];
 
1213
  int idx;
 
1214
 
 
1215
  /* Clear the values for easier error cleanup.  */
 
1216
  for (idx=0; idx < 6; idx++)
 
1217
    values[idx] = NULL;
 
1218
    
 
1219
  /* Fill values with all available parameters.  */
 
1220
  for (idx=0; idx < 6; idx++)
 
1221
    {
 
1222
      l1 = gcry_sexp_find_token (keyparam, names+idx, 1);
 
1223
      if (l1)
 
1224
        {
 
1225
          values[idx] = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
 
1226
          gcry_sexp_release (l1);
 
1227
          if (!values[idx])
 
1228
            {
 
1229
              ec = GPG_ERR_INV_OBJ;
 
1230
              goto leave;
 
1231
            }
 
1232
        }
 
1233
    }
 
1234
  
 
1235
  /* Check whether a curve parameter is available and use that to fill
 
1236
     in missing values.  */
 
1237
  l1 = gcry_sexp_find_token (keyparam, "curve", 5);
 
1238
  if (l1)
 
1239
    {
 
1240
      char *curve;
 
1241
      gcry_mpi_t tmpvalues[6];
 
1242
      
 
1243
      for (idx = 0; idx < 6; idx++)
 
1244
        tmpvalues[idx] = NULL;
 
1245
 
 
1246
      curve = _gcry_sexp_nth_string (l1, 1);
 
1247
      if (!curve)
 
1248
        {
 
1249
          ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
 
1250
          goto leave;
 
1251
        }
 
1252
      ec = ecc_get_param (curve, tmpvalues);
 
1253
      gcry_free (curve);
 
1254
      if (ec)
 
1255
        goto leave;
 
1256
 
 
1257
      for (idx = 0; idx < 6; idx++)
 
1258
        {
 
1259
          if (!values[idx])
 
1260
            values[idx] = tmpvalues[idx];
 
1261
          else
 
1262
            mpi_free (tmpvalues[idx]);
 
1263
        }
 
1264
    }
 
1265
 
 
1266
  /* Check that all parameters are known and normalize all MPIs (that
 
1267
     should not be required but we use an internal fucntion later and
 
1268
     thus we better make 100% sure that they are normalized). */
 
1269
  for (idx = 0; idx < 6; idx++)
 
1270
    if (!values[idx])
 
1271
      {
 
1272
        ec = GPG_ERR_NO_OBJ;
 
1273
        goto leave;
 
1274
      }
 
1275
    else
 
1276
      _gcry_mpi_normalize (values[idx]);
 
1277
      
 
1278
  /* Hash them all.  */
 
1279
  for (idx = 0; idx < 6; idx++)
 
1280
    {
 
1281
      char buf[30];
 
1282
      unsigned char *rawmpi;
 
1283
      unsigned int rawmpilen;
 
1284
      
 
1285
      rawmpi = _gcry_mpi_get_buffer (values[idx], &rawmpilen, NULL);
 
1286
      if (!rawmpi)
 
1287
        {
 
1288
          ec = gpg_err_code_from_syserror ();
 
1289
          goto leave;
 
1290
        }
 
1291
      snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], rawmpilen);
 
1292
      gcry_md_write (md, buf, strlen (buf));
 
1293
      gcry_md_write (md, rawmpi, rawmpilen);
 
1294
      gcry_md_write (md, ")", 1);
 
1295
      gcry_free (rawmpi);
 
1296
    }
 
1297
 
 
1298
 leave:
 
1299
  for (idx = 0; idx < 6; idx++)
 
1300
    _gcry_mpi_release (values[idx]);
 
1301
  
 
1302
  return ec;
 
1303
}
 
1304
 
 
1305
 
 
1306
 
 
1307
 
 
1308
 
 
1309
/* 
 
1310
     Self-test section.
 
1311
 */
 
1312
 
 
1313
 
 
1314
 
 
1315
 
 
1316
/* Run a full self-test for ALGO and return 0 on success.  */
 
1317
 
 
1318
 
 
1319
 
 
1320
 
 
1321
static const char *ecdsa_names[] =
 
1322
  {
 
1323
    "ecdsa",
 
1324
    "ecc",
 
1325
    NULL,
 
1326
  };
 
1327
 
 
1328
gcry_pk_spec_t _gcry_pubkey_spec_ecdsa =
 
1329
  {
 
1330
    "ECDSA", ecdsa_names,
 
1331
    "pabgnq", "pabgnqd", "", "rs", "pabgnq",
 
1332
    GCRY_PK_USAGE_SIGN,
 
1333
    ecc_generate,
 
1334
    ecc_check_secret_key,
 
1335
    NULL,
 
1336
    NULL,
 
1337
    ecc_sign,
 
1338
    ecc_verify,
 
1339
    ecc_get_nbits
 
1340
  };
 
1341
 
 
1342
pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = 
 
1343
  {
 
1344
    run_selftests,
 
1345
    ecc_generate_ext,
 
1346
    compute_keygrip,
 
1347
    ecc_get_param
 
1348
  };
 
1349