summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/crypto-api.c7
-rw-r--r--lib/fips.c49
-rw-r--r--lib/fips.h11
-rw-r--r--lib/gnutls_global.c15
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);
}