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

« back to all changes in this revision

Viewing changes to 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