diff options
author | Werner Koch <wk@gnupg.org> | 2008-09-18 12:14:09 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2008-09-18 12:14:09 +0000 |
commit | 29e44067f0797219b115fabf069e279283f13c13 (patch) | |
tree | 3ac09da7677080eb352c6957031724bc40521877 /src | |
parent | 58b91cf9cc72e7a7247f88279e3fbeba71619237 (diff) | |
download | libgcrypt-29e44067f0797219b115fabf069e279283f13c13.tar.gz |
Implemented an Enforced FIPS mode.
Documentation updates.
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 23 | ||||
-rw-r--r-- | src/fips.c | 39 | ||||
-rw-r--r-- | src/g10lib.h | 2 | ||||
-rw-r--r-- | src/global.c | 52 | ||||
-rw-r--r-- | src/secmem.c | 49 |
5 files changed, 138 insertions, 27 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index b96f8bb7..e29f05ee 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,26 @@ +2008-09-18 Werner Koch <wk@g10code.com> + + * secmem.c (_gcry_secmem_init): Factor most code out to .. + (secmem_init): .. new. + (DEFAULT_POOL_SIZE): Rename to MINIMUM_POOL_SIZE. + (STANDARD_POOL_SIZE): New. + (_gcry_secmem_malloc_internal): Don't abort if the pool is not + initialized but try to out intialize it first and only then print + an error message and return NULL. If the pool is not locked while + in FIPS mode, return NULL. + + * fips.c (FIPS_FORCE_FILE): New constant. Change the file name to + "/etc/gcrypt/fips_enabled". + (enforced_fips_mode): New. + (_gcry_initialize_fips_mode): Set that flag. + (_gcry_enforced_fips_mode): New. + * global.c (inactive_fips_mode): New. + (_gcry_vcontrol): Take that flag in account for GCRYCTL_FIPS_MODE_P. + (gcry_set_allocation_handler): Take care of the enforced fips mdoe + flag. + (get_no_secure_memory): New. + (do_malloc, gcry_is_secure): Use it. + 2008-09-16 Werner Koch <wk@g10code.com> * global.c (print_config): Use y/n for fips mode. @@ -35,6 +35,11 @@ #include "cipher-proto.h" #include "hmac256.h" + +/* The name of the file used to foce libgcrypt into fips mode. */ +#define FIPS_FORCE_FILE "/etc/gcrypt/fips_enabled" + + /* The states of the finite state machine used in fips mode. */ enum module_states { @@ -55,6 +60,9 @@ enum module_states fips_mode()! */ static int no_fips_mode_required; +/* Flag to indicate that we are in the enforced FIPS mode. */ +static int enforced_fips_mode; + /* This is the lock we use to protect the FSM. */ static ath_mutex_t fsm_lock = ATH_MUTEX_INITIALIZER; @@ -103,7 +111,7 @@ _gcry_initialize_fips_mode (int force) } done = 1; - /* If the calling applicatione explicitly requested fipsmode, do so. */ + /* If the calling application explicitly requested fipsmode, do so. */ if (force) { gcry_assert (!no_fips_mode_required); @@ -114,11 +122,8 @@ _gcry_initialize_fips_mode (int force) provided detection of the FIPS mode and force FIPS mode using a file. The filename is hardwired so that there won't be any confusion on whether /etc/gcrypt/ or /usr/local/etc/gcrypt/ is - actually used. The file itself may be empty. A comment may be - included in the file, but comment lines need to be prefixed with - a hash mark; only such comment lines and empty lines are - allowed. */ - if ( !access ("/etc/gcrypt/fips140.force", F_OK) ) + actually used. The file itself may be empty. */ + if ( !access (FIPS_FORCE_FILE, F_OK) ) { gcry_assert (!no_fips_mode_required); goto leave; @@ -167,6 +172,7 @@ _gcry_initialize_fips_mode (int force) if (!no_fips_mode_required) { /* Yes, we are in FIPS mode. */ + FILE *fp; /* Intitialize the lock to protect the FSM. */ err = ath_mutex_init (&fsm_lock); @@ -184,7 +190,20 @@ _gcry_initialize_fips_mode (int force) #endif /*HAVE_SYSLOG*/ abort (); } + + /* If the FIPS force files exists, is readable and has a number + != 0 on its first line, we enable the enforced fips mode. */ + fp = fopen (FIPS_FORCE_FILE, "r"); + if (fp) + { + char line[256]; + + if (fgets (line, sizeof line, fp) && atoi (line)) + enforced_fips_mode = 1; + fclose (fp); + } + /* Now get us into the INIT state. */ fips_new_state (STATE_INIT); @@ -245,6 +264,14 @@ _gcry_fips_mode (void) } +/* Return a flag telling whether we are in the enforced fips mode. */ +int +_gcry_enforced_fips_mode (void) +{ + return enforced_fips_mode; +} + + static const char * state2str (enum module_states state) { diff --git a/src/g10lib.h b/src/g10lib.h index 0d0aea68..6a23f261 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -293,6 +293,8 @@ void _gcry_initialize_fips_mode (int force); int _gcry_fips_mode (void); #define fips_mode() _gcry_fips_mode () +int _gcry_enforced_fips_mode (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 4af7412a..b8f7126f 100644 --- a/src/global.c +++ b/src/global.c @@ -50,6 +50,10 @@ 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; @@ -297,7 +301,9 @@ print_config ( int (*fnc)(FILE *fp, const char *format, ...), FILE *fp) /* We use y/n instead of 1/0 for the simple reason that Emacsen's compile error parser would accidently flag that line when printed during "make check" as an error. */ - fnc (fp, "fips-mode:%c:\n", fips_mode ()? 'y':'n' ); + fnc (fp, "fips-mode:%c:%c:\n", + fips_mode ()? 'y':'n'; + _gcry_enforced_fips_mode ()? 'y':'n' ); } @@ -489,7 +495,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr) break; case GCRYCTL_FIPS_MODE_P: - if (fips_mode ()) + if (fips_mode () && !inactive_fips_mode && !no_secure_memory) err = GPG_ERR_GENERAL; /* Used as TRUE value */ break; @@ -636,7 +642,10 @@ gcry_error_from_errno (int err) return gcry_error (gpg_err_code_from_errno (err)); } -/**************** + +/* Set custom allocation handlers. This is in general not useful + * because the libgcrypt allocation functions are guaranteed to + * provide proper allocation handlers which zeroize memory if needed. * NOTE: All 5 functions should be set. */ void gcry_set_allocation_handler (gcry_handler_alloc_t new_alloc_func, @@ -647,10 +656,22 @@ gcry_set_allocation_handler (gcry_handler_alloc_t new_alloc_func, { global_init (); - if (fips_mode () ) + if (fips_mode ()) { - fips_signal_error ("custom allocation handler used"); - return; + 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 + 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*/ } alloc_func = new_alloc_func; @@ -692,13 +713,28 @@ gcry_set_outofcore_handler( int (*f)( void*, size_t, unsigned int ), outofcore_handler_value = value; } +/* Return the no_secure_memory flag. */ +static int +get_no_secure_memory (void) +{ + if (!no_secure_memory) + return 0; + if (_gcry_enforced_fips_mode ()) + { + no_secure_memory = 0; + return 0; + } + return no_secure_memory; +} + + static gcry_err_code_t do_malloc (size_t n, unsigned int flags, void **mem) { gcry_err_code_t err = 0; void *m; - if ((flags & GCRY_ALLOC_FLAG_SECURE) && !no_secure_memory) + if ((flags & GCRY_ALLOC_FLAG_SECURE) && !get_no_secure_memory ()) { if (alloc_secure_func) m = (*alloc_secure_func) (n); @@ -750,7 +786,7 @@ gcry_malloc_secure (size_t n) int gcry_is_secure (const void *a) { - if (no_secure_memory) + if (get_no_secure_memory ()) return 0; if (is_secure_func) return is_secure_func (a) ; diff --git a/src/secmem.c b/src/secmem.c index 6525db05..a12af58a 100644 --- a/src/secmem.c +++ b/src/secmem.c @@ -44,7 +44,8 @@ #define MAP_ANONYMOUS MAP_ANON #endif -#define DEFAULT_POOL_SIZE 16384 +#define MINIMUM_POOL_SIZE 16384 +#define STANDARD_POOL_SIZE 32768 #define DEFAULT_PAGE_SIZE 4096 typedef struct memblock @@ -442,15 +443,12 @@ _gcry_secmem_get_flags (void) return flags; } -/* Initialize the secure memory system. If running with the necessary - privileges, the secure memory pool will be locked into the core in - order to prevent page-outs of the data. Furthermore allocated - secure memory will be wiped out when released. */ -void -_gcry_secmem_init (size_t n) -{ - SECMEM_LOCK; +/* See _gcry_secmem_init. This function is expected to be called with + the secmem lock held. */ +static void +secmem_init (size_t n) +{ if (!n) { #ifdef USE_CAPABILITIES @@ -471,8 +469,8 @@ _gcry_secmem_init (size_t n) } else { - if (n < DEFAULT_POOL_SIZE) - n = DEFAULT_POOL_SIZE; + if (n < MINIMUM_POOL_SIZE) + n = MINIMUM_POOL_SIZE; if (! pool_okay) { init_pool (n); @@ -481,6 +479,20 @@ _gcry_secmem_init (size_t n) else log_error ("Oops, secure memory pool already initialized\n"); } +} + + + +/* Initialize the secure memory system. If running with the necessary + privileges, the secure memory pool will be locked into the core in + order to prevent page-outs of the data. Furthermore allocated + secure memory will be wiped out when released. */ +void +_gcry_secmem_init (size_t n) +{ + SECMEM_LOCK; + + secmem_init (n); SECMEM_UNLOCK; } @@ -493,8 +505,19 @@ _gcry_secmem_malloc_internal (size_t size) if (!pool_okay) { - log_bug (_ - ("operation is not possible without initialized secure memory\n")); + /* Try to initialize the pool if the user forgot about it. */ + secmem_init (STANDARD_POOL_SIZE); + if (!pool_okay) + { + log_info (_("operation is not possible without " + "initialized secure memory\n")); + return NULL; + } + } + if (not_locked && fips_mode ()) + { + log_info (_("secure memory pool is not locked while in FIPS mode\n")); + return NULL; } if (show_warning && !suspend_warning) { |