From 5681a844ea16e74ededb45db7e9665b4ffd29045 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 4 Aug 2006 10:18:14 +0000 Subject: Fixed gcry_mpi_set_bit and enhanced mpi_rshift. Cleaned up andom-daemon initialization. --- tests/ChangeLog | 4 + tests/Makefile.am | 2 +- tests/t-mpi-bit.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 tests/t-mpi-bit.c (limited to 'tests') diff --git a/tests/ChangeLog b/tests/ChangeLog index 154bd5e2..af66e6ed 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2006-08-03 Werner Koch + + * t-mpi-bit.c: New. + 2006-07-06 Werner Koch * benchmark.c (main): New option --use-random-daemon. New command diff --git a/tests/Makefile.am b/tests/Makefile.am index 945ce5d0..e4a922ac 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -18,7 +18,7 @@ ## Process this file with automake to produce Makefile.in -TESTS = prime register ac ac-schemes ac-data basic \ +TESTS = t-mpi-bit prime register ac ac-schemes ac-data basic \ tsexp keygen pubkey benchmark pkbench hmac keygrip INCLUDES = -I$(top_srcdir)/src diff --git a/tests/t-mpi-bit.c b/tests/t-mpi-bit.c new file mode 100644 index 00000000..2465a8fd --- /dev/null +++ b/tests/t-mpi-bit.c @@ -0,0 +1,241 @@ +/* t-mpi-bit.c - Tests for bit level functions + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include + +#include "../src/gcrypt.h" + +#define PGM "t-mpi-bit" + +static const char *wherestr; +static int verbose; +static int error_count; + +#define xmalloc(a) gcry_xmalloc ((a)) +#define xcalloc(a,b) gcry_xcalloc ((a),(b)) +#define xfree(a) gcry_free ((a)) +#define pass() do { ; } while (0) + +static void +show (const char *format, ...) +{ + va_list arg_ptr; + + if (!verbose) + return; + fprintf (stderr, "%s: ", PGM); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); +} + +static void +fail (const char *format, ...) +{ + va_list arg_ptr; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + if (wherestr) + fprintf (stderr, "%s: ", wherestr); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + error_count++; +} + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + if (wherestr) + fprintf (stderr, "%s: ", wherestr); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + exit (1); +} + +/* Allocate a bit string consisting of '0' and '1' from the MPI + A. Return the LENGTH least significant bits. Caller needs to xfree + the result. */ +static char * +mpi2bitstr (gcry_mpi_t a, size_t length) +{ + char *p, *buf; + + buf = p = xmalloc (length+1); + while (length--) + *p++ = gcry_mpi_test_bit (a, length) ? '1':'0'; + *p = 0; + + return buf; +} + +/* Shift a bit string to the right. */ +static void +rshiftbitstring (char *string, size_t n) +{ + size_t len = strlen (string); + + if (n > len) + n = len; + + memmove (string+n, string, len-n); + memset (string, '0', n); +} + + +/* This is to check a bug reported by bpgcrypt at itaparica.org on + 2006-07-31 against libgcrypt 1.2.2. */ +static void +one_bit_only (int highbit) +{ + gcry_mpi_t a; + char *result; + int i; + + wherestr = "one_bit_only"; + show ("checking that set_%sbit does only set one bit\n", highbit?"high":""); + + a = gcry_mpi_new (0); + gcry_mpi_randomize (a, 70, GCRY_WEAK_RANDOM); + gcry_mpi_set_ui (a, 0); + + if (highbit) + gcry_mpi_set_highbit (a, 42); + else + gcry_mpi_set_bit (a, 42); + if (!gcry_mpi_test_bit (a, 42)) + fail ("failed to set a bit\n"); + gcry_mpi_clear_bit (a, 42); + if (gcry_mpi_test_bit (a, 42)) + 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; + if (result[i]) + fail ("spurious bits detected\n"); + xfree (result); + gcry_mpi_release (a); +} + +/* Check that the shifting actually works for an amount larger than + the number of bits per limb. */ +static void +test_rshift (int pass) +{ + gcry_mpi_t a, b; + char *result, *result2; + int i; + + wherestr = "test_rshift"; + show ("checking that rshift works as expected (pass %d)\n", pass); + + a = gcry_mpi_new (0); + b = gcry_mpi_new (0); + gcry_mpi_randomize (a, 70, GCRY_WEAK_RANDOM); + + for (i=0; i < 75; i++) + { + gcry_mpi_rshift (b, a, i); + + result = mpi2bitstr (b, 72); + result2 = mpi2bitstr (a, 72); + rshiftbitstring (result2, i); + if (strcmp (result, result2)) + { + show ("got =%s\n", result); + show ("want=%s\n", result2); + fail ("rshift by %d failed\n", i); + } + xfree (result); + xfree (result2); + } + + /* Again. This time using in-place operation. */ + gcry_mpi_randomize (a, 70, GCRY_WEAK_RANDOM); + + for (i=0; i < 75; i++) + { + gcry_mpi_release (b); + b = gcry_mpi_copy (a); + gcry_mpi_rshift (b, b, i); + + result = mpi2bitstr (b, 72); + result2 = mpi2bitstr (a, 72); + rshiftbitstring (result2, i); + if (strcmp (result, result2)) + { + show ("got =%s\n", result); + show ("want=%s\n", result2); + fail ("in-place rshift by %d failed\n", i); + } + xfree (result2); + xfree (result); + } + + gcry_mpi_release (b); + gcry_mpi_release (a); +} + + +int +main (int argc, char **argv) +{ + int debug = 0; + int i; + + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + verbose = debug = 1; + + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 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. */ + + show ("All tests completed. Errors: %d\n", error_count); + return error_count ? 1 : 0; +} -- cgit v1.2.1