~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

Show diffs side-by-side

added added

removed removed

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