diff options
author | Werner Koch <wk@gnupg.org> | 2013-09-07 10:06:46 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2013-09-17 15:22:15 +0200 |
commit | 89fe2173649a72019d75e059e6c6938efd10421f (patch) | |
tree | 2dca440a3424ed505d7015cdaf530f873b5b6467 /tests | |
parent | a7a9cdcaaf3979baa18dad51e722882581349f45 (diff) | |
download | libgcrypt-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.c | 374 |
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; |