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 : "-0x01",
134 : "-0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A",
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 6 : gcry_ctx_release (ctx);
544 6 : err = gcry_mpi_ec_new (&ctx, NULL, test_curve[idx].desc);
545 6 : if (err)
546 : {
547 0 : fail ("can't create context for curve '%s': %s\n",
548 : test_curve[idx].desc, gpg_strerror (err));
549 0 : continue;
550 : }
551 6 : if (get_and_cmp_mpi ("p", test_curve[idx].p, test_curve[idx].desc, ctx))
552 0 : continue;
553 6 : if (get_and_cmp_mpi ("a", test_curve[idx].a, test_curve[idx].desc, ctx))
554 0 : continue;
555 6 : if (get_and_cmp_mpi ("b", test_curve[idx].b, test_curve[idx].desc, ctx))
556 0 : continue;
557 6 : if (get_and_cmp_mpi ("g.x",test_curve[idx].g_x, test_curve[idx].desc,ctx))
558 0 : continue;
559 6 : if (get_and_cmp_mpi ("g.y",test_curve[idx].g_y, test_curve[idx].desc,ctx))
560 0 : continue;
561 6 : if (get_and_cmp_mpi ("n", test_curve[idx].n, test_curve[idx].desc, ctx))
562 0 : continue;
563 6 : if (get_and_cmp_point ("g", test_curve[idx].g_x, test_curve[idx].g_y,
564 : test_curve[idx].desc, ctx))
565 0 : continue;
566 6 : if (get_and_cmp_mpi ("h", test_curve[idx].h, test_curve[idx].desc, ctx))
567 0 : continue;
568 :
569 : }
570 :
571 1 : show ("checking sample public key (nistp256)\n");
572 1 : q = hex2mpi (sample_p256_q);
573 1 : err = gcry_sexp_build (&keyparam, NULL,
574 : "(public-key(ecc(curve %s)(q %m)))",
575 : "NIST P-256", q);
576 1 : if (err)
577 0 : die ("gcry_sexp_build failed: %s\n", gpg_strerror (err));
578 1 : gcry_mpi_release (q);
579 :
580 : /* We can't call gcry_pk_testkey because it is only implemented for
581 : private keys. */
582 : /* err = gcry_pk_testkey (keyparam); */
583 : /* if (err) */
584 : /* fail ("gcry_pk_testkey failed for sample public key: %s\n", */
585 : /* gpg_strerror (err)); */
586 :
587 1 : gcry_ctx_release (ctx);
588 1 : err = gcry_mpi_ec_new (&ctx, keyparam, NULL);
589 1 : if (err)
590 0 : fail ("gcry_mpi_ec_new failed for sample public key (nistp256): %s\n",
591 : gpg_strerror (err));
592 : else
593 : {
594 : gcry_sexp_t sexp;
595 :
596 1 : get_and_cmp_mpi ("q", sample_p256_q, "nistp256", ctx);
597 1 : get_and_cmp_point ("q", sample_p256_q_x, sample_p256_q_y, "nistp256",
598 : ctx);
599 :
600 : /* Delete Q. */
601 1 : err = gcry_mpi_ec_set_mpi ("q", NULL, ctx);
602 1 : if (err)
603 0 : fail ("clearing Q for nistp256 failed: %s\n", gpg_strerror (err));
604 1 : if (gcry_mpi_ec_get_mpi ("q", ctx, 0))
605 0 : fail ("clearing Q for nistp256 did not work\n");
606 :
607 : /* Set Q again. */
608 1 : q = hex2mpi (sample_p256_q);
609 1 : err = gcry_mpi_ec_set_mpi ("q", q, ctx);
610 1 : if (err)
611 0 : fail ("setting Q for nistp256 failed: %s\n", gpg_strerror (err));
612 1 : get_and_cmp_mpi ("q", sample_p256_q, "nistp256(2)", ctx);
613 1 : gcry_mpi_release (q);
614 :
615 : /* Get as s-expression. */
616 1 : err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
617 1 : if (err)
618 0 : fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
619 1 : else if (debug)
620 0 : print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
621 1 : gcry_sexp_release (sexp);
622 :
623 1 : err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
624 1 : if (err)
625 0 : fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n",
626 : gpg_strerror (err));
627 1 : else if (debug)
628 0 : print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
629 1 : gcry_sexp_release (sexp);
630 :
631 1 : err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
632 1 : if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
633 0 : fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
634 : gpg_strerror (err));
635 1 : gcry_sexp_release (sexp);
636 : }
637 :
638 1 : show ("checking sample public key (Ed25519)\n");
639 1 : q = hex2mpi (sample_ed25519_q);
640 1 : gcry_sexp_release (keyparam);
641 1 : err = gcry_sexp_build (&keyparam, NULL,
642 : "(public-key(ecc(curve %s)(flags eddsa)(q %m)))",
643 : "Ed25519", q);
644 1 : if (err)
645 0 : die ("gcry_sexp_build failed: %s\n", gpg_strerror (err));
646 1 : gcry_mpi_release (q);
647 :
648 : /* We can't call gcry_pk_testkey because it is only implemented for
649 : private keys. */
650 : /* err = gcry_pk_testkey (keyparam); */
651 : /* if (err) */
652 : /* fail ("gcry_pk_testkey failed for sample public key: %s\n", */
653 : /* gpg_strerror (err)); */
654 :
655 1 : gcry_ctx_release (ctx);
656 1 : err = gcry_mpi_ec_new (&ctx, keyparam, NULL);
657 1 : if (err)
658 0 : fail ("gcry_mpi_ec_new failed for sample public key: %s\n",
659 : gpg_strerror (err));
660 : else
661 : {
662 : gcry_sexp_t sexp;
663 :
664 1 : get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519", ctx);
665 1 : get_and_cmp_point ("q", sample_ed25519_q_x, sample_ed25519_q_y,
666 : "Ed25519", ctx);
667 1 : get_and_cmp_mpi ("q@eddsa", sample_ed25519_q_eddsa, "Ed25519", ctx);
668 :
669 : /* Set d to see whether Q is correctly re-computed. */
670 1 : d = hex2mpi (sample_ed25519_d);
671 1 : err = gcry_mpi_ec_set_mpi ("d", d, ctx);
672 1 : if (err)
673 0 : fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err));
674 1 : gcry_mpi_release (d);
675 1 : get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(recompute Q)", ctx);
676 :
677 : /* Delete Q by setting d and then clearing d. The clearing is
678 : required so that we can check whether Q has been cleared and
679 : because further tests only expect a public key. */
680 1 : d = hex2mpi (sample_ed25519_d);
681 1 : err = gcry_mpi_ec_set_mpi ("d", d, ctx);
682 1 : if (err)
683 0 : fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err));
684 1 : gcry_mpi_release (d);
685 1 : err = gcry_mpi_ec_set_mpi ("d", NULL, ctx);
686 1 : if (err)
687 0 : fail ("setting d for Ed25519 failed(2): %s\n", gpg_strerror (err));
688 1 : if (gcry_mpi_ec_get_mpi ("q", ctx, 0))
689 0 : fail ("setting d for Ed25519 did not reset Q\n");
690 :
691 : /* Set Q again. We need to use an opaque MPI here because
692 : sample_ed25519_q is in uncompressed format which can only be
693 : auto-detected if passed opaque. */
694 1 : q = hex2mpiopa (sample_ed25519_q);
695 1 : err = gcry_mpi_ec_set_mpi ("q", q, ctx);
696 1 : if (err)
697 0 : fail ("setting Q for Ed25519 failed: %s\n", gpg_strerror (err));
698 1 : gcry_mpi_release (q);
699 1 : get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(2)", ctx);
700 :
701 : /* Get as s-expression. */
702 1 : err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
703 1 : if (err)
704 0 : fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
705 1 : else if (debug)
706 0 : print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
707 1 : gcry_sexp_release (sexp);
708 :
709 1 : err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
710 1 : if (err)
711 0 : fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n",
712 : gpg_strerror (err));
713 1 : else if (debug)
714 0 : print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
715 1 : gcry_sexp_release (sexp);
716 :
717 1 : err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
718 1 : if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
719 0 : fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
720 : gpg_strerror (err));
721 1 : gcry_sexp_release (sexp);
722 :
723 : }
724 :
725 1 : gcry_ctx_release (ctx);
726 1 : gcry_sexp_release (keyparam);
727 1 : }
728 :
729 :
730 :
731 :
732 : /* Create a new point from (X,Y,Z) given as hex strings. */
733 : gcry_mpi_point_t
734 1 : make_point (const char *x, const char *y, const char *z)
735 : {
736 : gcry_mpi_point_t point;
737 :
738 1 : point = gcry_mpi_point_new (0);
739 1 : gcry_mpi_point_snatch_set (point, hex2mpi (x), hex2mpi (y), hex2mpi (z));
740 :
741 1 : return point;
742 : }
743 :
744 :
745 : /* This tests checks that the low-level EC API yields the same result
746 : as using the high level API. The values have been taken from a
747 : test run using the high level API. */
748 : static void
749 1 : basic_ec_math (void)
750 : {
751 : gpg_error_t err;
752 : gcry_ctx_t ctx;
753 : gcry_mpi_t P, A;
754 : gcry_mpi_point_t G, Q;
755 : gcry_mpi_t d;
756 : gcry_mpi_t x, y, z;
757 :
758 1 : wherestr = "basic_ec_math";
759 1 : show ("checking basic math functions for EC\n");
760 :
761 1 : P = hex2mpi ("0xfffffffffffffffffffffffffffffffeffffffffffffffff");
762 1 : A = hex2mpi ("0xfffffffffffffffffffffffffffffffefffffffffffffffc");
763 1 : G = make_point ("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
764 : "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
765 : "1");
766 1 : d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
767 1 : Q = gcry_mpi_point_new (0);
768 :
769 1 : err = ec_p_new (&ctx, P, A);
770 1 : if (err)
771 0 : die ("ec_p_new failed: %s\n", gpg_strerror (err));
772 :
773 1 : x = gcry_mpi_new (0);
774 1 : y = gcry_mpi_new (0);
775 1 : z = gcry_mpi_new (0);
776 :
777 : {
778 : /* A quick check that multiply by zero works. */
779 : gcry_mpi_t tmp;
780 :
781 1 : tmp = gcry_mpi_new (0);
782 1 : gcry_mpi_ec_mul (Q, tmp, G, ctx);
783 1 : gcry_mpi_release (tmp);
784 1 : gcry_mpi_point_get (x, y, z, Q);
785 1 : if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 0)
786 1 : || gcry_mpi_cmp_ui (z, 0))
787 0 : fail ("multiply a point by zero failed\n");
788 : }
789 :
790 1 : gcry_mpi_ec_mul (Q, d, G, ctx);
791 1 : gcry_mpi_point_get (x, y, z, Q);
792 1 : if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
793 1 : || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
794 1 : || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
795 0 : fail ("computed public key does not match\n");
796 1 : if (debug)
797 : {
798 0 : print_mpi ("Q.x", x);
799 0 : print_mpi ("Q.y", y);
800 0 : print_mpi ("Q.z", z);
801 : }
802 :
803 1 : if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
804 0 : fail ("failed to get affine coordinates\n");
805 1 : if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
806 1 : || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
807 0 : fail ("computed affine coordinates of public key do not match\n");
808 1 : if (debug)
809 : {
810 0 : print_mpi ("q.x", x);
811 0 : print_mpi ("q.y", y);
812 : }
813 :
814 1 : gcry_mpi_release (z);
815 1 : gcry_mpi_release (y);
816 1 : gcry_mpi_release (x);
817 1 : gcry_mpi_point_release (Q);
818 1 : gcry_mpi_release (d);
819 1 : gcry_mpi_point_release (G);
820 1 : gcry_mpi_release (A);
821 1 : gcry_mpi_release (P);
822 1 : gcry_ctx_release (ctx);
823 1 : }
824 :
825 :
826 : /* This is the same as basic_ec_math but uses more advanced
827 : features. */
828 : static void
829 1 : basic_ec_math_simplified (void)
830 : {
831 : gpg_error_t err;
832 : gcry_ctx_t ctx;
833 : gcry_mpi_point_t G, Q;
834 : gcry_mpi_t d;
835 : gcry_mpi_t x, y, z;
836 : gcry_sexp_t sexp;
837 :
838 1 : wherestr = "basic_ec_math_simplified";
839 1 : show ("checking basic math functions for EC (variant)\n");
840 :
841 1 : d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
842 1 : Q = gcry_mpi_point_new (0);
843 :
844 1 : err = gcry_mpi_ec_new (&ctx, NULL, "NIST P-192");
845 1 : if (err)
846 0 : die ("gcry_mpi_ec_new failed: %s\n", gpg_strerror (err));
847 1 : G = gcry_mpi_ec_get_point ("g", ctx, 1);
848 1 : if (!G)
849 0 : die ("gcry_mpi_ec_get_point(G) failed\n");
850 1 : gcry_mpi_ec_mul (Q, d, G, ctx);
851 :
852 1 : x = gcry_mpi_new (0);
853 1 : y = gcry_mpi_new (0);
854 1 : z = gcry_mpi_new (0);
855 1 : gcry_mpi_point_get (x, y, z, Q);
856 1 : if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
857 1 : || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
858 1 : || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
859 0 : fail ("computed public key does not match\n");
860 1 : if (debug)
861 : {
862 0 : print_mpi ("Q.x", x);
863 0 : print_mpi ("Q.y", y);
864 0 : print_mpi ("Q.z", z);
865 : }
866 :
867 1 : if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
868 0 : fail ("failed to get affine coordinates\n");
869 1 : if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
870 1 : || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
871 0 : fail ("computed affine coordinates of public key do not match\n");
872 1 : if (debug)
873 : {
874 0 : print_mpi ("q.x", x);
875 0 : print_mpi ("q.y", y);
876 : }
877 :
878 1 : gcry_mpi_release (z);
879 1 : gcry_mpi_release (y);
880 1 : gcry_mpi_release (x);
881 :
882 : /* Let us also check whether we can update the context. */
883 1 : err = gcry_mpi_ec_set_point ("g", G, ctx);
884 1 : if (err)
885 0 : die ("gcry_mpi_ec_set_point(G) failed\n");
886 1 : err = gcry_mpi_ec_set_mpi ("d", d, ctx);
887 1 : if (err)
888 0 : die ("gcry_mpi_ec_set_mpi(d) failed\n");
889 :
890 : /* FIXME: Below we need to check that the returned S-expression is
891 : as requested. For now we use manual inspection using --debug. */
892 :
893 : /* Does get_sexp return the private key? */
894 1 : err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
895 1 : if (err)
896 0 : fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
897 1 : else if (debug)
898 0 : print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
899 1 : gcry_sexp_release (sexp);
900 :
901 : /* Does get_sexp return the public key if requested? */
902 1 : err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
903 1 : if (err)
904 0 : fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n", gpg_strerror (err));
905 1 : else if (debug)
906 0 : print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
907 1 : gcry_sexp_release (sexp);
908 :
909 : /* Does get_sexp return the public key after d has been deleted? */
910 1 : err = gcry_mpi_ec_set_mpi ("d", NULL, ctx);
911 1 : if (err)
912 0 : die ("gcry_mpi_ec_set_mpi(d=NULL) failed\n");
913 1 : err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
914 1 : if (err)
915 0 : fail ("gcry_pubkey_get_sexp(0 w/o d) failed: %s\n", gpg_strerror (err));
916 1 : else if (debug)
917 0 : print_sexp ("Result of gcry_pubkey_get_sexp (0 w/o d):\n", sexp);
918 1 : gcry_sexp_release (sexp);
919 :
920 : /* Does get_sexp return an error after d has been deleted? */
921 1 : err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
922 1 : if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
923 0 : fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
924 : gpg_strerror (err));
925 1 : gcry_sexp_release (sexp);
926 :
927 : /* Does get_sexp return an error after d and Q have been deleted? */
928 1 : err = gcry_mpi_ec_set_point ("q", NULL, ctx);
929 1 : if (err)
930 0 : die ("gcry_mpi_ec_set_point(q=NULL) failed\n");
931 1 : err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
932 1 : if (gpg_err_code (err) != GPG_ERR_BAD_CRYPT_CTX)
933 0 : fail ("gcry_pubkey_get_sexp(0 w/o Q,d) returned wrong error: %s\n",
934 : gpg_strerror (err));
935 1 : gcry_sexp_release (sexp);
936 :
937 :
938 1 : gcry_mpi_point_release (Q);
939 1 : gcry_mpi_release (d);
940 1 : gcry_mpi_point_release (G);
941 1 : gcry_ctx_release (ctx);
942 1 : }
943 :
944 :
945 : /* Check the math used with Twisted Edwards curves. */
946 : static void
947 1 : twistededwards_math (void)
948 : {
949 : gpg_error_t err;
950 : gcry_ctx_t ctx;
951 : gcry_mpi_point_t G, Q;
952 : gcry_mpi_t k;
953 : gcry_mpi_t w, a, x, y, z, p, n, b, I;
954 :
955 1 : wherestr = "twistededwards_math";
956 1 : show ("checking basic Twisted Edwards math\n");
957 :
958 1 : err = gcry_mpi_ec_new (&ctx, NULL, "Ed25519");
959 1 : if (err)
960 0 : die ("gcry_mpi_ec_new failed: %s\n", gpg_strerror (err));
961 :
962 1 : k = hex2mpi
963 : ("2D3501E723239632802454EE5DDC406EFB0BDF18486A5BDE9C0390A9C2984004"
964 : "F47252B628C953625B8DEB5DBCB8DA97AA43A1892D11FA83596F42E0D89CB1B6");
965 1 : G = gcry_mpi_ec_get_point ("g", ctx, 1);
966 1 : if (!G)
967 0 : die ("gcry_mpi_ec_get_point(G) failed\n");
968 1 : Q = gcry_mpi_point_new (0);
969 :
970 :
971 1 : w = gcry_mpi_new (0);
972 1 : a = gcry_mpi_new (0);
973 1 : x = gcry_mpi_new (0);
974 1 : y = gcry_mpi_new (0);
975 1 : z = gcry_mpi_new (0);
976 1 : I = gcry_mpi_new (0);
977 1 : p = gcry_mpi_ec_get_mpi ("p", ctx, 1);
978 1 : n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
979 1 : b = gcry_mpi_ec_get_mpi ("b", ctx, 1);
980 :
981 : /* Check: 2^{p-1} mod p == 1 */
982 1 : gcry_mpi_sub_ui (a, p, 1);
983 1 : gcry_mpi_powm (w, GCRYMPI_CONST_TWO, a, p);
984 1 : if (gcry_mpi_cmp_ui (w, 1))
985 0 : fail ("failed assertion: 2^{p-1} mod p == 1\n");
986 :
987 : /* Check: p % 4 == 1 */
988 1 : gcry_mpi_mod (w, p, GCRYMPI_CONST_FOUR);
989 1 : if (gcry_mpi_cmp_ui (w, 1))
990 0 : fail ("failed assertion: p % 4 == 1\n");
991 :
992 : /* Check: 2^{n-1} mod n == 1 */
993 1 : gcry_mpi_sub_ui (a, n, 1);
994 1 : gcry_mpi_powm (w, GCRYMPI_CONST_TWO, a, n);
995 1 : if (gcry_mpi_cmp_ui (w, 1))
996 0 : fail ("failed assertion: 2^{n-1} mod n == 1\n");
997 :
998 : /* Check: b^{(p-1)/2} mod p == p-1 */
999 1 : gcry_mpi_sub_ui (a, p, 1);
1000 1 : gcry_mpi_div (x, NULL, a, GCRYMPI_CONST_TWO, -1);
1001 1 : gcry_mpi_powm (w, b, x, p);
1002 1 : gcry_mpi_abs (w);
1003 1 : if (gcry_mpi_cmp (w, a))
1004 0 : fail ("failed assertion: b^{(p-1)/2} mod p == p-1\n");
1005 :
1006 : /* I := 2^{(p-1)/4} mod p */
1007 1 : gcry_mpi_sub_ui (a, p, 1);
1008 1 : gcry_mpi_div (x, NULL, a, GCRYMPI_CONST_FOUR, -1);
1009 1 : gcry_mpi_powm (I, GCRYMPI_CONST_TWO, x, p);
1010 :
1011 : /* Check: I^2 mod p == p-1 */
1012 1 : gcry_mpi_powm (w, I, GCRYMPI_CONST_TWO, p);
1013 1 : if (gcry_mpi_cmp (w, a))
1014 0 : fail ("failed assertion: I^2 mod p == p-1\n");
1015 :
1016 : /* Check: G is on the curve */
1017 1 : if (!gcry_mpi_ec_curve_point (G, ctx))
1018 0 : fail ("failed assertion: G is on the curve\n");
1019 :
1020 : /* Check: nG == (0,1) */
1021 1 : gcry_mpi_ec_mul (Q, n, G, ctx);
1022 1 : if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
1023 0 : fail ("failed to get affine coordinates\n");
1024 1 : if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 1))
1025 0 : fail ("failed assertion: nG == (0,1)\n");
1026 :
1027 : /* Now two arbitrary point operations taken from the ed25519.py
1028 : sample data. */
1029 1 : gcry_mpi_release (a);
1030 1 : a = hex2mpi
1031 : ("4f71d012df3c371af3ea4dc38385ca5bb7272f90cb1b008b3ed601c76de1d496"
1032 : "e30cbf625f0a756a678d8f256d5325595cccc83466f36db18f0178eb9925edd3");
1033 1 : gcry_mpi_ec_mul (Q, a, G, ctx);
1034 1 : if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
1035 0 : fail ("failed to get affine coordinates\n");
1036 1 : if (cmp_mpihex (x, ("157f7361c577aad36f67ed33e38dc7be"
1037 : "00014fecc2165ca5cee9eee19fe4d2c1"))
1038 1 : || cmp_mpihex (y, ("5a69dbeb232276b38f3f5016547bb2a2"
1039 : "4025645f0b820e72b8cad4f0a909a092")))
1040 : {
1041 0 : fail ("sample point multiply failed:\n");
1042 0 : print_mpi ("r", a);
1043 0 : print_mpi ("Rx", x);
1044 0 : print_mpi ("Ry", y);
1045 : }
1046 :
1047 1 : gcry_mpi_release (a);
1048 1 : a = hex2mpi
1049 : ("2d3501e723239632802454ee5ddc406efb0bdf18486a5bde9c0390a9c2984004"
1050 : "f47252b628c953625b8deb5dbcb8da97aa43a1892d11fa83596f42e0d89cb1b6");
1051 1 : gcry_mpi_ec_mul (Q, a, G, ctx);
1052 1 : if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
1053 0 : fail ("failed to get affine coordinates\n");
1054 1 : if (cmp_mpihex (x, ("6218e309d40065fcc338b3127f468371"
1055 : "82324bd01ce6f3cf81ab44e62959c82a"))
1056 1 : || cmp_mpihex (y, ("5501492265e073d874d9e5b81e7f8784"
1057 : "8a826e80cce2869072ac60c3004356e5")))
1058 : {
1059 0 : fail ("sample point multiply failed:\n");
1060 0 : print_mpi ("r", a);
1061 0 : print_mpi ("Rx", x);
1062 0 : print_mpi ("Ry", y);
1063 : }
1064 :
1065 :
1066 1 : gcry_mpi_release (I);
1067 1 : gcry_mpi_release (b);
1068 1 : gcry_mpi_release (n);
1069 1 : gcry_mpi_release (p);
1070 1 : gcry_mpi_release (w);
1071 1 : gcry_mpi_release (a);
1072 1 : gcry_mpi_release (x);
1073 1 : gcry_mpi_release (y);
1074 1 : gcry_mpi_release (z);
1075 1 : gcry_mpi_point_release (Q);
1076 1 : gcry_mpi_point_release (G);
1077 1 : gcry_mpi_release (k);
1078 1 : gcry_ctx_release (ctx);
1079 1 : }
1080 :
1081 :
1082 : int
1083 1 : main (int argc, char **argv)
1084 : {
1085 :
1086 1 : if (argc > 1 && !strcmp (argv[1], "--verbose"))
1087 0 : verbose = 1;
1088 1 : else if (argc > 1 && !strcmp (argv[1], "--debug"))
1089 0 : verbose = debug = 1;
1090 :
1091 1 : if (!gcry_check_version (GCRYPT_VERSION))
1092 0 : die ("version mismatch\n");
1093 :
1094 1 : gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
1095 1 : gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
1096 1 : if (debug)
1097 0 : gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
1098 1 : gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
1099 :
1100 1 : set_get_point ();
1101 1 : context_alloc ();
1102 1 : context_param ();
1103 1 : basic_ec_math ();
1104 1 : basic_ec_math_simplified ();
1105 1 : twistededwards_math ();
1106 :
1107 1 : show ("All tests completed. Errors: %d\n", error_count);
1108 1 : return error_count ? 1 : 0;
1109 : }
|