]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Better handling of FIPS140-2 initialization
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 22 Nov 2013 13:33:23 +0000 (14:33 +0100)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Wed, 27 Nov 2013 10:41:44 +0000 (11:41 +0100)
lib/crypto-api.c
lib/fips.c
lib/fips.h
lib/gnutls_global.c

index 0f421fae22c11c7754090c9c266b473d0a4075b8..b2d11a414f02ef0e47b4e23dc1d2f105cd13044e 100644 (file)
@@ -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));
index 72bbd68a6e1fbb755b70818ae2cf32740acac974..6587e8b921cdf1dda1864329d64e4c8507576f59 100644 (file)
 #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) {
index 867431c5e7930bf0f13fbaa1b86eeb394d1229b3..eae742c848218eea16e069abe95ecf929cdf3c50 100644 (file)
 #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);
 
index 12912f73d96dbb2cc8bec11cda1234c86b095854..8c8bef8db8b6ffaf7cf91bf10e001cd978dfe6b9 100644 (file)
@@ -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);
        }