summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2008-09-18 12:14:09 +0000
committerWerner Koch <wk@gnupg.org>2008-09-18 12:14:09 +0000
commit29e44067f0797219b115fabf069e279283f13c13 (patch)
tree3ac09da7677080eb352c6957031724bc40521877 /src
parent58b91cf9cc72e7a7247f88279e3fbeba71619237 (diff)
downloadlibgcrypt-29e44067f0797219b115fabf069e279283f13c13.tar.gz
Implemented an Enforced FIPS mode.
Documentation updates.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog23
-rw-r--r--src/fips.c39
-rw-r--r--src/g10lib.h2
-rw-r--r--src/global.c52
-rw-r--r--src/secmem.c49
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.
diff --git a/src/fips.c b/src/fips.c
index e98930d7..90fb3e22 100644
--- a/src/fips.c
+++ b/src/fips.c
@@ -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)
{