Line data Source code
1 : /* t-mpi-point.c - Tests for mpi point functions
2 : * Copyright (C) 2013 g10 Code GmbH
3 : *
4 : * This file is part of Libgcrypt.
5 : *
6 : * Libgcrypt is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * Libgcrypt is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #ifdef HAVE_CONFIG_H
21 : # include <config.h>
22 : #endif
23 : #include <stdio.h>
24 : #include <stdlib.h>
25 : #include <string.h>
26 : #include <assert.h>
27 : #include <stdarg.h>
28 :
29 : #include "../src/gcrypt-int.h"
30 :
31 : #define PGM "t-mpi-point"
32 :
33 : static const char *wherestr;
34 : static int verbose;
35 : static int debug;
36 : static int error_count;
37 :
38 :
39 : #define my_isascii(c) (!((c) & 0x80))
40 : #define digitp(p) (*(p) >= '0' && *(p) <= '9')
41 : #define hexdigitp(a) (digitp (a) \
42 : || (*(a) >= 'A' && *(a) <= 'F') \
43 : || (*(a) >= 'a' && *(a) <= 'f'))
44 : #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
45 : *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
46 : #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
47 : #define xmalloc(a) gcry_xmalloc ((a))
48 : #define xcalloc(a,b) gcry_xcalloc ((a),(b))
49 : #define xfree(a) gcry_free ((a))
50 : #define pass() do { ; } while (0)
51 :
52 :
53 : static struct
54 : {
55 : const char *desc; /* Description of the curve. */
56 : const char *p; /* Order of the prime field. */
57 : const char *a, *b; /* The coefficients. */
58 : const char *n; /* The order of the base point. */
59 : const char *g_x, *g_y; /* Base point. */
60 : const char *h; /* Cofactor. */
61 : } test_curve[] =
62 : {
63 : {
64 : "NIST P-192",
65 : "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
66 : "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
67 : "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
68 : "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
69 :
70 : "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
71 : "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
72 : "0x01"
73 : },
74 : {
75 : "NIST P-224",
76 : "0xffffffffffffffffffffffffffffffff000000000000000000000001",
77 : "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
78 : "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
79 : "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
80 :
81 : "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
82 : "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
83 : "0x01"
84 : },
85 : {
86 : "NIST P-256",
87 : "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
88 : "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
89 : "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
90 : "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
91 :
92 : "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
93 : "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
94 : "0x01"
95 : },
96 : {
97 : "NIST P-384",
98 : "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
99 : "ffffffff0000000000000000ffffffff",
100 : "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
101 : "ffffffff0000000000000000fffffffc",
102 : "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
103 : "c656398d8a2ed19d2a85c8edd3ec2aef",
104 : "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
105 : "581a0db248b0a77aecec196accc52973",
106 :
107 : "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
108 : "5502f25dbf55296c3a545e3872760ab7",
109 : "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
110 : "0a60b1ce1d7e819d7a431d7c90ea0e5f",
111 : "0x01"
112 : },
113 : {
114 : "NIST P-521",
115 : "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
116 : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
117 : "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
118 : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
119 : "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
120 : "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
121 : "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
122 : "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
123 :
124 : "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
125 : "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
126 : "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
127 : "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
128 : "0x01"
129 : },
130 : {
131 : "Ed25519",
132 : "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
133 : "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC",
134 : "0x52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3",
135 : "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
136 : "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
137 : "0x6666666666666666666666666666666666666666666666666666666666666658",
138 : "0x08"
139 : },
140 : { NULL, NULL, NULL, NULL, NULL, NULL }
141 : };
142 :
143 : /* A sample public key for NIST P-256. */
144 : static const char sample_p256_q[] =
145 : "04"
146 : "42B927242237639A36CE9221B340DB1A9AB76DF2FE3E171277F6A4023DED146E"
147 : "E86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E";
148 : static const char sample_p256_q_x[] =
149 : "42B927242237639A36CE9221B340DB1A9AB76DF2FE3E171277F6A4023DED146E";
150 : static const char sample_p256_q_y[] =
151 : "00E86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E";
152 :
153 :
154 : /* A sample public key for Ed25519. */
155 : static const char sample_ed25519_q[] =
156 : "04"
157 : "55d0e09a2b9d34292297e08d60d0f620c513d47253187c24b12786bd777645ce"
158 : "1a5107f7681a02af2523a6daf372e10e3a0764c9d3fe4bd5b70ab18201985ad7";
159 : static const char sample_ed25519_q_x[] =
160 : "55d0e09a2b9d34292297e08d60d0f620c513d47253187c24b12786bd777645ce";
161 : static const char sample_ed25519_q_y[] =
162 : "1a5107f7681a02af2523a6daf372e10e3a0764c9d3fe4bd5b70ab18201985ad7";
163 : static const char sample_ed25519_q_eddsa[] =
164 : "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a";
165 : static const char sample_ed25519_d[] =
166 : "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60";
167 :
168 :
169 : static void
170 9 : show (const char *format, ...)
171 : {
172 : va_list arg_ptr;
173 :
174 9 : if (!verbose)
175 18 : return;
176 0 : fprintf (stderr, "%s: ", PGM);
177 0 : va_start (arg_ptr, format);
178 0 : vfprintf (stderr, format, arg_ptr);
179 0 : va_end (arg_ptr);
180 : }
181 :
182 : static void
183 0 : fail (const char *format, ...)
184 : {
185 : va_list arg_ptr;
186 :
187 0 : fflush (stdout);
188 0 : fprintf (stderr, "%s: ", PGM);
189 0 : if (wherestr)
190 0 : fprintf (stderr, "%s: ", wherestr);
191 0 : va_start (arg_ptr, format);
192 0 : vfprintf (stderr, format, arg_ptr);
193 0 : va_end (arg_ptr);
194 0 : error_count++;
195 0 : }
196 :
197 : static void
198 0 : die (const char *format, ...)
199 : {
200 : va_list arg_ptr;
201 :
202 0 : fflush (stdout);
203 0 : fprintf (stderr, "%s: ", PGM);
204 0 : if (wherestr)
205 0 : fprintf (stderr, "%s: ", wherestr);
206 0 : va_start (arg_ptr, format);
207 0 : vfprintf (stderr, format, arg_ptr);
208 0 : va_end (arg_ptr);
209 0 : exit (1);
210 : }
211 :
212 :
213 : static void
214 0 : print_mpi_2 (const char *text, const char *text2, gcry_mpi_t a)
215 : {
216 : gcry_error_t err;
217 : char *buf;
218 0 : void *bufaddr = &buf;
219 :
220 0 : err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
221 0 : if (err)
222 0 : fprintf (stderr, "%s%s: [error printing number: %s]\n",
223 : text, text2? text2:"", gpg_strerror (err));
224 : else
225 : {
226 0 : fprintf (stderr, "%s%s: %s\n", text, text2? text2:"", buf);
227 0 : gcry_free (buf);
228 : }
229 0 : }
230 :
231 :
232 : static void
233 0 : print_mpi (const char *text, gcry_mpi_t a)
234 : {
235 0 : print_mpi_2 (text, NULL, a);
236 0 : }
237 :
238 :
239 : static void
240 0 : print_point (const char *text, gcry_mpi_point_t a)
241 : {
242 : gcry_mpi_t x, y, z;
243 :
244 0 : x = gcry_mpi_new (0);
245 0 : y = gcry_mpi_new (0);
246 0 : z = gcry_mpi_new (0);
247 0 : gcry_mpi_point_get (x, y, z, a);
248 0 : print_mpi_2 (text, ".x", x);
249 0 : print_mpi_2 (text, ".y", y);
250 0 : print_mpi_2 (text, ".z", z);
251 0 : gcry_mpi_release (x);
252 0 : gcry_mpi_release (y);
253 0 : gcry_mpi_release (z);
254 0 : }
255 :
256 :
257 : static void
258 0 : print_sexp (const char *prefix, gcry_sexp_t a)
259 : {
260 : char *buf;
261 : size_t size;
262 :
263 0 : if (prefix)
264 0 : fputs (prefix, stderr);
265 0 : size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
266 0 : buf = gcry_xmalloc (size);
267 :
268 0 : gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
269 0 : fprintf (stderr, "%.*s", (int)size, buf);
270 0 : gcry_free (buf);
271 0 : }
272 :
273 :
274 : static gcry_mpi_t
275 100 : hex2mpi (const char *string)
276 : {
277 : gpg_error_t err;
278 : gcry_mpi_t val;
279 :
280 100 : err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
281 100 : if (err)
282 0 : die ("hex2mpi '%s' failed: %s\n", string, gpg_strerror (err));
283 100 : return val;
284 : }
285 :
286 :
287 : /* Convert STRING consisting of hex characters into its binary
288 : representation and return it as an allocated buffer. The valid
289 : length of the buffer is returned at R_LENGTH. The string is
290 : delimited by end of string. The function returns NULL on
291 : error. */
292 : static void *
293 2 : hex2buffer (const char *string, size_t *r_length)
294 : {
295 : const char *s;
296 : unsigned char *buffer;
297 : size_t length;
298 :
299 2 : buffer = xmalloc (strlen(string)/2+1);
300 2 : length = 0;
301 99 : for (s=string; *s; s +=2 )
302 : {
303 97 : if (!hexdigitp (s) || !hexdigitp (s+1))
304 0 : return NULL; /* Invalid hex digits. */
305 97 : ((unsigned char*)buffer)[length++] = xtoi_2 (s);
306 : }
307 2 : *r_length = length;
308 2 : return buffer;
309 : }
310 :
311 :
312 : static gcry_mpi_t
313 2 : hex2mpiopa (const char *string)
314 : {
315 : char *buffer;
316 : size_t buflen;
317 : gcry_mpi_t val;
318 :
319 2 : buffer = hex2buffer (string, &buflen);
320 2 : if (!buffer)
321 0 : die ("hex2mpiopa '%s' failed: parser error\n", string);
322 2 : val = gcry_mpi_set_opaque (NULL, buffer, buflen*8);
323 2 : if (!buffer)
324 0 : die ("hex2mpiopa '%s' failed: set_opaque error%s\n", string);
325 2 : return val;
326 : }
327 :
328 :
329 : /* Compare A to B, where B is given as a hex string. */
330 : static int
331 86 : cmp_mpihex (gcry_mpi_t a, const char *b)
332 : {
333 : gcry_mpi_t bval;
334 : int res;
335 :
336 86 : if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
337 1 : bval = hex2mpiopa (b);
338 : else
339 85 : bval = hex2mpi (b);
340 86 : res = gcry_mpi_cmp (a, bval);
341 86 : gcry_mpi_release (bval);
342 86 : return res;
343 : }
344 :
345 :
346 : /* Wrapper to emulate the libgcrypt internal EC context allocation
347 : function. */
348 : static gpg_error_t
349 4 : ec_p_new (gcry_ctx_t *r_ctx, gcry_mpi_t p, gcry_mpi_t a)
350 : {
351 : gpg_error_t err;
352 : gcry_sexp_t sexp;
353 :
354 4 : if (p && a)
355 2 : err = gcry_sexp_build (&sexp, NULL, "(ecdsa (p %m)(a %m))", p, a);
356 2 : else if (p)
357 0 : err = gcry_sexp_build (&sexp, NULL, "(ecdsa (p %m))", p);
358 2 : else if (a)
359 1 : err = gcry_sexp_build (&sexp, NULL, "(ecdsa (a %m))", a);
360 : else
361 1 : err = gcry_sexp_build (&sexp, NULL, "(ecdsa)");
362 4 : if (err)
363 0 : return err;
364 4 : err = gcry_mpi_ec_new (r_ctx, sexp, NULL);
365 4 : gcry_sexp_release (sexp);
366 4 : return err;
367 : }
368 :
369 :
370 :
371 : static void
372 1 : set_get_point (void)
373 : {
374 : gcry_mpi_point_t point;
375 : gcry_mpi_t x, y, z;
376 :
377 1 : wherestr = "set_get_point";
378 1 : show ("checking point setting functions\n");
379 :
380 1 : point = gcry_mpi_point_new (0);
381 1 : x = gcry_mpi_set_ui (NULL, 17);
382 1 : y = gcry_mpi_set_ui (NULL, 42);
383 1 : z = gcry_mpi_set_ui (NULL, 11371);
384 1 : gcry_mpi_point_get (x, y, z, point);
385 1 : if (gcry_mpi_cmp_ui (x, 0)
386 1 : || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0))
387 0 : fail ("new point not initialized to (0,0,0)\n");
388 1 : gcry_mpi_point_snatch_get (x, y, z, point);
389 1 : point = NULL;
390 1 : if (gcry_mpi_cmp_ui (x, 0)
391 1 : || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0))
392 0 : fail ("snatch_get failed\n");
393 1 : gcry_mpi_release (x);
394 1 : gcry_mpi_release (y);
395 1 : gcry_mpi_release (z);
396 :
397 1 : point = gcry_mpi_point_new (0);
398 1 : x = gcry_mpi_set_ui (NULL, 17);
399 1 : y = gcry_mpi_set_ui (NULL, 42);
400 1 : z = gcry_mpi_set_ui (NULL, 11371);
401 1 : gcry_mpi_point_set (point, x, y, z);
402 1 : gcry_mpi_set_ui (x, 23);
403 1 : gcry_mpi_set_ui (y, 24);
404 1 : gcry_mpi_set_ui (z, 25);
405 1 : gcry_mpi_point_get (x, y, z, point);
406 1 : if (gcry_mpi_cmp_ui (x, 17)
407 1 : || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
408 0 : fail ("point_set/point_get failed\n");
409 1 : gcry_mpi_point_snatch_set (point, x, y, z);
410 1 : x = gcry_mpi_new (0);
411 1 : y = gcry_mpi_new (0);
412 1 : z = gcry_mpi_new (0);
413 1 : gcry_mpi_point_get (x, y, z, point);
414 1 : if (gcry_mpi_cmp_ui (x, 17)
415 1 : || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
416 0 : fail ("point_snatch_set/point_get failed\n");
417 :
418 1 : gcry_mpi_point_release (point);
419 1 : gcry_mpi_release (x);
420 1 : gcry_mpi_release (y);
421 1 : gcry_mpi_release (z);
422 1 : }
423 :
424 :
425 : static void
426 1 : context_alloc (void)
427 : {
428 : gpg_error_t err;
429 : gcry_ctx_t ctx;
430 : gcry_mpi_t p, a;
431 :
432 1 : wherestr = "context_alloc";
433 1 : show ("checking context functions\n");
434 :
435 1 : p = gcry_mpi_set_ui (NULL, 1);
436 1 : a = gcry_mpi_set_ui (NULL, 1);
437 1 : err = ec_p_new (&ctx, p, a);
438 1 : if (err)
439 0 : die ("ec_p_new returned an error: %s\n", gpg_strerror (err));
440 1 : gcry_mpi_release (p);
441 1 : gcry_mpi_release (a);
442 1 : gcry_ctx_release (ctx);
443 :
444 1 : p = NULL;
445 1 : a = gcry_mpi_set_ui (NULL, 0);
446 :
447 1 : err = ec_p_new (&ctx, p, a);
448 1 : if (!err || gpg_err_code (err) != GPG_ERR_EINVAL)
449 0 : fail ("ec_p_new: bad parameter detection failed (1)\n");
450 :
451 1 : gcry_mpi_release (a);
452 1 : a = NULL;
453 1 : err = ec_p_new (&ctx, p, a);
454 1 : if (!err || gpg_err_code (err) != GPG_ERR_EINVAL)
455 0 : fail ("ec_p_new: bad parameter detection failed (2)\n");
456 :
457 1 : }
458 :
459 :
460 : static int
461 48 : get_and_cmp_mpi (const char *name, const char *mpistring, const char *desc,
462 : gcry_ctx_t ctx)
463 : {
464 : gcry_mpi_t mpi;
465 :
466 48 : mpi = gcry_mpi_ec_get_mpi (name, ctx, 1);
467 48 : if (!mpi)
468 : {
469 0 : fail ("error getting parameter '%s' of curve '%s'\n", name, desc);
470 0 : return 1;
471 : }
472 48 : if (debug)
473 0 : print_mpi (name, mpi);
474 48 : if (cmp_mpihex (mpi, mpistring))
475 : {
476 0 : fail ("parameter '%s' of curve '%s' does not match\n", name, desc);
477 0 : gcry_mpi_release (mpi);
478 0 : return 1;
479 : }
480 48 : gcry_mpi_release (mpi);
481 48 : return 0;
482 : }
483 :
484 :
485 : static int
486 8 : get_and_cmp_point (const char *name,
487 : const char *mpi_x_string, const char *mpi_y_string,
488 : const char *desc, gcry_ctx_t ctx)
489 : {
490 : gcry_mpi_point_t point;
491 : gcry_mpi_t x, y, z;
492 8 : int result = 0;
493 :
494 8 : point = gcry_mpi_ec_get_point (name, ctx, 1);
495 8 : if (!point)
496 : {
497 0 : fail ("error getting point parameter '%s' of curve '%s'\n", name, desc);
498 0 : return 1;
499 : }
500 8 : if (debug)
501 0 : print_point (name, point);
502 :
503 8 : x = gcry_mpi_new (0);
504 8 : y = gcry_mpi_new (0);
505 8 : z = gcry_mpi_new (0);
506 8 : gcry_mpi_point_snatch_get (x, y, z, point);
507 8 : if (cmp_mpihex (x, mpi_x_string))
508 : {
509 0 : fail ("x coordinate of '%s' of curve '%s' does not match\n", name, desc);
510 0 : result = 1;
511 : }
512 8 : if (cmp_mpihex (y, mpi_y_string))
513 : {
514 0 : fail ("y coordinate of '%s' of curve '%s' does not match\n", name, desc);
515 0 : result = 1;
516 : }
517 8 : if (cmp_mpihex (z, "01"))
518 : {
519 0 : fail ("z coordinate of '%s' of curve '%s' is not 1\n", name, desc);
520 0 : result = 1;
521 : }
522 8 : gcry_mpi_release (x);
523 8 : gcry_mpi_release (y);
524 8 : gcry_mpi_release (z);
525 8 : return result;
526 : }
527 :
528 :
529 : static void
530 1 : context_param (void)
531 : {
532 : gpg_error_t err;
533 : int idx;
534 1 : gcry_ctx_t ctx = NULL;
535 : gcry_mpi_t q, d;
536 : gcry_sexp_t keyparam;
537 :
538 1 : wherestr = "context_param";
539 :
540 1 : show ("checking standard curves\n");
541 7 : for (idx=0; test_curve[idx].desc; idx++)
542 : {
543 : /* P-192 and Ed25519 are not supported in fips mode */
544 6 : if (gcry_fips_mode_active())
545 : {
546 0 : if (!strcmp(test_curve[idx].desc, "NIST P-192")
547 0 : || !strcmp(test_curve[idx].desc, "Ed25519"))
548 : {
549 0 : show("skipping %s in fips mode\n", test_curve[idx].desc );
550 0 : continue;
551 : }
552 : }
553 :
554 6 : gcry_ctx_release (ctx);
555 6 : err = gcry_mpi_ec_new (&ctx, NULL, test_curve[idx].desc);
556 6 : if (err)
557 : {
558 0 : fail ("can't create context for curve '%s': %s\n",
559 : test_curve[idx].desc, gpg_strerror (err));
560 0 : continue;
561 : }
562 6 : if (get_and_cmp_mpi ("p", test_curve[idx].p, test_curve[idx].desc, ctx))
563 0 : continue;
564 6 : if (get_and_cmp_mpi ("a", test_curve[idx].a, test_curve[idx].desc, ctx))
565 0 : continue;
566 6 : if (get_and_cmp_mpi ("b", test_curve[idx].b, test_curve[idx].desc, ctx))
567 0 : continue;
568 6 : if (get_and_cmp_mpi ("g.x",test_curve[idx].g_x, test_curve[idx].desc,ctx))
569 0 : continue;
570 6 : if (get_and_cmp_mpi ("g.y",test_curve[idx].g_y, test_curve[idx].desc,ctx))
571 0 : continue;
572 6 : if (get_and_cmp_mpi ("n", test_curve[idx].n, test_curve[idx].desc, ctx))
573 0 : continue;
574 6 : if (get_and_cmp_point ("g", test_curve[idx].g_x, test_curve[idx].g_y,
575 : test_curve[idx].desc, ctx))
576 0 : continue;
577 6 : if (get_and_cmp_mpi ("h", test_curve[idx].h, test_curve[idx].desc, ctx))
578 0 : continue;
579 :
580 : }
581 :
582 1 : show ("checking sample public key (nistp256)\n");
583 1 : q = hex2mpi (sample_p256_q);
584 1 : err = gcry_sexp_build (&keyparam, NULL,
585 : "(public-key(ecc(curve %s)(q %m)))",
586 : "NIST P-256", q);
587 1 : if (err)
588 0 : die ("gcry_sexp_build failed: %s\n", gpg_strerror (err));
589 1 : gcry_mpi_release (q);
590 :
591 : /* We can't call gcry_pk_testkey because it is only implemented for
592 : private keys. */
593 : /* err = gcry_pk_testkey (keyparam); */
594 : /* if (err) */
595 : /* fail ("gcry_pk_testkey failed for sample public key: %s\n", */
596 : /* gpg_strerror (err)); */
597 :
598 1 : gcry_ctx_release (ctx);
599 1 : err = gcry_mpi_ec_new (&ctx, keyparam, NULL);
600 1 : if (err)
601 0 : fail ("gcry_mpi_ec_new failed for sample public key (nistp256): %s\n",
602 : gpg_strerror (err));
603 : else
604 : {
605 : gcry_sexp_t sexp;
606 :
607 1 : get_and_cmp_mpi ("q", sample_p256_q, "nistp256", ctx);
608 1 : get_and_cmp_point ("q", sample_p256_q_x, sample_p256_q_y, "nistp256",
609 : ctx);
610 :
611 : /* Delete Q. */
612 1 : err = gcry_mpi_ec_set_mpi ("q", NULL, ctx);
613 1 : if (err)
614 0 : fail ("clearing Q for nistp256 failed: %s\n", gpg_strerror (err));
615 1 : if (gcry_mpi_ec_get_mpi ("q", ctx, 0))
616 0 : fail ("clearing Q for nistp256 did not work\n");
617 :
618 : /* Set Q again. */
619 1 : q = hex2mpi (sample_p256_q);
620 1 : err = gcry_mpi_ec_set_mpi ("q", q, ctx);
621 1 : if (err)
622 0 : fail ("setting Q for nistp256 failed: %s\n", gpg_strerror (err));
623 1 : get_and_cmp_mpi ("q", sample_p256_q, "nistp256(2)", ctx);
624 1 : gcry_mpi_release (q);
625 :
626 : /* Get as s-expression. */
627 1 : err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
628 1 : if (err)
629 0 : fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
630 1 : else if (debug)
631 0 : print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
632 1 : gcry_sexp_release (sexp);
633 :
634 1 : err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
635 1 : if (err)
636 0 : fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n",
637 : gpg_strerror (err));
638 1 : else if (debug)
639 0 : print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
640 1 : gcry_sexp_release (sexp);
641 :
642 1 : err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
643 1 : if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
644 0 : fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
645 : gpg_strerror (err));
646 1 : gcry_sexp_release (sexp);
647 : }
648 :
649 : /* Skipping Ed25519 if in FIPS mode (it isn't supported) */
650 1 : if (gcry_fips_mode_active())
651 0 : goto cleanup;
652 :
653 1 : show ("checking sample public key (Ed25519)\n");
654 1 : q = hex2mpi (sample_ed25519_q);
655 1 : gcry_sexp_release (keyparam);
656 1 : err = gcry_sexp_build (&keyparam, NULL,
657 : "(public-key(ecc(curve %s)(flags eddsa)(q %m)))",
658 : "Ed25519", q);
659 1 : if (err)
660 0 : die ("gcry_sexp_build failed: %s\n", gpg_strerror (err));
661 1 : gcry_mpi_release (q);
662 :
663 : /* We can't call gcry_pk_testkey because it is only implemented for
664 : private keys. */
665 : /* err = gcry_pk_testkey (keyparam); */
666 : /* if (err) */
667 : /* fail ("gcry_pk_testkey failed for sample public key: %s\n", */
668 : /* gpg_strerror (err)); */
669 :
670 1 : gcry_ctx_release (ctx);
671 1 : err = gcry_mpi_ec_new (&ctx, keyparam, NULL);
672 1 : if (err)
673 0 : fail ("gcry_mpi_ec_new failed for sample public key: %s\n",
674 : gpg_strerror (err));
675 : else
676 : {
677 : gcry_sexp_t sexp;
678 :
679 1 : get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519", ctx);
680 1 : get_and_cmp_point ("q", sample_ed25519_q_x, sample_ed25519_q_y,
681 : "Ed25519", ctx);
682 1 : get_and_cmp_mpi ("q@eddsa", sample_ed25519_q_eddsa, "Ed25519", ctx);
683 :
684 : /* Set d to see whether Q is correctly re-computed. */
685 1 : d = hex2mpi (sample_ed25519_d);
686 1 : err = gcry_mpi_ec_set_mpi ("d", d, ctx);
687 1 : if (err)
688 0 : fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err));
689 1 : gcry_mpi_release (d);
690 1 : get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(recompute Q)", ctx);
691 :
692 : /* Delete Q by setting d and then clearing d. The clearing is
693 : required so that we can check whether Q has been cleared and
694 : because further tests only expect a public key. */
695 1 : d = hex2mpi (sample_ed25519_d);
696 1 : err = gcry_mpi_ec_set_mpi ("d", d, ctx);
697 1 : if (err)
698 0 : fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err));
699 1 : gcry_mpi_release (d);
700 1 : err = gcry_mpi_ec_set_mpi ("d", NULL, ctx);
701 1 : if (err)
702 0 : fail ("setting d for Ed25519 failed(2): %s\n", gpg_strerror (err));
703 1 : if (gcry_mpi_ec_get_mpi ("q", ctx, 0))
704 0 : fail ("setting d for Ed25519 did not reset Q\n");
705 :
706 : /* Set Q again. We need to use an opaque MPI here because
707 : sample_ed25519_q is in uncompressed format which can only be
708 : auto-detected if passed opaque. */
709 1 : q = hex2mpiopa (sample_ed25519_q);
710 1 : err = gcry_mpi_ec_set_mpi ("q", q, ctx);
711 1 : if (err)
712 0 : fail ("setting Q for Ed25519 failed: %s\n", gpg_strerror (err));
713 1 : gcry_mpi_release (q);
714 1 : get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(2)", ctx);
715 :
716 : /* Get as s-expression. */
717 1 : err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
718 1 : if (err)
719 0 : fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
720 1 : else if (debug)
721 0 : print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
722 1 : gcry_sexp_release (sexp);
723 :
724 1 : err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
725 1 : if (err)
726 0 : fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n",
727 : gpg_strerror (err));
728 1 : else if (debug)
729 0 : print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
730 1 : gcry_sexp_release (sexp);
731 :
732 1 : err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
733 1 : if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
734 0 : fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
735 : gpg_strerror (err));
736 1 : gcry_sexp_release (sexp);
737 :
738 : }
739 :
740 : cleanup:
741 1 : gcry_ctx_release (ctx);
742 1 : gcry_sexp_release (keyparam);
743 1 : }
744 :
745 :
746 :
747 :
748 : /* Create a new point from (X,Y,Z) given as hex strings. */
749 : gcry_mpi_point_t
750 1 : make_point (const char *x, const char *y, const char *z)
751 : {
752 : gcry_mpi_point_t point;
753 :
754 1 : point = gcry_mpi_point_new (0);
755 1 : gcry_mpi_point_snatch_set (point, hex2mpi (x), hex2mpi (y), hex2mpi (z));
756 :
757 1 : return point;
758 : }
759 :
760 :
761 : /* This tests checks that the low-level EC API yields the same result
762 : as using the high level API. The values have been taken from a
763 : test run using the high level API. */
764 : static void
765 1 : basic_ec_math (void)
766 : {
767 : gpg_error_t err;
768 : gcry_ctx_t ctx;
769 : gcry_mpi_t P, A;
770 : gcry_mpi_point_t G, Q;
771 : gcry_mpi_t d;
772 : gcry_mpi_t x, y, z;
773 :
774 1 : wherestr = "basic_ec_math";
775 1 : show ("checking basic math functions for EC\n");
776 :
777 1 : P = hex2mpi ("0xfffffffffffffffffffffffffffffffeffffffffffffffff");
778 1 : A = hex2mpi ("0xfffffffffffffffffffffffffffffffefffffffffffffffc");
779 1 : G = make_point ("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
780 : "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
781 : "1");
782 1 : d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
783 1 : Q = gcry_mpi_point_new (0);
784 :
785 1 : err = ec_p_new (&ctx, P, A);
786 1 : if (err)
787 0 : die ("ec_p_new failed: %s\n", gpg_strerror (err));
788 :
789 1 : x = gcry_mpi_new (0);
790 1 : y = gcry_mpi_new (0);
791 1 : z = gcry_mpi_new (0);
792 :
793 : {
794 : /* A quick check that multiply by zero works. */
795 : gcry_mpi_t tmp;
796 :
797 1 : tmp = gcry_mpi_new (0);
798 1 : gcry_mpi_ec_mul (Q, tmp, G, ctx);
799 1 : gcry_mpi_release (tmp);
800 1 : gcry_mpi_point_get (x, y, z, Q);
801 1 : if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 0)
802 1 : || gcry_mpi_cmp_ui (z, 0))
803 0 : fail ("multiply a point by zero failed\n");
804 : }
805 :
806 1 : gcry_mpi_ec_mul (Q, d, G, ctx);
807 1 : gcry_mpi_point_get (x, y, z, Q);
808 1 : if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
809 1 : || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
810 1 : || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
811 0 : fail ("computed public key does not match\n");
812 1 : if (debug)
813 : {
814 0 : print_mpi ("Q.x", x);
815 0 : print_mpi ("Q.y", y);
816 0 : print_mpi ("Q.z", z);
817 : }
818 :
819 1 : if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
820 0 : fail ("failed to get affine coordinates\n");
821 1 : if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
822 1 : || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
823 0 : fail ("computed affine coordinates of public key do not match\n");
824 1 : if (debug)
825 : {
826 0 : print_mpi ("q.x", x);
827 0 : print_mpi ("q.y", y);
828 : }
829 :
830 1 : gcry_mpi_release (z);
831 1 : gcry_mpi_release (y);
832 1 : gcry_mpi_release (x);
833 1 : gcry_mpi_point_release (Q);
834 1 : gcry_mpi_release (d);
835 1 : gcry_mpi_point_release (G);
836 1 : gcry_mpi_release (A);
837 1 : gcry_mpi_release (P);
838 1 : gcry_ctx_release (ctx);
839 1 : }
840 :
841 :
842 : /* This is the same as basic_ec_math but uses more advanced
843 : features. */
844 : static void
845 1 : basic_ec_math_simplified (void)
846 : {
847 : gpg_error_t err;
848 : gcry_ctx_t ctx;
849 : gcry_mpi_point_t G, Q;
850 : gcry_mpi_t d;
851 : gcry_mpi_t x, y, z;
852 : gcry_sexp_t sexp;
853 :
854 1 : wherestr = "basic_ec_math_simplified";
855 1 : show ("checking basic math functions for EC (variant)\n");
856 :
857 1 : d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
858 1 : Q = gcry_mpi_point_new (0);
859 :
860 1 : err = gcry_mpi_ec_new (&ctx, NULL, "NIST P-192");
861 1 : if (err)
862 0 : die ("gcry_mpi_ec_new failed: %s\n", gpg_strerror (err));
863 1 : G = gcry_mpi_ec_get_point ("g", ctx, 1);
864 1 : if (!G)
865 0 : die ("gcry_mpi_ec_get_point(G) failed\n");
866 1 : gcry_mpi_ec_mul (Q, d, G, ctx);
867 :
868 1 : x = gcry_mpi_new (0);
869 1 : y = gcry_mpi_new (0);
870 1 : z = gcry_mpi_new (0);
871 1 : gcry_mpi_point_get (x, y, z, Q);
872 1 : if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
873 1 : || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
874 1 : || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
875 0 : fail ("computed public key does not match\n");
876 1 : if (debug)
877 : {
878 0 : print_mpi ("Q.x", x);
879 0 : print_mpi ("Q.y", y);
880 0 : print_mpi ("Q.z", z);
881 : }
882 :
883 1 : if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
884 0 : fail ("failed to get affine coordinates\n");
885 1 : if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
886 1 : || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
887 0 : fail ("computed affine coordinates of public key do not match\n");
888 1 : if (debug)
889 : {
890 0 : print_mpi ("q.x", x);
891 0 : print_mpi ("q.y", y);
892 : }
893 :
894 1 : gcry_mpi_release (z);
895 1 : gcry_mpi_release (y);
896 1 : gcry_mpi_release (x);
897 :
898 : /* Let us also check whether we can update the context. */
899 1 : err = gcry_mpi_ec_set_point ("g", G, ctx);
900 1 : if (err)
901 0 : die ("gcry_mpi_ec_set_point(G) failed\n");
902 1 : err = gcry_mpi_ec_set_mpi ("d", d, ctx);
903 1 : if (err)
904 0 : die ("gcry_mpi_ec_set_mpi(d) failed\n");
905 :
906 : /* FIXME: Below we need to check that the returned S-expression is
907 : as requested. For now we use manual inspection using --debug. */
908 :
909 : /* Does get_sexp return the private key? */
910 1 : err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
911 1 : if (err)
912 0 : fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
913 1 : else if (debug)
914 0 : print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
915 1 : gcry_sexp_release (sexp);
916 :
917 : /* Does get_sexp return the public key if requested? */
918 1 : err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
919 1 : if (err)
920 0 : fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n", gpg_strerror (err));
921 1 : else if (debug)
922 0 : print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
923 1 : gcry_sexp_release (sexp);
924 :
925 : /* Does get_sexp return the public key after d has been deleted? */
926 1 : err = gcry_mpi_ec_set_mpi ("d", NULL, ctx);
927 1 : if (err)
928 0 : die ("gcry_mpi_ec_set_mpi(d=NULL) failed\n");
929 1 : err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
930 1 : if (err)
931 0 : fail ("gcry_pubkey_get_sexp(0 w/o d) failed: %s\n", gpg_strerror (err));
932 1 : else if (debug)
933 0 : print_sexp ("Result of gcry_pubkey_get_sexp (0 w/o d):\n", sexp);
934 1 : gcry_sexp_release (sexp);
935 :
936 : /* Does get_sexp return an error after d has been deleted? */
937 1 : err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
938 1 : if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
939 0 : fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
940 : gpg_strerror (err));
941 1 : gcry_sexp_release (sexp);
942 :
943 : /* Does get_sexp return an error after d and Q have been deleted? */
944 1 : err = gcry_mpi_ec_set_point ("q", NULL, ctx);
945 1 : if (err)
946 0 : die ("gcry_mpi_ec_set_point(q=NULL) failed\n");
947 1 : err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
948 1 : if (gpg_err_code (err) != GPG_ERR_BAD_CRYPT_CTX)
949 0 : fail ("gcry_pubkey_get_sexp(0 w/o Q,d) returned wrong error: %s\n",
950 : gpg_strerror (err));
951 1 : gcry_sexp_release (sexp);
952 :
953 :
954 1 : gcry_mpi_point_release (Q);
955 1 : gcry_mpi_release (d);
956 1 : gcry_mpi_point_release (G);
957 1 : gcry_ctx_release (ctx);
958 1 : }
959 :
960 :
961 : /* Check the math used with Twisted Edwards curves. */
962 : static void
963 1 : twistededwards_math (void)
964 : {
965 : gpg_error_t err;
966 : gcry_ctx_t ctx;
967 : gcry_mpi_point_t G, Q;
968 : gcry_mpi_t k;
969 : gcry_mpi_t w, a, x, y, z, p, n, b, I;
970 :
971 1 : wherestr = "twistededwards_math";
972 1 : show ("checking basic Twisted Edwards math\n");
973 :
974 1 : err = gcry_mpi_ec_new (&ctx, NULL, "Ed25519");
975 1 : if (err)
976 0 : die ("gcry_mpi_ec_new failed: %s\n", gpg_strerror (err));
977 :
978 1 : k = hex2mpi
979 : ("2D3501E723239632802454EE5DDC406EFB0BDF18486A5BDE9C0390A9C2984004"
980 : "F47252B628C953625B8DEB5DBCB8DA97AA43A1892D11FA83596F42E0D89CB1B6");
981 1 : G = gcry_mpi_ec_get_point ("g", ctx, 1);
982 1 : if (!G)
983 0 : die ("gcry_mpi_ec_get_point(G) failed\n");
984 1 : Q = gcry_mpi_point_new (0);
985 :
986 :
987 1 : w = gcry_mpi_new (0);
988 1 : a = gcry_mpi_new (0);
989 1 : x = gcry_mpi_new (0);
990 1 : y = gcry_mpi_new (0);
991 1 : z = gcry_mpi_new (0);
992 1 : I = gcry_mpi_new (0);
993 1 : p = gcry_mpi_ec_get_mpi ("p", ctx, 1);
994 1 : n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
995 1 : b = gcry_mpi_ec_get_mpi ("b", ctx, 1);
996 :
997 : /* Check: 2^{p-1} mod p == 1 */
998 1 : gcry_mpi_sub_ui (a, p, 1);
999 1 : gcry_mpi_powm (w, GCRYMPI_CONST_TWO, a, p);
1000 1 : if (gcry_mpi_cmp_ui (w, 1))
1001 0 : fail ("failed assertion: 2^{p-1} mod p == 1\n");
1002 :
1003 : /* Check: p % 4 == 1 */
1004 1 : gcry_mpi_mod (w, p, GCRYMPI_CONST_FOUR);
1005 1 : if (gcry_mpi_cmp_ui (w, 1))
1006 0 : fail ("failed assertion: p % 4 == 1\n");
1007 :
1008 : /* Check: 2^{n-1} mod n == 1 */
1009 1 : gcry_mpi_sub_ui (a, n, 1);
1010 1 : gcry_mpi_powm (w, GCRYMPI_CONST_TWO, a, n);
1011 1 : if (gcry_mpi_cmp_ui (w, 1))
1012 0 : fail ("failed assertion: 2^{n-1} mod n == 1\n");
1013 :
1014 : /* Check: b^{(p-1)/2} mod p == p-1 */
1015 1 : gcry_mpi_sub_ui (a, p, 1);
1016 1 : gcry_mpi_div (x, NULL, a, GCRYMPI_CONST_TWO, -1);
1017 1 : gcry_mpi_powm (w, b, x, p);
1018 1 : gcry_mpi_abs (w);
1019 1 : if (gcry_mpi_cmp (w, a))
1020 0 : fail ("failed assertion: b^{(p-1)/2} mod p == p-1\n");
1021 :
1022 : /* I := 2^{(p-1)/4} mod p */
1023 1 : gcry_mpi_sub_ui (a, p, 1);
1024 1 : gcry_mpi_div (x, NULL, a, GCRYMPI_CONST_FOUR, -1);
1025 1 : gcry_mpi_powm (I, GCRYMPI_CONST_TWO, x, p);
1026 :
1027 : /* Check: I^2 mod p == p-1 */
1028 1 : gcry_mpi_powm (w, I, GCRYMPI_CONST_TWO, p);
1029 1 : if (gcry_mpi_cmp (w, a))
1030 0 : fail ("failed assertion: I^2 mod p == p-1\n");
1031 :
1032 : /* Check: G is on the curve */
1033 1 : if (!gcry_mpi_ec_curve_point (G, ctx))
1034 0 : fail ("failed assertion: G is on the curve\n");
1035 :
1036 : /* Check: nG == (0,1) */
1037 1 : gcry_mpi_ec_mul (Q, n, G, ctx);
1038 1 : if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
1039 0 : fail ("failed to get affine coordinates\n");
1040 1 : if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 1))
1041 0 : fail ("failed assertion: nG == (0,1)\n");
1042 :
1043 : /* Now two arbitrary point operations taken from the ed25519.py
1044 : sample data. */
1045 1 : gcry_mpi_release (a);
1046 1 : a = hex2mpi
1047 : ("4f71d012df3c371af3ea4dc38385ca5bb7272f90cb1b008b3ed601c76de1d496"
1048 : "e30cbf625f0a756a678d8f256d5325595cccc83466f36db18f0178eb9925edd3");
1049 1 : gcry_mpi_ec_mul (Q, a, G, ctx);
1050 1 : if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
1051 0 : fail ("failed to get affine coordinates\n");
1052 1 : if (cmp_mpihex (x, ("157f7361c577aad36f67ed33e38dc7be"
1053 : "00014fecc2165ca5cee9eee19fe4d2c1"))
1054 1 : || cmp_mpihex (y, ("5a69dbeb232276b38f3f5016547bb2a2"
1055 : "4025645f0b820e72b8cad4f0a909a092")))
1056 : {
1057 0 : fail ("sample point multiply failed:\n");
1058 0 : print_mpi ("r", a);
1059 0 : print_mpi ("Rx", x);
1060 0 : print_mpi ("Ry", y);
1061 : }
1062 :
1063 1 : gcry_mpi_release (a);
1064 1 : a = hex2mpi
1065 : ("2d3501e723239632802454ee5ddc406efb0bdf18486a5bde9c0390a9c2984004"
1066 : "f47252b628c953625b8deb5dbcb8da97aa43a1892d11fa83596f42e0d89cb1b6");
1067 1 : gcry_mpi_ec_mul (Q, a, G, ctx);
1068 1 : if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
1069 0 : fail ("failed to get affine coordinates\n");
1070 1 : if (cmp_mpihex (x, ("6218e309d40065fcc338b3127f468371"
1071 : "82324bd01ce6f3cf81ab44e62959c82a"))
1072 1 : || cmp_mpihex (y, ("5501492265e073d874d9e5b81e7f8784"
1073 : "8a826e80cce2869072ac60c3004356e5")))
1074 : {
1075 0 : fail ("sample point multiply failed:\n");
1076 0 : print_mpi ("r", a);
1077 0 : print_mpi ("Rx", x);
1078 0 : print_mpi ("Ry", y);
1079 : }
1080 :
1081 :
1082 1 : gcry_mpi_release (I);
1083 1 : gcry_mpi_release (b);
1084 1 : gcry_mpi_release (n);
1085 1 : gcry_mpi_release (p);
1086 1 : gcry_mpi_release (w);
1087 1 : gcry_mpi_release (a);
1088 1 : gcry_mpi_release (x);
1089 1 : gcry_mpi_release (y);
1090 1 : gcry_mpi_release (z);
1091 1 : gcry_mpi_point_release (Q);
1092 1 : gcry_mpi_point_release (G);
1093 1 : gcry_mpi_release (k);
1094 1 : gcry_ctx_release (ctx);
1095 1 : }
1096 :
1097 :
1098 : int
1099 1 : main (int argc, char **argv)
1100 : {
1101 :
1102 1 : if (argc > 1 && !strcmp (argv[1], "--verbose"))
1103 0 : verbose = 1;
1104 1 : else if (argc > 1 && !strcmp (argv[1], "--debug"))
1105 0 : verbose = debug = 1;
1106 :
1107 1 : if (!gcry_check_version (GCRYPT_VERSION))
1108 0 : die ("version mismatch\n");
1109 :
1110 1 : gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
1111 1 : gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
1112 1 : if (debug)
1113 0 : gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
1114 1 : gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
1115 :
1116 1 : set_get_point ();
1117 1 : context_alloc ();
1118 1 : context_param ();
1119 1 : basic_ec_math ();
1120 :
1121 : /* The tests are for P-192 and ed25519 which are not supported in
1122 : FIPS mode. */
1123 1 : if (!gcry_fips_mode_active())
1124 : {
1125 1 : basic_ec_math_simplified ();
1126 1 : twistededwards_math ();
1127 : }
1128 :
1129 1 : show ("All tests completed. Errors: %d\n", error_count);
1130 1 : return error_count ? 1 : 0;
1131 : }
|