1 /* t-convert.c - Tests for mpi print and scna functions
2 * Copyright (C) 2013 g10 Code GmbH
4 * This file is part of Libgcrypt.
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.
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.
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/>.
29 #include "../src/gcrypt-int.h"
31 #define PGM "t-convert"
33 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
34 #define DIMof(type,member) DIM(((type *)0)->member)
36 static const char *wherestr;
39 static int error_count;
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)
48 show (const char *format, ...)
54 fprintf (stderr, "%s: ", PGM);
55 va_start (arg_ptr, format);
56 vfprintf (stderr, format, arg_ptr);
61 showhex (const char *prefix, const void *buffer, size_t buflen)
63 const unsigned char *s;
67 fprintf (stderr, "%s: %s ", PGM, prefix);
68 for (s= buffer; buflen; buflen--, s++)
69 fprintf (stderr, "%02x", *s);
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
78 mpi2bitstr_nlz (gcry_mpi_t a)
81 size_t length = gcry_mpi_get_nbits (a);
85 buf = p = xmalloc (3);
91 buf = p = xmalloc (length + 1 + 1);
92 *p++ = gcry_mpi_is_neg (a)? '-':' ';
94 *p++ = gcry_mpi_test_bit (a, length) ? '1':'0';
95 *p++ = gcry_mpi_test_bit (a, 0) ? '1':'0';
103 showmpi (const char *prefix, gcry_mpi_t a)
109 bitstr = mpi2bitstr_nlz (a);
110 fprintf (stderr, "%s: %s%s\n", PGM, prefix, bitstr);
116 fail (const char *format, ...)
121 fprintf (stderr, "%s: ", PGM);
123 fprintf (stderr, "%s: ", wherestr);
124 va_start (arg_ptr, format);
125 vfprintf (stderr, format, arg_ptr);
131 die (const char *format, ...)
136 fprintf (stderr, "%s: ", PGM);
138 fprintf (stderr, "%s: ", wherestr);
139 va_start (arg_ptr, format);
140 vfprintf (stderr, format, arg_ptr);
146 /* Check that mpi_print does not return a negative zero. */
153 void *bufaddr = &buf;
154 struct { const char *name; enum gcry_mpi_format format; } fmts[] =
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 },
166 show ("negative zero printing\n");
168 a = gcry_mpi_new (0);
169 for (i=0; fmts[i].name; i++)
171 err = gcry_mpi_aprint (fmts[i].format, bufaddr, NULL, a);
173 fail ("error printing a zero as %s: %s\n",
174 fmts[i].name,gpg_strerror (err) );
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);
184 for (i=0; fmts[i].name; i++)
186 err = gcry_mpi_aprint (fmts[i].format, bufaddr, NULL, a);
188 fail ("error printing a negative zero as %s: %s\n",
189 fmts[i].name,gpg_strerror (err) );
194 gcry_mpi_release (a);
217 4, "\x00\x00\x00\x00",
223 5, "\x00\x00\x00\x01\x01",
229 5, "\x00\x00\x00\x01\x02",
235 5, "\x00\x00\x00\x01\x7f",
241 6, "\x00\x00\x00\x02\x00\x80",
247 6, "\x00\x00\x00\x02\x00\x81",
253 6, "\x00\x00\x00\x02\x00\xff",
259 6, "\x00\x00\x00\x02\x01\x00",
261 4, "\x00\x09\x01\x00" }
265 6, "\x00\x00\x00\x02\x01\x01",
267 4, "\x00\x09\x01\x01" }
271 5, "\x00\x00\x00\x01\xff",
276 5, "\x00\x00\x00\x01\xfe",
281 5, "\x00\x00\x00\x01\x81",
286 5, "\x00\x00\x00\x01\x80",
291 6, "\x00\x00\x00\x02\xff\x7f",
296 6, "\x00\x00\x00\x02\xff\x01",
301 6, "\x00\x00\x00\x02\xff\x00",
306 6, "\x00\x00\x00\x02\xfe\xff",
311 7, "\x00\x00\x00\x03\x00\xff\xff",
313 4, "\x00\x10\xff\xff" }
317 7, "\x00\x00\x00\x03\x01\x00\x00",
319 5, "\x00\x11\x01\x00\x00 "}
323 7, "\x00\x00\x00\x03\x01\x00\x01",
325 5, "\x00\x11\x01\x00\x01" }
327 { -65537, { "-010001",
329 7, "\x00\x00\x00\x03\xfe\xff\xff",
332 { -65536, { "-010000",
334 7, "\x00\x00\x00\x03\xff\x00\x00",
337 { -65535, { "-00FFFF",
339 7, "\x00\x00\x00\x03\xff\x00\x01",
346 void *bufaddr = &buf;
350 a = gcry_mpi_new (0);
351 for (idx=0; idx < DIM(data); idx++)
354 show ("print test %d\n", data[idx].value);
356 if (data[idx].value < 0)
358 gcry_mpi_set_ui (a, -data[idx].value);
362 gcry_mpi_set_ui (a, data[idx].value);
364 err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
366 fail ("error printing value %d as %s: %s\n",
367 data[idx].value, "HEX", gpg_strerror (err));
370 if (strcmp (buf, data[idx].a.hex))
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);
380 err = gcry_mpi_aprint (GCRYMPI_FMT_STD, bufaddr, &buflen, a);
382 fail ("error printing value %d as %s: %s\n",
383 data[idx].value, "STD", gpg_strerror (err));
386 if (buflen != data[idx].a.stdlen
387 || memcmp (buf, data[idx].a.std, data[idx].a.stdlen))
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);
397 err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, bufaddr, &buflen, a);
399 fail ("error printing value %d as %s: %s\n",
400 data[idx].value, "SSH", gpg_strerror (err));
403 if (buflen != data[idx].a.sshlen
404 || memcmp (buf, data[idx].a.ssh, data[idx].a.sshlen))
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);
414 err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufaddr, &buflen, a);
416 fail ("error printing value %d as %s: %s\n",
417 data[idx].value, "USG", gpg_strerror (err));
420 if (buflen != data[idx].a.usglen
421 || memcmp (buf, data[idx].a.usg, data[idx].a.usglen))
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);
431 err = gcry_mpi_aprint (GCRYMPI_FMT_PGP, bufaddr, &buflen, a);
432 if (gcry_mpi_is_neg (a))
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");
439 fail ("error printing value %d as %s: %s\n",
440 data[idx].value, "PGP", gpg_strerror (err));
443 if (buflen != data[idx].a.pgplen
444 || memcmp (buf, data[idx].a.pgp, data[idx].a.pgplen))
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);
456 /* Now for the other direction. */
457 for (idx=0; idx < DIM(data); idx++)
460 show ("scan test %d\n", data[idx].value);
462 if (data[idx].value < 0)
464 gcry_mpi_set_ui (a, -data[idx].value);
468 gcry_mpi_set_ui (a, data[idx].value);
470 err = gcry_mpi_scan (&b, GCRYMPI_FMT_HEX, data[idx].a.hex, 0, &buflen);
472 fail ("error scanning value %d from %s: %s\n",
473 data[idx].value, "HEX", gpg_strerror (err));
476 if (gcry_mpi_cmp (a, b))
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);
483 gcry_mpi_release (b);
486 err = gcry_mpi_scan (&b, GCRYMPI_FMT_STD,
487 data[idx].a.std, data[idx].a.stdlen, &buflen);
489 fail ("error scanning value %d as %s: %s\n",
490 data[idx].value, "STD", gpg_strerror (err));
493 if (gcry_mpi_cmp (a, b) || data[idx].a.stdlen != buflen)
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);
500 gcry_mpi_release (b);
503 err = gcry_mpi_scan (&b, GCRYMPI_FMT_SSH,
504 data[idx].a.ssh, data[idx].a.sshlen, &buflen);
506 fail ("error scanning value %d as %s: %s\n",
507 data[idx].value, "SSH", gpg_strerror (err));
510 if (gcry_mpi_cmp (a, b) || data[idx].a.sshlen != buflen)
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);
517 gcry_mpi_release (b);
520 err = gcry_mpi_scan (&b, GCRYMPI_FMT_USG,
521 data[idx].a.usg, data[idx].a.usglen, &buflen);
523 fail ("error scanning value %d as %s: %s\n",
524 data[idx].value, "USG", gpg_strerror (err));
527 if (gcry_mpi_is_neg (a))
529 if (gcry_mpi_cmp (a, b) || data[idx].a.usglen != buflen)
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);
536 gcry_mpi_release (b);
539 /* Negative values are not supported by PGP, thus we don't have
541 if (!gcry_mpi_is_neg (a))
543 err = gcry_mpi_scan (&b, GCRYMPI_FMT_PGP,
544 data[idx].a.pgp, data[idx].a.pgplen, &buflen);
546 fail ("error scanning value %d as %s: %s\n",
547 data[idx].value, "PGP", gpg_strerror (err));
550 if (gcry_mpi_cmp (a, b) || data[idx].a.pgplen != buflen)
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);
557 gcry_mpi_release (b);
562 gcry_mpi_release (a);
567 main (int argc, char **argv)
569 if (argc > 1 && !strcmp (argv[1], "--verbose"))
571 else if (argc > 1 && !strcmp (argv[1], "--debug"))
574 if (!gcry_check_version (GCRYPT_VERSION))
575 die ("version mismatch\n");
577 gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
578 gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
580 gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
581 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
586 show ("All tests completed. Errors: %d\n", error_count);
587 return error_count ? 1 : 0;