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