8714d388b037bfb4a819060323e0a66a6704aa22
[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.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 static void
45 show (const char *format, ...)
46 {
47   va_list arg_ptr;
48
49   if (!verbose)
50     return;
51   fprintf (stderr, "%s: ", PGM);
52   va_start (arg_ptr, format);
53   vfprintf (stderr, format, arg_ptr);
54   va_end (arg_ptr);
55 }
56
57 static void
58 fail (const char *format, ...)
59 {
60   va_list arg_ptr;
61
62   fflush (stdout);
63   fprintf (stderr, "%s: ", PGM);
64   if (wherestr)
65     fprintf (stderr, "%s: ", wherestr);
66   va_start (arg_ptr, format);
67   vfprintf (stderr, format, arg_ptr);
68   va_end (arg_ptr);
69   error_count++;
70 }
71
72 static void
73 die (const char *format, ...)
74 {
75   va_list arg_ptr;
76
77   fflush (stdout);
78   fprintf (stderr, "%s: ", PGM);
79   if (wherestr)
80     fprintf (stderr, "%s: ", wherestr);
81   va_start (arg_ptr, format);
82   vfprintf (stderr, format, arg_ptr);
83   va_end (arg_ptr);
84   exit (1);
85 }
86
87
88 static void
89 print_mpi (const char *text, gcry_mpi_t a)
90 {
91   gcry_error_t err;
92   char *buf;
93   void *bufaddr = &buf;
94
95   err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
96   if (err)
97     fprintf (stderr, "%s: [error printing number: %s]\n",
98              text, gpg_strerror (err));
99   else
100     {
101       fprintf (stderr, "%s: %s\n", text, buf);
102       gcry_free (buf);
103     }
104 }
105
106
107 static gcry_mpi_t
108 hex2mpi (const char *string)
109 {
110   gpg_error_t err;
111   gcry_mpi_t val;
112
113   err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
114   if (err)
115     die ("hex2mpi '%s' failed: %s\n", gpg_strerror (err));
116   return val;
117 }
118
119
120 /* Compare A to B, where B is given as a hex string.  */
121 static int
122 cmp_mpihex (gcry_mpi_t a, const char *b)
123 {
124   gcry_mpi_t bval;
125   int res;
126
127   bval = hex2mpi (b);
128   res = gcry_mpi_cmp (a, bval);
129   gcry_mpi_release (bval);
130   return res;
131 }
132
133
134 \f
135 static void
136 set_get_point (void)
137 {
138   gcry_mpi_point_t point;
139   gcry_mpi_t x, y, z;
140
141   wherestr = "set_get_point";
142   show ("checking point setting functions\n");
143
144   point = gcry_mpi_point_new (0);
145   x = gcry_mpi_set_ui (NULL, 17);
146   y = gcry_mpi_set_ui (NULL, 42);
147   z = gcry_mpi_set_ui (NULL, 11371);
148   gcry_mpi_point_get (x, y, z, point);
149   if (gcry_mpi_cmp_ui (x, 0)
150       || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0))
151     fail ("new point not initialized to (0,0,0)\n");
152   gcry_mpi_point_snatch_get (x, y, z, point);
153   point = NULL;
154   if (gcry_mpi_cmp_ui (x, 0)
155       || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0))
156     fail ("snatch_get failed\n");
157   gcry_mpi_release (x);
158   gcry_mpi_release (y);
159   gcry_mpi_release (z);
160
161   point = gcry_mpi_point_new (0);
162   x = gcry_mpi_set_ui (NULL, 17);
163   y = gcry_mpi_set_ui (NULL, 42);
164   z = gcry_mpi_set_ui (NULL, 11371);
165   gcry_mpi_point_set (point, x, y, z);
166   gcry_mpi_set_ui (x, 23);
167   gcry_mpi_set_ui (y, 24);
168   gcry_mpi_set_ui (z, 25);
169   gcry_mpi_point_get (x, y, z, point);
170   if (gcry_mpi_cmp_ui (x, 17)
171       || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
172     fail ("point_set/point_get failed\n");
173   gcry_mpi_point_snatch_set (point, x, y, z);
174   x = gcry_mpi_new (0);
175   y = gcry_mpi_new (0);
176   z = gcry_mpi_new (0);
177   gcry_mpi_point_get (x, y, z, point);
178   if (gcry_mpi_cmp_ui (x, 17)
179       || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
180     fail ("point_snatch_set/point_get failed\n");
181
182   gcry_mpi_point_release (point);
183   gcry_mpi_release (x);
184   gcry_mpi_release (y);
185   gcry_mpi_release (z);
186 }
187
188
189 static void
190 context_alloc (void)
191 {
192   gcry_ctx_t ctx;
193   gcry_mpi_t p, a;
194
195   wherestr = "context_alloc";
196   show ("checking context functions\n");
197
198   p = gcry_mpi_set_ui (NULL, 1);
199   a = gcry_mpi_set_ui (NULL, 1);
200   ctx = gcry_mpi_ec_p_new (p, a);
201   if (!ctx)
202     die ("gcry_mpi_ec_p_new returned an error: %s\n",
203          gpg_strerror (gpg_error_from_syserror ()));
204   gcry_mpi_release (p);
205   gcry_mpi_release (a);
206   gcry_ctx_release (ctx);
207
208   p = gcry_mpi_set_ui (NULL, 0);
209   a = gcry_mpi_set_ui (NULL, 0);
210   ctx = gcry_mpi_ec_p_new (p, a);
211   if (ctx || gpg_err_code_from_syserror () != GPG_ERR_EINVAL)
212     fail ("gcry_mpi_ec_p_new: bad parameter detection failed (1)\n");
213
214   gcry_mpi_set_ui (p, 1);
215   ctx = gcry_mpi_ec_p_new (p, a);
216   if (ctx || gpg_err_code_from_syserror () != GPG_ERR_EINVAL)
217     fail ("gcry_mpi_ec_p_new: bad parameter detection failed (2)\n");
218
219   gcry_mpi_release (p);
220   p = NULL;
221   ctx = gcry_mpi_ec_p_new (p, a);
222   if (ctx || gpg_err_code_from_syserror () != GPG_ERR_EINVAL)
223     fail ("gcry_mpi_ec_p_new: bad parameter detection failed (3)\n");
224
225   gcry_mpi_release (a);
226   a = NULL;
227   ctx = gcry_mpi_ec_p_new (p, a);
228   if (ctx || gpg_err_code_from_syserror () != GPG_ERR_EINVAL)
229     fail ("gcry_mpi_ec_p_new: bad parameter detection failed (4)\n");
230
231 }
232
233
234 /* Create a new point from (X,Y,Z) given as hex strings.  */
235 gcry_mpi_point_t
236 make_point (const char *x, const char *y, const char *z)
237 {
238   gcry_mpi_point_t point;
239
240   point = gcry_mpi_point_new (0);
241   gcry_mpi_point_snatch_set (point, hex2mpi (x), hex2mpi (y), hex2mpi (z));
242
243   return point;
244 }
245
246
247 static void
248 basic_ec_math (void)
249 {
250   gcry_ctx_t ctx;
251   gcry_mpi_t P, A;
252   gcry_mpi_point_t G, Q;
253   gcry_mpi_t d;
254   gcry_mpi_t x, y, z;
255
256   wherestr = "set_get_point";
257   show ("checking basic math functions for EC\n");
258
259   P = hex2mpi ("0xfffffffffffffffffffffffffffffffeffffffffffffffff");
260   A = hex2mpi ("0xfffffffffffffffffffffffffffffffefffffffffffffffc");
261   G = make_point ("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
262                   "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
263                   "1");
264   d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
265   Q = gcry_mpi_point_new (0);
266
267   ctx = gcry_mpi_ec_p_new (P, A);
268   gcry_mpi_ec_mul (Q, d, G, ctx);
269
270   x = gcry_mpi_new (0);
271   y = gcry_mpi_new (0);
272   z = gcry_mpi_new (0);
273   gcry_mpi_point_get (x, y, z, Q);
274   if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
275       || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
276       || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
277     fail ("computed public key does not match\n");
278   if (debug)
279     {
280       print_mpi ("Q.x", x);
281       print_mpi ("Q.y", y);
282       print_mpi ("Q.z", z);
283     }
284
285   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
286     fail ("failed to get affine coordinates\n");
287   if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
288       || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
289     fail ("computed affine coordinates of public key do not match\n");
290   if (debug)
291     {
292       print_mpi ("q.x", x);
293       print_mpi ("q.y", y);
294     }
295
296   gcry_mpi_release (z);
297   gcry_mpi_release (y);
298   gcry_mpi_release (x);
299   gcry_mpi_point_release (Q);
300   gcry_mpi_release (d);
301   gcry_mpi_point_release (G);
302   gcry_mpi_release (A);
303   gcry_mpi_release (P);
304 }
305
306
307 int
308 main (int argc, char **argv)
309 {
310
311   if (argc > 1 && !strcmp (argv[1], "--verbose"))
312     verbose = 1;
313   else if (argc > 1 && !strcmp (argv[1], "--debug"))
314     verbose = debug = 1;
315
316   if (!gcry_check_version (GCRYPT_VERSION))
317     die ("version mismatch\n");
318
319   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
320   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
321   if (debug)
322     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
323   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
324
325   set_get_point ();
326   context_alloc ();
327   basic_ec_math ();
328
329   show ("All tests completed. Errors: %d\n", error_count);
330   return error_count ? 1 : 0;
331 }