From ee4d4642216dd04c84a360a5dd59c090e095114c Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 20 Aug 2008 14:10:11 +0000 Subject: Implemented gcry_mpi_lshift. Reordered some code in mpi-bit.c --- tests/t-mpi-bit.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 116 insertions(+), 3 deletions(-) (limited to 'tests/t-mpi-bit.c') diff --git a/tests/t-mpi-bit.c b/tests/t-mpi-bit.c index 2465a8fd..208a1271 100644 --- a/tests/t-mpi-bit.c +++ b/tests/t-mpi-bit.c @@ -100,6 +100,24 @@ mpi2bitstr (gcry_mpi_t a, size_t length) return buf; } +/* Allocate a bit string consisting of '0' and '1' from the MPI A. Do + not return any leading zero bits. Caller needs to xfree the + result. */ +static char * +mpi2bitstr_nlz (gcry_mpi_t a) +{ + char *p, *buf; + size_t length = gcry_mpi_get_nbits (a); + + buf = p = xmalloc (length + 1); + 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; +} + /* Shift a bit string to the right. */ static void rshiftbitstring (char *string, size_t n) @@ -113,6 +131,28 @@ rshiftbitstring (char *string, size_t n) memset (string, '0', n); } +/* Shift a bit string to the left. Caller needs to free the result. */ +static char * +lshiftbitstring (const char *string, size_t n) +{ + size_t len = strlen (string); + char *result; + + if (len+n+1 < len) + die ("internal overflow\n"); + /* Allocate enough space. */ + result = xmalloc (len+n+1); + for (; *string == '0' && string[1]; string++, len--) + ; + memcpy (result, string, len); + if (*string == '0' && !string[1]) + n = 0; /* Avoid extra nulls for an only 0 string. */ + else + memset (result+len, '0', n); + result[len+n] = 0; + return result; +} + /* This is to check a bug reported by bpgcrypt at itaparica.org on 2006-07-31 against libgcrypt 1.2.2. */ @@ -141,7 +181,6 @@ one_bit_only (int highbit) fail ("failed to clear a bit\n"); result = mpi2bitstr (a, 70); assert (strlen (result) == 70); - show ("r=%s\n", result); for (i=0; result[i]; i++) if ( result[i] != '0' ) break; @@ -210,6 +249,76 @@ test_rshift (int pass) gcry_mpi_release (a); } +/* Check that the left shifting. */ +static void +test_lshift (int pass) +{ + static int size_list[] = {1, 31, 32, 63, 64, 65, 70, 0}; + int size_idx; + gcry_mpi_t a, b; + char *tmpstr, *result, *result2; + int i; + + wherestr = "test_lshift"; + show ("checking that lshift works as expected (pass %d)\n", pass); + + for (size_idx=0; size_list[size_idx]; size_idx++) + { + a = gcry_mpi_new (0); + b = gcry_mpi_new (0); + + /* gcry_mpi_randomize rounds up to full bytes, thus we need to + use gcry_mpi_clear_highbit to fix that. */ + gcry_mpi_randomize (a, size_list[size_idx], GCRY_WEAK_RANDOM); + gcry_mpi_clear_highbit (a, size_list[size_idx]); + + for (i=0; i < 75; i++) + { + gcry_mpi_lshift (b, a, i); + + result = mpi2bitstr_nlz (b); + tmpstr = mpi2bitstr_nlz (a); + result2 = lshiftbitstring (tmpstr, i); + xfree (tmpstr); + if (strcmp (result, result2)) + { + show ("got =%s\n", result); + show ("want=%s\n", result2); + fail ("lshift by %d failed\n", i); + } + xfree (result); + xfree (result2); + } + + /* Again. This time using in-place operation. */ + gcry_mpi_randomize (a, size_list[size_idx], GCRY_WEAK_RANDOM); + gcry_mpi_clear_highbit (a, size_list[size_idx]); + + for (i=0; i < 75; i++) + { + gcry_mpi_release (b); + b = gcry_mpi_copy (a); + gcry_mpi_lshift (b, b, i); + + result = mpi2bitstr_nlz (b); + tmpstr = mpi2bitstr_nlz (a); + result2 = lshiftbitstring (tmpstr, i); + xfree (tmpstr); + if (strcmp (result, result2)) + { + show ("got =%s\n", result); + show ("want=%s\n", result2); + fail ("in-place lshift by %d failed\n", i); + } + xfree (result2); + xfree (result); + } + + gcry_mpi_release (b); + gcry_mpi_release (a); + } +} + int main (int argc, char **argv) @@ -226,15 +335,19 @@ main (int argc, char **argv) die ("version mismatch\n"); gcry_control (GCRYCTL_DISABLE_SECMEM, 0); - gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); if (debug) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); - gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); one_bit_only (0); one_bit_only (1); for (i=0; i < 5; i++) test_rshift (i); /* Run several times due to random initializations. */ + + for (i=0; i < 5; i++) + test_lshift (i); /* Run several times due to random initializations. */ show ("All tests completed. Errors: %d\n", error_count); return error_count ? 1 : 0; -- cgit v1.2.1