Make gpg-error replacement defines more robust.
[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 #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 xmalloc(a)    gcry_xmalloc ((a))
40 #define xcalloc(a,b)  gcry_xcalloc ((a),(b))
41 #define xfree(a)      gcry_free ((a))
42 #define pass() do { ; } while (0)
43
44
45 static struct
46 {
47   const char *desc;           /* Description of the curve.  */
48   const char *p;              /* Order of the prime field.  */
49   const char *a, *b;          /* The coefficients. */
50   const char *n;              /* The order of the base point.  */
51   const char *g_x, *g_y;      /* Base point.  */
52 } test_curve[] =
53   {
54     {
55       "NIST P-192",
56       "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
57       "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
58       "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
59       "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
60
61       "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
62       "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
63     },
64     {
65       "NIST P-224",
66       "0xffffffffffffffffffffffffffffffff000000000000000000000001",
67       "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
68       "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
69       "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
70
71       "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
72       "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
73     },
74     {
75       "NIST P-256",
76       "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
77       "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
78       "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
79       "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
80
81       "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
82       "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
83     },
84     {
85       "NIST P-384",
86       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
87       "ffffffff0000000000000000ffffffff",
88       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
89       "ffffffff0000000000000000fffffffc",
90       "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
91       "c656398d8a2ed19d2a85c8edd3ec2aef",
92       "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
93       "581a0db248b0a77aecec196accc52973",
94
95       "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
96       "5502f25dbf55296c3a545e3872760ab7",
97       "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
98       "0a60b1ce1d7e819d7a431d7c90ea0e5f"
99     },
100     {
101       "NIST P-521",
102       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
103       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
104       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
105       "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
106       "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
107       "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
108       "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
109       "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
110
111       "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
112       "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
113       "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
114       "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
115     },
116     { NULL, NULL, NULL, NULL, NULL }
117   };
118
119 /* A sample public key for NIST P-256.  */
120 static const char sample_p256_q[] =
121   "04"
122   "42B927242237639A36CE9221B340DB1A9AB76DF2FE3E171277F6A4023DED146E"
123   "E86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E";
124 static const char sample_p256_q_x[] =
125   "42B927242237639A36CE9221B340DB1A9AB76DF2FE3E171277F6A4023DED146E";
126 static const char sample_p256_q_y[] =
127   "00E86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E";
128
129
130
131 static void
132 show (const char *format, ...)
133 {
134   va_list arg_ptr;
135
136   if (!verbose)
137     return;
138   fprintf (stderr, "%s: ", PGM);
139   va_start (arg_ptr, format);
140   vfprintf (stderr, format, arg_ptr);
141   va_end (arg_ptr);
142 }
143
144 static void
145 fail (const char *format, ...)
146 {
147   va_list arg_ptr;
148
149   fflush (stdout);
150   fprintf (stderr, "%s: ", PGM);
151   if (wherestr)
152     fprintf (stderr, "%s: ", wherestr);
153   va_start (arg_ptr, format);
154   vfprintf (stderr, format, arg_ptr);
155   va_end (arg_ptr);
156   error_count++;
157 }
158
159 static void
160 die (const char *format, ...)
161 {
162   va_list arg_ptr;
163
164   fflush (stdout);
165   fprintf (stderr, "%s: ", PGM);
166   if (wherestr)
167     fprintf (stderr, "%s: ", wherestr);
168   va_start (arg_ptr, format);
169   vfprintf (stderr, format, arg_ptr);
170   va_end (arg_ptr);
171   exit (1);
172 }
173
174
175 static void
176 print_mpi_2 (const char *text, const char *text2, gcry_mpi_t a)
177 {
178   gcry_error_t err;
179   char *buf;
180   void *bufaddr = &buf;
181
182   err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
183   if (err)
184     fprintf (stderr, "%s%s: [error printing number: %s]\n",
185              text, text2? text2:"", gpg_strerror (err));
186   else
187     {
188       fprintf (stderr, "%s%s: %s\n", text, text2? text2:"", buf);
189       gcry_free (buf);
190     }
191 }
192
193
194 static void
195 print_mpi (const char *text, gcry_mpi_t a)
196 {
197   print_mpi_2 (text, NULL, a);
198 }
199
200
201 static void
202 print_point (const char *text, gcry_mpi_point_t a)
203 {
204   gcry_mpi_t x, y, z;
205
206   x = gcry_mpi_new (0);
207   y = gcry_mpi_new (0);
208   z = gcry_mpi_new (0);
209   gcry_mpi_point_get (x, y, z, a);
210   print_mpi_2 (text, ".x", x);
211   print_mpi_2 (text, ".y", y);
212   print_mpi_2 (text, ".z", z);
213   gcry_mpi_release (x);
214   gcry_mpi_release (y);
215   gcry_mpi_release (z);
216 }
217
218
219 static void
220 print_sexp (const char *prefix, gcry_sexp_t a)
221 {
222   char *buf;
223   size_t size;
224
225   if (prefix)
226     fputs (prefix, stderr);
227   size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
228   buf = gcry_xmalloc (size);
229
230   gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
231   fprintf (stderr, "%.*s", (int)size, buf);
232   gcry_free (buf);
233 }
234
235
236 static gcry_mpi_t
237 hex2mpi (const char *string)
238 {
239   gpg_error_t err;
240   gcry_mpi_t val;
241
242   err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
243   if (err)
244     die ("hex2mpi '%s' failed: %s\n", gpg_strerror (err));
245   return val;
246 }
247
248
249 /* Compare A to B, where B is given as a hex string.  */
250 static int
251 cmp_mpihex (gcry_mpi_t a, const char *b)
252 {
253   gcry_mpi_t bval;
254   int res;
255
256   bval = hex2mpi (b);
257   res = gcry_mpi_cmp (a, bval);
258   gcry_mpi_release (bval);
259   return res;
260 }
261
262
263 /* Wrapper to emulate the libgcrypt internal EC context allocation
264    function.  */
265 static gpg_error_t
266 ec_p_new (gcry_ctx_t *r_ctx, gcry_mpi_t p, gcry_mpi_t a)
267 {
268   gpg_error_t err;
269   gcry_sexp_t sexp;
270
271   if (p && a)
272     err = gcry_sexp_build (&sexp, NULL, "(ecdsa (p %m)(a %m))", p, a);
273   else if (p)
274     err = gcry_sexp_build (&sexp, NULL, "(ecdsa (p %m))", p);
275   else if (a)
276     err = gcry_sexp_build (&sexp, NULL, "(ecdsa (a %m))", a);
277   else
278     err = gcry_sexp_build (&sexp, NULL, "(ecdsa)");
279   if (err)
280     return err;
281   err = gcry_mpi_ec_new (r_ctx, sexp, NULL);
282   gcry_sexp_release (sexp);
283   return err;
284 }
285
286
287 \f
288 static void
289 set_get_point (void)
290 {
291   gcry_mpi_point_t point;
292   gcry_mpi_t x, y, z;
293
294   wherestr = "set_get_point";
295   show ("checking point setting functions\n");
296
297   point = gcry_mpi_point_new (0);
298   x = gcry_mpi_set_ui (NULL, 17);
299   y = gcry_mpi_set_ui (NULL, 42);
300   z = gcry_mpi_set_ui (NULL, 11371);
301   gcry_mpi_point_get (x, y, z, point);
302   if (gcry_mpi_cmp_ui (x, 0)
303       || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0))
304     fail ("new point not initialized to (0,0,0)\n");
305   gcry_mpi_point_snatch_get (x, y, z, point);
306   point = NULL;
307   if (gcry_mpi_cmp_ui (x, 0)
308       || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0))
309     fail ("snatch_get failed\n");
310   gcry_mpi_release (x);
311   gcry_mpi_release (y);
312   gcry_mpi_release (z);
313
314   point = gcry_mpi_point_new (0);
315   x = gcry_mpi_set_ui (NULL, 17);
316   y = gcry_mpi_set_ui (NULL, 42);
317   z = gcry_mpi_set_ui (NULL, 11371);
318   gcry_mpi_point_set (point, x, y, z);
319   gcry_mpi_set_ui (x, 23);
320   gcry_mpi_set_ui (y, 24);
321   gcry_mpi_set_ui (z, 25);
322   gcry_mpi_point_get (x, y, z, point);
323   if (gcry_mpi_cmp_ui (x, 17)
324       || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
325     fail ("point_set/point_get failed\n");
326   gcry_mpi_point_snatch_set (point, x, y, z);
327   x = gcry_mpi_new (0);
328   y = gcry_mpi_new (0);
329   z = gcry_mpi_new (0);
330   gcry_mpi_point_get (x, y, z, point);
331   if (gcry_mpi_cmp_ui (x, 17)
332       || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
333     fail ("point_snatch_set/point_get failed\n");
334
335   gcry_mpi_point_release (point);
336   gcry_mpi_release (x);
337   gcry_mpi_release (y);
338   gcry_mpi_release (z);
339 }
340
341
342 static void
343 context_alloc (void)
344 {
345   gpg_error_t err;
346   gcry_ctx_t ctx;
347   gcry_mpi_t p, a;
348
349   wherestr = "context_alloc";
350   show ("checking context functions\n");
351
352   p = gcry_mpi_set_ui (NULL, 1);
353   a = gcry_mpi_set_ui (NULL, 1);
354   err = ec_p_new (&ctx, p, a);
355   if (err)
356     die ("ec_p_new returned an error: %s\n", gpg_strerror (err));
357   gcry_mpi_release (p);
358   gcry_mpi_release (a);
359   gcry_ctx_release (ctx);
360
361   p = gcry_mpi_set_ui (NULL, 0);
362   a = gcry_mpi_set_ui (NULL, 0);
363   err = ec_p_new (&ctx, p, a);
364   if (!err || gpg_err_code (err) != GPG_ERR_EINVAL)
365     fail ("ec_p_new: bad parameter detection failed (1)\n");
366
367   gcry_mpi_set_ui (p, 1);
368   err = ec_p_new (&ctx, p, a);
369   if (!err || gpg_err_code (err) != GPG_ERR_EINVAL)
370     fail ("ec_p_new: bad parameter detection failed (2)\n");
371
372   gcry_mpi_release (p);
373   p = NULL;
374   err = ec_p_new (&ctx, p, a);
375   if (!err || gpg_err_code (err) != GPG_ERR_EINVAL)
376     fail ("ec_p_new: bad parameter detection failed (3)\n");
377
378   gcry_mpi_release (a);
379   a = NULL;
380   err = ec_p_new (&ctx, p, a);
381   if (!err || gpg_err_code (err) != GPG_ERR_EINVAL)
382     fail ("ec_p_new: bad parameter detection failed (4)\n");
383
384 }
385
386
387 static int
388 get_and_cmp_mpi (const char *name, const char *mpistring, const char *desc,
389                  gcry_ctx_t ctx)
390 {
391   gcry_mpi_t mpi;
392
393   mpi = gcry_mpi_ec_get_mpi (name, ctx, 1);
394   if (!mpi)
395     {
396       fail ("error getting parameter '%s' of curve '%s'\n", name, desc);
397       return 1;
398     }
399   if (debug)
400     print_mpi (name, mpi);
401   if (cmp_mpihex (mpi, mpistring))
402     {
403       fail ("parameter '%s' of curve '%s' does not match\n", name, desc);
404       gcry_mpi_release (mpi);
405       return 1;
406     }
407   gcry_mpi_release (mpi);
408   return 0;
409 }
410
411
412 static int
413 get_and_cmp_point (const char *name,
414                    const char *mpi_x_string, const char *mpi_y_string,
415                    const char *desc, gcry_ctx_t ctx)
416 {
417   gcry_mpi_point_t point;
418   gcry_mpi_t x, y, z;
419   int result = 0;
420
421   point = gcry_mpi_ec_get_point (name, ctx, 1);
422   if (!point)
423     {
424       fail ("error getting point parameter '%s' of curve '%s'\n", name, desc);
425       return 1;
426     }
427   if (debug)
428     print_point (name, point);
429
430   x = gcry_mpi_new (0);
431   y = gcry_mpi_new (0);
432   z = gcry_mpi_new (0);
433   gcry_mpi_point_snatch_get (x, y, z, point);
434   if (cmp_mpihex (x, mpi_x_string))
435     {
436       fail ("x coordinate of '%s' of curve '%s' does not match\n", name, desc);
437       result = 1;
438     }
439   if (cmp_mpihex (y, mpi_y_string))
440     {
441       fail ("y coordinate of '%s' of curve '%s' does not match\n", name, desc);
442       result = 1;
443     }
444   if (cmp_mpihex (z, "01"))
445     {
446       fail ("z coordinate of '%s' of curve '%s' is not 1\n", name, desc);
447       result = 1;
448     }
449   gcry_mpi_release (x);
450   gcry_mpi_release (y);
451   gcry_mpi_release (z);
452   return result;
453 }
454
455
456 static void
457 context_param (void)
458 {
459   gpg_error_t err;
460   int idx;
461   gcry_ctx_t ctx = NULL;
462   gcry_mpi_t q;
463   gcry_sexp_t keyparam;
464
465   wherestr = "context_param";
466
467   show ("checking standard curves\n");
468   for (idx=0; test_curve[idx].desc; idx++)
469     {
470       gcry_ctx_release (ctx);
471       err = gcry_mpi_ec_new (&ctx, NULL, test_curve[idx].desc);
472       if (err)
473         {
474           fail ("can't create context for curve '%s': %s\n",
475                 test_curve[idx].desc, gpg_strerror (err));
476           continue;
477         }
478       if (get_and_cmp_mpi ("p", test_curve[idx].p, test_curve[idx].desc, ctx))
479         continue;
480       if (get_and_cmp_mpi ("a", test_curve[idx].a, test_curve[idx].desc, ctx))
481         continue;
482       if (get_and_cmp_mpi ("b", test_curve[idx].b, test_curve[idx].desc, ctx))
483         continue;
484       if (get_and_cmp_mpi ("g.x",test_curve[idx].g_x, test_curve[idx].desc,ctx))
485         continue;
486       if (get_and_cmp_mpi ("g.y",test_curve[idx].g_y, test_curve[idx].desc,ctx))
487         continue;
488       if (get_and_cmp_mpi ("n", test_curve[idx].n, test_curve[idx].desc, ctx))
489         continue;
490       if (get_and_cmp_point ("g", test_curve[idx].g_x, test_curve[idx].g_y,
491                              test_curve[idx].desc, ctx))
492         continue;
493
494     }
495   gcry_ctx_release (ctx);
496
497
498   show ("checking sample public key\n");
499   q = hex2mpi (sample_p256_q);
500   err = gcry_sexp_build (&keyparam, NULL,
501                         "(public-key(ecdsa(curve %s)(q %m)))",
502                         "NIST P-256", q);
503   if (err)
504     die ("gcry_sexp_build failed: %s\n", gpg_strerror (err));
505   gcry_mpi_release (q);
506
507   /* We can't call gcry_pk_testkey because it is only implemented for
508      private keys.  */
509   /* err = gcry_pk_testkey (keyparam); */
510   /* if (err) */
511   /*   fail ("gcry_pk_testkey failed for sample public key: %s\n", */
512   /*         gpg_strerror (err)); */
513
514   err = gcry_mpi_ec_new (&ctx, keyparam, NULL);
515   if (err)
516     fail ("gcry_mpi_ec_new failed for sample public key: %s\n",
517           gpg_strerror (err));
518   else
519     {
520       gcry_sexp_t sexp;
521
522       get_and_cmp_mpi ("q", sample_p256_q, "NIST P-256", ctx);
523       get_and_cmp_point ("q", sample_p256_q_x, sample_p256_q_y, "NIST P-256",
524                          ctx);
525
526       err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
527       if (err)
528         fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
529       else if (debug)
530         print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
531       gcry_sexp_release (sexp);
532
533       err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
534       if (err)
535         fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n",
536               gpg_strerror (err));
537       else if (debug)
538         print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
539       gcry_sexp_release (sexp);
540
541       err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
542       if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
543         fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
544               gpg_strerror (err));
545       gcry_sexp_release (sexp);
546
547       gcry_ctx_release (ctx);
548     }
549
550   gcry_sexp_release (keyparam);
551 }
552
553
554
555
556 /* Create a new point from (X,Y,Z) given as hex strings.  */
557 gcry_mpi_point_t
558 make_point (const char *x, const char *y, const char *z)
559 {
560   gcry_mpi_point_t point;
561
562   point = gcry_mpi_point_new (0);
563   gcry_mpi_point_snatch_set (point, hex2mpi (x), hex2mpi (y), hex2mpi (z));
564
565   return point;
566 }
567
568
569 /* This tests checks that the low-level EC API yields the same result
570    as using the high level API.  The values have been taken from a
571    test run using the high level API.  */
572 static void
573 basic_ec_math (void)
574 {
575   gpg_error_t err;
576   gcry_ctx_t ctx;
577   gcry_mpi_t P, A;
578   gcry_mpi_point_t G, Q;
579   gcry_mpi_t d;
580   gcry_mpi_t x, y, z;
581
582   wherestr = "basic_ec_math";
583   show ("checking basic math functions for EC\n");
584
585   P = hex2mpi ("0xfffffffffffffffffffffffffffffffeffffffffffffffff");
586   A = hex2mpi ("0xfffffffffffffffffffffffffffffffefffffffffffffffc");
587   G = make_point ("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
588                   "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
589                   "1");
590   d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
591   Q = gcry_mpi_point_new (0);
592
593   err = ec_p_new (&ctx, P, A);
594   if (err)
595     die ("ec_p_new failed: %s\n", gpg_strerror (err));
596
597   x = gcry_mpi_new (0);
598   y = gcry_mpi_new (0);
599   z = gcry_mpi_new (0);
600
601   {
602     /* A quick check that multiply by zero works.  */
603     gcry_mpi_t tmp;
604
605     tmp = gcry_mpi_new (0);
606     gcry_mpi_ec_mul (Q, tmp, G, ctx);
607     gcry_mpi_release (tmp);
608     gcry_mpi_point_get (x, y, z, Q);
609     if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 0)
610         || gcry_mpi_cmp_ui (z, 0))
611       fail ("multiply a point by zero failed\n");
612   }
613
614   gcry_mpi_ec_mul (Q, d, G, ctx);
615   gcry_mpi_point_get (x, y, z, Q);
616   if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
617       || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
618       || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
619     fail ("computed public key does not match\n");
620   if (debug)
621     {
622       print_mpi ("Q.x", x);
623       print_mpi ("Q.y", y);
624       print_mpi ("Q.z", z);
625     }
626
627   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
628     fail ("failed to get affine coordinates\n");
629   if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
630       || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
631     fail ("computed affine coordinates of public key do not match\n");
632   if (debug)
633     {
634       print_mpi ("q.x", x);
635       print_mpi ("q.y", y);
636     }
637
638   gcry_mpi_release (z);
639   gcry_mpi_release (y);
640   gcry_mpi_release (x);
641   gcry_mpi_point_release (Q);
642   gcry_mpi_release (d);
643   gcry_mpi_point_release (G);
644   gcry_mpi_release (A);
645   gcry_mpi_release (P);
646 }
647
648
649 /* This is the same as basic_ec_math but uses more advanced
650    features.  */
651 static void
652 basic_ec_math_simplified (void)
653 {
654   gpg_error_t err;
655   gcry_ctx_t ctx;
656   gcry_mpi_point_t G, Q;
657   gcry_mpi_t d;
658   gcry_mpi_t x, y, z;
659   gcry_sexp_t sexp;
660
661   wherestr = "basic_ec_math_simplified";
662   show ("checking basic math functions for EC (variant)\n");
663
664   d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
665   Q = gcry_mpi_point_new (0);
666
667   err = gcry_mpi_ec_new (&ctx, NULL, "NIST P-192");
668   if (err)
669     die ("gcry_mpi_ec_new failed: %s\n", gpg_strerror (err));
670   G = gcry_mpi_ec_get_point ("g", ctx, 1);
671   if (!G)
672     die ("gcry_mpi_ec_get_point(G) failed\n");
673   gcry_mpi_ec_mul (Q, d, G, ctx);
674
675   x = gcry_mpi_new (0);
676   y = gcry_mpi_new (0);
677   z = gcry_mpi_new (0);
678   gcry_mpi_point_get (x, y, z, Q);
679   if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
680       || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
681       || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
682     fail ("computed public key does not match\n");
683   if (debug)
684     {
685       print_mpi ("Q.x", x);
686       print_mpi ("Q.y", y);
687       print_mpi ("Q.z", z);
688     }
689
690   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
691     fail ("failed to get affine coordinates\n");
692   if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
693       || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
694     fail ("computed affine coordinates of public key do not match\n");
695   if (debug)
696     {
697       print_mpi ("q.x", x);
698       print_mpi ("q.y", y);
699     }
700
701   gcry_mpi_release (z);
702   gcry_mpi_release (y);
703   gcry_mpi_release (x);
704
705   /* Let us also check wheer we can update the context.  */
706   err = gcry_mpi_ec_set_point ("g", G, ctx);
707   if (err)
708     die ("gcry_mpi_ec_set_point(G) failed\n");
709   err = gcry_mpi_ec_set_mpi ("d", d, ctx);
710   if (err)
711     die ("gcry_mpi_ec_set_mpi(d) failed\n");
712
713   /* FIXME: Below we need to check that the returned S-expression is
714      as requested.  For now we use manual inspection using --debug.  */
715
716   /* Does get_sexp return the private key?  */
717   err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
718   if (err)
719     fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
720   else if (verbose)
721     print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
722   gcry_sexp_release (sexp);
723
724   /* Does get_sexp return the public key if requested?  */
725   err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
726   if (err)
727     fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n", gpg_strerror (err));
728   else if (verbose)
729     print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
730   gcry_sexp_release (sexp);
731
732   /* Does get_sexp return the public key if after d has been deleted?  */
733   err = gcry_mpi_ec_set_mpi ("d", NULL, ctx);
734   if (err)
735     die ("gcry_mpi_ec_set_mpi(d=NULL) failed\n");
736   err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
737   if (err)
738     fail ("gcry_pubkey_get_sexp(0 w/o d) failed: %s\n", gpg_strerror (err));
739   else if (verbose)
740     print_sexp ("Result of gcry_pubkey_get_sexp (0 w/o d):\n", sexp);
741   gcry_sexp_release (sexp);
742
743   /* Does get_sexp return an error after d has been deleted?  */
744   err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
745   if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
746     fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
747           gpg_strerror (err));
748   gcry_sexp_release (sexp);
749
750   /* Does get_sexp return an error after d and Q have been deleted?  */
751   err = gcry_mpi_ec_set_point ("q", NULL, ctx);
752   if (err)
753     die ("gcry_mpi_ec_set_point(q=NULL) failed\n");
754   err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
755   if (gpg_err_code (err) != GPG_ERR_BAD_CRYPT_CTX)
756     fail ("gcry_pubkey_get_sexp(0 w/o Q,d) returned wrong error: %s\n",
757           gpg_strerror (err));
758   gcry_sexp_release (sexp);
759
760
761   gcry_mpi_point_release (Q);
762   gcry_mpi_release (d);
763   gcry_mpi_point_release (G);
764 }
765
766
767 int
768 main (int argc, char **argv)
769 {
770
771   if (argc > 1 && !strcmp (argv[1], "--verbose"))
772     verbose = 1;
773   else if (argc > 1 && !strcmp (argv[1], "--debug"))
774     verbose = debug = 1;
775
776   if (!gcry_check_version (GCRYPT_VERSION))
777     die ("version mismatch\n");
778
779   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
780   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
781   if (debug)
782     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
783   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
784
785   set_get_point ();
786   context_alloc ();
787   context_param ();
788   basic_ec_math ();
789   basic_ec_math_simplified ();
790
791   show ("All tests completed. Errors: %d\n", error_count);
792   return error_count ? 1 : 0;
793 }