1 /* ecc.c - Elliptic Curve Cryptography
2 Copyright (C) 2007, 2008 Free Software Foundation, Inc.
4 This file is part of Libgcrypt.
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.
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.
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,
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:
26 Sergi Blanch i Torne <d4372211 at alumnes.eup.udl.es>,
27 Ramiro Moreno Chiral <ramiro at eup.udl.es>
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. */
41 - If we support point compression we need to decide how to compute
42 the keygrip - it should not change due to compression.
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.
47 - Decide whether we should hide the mpi_point_t definition.
49 - Support more than just ECDSA.
63 /* Definition of a curve. */
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. */
77 mpi_point_t Q
; /* Q = [d]G */
88 /* This tables defines aliases for curve names. */
91 const char *name
; /* Our name. */
92 const char *other
; /* Other name. */
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. */
99 { "NIST P-224", "secp224r1" },
100 { "NIST P-224", "1.3.132.0.33" }, /* SECP OID. */
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" },
106 { "NIST P-384", "secp384r1" },
107 { "NIST P-384", "1.3.132.0.34" },
109 { "NIST P-521", "secp521r1" },
110 { "NIST P-521", "1.3.132.0.35" },
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"},
125 /* This static table defines all available curves. */
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. */
138 "NIST P-192", 192, 1,
139 "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
140 "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
141 "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
142 "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
144 "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
145 "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
148 "NIST P-224", 224, 1,
149 "0xffffffffffffffffffffffffffffffff000000000000000000000001",
150 "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
151 "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
152 "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
154 "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
155 "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
158 "NIST P-256", 256, 1,
159 "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
160 "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
161 "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
162 "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
164 "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
165 "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
168 "NIST P-384", 384, 1,
169 "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
170 "ffffffff0000000000000000ffffffff",
171 "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
172 "ffffffff0000000000000000fffffffc",
173 "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
174 "c656398d8a2ed19d2a85c8edd3ec2aef",
175 "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
176 "581a0db248b0a77aecec196accc52973",
178 "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
179 "5502f25dbf55296c3a545e3872760ab7",
180 "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
181 "0a60b1ce1d7e819d7a431d7c90ea0e5f"
184 "NIST P-521", 521, 1,
185 "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
186 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
187 "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
188 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
189 "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
190 "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
191 "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
192 "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
194 "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
195 "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
196 "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
197 "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
200 { "brainpoolP160r1", 160, 0,
201 "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
202 "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
203 "0x1e589a8595423412134faa2dbdec95c8d8675e58",
204 "0xe95e4a5f737059dc60df5991d45029409e60fc09",
205 "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
206 "0x1667cb477a1a8ec338f94741669c976316da6321"
209 { "brainpoolP192r1", 192, 0,
210 "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
211 "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
212 "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
213 "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
214 "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
215 "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
218 { "brainpoolP224r1", 224, 0,
219 "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
220 "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
221 "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
222 "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
223 "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
224 "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
227 { "brainpoolP256r1", 256, 0,
228 "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
229 "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
230 "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
231 "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
232 "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
233 "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
236 { "brainpoolP320r1", 320, 0,
237 "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
239 "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
241 "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981"
243 "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9"
245 "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
247 "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
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"
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"
281 { NULL
, 0, 0, NULL
, NULL
, NULL
, NULL
}
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
;
290 #define point_init(a) _gcry_mpi_ec_point_init ((a))
291 #define point_free(a) _gcry_mpi_ec_point_free ((a))
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
);
305 static gcry_mpi_t
gen_y_2 (gcry_mpi_t x
, elliptic_curve_t
* base
);
311 _gcry_register_pk_ecc_progress (void (*cb
) (void *, const char *,
316 progress_cb_data
= cb_data
;
320 /* progress (int c) */
322 /* if (progress_cb) */
323 /* progress_cb (progress_cb_data, "pk_ecc", c, 0, 0); */
329 /* Set the value from S into D. */
331 point_set (mpi_point_t
*d
, mpi_point_t
*s
)
333 mpi_set (d
->x
, s
->x
);
334 mpi_set (d
->y
, s
->y
);
335 mpi_set (d
->z
, s
->z
);
340 * Release a curve object.
343 curve_free (elliptic_curve_t
*E
)
345 mpi_free (E
->p
); E
->p
= NULL
;
346 mpi_free (E
->a
); E
->a
= NULL
;
347 mpi_free (E
->b
); E
->b
= NULL
;
349 mpi_free (E
->n
); E
->n
= NULL
;
354 * Return a copy of a curve object.
356 static elliptic_curve_t
357 curve_copy (elliptic_curve_t E
)
361 R
.p
= mpi_copy (E
.p
);
362 R
.a
= mpi_copy (E
.a
);
363 R
.b
= mpi_copy (E
.b
);
365 point_set (&R
.G
, &E
.G
);
366 R
.n
= mpi_copy (E
.n
);
373 /* Helper to scan a hex string. */
375 scanval (const char *string
)
380 err
= gcry_mpi_scan (&val
, GCRYMPI_FMT_HEX
, string
, 0, NULL
);
382 log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err
));
391 * Solve the right side of the equation that defines a curve.
394 gen_y_2 (gcry_mpi_t x
, elliptic_curve_t
*base
)
396 gcry_mpi_t three
, x_3
, axb
, y
;
398 three
= mpi_alloc_set_ui (3);
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
);
411 return y
; /* The quadratic value of the coordinate if it exist. */
418 /* Generate a random secret scalar k with an order of p
420 At the beginning this was identical to the code is in elgamal.c.
421 Later imporved by mmr. Further simplified by wk. */
423 gen_k (gcry_mpi_t p
, int security_level
)
428 nbits
= mpi_get_nbits (p
);
429 k
= mpi_snew (nbits
);
431 log_debug ("choosing a random k of %u bits\n", nbits
);
433 gcry_mpi_randomize (k
, nbits
, security_level
);
435 mpi_mod (k
, k
, p
); /* k = k mod p */
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.
445 static gpg_err_code_t
446 generate_curve (unsigned int nbits
, const char *name
,
447 elliptic_curve_t
*curve
, unsigned int *r_nbits
)
453 /* First check nor native curves. */
454 for (idx
= 0; domain_parms
[idx
].desc
; idx
++)
455 if (!strcmp (name
, domain_parms
[idx
].desc
))
457 /* If not found consult the alias table. */
458 if (!domain_parms
[idx
].desc
)
460 for (aliasno
= 0; curve_aliases
[aliasno
].name
; aliasno
++)
461 if (!strcmp (name
, curve_aliases
[aliasno
].other
))
463 if (curve_aliases
[aliasno
].name
)
465 for (idx
= 0; domain_parms
[idx
].desc
; idx
++)
466 if (!strcmp (curve_aliases
[aliasno
].name
,
467 domain_parms
[idx
].desc
))
474 for (idx
= 0; domain_parms
[idx
].desc
; idx
++)
475 if (nbits
== domain_parms
[idx
].nbits
)
478 if (!domain_parms
[idx
].desc
)
479 return GPG_ERR_INV_VALUE
;
481 /* In fips mode we only support NIST curves. Note that it is
482 possible to bypass this check by specifying the curve parameters
484 if (fips_mode () && !domain_parms
[idx
].fips
)
485 return GPG_ERR_NOT_SUPPORTED
;
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);
502 * First obtain the setup. Over the finite field randomize an scalar
503 * secret value, and calculate the public point.
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
)
516 err
= generate_curve (nbits
, name
, &E
, &nbits
);
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
);
532 log_debug ("choosing a random x of size %u\n", nbits
);
533 d
= gen_k (E
.n
, GCRY_VERY_STRONG_RANDOM
);
537 ctx
= _gcry_mpi_ec_init (E
.p
, E
.a
);
538 _gcry_mpi_ec_mul_point (&Q
, d
, &E
.G
, ctx
);
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
);
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
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");
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");
562 _gcry_mpi_ec_free (ctx
);
568 /* Now we can test our keys (this should never fail!). */
569 test_keys (sk
, nbits
- 64);
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.
582 test_keys (ECC_secret_key
*sk
, unsigned int nbits
)
585 gcry_mpi_t test
= mpi_new (nbits
);
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
);
593 log_debug ("Testing key.\n");
597 pk
.E
= curve_copy (sk
->E
);
599 point_set (&pk
.Q
, &sk
->Q
);
601 gcry_mpi_randomize (test
, nbits
, GCRY_WEAK_RANDOM
);
603 if (sign (test
, sk
, r
, s
) )
604 log_fatal ("ECDSA operation: sign failed\n");
606 if (verify (test
, &pk
, r
, s
))
608 log_fatal ("ECDSA operation: sign, verify failed\n");
612 log_debug ("ECDSA operation: sign, verify ok.\n");
626 * To check the validity of the value, recalculate the correspondence
627 * between the public value and the secret one.
630 check_secret_key (ECC_secret_key
* sk
)
633 gcry_mpi_t y_2
, y2
= mpi_alloc (0);
636 /* ?primarity test of '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
))
644 log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n");
648 if (!mpi_cmp_ui (sk
->E
.G
.z
, 0))
651 log_debug ("Bad check: 'G' cannot be Point at Infinity!\n");
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))
661 log_debug ("check_secret_key: E is not a curve of order n\n");
663 _gcry_mpi_ec_free (ctx
);
666 /* pubkey cannot be PaI */
667 if (!mpi_cmp_ui (sk
->Q
.z
, 0))
670 log_debug ("Bad check: Q can not be a Point at Infinity!\n");
671 _gcry_mpi_ec_free (ctx
);
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
))
680 ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
681 _gcry_mpi_ec_free (ctx
);
684 _gcry_mpi_ec_free (ctx
);
691 * Return the signature struct (r,s) from the message hash. The caller
692 * must have allocated R and S.
694 static gpg_err_code_t
695 sign (gcry_mpi_t input
, ECC_secret_key
*skey
, gcry_mpi_t r
, gcry_mpi_t s
)
697 gpg_err_code_t err
= 0;
698 gcry_mpi_t k
, dr
, sum
, k_1
, x
;
712 ctx
= _gcry_mpi_ec_init (skey
->E
.p
, skey
->E
.a
);
714 while (!mpi_cmp_ui (s
, 0)) /* s == 0 */
716 while (!mpi_cmp_ui (r
, 0)) /* r == 0 */
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. */
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
))
728 log_debug ("ecc sign: Failed to get affine coordinates\n");
729 err
= GPG_ERR_BAD_SIGNATURE
;
732 mpi_mod (r
, x
, skey
->E
.n
); /* r = x mod n */
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 */
741 _gcry_mpi_ec_free (ctx
);
753 * Check if R and S verifies INPUT.
755 static gpg_err_code_t
756 verify (gcry_mpi_t input
, ECC_public_key
*pkey
, gcry_mpi_t r
, gcry_mpi_t s
)
758 gpg_err_code_t err
= 0;
759 gcry_mpi_t h
, h1
, h2
, x
, y
;
760 mpi_point_t Q
, Q1
, Q2
;
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. */
777 ctx
= _gcry_mpi_ec_init (pkey
->E
.p
, pkey
->E
.a
);
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); */
804 if (!mpi_cmp_ui (Q
.z
, 0))
807 log_debug ("ecc verify: Rejected\n");
808 err
= GPG_ERR_BAD_SIGNATURE
;
811 if (_gcry_mpi_ec_get_affine (x
, y
, &Q
, ctx
))
814 log_debug ("ecc verify: Failed to get affine coordinates\n");
815 err
= GPG_ERR_BAD_SIGNATURE
;
818 mpi_mod (x
, x
, pkey
->E
.n
); /* x = x mod E_n */
819 if (mpi_cmp (x
, r
)) /* x != r */
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");
829 err
= GPG_ERR_BAD_SIGNATURE
;
833 log_debug ("ecc verify: Accepted\n");
836 _gcry_mpi_ec_free (ctx
);
850 /*********************************************
851 ************** interface ******************
852 *********************************************/
854 ec2os (gcry_mpi_t x
, gcry_mpi_t y
, gcry_mpi_t p
)
857 int pbytes
= (mpi_get_nbits (p
)+7)/8;
859 unsigned char *buf
, *ptr
;
862 buf
= gcry_xmalloc ( 1 + 2*pbytes
);
863 *buf
= 04; /* Uncompressed point. */
865 err
= gcry_mpi_print (GCRYMPI_FMT_USG
, ptr
, pbytes
, &n
, x
);
867 log_fatal ("mpi_print failed: %s\n", gpg_strerror (err
));
870 memmove (ptr
+(pbytes
-n
), ptr
, n
);
871 memset (ptr
, 0, (pbytes
-n
));
874 err
= gcry_mpi_print (GCRYMPI_FMT_USG
, ptr
, pbytes
, &n
, y
);
876 log_fatal ("mpi_print failed: %s\n", gpg_strerror (err
));
879 memmove (ptr
+(pbytes
-n
), ptr
, n
);
880 memset (ptr
, 0, (pbytes
-n
));
883 err
= gcry_mpi_scan (&result
, GCRYMPI_FMT_USG
, buf
, 1+2*pbytes
, NULL
);
885 log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err
));
894 /* RESULT must have been initialized and is set on success to the
895 point given by VALUE. */
897 os2ec (mpi_point_t
*result
, gcry_mpi_t value
)
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
);
915 return GPG_ERR_INV_OBJ
;
920 return GPG_ERR_NOT_IMPLEMENTED
; /* No support for point compression. */
925 return GPG_ERR_INV_OBJ
;
928 err
= gcry_mpi_scan (&x
, GCRYMPI_FMT_USG
, buf
+1, n
, NULL
);
934 err
= gcry_mpi_scan (&y
, GCRYMPI_FMT_USG
, buf
+1+n
, n
, NULL
);
942 mpi_set (result
->x
, x
);
943 mpi_set (result
->y
, y
);
944 mpi_set_ui (result
->z
, 1);
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
)
962 gcry_mpi_t g_x
, g_y
, q_x
, q_y
;
963 char *curve_name
= NULL
;
972 /* Parse the optional "curve" parameter. */
973 l1
= gcry_sexp_find_token (genparms
, "curve", 0);
976 curve_name
= _gcry_sexp_nth_string (l1
, 1);
977 gcry_sexp_release (l1
);
979 return GPG_ERR_INV_OBJ
; /* No curve name or value too large. */
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. */
991 ec
= generate_key (&sk
, nbits
, curve_name
, g_x
, g_y
, q_x
, q_y
);
992 gcry_free (curve_name
);
999 /* The function ec2os releases g_x and g_y. */
1000 skey
[3] = ec2os (g_x
, g_y
, sk
.E
.p
);
1002 /* The function ec2os releases g_x and g_y. */
1003 skey
[5] = ec2os (q_x
, q_y
, sk
.E
.p
);
1006 point_free (&sk
.E
.G
);
1009 /* Make an empty list of factors. */
1010 *retfactors
= gcry_calloc ( 1, sizeof **retfactors
);
1012 return gpg_err_code_from_syserror ();
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
)
1023 return ecc_generate_ext (algo
, nbits
, 0, NULL
, skey
, retfactors
, NULL
);
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
)
1035 gcry_mpi_t g_x
, g_y
;
1037 err
= generate_curve (0, name
, &E
, &nbits
);
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
);
1052 pkey
[3] = ec2os (g_x
, g_y
, E
.p
);
1060 static gcry_err_code_t
1061 ecc_check_secret_key (int algo
, gcry_mpi_t
*skey
)
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
;
1075 point_init (&sk
.E
.G
);
1076 err
= os2ec (&sk
.E
.G
, skey
[3]);
1079 point_free (&sk
.E
.G
);
1084 err
= os2ec (&sk
.Q
, skey
[5]);
1087 point_free (&sk
.E
.G
);
1094 if (check_secret_key (&sk
))
1096 point_free (&sk
.E
.G
);
1098 return GPG_ERR_BAD_SECKEY
;
1100 point_free (&sk
.E
.G
);
1106 static gcry_err_code_t
1107 ecc_sign (int algo
, gcry_mpi_t
*resarr
, gcry_mpi_t data
, gcry_mpi_t
*skey
)
1114 if (!data
|| !skey
[0] || !skey
[1] || !skey
[2] || !skey
[3] || !skey
[4]
1115 || !skey
[5] || !skey
[6] )
1116 return GPG_ERR_BAD_MPI
;
1121 point_init (&sk
.E
.G
);
1122 err
= os2ec (&sk
.E
.G
, skey
[3]);
1125 point_free (&sk
.E
.G
);
1130 err
= os2ec (&sk
.Q
, skey
[5]);
1133 point_free (&sk
.E
.G
);
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]);
1144 mpi_free (resarr
[0]);
1145 mpi_free (resarr
[1]);
1146 resarr
[0] = NULL
; /* Mark array as released. */
1148 point_free (&sk
.E
.G
);
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
)
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
;
1171 point_init (&pk
.E
.G
);
1172 err
= os2ec (&pk
.E
.G
, pkey
[3]);
1175 point_free (&pk
.E
.G
);
1180 err
= os2ec (&pk
.Q
, pkey
[5]);
1183 point_free (&pk
.E
.G
);
1188 err
= verify (hash
, &pk
, data
[0], data
[1]);
1190 point_free (&pk
.E
.G
);
1198 ecc_get_nbits (int algo
, gcry_mpi_t
*pkey
)
1202 return mpi_get_nbits (pkey
[0]);
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
)
1211 static const char names
[] = "pabgnq";
1212 gpg_err_code_t ec
= 0;
1214 gcry_mpi_t values
[6];
1217 /* Clear the values for easier error cleanup. */
1218 for (idx
=0; idx
< 6; idx
++)
1221 /* Fill values with all available parameters. */
1222 for (idx
=0; idx
< 6; idx
++)
1224 l1
= gcry_sexp_find_token (keyparam
, names
+idx
, 1);
1227 values
[idx
] = gcry_sexp_nth_mpi (l1
, 1, GCRYMPI_FMT_USG
);
1228 gcry_sexp_release (l1
);
1231 ec
= GPG_ERR_INV_OBJ
;
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);
1243 gcry_mpi_t tmpvalues
[6];
1245 for (idx
= 0; idx
< 6; idx
++)
1246 tmpvalues
[idx
] = NULL
;
1248 curve
= _gcry_sexp_nth_string (l1
, 1);
1251 ec
= GPG_ERR_INV_OBJ
; /* Name missing or out of core. */
1254 ec
= ecc_get_param (curve
, tmpvalues
);
1259 for (idx
= 0; idx
< 6; idx
++)
1262 values
[idx
] = tmpvalues
[idx
];
1264 mpi_free (tmpvalues
[idx
]);
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
++)
1274 ec
= GPG_ERR_NO_OBJ
;
1278 _gcry_mpi_normalize (values
[idx
]);
1280 /* Hash them all. */
1281 for (idx
= 0; idx
< 6; idx
++)
1284 unsigned char *rawmpi
;
1285 unsigned int rawmpilen
;
1287 rawmpi
= _gcry_mpi_get_buffer (values
[idx
], &rawmpilen
, NULL
);
1290 ec
= gpg_err_code_from_syserror ();
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);
1301 for (idx
= 0; idx
< 6; idx
++)
1302 _gcry_mpi_release (values
[idx
]);
1316 static gpg_err_code_t
1317 selftests_ecdsa (selftest_report_func_t report
)
1323 errtxt
= NULL
; /*selftest ();*/
1327 /* FIXME: need more tests. */
1329 return 0; /* Succeeded. */
1333 report ("pubkey", GCRY_PK_ECDSA
, what
, errtxt
);
1334 return GPG_ERR_SELFTEST_FAILED
;
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
)
1349 ec
= selftests_ecdsa (report
);
1352 ec
= GPG_ERR_PUBKEY_ALGO
;
1362 static const char *ecdsa_names
[] =
1369 gcry_pk_spec_t _gcry_pubkey_spec_ecdsa
=
1371 "ECDSA", ecdsa_names
,
1372 "pabgnq", "pabgnqd", "", "rs", "pabgnq",
1375 ecc_check_secret_key
,
1383 pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa
=