Line data Source code
1 : /* ecc.c - Elliptic Curve Cryptography
2 : * Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
3 : * Copyright (C) 2013, 2015 g10 Code GmbH
4 : *
5 : * This file is part of Libgcrypt.
6 : *
7 : * Libgcrypt is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU Lesser General Public License as
9 : * published by the Free Software Foundation; either version 2.1 of
10 : * the License, or (at your option) any later version.
11 : *
12 : * Libgcrypt is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU Lesser General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU Lesser General Public
18 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : /* 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 originally 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 : ECDH encrypt and decrypt code written by Andrey Jivsov.
39 : */
40 :
41 :
42 : /* TODO:
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 : */
48 :
49 :
50 : #include <config.h>
51 : #include <stdio.h>
52 : #include <stdlib.h>
53 : #include <string.h>
54 : #include <errno.h>
55 :
56 : #include "g10lib.h"
57 : #include "mpi.h"
58 : #include "cipher.h"
59 : #include "context.h"
60 : #include "ec-context.h"
61 : #include "pubkey-internal.h"
62 : #include "ecc-common.h"
63 :
64 :
65 : static const char *ecc_names[] =
66 : {
67 : "ecc",
68 : "ecdsa",
69 : "ecdh",
70 : "eddsa",
71 : "gost",
72 : NULL,
73 : };
74 :
75 :
76 : /* Sample NIST P-256 key from RFC 6979 A.2.5 */
77 : static const char sample_public_key_secp256[] =
78 : "(public-key"
79 : " (ecc"
80 : " (curve secp256r1)"
81 : " (q #04"
82 : /**/ "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"
83 : /**/ "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)))";
84 :
85 : static const char sample_secret_key_secp256[] =
86 : "(private-key"
87 : " (ecc"
88 : " (curve secp256r1)"
89 : " (d #C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721#)"
90 : " (q #04"
91 : /**/ "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"
92 : /**/ "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)))";
93 :
94 :
95 : /* Registered progress function and its callback value. */
96 : static void (*progress_cb) (void *, const char*, int, int, int);
97 : static void *progress_cb_data;
98 :
99 :
100 :
101 : /* Local prototypes. */
102 : static void test_keys (ECC_secret_key * sk, unsigned int nbits);
103 : static void test_ecdh_only_keys (ECC_secret_key * sk, unsigned int nbits, int flags);
104 : static unsigned int ecc_get_nbits (gcry_sexp_t parms);
105 :
106 :
107 :
108 :
109 : void
110 0 : _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
111 : int, int, int),
112 : void *cb_data)
113 : {
114 0 : progress_cb = cb;
115 0 : progress_cb_data = cb_data;
116 0 : }
117 :
118 : /* static void */
119 : /* progress (int c) */
120 : /* { */
121 : /* if (progress_cb) */
122 : /* progress_cb (progress_cb_data, "pk_ecc", c, 0, 0); */
123 : /* } */
124 :
125 :
126 :
127 : /**
128 : * nist_generate_key - Standard version of the ECC key generation.
129 : * @sk: A struct to receive the secret key.
130 : * @E: Parameters of the curve.
131 : * @ctx: Elliptic curve computation context.
132 : * @flags: Flags controlling aspects of the creation.
133 : * @nbits: Only for testing
134 : * @r_x: On success this receives an allocated MPI with the affine
135 : * x-coordinate of the poblic key. On error NULL is stored.
136 : * @r_y: Ditto for the y-coordinate.
137 : *
138 : * Return: An error code.
139 : *
140 : * The @flags bits used by this function are %PUBKEY_FLAG_TRANSIENT to
141 : * use a faster RNG, and %PUBKEY_FLAG_NO_KEYTEST to skip the assertion
142 : * that the key works as expected.
143 : *
144 : * FIXME: Check whether N is needed.
145 : */
146 : static gpg_err_code_t
147 16 : nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
148 : int flags, unsigned int nbits,
149 : gcry_mpi_t *r_x, gcry_mpi_t *r_y)
150 : {
151 : mpi_point_struct Q;
152 : gcry_random_level_t random_level;
153 : gcry_mpi_t x, y;
154 16 : const unsigned int pbits = mpi_get_nbits (E->p);
155 :
156 16 : point_init (&Q);
157 :
158 16 : if ((flags & PUBKEY_FLAG_TRANSIENT_KEY))
159 2 : random_level = GCRY_STRONG_RANDOM;
160 : else
161 14 : random_level = GCRY_VERY_STRONG_RANDOM;
162 :
163 : /* Generate a secret. */
164 16 : if (ctx->dialect == ECC_DIALECT_ED25519 || (flags & PUBKEY_FLAG_DJB_TWEAK))
165 4 : {
166 : char *rndbuf;
167 :
168 4 : sk->d = mpi_snew (256);
169 4 : rndbuf = _gcry_random_bytes_secure (32, random_level);
170 4 : rndbuf[0] &= 0x7f; /* Clear bit 255. */
171 4 : rndbuf[0] |= 0x40; /* Set bit 254. */
172 4 : rndbuf[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0 */
173 4 : _gcry_mpi_set_buffer (sk->d, rndbuf, 32, 0);
174 4 : xfree (rndbuf);
175 : }
176 : else
177 12 : sk->d = _gcry_dsa_gen_k (E->n, random_level);
178 :
179 :
180 : /* Compute Q. */
181 16 : _gcry_mpi_ec_mul_point (&Q, sk->d, &E->G, ctx);
182 :
183 : /* Copy the stuff to the key structures. */
184 16 : sk->E.model = E->model;
185 16 : sk->E.dialect = E->dialect;
186 16 : sk->E.p = mpi_copy (E->p);
187 16 : sk->E.a = mpi_copy (E->a);
188 16 : sk->E.b = mpi_copy (E->b);
189 16 : point_init (&sk->E.G);
190 16 : point_set (&sk->E.G, &E->G);
191 16 : sk->E.n = mpi_copy (E->n);
192 16 : sk->E.h = mpi_copy (E->h);
193 16 : point_init (&sk->Q);
194 :
195 16 : x = mpi_new (pbits);
196 16 : if (r_y == NULL)
197 0 : y = NULL;
198 : else
199 16 : y = mpi_new (pbits);
200 16 : if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx))
201 0 : log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
202 :
203 : /* We want the Q=(x,y) be a "compliant key" in terms of the
204 : * http://tools.ietf.org/html/draft-jivsov-ecc-compact, which simply
205 : * means that we choose either Q=(x,y) or -Q=(x,p-y) such that we
206 : * end up with the min(y,p-y) as the y coordinate. Such a public
207 : * key allows the most efficient compression: y can simply be
208 : * dropped because we know that it's a minimum of the two
209 : * possibilities without any loss of security. Note that we don't
210 : * do that for Ed25519 so that we do not violate the special
211 : * construction of the secret key. */
212 16 : if (r_y == NULL || E->dialect == ECC_DIALECT_ED25519)
213 4 : point_set (&sk->Q, &Q);
214 : else
215 : {
216 : gcry_mpi_t negative;
217 :
218 12 : negative = mpi_new (pbits);
219 :
220 12 : if (E->model == MPI_EC_WEIERSTRASS)
221 12 : mpi_sub (negative, E->p, y); /* negative = p - y */
222 : else
223 0 : mpi_sub (negative, E->p, x); /* negative = p - x */
224 :
225 12 : if (mpi_cmp (negative, y) < 0) /* p - y < p */
226 : {
227 : /* We need to end up with -Q; this assures that new Q's y is
228 : the smallest one */
229 6 : if (E->model == MPI_EC_WEIERSTRASS)
230 : {
231 6 : mpi_free (y);
232 6 : y = negative;
233 : }
234 : else
235 : {
236 0 : mpi_free (x);
237 0 : x = negative;
238 : }
239 6 : mpi_sub (sk->d, E->n, sk->d); /* d = order - d */
240 6 : mpi_point_set (&sk->Q, x, y, mpi_const (MPI_C_ONE));
241 :
242 6 : if (DBG_CIPHER)
243 0 : log_debug ("ecgen converted Q to a compliant point\n");
244 : }
245 : else /* p - y >= p */
246 : {
247 : /* No change is needed exactly 50% of the time: just copy. */
248 6 : mpi_free (negative);
249 6 : point_set (&sk->Q, &Q);
250 6 : if (DBG_CIPHER)
251 0 : log_debug ("ecgen didn't need to convert Q to a compliant point\n");
252 : }
253 : }
254 :
255 16 : *r_x = x;
256 16 : if (r_y)
257 16 : *r_y = y;
258 :
259 16 : point_free (&Q);
260 : /* Now we can test our keys (this should never fail!). */
261 16 : if ((flags & PUBKEY_FLAG_NO_KEYTEST))
262 : ; /* User requested to skip the test. */
263 15 : else if (sk->E.model != MPI_EC_MONTGOMERY)
264 15 : test_keys (sk, nbits - 64);
265 : else
266 0 : test_ecdh_only_keys (sk, nbits - 64, flags);
267 :
268 16 : return 0;
269 : }
270 :
271 :
272 : /*
273 : * To verify correct skey it use a random information.
274 : * First, encrypt and decrypt this dummy value,
275 : * test if the information is recuperated.
276 : * Second, test with the sign and verify functions.
277 : */
278 : static void
279 15 : test_keys (ECC_secret_key *sk, unsigned int nbits)
280 : {
281 : ECC_public_key pk;
282 15 : gcry_mpi_t test = mpi_new (nbits);
283 : mpi_point_struct R_;
284 15 : gcry_mpi_t c = mpi_new (nbits);
285 15 : gcry_mpi_t out = mpi_new (nbits);
286 15 : gcry_mpi_t r = mpi_new (nbits);
287 15 : gcry_mpi_t s = mpi_new (nbits);
288 :
289 15 : if (DBG_CIPHER)
290 0 : log_debug ("Testing key.\n");
291 :
292 15 : point_init (&R_);
293 :
294 15 : pk.E = _gcry_ecc_curve_copy (sk->E);
295 15 : point_init (&pk.Q);
296 15 : point_set (&pk.Q, &sk->Q);
297 :
298 15 : _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
299 :
300 15 : if (_gcry_ecc_ecdsa_sign (test, sk, r, s, 0, 0) )
301 0 : log_fatal ("ECDSA operation: sign failed\n");
302 :
303 15 : if (_gcry_ecc_ecdsa_verify (test, &pk, r, s))
304 : {
305 0 : log_fatal ("ECDSA operation: sign, verify failed\n");
306 : }
307 :
308 15 : if (DBG_CIPHER)
309 0 : log_debug ("ECDSA operation: sign, verify ok.\n");
310 :
311 15 : point_free (&pk.Q);
312 15 : _gcry_ecc_curve_free (&pk.E);
313 :
314 15 : point_free (&R_);
315 15 : mpi_free (s);
316 15 : mpi_free (r);
317 15 : mpi_free (out);
318 15 : mpi_free (c);
319 15 : mpi_free (test);
320 15 : }
321 :
322 :
323 : static void
324 0 : test_ecdh_only_keys (ECC_secret_key *sk, unsigned int nbits, int flags)
325 : {
326 : ECC_public_key pk;
327 : gcry_mpi_t test;
328 : mpi_point_struct R_;
329 : gcry_mpi_t x0, x1;
330 : mpi_ec_t ec;
331 :
332 0 : if (DBG_CIPHER)
333 0 : log_debug ("Testing ECDH only key.\n");
334 :
335 0 : point_init (&R_);
336 :
337 0 : pk.E = _gcry_ecc_curve_copy (sk->E);
338 0 : point_init (&pk.Q);
339 0 : point_set (&pk.Q, &sk->Q);
340 :
341 0 : if ((flags & PUBKEY_FLAG_DJB_TWEAK))
342 : {
343 : char *rndbuf;
344 :
345 0 : test = mpi_new (256);
346 0 : rndbuf = _gcry_random_bytes (32, GCRY_WEAK_RANDOM);
347 0 : rndbuf[0] &= 0x7f; /* Clear bit 255. */
348 0 : rndbuf[0] |= 0x40; /* Set bit 254. */
349 0 : rndbuf[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0 */
350 0 : _gcry_mpi_set_buffer (test, rndbuf, 32, 0);
351 0 : xfree (rndbuf);
352 : }
353 : else
354 : {
355 0 : test = mpi_new (nbits);
356 0 : _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
357 : }
358 :
359 0 : ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, flags,
360 : pk.E.p, pk.E.a, pk.E.b);
361 0 : x0 = mpi_new (0);
362 0 : x1 = mpi_new (0);
363 :
364 : /* R_ = hkQ <=> R_ = hkdG */
365 0 : _gcry_mpi_ec_mul_point (&R_, test, &pk.Q, ec);
366 0 : if (!(flags & PUBKEY_FLAG_DJB_TWEAK))
367 0 : _gcry_mpi_ec_mul_point (&R_, ec->h, &R_, ec);
368 0 : if (_gcry_mpi_ec_get_affine (x0, NULL, &R_, ec))
369 0 : log_fatal ("ecdh: Failed to get affine coordinates for hkQ\n");
370 :
371 0 : _gcry_mpi_ec_mul_point (&R_, test, &pk.E.G, ec);
372 0 : _gcry_mpi_ec_mul_point (&R_, sk->d, &R_, ec);
373 : /* R_ = hdkG */
374 0 : if (!(flags & PUBKEY_FLAG_DJB_TWEAK))
375 0 : _gcry_mpi_ec_mul_point (&R_, ec->h, &R_, ec);
376 :
377 0 : if (_gcry_mpi_ec_get_affine (x1, NULL, &R_, ec))
378 0 : log_fatal ("ecdh: Failed to get affine coordinates for hdkG\n");
379 :
380 0 : if (mpi_cmp (x0, x1))
381 : {
382 0 : log_fatal ("ECDH test failed.\n");
383 : }
384 :
385 0 : mpi_free (x0);
386 0 : mpi_free (x1);
387 0 : _gcry_mpi_ec_free (ec);
388 :
389 0 : point_free (&pk.Q);
390 0 : _gcry_ecc_curve_free (&pk.E);
391 :
392 0 : point_free (&R_);
393 0 : mpi_free (test);
394 0 : }
395 :
396 :
397 : /*
398 : * To check the validity of the value, recalculate the correspondence
399 : * between the public value and the secret one.
400 : */
401 : static int
402 20 : check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
403 : {
404 20 : int rc = 1;
405 : mpi_point_struct Q;
406 : gcry_mpi_t x1, y1;
407 20 : gcry_mpi_t x2 = NULL;
408 20 : gcry_mpi_t y2 = NULL;
409 :
410 20 : point_init (&Q);
411 20 : x1 = mpi_new (0);
412 20 : if (ec->model == MPI_EC_MONTGOMERY)
413 0 : y1 = NULL;
414 : else
415 20 : y1 = mpi_new (0);
416 :
417 : /* G in E(F_p) */
418 20 : if (!_gcry_mpi_ec_curve_point (&sk->E.G, ec))
419 : {
420 0 : if (DBG_CIPHER)
421 0 : log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n");
422 0 : goto leave;
423 : }
424 :
425 : /* G != PaI */
426 20 : if (!mpi_cmp_ui (sk->E.G.z, 0))
427 : {
428 0 : if (DBG_CIPHER)
429 0 : log_debug ("Bad check: 'G' cannot be Point at Infinity!\n");
430 0 : goto leave;
431 : }
432 :
433 : /* Check order of curve. */
434 20 : if (sk->E.dialect != ECC_DIALECT_ED25519 && !(flags & PUBKEY_FLAG_DJB_TWEAK))
435 : {
436 12 : _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ec);
437 12 : if (mpi_cmp_ui (Q.z, 0))
438 : {
439 0 : if (DBG_CIPHER)
440 0 : log_debug ("check_secret_key: E is not a curve of order n\n");
441 0 : goto leave;
442 : }
443 : }
444 :
445 : /* Pubkey cannot be PaI */
446 20 : if (!mpi_cmp_ui (sk->Q.z, 0))
447 : {
448 0 : if (DBG_CIPHER)
449 0 : log_debug ("Bad check: Q can not be a Point at Infinity!\n");
450 0 : goto leave;
451 : }
452 :
453 : /* pubkey = [d]G over E */
454 20 : if (!_gcry_ecc_compute_public (&Q, ec, &sk->E.G, sk->d))
455 : {
456 0 : if (DBG_CIPHER)
457 0 : log_debug ("Bad check: computation of dG failed\n");
458 0 : goto leave;
459 : }
460 20 : if (_gcry_mpi_ec_get_affine (x1, y1, &Q, ec))
461 : {
462 0 : if (DBG_CIPHER)
463 0 : log_debug ("Bad check: Q can not be a Point at Infinity!\n");
464 0 : goto leave;
465 : }
466 :
467 20 : if ((flags & PUBKEY_FLAG_EDDSA))
468 : ; /* Fixme: EdDSA is special. */
469 18 : else if (!mpi_cmp_ui (sk->Q.z, 1))
470 : {
471 : /* Fast path if Q is already in affine coordinates. */
472 18 : if (mpi_cmp (x1, sk->Q.x) || (y1 && mpi_cmp (y1, sk->Q.y)))
473 : {
474 0 : if (DBG_CIPHER)
475 0 : log_debug
476 : ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
477 0 : goto leave;
478 : }
479 : }
480 : else
481 : {
482 0 : x2 = mpi_new (0);
483 0 : y2 = mpi_new (0);
484 0 : if (_gcry_mpi_ec_get_affine (x2, y2, &sk->Q, ec))
485 : {
486 0 : if (DBG_CIPHER)
487 0 : log_debug ("Bad check: Q can not be a Point at Infinity!\n");
488 0 : goto leave;
489 : }
490 :
491 0 : if (mpi_cmp (x1, x2) || mpi_cmp (y1, y2))
492 : {
493 0 : if (DBG_CIPHER)
494 0 : log_debug
495 : ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
496 0 : goto leave;
497 : }
498 : }
499 20 : rc = 0; /* Okay. */
500 :
501 : leave:
502 20 : mpi_free (x2);
503 20 : mpi_free (x1);
504 20 : mpi_free (y1);
505 20 : mpi_free (y2);
506 20 : point_free (&Q);
507 20 : return rc;
508 : }
509 :
510 :
511 :
512 : /*********************************************
513 : ************** interface ******************
514 : *********************************************/
515 :
516 : static gcry_err_code_t
517 18 : ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
518 : {
519 : gpg_err_code_t rc;
520 : unsigned int nbits;
521 : elliptic_curve_t E;
522 : ECC_secret_key sk;
523 18 : gcry_mpi_t Gx = NULL;
524 18 : gcry_mpi_t Gy = NULL;
525 18 : gcry_mpi_t Qx = NULL;
526 18 : gcry_mpi_t Qy = NULL;
527 18 : char *curve_name = NULL;
528 : gcry_sexp_t l1;
529 18 : mpi_ec_t ctx = NULL;
530 18 : gcry_sexp_t curve_info = NULL;
531 18 : gcry_sexp_t curve_flags = NULL;
532 18 : gcry_mpi_t base = NULL;
533 18 : gcry_mpi_t public = NULL;
534 18 : gcry_mpi_t secret = NULL;
535 18 : int flags = 0;
536 :
537 18 : memset (&E, 0, sizeof E);
538 18 : memset (&sk, 0, sizeof sk);
539 :
540 18 : rc = _gcry_pk_util_get_nbits (genparms, &nbits);
541 18 : if (rc)
542 0 : return rc;
543 :
544 : /* Parse the optional "curve" parameter. */
545 18 : l1 = sexp_find_token (genparms, "curve", 0);
546 18 : if (l1)
547 : {
548 13 : curve_name = _gcry_sexp_nth_string (l1, 1);
549 13 : sexp_release (l1);
550 13 : if (!curve_name)
551 0 : return GPG_ERR_INV_OBJ; /* No curve name or value too large. */
552 : }
553 :
554 : /* Parse the optional flags list. */
555 18 : l1 = sexp_find_token (genparms, "flags", 0);
556 18 : if (l1)
557 : {
558 9 : rc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
559 9 : sexp_release (l1);
560 9 : if (rc)
561 0 : goto leave;
562 : }
563 :
564 : /* Parse the deprecated optional transient-key flag. */
565 18 : l1 = sexp_find_token (genparms, "transient-key", 0);
566 18 : if (l1)
567 : {
568 0 : flags |= PUBKEY_FLAG_TRANSIENT_KEY;
569 0 : sexp_release (l1);
570 : }
571 :
572 : /* NBITS is required if no curve name has been given. */
573 18 : if (!nbits && !curve_name)
574 0 : return GPG_ERR_NO_OBJ; /* No NBITS parameter. */
575 :
576 18 : rc = _gcry_ecc_fill_in_curve (nbits, curve_name, &E, &nbits);
577 18 : if (rc)
578 0 : goto leave;
579 :
580 18 : if (DBG_CIPHER)
581 : {
582 0 : log_debug ("ecgen curve info: %s/%s\n",
583 : _gcry_ecc_model2str (E.model),
584 : _gcry_ecc_dialect2str (E.dialect));
585 0 : if (E.name)
586 0 : log_debug ("ecgen curve used: %s\n", E.name);
587 0 : log_printmpi ("ecgen curve p", E.p);
588 0 : log_printmpi ("ecgen curve a", E.a);
589 0 : log_printmpi ("ecgen curve b", E.b);
590 0 : log_printmpi ("ecgen curve n", E.n);
591 0 : log_printmpi ("ecgen curve h", E.h);
592 0 : log_printpnt ("ecgen curve G", &E.G, NULL);
593 : }
594 :
595 18 : ctx = _gcry_mpi_ec_p_internal_new (E.model, E.dialect, flags, E.p, E.a, E.b);
596 :
597 18 : if (E.model == MPI_EC_MONTGOMERY)
598 0 : rc = nist_generate_key (&sk, &E, ctx, flags, nbits, &Qx, NULL);
599 18 : else if ((flags & PUBKEY_FLAG_EDDSA))
600 2 : rc = _gcry_ecc_eddsa_genkey (&sk, &E, ctx, flags);
601 : else
602 16 : rc = nist_generate_key (&sk, &E, ctx, flags, nbits, &Qx, &Qy);
603 18 : if (rc)
604 0 : goto leave;
605 :
606 : /* Copy data to the result. */
607 18 : Gx = mpi_new (0);
608 18 : Gy = mpi_new (0);
609 18 : if (E.model != MPI_EC_MONTGOMERY)
610 : {
611 18 : if (_gcry_mpi_ec_get_affine (Gx, Gy, &sk.E.G, ctx))
612 0 : log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "G");
613 18 : base = _gcry_ecc_ec2os (Gx, Gy, sk.E.p);
614 : }
615 18 : if ((sk.E.dialect == ECC_DIALECT_ED25519 || E.model == MPI_EC_MONTGOMERY)
616 6 : && !(flags & PUBKEY_FLAG_NOCOMP))
617 5 : {
618 : unsigned char *encpk;
619 : unsigned int encpklen;
620 :
621 5 : if (E.model != MPI_EC_MONTGOMERY)
622 : /* (Gx and Gy are used as scratch variables) */
623 5 : rc = _gcry_ecc_eddsa_encodepoint (&sk.Q, ctx, Gx, Gy,
624 5 : !!(flags & PUBKEY_FLAG_COMP),
625 : &encpk, &encpklen);
626 : else
627 : {
628 0 : encpk = _gcry_mpi_get_buffer_extra (Qx, nbits/8,
629 : -1, &encpklen, NULL);
630 0 : if (encpk == NULL)
631 0 : rc = gpg_err_code_from_syserror ();
632 : else
633 : {
634 0 : encpk[0] = 0x40;
635 0 : encpklen++;
636 : }
637 : }
638 5 : if (rc)
639 0 : goto leave;
640 5 : public = mpi_new (0);
641 5 : mpi_set_opaque (public, encpk, encpklen*8);
642 : }
643 : else
644 : {
645 13 : if (!Qx)
646 : {
647 : /* This is the case for a key from _gcry_ecc_eddsa_generate
648 : with no compression. */
649 0 : Qx = mpi_new (0);
650 0 : Qy = mpi_new (0);
651 0 : if (_gcry_mpi_ec_get_affine (Qx, Qy, &sk.Q, ctx))
652 0 : log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
653 : }
654 13 : public = _gcry_ecc_ec2os (Qx, Qy, sk.E.p);
655 : }
656 18 : secret = sk.d; sk.d = NULL;
657 18 : if (E.name)
658 : {
659 18 : rc = sexp_build (&curve_info, NULL, "(curve %s)", E.name);
660 18 : if (rc)
661 0 : goto leave;
662 : }
663 :
664 18 : if ((flags & PUBKEY_FLAG_PARAM) || (flags & PUBKEY_FLAG_EDDSA)
665 13 : || (flags & PUBKEY_FLAG_DJB_TWEAK))
666 : {
667 9 : rc = sexp_build
668 : (&curve_flags, NULL,
669 9 : ((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_EDDSA))?
670 : "(flags param eddsa)" :
671 : ((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_EDDSA))?
672 : "(flags param djb-tweak)" :
673 4 : ((flags & PUBKEY_FLAG_PARAM))?
674 5 : "(flags param)" : ((flags & PUBKEY_FLAG_EDDSA))?
675 1 : "(flags eddsa)" : "(flags djb-tweak)" );
676 5 : if (rc)
677 0 : goto leave;
678 : }
679 :
680 18 : if ((flags & PUBKEY_FLAG_PARAM) && E.name)
681 4 : rc = sexp_build (r_skey, NULL,
682 : "(key-data"
683 : " (public-key"
684 : " (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(q%m)))"
685 : " (private-key"
686 : " (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(q%m)(d%m)))"
687 : " )",
688 : curve_info, curve_flags,
689 : sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, sk.E.h, public,
690 : curve_info, curve_flags,
691 : sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, sk.E.h, public,
692 : secret);
693 : else
694 14 : rc = sexp_build (r_skey, NULL,
695 : "(key-data"
696 : " (public-key"
697 : " (ecc%S%S(q%m)))"
698 : " (private-key"
699 : " (ecc%S%S(q%m)(d%m)))"
700 : " )",
701 : curve_info, curve_flags,
702 : public,
703 : curve_info, curve_flags,
704 : public, secret);
705 18 : if (rc)
706 0 : goto leave;
707 :
708 18 : if (DBG_CIPHER)
709 : {
710 0 : log_printmpi ("ecgen result p", sk.E.p);
711 0 : log_printmpi ("ecgen result a", sk.E.a);
712 0 : log_printmpi ("ecgen result b", sk.E.b);
713 0 : log_printmpi ("ecgen result G", base);
714 0 : log_printmpi ("ecgen result n", sk.E.n);
715 0 : log_printmpi ("ecgen result h", sk.E.h);
716 0 : log_printmpi ("ecgen result Q", public);
717 0 : log_printmpi ("ecgen result d", secret);
718 0 : if ((flags & PUBKEY_FLAG_EDDSA))
719 0 : log_debug ("ecgen result using Ed25519+EdDSA\n");
720 : }
721 :
722 : leave:
723 18 : mpi_free (secret);
724 18 : mpi_free (public);
725 18 : mpi_free (base);
726 : {
727 18 : _gcry_ecc_curve_free (&sk.E);
728 18 : point_free (&sk.Q);
729 18 : mpi_free (sk.d);
730 : }
731 18 : _gcry_ecc_curve_free (&E);
732 18 : mpi_free (Gx);
733 18 : mpi_free (Gy);
734 18 : mpi_free (Qx);
735 18 : mpi_free (Qy);
736 18 : _gcry_mpi_ec_free (ctx);
737 18 : xfree (curve_name);
738 18 : sexp_release (curve_flags);
739 18 : sexp_release (curve_info);
740 18 : return rc;
741 : }
742 :
743 :
744 : static gcry_err_code_t
745 20 : ecc_check_secret_key (gcry_sexp_t keyparms)
746 : {
747 : gcry_err_code_t rc;
748 20 : gcry_sexp_t l1 = NULL;
749 20 : int flags = 0;
750 20 : char *curvename = NULL;
751 20 : gcry_mpi_t mpi_g = NULL;
752 20 : gcry_mpi_t mpi_q = NULL;
753 : ECC_secret_key sk;
754 20 : mpi_ec_t ec = NULL;
755 :
756 20 : memset (&sk, 0, sizeof sk);
757 :
758 : /* Look for flags. */
759 20 : l1 = sexp_find_token (keyparms, "flags", 0);
760 20 : if (l1)
761 : {
762 8 : rc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
763 8 : if (rc)
764 0 : goto leave;
765 : }
766 :
767 : /* Extract the parameters. */
768 20 : if ((flags & PUBKEY_FLAG_PARAM))
769 8 : rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?h?/q?+d",
770 : &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
771 : &sk.E.h, &mpi_q, &sk.d, NULL);
772 : else
773 12 : rc = sexp_extract_param (keyparms, NULL, "/q?+d",
774 : &mpi_q, &sk.d, NULL);
775 20 : if (rc)
776 0 : goto leave;
777 :
778 : /* Add missing parameters using the optional curve parameter. */
779 20 : sexp_release (l1);
780 20 : l1 = sexp_find_token (keyparms, "curve", 5);
781 20 : if (l1)
782 : {
783 20 : curvename = sexp_nth_string (l1, 1);
784 20 : if (curvename)
785 : {
786 20 : rc = _gcry_ecc_fill_in_curve (0, curvename, &sk.E, NULL);
787 20 : if (rc)
788 0 : goto leave;
789 : }
790 : }
791 20 : if (mpi_g)
792 : {
793 8 : if (!sk.E.G.x)
794 0 : point_init (&sk.E.G);
795 8 : rc = _gcry_ecc_os2ec (&sk.E.G, mpi_g);
796 8 : if (rc)
797 0 : goto leave;
798 : }
799 :
800 : /* Guess required fields if a curve parameter has not been given.
801 : FIXME: This is a crude hacks. We need to fix that. */
802 20 : if (!curvename)
803 : {
804 0 : sk.E.model = ((flags & PUBKEY_FLAG_EDDSA)
805 : ? MPI_EC_EDWARDS
806 0 : : MPI_EC_WEIERSTRASS);
807 0 : sk.E.dialect = ((flags & PUBKEY_FLAG_EDDSA)
808 : ? ECC_DIALECT_ED25519
809 0 : : ECC_DIALECT_STANDARD);
810 0 : if (!sk.E.h)
811 0 : sk.E.h = mpi_const (MPI_C_ONE);
812 : }
813 20 : if (DBG_CIPHER)
814 : {
815 0 : log_debug ("ecc_testkey inf: %s/%s\n",
816 : _gcry_ecc_model2str (sk.E.model),
817 : _gcry_ecc_dialect2str (sk.E.dialect));
818 0 : if (sk.E.name)
819 0 : log_debug ("ecc_testkey nam: %s\n", sk.E.name);
820 0 : log_printmpi ("ecc_testkey p", sk.E.p);
821 0 : log_printmpi ("ecc_testkey a", sk.E.a);
822 0 : log_printmpi ("ecc_testkey b", sk.E.b);
823 0 : log_printpnt ("ecc_testkey g", &sk.E.G, NULL);
824 0 : log_printmpi ("ecc_testkey n", sk.E.n);
825 0 : log_printmpi ("ecc_testkey h", sk.E.h);
826 0 : log_printmpi ("ecc_testkey q", mpi_q);
827 0 : if (!fips_mode ())
828 0 : log_printmpi ("ecc_testkey d", sk.d);
829 : }
830 20 : if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.E.h || !sk.d)
831 : {
832 0 : rc = GPG_ERR_NO_OBJ;
833 0 : goto leave;
834 : }
835 :
836 20 : ec = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect, flags,
837 : sk.E.p, sk.E.a, sk.E.b);
838 :
839 20 : if (mpi_q)
840 : {
841 20 : point_init (&sk.Q);
842 20 : if (ec->dialect == ECC_DIALECT_ED25519)
843 8 : rc = _gcry_ecc_eddsa_decodepoint (mpi_q, ec, &sk.Q, NULL, NULL);
844 12 : else if (ec->model == MPI_EC_MONTGOMERY)
845 0 : rc = _gcry_ecc_mont_decodepoint (mpi_q, ec, &sk.Q);
846 : else
847 12 : rc = _gcry_ecc_os2ec (&sk.Q, mpi_q);
848 20 : if (rc)
849 0 : goto leave;
850 : }
851 : else
852 : {
853 : /* The secret key test requires Q. */
854 0 : rc = GPG_ERR_NO_OBJ;
855 0 : goto leave;
856 : }
857 :
858 20 : if (check_secret_key (&sk, ec, flags))
859 0 : rc = GPG_ERR_BAD_SECKEY;
860 :
861 : leave:
862 20 : _gcry_mpi_ec_free (ec);
863 20 : _gcry_mpi_release (sk.E.p);
864 20 : _gcry_mpi_release (sk.E.a);
865 20 : _gcry_mpi_release (sk.E.b);
866 20 : _gcry_mpi_release (mpi_g);
867 20 : point_free (&sk.E.G);
868 20 : _gcry_mpi_release (sk.E.n);
869 20 : _gcry_mpi_release (sk.E.h);
870 20 : _gcry_mpi_release (mpi_q);
871 20 : point_free (&sk.Q);
872 20 : _gcry_mpi_release (sk.d);
873 20 : xfree (curvename);
874 20 : sexp_release (l1);
875 20 : if (DBG_CIPHER)
876 0 : log_debug ("ecc_testkey => %s\n", gpg_strerror (rc));
877 20 : return rc;
878 : }
879 :
880 :
881 : static gcry_err_code_t
882 1190 : ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
883 : {
884 : gcry_err_code_t rc;
885 : struct pk_encoding_ctx ctx;
886 1190 : gcry_mpi_t data = NULL;
887 1190 : gcry_sexp_t l1 = NULL;
888 1190 : char *curvename = NULL;
889 1190 : gcry_mpi_t mpi_g = NULL;
890 1190 : gcry_mpi_t mpi_q = NULL;
891 : ECC_secret_key sk;
892 1190 : gcry_mpi_t sig_r = NULL;
893 1190 : gcry_mpi_t sig_s = NULL;
894 :
895 1190 : memset (&sk, 0, sizeof sk);
896 :
897 1190 : _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN, 0);
898 :
899 : /* Extract the data. */
900 1190 : rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
901 1190 : if (rc)
902 0 : goto leave;
903 1190 : if (DBG_CIPHER)
904 0 : log_mpidump ("ecc_sign data", data);
905 :
906 : /*
907 : * Extract the key.
908 : */
909 1190 : if ((ctx.flags & PUBKEY_FLAG_PARAM))
910 0 : rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?h?/q?+d",
911 : &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
912 : &sk.E.h, &mpi_q, &sk.d, NULL);
913 : else
914 1190 : rc = sexp_extract_param (keyparms, NULL, "/q?+d",
915 : &mpi_q, &sk.d, NULL);
916 1190 : if (rc)
917 0 : goto leave;
918 1190 : if (mpi_g)
919 : {
920 0 : point_init (&sk.E.G);
921 0 : rc = _gcry_ecc_os2ec (&sk.E.G, mpi_g);
922 0 : if (rc)
923 0 : goto leave;
924 : }
925 : /* Add missing parameters using the optional curve parameter. */
926 1190 : l1 = sexp_find_token (keyparms, "curve", 5);
927 1190 : if (l1)
928 : {
929 1190 : curvename = sexp_nth_string (l1, 1);
930 1190 : if (curvename)
931 : {
932 1190 : rc = _gcry_ecc_fill_in_curve (0, curvename, &sk.E, NULL);
933 1190 : if (rc)
934 0 : goto leave;
935 : }
936 : }
937 : /* Guess required fields if a curve parameter has not been given.
938 : FIXME: This is a crude hacks. We need to fix that. */
939 1190 : if (!curvename)
940 : {
941 0 : sk.E.model = ((ctx.flags & PUBKEY_FLAG_EDDSA)
942 : ? MPI_EC_EDWARDS
943 0 : : MPI_EC_WEIERSTRASS);
944 0 : sk.E.dialect = ((ctx.flags & PUBKEY_FLAG_EDDSA)
945 : ? ECC_DIALECT_ED25519
946 0 : : ECC_DIALECT_STANDARD);
947 0 : if (!sk.E.h)
948 0 : sk.E.h = mpi_const (MPI_C_ONE);
949 : }
950 1190 : if (DBG_CIPHER)
951 : {
952 0 : log_debug ("ecc_sign info: %s/%s%s\n",
953 : _gcry_ecc_model2str (sk.E.model),
954 : _gcry_ecc_dialect2str (sk.E.dialect),
955 0 : (ctx.flags & PUBKEY_FLAG_EDDSA)? "+EdDSA":"");
956 0 : if (sk.E.name)
957 0 : log_debug ("ecc_sign name: %s\n", sk.E.name);
958 0 : log_printmpi ("ecc_sign p", sk.E.p);
959 0 : log_printmpi ("ecc_sign a", sk.E.a);
960 0 : log_printmpi ("ecc_sign b", sk.E.b);
961 0 : log_printpnt ("ecc_sign g", &sk.E.G, NULL);
962 0 : log_printmpi ("ecc_sign n", sk.E.n);
963 0 : log_printmpi ("ecc_sign h", sk.E.h);
964 0 : log_printmpi ("ecc_sign q", mpi_q);
965 0 : if (!fips_mode ())
966 0 : log_printmpi ("ecc_sign d", sk.d);
967 : }
968 1190 : if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.E.h || !sk.d)
969 : {
970 0 : rc = GPG_ERR_NO_OBJ;
971 0 : goto leave;
972 : }
973 :
974 :
975 1190 : sig_r = mpi_new (0);
976 1190 : sig_s = mpi_new (0);
977 1190 : if ((ctx.flags & PUBKEY_FLAG_EDDSA))
978 : {
979 : /* EdDSA requires the public key. */
980 1036 : rc = _gcry_ecc_eddsa_sign (data, &sk, sig_r, sig_s, ctx.hash_algo, mpi_q);
981 1036 : if (!rc)
982 1036 : rc = sexp_build (r_sig, NULL,
983 : "(sig-val(eddsa(r%M)(s%M)))", sig_r, sig_s);
984 : }
985 154 : else if ((ctx.flags & PUBKEY_FLAG_GOST))
986 : {
987 26 : rc = _gcry_ecc_gost_sign (data, &sk, sig_r, sig_s);
988 26 : if (!rc)
989 26 : rc = sexp_build (r_sig, NULL,
990 : "(sig-val(gost(r%M)(s%M)))", sig_r, sig_s);
991 : }
992 : else
993 : {
994 128 : rc = _gcry_ecc_ecdsa_sign (data, &sk, sig_r, sig_s,
995 : ctx.flags, ctx.hash_algo);
996 128 : if (!rc)
997 128 : rc = sexp_build (r_sig, NULL,
998 : "(sig-val(ecdsa(r%M)(s%M)))", sig_r, sig_s);
999 : }
1000 :
1001 :
1002 : leave:
1003 1190 : _gcry_mpi_release (sk.E.p);
1004 1190 : _gcry_mpi_release (sk.E.a);
1005 1190 : _gcry_mpi_release (sk.E.b);
1006 1190 : _gcry_mpi_release (mpi_g);
1007 1190 : point_free (&sk.E.G);
1008 1190 : _gcry_mpi_release (sk.E.n);
1009 1190 : _gcry_mpi_release (sk.E.h);
1010 1190 : _gcry_mpi_release (mpi_q);
1011 1190 : point_free (&sk.Q);
1012 1190 : _gcry_mpi_release (sk.d);
1013 1190 : _gcry_mpi_release (sig_r);
1014 1190 : _gcry_mpi_release (sig_s);
1015 1190 : xfree (curvename);
1016 1190 : _gcry_mpi_release (data);
1017 1190 : sexp_release (l1);
1018 1190 : _gcry_pk_util_free_encoding_ctx (&ctx);
1019 1190 : if (DBG_CIPHER)
1020 0 : log_debug ("ecc_sign => %s\n", gpg_strerror (rc));
1021 1190 : return rc;
1022 : }
1023 :
1024 :
1025 : static gcry_err_code_t
1026 1220 : ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
1027 : {
1028 : gcry_err_code_t rc;
1029 : struct pk_encoding_ctx ctx;
1030 1220 : gcry_sexp_t l1 = NULL;
1031 1220 : char *curvename = NULL;
1032 1220 : gcry_mpi_t mpi_g = NULL;
1033 1220 : gcry_mpi_t mpi_q = NULL;
1034 1220 : gcry_mpi_t sig_r = NULL;
1035 1220 : gcry_mpi_t sig_s = NULL;
1036 1220 : gcry_mpi_t data = NULL;
1037 : ECC_public_key pk;
1038 : int sigflags;
1039 :
1040 1220 : memset (&pk, 0, sizeof pk);
1041 1220 : _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY,
1042 : ecc_get_nbits (s_keyparms));
1043 :
1044 : /* Extract the data. */
1045 1220 : rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
1046 1220 : if (rc)
1047 0 : goto leave;
1048 1220 : if (DBG_CIPHER)
1049 0 : log_mpidump ("ecc_verify data", data);
1050 :
1051 : /*
1052 : * Extract the signature value.
1053 : */
1054 1220 : rc = _gcry_pk_util_preparse_sigval (s_sig, ecc_names, &l1, &sigflags);
1055 1220 : if (rc)
1056 0 : goto leave;
1057 1220 : rc = sexp_extract_param (l1, NULL, (sigflags & PUBKEY_FLAG_EDDSA)? "/rs":"rs",
1058 : &sig_r, &sig_s, NULL);
1059 1220 : if (rc)
1060 0 : goto leave;
1061 1220 : if (DBG_CIPHER)
1062 : {
1063 0 : log_mpidump ("ecc_verify s_r", sig_r);
1064 0 : log_mpidump ("ecc_verify s_s", sig_s);
1065 : }
1066 1220 : if ((ctx.flags & PUBKEY_FLAG_EDDSA) ^ (sigflags & PUBKEY_FLAG_EDDSA))
1067 : {
1068 0 : rc = GPG_ERR_CONFLICT; /* Inconsistent use of flag/algoname. */
1069 0 : goto leave;
1070 : }
1071 :
1072 :
1073 : /*
1074 : * Extract the key.
1075 : */
1076 1220 : if ((ctx.flags & PUBKEY_FLAG_PARAM))
1077 0 : rc = sexp_extract_param (s_keyparms, NULL, "-p?a?b?g?n?h?/q",
1078 : &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n,
1079 : &pk.E.h, &mpi_q, NULL);
1080 : else
1081 1220 : rc = sexp_extract_param (s_keyparms, NULL, "/q",
1082 : &mpi_q, NULL);
1083 1220 : if (rc)
1084 0 : goto leave;
1085 1220 : if (mpi_g)
1086 : {
1087 0 : point_init (&pk.E.G);
1088 0 : rc = _gcry_ecc_os2ec (&pk.E.G, mpi_g);
1089 0 : if (rc)
1090 0 : goto leave;
1091 : }
1092 : /* Add missing parameters using the optional curve parameter. */
1093 1220 : sexp_release (l1);
1094 1220 : l1 = sexp_find_token (s_keyparms, "curve", 5);
1095 1220 : if (l1)
1096 : {
1097 1220 : curvename = sexp_nth_string (l1, 1);
1098 1220 : if (curvename)
1099 : {
1100 1220 : rc = _gcry_ecc_fill_in_curve (0, curvename, &pk.E, NULL);
1101 1220 : if (rc)
1102 0 : goto leave;
1103 : }
1104 : }
1105 : /* Guess required fields if a curve parameter has not been given.
1106 : FIXME: This is a crude hacks. We need to fix that. */
1107 1220 : if (!curvename)
1108 : {
1109 0 : pk.E.model = ((sigflags & PUBKEY_FLAG_EDDSA)
1110 : ? MPI_EC_EDWARDS
1111 0 : : MPI_EC_WEIERSTRASS);
1112 0 : pk.E.dialect = ((sigflags & PUBKEY_FLAG_EDDSA)
1113 : ? ECC_DIALECT_ED25519
1114 0 : : ECC_DIALECT_STANDARD);
1115 0 : if (!pk.E.h)
1116 0 : pk.E.h = mpi_const (MPI_C_ONE);
1117 : }
1118 :
1119 1220 : if (DBG_CIPHER)
1120 : {
1121 0 : log_debug ("ecc_verify info: %s/%s%s\n",
1122 : _gcry_ecc_model2str (pk.E.model),
1123 : _gcry_ecc_dialect2str (pk.E.dialect),
1124 0 : (sigflags & PUBKEY_FLAG_EDDSA)? "+EdDSA":"");
1125 0 : if (pk.E.name)
1126 0 : log_debug ("ecc_verify name: %s\n", pk.E.name);
1127 0 : log_printmpi ("ecc_verify p", pk.E.p);
1128 0 : log_printmpi ("ecc_verify a", pk.E.a);
1129 0 : log_printmpi ("ecc_verify b", pk.E.b);
1130 0 : log_printpnt ("ecc_verify g", &pk.E.G, NULL);
1131 0 : log_printmpi ("ecc_verify n", pk.E.n);
1132 0 : log_printmpi ("ecc_verify h", pk.E.h);
1133 0 : log_printmpi ("ecc_verify q", mpi_q);
1134 : }
1135 1220 : if (!pk.E.p || !pk.E.a || !pk.E.b || !pk.E.G.x || !pk.E.n || !pk.E.h || !mpi_q)
1136 : {
1137 0 : rc = GPG_ERR_NO_OBJ;
1138 0 : goto leave;
1139 : }
1140 :
1141 :
1142 : /*
1143 : * Verify the signature.
1144 : */
1145 1220 : if ((sigflags & PUBKEY_FLAG_EDDSA))
1146 : {
1147 1036 : rc = _gcry_ecc_eddsa_verify (data, &pk, sig_r, sig_s,
1148 : ctx.hash_algo, mpi_q);
1149 : }
1150 184 : else if ((sigflags & PUBKEY_FLAG_GOST))
1151 : {
1152 32 : point_init (&pk.Q);
1153 32 : rc = _gcry_ecc_os2ec (&pk.Q, mpi_q);
1154 32 : if (rc)
1155 0 : goto leave;
1156 :
1157 32 : rc = _gcry_ecc_gost_verify (data, &pk, sig_r, sig_s);
1158 : }
1159 : else
1160 : {
1161 152 : point_init (&pk.Q);
1162 152 : if (pk.E.dialect == ECC_DIALECT_ED25519)
1163 : {
1164 : mpi_ec_t ec;
1165 :
1166 : /* Fixme: Factor the curve context setup out of eddsa_verify
1167 : and ecdsa_verify. So that we don't do it twice. */
1168 4 : ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, 0,
1169 : pk.E.p, pk.E.a, pk.E.b);
1170 :
1171 4 : rc = _gcry_ecc_eddsa_decodepoint (mpi_q, ec, &pk.Q, NULL, NULL);
1172 4 : _gcry_mpi_ec_free (ec);
1173 : }
1174 : else
1175 : {
1176 148 : rc = _gcry_ecc_os2ec (&pk.Q, mpi_q);
1177 : }
1178 152 : if (rc)
1179 0 : goto leave;
1180 :
1181 152 : if (mpi_is_opaque (data))
1182 72 : {
1183 : const void *abuf;
1184 : unsigned int abits, qbits;
1185 : gcry_mpi_t a;
1186 :
1187 72 : qbits = mpi_get_nbits (pk.E.n);
1188 :
1189 72 : abuf = mpi_get_opaque (data, &abits);
1190 72 : rc = _gcry_mpi_scan (&a, GCRYMPI_FMT_USG, abuf, (abits+7)/8, NULL);
1191 72 : if (!rc)
1192 : {
1193 72 : if (abits > qbits)
1194 26 : mpi_rshift (a, a, abits - qbits);
1195 :
1196 72 : rc = _gcry_ecc_ecdsa_verify (a, &pk, sig_r, sig_s);
1197 72 : _gcry_mpi_release (a);
1198 : }
1199 : }
1200 : else
1201 80 : rc = _gcry_ecc_ecdsa_verify (data, &pk, sig_r, sig_s);
1202 : }
1203 :
1204 : leave:
1205 1220 : _gcry_mpi_release (pk.E.p);
1206 1220 : _gcry_mpi_release (pk.E.a);
1207 1220 : _gcry_mpi_release (pk.E.b);
1208 1220 : _gcry_mpi_release (mpi_g);
1209 1220 : point_free (&pk.E.G);
1210 1220 : _gcry_mpi_release (pk.E.n);
1211 1220 : _gcry_mpi_release (pk.E.h);
1212 1220 : _gcry_mpi_release (mpi_q);
1213 1220 : point_free (&pk.Q);
1214 1220 : _gcry_mpi_release (data);
1215 1220 : _gcry_mpi_release (sig_r);
1216 1220 : _gcry_mpi_release (sig_s);
1217 1220 : xfree (curvename);
1218 1220 : sexp_release (l1);
1219 1220 : _gcry_pk_util_free_encoding_ctx (&ctx);
1220 1220 : if (DBG_CIPHER)
1221 0 : log_debug ("ecc_verify => %s\n", rc?gpg_strerror (rc):"Good");
1222 1220 : return rc;
1223 : }
1224 :
1225 :
1226 : /* ecdh raw is classic 2-round DH protocol published in 1976.
1227 : *
1228 : * Overview of ecc_encrypt_raw and ecc_decrypt_raw.
1229 : *
1230 : * As with any PK operation, encrypt version uses a public key and
1231 : * decrypt -- private.
1232 : *
1233 : * Symbols used below:
1234 : * G - field generator point
1235 : * d - private long-term scalar
1236 : * dG - public long-term key
1237 : * k - ephemeral scalar
1238 : * kG - ephemeral public key
1239 : * dkG - shared secret
1240 : *
1241 : * ecc_encrypt_raw description:
1242 : * input:
1243 : * data[0] : private scalar (k)
1244 : * output: A new S-expression with the parameters:
1245 : * s : shared point (kdG)
1246 : * e : generated ephemeral public key (kG)
1247 : *
1248 : * ecc_decrypt_raw description:
1249 : * input:
1250 : * data[0] : a point kG (ephemeral public key)
1251 : * output:
1252 : * result[0] : shared point (kdG)
1253 : */
1254 : static gcry_err_code_t
1255 19 : ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
1256 : {
1257 : unsigned int nbits;
1258 : gcry_err_code_t rc;
1259 : struct pk_encoding_ctx ctx;
1260 19 : gcry_sexp_t l1 = NULL;
1261 19 : char *curvename = NULL;
1262 19 : gcry_mpi_t mpi_g = NULL;
1263 19 : gcry_mpi_t mpi_q = NULL;
1264 19 : gcry_mpi_t mpi_s = NULL;
1265 19 : gcry_mpi_t mpi_e = NULL;
1266 19 : gcry_mpi_t data = NULL;
1267 : ECC_public_key pk;
1268 19 : mpi_ec_t ec = NULL;
1269 19 : int flags = 0;
1270 :
1271 19 : memset (&pk, 0, sizeof pk);
1272 19 : _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT,
1273 : (nbits = ecc_get_nbits (keyparms)));
1274 :
1275 : /* Look for flags. */
1276 19 : l1 = sexp_find_token (keyparms, "flags", 0);
1277 19 : if (l1)
1278 : {
1279 19 : rc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
1280 19 : if (rc)
1281 0 : goto leave;
1282 : }
1283 19 : sexp_release (l1);
1284 19 : l1 = NULL;
1285 :
1286 : /*
1287 : * Extract the data.
1288 : */
1289 19 : rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
1290 19 : if (rc)
1291 0 : goto leave;
1292 19 : if (mpi_is_opaque (data))
1293 : {
1294 0 : rc = GPG_ERR_INV_DATA;
1295 0 : goto leave;
1296 : }
1297 :
1298 : /*
1299 : * Extract the key.
1300 : */
1301 19 : rc = sexp_extract_param (keyparms, NULL,
1302 19 : (flags & PUBKEY_FLAG_DJB_TWEAK)?
1303 : "-p?a?b?g?n?h?/q" : "-p?a?b?g?n?h?+q",
1304 : &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n, &pk.E.h,
1305 : &mpi_q, NULL);
1306 19 : if (rc)
1307 0 : goto leave;
1308 19 : if (mpi_g)
1309 : {
1310 0 : point_init (&pk.E.G);
1311 0 : rc = _gcry_ecc_os2ec (&pk.E.G, mpi_g);
1312 0 : if (rc)
1313 0 : goto leave;
1314 : }
1315 : /* Add missing parameters using the optional curve parameter. */
1316 19 : l1 = sexp_find_token (keyparms, "curve", 5);
1317 19 : if (l1)
1318 : {
1319 19 : curvename = sexp_nth_string (l1, 1);
1320 19 : if (curvename)
1321 : {
1322 19 : rc = _gcry_ecc_fill_in_curve (0, curvename, &pk.E, NULL);
1323 19 : if (rc)
1324 0 : goto leave;
1325 : }
1326 : }
1327 : /* Guess required fields if a curve parameter has not been given. */
1328 19 : if (!curvename)
1329 : {
1330 0 : pk.E.model = MPI_EC_WEIERSTRASS;
1331 0 : pk.E.dialect = ECC_DIALECT_STANDARD;
1332 0 : if (!pk.E.h)
1333 0 : pk.E.h = mpi_const (MPI_C_ONE);
1334 : }
1335 :
1336 : /*
1337 : * Tweak the scalar bits by cofactor and number of bits of the field.
1338 : * It assumes the cofactor is a power of 2.
1339 : */
1340 19 : if ((flags & PUBKEY_FLAG_DJB_TWEAK))
1341 : {
1342 : int i;
1343 :
1344 76 : for (i = 0; i < mpi_get_nbits (pk.E.h) - 1; i++)
1345 57 : mpi_clear_bit (data, i);
1346 19 : mpi_set_highbit (data, mpi_get_nbits (pk.E.p) - 1);
1347 : }
1348 19 : if (DBG_CIPHER)
1349 0 : log_mpidump ("ecc_encrypt data", data);
1350 :
1351 19 : if (DBG_CIPHER)
1352 : {
1353 0 : log_debug ("ecc_encrypt info: %s/%s\n",
1354 : _gcry_ecc_model2str (pk.E.model),
1355 : _gcry_ecc_dialect2str (pk.E.dialect));
1356 0 : if (pk.E.name)
1357 0 : log_debug ("ecc_encrypt name: %s\n", pk.E.name);
1358 0 : log_printmpi ("ecc_encrypt p", pk.E.p);
1359 0 : log_printmpi ("ecc_encrypt a", pk.E.a);
1360 0 : log_printmpi ("ecc_encrypt b", pk.E.b);
1361 0 : log_printpnt ("ecc_encrypt g", &pk.E.G, NULL);
1362 0 : log_printmpi ("ecc_encrypt n", pk.E.n);
1363 0 : log_printmpi ("ecc_encrypt h", pk.E.h);
1364 0 : log_printmpi ("ecc_encrypt q", mpi_q);
1365 : }
1366 19 : if (!pk.E.p || !pk.E.a || !pk.E.b || !pk.E.G.x || !pk.E.n || !pk.E.h || !mpi_q)
1367 : {
1368 0 : rc = GPG_ERR_NO_OBJ;
1369 0 : goto leave;
1370 : }
1371 :
1372 : /* Compute the encrypted value. */
1373 19 : ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, flags,
1374 : pk.E.p, pk.E.a, pk.E.b);
1375 :
1376 : /* Convert the public key. */
1377 19 : if (mpi_q)
1378 : {
1379 19 : point_init (&pk.Q);
1380 19 : if (ec->model == MPI_EC_MONTGOMERY)
1381 19 : rc = _gcry_ecc_mont_decodepoint (mpi_q, ec, &pk.Q);
1382 : else
1383 0 : rc = _gcry_ecc_os2ec (&pk.Q, mpi_q);
1384 19 : if (rc)
1385 0 : goto leave;
1386 : }
1387 :
1388 : /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
1389 : {
1390 : mpi_point_struct R; /* Result that we return. */
1391 : gcry_mpi_t x, y;
1392 : unsigned char *rawmpi;
1393 : unsigned int rawmpilen;
1394 :
1395 19 : x = mpi_new (0);
1396 19 : if (ec->model == MPI_EC_MONTGOMERY)
1397 19 : y = NULL;
1398 : else
1399 0 : y = mpi_new (0);
1400 :
1401 19 : point_init (&R);
1402 :
1403 : /* R = kQ <=> R = kdG */
1404 19 : _gcry_mpi_ec_mul_point (&R, data, &pk.Q, ec);
1405 :
1406 19 : if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
1407 : {
1408 : /*
1409 : * Here, X is 0. In the X25519 computation on Curve25519, X0
1410 : * function maps infinity to zero. So, when PUBKEY_FLAG_DJB_TWEAK
1411 : * is enabled, return the result of 0 not raising an error.
1412 : *
1413 : * This is a corner case. It never occurs with properly
1414 : * generated public keys, but it might happen with blindly
1415 : * imported public key which might not follow the key
1416 : * generation procedure.
1417 : */
1418 7 : if (!(flags & PUBKEY_FLAG_DJB_TWEAK))
1419 : { /* It's not for X25519, then, the input data was simply wrong. */
1420 0 : rc = GPG_ERR_INV_DATA;
1421 0 : goto leave;
1422 : }
1423 : }
1424 19 : if (y)
1425 0 : mpi_s = _gcry_ecc_ec2os (x, y, pk.E.p);
1426 : else
1427 : {
1428 19 : rawmpi = _gcry_mpi_get_buffer_extra (x, nbits/8, -1, &rawmpilen, NULL);
1429 19 : if (!rawmpi)
1430 0 : rc = gpg_err_code_from_syserror ();
1431 : else
1432 : {
1433 19 : rawmpi[0] = 0x40;
1434 19 : rawmpilen++;
1435 19 : mpi_s = mpi_new (0);
1436 19 : mpi_set_opaque (mpi_s, rawmpi, rawmpilen*8);
1437 : }
1438 : }
1439 :
1440 : /* R = kG */
1441 19 : _gcry_mpi_ec_mul_point (&R, data, &pk.E.G, ec);
1442 :
1443 19 : if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
1444 : {
1445 0 : rc = GPG_ERR_INV_DATA;
1446 0 : goto leave;
1447 : }
1448 19 : if (y)
1449 0 : mpi_e = _gcry_ecc_ec2os (x, y, pk.E.p);
1450 : else
1451 : {
1452 19 : rawmpi = _gcry_mpi_get_buffer_extra (x, nbits/8, -1, &rawmpilen, NULL);
1453 19 : if (!rawmpi)
1454 0 : rc = gpg_err_code_from_syserror ();
1455 : else
1456 : {
1457 19 : rawmpi[0] = 0x40;
1458 19 : rawmpilen++;
1459 19 : mpi_e = mpi_new (0);
1460 19 : mpi_set_opaque (mpi_e, rawmpi, rawmpilen*8);
1461 : }
1462 : }
1463 :
1464 :
1465 19 : mpi_free (x);
1466 19 : mpi_free (y);
1467 :
1468 19 : point_free (&R);
1469 : }
1470 :
1471 19 : if (!rc)
1472 19 : rc = sexp_build (r_ciph, NULL, "(enc-val(ecdh(s%m)(e%m)))", mpi_s, mpi_e);
1473 :
1474 : leave:
1475 19 : _gcry_mpi_release (pk.E.p);
1476 19 : _gcry_mpi_release (pk.E.a);
1477 19 : _gcry_mpi_release (pk.E.b);
1478 19 : _gcry_mpi_release (mpi_g);
1479 19 : point_free (&pk.E.G);
1480 19 : _gcry_mpi_release (pk.E.n);
1481 19 : _gcry_mpi_release (pk.E.h);
1482 19 : _gcry_mpi_release (mpi_q);
1483 19 : point_free (&pk.Q);
1484 19 : _gcry_mpi_release (data);
1485 19 : _gcry_mpi_release (mpi_s);
1486 19 : _gcry_mpi_release (mpi_e);
1487 19 : xfree (curvename);
1488 19 : sexp_release (l1);
1489 19 : _gcry_mpi_ec_free (ec);
1490 19 : _gcry_pk_util_free_encoding_ctx (&ctx);
1491 19 : if (DBG_CIPHER)
1492 0 : log_debug ("ecc_encrypt => %s\n", gpg_strerror (rc));
1493 19 : return rc;
1494 : }
1495 :
1496 :
1497 : /* input:
1498 : * data[0] : a point kG (ephemeral public key)
1499 : * output:
1500 : * resaddr[0] : shared point kdG
1501 : *
1502 : * see ecc_encrypt_raw for details.
1503 : */
1504 : static gcry_err_code_t
1505 0 : ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
1506 : {
1507 : unsigned int nbits;
1508 : gpg_err_code_t rc;
1509 : struct pk_encoding_ctx ctx;
1510 0 : gcry_sexp_t l1 = NULL;
1511 0 : gcry_mpi_t data_e = NULL;
1512 : ECC_secret_key sk;
1513 0 : gcry_mpi_t mpi_g = NULL;
1514 0 : char *curvename = NULL;
1515 0 : mpi_ec_t ec = NULL;
1516 : mpi_point_struct kG;
1517 : mpi_point_struct R;
1518 0 : gcry_mpi_t r = NULL;
1519 0 : int flags = 0;
1520 :
1521 0 : memset (&sk, 0, sizeof sk);
1522 0 : point_init (&kG);
1523 0 : point_init (&R);
1524 :
1525 0 : _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT,
1526 : (nbits = ecc_get_nbits (keyparms)));
1527 :
1528 : /* Look for flags. */
1529 0 : l1 = sexp_find_token (keyparms, "flags", 0);
1530 0 : if (l1)
1531 : {
1532 0 : rc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
1533 0 : if (rc)
1534 0 : goto leave;
1535 : }
1536 0 : sexp_release (l1);
1537 0 : l1 = NULL;
1538 :
1539 : /*
1540 : * Extract the data.
1541 : */
1542 0 : rc = _gcry_pk_util_preparse_encval (s_data, ecc_names, &l1, &ctx);
1543 0 : if (rc)
1544 0 : goto leave;
1545 0 : rc = sexp_extract_param (l1, NULL, "e", &data_e, NULL);
1546 0 : if (rc)
1547 0 : goto leave;
1548 0 : if (DBG_CIPHER)
1549 0 : log_printmpi ("ecc_decrypt d_e", data_e);
1550 0 : if (mpi_is_opaque (data_e))
1551 : {
1552 0 : rc = GPG_ERR_INV_DATA;
1553 0 : goto leave;
1554 : }
1555 :
1556 : /*
1557 : * Extract the key.
1558 : */
1559 0 : rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?h?+d",
1560 : &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
1561 : &sk.E.h, &sk.d, NULL);
1562 0 : if (rc)
1563 0 : goto leave;
1564 0 : if (mpi_g)
1565 : {
1566 0 : point_init (&sk.E.G);
1567 0 : rc = _gcry_ecc_os2ec (&sk.E.G, mpi_g);
1568 0 : if (rc)
1569 0 : goto leave;
1570 : }
1571 : /* Add missing parameters using the optional curve parameter. */
1572 0 : sexp_release (l1);
1573 0 : l1 = sexp_find_token (keyparms, "curve", 5);
1574 0 : if (l1)
1575 : {
1576 0 : curvename = sexp_nth_string (l1, 1);
1577 0 : if (curvename)
1578 : {
1579 0 : rc = _gcry_ecc_fill_in_curve (0, curvename, &sk.E, NULL);
1580 0 : if (rc)
1581 0 : goto leave;
1582 : }
1583 : }
1584 : /* Guess required fields if a curve parameter has not been given. */
1585 0 : if (!curvename)
1586 : {
1587 0 : sk.E.model = MPI_EC_WEIERSTRASS;
1588 0 : sk.E.dialect = ECC_DIALECT_STANDARD;
1589 0 : if (!sk.E.h)
1590 0 : sk.E.h = mpi_const (MPI_C_ONE);
1591 : }
1592 0 : if (DBG_CIPHER)
1593 : {
1594 0 : log_debug ("ecc_decrypt info: %s/%s\n",
1595 : _gcry_ecc_model2str (sk.E.model),
1596 : _gcry_ecc_dialect2str (sk.E.dialect));
1597 0 : if (sk.E.name)
1598 0 : log_debug ("ecc_decrypt name: %s\n", sk.E.name);
1599 0 : log_printmpi ("ecc_decrypt p", sk.E.p);
1600 0 : log_printmpi ("ecc_decrypt a", sk.E.a);
1601 0 : log_printmpi ("ecc_decrypt b", sk.E.b);
1602 0 : log_printpnt ("ecc_decrypt g", &sk.E.G, NULL);
1603 0 : log_printmpi ("ecc_decrypt n", sk.E.n);
1604 0 : log_printmpi ("ecc_decrypt h", sk.E.h);
1605 0 : if (!fips_mode ())
1606 0 : log_printmpi ("ecc_decrypt d", sk.d);
1607 : }
1608 0 : if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.E.h || !sk.d)
1609 : {
1610 0 : rc = GPG_ERR_NO_OBJ;
1611 0 : goto leave;
1612 : }
1613 :
1614 :
1615 0 : ec = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect, flags,
1616 : sk.E.p, sk.E.a, sk.E.b);
1617 :
1618 : /*
1619 : * Compute the plaintext.
1620 : */
1621 0 : if (ec->model == MPI_EC_MONTGOMERY)
1622 0 : rc = _gcry_ecc_mont_decodepoint (data_e, ec, &kG);
1623 : else
1624 0 : rc = _gcry_ecc_os2ec (&kG, data_e);
1625 0 : if (rc)
1626 0 : goto leave;
1627 :
1628 0 : if (DBG_CIPHER)
1629 0 : log_printpnt ("ecc_decrypt kG", &kG, NULL);
1630 :
1631 0 : if (!(flags & PUBKEY_FLAG_DJB_TWEAK)
1632 : /* For X25519, by its definition, validation should not be done. */
1633 0 : && !_gcry_mpi_ec_curve_point (&kG, ec))
1634 : {
1635 0 : rc = GPG_ERR_INV_DATA;
1636 0 : goto leave;
1637 : }
1638 :
1639 : /* R = dkG */
1640 0 : _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ec);
1641 :
1642 : /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so: */
1643 : {
1644 : gcry_mpi_t x, y;
1645 :
1646 0 : x = mpi_new (0);
1647 0 : if (ec->model == MPI_EC_MONTGOMERY)
1648 0 : y = NULL;
1649 : else
1650 0 : y = mpi_new (0);
1651 :
1652 0 : if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
1653 : {
1654 0 : rc = GPG_ERR_INV_DATA;
1655 0 : goto leave;
1656 : /*
1657 : * Note for X25519.
1658 : *
1659 : * By the definition of X25519, this is the case where X25519
1660 : * returns 0, mapping infinity to zero. However, we
1661 : * deliberately let it return an error.
1662 : *
1663 : * For X25519 ECDH, comming here means that it might be
1664 : * decrypted by anyone with the shared secret of 0 (the result
1665 : * of this function could be always 0 by other scalar values,
1666 : * other than the private key of SK.D).
1667 : *
1668 : * So, it looks like an encrypted message but it can be
1669 : * decrypted by anyone, or at least something wrong
1670 : * happens. Recipient should not proceed as if it were
1671 : * properly encrypted message.
1672 : *
1673 : * This handling is needed for our major usage of GnuPG,
1674 : * where it does the One-Pass Diffie-Hellman method,
1675 : * C(1, 1, ECC CDH), with an ephemeral key.
1676 : */
1677 : }
1678 :
1679 0 : if (y)
1680 0 : r = _gcry_ecc_ec2os (x, y, sk.E.p);
1681 : else
1682 : {
1683 : unsigned char *rawmpi;
1684 : unsigned int rawmpilen;
1685 :
1686 0 : rawmpi = _gcry_mpi_get_buffer_extra (x, nbits/8, -1,
1687 : &rawmpilen, NULL);
1688 0 : if (!rawmpi)
1689 : {
1690 0 : rc = gpg_err_code_from_syserror ();
1691 0 : goto leave;
1692 : }
1693 : else
1694 : {
1695 0 : rawmpi[0] = 0x40;
1696 0 : rawmpilen++;
1697 0 : r = mpi_new (0);
1698 0 : mpi_set_opaque (r, rawmpi, rawmpilen*8);
1699 : }
1700 : }
1701 0 : if (!r)
1702 0 : rc = gpg_err_code_from_syserror ();
1703 : else
1704 0 : rc = 0;
1705 0 : mpi_free (x);
1706 0 : mpi_free (y);
1707 : }
1708 0 : if (DBG_CIPHER)
1709 0 : log_printmpi ("ecc_decrypt res", r);
1710 :
1711 0 : if (!rc)
1712 0 : rc = sexp_build (r_plain, NULL, "(value %m)", r);
1713 :
1714 : leave:
1715 0 : point_free (&R);
1716 0 : point_free (&kG);
1717 0 : _gcry_mpi_release (r);
1718 0 : _gcry_mpi_release (sk.E.p);
1719 0 : _gcry_mpi_release (sk.E.a);
1720 0 : _gcry_mpi_release (sk.E.b);
1721 0 : _gcry_mpi_release (mpi_g);
1722 0 : point_free (&sk.E.G);
1723 0 : _gcry_mpi_release (sk.E.n);
1724 0 : _gcry_mpi_release (sk.E.h);
1725 0 : _gcry_mpi_release (sk.d);
1726 0 : _gcry_mpi_release (data_e);
1727 0 : xfree (curvename);
1728 0 : sexp_release (l1);
1729 0 : _gcry_mpi_ec_free (ec);
1730 0 : _gcry_pk_util_free_encoding_ctx (&ctx);
1731 0 : if (DBG_CIPHER)
1732 0 : log_debug ("ecc_decrypt => %s\n", gpg_strerror (rc));
1733 0 : return rc;
1734 : }
1735 :
1736 :
1737 : /* Return the number of bits for the key described by PARMS. On error
1738 : * 0 is returned. The format of PARMS starts with the algorithm name;
1739 : * for example:
1740 : *
1741 : * (ecc
1742 : * (curve <name>)
1743 : * (p <mpi>)
1744 : * (a <mpi>)
1745 : * (b <mpi>)
1746 : * (g <mpi>)
1747 : * (n <mpi>)
1748 : * (q <mpi>))
1749 : *
1750 : * More parameters may be given. Either P or CURVE is needed.
1751 : */
1752 : static unsigned int
1753 1255 : ecc_get_nbits (gcry_sexp_t parms)
1754 : {
1755 : gcry_sexp_t l1;
1756 : gcry_mpi_t p;
1757 1255 : unsigned int nbits = 0;
1758 : char *curve;
1759 :
1760 1255 : l1 = sexp_find_token (parms, "p", 1);
1761 1255 : if (!l1)
1762 : { /* Parameter P not found - check whether we have "curve". */
1763 1255 : l1 = sexp_find_token (parms, "curve", 5);
1764 1255 : if (!l1)
1765 0 : return 0; /* Neither P nor CURVE found. */
1766 :
1767 1255 : curve = sexp_nth_string (l1, 1);
1768 1255 : sexp_release (l1);
1769 1255 : if (!curve)
1770 0 : return 0; /* No curve name given (or out of core). */
1771 :
1772 1255 : if (_gcry_ecc_fill_in_curve (0, curve, NULL, &nbits))
1773 0 : nbits = 0;
1774 1255 : xfree (curve);
1775 : }
1776 : else
1777 : {
1778 0 : p = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
1779 0 : sexp_release (l1);
1780 0 : if (p)
1781 : {
1782 0 : nbits = mpi_get_nbits (p);
1783 0 : _gcry_mpi_release (p);
1784 : }
1785 : }
1786 1255 : return nbits;
1787 : }
1788 :
1789 :
1790 : /* See rsa.c for a description of this function. */
1791 : static gpg_err_code_t
1792 9 : compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
1793 : {
1794 : #define N_COMPONENTS 7
1795 : static const char names[N_COMPONENTS] = "pabgnhq";
1796 : gpg_err_code_t rc;
1797 : gcry_sexp_t l1;
1798 : gcry_mpi_t values[N_COMPONENTS];
1799 : int idx;
1800 9 : char *curvename = NULL;
1801 9 : int flags = 0;
1802 9 : enum gcry_mpi_ec_models model = 0;
1803 9 : enum ecc_dialects dialect = 0;
1804 :
1805 : /* Clear the values first. */
1806 72 : for (idx=0; idx < N_COMPONENTS; idx++)
1807 63 : values[idx] = NULL;
1808 :
1809 :
1810 : /* Look for flags. */
1811 9 : l1 = sexp_find_token (keyparms, "flags", 0);
1812 9 : if (l1)
1813 : {
1814 5 : rc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
1815 5 : if (rc)
1816 0 : goto leave;
1817 : }
1818 :
1819 : /* Extract the parameters. */
1820 9 : if ((flags & PUBKEY_FLAG_PARAM))
1821 : {
1822 2 : if ((flags & PUBKEY_FLAG_DJB_TWEAK))
1823 0 : rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?h?/q",
1824 : &values[0], &values[1], &values[2],
1825 : &values[3], &values[4], &values[5],
1826 : &values[6], NULL);
1827 : else
1828 2 : rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?h?q",
1829 : &values[0], &values[1], &values[2],
1830 : &values[3], &values[4], &values[5],
1831 : &values[6], NULL);
1832 : }
1833 : else
1834 : {
1835 7 : if ((flags & PUBKEY_FLAG_DJB_TWEAK))
1836 3 : rc = sexp_extract_param (keyparms, NULL, "/q",
1837 : &values[6], NULL);
1838 : else
1839 4 : rc = sexp_extract_param (keyparms, NULL, "q",
1840 : &values[6], NULL);
1841 : }
1842 9 : if (rc)
1843 0 : goto leave;
1844 :
1845 : /* Check whether a curve parameter is available and use that to fill
1846 : in missing values. */
1847 9 : sexp_release (l1);
1848 9 : l1 = sexp_find_token (keyparms, "curve", 5);
1849 9 : if (l1)
1850 : {
1851 8 : curvename = sexp_nth_string (l1, 1);
1852 8 : if (curvename)
1853 : {
1854 8 : rc = _gcry_ecc_update_curve_param (curvename,
1855 : &model, &dialect,
1856 : &values[0], &values[1], &values[2],
1857 : &values[3], &values[4], &values[5]);
1858 8 : if (rc)
1859 0 : goto leave;
1860 : }
1861 : }
1862 :
1863 : /* Guess required fields if a curve parameter has not been given.
1864 : FIXME: This is a crude hacks. We need to fix that. */
1865 9 : if (!curvename)
1866 : {
1867 2 : model = ((flags & PUBKEY_FLAG_EDDSA)
1868 : ? MPI_EC_EDWARDS
1869 1 : : MPI_EC_WEIERSTRASS);
1870 2 : dialect = ((flags & PUBKEY_FLAG_EDDSA)
1871 : ? ECC_DIALECT_ED25519
1872 1 : : ECC_DIALECT_STANDARD);
1873 1 : if (!values[5])
1874 0 : values[5] = mpi_const (MPI_C_ONE);
1875 : }
1876 :
1877 : /* Check that all parameters are known and normalize all MPIs (that
1878 : should not be required but we use an internal function later and
1879 : thus we better make 100% sure that they are normalized). */
1880 72 : for (idx = 0; idx < N_COMPONENTS; idx++)
1881 63 : if (!values[idx])
1882 : {
1883 0 : rc = GPG_ERR_NO_OBJ;
1884 0 : goto leave;
1885 : }
1886 : else
1887 63 : _gcry_mpi_normalize (values[idx]);
1888 :
1889 : /* Uncompress the public key with the exception of EdDSA where
1890 : compression is the default and we thus compute the keygrip using
1891 : the compressed version. Because we don't support any non-eddsa
1892 : compression, the only thing we need to do is to compress
1893 : EdDSA. */
1894 9 : if ((flags & PUBKEY_FLAG_DJB_TWEAK))
1895 : {
1896 3 : rc = _gcry_ecc_eddsa_ensure_compact (values[6], 256);
1897 3 : if (rc)
1898 0 : goto leave;
1899 : }
1900 :
1901 : /* Hash them all. */
1902 72 : for (idx = 0; idx < N_COMPONENTS; idx++)
1903 : {
1904 : char buf[30];
1905 :
1906 63 : if (idx == 5)
1907 9 : continue; /* Skip cofactor. */
1908 :
1909 54 : if (mpi_is_opaque (values[idx]))
1910 3 : {
1911 : const unsigned char *raw;
1912 : unsigned int n;
1913 :
1914 3 : raw = mpi_get_opaque (values[idx], &n);
1915 3 : n = (n + 7)/8;
1916 3 : snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], n);
1917 3 : _gcry_md_write (md, buf, strlen (buf));
1918 3 : _gcry_md_write (md, raw, n);
1919 3 : _gcry_md_write (md, ")", 1);
1920 : }
1921 : else
1922 : {
1923 : unsigned char *rawmpi;
1924 : unsigned int rawmpilen;
1925 :
1926 51 : rawmpi = _gcry_mpi_get_buffer (values[idx], 0, &rawmpilen, NULL);
1927 51 : if (!rawmpi)
1928 : {
1929 0 : rc = gpg_err_code_from_syserror ();
1930 0 : goto leave;
1931 : }
1932 51 : snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], rawmpilen);
1933 51 : _gcry_md_write (md, buf, strlen (buf));
1934 51 : _gcry_md_write (md, rawmpi, rawmpilen);
1935 51 : _gcry_md_write (md, ")", 1);
1936 51 : xfree (rawmpi);
1937 : }
1938 : }
1939 :
1940 : leave:
1941 9 : xfree (curvename);
1942 9 : sexp_release (l1);
1943 72 : for (idx = 0; idx < N_COMPONENTS; idx++)
1944 63 : _gcry_mpi_release (values[idx]);
1945 :
1946 9 : return rc;
1947 : #undef N_COMPONENTS
1948 : }
1949 :
1950 :
1951 :
1952 : /*
1953 : Low-level API helper functions.
1954 : */
1955 :
1956 : /* This is the worker function for gcry_pubkey_get_sexp for ECC
1957 : algorithms. Note that the caller has already stored NULL at
1958 : R_SEXP. */
1959 : gpg_err_code_t
1960 11 : _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
1961 : {
1962 : gpg_err_code_t rc;
1963 11 : gcry_mpi_t mpi_G = NULL;
1964 11 : gcry_mpi_t mpi_Q = NULL;
1965 :
1966 11 : if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n || !ec->h)
1967 0 : return GPG_ERR_BAD_CRYPT_CTX;
1968 :
1969 11 : if (mode == GCRY_PK_GET_SECKEY && !ec->d)
1970 3 : return GPG_ERR_NO_SECKEY;
1971 :
1972 : /* Compute the public point if it is missing. */
1973 8 : if (!ec->Q && ec->d)
1974 1 : ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
1975 :
1976 : /* Encode G and Q. */
1977 8 : mpi_G = _gcry_mpi_ec_ec2os (ec->G, ec);
1978 8 : if (!mpi_G)
1979 : {
1980 0 : rc = GPG_ERR_BROKEN_PUBKEY;
1981 0 : goto leave;
1982 : }
1983 8 : if (!ec->Q)
1984 : {
1985 1 : rc = GPG_ERR_BAD_CRYPT_CTX;
1986 1 : goto leave;
1987 : }
1988 :
1989 7 : if (ec->dialect == ECC_DIALECT_ED25519)
1990 : {
1991 : unsigned char *encpk;
1992 : unsigned int encpklen;
1993 :
1994 2 : rc = _gcry_ecc_eddsa_encodepoint (ec->Q, ec, NULL, NULL, 0,
1995 : &encpk, &encpklen);
1996 2 : if (rc)
1997 0 : goto leave;
1998 2 : mpi_Q = mpi_set_opaque (NULL, encpk, encpklen*8);
1999 2 : encpk = NULL;
2000 : }
2001 : else
2002 : {
2003 5 : mpi_Q = _gcry_mpi_ec_ec2os (ec->Q, ec);
2004 : }
2005 7 : if (!mpi_Q)
2006 : {
2007 0 : rc = GPG_ERR_BROKEN_PUBKEY;
2008 0 : goto leave;
2009 : }
2010 :
2011 : /* Fixme: We should return a curve name instead of the parameters if
2012 : if know that they match a curve. */
2013 :
2014 7 : if (ec->d && (!mode || mode == GCRY_PK_GET_SECKEY))
2015 : {
2016 : /* Let's return a private key. */
2017 1 : rc = sexp_build (r_sexp, NULL,
2018 : "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(q%m)(d%m)))",
2019 : ec->p, ec->a, ec->b, mpi_G, ec->n, ec->h, mpi_Q, ec->d);
2020 : }
2021 6 : else if (ec->Q)
2022 : {
2023 : /* Let's return a public key. */
2024 6 : rc = sexp_build (r_sexp, NULL,
2025 : "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(q%m)))",
2026 : ec->p, ec->a, ec->b, mpi_G, ec->n, ec->h, mpi_Q);
2027 : }
2028 : else
2029 0 : rc = GPG_ERR_BAD_CRYPT_CTX;
2030 :
2031 : leave:
2032 8 : mpi_free (mpi_Q);
2033 8 : mpi_free (mpi_G);
2034 8 : return rc;
2035 : }
2036 :
2037 :
2038 :
2039 : /*
2040 : Self-test section.
2041 : */
2042 :
2043 : static const char *
2044 2 : selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey)
2045 : {
2046 : /* Sample data from RFC 6979 section A.2.5, hash is of message "sample" */
2047 : static const char sample_data[] =
2048 : "(data (flags rfc6979)"
2049 : " (hash sha256 #af2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915"
2050 : /**/ "62113d8a62add1bf#))";
2051 : static const char sample_data_bad[] =
2052 : "(data (flags rfc6979)"
2053 : " (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915"
2054 : /**/ "62113d8a62add1bf#))";
2055 : static const char signature_r[] =
2056 : "efd48b2aacb6a8fd1140dd9cd45e81d69d2c877b56aaf991c34d0ea84eaf3716";
2057 : static const char signature_s[] =
2058 : "f7cb1c942d657c41d436c7a1b6e29f65f3e900dbb9aff4064dc4ab2f843acda8";
2059 :
2060 2 : const char *errtxt = NULL;
2061 : gcry_error_t err;
2062 2 : gcry_sexp_t data = NULL;
2063 2 : gcry_sexp_t data_bad = NULL;
2064 2 : gcry_sexp_t sig = NULL;
2065 2 : gcry_sexp_t l1 = NULL;
2066 2 : gcry_sexp_t l2 = NULL;
2067 2 : gcry_mpi_t r = NULL;
2068 2 : gcry_mpi_t s = NULL;
2069 2 : gcry_mpi_t calculated_r = NULL;
2070 2 : gcry_mpi_t calculated_s = NULL;
2071 : int cmp;
2072 :
2073 2 : err = sexp_sscan (&data, NULL, sample_data, strlen (sample_data));
2074 2 : if (!err)
2075 2 : err = sexp_sscan (&data_bad, NULL,
2076 : sample_data_bad, strlen (sample_data_bad));
2077 2 : if (!err)
2078 2 : err = _gcry_mpi_scan (&r, GCRYMPI_FMT_HEX, signature_r, 0, NULL);
2079 2 : if (!err)
2080 2 : err = _gcry_mpi_scan (&s, GCRYMPI_FMT_HEX, signature_s, 0, NULL);
2081 :
2082 2 : if (err)
2083 : {
2084 0 : errtxt = "converting data failed";
2085 0 : goto leave;
2086 : }
2087 :
2088 2 : err = _gcry_pk_sign (&sig, data, skey);
2089 2 : if (err)
2090 : {
2091 0 : errtxt = "signing failed";
2092 0 : goto leave;
2093 : }
2094 :
2095 : /* check against known signature */
2096 2 : errtxt = "signature validity failed";
2097 2 : l1 = _gcry_sexp_find_token (sig, "sig-val", 0);
2098 2 : if (!l1)
2099 0 : goto leave;
2100 2 : l2 = _gcry_sexp_find_token (l1, "ecdsa", 0);
2101 2 : if (!l2)
2102 0 : goto leave;
2103 :
2104 2 : sexp_release (l1);
2105 2 : l1 = l2;
2106 :
2107 2 : l2 = _gcry_sexp_find_token (l1, "r", 0);
2108 2 : if (!l2)
2109 0 : goto leave;
2110 2 : calculated_r = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
2111 2 : if (!calculated_r)
2112 0 : goto leave;
2113 :
2114 2 : sexp_release (l2);
2115 2 : l2 = _gcry_sexp_find_token (l1, "s", 0);
2116 2 : if (!l2)
2117 0 : goto leave;
2118 2 : calculated_s = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
2119 2 : if (!calculated_s)
2120 0 : goto leave;
2121 :
2122 2 : errtxt = "known sig check failed";
2123 :
2124 2 : cmp = _gcry_mpi_cmp (r, calculated_r);
2125 2 : if (cmp)
2126 0 : goto leave;
2127 2 : cmp = _gcry_mpi_cmp (s, calculated_s);
2128 2 : if (cmp)
2129 0 : goto leave;
2130 :
2131 2 : errtxt = NULL;
2132 :
2133 : /* verify generated signature */
2134 2 : err = _gcry_pk_verify (sig, data, pkey);
2135 2 : if (err)
2136 : {
2137 0 : errtxt = "verify failed";
2138 0 : goto leave;
2139 : }
2140 2 : err = _gcry_pk_verify (sig, data_bad, pkey);
2141 2 : if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE)
2142 : {
2143 0 : errtxt = "bad signature not detected";
2144 0 : goto leave;
2145 : }
2146 :
2147 :
2148 : leave:
2149 2 : sexp_release (sig);
2150 2 : sexp_release (data_bad);
2151 2 : sexp_release (data);
2152 2 : sexp_release (l1);
2153 2 : sexp_release (l2);
2154 2 : mpi_release (r);
2155 2 : mpi_release (s);
2156 2 : mpi_release (calculated_r);
2157 2 : mpi_release (calculated_s);
2158 2 : return errtxt;
2159 : }
2160 :
2161 :
2162 : static gpg_err_code_t
2163 2 : selftests_ecdsa (selftest_report_func_t report)
2164 : {
2165 : const char *what;
2166 : const char *errtxt;
2167 : gcry_error_t err;
2168 2 : gcry_sexp_t skey = NULL;
2169 2 : gcry_sexp_t pkey = NULL;
2170 :
2171 2 : what = "convert";
2172 2 : err = sexp_sscan (&skey, NULL, sample_secret_key_secp256,
2173 : strlen (sample_secret_key_secp256));
2174 2 : if (!err)
2175 2 : err = sexp_sscan (&pkey, NULL, sample_public_key_secp256,
2176 : strlen (sample_public_key_secp256));
2177 2 : if (err)
2178 : {
2179 0 : errtxt = _gcry_strerror (err);
2180 0 : goto failed;
2181 : }
2182 :
2183 2 : what = "key consistency";
2184 2 : err = ecc_check_secret_key(skey);
2185 2 : if (err)
2186 : {
2187 0 : errtxt = _gcry_strerror (err);
2188 0 : goto failed;
2189 : }
2190 :
2191 2 : what = "sign";
2192 2 : errtxt = selftest_sign (pkey, skey);
2193 2 : if (errtxt)
2194 0 : goto failed;
2195 :
2196 2 : sexp_release(pkey);
2197 2 : sexp_release(skey);
2198 2 : return 0; /* Succeeded. */
2199 :
2200 : failed:
2201 0 : sexp_release(pkey);
2202 0 : sexp_release(skey);
2203 0 : if (report)
2204 0 : report ("pubkey", GCRY_PK_ECC, what, errtxt);
2205 0 : return GPG_ERR_SELFTEST_FAILED;
2206 : }
2207 :
2208 :
2209 : /* Run a full self-test for ALGO and return 0 on success. */
2210 : static gpg_err_code_t
2211 2 : run_selftests (int algo, int extended, selftest_report_func_t report)
2212 : {
2213 : (void)extended;
2214 :
2215 2 : if (algo != GCRY_PK_ECC)
2216 0 : return GPG_ERR_PUBKEY_ALGO;
2217 :
2218 2 : return selftests_ecdsa (report);
2219 : }
2220 :
2221 :
2222 :
2223 :
2224 : gcry_pk_spec_t _gcry_pubkey_spec_ecc =
2225 : {
2226 : GCRY_PK_ECC, { 0, 1 },
2227 : (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR),
2228 : "ECC", ecc_names,
2229 : "pabgnhq", "pabgnhqd", "sw", "rs", "pabgnhq",
2230 : ecc_generate,
2231 : ecc_check_secret_key,
2232 : ecc_encrypt_raw,
2233 : ecc_decrypt_raw,
2234 : ecc_sign,
2235 : ecc_verify,
2236 : ecc_get_nbits,
2237 : run_selftests,
2238 : compute_keygrip,
2239 : _gcry_ecc_get_curve,
2240 : _gcry_ecc_get_param_sexp
2241 : };
|