diff options
author | Werner Koch <wk@gnupg.org> | 2008-10-24 17:01:30 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2008-10-24 17:01:30 +0000 |
commit | 3f204a1533f15446f3579e648f0cf70639c4bc49 (patch) | |
tree | ecf24d2b8ccd0490973c37af0c7104bcea522950 | |
parent | 467211879b93495e4c423c057fffe78e7b18089f (diff) | |
download | libgcrypt-3f204a1533f15446f3579e648f0cf70639c4bc49.tar.gz |
Do no restrtc usage of MD5 in fips mode.
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | cipher/ChangeLog | 6 | ||||
-rw-r--r-- | cipher/md.c | 45 | ||||
-rw-r--r-- | cipher/rsa.c | 12 | ||||
-rw-r--r-- | doc/gcrypt.texi | 27 | ||||
-rw-r--r-- | src/ChangeLog | 7 | ||||
-rw-r--r-- | src/fips.c | 55 | ||||
-rw-r--r-- | src/g10lib.h | 4 | ||||
-rw-r--r-- | src/global.c | 22 | ||||
-rw-r--r-- | tests/ChangeLog | 5 | ||||
-rw-r--r-- | tests/basic.c | 10 | ||||
-rw-r--r-- | tests/benchmark.c | 15 |
12 files changed, 173 insertions, 37 deletions
@@ -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): @@ -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; } |