/* mpitests.c - basic mpi tests * Copyright (C) 2001, 2002, 2003, 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 #ifdef _GCRYPT_IN_LIBGCRYPT # include "../src/gcrypt-int.h" #else # include #endif static int verbose; static int debug; static void die (const char *format, ...) { va_list arg_ptr; va_start (arg_ptr, format); vfprintf (stderr, format, arg_ptr); va_end (arg_ptr); exit (1); } /* Set up some test patterns */ /* 48 bytes with value 1: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */ unsigned char ones[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; /* 48 bytes with value 2: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */ unsigned char twos[] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }; /* 48 bytes with value 3: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */ unsigned char threes[] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; /* 48 bytes with value 0x80: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */ unsigned char eighties[] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }; /* 48 bytes with value 0xff: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */ unsigned char manyff[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; static int test_const_and_immutable (void) { gcry_mpi_t one, second_one; one = gcry_mpi_set_ui (NULL, 1); if (gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE) || gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST)) die ("immutable or const flag initially set\n"); second_one = gcry_mpi_copy (one); if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE)) die ("immutable flag set after copy\n"); if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST)) die ("const flag set after copy\n"); gcry_mpi_release (second_one); gcry_mpi_set_flag (one, GCRYMPI_FLAG_IMMUTABLE); if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE)) die ("failed to set immutable flag\n"); if (gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST)) die ("const flag unexpectly set\n"); second_one = gcry_mpi_copy (one); if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE)) die ("immutable flag not cleared after copy\n"); if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST)) die ("const flag unexpectly set after copy\n"); gcry_mpi_release (second_one); gcry_mpi_clear_flag (one, GCRYMPI_FLAG_IMMUTABLE); if (gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE)) die ("failed to clear immutable flag\n"); if (gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST)) die ("const flag unexpectly set\n"); gcry_mpi_set_flag (one, GCRYMPI_FLAG_CONST); if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST)) die ("failed to set const flag\n"); if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE)) die ("failed to set immutable flag with const flag\n"); second_one = gcry_mpi_copy (one); if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE)) die ("immutable flag not cleared after copy\n"); if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST)) die ("const flag not cleared after copy\n"); gcry_mpi_release (second_one); gcry_mpi_clear_flag (one, GCRYMPI_FLAG_IMMUTABLE); if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE)) die ("clearing immutable flag not ignored for a constant MPI\n"); if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST)) die ("const flag unexpectly cleared\n"); second_one = gcry_mpi_set (NULL, GCRYMPI_CONST_ONE); if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE)) die ("immutable flag not cleared by mpi_set (NULL,x)\n"); if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST)) die ("const flag not cleared by mpi_set (NULL,x)\n"); gcry_mpi_release (second_one); second_one = gcry_mpi_set_ui (NULL, 42); gcry_mpi_set (second_one, GCRYMPI_CONST_ONE); if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE)) die ("immutable flag not cleared after mpi_set (a,x)\n"); if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST)) die ("const flag not cleared mpi_set (a,x)\n"); gcry_mpi_release (second_one); /* Due to the the constant flag the release below should be a NOP and will leak memory. */ gcry_mpi_release (one); return 1; } static void test_opaque (void) { gcry_mpi_t a; char *p; unsigned int nbits; p = gcry_xstrdup ("This is a test buffer"); a = gcry_mpi_set_opaque (NULL, p, 21*8+1); /* (a non byte aligned length) */ if (!gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) die ("opaque flag not set\n"); p = gcry_mpi_get_opaque (a, &nbits); if (!p) die ("gcry_mpi_get_opaque returned NULL\n"); if (nbits != 21*8+1) die ("gcry_mpi_get_opaque returned a changed bit size\n"); if (strcmp (p, "This is a test buffer")) die ("gcry_mpi_get_opaque returned a changed buffer\n"); if (verbose) { fprintf (stderr, "mpi: "); gcry_mpi_dump (a); putc ('\n', stderr); } gcry_mpi_release (a); } static int test_add (void) { gcry_mpi_t one; gcry_mpi_t two; gcry_mpi_t ff; gcry_mpi_t result; unsigned char* pc; gcry_mpi_scan(&one, GCRYMPI_FMT_USG, ones, sizeof(ones), NULL); gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL); gcry_mpi_scan(&ff, GCRYMPI_FMT_USG, manyff, sizeof(manyff), NULL); result = gcry_mpi_new(0); gcry_mpi_add(result, one, two); gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result); if (verbose) printf("Result of one plus two:\n%s\n", pc); gcry_free(pc); gcry_mpi_add(result, ff, one); gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result); if (verbose) printf("Result of ff plus one:\n%s\n", pc); gcry_free(pc); gcry_mpi_release(one); gcry_mpi_release(two); gcry_mpi_release(ff); gcry_mpi_release(result); return 1; } static int test_sub (void) { gcry_mpi_t one; gcry_mpi_t two; gcry_mpi_t result; unsigned char* pc; gcry_mpi_scan(&one, GCRYMPI_FMT_USG, ones, sizeof(ones), NULL); gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL); result = gcry_mpi_new(0); gcry_mpi_sub(result, two, one); gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result); if (verbose) printf("Result of two minus one:\n%s\n", pc); gcry_free(pc); gcry_mpi_release(one); gcry_mpi_release(two); gcry_mpi_release(result); return 1; } static int test_mul (void) { gcry_mpi_t two; gcry_mpi_t three; gcry_mpi_t result; unsigned char* pc; gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL); gcry_mpi_scan(&three, GCRYMPI_FMT_USG, threes, sizeof(threes), NULL); result = gcry_mpi_new(0); gcry_mpi_mul(result, two, three); gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result); if (verbose) printf("Result of two mul three:\n%s\n", pc); gcry_free(pc); gcry_mpi_release(two); gcry_mpi_release(three); gcry_mpi_release(result); return 1; } /* What we test here is that we don't overwrite our args and that using thne same mpi for several args works. */ static int test_powm (void) { int b_int = 17; int e_int = 3; int m_int = 19; gcry_mpi_t base = gcry_mpi_set_ui (NULL, b_int); gcry_mpi_t exp = gcry_mpi_set_ui (NULL, e_int); gcry_mpi_t mod = gcry_mpi_set_ui (NULL, m_int); gcry_mpi_t res = gcry_mpi_new (0); gcry_mpi_powm (res, base, exp, mod); if (gcry_mpi_cmp_ui (base, b_int)) die ("test_powm failed for base at %d\n", __LINE__); if (gcry_mpi_cmp_ui (exp, e_int)) die ("test_powm_ui failed for exp at %d\n", __LINE__); if (gcry_mpi_cmp_ui (mod, m_int)) die ("test_powm failed for mod at %d\n", __LINE__); /* Check using base for the result. */ gcry_mpi_set_ui (base, b_int); gcry_mpi_set_ui (exp, e_int); gcry_mpi_set_ui(mod, m_int); gcry_mpi_powm (base, base, exp, mod); if (gcry_mpi_cmp (res, base)) die ("test_powm failed at %d\n", __LINE__); if (gcry_mpi_cmp_ui (exp, e_int)) die ("test_powm_ui failed for exp at %d\n", __LINE__); if (gcry_mpi_cmp_ui (mod, m_int)) die ("test_powm failed for mod at %d\n", __LINE__); /* Check using exp for the result. */ gcry_mpi_set_ui (base, b_int); gcry_mpi_set_ui (exp, e_int); gcry_mpi_set_ui(mod, m_int); gcry_mpi_powm (exp, base, exp, mod); if (gcry_mpi_cmp (res, exp)) die ("test_powm failed at %d\n", __LINE__); if (gcry_mpi_cmp_ui (base, b_int)) die ("test_powm failed for base at %d\n", __LINE__); if (gcry_mpi_cmp_ui (mod, m_int)) die ("test_powm failed for mod at %d\n", __LINE__); /* Check using mod for the result. */ gcry_mpi_set_ui (base, b_int); gcry_mpi_set_ui (exp, e_int); gcry_mpi_set_ui(mod, m_int); gcry_mpi_powm (mod, base, exp, mod); if (gcry_mpi_cmp (res, mod)) die ("test_powm failed at %d\n", __LINE__); if (gcry_mpi_cmp_ui (base, b_int)) die ("test_powm failed for base at %d\n", __LINE__); if (gcry_mpi_cmp_ui (exp, e_int)) die ("test_powm_ui failed for exp at %d\n", __LINE__); /* Now check base ^ base mod mod. */ gcry_mpi_set_ui (base, b_int); gcry_mpi_set_ui(mod, m_int); gcry_mpi_powm (res, base, base, mod); if (gcry_mpi_cmp_ui (base, b_int)) die ("test_powm failed for base at %d\n", __LINE__); if (gcry_mpi_cmp_ui (mod, m_int)) die ("test_powm failed for mod at %d\n", __LINE__); /* Check base ^ base mod mod with base as result. */ gcry_mpi_set_ui (base, b_int); gcry_mpi_set_ui(mod, m_int); gcry_mpi_powm (base, base, base, mod); if (gcry_mpi_cmp (res, base)) die ("test_powm failed at %d\n", __LINE__); if (gcry_mpi_cmp_ui (mod, m_int)) die ("test_powm failed for mod at %d\n", __LINE__); /* Check base ^ base mod mod with mod as result. */ gcry_mpi_set_ui (base, b_int); gcry_mpi_set_ui(mod, m_int); gcry_mpi_powm (mod, base, base, mod); if (gcry_mpi_cmp (res, mod)) die ("test_powm failed at %d\n", __LINE__); if (gcry_mpi_cmp_ui (base, b_int)) die ("test_powm failed for base at %d\n", __LINE__); /* Now check base ^ base mod base. */ gcry_mpi_set_ui (base, b_int); gcry_mpi_powm (res, base, base, base); if (gcry_mpi_cmp_ui (base, b_int)) die ("test_powm failed for base at %d\n", __LINE__); /* Check base ^ base mod base with base as result. */ gcry_mpi_set_ui (base, b_int); gcry_mpi_powm (base, base, base, base); if (gcry_mpi_cmp (res, base)) die ("test_powm failed at %d\n", __LINE__); gcry_mpi_release (base); gcry_mpi_release (exp); gcry_mpi_release (mod); gcry_mpi_release (res); /* Fixme: We should add the rest of the cases of course. */ return 1; } int main (int argc, char* argv[]) { 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)) { fputs ("version mismatch\n", stderr); exit (1); } gcry_control(GCRYCTL_DISABLE_SECMEM); test_const_and_immutable (); test_opaque (); test_add (); test_sub (); test_mul (); test_powm (); return 0; }