summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2013-09-07 10:06:46 +0200
committerWerner Koch <wk@gnupg.org>2013-09-17 15:22:15 +0200
commit89fe2173649a72019d75e059e6c6938efd10421f (patch)
tree2dca440a3424ed505d7015cdaf530f873b5b6467 /tests
parenta7a9cdcaaf3979baa18dad51e722882581349f45 (diff)
downloadlibgcrypt-89fe2173649a72019d75e059e6c6938efd10421f.tar.gz
mpi: Support printing of negative numbers.
* mpi/mpicoder.c (twocompl, onecompl): New. (gcry_mpi_print): Use it for STD and SSH. (gcry_mpi_scan): Use it for STD and SSH. Always set NSCANNED. (gcry_mpi_aprint): Clear the extra allocated byte. * tests/t-convert.c (showhex, showmpi): New. (mpi2bitstr_nlz): New. (check_formats): New. (main): Call new test. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/t-convert.c374
1 files changed, 369 insertions, 5 deletions
diff --git a/tests/t-convert.c b/tests/t-convert.c
index b7f97fa3..d44c4395 100644
--- a/tests/t-convert.c
+++ b/tests/t-convert.c
@@ -28,7 +28,10 @@
#include "../src/gcrypt-int.h"
-#define PGM "t-mpi-point"
+#define PGM "t-convert"
+
+#define DIM(v) (sizeof(v)/sizeof((v)[0]))
+#define DIMof(type,member) DIM(((type *)0)->member)
static const char *wherestr;
static int verbose;
@@ -55,6 +58,61 @@ show (const char *format, ...)
}
static void
+showhex (const char *prefix, const void *buffer, size_t buflen)
+{
+ const unsigned char *s;
+
+ if (!verbose)
+ return;
+ fprintf (stderr, "%s: %s ", PGM, prefix);
+ for (s= buffer; buflen; buflen--, s++)
+ fprintf (stderr, "%02x", *s);
+ putc ('\n', stderr);
+}
+
+
+/* Allocate a bit string consisting of '0' and '1' from the MPI A. Do
+ not return any leading zero bits. Caller needs to gcry_free the
+ result. */
+static char *
+mpi2bitstr_nlz (gcry_mpi_t a)
+{
+ char *p, *buf;
+ size_t length = gcry_mpi_get_nbits (a);
+
+ if (!length)
+ {
+ buf = p = xmalloc (3);
+ *p++ = ' ';
+ *p++ = '0';
+ }
+ else
+ {
+ buf = p = xmalloc (length + 1 + 1);
+ *p++ = gcry_mpi_is_neg (a)? '-':' ';
+ while (length-- > 1)
+ *p++ = gcry_mpi_test_bit (a, length) ? '1':'0';
+ *p++ = gcry_mpi_test_bit (a, 0) ? '1':'0';
+ }
+ *p = 0;
+ return buf;
+}
+
+
+static void
+showmpi (const char *prefix, gcry_mpi_t a)
+{
+ char *bitstr;
+
+ if (!verbose)
+ return;
+ bitstr = mpi2bitstr_nlz (a);
+ fprintf (stderr, "%s: %s%s\n", PGM, prefix, bitstr);
+ xfree (bitstr);
+}
+
+
+static void
fail (const char *format, ...)
{
va_list arg_ptr;
@@ -95,10 +153,10 @@ negative_zero (void)
void *bufaddr = &buf;
struct { const char *name; enum gcry_mpi_format format; } fmts[] =
{
- { "STD", GCRYMPI_FMT_STD },
- { "PGP", GCRYMPI_FMT_PGP },
- { "SSH", GCRYMPI_FMT_SSH },
- { "HEX", GCRYMPI_FMT_HEX },
+ /* { "STD", GCRYMPI_FMT_STD }, */
+ /* { "PGP", GCRYMPI_FMT_PGP }, */
+ /* { "SSH", GCRYMPI_FMT_SSH }, */
+ /* { "HEX", GCRYMPI_FMT_HEX }, */
{ "USG", GCRYMPI_FMT_USG },
{ NULL, 0 }
};
@@ -134,6 +192,311 @@ negative_zero (void)
}
+static void
+check_formats (void)
+{
+ static struct {
+ int value;
+ struct {
+ const char *hex;
+ size_t stdlen;
+ const char *std;
+ size_t sshlen;
+ const char *ssh;
+ size_t usglen;
+ const char *usg;
+ } a;
+ } data[] = {
+ { 0, { "00",
+ 0, "",
+ 4, "\x00\x00\x00\x00",
+ 0, "" }
+ },
+ { 1, { "01",
+ 1, "\x01",
+ 5, "\x00\x00\x00\x01\x01",
+ 1, "\x01" }
+ },
+ { 2, { "02",
+ 1, "\x02",
+ 5, "\x00\x00\x00\x01\x02",
+ 1, "\x02", }
+ },
+ { 127, { "7F",
+ 1, "\x7f",
+ 5, "\x00\x00\x00\x01\x7f",
+ 1, "\x7f" }
+ },
+ { 128, { "0080",
+ 2, "\x00\x80",
+ 6, "\x00\x00\x00\x02\x00\x80",
+ 1, "\x80" }
+ },
+ { 129, { "0081",
+ 2, "\x00\x81",
+ 6, "\x00\x00\x00\x02\x00\x81",
+ 1, "\x81" }
+ },
+ { 255, { "00FF",
+ 2, "\x00\xff",
+ 6, "\x00\x00\x00\x02\x00\xff",
+ 1, "\xff" }
+ },
+ { 256, { "0100",
+ 2, "\x01\x00",
+ 6, "\x00\x00\x00\x02\x01\x00",
+ 2, "\x01\x00" }
+ },
+ { 257, { "0101",
+ 2, "\x01\x01",
+ 6, "\x00\x00\x00\x02\x01\x01",
+ 2, "\x01\x01" }
+ },
+ { -1, { "-01",
+ 1, "\xff",
+ 5, "\x00\x00\x00\x01\xff",
+ 1,"\x01" }
+ },
+ { -2, { "-02",
+ 1, "\xfe",
+ 5, "\x00\x00\x00\x01\xfe",
+ 1, "\x02" }
+ },
+ { -127, { "-7F",
+ 1, "\x81",
+ 5, "\x00\x00\x00\x01\x81",
+ 1, "\x7f" }
+ },
+ { -128, { "-0080",
+ 1, "\x80",
+ 5, "\x00\x00\x00\x01\x80",
+ 1, "\x80" }
+ },
+ { -129, { "-0081",
+ 2, "\xff\x7f",
+ 6, "\x00\x00\x00\x02\xff\x7f",
+ 1, "\x81" }
+ },
+ { -255, { "-00FF",
+ 2, "\xff\x01",
+ 6, "\x00\x00\x00\x02\xff\x01",
+ 1, "\xff" }
+ },
+ { -256, { "-0100",
+ 2, "\xff\x00",
+ 6, "\x00\x00\x00\x02\xff\x00",
+ 2, "\x01\x00" }
+ },
+ { -257, { "-0101",
+ 2, "\xfe\xff",
+ 6, "\x00\x00\x00\x02\xfe\xff",
+ 2, "\x01\x01" }
+ },
+ { 65535, { "00FFFF",
+ 3, "\x00\xff\xff",
+ 7, "\x00\x00\x00\x03\x00\xff\xff",
+ 2, "\xff\xff" }
+ },
+ { 65536, { "010000",
+ 3, "\x01\00\x00",
+ 7, "\x00\x00\x00\x03\x01\x00\x00",
+ 3, "\x01\x00\x00" }
+ },
+ { 65537, { "010001",
+ 3, "\x01\00\x01",
+ 7, "\x00\x00\x00\x03\x01\x00\x01",
+ 3, "\x01\x00\x01" }
+ },
+ { -65537, { "-010001",
+ 3, "\xfe\xff\xff",
+ 7, "\x00\x00\x00\x03\xfe\xff\xff",
+ 3, "\x01\x00\x01" }
+ },
+ { -65536, { "-010000",
+ 3, "\xff\x00\x00",
+ 7, "\x00\x00\x00\x03\xff\x00\x00",
+ 3, "\x01\x00\x00" }
+ },
+ { -65535, { "-00FFFF",
+ 3, "\xff\x00\x01",
+ 7, "\x00\x00\x00\x03\xff\x00\x01",
+ 2, "\xff\xff" }
+ }
+ };
+ gpg_error_t err;
+ gcry_mpi_t a, b;
+ char *buf;
+ void *bufaddr = &buf;
+ int idx;
+ size_t buflen;
+
+ a = gcry_mpi_new (0);
+ for (idx=0; idx < DIM(data); idx++)
+ {
+ if (debug)
+ show ("print test %d\n", data[idx].value);
+
+ if (data[idx].value < 0)
+ {
+ gcry_mpi_set_ui (a, -data[idx].value);
+ gcry_mpi_neg (a, a);
+ }
+ else
+ gcry_mpi_set_ui (a, data[idx].value);
+
+ err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
+ if (err)
+ fail ("error printing value %d as %s: %s\n",
+ data[idx].value, "HEX", gpg_strerror (err));
+ else
+ {
+ if (strcmp (buf, data[idx].a.hex))
+ {
+ fail ("error printing value %d as %s: %s\n",
+ data[idx].value, "HEX", "wrong result");
+ show ("expected: '%s'\n", data[idx].a.hex);
+ show (" got: '%s'\n", buf);
+ }
+ gcry_free (buf);
+ }
+
+ err = gcry_mpi_aprint (GCRYMPI_FMT_STD, bufaddr, &buflen, a);
+ if (err)
+ fail ("error printing value %d as %s: %s\n",
+ data[idx].value, "STD", gpg_strerror (err));
+ else
+ {
+ if (buflen != data[idx].a.stdlen
+ || memcmp (buf, data[idx].a.std, data[idx].a.stdlen))
+ {
+ fail ("error printing value %d as %s: %s\n",
+ data[idx].value, "STD", "wrong result");
+ showhex ("expected:", data[idx].a.std, data[idx].a.stdlen);
+ showhex (" got:", buf, buflen);
+ }
+ gcry_free (buf);
+ }
+
+ err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, bufaddr, &buflen, a);
+ if (err)
+ fail ("error printing value %d as %s: %s\n",
+ data[idx].value, "SSH", gpg_strerror (err));
+ else
+ {
+ if (buflen != data[idx].a.sshlen
+ || memcmp (buf, data[idx].a.ssh, data[idx].a.sshlen))
+ {
+ fail ("error printing value %d as %s: %s\n",
+ data[idx].value, "SSH", "wrong result");
+ showhex ("expected:", data[idx].a.ssh, data[idx].a.sshlen);
+ showhex (" got:", buf, buflen);
+ }
+ gcry_free (buf);
+ }
+
+ err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufaddr, &buflen, a);
+ if (err)
+ fail ("error printing value %d as %s: %s\n",
+ data[idx].value, "USG", gpg_strerror (err));
+ else
+ {
+ if (buflen != data[idx].a.usglen
+ || memcmp (buf, data[idx].a.usg, data[idx].a.usglen))
+ {
+ fail ("error printing value %d as %s: %s\n",
+ data[idx].value, "USG", "wrong result");
+ showhex ("expected:", data[idx].a.usg, data[idx].a.usglen);
+ showhex (" got:", buf, buflen);
+ }
+ gcry_free (buf);
+ }
+ }
+
+
+ /* Now for the other direction. */
+ for (idx=0; idx < DIM(data); idx++)
+ {
+ if (debug)
+ show ("scan test %d\n", data[idx].value);
+
+ if (data[idx].value < 0)
+ {
+ gcry_mpi_set_ui (a, -data[idx].value);
+ gcry_mpi_neg (a, a);
+ }
+ else
+ gcry_mpi_set_ui (a, data[idx].value);
+
+ err = gcry_mpi_scan (&b, GCRYMPI_FMT_HEX, data[idx].a.hex, 0, &buflen);
+ if (err)
+ fail ("error scanning value %d from %s: %s\n",
+ data[idx].value, "HEX", gpg_strerror (err));
+ else
+ {
+ if (gcry_mpi_cmp (a, b))
+ {
+ fail ("error scanning value %d from %s: %s\n",
+ data[idx].value, "HEX", "wrong result");
+ showmpi ("expected:", a);
+ showmpi (" got:", b);
+ }
+ gcry_mpi_release (b);
+ }
+
+ err = gcry_mpi_scan (&b, GCRYMPI_FMT_STD,
+ data[idx].a.std, data[idx].a.stdlen, &buflen);
+ if (err)
+ fail ("error scanning value %d as %s: %s\n",
+ data[idx].value, "STD", gpg_strerror (err));
+ else
+ {
+ if (gcry_mpi_cmp (a, b) || data[idx].a.stdlen != buflen)
+ {
+ fail ("error scanning value %d from %s: %s (%u)\n",
+ data[idx].value, "STD", "wrong result", buflen);
+ showmpi ("expected:", a);
+ showmpi (" got:", b);
+ }
+ gcry_mpi_release (b);
+ }
+
+ err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, bufaddr, &buflen, a);
+ if (err)
+ fail ("error printing value %d as %s: %s\n",
+ data[idx].value, "SSH", gpg_strerror (err));
+ else
+ {
+ if (buflen != data[idx].a.sshlen
+ || memcmp (buf, data[idx].a.ssh, data[idx].a.sshlen))
+ {
+ fail ("error printing value %d as %s: %s\n",
+ data[idx].value, "SSH", "wrong result");
+ showhex ("expected:", data[idx].a.ssh, data[idx].a.sshlen);
+ showhex (" got:", buf, buflen);
+ }
+ gcry_free (buf);
+ }
+
+ err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufaddr, &buflen, a);
+ if (err)
+ fail ("error printing value %d as %s: %s\n",
+ data[idx].value, "USG", gpg_strerror (err));
+ else
+ {
+ if (buflen != data[idx].a.usglen
+ || memcmp (buf, data[idx].a.usg, data[idx].a.usglen))
+ {
+ fail ("error printing value %d as %s: %s\n",
+ data[idx].value, "USG", "wrong result");
+ showhex ("expected:", data[idx].a.usg, data[idx].a.usglen);
+ showhex (" got:", buf, buflen);
+ }
+ gcry_free (buf);
+ }
+ }
+
+ gcry_mpi_release (a);
+}
int
@@ -154,6 +517,7 @@ main (int argc, char **argv)
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
negative_zero ();
+ check_formats ();
show ("All tests completed. Errors: %d\n", error_count);
return error_count ? 1 : 0;