diff options
-rw-r--r-- | lib/crypto-api.c | 7 | ||||
-rw-r--r-- | lib/fips.c | 49 | ||||
-rw-r--r-- | lib/fips.h | 11 | ||||
-rw-r--r-- | lib/gnutls_global.c | 15 |
4 files changed, 58 insertions, 24 deletions
diff --git a/lib/crypto-api.c b/lib/crypto-api.c index 0f421fae22..b2d11a414f 100644 --- a/lib/crypto-api.c +++ b/lib/crypto-api.c @@ -317,8 +317,11 @@ gnutls_hmac_init(gnutls_hmac_hd_t * dig, { #ifdef ENABLE_FIPS140 /* MD5 is only allowed internally for TLS */ - if (algorithm == GNUTLS_MAC_MD5) - return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM); + if (_gnutls_get_fips_state() != FIPS_STATE_SELFTEST && + _gnutls_get_fips_state() != FIPS_STATE_ZOMBIE) { + if (algorithm == GNUTLS_MAC_MD5) + return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM); + } #endif *dig = gnutls_malloc(sizeof(mac_hd_st)); diff --git a/lib/fips.c b/lib/fips.c index 72bbd68a6e..6587e8b921 100644 --- a/lib/fips.c +++ b/lib/fips.c @@ -25,29 +25,51 @@ #include <unistd.h> #include <gnutls_errors.h> #include <fips.h> +#include <stdio.h> #include <random.h> #include <gnutls/fips140.h> #include <dlfcn.h> #ifdef ENABLE_FIPS140 +#define FIPS_KERNEL_FILE "/proc/sys/crypto/fips_enabled" +#define FIPS_SYSTEM_FILE "/etc/system-fips" + unsigned int _gnutls_fips_mode = FIPS_STATE_POWERON; unsigned _gnutls_fips_mode_enabled(void) { - /* FIXME: There are some subtle differences here. Check it out later */ - if (access("/proc/sys/crypto/fips_enabled", R_OK) == 0 && - access("/etc/system-fips", R_OK) == 0) +unsigned f1p, f2p; +FILE* fd; + + fd = fopen(FIPS_KERNEL_FILE, "r"); + if (fd != NULL) { + f1p = fgetc(fd); + fclose(fd); + + if (f1p == '1') f1p = 1; + else f1p = 0; + } + + f2p = !access(FIPS_SYSTEM_FILE, R_OK); + + if (f1p != 0 && f2p != 0) { + _gnutls_debug_log("FIPS140-2 mode enabled\n"); return 1; + } + + if (f2p != 0) { + /* a funny state where self tests are performed + * and ignored */ + _gnutls_switch_fips_state(FIPS_STATE_ZOMBIE); + _gnutls_debug_log("FIPS140-2 ZOMBIE mode enabled\n"); + return 1; + } -#ifndef FIPS140_TEST return 0; -#else - return 1; -#endif } -static const char fips_key[] = "I'd rather be skiing."; +static const char fips_key[] = "orboDeJITITejsirpADONivirpUkvarP"; #define HMAC_SUFFIX ".hmac" #define HMAC_SIZE 32 @@ -91,21 +113,26 @@ static unsigned check_binary_integrity(void) snprintf(mac_file, sizeof(mac_file), "%s"HMAC_SUFFIX, info.dli_fname); ret = gnutls_load_file(mac_file, &data); - if (ret < 0) + if (ret < 0) { + _gnutls_debug_log("Could not open %s%s for MAC testing: %s\n", info.dli_fname, HMAC_SUFFIX, gnutls_strerror(ret)); return gnutls_assert_val(0); + } hmac_size = sizeof(hmac); ret = _gnutls_hex2bin((void*)data.data, data.size, hmac, &hmac_size); gnutls_free(data.data); - if (ret < 0) + if (ret < 0) { + _gnutls_debug_log("Could not convert hex data to binary for MAC testing.\n"); return gnutls_assert_val(0); + } if (hmac_size != sizeof(hmac) || memcmp(hmac, new_hmac, sizeof(hmac)) != 0) { _gnutls_debug_log("Calculated MAC does not match\n"); return gnutls_assert_val(0); } + _gnutls_debug_log("Successfully verified library MAC\n"); return 1; } @@ -214,9 +241,7 @@ int _gnutls_fips_perform_self_checks(void) ret = check_binary_integrity(); if (ret == 0) { gnutls_assert(); -#ifndef FIPS140_TEST goto error; -#endif } if (_gnutls_rnd_ops.self_test == NULL) { diff --git a/lib/fips.h b/lib/fips.h index 867431c5e7..eae742c848 100644 --- a/lib/fips.h +++ b/lib/fips.h @@ -26,13 +26,11 @@ #include <gnutls_int.h> #include <gnutls/gnutls.h> -/* This must be removed when finished */ -#define FIPS140_TEST - #define FIPS140_RND_KEY_SIZE 32 typedef enum { FIPS_STATE_POWERON, + FIPS_STATE_ZOMBIE, FIPS_STATE_INIT, FIPS_STATE_SELFTEST, FIPS_STATE_OPERATIONAL, @@ -48,7 +46,9 @@ extern unsigned int _gnutls_fips_mode; inline static void _gnutls_switch_fips_state(gnutls_fips_state_t state) { - _gnutls_fips_mode = state; + /* Once into zombie state no errors can change us */ + if (_gnutls_fips_mode != FIPS_STATE_ZOMBIE) + _gnutls_fips_mode = state; } inline static gnutls_fips_state_t _gnutls_get_fips_state(void) @@ -61,7 +61,8 @@ unsigned _gnutls_fips_mode_enabled(void); # define FAIL_IF_FIPS_ERROR \ if (_gnutls_get_fips_state() != FIPS_STATE_OPERATIONAL && \ - _gnutls_get_fips_state() != FIPS_STATE_SELFTEST) return GNUTLS_E_LIB_IN_ERROR_STATE + _gnutls_get_fips_state() != FIPS_STATE_SELFTEST && \ + _gnutls_get_fips_state() != FIPS_STATE_ZOMBIE) return GNUTLS_E_LIB_IN_ERROR_STATE void _gnutls_switch_fips_state(gnutls_fips_state_t state); diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c index 12912f73d9..8c8bef8db8 100644 --- a/lib/gnutls_global.c +++ b/lib/gnutls_global.c @@ -282,12 +282,17 @@ int gnutls_global_init(void) #endif _gnutls_cryptodev_init(); - - if (_gnutls_fips_mode_enabled()) { + + result = _gnutls_fips_mode_enabled(); + if (result != 0) { result = _gnutls_fips_perform_self_checks(); - if (result < 0) { - gnutls_assert(); - goto out; + if (_gnutls_get_fips_state() != FIPS_STATE_ZOMBIE) { + if (result < 0) { + gnutls_assert(); + goto out; + } + } else { + result = 0; } _gnutls_switch_fips_state(FIPS_STATE_OPERATIONAL); } |