[svn] gcry - r1322 - in trunk: cipher doc src tests
svn author wk
cvs at cvs.gnupg.org
Thu Sep 11 12:38:05 CEST 2008
Author: wk
Date: 2008-09-11 12:38:04 +0200 (Thu, 11 Sep 2008)
New Revision: 1322
Modified:
trunk/cipher/ChangeLog
trunk/cipher/dsa.c
trunk/cipher/rsa.c
trunk/doc/ChangeLog
trunk/doc/Makefile.am
trunk/doc/gcrypt.texi
trunk/src/ChangeLog
trunk/src/fips.c
trunk/tests/basic.c
Log:
Implemented more self-tests.
Modified: trunk/cipher/ChangeLog
===================================================================
--- trunk/cipher/ChangeLog 2008-09-09 18:06:38 UTC (rev 1321)
+++ trunk/cipher/ChangeLog 2008-09-11 10:38:04 UTC (rev 1322)
@@ -1,3 +1,14 @@
+2008-09-11 Werner Koch <wk at g10code.com>
+
+ * rsa.c (_gcry_rsa_decrypt): Return an error instead of calling
+ BUG in case of a practically impossible condition.
+ (sample_secret_key, sample_public_key): New.
+ (selftest_sign_1024, selftest_encr_1024): New.
+ (selftests_rsa): Implement tests.
+ * dsa.c (sample_secret_key, sample_public_key): New.
+ (selftest_sign_1024): New.
+ (selftests_dsa): Implement tests.
+
2008-09-09 Werner Koch <wk at g10code.com>
* hmac-tests.c (selftests_sha1): Add tests.
Modified: trunk/doc/ChangeLog
===================================================================
--- trunk/doc/ChangeLog 2008-09-09 18:06:38 UTC (rev 1321)
+++ trunk/doc/ChangeLog 2008-09-11 10:38:04 UTC (rev 1322)
@@ -1,3 +1,8 @@
+2008-09-11 Werner Koch <wk at g10code.com>
+
+ * gcrypt.texi (Public-Key Subsystem Architecture): Explain RSA
+ blinding.
+
2008-09-08 Marcus Brinkmann <marcus at g10code.com>
* gcrypt.texi: Some typos fixed.
Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog 2008-09-09 18:06:38 UTC (rev 1321)
+++ trunk/src/ChangeLog 2008-09-11 10:38:04 UTC (rev 1322)
@@ -1,3 +1,8 @@
+2008-09-11 Werner Koch <wk at g10code.com>
+
+ * fips.c (_gcry_fips_run_selftests): Run random tests before the
+ pubkey tests.
+
2008-09-05 Werner Koch <wk at g10code.com>
* gcrypt.h.in (GCYRCTL_SELFTEST): New.
Modified: trunk/cipher/dsa.c
===================================================================
--- trunk/cipher/dsa.c 2008-09-09 18:06:38 UTC (rev 1321)
+++ trunk/cipher/dsa.c 2008-09-11 10:38:04 UTC (rev 1322)
@@ -1,4 +1,4 @@
-/* dsa.c - DSA signature scheme
+/* dsa.c - DSA signature scheme
* Copyright (C) 1998, 2000, 2001, 2002, 2003,
* 2006, 2008 Free Software Foundation, Inc.
*
@@ -47,6 +47,45 @@
} DSA_secret_key;
+/* A sample 1024 bit DSA key used for the selftests. */
+static const char sample_secret_key[] =
+"(private-key"
+" (dsa"
+" (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB"
+" 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191"
+" CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44"
+" 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)"
+" (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)"
+" (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503"
+" AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E"
+" B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984"
+" 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)"
+" (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46"
+" A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827"
+" 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20"
+" 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)"
+" (x #11D54E4ADBD3034160F2CED4B7CD292A4EBF3EC0#)))";
+/* A sample 1024 bit DSA key used for the selftests (public only). */
+static const char sample_public_key[] =
+"(public-key"
+" (dsa"
+" (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB"
+" 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191"
+" CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44"
+" 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)"
+" (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)"
+" (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503"
+" AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E"
+" B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984"
+" 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)"
+" (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46"
+" A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827"
+" 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20"
+" 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)))";
+
+
+
+
static gcry_mpi_t gen_k (gcry_mpi_t q);
static void test_keys (DSA_secret_key *sk, unsigned qbits);
static int check_secret_key (DSA_secret_key *sk);
@@ -539,23 +578,103 @@
Self-test section.
*/
+static const char *
+selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
+{
+ static const char sample_data[] =
+ "(data (flags pkcs1)"
+ " (hash sha1 #a0b1c2d3e4f500102030405060708090a1b2c3d4#))";
+ static const char sample_data_bad[] =
+ "(data (flags pkcs1)"
+ " (hash sha1 #a0b1c2d3e4f510102030405060708090a1b2c3d4#))";
+ const char *errtxt = NULL;
+ gcry_error_t err;
+ gcry_sexp_t data = NULL;
+ gcry_sexp_t data_bad = NULL;
+ gcry_sexp_t sig = NULL;
+
+ err = gcry_sexp_sscan (&data, NULL,
+ sample_data, strlen (sample_data));
+ if (!err)
+ err = gcry_sexp_sscan (&data_bad, NULL,
+ sample_data_bad, strlen (sample_data_bad));
+ if (err)
+ {
+ errtxt = "converting data failed";
+ goto leave;
+ }
+
+ err = gcry_pk_sign (&sig, data, skey);
+ if (err)
+ {
+ errtxt = "signing failed";
+ goto leave;
+ }
+ err = gcry_pk_verify (sig, data, pkey);
+ if (err)
+ {
+ errtxt = "verify failed";
+ goto leave;
+ }
+ err = gcry_pk_verify (sig, data_bad, pkey);
+ if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE)
+ {
+ errtxt = "bad signature not detected";
+ goto leave;
+ }
+
+
+ leave:
+ gcry_sexp_release (sig);
+ gcry_sexp_release (data_bad);
+ gcry_sexp_release (data);
+ return errtxt;
+}
+
+
static gpg_err_code_t
selftests_dsa (selftest_report_func_t report)
{
const char *what;
const char *errtxt;
-
- what = "low-level";
- errtxt = NULL; /*selftest ();*/
+ gcry_error_t err;
+ gcry_sexp_t skey = NULL;
+ gcry_sexp_t pkey = NULL;
+
+ /* Convert the S-expressions into the internal representation. */
+ what = "convert";
+ err = gcry_sexp_sscan (&skey, NULL,
+ sample_secret_key, strlen (sample_secret_key));
+ if (!err)
+ err = gcry_sexp_sscan (&pkey, NULL,
+ sample_public_key, strlen (sample_public_key));
+ if (err)
+ {
+ errtxt = gcry_strerror (err);
+ goto failed;
+ }
+
+ what = "key consistency";
+ err = gcry_pk_testkey (skey);
+ if (err)
+ {
+ errtxt = gcry_strerror (err);
+ goto failed;
+ }
+
+ what = "sign";
+ errtxt = selftest_sign_1024 (pkey, skey);
if (errtxt)
goto failed;
- /* FIXME: need more tests. */
-
+ gcry_sexp_release (pkey);
+ gcry_sexp_release (skey);
return 0; /* Succeeded. */
failed:
+ gcry_sexp_release (pkey);
+ gcry_sexp_release (skey);
if (report)
report ("pubkey", GCRY_PK_DSA, what, errtxt);
return GPG_ERR_SELFTEST_FAILED;
Modified: trunk/cipher/rsa.c
===================================================================
--- trunk/cipher/rsa.c 2008-09-09 18:06:38 UTC (rev 1321)
+++ trunk/cipher/rsa.c 2008-09-11 10:38:04 UTC (rev 1322)
@@ -1,4 +1,4 @@
-/* rsa.c - RSA function
+/* rsa.c - RSA implementation
* Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn)
* Copyright (C) 2000, 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
*
@@ -52,6 +52,38 @@
} RSA_secret_key;
+/* A sample 1024 bit RSA key used for the selftests. */
+static const char sample_secret_key[] =
+"(private-key"
+" (rsa"
+" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
+" 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
+" ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
+" 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)"
+" (e #010001#)"
+" (d #046129f2489d71579be0a75fe029bd6cdb574ebf57ea8a5b0fda942cab943b11"
+" 7d7bb95e5d28875e0f9fc5fcc06a72f6d502464dabded78ef6b716177b83d5bd"
+" c543dc5d3fed932e59f5897e92e6f58a0f33424106a3b6fa2cbf877510e4ac21"
+" c3ee47851e97d12996222ac3566d4ccb0b83d164074abf7de655fc2446da1781#)"
+" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213"
+" fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)"
+" (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9"
+" 35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)"
+" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e"
+" ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)))";
+/* A sample 1024 bit RSA key used for the selftests (public only). */
+static const char sample_public_key[] =
+"(public-key"
+" (rsa"
+" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
+" 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
+" ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
+" 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)"
+" (e #010001#)))";
+
+
+
+
static void test_keys (RSA_secret_key *sk, unsigned nbits);
static gpg_err_code_t generate (RSA_secret_key *sk,
unsigned int nbits, unsigned long use_e,
@@ -585,12 +617,11 @@
GCRY_STRONG_RANDOM);
gcry_mpi_mod (r, r, sk.n);
- /* Actually it should be okay to skip the check for equality
- with either p or q here. */
-
- /* Calculate inverse of r. */
- if (! gcry_mpi_invm (ri, r, sk.n))
- BUG ();
+ /* Calculate inverse of r. It practically impossible that the
+ follwing test fails, thus we do not add code to release
+ allocated resources. */
+ if (!gcry_mpi_invm (ri, r, sk.n))
+ return GPG_ERR_INTERNAL;
}
if (! (flags & PUBKEY_FLAG_NO_BLINDING))
@@ -730,23 +761,179 @@
Self-test section.
*/
+static const char *
+selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
+{
+ static const char sample_data[] =
+ "(data (flags pkcs1)"
+ " (hash sha1 #11223344556677889900aabbccddeeff10203040#))";
+ static const char sample_data_bad[] =
+ "(data (flags pkcs1)"
+ " (hash sha1 #11223344556677889900aabbccddeeff80203040#))";
+ const char *errtxt = NULL;
+ gcry_error_t err;
+ gcry_sexp_t data = NULL;
+ gcry_sexp_t data_bad = NULL;
+ gcry_sexp_t sig = NULL;
+
+ err = gcry_sexp_sscan (&data, NULL,
+ sample_data, strlen (sample_data));
+ if (!err)
+ err = gcry_sexp_sscan (&data_bad, NULL,
+ sample_data_bad, strlen (sample_data_bad));
+ if (err)
+ {
+ errtxt = "converting data failed";
+ goto leave;
+ }
+
+ err = gcry_pk_sign (&sig, data, skey);
+ if (err)
+ {
+ errtxt = "signing failed";
+ goto leave;
+ }
+ err = gcry_pk_verify (sig, data, pkey);
+ if (err)
+ {
+ errtxt = "verify failed";
+ goto leave;
+ }
+ err = gcry_pk_verify (sig, data_bad, pkey);
+ if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE)
+ {
+ errtxt = "bad signature not detected";
+ goto leave;
+ }
+
+
+ leave:
+ gcry_sexp_release (sig);
+ gcry_sexp_release (data_bad);
+ gcry_sexp_release (data);
+ return errtxt;
+}
+
+
+static const char *
+selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
+{
+ const char *errtxt = NULL;
+ gcry_error_t err;
+ const unsigned int nbits = 1000; /* Encrypt 1000 random bits. */
+ gcry_mpi_t value = NULL;
+ gcry_sexp_t plain = NULL;
+ gcry_sexp_t encr = NULL;
+ gcry_sexp_t decr = NULL;
+ gcry_mpi_t decr_value = NULL;
+ gcry_sexp_t tmplist = NULL;
+
+ /* Create plain text. */
+ value = gcry_mpi_new (nbits);
+ gcry_mpi_randomize (value, nbits, GCRY_WEAK_RANDOM);
+
+ err = gcry_sexp_build (&plain, NULL, "(data (flags raw) (value %m))", value);
+ if (err)
+ {
+ errtxt = "converting data failed";
+ goto leave;
+ }
+
+ /* Encrypt and decrypt. */
+ err = gcry_pk_encrypt (&encr, plain, pkey);
+ if (err)
+ {
+ errtxt = "encrypt failed";
+ goto leave;
+ }
+ err = gcry_pk_decrypt (&decr, encr, skey);
+ if (err)
+ {
+ errtxt = "decrypt failed";
+ goto leave;
+ }
+
+ /* Extract decrypted data. The output of gcry_pk_decrypt depends on
+ whether a flags lists occurs in its input data. Because we
+ passed the output of gcry_pk_encrypt directly to gcry_pk_decrypt,
+ such a flag value won't be there as of today. To be prepared for
+ future changes we take care of it anyway. */
+ tmplist = gcry_sexp_find_token (decr, "value", 0);
+ if (tmplist)
+ decr_value = gcry_sexp_nth_mpi (tmplist, 1, GCRYMPI_FMT_USG);
+ else
+ decr_value = gcry_sexp_nth_mpi (decr, 0, GCRYMPI_FMT_USG);
+ if (!decr_value)
+ {
+ errtxt = "decrypt returned no value";
+ goto leave;
+ }
+
+ if (gcry_mpi_cmp (value, decr_value))
+ {
+ errtxt = "mismatch";
+ goto leave;
+ }
+
+ leave:
+ gcry_sexp_release (tmplist);
+ gcry_mpi_release (decr_value);
+ gcry_sexp_release (decr);
+ gcry_sexp_release (encr);
+ gcry_sexp_release (plain);
+ gcry_mpi_release (value);
+ return errtxt;
+}
+
+
static gpg_err_code_t
selftests_rsa (selftest_report_func_t report)
{
const char *what;
const char *errtxt;
+ gcry_error_t err;
+ gcry_sexp_t skey = NULL;
+ gcry_sexp_t pkey = NULL;
- what = "low-level";
- errtxt = NULL; /*selftest ();*/
+ /* Convert the S-expressions into the internal representation. */
+ what = "convert";
+ err = gcry_sexp_sscan (&skey, NULL,
+ sample_secret_key, strlen (sample_secret_key));
+ if (!err)
+ err = gcry_sexp_sscan (&pkey, NULL,
+ sample_public_key, strlen (sample_public_key));
+ if (err)
+ {
+ errtxt = gcry_strerror (err);
+ goto failed;
+ }
+
+ what = "key consistency";
+ err = gcry_pk_testkey (skey);
+ if (err)
+ {
+ errtxt = gcry_strerror (err);
+ goto failed;
+ }
+
+ what = "sign";
+ errtxt = selftest_sign_1024 (pkey, skey);
if (errtxt)
goto failed;
- /* FIXME: need more tests. */
+ what = "encrypt";
+ errtxt = selftest_encr_1024 (pkey, skey);
+ if (errtxt)
+ goto failed;
+ gcry_sexp_release (pkey);
+ gcry_sexp_release (skey);
return 0; /* Succeeded. */
failed:
+ gcry_sexp_release (pkey);
+ gcry_sexp_release (skey);
if (report)
report ("pubkey", GCRY_PK_RSA, what, errtxt);
return GPG_ERR_SELFTEST_FAILED;
Modified: trunk/doc/Makefile.am
===================================================================
--- trunk/doc/Makefile.am 2008-09-09 18:06:38 UTC (rev 1321)
+++ trunk/doc/Makefile.am 2008-09-11 10:38:04 UTC (rev 1322)
@@ -63,9 +63,9 @@
cp gcrypt.info gcrypt.html/; \
else \
rsync -v gcrypt.pdf gcrypt.info \
- $${user}@cvs.gnupg.org:webspace/manuals/ ; \
+ $${user}@trithemius.gnupg.org:webspace/manuals/ ; \
fi ; \
cd gcrypt.html ; \
rsync -vr --exclude='.svn' . \
- $${user}@cvs.gnupg.org:webspace/manuals/gcrypt$${dashdevel}/
+ $${user}@trithemius.gnupg.org:webspace/manuals/gcrypt$${dashdevel}/
Modified: trunk/doc/gcrypt.texi
===================================================================
--- trunk/doc/gcrypt.texi 2008-09-09 18:06:38 UTC (rev 1321)
+++ trunk/doc/gcrypt.texi 2008-09-11 10:38:04 UTC (rev 1322)
@@ -2273,7 +2273,7 @@
does the padding and encrypts it.
If the function could successfully perform the encryption, the return
-value will be 0 and a a new S-expression with the encrypted result is
+value will be 0 and a new S-expression with the encrypted result is
allocated and assigned to the variable at the address of @var{r_ciph}.
The caller is responsible to release this value using
@code{gcry_sexp_release}. In case of an error, an error code is
@@ -4608,11 +4608,22 @@
between the algorithm modules and the high level functions passes data
in a custom format. The interface to the modules is published
(@file{gcrypt-modules.h}) so that it can used to register external
-implementations of algorithms with Libgcrypt. However, for some algorithms this
-module interface is to limited and thus for the internal modules an
-extra interface is sometimes used to convey more information.
+implementations of algorithms with Libgcrypt. However, for some
+algorithms this module interface is to limited and thus for the
+internal modules an extra interface is sometimes used to convey more
+information.
+By default Libgcrypt uses a blinding technique for RSA decryption to
+mitigate real world timing attacks over a network: Instead of using
+the RSA decryption directly, a blinded value @math{y = x r^{e} \bmod n}
+is decrypted and the unblinded value @math{x' = y' r^{-1} \bmod n}
+returned. The blinding value @math{r} is a random value with the size
+of the modulus @math{n} and generated with @code{GCRY_STRONG_RANDOM}
+random level.
+
+
+
@node Symmetric Encryption Subsystem Architecture
@section Symmetric Encryption Subsystem Architecture
Modified: trunk/src/fips.c
===================================================================
--- trunk/src/fips.c 2008-09-09 18:06:38 UTC (rev 1321)
+++ trunk/src/fips.c 2008-09-11 10:38:04 UTC (rev 1322)
@@ -538,10 +538,12 @@
if (run_hmac_selftests ())
goto leave;
- if (run_pubkey_selftests ())
+ /* Run random tests before the pubkey tests because the latter
+ require random. */
+ if (run_random_selftests ())
goto leave;
- if (run_random_selftests ())
+ if (run_pubkey_selftests ())
goto leave;
/* Now check the integrity of the binary. We do this this after
Modified: trunk/tests/basic.c
===================================================================
--- trunk/tests/basic.c 2008-09-09 18:06:38 UTC (rev 1321)
+++ trunk/tests/basic.c 2008-09-11 10:38:04 UTC (rev 1322)
@@ -1375,7 +1375,7 @@
gcry_md_close (hd);
p = gcry_md_read (hd2, algo);
- if (0 == p)
+ if (!p)
fail("algo %d, hmac gcry_md_read failed\n", algo);
if (memcmp (p, expect, mdlen))
More information about the Gnupg-commits
mailing list