]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added binary integrity test
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 11 Nov 2013 20:12:16 +0000 (21:12 +0100)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Wed, 27 Nov 2013 10:41:05 +0000 (11:41 +0100)
lib/fips.c
lib/fips.h

index 726dae632cb76f0a55182069d49805be86088415..c88ca419f111732d9a265b23598b4fc791c5d0ca 100644 (file)
  *
  */
 
-#ifdef ENABLE_FIPS140
+#include <gnutls_int.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+#include <unistd.h>
+#include <gnutls_errors.h>
+#include <fips.h>
 
-# include <gnutls_int.h>
-# include <gnutls/gnutls.h>
-# include <unistd.h>
+#ifdef ENABLE_FIPS140
 
-unsigned int _gnutls_fips_mode = STATE_POWERON;
+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)
+           access("/etc/system-fips", R_OK) == 0)
                return 1;
-       
+
        return 0;
 }
 
+#ifdef HAVE_DLADDR
+static const char fips_key[] = "I'd rather be skiing.";
+
+#define HMAC_SUFFIX ".hmac"
+
+
+/* Run an HMAC using the key above on the library binary data. 
+ * Returns true success and false on error.
+ */
+static unsigned check_binary_integrity(void)
+{
+       int ret;
+       Dl_info info;
+       unsigned prev;
+       char mac_file[GNUTLS_PATH_MAX];
+       uint8_t sha256_hmac[32];
+       uint8_t new_sha256_hmac[32];
+       size_t sha256_hmac_size;
+       gnutls_datum_t data;
+
+       ret = dladdr("gnutls_global_init", &info);
+       if (ret == 0)
+               return gnutls_assert_val(0);
+
+       ret = gnutls_load_file(info.dli_fname, &data);
+       if (ret < 0)
+               return gnutls_assert_val(0);
+
+       prev = _gnutls_get_fips_state();
+       _gnutls_switch_fips_state(FIPS_STATE_OPERATIONAL);
+       ret = gnutls_hmac_fast(GNUTLS_MAC_SHA256, fips_key, sizeof(fips_key)-1,
+               data.data, data.size, new_sha256_hmac);
+       _gnutls_switch_fips_state(prev);
+       
+       gnutls_free(data.data);
+
+       if (ret < 0)
+               return gnutls_assert_val(0);
+
+       /* now open the .hmac file and compare */
+       snprintf(mac_file, sizeof(mac_file), "%s"HMAC_SUFFIX, info.dli_fname);
+       
+       ret = gnutls_load_file(info.dli_fname, &data);
+       if (ret < 0)
+               return gnutls_assert_val(0);
+
+       sha256_hmac_size = sizeof(sha256_hmac);
+       ret = _gnutls_hex2bin(data.data, data.size, sha256_hmac, &sha256_hmac_size);
+       gnutls_free(data.data);
+
+       if (ret < 0)
+               return gnutls_assert_val(0);
+
+       if (sha256_hmac_size != sizeof(sha256_hmac) ||
+                       memcmp(sha256_hmac, new_sha256_hmac, sizeof(sha256_hmac)) != 0)
+               return gnutls_assert_val(0);
+       
+       return 1;
+}
+
+#else
+static int check_binary_integrity(void)
+{
+       return 1;
+}
+#endif
+
 int _gnutls_fips_perform_self_checks(void)
 {
+       int ret;
+
        _gnutls_switch_fips_state(FIPS_STATE_SELFTEST);
-       
+
        /* Tests the FIPS algorithms */
-       
+
        /* ciphers */
        ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_128_CBC);
        if (ret < 0) {
@@ -62,7 +134,7 @@ int _gnutls_fips_perform_self_checks(void)
                gnutls_assert();
                goto error;
        }
-       
+
        ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_3DES_CBC);
        if (ret < 0) {
                gnutls_assert();
@@ -131,7 +203,13 @@ int _gnutls_fips_perform_self_checks(void)
                goto error;
        }
 
-       ret = gnutls_pk_self_test(0, GNUTLS_PK_ECDSA);
+       ret = gnutls_pk_self_test(0, GNUTLS_PK_EC);
+       if (ret < 0) {
+               gnutls_assert();
+               goto error;
+       }
+       
+       ret = check_binary_integrity();
        if (ret < 0) {
                gnutls_assert();
                goto error;
@@ -140,7 +218,8 @@ int _gnutls_fips_perform_self_checks(void)
        return 0;
 error:
        _gnutls_switch_fips_state(FIPS_STATE_ERROR);
-       return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERR);
+
+       return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
 }
 
 #endif
index 9cd17a40c0829914a8d0826b72b4cbeeaf25b64e..355ab9ee61ecf81fb02cf4e363653fb11edc0590 100644 (file)
@@ -23,6 +23,7 @@
 #ifndef FIPS_H
 # define FIPS_H
 
+#include <gnutls_int.h>
 #include <gnutls/gnutls.h>
 
 typedef enum {