summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2008-10-24 17:01:30 +0000
committerWerner Koch <wk@gnupg.org>2008-10-24 17:01:30 +0000
commit3f204a1533f15446f3579e648f0cf70639c4bc49 (patch)
treeecf24d2b8ccd0490973c37af0c7104bcea522950
parent467211879b93495e4c423c057fffe78e7b18089f (diff)
downloadlibgcrypt-3f204a1533f15446f3579e648f0cf70639c4bc49.tar.gz
Do no restrtc usage of MD5 in fips mode.
-rw-r--r--NEWS2
-rw-r--r--cipher/ChangeLog6
-rw-r--r--cipher/md.c45
-rw-r--r--cipher/rsa.c12
-rw-r--r--doc/gcrypt.texi27
-rw-r--r--src/ChangeLog7
-rw-r--r--src/fips.c55
-rw-r--r--src/g10lib.h4
-rw-r--r--src/global.c22
-rw-r--r--tests/ChangeLog5
-rw-r--r--tests/basic.c10
-rw-r--r--tests/benchmark.c15
12 files changed, 173 insertions, 37 deletions
diff --git a/NEWS b/NEWS
index 0678dd28..76dada39 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ Noteworthy changes in version 1.4.4
* Publish GCRY_MODULE_ID_USER and GCRY_MODULE_ID_USER_LAST constants.
This functionality is in Libgcrypt since 1.3.0.
+ * MD5 may now be used in non-enforced fips mode.
+
Noteworthy changes in version 1.4.3 (2008-09-18)
------------------------------------------------
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index b8ed7921..6e24cfc0 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,9 @@
+2008-10-24 Werner Koch <wk@g10code.com>
+
+ * md.c (digest_table): Allow MD5 in fips mode.
+ (md_register_default): Take special action for MD5.
+ (md_enable, gcry_md_hash_buffer): Ditto.
+
2008-09-30 Werner Koch <wk@g10code.com>
* rijndael.c (do_setkey): Properly align "t" and "tk".
diff --git a/cipher/md.c b/cipher/md.c
index ce128bb7..d6890873 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -43,7 +43,7 @@ static struct digest_table_entry
gcry_md_spec_t *digest;
md_extra_spec_t *extraspec;
unsigned int algorithm;
- int fips_allowed;
+ int fips_allowed;
} digest_table[] =
{
#if USE_CRC
@@ -62,7 +62,7 @@ static struct digest_table_entry
#endif
#if USE_MD5
{ &_gcry_digest_spec_md5,
- &dummy_extra_spec, GCRY_MD_MD5 },
+ &dummy_extra_spec, GCRY_MD_MD5, 1 },
#endif
#if USE_RMD160
{ &_gcry_digest_spec_rmd160,
@@ -176,8 +176,14 @@ md_register_default (void)
for (i = 0; !err && digest_table[i].digest; i++)
{
- if ( fips_mode () && !digest_table[i].fips_allowed )
- continue;
+ if ( fips_mode ())
+ {
+ if (!digest_table[i].fips_allowed)
+ continue;
+ if (digest_table[i].algorithm == GCRY_MD_MD5
+ && _gcry_enforced_fips_mode () )
+ continue; /* Do not register in enforced fips mode. */
+ }
err = _gcry_module_add (&digests_registered,
digest_table[i].algorithm,
@@ -550,10 +556,22 @@ md_enable (gcry_md_hd_t hd, int algorithm)
log_debug ("md_enable: algorithm %d not available\n", algorithm);
err = GPG_ERR_DIGEST_ALGO;
}
- else
+ else
digest = (gcry_md_spec_t *) module->spec;
- if (! err)
+
+ if (!err && algorithm == GCRY_MD_MD5 && fips_mode ())
+ {
+ _gcry_inactivate_fips_mode ("MD5 used");
+ if (_gcry_enforced_fips_mode () )
+ {
+ /* We should never get to here because we do not register
+ MD5 in enforced fips mode. But better throw an error. */
+ err = GPG_ERR_DIGEST_ALGO;
+ }
+ }
+
+ if (!err)
{
size_t size = (sizeof (*entry)
+ digest->contextsize
@@ -992,7 +1010,20 @@ gcry_md_hash_buffer (int algo, void *digest,
/* For the others we do not have a fast function, so we use the
normal functions. */
gcry_md_hd_t h;
- gpg_err_code_t err = md_open (&h, algo, 0, 0);
+ gpg_err_code_t err;
+
+ if (algo == GCRY_MD_MD5 && fips_mode ())
+ {
+ _gcry_inactivate_fips_mode ("MD5 used");
+ if (_gcry_enforced_fips_mode () )
+ {
+ /* We should never get to here because we do not register
+ MD5 in enforced fips mode. */
+ _gcry_fips_noreturn ();
+ }
+ }
+
+ err = md_open (&h, algo, 0, 0);
if (err)
log_bug ("gcry_md_open failed for algo %d: %s",
algo, gpg_strerror (gcry_error(err)));
diff --git a/cipher/rsa.c b/cipher/rsa.c
index 434fd8ba..8b0fe9f4 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -196,12 +196,12 @@ generate (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
gcry_random_level_t random_level;
if (fips_mode ())
- {
- if (nbits < 1024)
- return GPG_ERR_INV_VALUE;
- if (transient_key)
- return GPG_ERR_INV_VALUE;
- }
+ {
+ if (nbits < 1024)
+ return GPG_ERR_INV_VALUE;
+ if (transient_key)
+ return GPG_ERR_INV_VALUE;
+ }
/* The random quality depends on the transient_key flag. */
random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 32f21171..87fb9cec 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -5524,6 +5524,11 @@ The function @code{gcry_set_allocation_handler} may not be used. If
it is used Libgcrypt disables FIPS mode unless Enforced FIPS mode is
enabled, in which case Libgcrypt will enter the error state.
+@item
+The digest algorithm MD5 may not be used. If it is used Libgcrypt
+disables FIPS mode unless Enforced FIPS mode is enabled, in which case
+Libgcrypt will enter the error state.
+
@item
In Enforced FIPS mode the command @code{GCRYCTL_DISABLE_SECMEM} is
ignored. In standard FIPS mode it disables FIPS mode.
@@ -5536,10 +5541,9 @@ A handler set by @code{gcry_set_fatalerror_handler} is ignored.
@end itemize
Note that when we speak about disabling FIPS mode, it merely means
-that the fucntion @code{gcry_fips_mode_active} returns false; it does
+that the function @code{gcry_fips_mode_active} returns false; it does
not mean that any non FIPS algorithms are allowed.
-
@c ********************************************
@section FIPS Finite State Machine
@@ -5688,6 +5692,25 @@ state.
@end table
@end float
+@c ********************************************
+@section FIPS Miscellaneous Information
+
+Libgcrypt does not do any key management on itself; the application
+needs to care about it. Keys which are passed to Libgcrypt should be
+allocated in secure memory as available with the functions
+@code{gcry_malloc_secure} and @code{gcry_calloc_secure}. By calling
+@code{gcry_free} on this memory, the memory and thus the keys are
+overwritten with zero bytes before releasing the memory.
+
+For use with the random number generator, Libgcrypt generates 3
+internal keys which are stored in the encryption contexts used by the
+RNG. These keys are stored in secure memory for the lifetime of the
+process. Application are required to use @code{GCRYCTL_TERM_SECMEM}
+before process termination. This will zero out the entire secure
+memory and thus also the encryption contexts with these keys.
+
+
+
@c **********************************************************
@c ************* Appendices (license etc.) ****************
@c **********************************************************
diff --git a/src/ChangeLog b/src/ChangeLog
index 7759dbb8..ff50b49f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
+2008-10-24 Werner Koch <wk@g10code.com>
+
+ * global.c (inactive_fips_mode): Move to fips.c.
+ (gcry_set_allocation_handler): Factor code out to ...
+ * fips.c (_gcry_inactivate_fips_mode): New.
+ (_gcry_is_fips_mode_inactive): New.
+
2008-09-29 Werner Koch <wk@g10code.com>
* gcrypt-module.h (GCRY_MODULE_ID_USER, GCRY_MODULE_ID_USER_LAST):
diff --git a/src/fips.c b/src/fips.c
index 0a8a15e9..f2d898b1 100644
--- a/src/fips.c
+++ b/src/fips.c
@@ -63,6 +63,11 @@ static int no_fips_mode_required;
/* Flag to indicate that we are in the enforced FIPS mode. */
static int enforced_fips_mode;
+/* If this flag is set, the application may no longer assume that the
+ process is running in FIPS mode. This flag is protected by the
+ FSM_LOCK. */
+static int inactive_fips_mode;
+
/* This is the lock we use to protect the FSM. */
static ath_mutex_t fsm_lock = ATH_MUTEX_INITIALIZER;
@@ -259,7 +264,7 @@ _gcry_fips_mode (void)
{
/* No locking is required becuase we have the requirement that this
variable is only intialized once with no other threads
- exiisting. */
+ existing. */
return !no_fips_mode_required;
}
@@ -272,6 +277,54 @@ _gcry_enforced_fips_mode (void)
}
+/* If we do not want to enforce the fips mode, we can set a flag so
+ that the application may check whether it is still in fips mode.
+ TEXT will be printed as part of a syslog message. This function
+ may only be be called if in fips mode. */
+void
+_gcry_inactivate_fips_mode (const char *text)
+{
+ gcry_assert (_gcry_fips_mode ());
+
+ if (_gcry_enforced_fips_mode () )
+ {
+ /* Get us into the error state. */
+ fips_signal_error (text);
+ return;
+ }
+
+ lock_fsm ();
+ if (!inactive_fips_mode)
+ {
+ inactive_fips_mode = 1;
+ unlock_fsm ();
+#ifdef HAVE_SYSLOG
+ syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
+ "%s - FIPS mode inactivated", text);
+#endif /*HAVE_SYSLOG*/
+ }
+ else
+ unlock_fsm ();
+}
+
+
+/* Return the FIPS mode inactive flag. If it is true the FIPS mode is
+ not anymore active. */
+int
+_gcry_is_fips_mode_inactive (void)
+{
+ int flag;
+
+ if (!_gcry_fips_mode ())
+ return 0;
+ lock_fsm ();
+ flag = inactive_fips_mode;
+ unlock_fsm ();
+ return flag;
+}
+
+
+
static const char *
state2str (enum module_states state)
{
diff --git a/src/g10lib.h b/src/g10lib.h
index 6a23f261..a3ffb127 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -295,6 +295,10 @@ int _gcry_fips_mode (void);
int _gcry_enforced_fips_mode (void);
+void _gcry_inactivate_fips_mode (const char *text);
+int _gcry_is_fips_mode_inactive (void);
+
+
void _gcry_fips_signal_error (const char *srcfile,
int srcline,
const char *srcfunc,
diff --git a/src/global.c b/src/global.c
index 15b7672a..3177a02b 100644
--- a/src/global.c
+++ b/src/global.c
@@ -50,10 +50,6 @@ static unsigned int debug_flags;
intialization code swicthed fips mode on. */
static int force_fips_mode;
-/* If this flag is set, the application may no longer assume that the
- process is running in FIPS mode. */
-static int inactive_fips_mode;
-
/* Controlled by global_init(). */
static int any_init_done;
@@ -495,7 +491,9 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
break;
case GCRYCTL_FIPS_MODE_P:
- if (fips_mode () && !inactive_fips_mode && !no_secure_memory)
+ if (fips_mode ()
+ && !_gcry_is_fips_mode_inactive ()
+ && !no_secure_memory)
err = GPG_ERR_GENERAL; /* Used as TRUE value */
break;
@@ -658,20 +656,10 @@ gcry_set_allocation_handler (gcry_handler_alloc_t new_alloc_func,
if (fips_mode ())
{
- if (_gcry_enforced_fips_mode () )
- {
- /* Get us into the error state. */
- fips_signal_error ("custom allocation handler used");
- return;
- }
/* We do not want to enforce the fips mode, but merely set a
- flag so that the application may check wheter it is still in
+ flag so that the application may check whether it is still in
fips mode. */
- inactive_fips_mode = 1;
-#ifdef HAVE_SYSLOG
- syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
- "custom allocation handler used - FIPS mode disabled");
-#endif /*HAVE_SYSLOG*/
+ _gcry_inactivate_fips_mode ("custom allocation handler");
}
alloc_func = new_alloc_func;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index ff5d0b45..2eb61fd1 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2008-10-24 Werner Koch <wk@g10code.com>
+
+ * benchmark.c (md_bench): Do not test MD5 in fips mode.
+ * basic.c (check_digests, check_hmac): Ditto.
+
2008-10-06 Werner Koch <wk@g10code.com>
* cavs_driver.pl: New version from upstream.
diff --git a/tests/basic.c b/tests/basic.c
index b735e0f1..0d489994 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -1316,7 +1316,8 @@ check_digests (void)
for (i = 0; algos[i].md; i++)
{
- if (gcry_md_test_algo (algos[i].md) && in_fips_mode)
+ if ((gcry_md_test_algo (algos[i].md) || algos[i].md == GCRY_MD_MD5)
+ && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
@@ -1685,7 +1686,8 @@ check_hmac (void)
for (i = 0; algos[i].md; i++)
{
- if (gcry_md_test_algo (algos[i].md) && in_fips_mode)
+ if ((gcry_md_test_algo (algos[i].md) || algos[i].md == GCRY_MD_MD5)
+ && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
@@ -2117,6 +2119,7 @@ main (int argc, char **argv)
check_pubkey ();
}
+
if (in_fips_mode && !selftest_only)
{
/* If we are in fips mode do some more tests. */
@@ -2170,5 +2173,8 @@ main (int argc, char **argv)
if (verbose)
fprintf (stderr, "\nAll tests completed. Errors: %i\n", error_count);
+ if (in_fips_mode && !gcry_fips_mode_active ())
+ fprintf (stderr, "FIPS mode is not anymore active\n");
+
return error_count ? 1 : 0;
}
diff --git a/tests/benchmark.c b/tests/benchmark.c
index a7a0b413..f8a5b0e6 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
@@ -41,6 +41,9 @@ static int large_buffers;
/* Number of cipher repetitions. */
static int cipher_repetitions;
+/* Whether fips mode was active at startup. */
+static int in_fips_mode;
+
static const char sample_private_dsa_key_1024[] =
"(private-key\n"
@@ -373,7 +376,9 @@ md_bench ( const char *algoname )
if (!algoname)
{
for (i=1; i < 400; i++)
- if ( !gcry_md_test_algo (i) )
+ if (in_fips_mode && i == GCRY_MD_MD5)
+ ; /* Don't use MD5 in fips mode. */
+ else if ( !gcry_md_test_algo (i) )
md_bench (gcry_md_algo_name (i));
return;
}
@@ -1055,7 +1060,9 @@ main( int argc, char **argv )
exit (1);
}
- if (!gcry_fips_mode_active ())
+ if (gcry_fips_mode_active ())
+ in_fips_mode = 1;
+ else
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
if (use_random_daemon)
@@ -1135,6 +1142,10 @@ main( int argc, char **argv )
fprintf (stderr, PGM ": bad arguments\n");
return 1;
}
+
+
+ if (in_fips_mode && !gcry_fips_mode_active ())
+ fprintf (stderr, PGM ": FIPS mode is not anymore active\n");
return 0;
}