mpi/ec: fix when 'unsigned long' is 32-bit but limb size is 64-bit
[libgcrypt.git] / tests / t-convert.c
1 /* t-convert.c  - Tests for mpi print and scna 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-convert"
30 #include "t-common.h"
31
32
33 static void
34 showhex (const char *prefix, const void *buffer, size_t buflen)
35 {
36   const unsigned char *s;
37
38   if (!verbose)
39     return;
40   fprintf (stderr, "%s: %s ", PGM, prefix);
41   for (s= buffer; buflen; buflen--, s++)
42     fprintf (stderr, "%02x", *s);
43   putc ('\n', stderr);
44 }
45
46
47 /* Allocate a bit string consisting of '0' and '1' from the MPI A.  Do
48    not return any leading zero bits.  Caller needs to gcry_free the
49    result. */
50 static char *
51 mpi2bitstr_nlz (gcry_mpi_t a)
52 {
53   char *p, *buf;
54   size_t length = gcry_mpi_get_nbits (a);
55
56   if (!length)
57     {
58       buf = p = xmalloc (3);
59       *p++ = ' ';
60       *p++ = '0';
61     }
62   else
63     {
64       buf = p = xmalloc (length + 1 + 1);
65       *p++ = gcry_mpi_is_neg (a)? '-':' ';
66       while (length-- > 1)
67         *p++ = gcry_mpi_test_bit (a, length) ? '1':'0';
68       *p++ = gcry_mpi_test_bit (a, 0) ? '1':'0';
69     }
70   *p = 0;
71   return buf;
72 }
73
74
75 static void
76 showmpi (const char *prefix, gcry_mpi_t a)
77 {
78   char *bitstr;
79
80   if (!verbose)
81     return;
82   bitstr = mpi2bitstr_nlz (a);
83   fprintf (stderr, "%s: %s%s\n", PGM, prefix, bitstr);
84   xfree (bitstr);
85 }
86
87
88 /* Check that mpi_print does not return a negative zero.  */
89 static void
90 negative_zero (void)
91 {
92   gpg_error_t err;
93   gcry_mpi_t a;
94   char *buf;
95   void *bufaddr = &buf;
96   struct { const char *name; enum gcry_mpi_format format; } fmts[] =
97     {
98       { "STD", GCRYMPI_FMT_STD },
99       { "PGP", GCRYMPI_FMT_PGP },
100       { "SSH", GCRYMPI_FMT_SSH },
101       { "HEX", GCRYMPI_FMT_HEX },
102       { "USG", GCRYMPI_FMT_USG },
103       { NULL, 0 }
104     };
105   int i;
106
107   if (debug)
108     info ("negative zero printing\n");
109
110   a = gcry_mpi_new (0);
111   for (i=0; fmts[i].name; i++)
112     {
113       err = gcry_mpi_aprint (fmts[i].format, bufaddr, NULL, a);
114       if (err)
115         fail ("error printing a zero as %s: %s\n",
116               fmts[i].name,gpg_strerror (err) );
117       else
118         gcry_free (buf);
119     }
120
121   /* With the current version of libgcrypt the next two statements
122      should set a to -0. */
123   gcry_mpi_sub_ui (a, a, 1);
124   gcry_mpi_add_ui (a, a, 1);
125
126   for (i=0; fmts[i].name; i++)
127     {
128       err = gcry_mpi_aprint (fmts[i].format, bufaddr, NULL, a);
129       if (err)
130         fail ("error printing a negative zero as %s: %s\n",
131               fmts[i].name,gpg_strerror (err) );
132       else
133         gcry_free (buf);
134     }
135
136   gcry_mpi_release (a);
137 }
138
139
140 static void
141 check_formats (void)
142 {
143   static struct {
144     int value;
145     struct {
146       const char *hex;
147       size_t stdlen;
148       const char *std;
149       size_t sshlen;
150       const char *ssh;
151       size_t usglen;
152       const char *usg;
153       size_t pgplen;
154       const char *pgp;
155     } a;
156   } data[] = {
157     {    0, { "00",
158               0, "",
159               4, "\x00\x00\x00\x00",
160               0, "",
161               2, "\x00\x00"}
162     },
163     {    1, { "01",
164               1, "\x01",
165               5, "\x00\x00\x00\x01\x01",
166               1, "\x01",
167               3, "\x00\x01\x01" }
168     },
169     {    2, { "02",
170               1, "\x02",
171               5, "\x00\x00\x00\x01\x02",
172               1, "\x02",
173               3, "\x00\x02\x02" }
174     },
175     {  127, { "7F",
176               1, "\x7f",
177               5, "\x00\x00\x00\x01\x7f",
178               1, "\x7f",
179               3, "\x00\x07\x7f" }
180     },
181     {  128, { "0080",
182               2, "\x00\x80",
183               6, "\x00\x00\x00\x02\x00\x80",
184               1, "\x80",
185               3, "\x00\x08\x80" }
186     },
187     {  129, { "0081",
188               2, "\x00\x81",
189               6, "\x00\x00\x00\x02\x00\x81",
190               1, "\x81",
191               3, "\x00\x08\x81" }
192     },
193     {  255, { "00FF",
194               2, "\x00\xff",
195               6, "\x00\x00\x00\x02\x00\xff",
196               1, "\xff",
197               3, "\x00\x08\xff" }
198     },
199     {  256, { "0100",
200               2, "\x01\x00",
201               6, "\x00\x00\x00\x02\x01\x00",
202               2, "\x01\x00",
203               4, "\x00\x09\x01\x00" }
204     },
205     {  257, { "0101",
206               2, "\x01\x01",
207               6, "\x00\x00\x00\x02\x01\x01",
208               2, "\x01\x01",
209               4, "\x00\x09\x01\x01" }
210     },
211     {   -1, { "-01",
212               1, "\xff",
213               5, "\x00\x00\x00\x01\xff",
214               1,"\x01" }
215     },
216     {   -2, { "-02",
217               1, "\xfe",
218               5, "\x00\x00\x00\x01\xfe",
219               1, "\x02" }
220     },
221     { -127, { "-7F",
222               1, "\x81",
223               5, "\x00\x00\x00\x01\x81",
224               1, "\x7f" }
225     },
226     { -128, { "-0080",
227               1, "\x80",
228               5, "\x00\x00\x00\x01\x80",
229               1, "\x80" }
230     },
231     { -129, { "-0081",
232               2, "\xff\x7f",
233               6, "\x00\x00\x00\x02\xff\x7f",
234               1, "\x81" }
235     },
236     { -255, { "-00FF",
237               2, "\xff\x01",
238               6, "\x00\x00\x00\x02\xff\x01",
239               1, "\xff" }
240     },
241     { -256, { "-0100",
242               2, "\xff\x00",
243               6, "\x00\x00\x00\x02\xff\x00",
244               2, "\x01\x00" }
245     },
246     { -257, { "-0101",
247               2, "\xfe\xff",
248               6, "\x00\x00\x00\x02\xfe\xff",
249               2, "\x01\x01" }
250     },
251     {  65535, { "00FFFF",
252                 3, "\x00\xff\xff",
253                 7, "\x00\x00\x00\x03\x00\xff\xff",
254                 2, "\xff\xff",
255                 4, "\x00\x10\xff\xff" }
256     },
257     {  65536, { "010000",
258                 3, "\x01\00\x00",
259                 7, "\x00\x00\x00\x03\x01\x00\x00",
260                 3, "\x01\x00\x00",
261                 5, "\x00\x11\x01\x00\x00 "}
262     },
263     {  65537, { "010001",
264                 3, "\x01\00\x01",
265                 7, "\x00\x00\x00\x03\x01\x00\x01",
266                 3, "\x01\x00\x01",
267                 5, "\x00\x11\x01\x00\x01" }
268     },
269     { -65537, { "-010001",
270                 3, "\xfe\xff\xff",
271                 7, "\x00\x00\x00\x03\xfe\xff\xff",
272                 3, "\x01\x00\x01" }
273     },
274     { -65536, { "-010000",
275                 3, "\xff\x00\x00",
276                 7, "\x00\x00\x00\x03\xff\x00\x00",
277                 3, "\x01\x00\x00" }
278     },
279     { -65535, { "-00FFFF",
280                 3, "\xff\x00\x01",
281                 7, "\x00\x00\x00\x03\xff\x00\x01",
282                 2, "\xff\xff" }
283     }
284   };
285   gpg_error_t err;
286   gcry_mpi_t a, b;
287   char *buf;
288   void *bufaddr = &buf;
289   int idx;
290   size_t buflen;
291
292   a = gcry_mpi_new (0);
293   for (idx=0; idx < DIM(data); idx++)
294     {
295       if (debug)
296         info ("print test %d\n", data[idx].value);
297
298       if (data[idx].value < 0)
299         {
300           gcry_mpi_set_ui (a, -data[idx].value);
301           gcry_mpi_neg (a, a);
302         }
303       else
304         gcry_mpi_set_ui (a, data[idx].value);
305
306       err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
307       if (err)
308         fail ("error printing value %d as %s: %s\n",
309               data[idx].value, "HEX", gpg_strerror (err));
310       else
311         {
312           if (strcmp (buf, data[idx].a.hex))
313             {
314               fail ("error printing value %d as %s: %s\n",
315                     data[idx].value, "HEX", "wrong result");
316               info ("expected: '%s'\n", data[idx].a.hex);
317               info ("     got: '%s'\n", buf);
318             }
319           gcry_free (buf);
320         }
321
322       err = gcry_mpi_aprint (GCRYMPI_FMT_STD, bufaddr, &buflen, a);
323       if (err)
324         fail ("error printing value %d as %s: %s\n",
325               data[idx].value, "STD", gpg_strerror (err));
326       else
327         {
328           if (buflen != data[idx].a.stdlen
329               || memcmp (buf, data[idx].a.std, data[idx].a.stdlen))
330             {
331               fail ("error printing value %d as %s: %s\n",
332                     data[idx].value, "STD", "wrong result");
333               showhex ("expected:", data[idx].a.std, data[idx].a.stdlen);
334               showhex ("     got:", buf, buflen);
335             }
336           gcry_free (buf);
337         }
338
339       err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, bufaddr, &buflen, a);
340       if (err)
341         fail ("error printing value %d as %s: %s\n",
342               data[idx].value, "SSH", gpg_strerror (err));
343       else
344         {
345           if (buflen != data[idx].a.sshlen
346               || memcmp (buf, data[idx].a.ssh, data[idx].a.sshlen))
347             {
348               fail ("error printing value %d as %s: %s\n",
349                     data[idx].value, "SSH", "wrong result");
350               showhex ("expected:", data[idx].a.ssh, data[idx].a.sshlen);
351               showhex ("     got:", buf, buflen);
352             }
353           gcry_free (buf);
354         }
355
356       err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufaddr, &buflen, a);
357       if (err)
358         fail ("error printing value %d as %s: %s\n",
359               data[idx].value, "USG", gpg_strerror (err));
360       else
361         {
362           if (buflen != data[idx].a.usglen
363               || memcmp (buf, data[idx].a.usg, data[idx].a.usglen))
364             {
365               fail ("error printing value %d as %s: %s\n",
366                     data[idx].value, "USG", "wrong result");
367               showhex ("expected:", data[idx].a.usg, data[idx].a.usglen);
368               showhex ("     got:", buf, buflen);
369             }
370           gcry_free (buf);
371         }
372
373       err = gcry_mpi_aprint (GCRYMPI_FMT_PGP, bufaddr, &buflen, a);
374       if (gcry_mpi_is_neg (a))
375         {
376           if (gpg_err_code (err) != GPG_ERR_INV_ARG)
377             fail ("error printing value %d as %s: %s\n",
378                   data[idx].value, "PGP", "Expected error not returned");
379         }
380       else if (err)
381         fail ("error printing value %d as %s: %s\n",
382               data[idx].value, "PGP", gpg_strerror (err));
383       else
384         {
385           if (buflen != data[idx].a.pgplen
386               || memcmp (buf, data[idx].a.pgp, data[idx].a.pgplen))
387             {
388               fail ("error printing value %d as %s: %s\n",
389                     data[idx].value, "PGP", "wrong result");
390               showhex ("expected:", data[idx].a.pgp, data[idx].a.pgplen);
391               showhex ("     got:", buf, buflen);
392             }
393           gcry_free (buf);
394         }
395     }
396
397
398   /* Now for the other direction.  */
399   for (idx=0; idx < DIM(data); idx++)
400     {
401       if (debug)
402         info ("scan test %d\n", data[idx].value);
403
404       if (data[idx].value < 0)
405         {
406           gcry_mpi_set_ui (a, -data[idx].value);
407           gcry_mpi_neg (a, a);
408         }
409       else
410         gcry_mpi_set_ui (a, data[idx].value);
411
412       err = gcry_mpi_scan (&b, GCRYMPI_FMT_HEX, data[idx].a.hex, 0, &buflen);
413       if (err)
414         fail ("error scanning value %d from %s: %s\n",
415               data[idx].value, "HEX", gpg_strerror (err));
416       else
417         {
418           if (gcry_mpi_cmp (a, b))
419             {
420               fail ("error scanning value %d from %s: %s\n",
421                     data[idx].value, "HEX", "wrong result");
422               showmpi ("expected:", a);
423               showmpi ("     got:", b);
424             }
425           gcry_mpi_release (b);
426         }
427
428       err = gcry_mpi_scan (&b, GCRYMPI_FMT_STD,
429                            data[idx].a.std, data[idx].a.stdlen, &buflen);
430       if (err)
431         fail ("error scanning value %d as %s: %s\n",
432               data[idx].value, "STD", gpg_strerror (err));
433       else
434         {
435           if (gcry_mpi_cmp (a, b) || data[idx].a.stdlen != buflen)
436             {
437               fail ("error scanning value %d from %s: %s (%lu)\n",
438                     data[idx].value, "STD", "wrong result",
439                     (long unsigned int)buflen);
440               showmpi ("expected:", a);
441               showmpi ("     got:", b);
442             }
443           gcry_mpi_release (b);
444         }
445
446       err = gcry_mpi_scan (&b, GCRYMPI_FMT_SSH,
447                            data[idx].a.ssh, data[idx].a.sshlen, &buflen);
448       if (err)
449         fail ("error scanning value %d as %s: %s\n",
450               data[idx].value, "SSH", gpg_strerror (err));
451       else
452         {
453           if (gcry_mpi_cmp (a, b) || data[idx].a.sshlen != buflen)
454             {
455               fail ("error scanning value %d from %s: %s (%lu)\n",
456                     data[idx].value, "SSH", "wrong result",
457                     (long unsigned int)buflen);
458               showmpi ("expected:", a);
459               showmpi ("     got:", b);
460             }
461           gcry_mpi_release (b);
462         }
463
464       err = gcry_mpi_scan (&b, GCRYMPI_FMT_USG,
465                            data[idx].a.usg, data[idx].a.usglen, &buflen);
466       if (err)
467         fail ("error scanning value %d as %s: %s\n",
468               data[idx].value, "USG", gpg_strerror (err));
469       else
470         {
471           if (gcry_mpi_is_neg (a))
472             gcry_mpi_neg (b, b);
473           if (gcry_mpi_cmp (a, b) || data[idx].a.usglen != buflen)
474             {
475               fail ("error scanning value %d from %s: %s (%lu)\n",
476                     data[idx].value, "USG", "wrong result",
477                     (long unsigned int)buflen);
478               showmpi ("expected:", a);
479               showmpi ("     got:", b);
480             }
481           gcry_mpi_release (b);
482         }
483
484       /* Negative values are not supported by PGP, thus we don't have
485          an samples.  */
486       if (!gcry_mpi_is_neg (a))
487         {
488           err = gcry_mpi_scan (&b, GCRYMPI_FMT_PGP,
489                                data[idx].a.pgp, data[idx].a.pgplen, &buflen);
490           if (err)
491             fail ("error scanning value %d as %s: %s\n",
492                   data[idx].value, "PGP", gpg_strerror (err));
493           else
494             {
495               if (gcry_mpi_cmp (a, b) || data[idx].a.pgplen != buflen)
496                 {
497                   fail ("error scanning value %d from %s: %s (%lu)\n",
498                         data[idx].value, "PGP", "wrong result",
499                         (long unsigned int)buflen);
500                   showmpi ("expected:", a);
501                   showmpi ("     got:", b);
502                 }
503               gcry_mpi_release (b);
504             }
505         }
506     }
507
508   gcry_mpi_release (a);
509 }
510
511
512 int
513 main (int argc, char **argv)
514 {
515   if (argc > 1 && !strcmp (argv[1], "--verbose"))
516     verbose = 1;
517   else if (argc > 1 && !strcmp (argv[1], "--debug"))
518     verbose = debug = 1;
519
520   if (!gcry_check_version (GCRYPT_VERSION))
521     die ("version mismatch\n");
522
523   xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
524   xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
525   if (debug)
526     xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
527   xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
528
529   negative_zero ();
530   check_formats ();
531
532   info ("All tests completed. Errors: %d\n", error_count);
533   return error_count ? 1 : 0;
534 }