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