summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2013-12-09 11:03:25 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2013-12-09 11:08:59 +0100
commit80596228381b256eab9e4980295f32487e530454 (patch)
tree958a20e1e445e42b1e20ab57ce91606bda474662 /lib
parent49a856323097012a465334889310de1103c966ae (diff)
downloadgnutls-80596228381b256eab9e4980295f32487e530454.tar.gz
FIPS140 mode is detected on run-time.
That allows a library compiled in FIPS140 mode to operate as the full library if the system is not in FIPS mode.
Diffstat (limited to 'lib')
-rw-r--r--lib/crypto-api.c7
-rw-r--r--lib/fips.c13
-rw-r--r--lib/fips.h5
-rw-r--r--lib/gnutls_global.c2
-rw-r--r--lib/gnutls_int.h2
-rw-r--r--lib/gnutls_priority.c43
-rw-r--r--lib/nettle/cipher.c51
-rw-r--r--lib/nettle/mac.c37
8 files changed, 116 insertions, 44 deletions
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
index 850e206898..5f8be211a3 100644
--- a/lib/crypto-api.c
+++ b/lib/crypto-api.c
@@ -317,7 +317,7 @@ gnutls_hmac_init(gnutls_hmac_hd_t * dig,
{
#ifdef ENABLE_FIPS140
/* MD5 is only allowed internally for TLS */
- if (gnutls_fips140_mode_enabled() != 0 &&
+ if (_gnutls_fips_mode_enabled() != 0 &&
_gnutls_get_lib_state() != LIB_STATE_SELFTEST) {
if (algorithm == GNUTLS_MAC_MD5)
@@ -464,7 +464,7 @@ gnutls_hash_init(gnutls_hash_hd_t * dig,
{
#ifdef ENABLE_FIPS140
/* MD5 is only allowed internally for TLS */
- if (gnutls_fips140_mode_enabled() != 0 &&
+ if (_gnutls_fips_mode_enabled() != 0 &&
_gnutls_get_lib_state() != LIB_STATE_SELFTEST) {
if (algorithm == GNUTLS_DIG_MD5)
@@ -589,7 +589,8 @@ int gnutls_key_generate(gnutls_datum_t * key, unsigned int key_size)
/* The FIPS140 approved RNGs are not allowed to be used
* to extract key sizes longer than their original seed.
*/
- if (key_size > FIPS140_RND_KEY_SIZE)
+ if (_gnutls_fips_mode_enabled() != 0 &&
+ key_size > FIPS140_RND_KEY_SIZE)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
#endif
diff --git a/lib/fips.c b/lib/fips.c
index 3444e4d577..3f3fec0d0f 100644
--- a/lib/fips.c
+++ b/lib/fips.c
@@ -39,7 +39,11 @@ unsigned _gnutls_fips_mode_enabled(void)
{
unsigned f1p, f2p;
FILE* fd;
+static int fips_mode = -1;
+ if (fips_mode != -1)
+ return fips_mode;
+
fd = fopen(FIPS_KERNEL_FILE, "r");
if (fd != NULL) {
f1p = fgetc(fd);
@@ -53,17 +57,20 @@ FILE* fd;
if (f1p != 0 && f2p != 0) {
_gnutls_debug_log("FIPS140-2 mode enabled\n");
- return 1;
+ fips_mode = 1;
+ return fips_mode;
}
if (f2p != 0) {
/* a funny state where self tests are performed
* and ignored */
_gnutls_debug_log("FIPS140-2 ZOMBIE mode enabled\n");
- return 2;
+ fips_mode = 2;
+ return fips_mode;
}
- return 0;
+ fips_mode = 0;
+ return fips_mode;
}
#define GNUTLS_LIBRARY_NAME "libgnutls.so.28"
diff --git a/lib/fips.h b/lib/fips.h
index 6b48be4a5a..375e244300 100644
--- a/lib/fips.h
+++ b/lib/fips.h
@@ -53,7 +53,12 @@ inline static gnutls_lib_state_t _gnutls_get_lib_state(void)
}
int _gnutls_fips_perform_self_checks(void);
+
+#ifdef ENABLE_FIPS140
unsigned _gnutls_fips_mode_enabled(void);
+#else
+# define _gnutls_fips_mode_enabled() 0
+#endif
# define FAIL_IF_LIB_ERROR \
if (_gnutls_get_lib_state() != LIB_STATE_OPERATIONAL && \
diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c
index f23967f92d..b99ad28e0b 100644
--- a/lib/gnutls_global.c
+++ b/lib/gnutls_global.c
@@ -338,6 +338,8 @@ static int gnutls_global_init2(unsigned int flags)
* res == not in fips140 mode
*/
if (res != 0) {
+ _gnutls_priority_update_fips();
+
ret = _gnutls_fips_perform_self_checks();
if (res != 2) {
if (ret < 0) {
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 1304b8ff67..3d30218cd6 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -1022,6 +1022,8 @@ inline static unsigned get_num_version(gnutls_session_t session)
return GNUTLS_VERSION_UNKNOWN;
}
+void _gnutls_priority_update_fips(void);
+
#define _gnutls_set_current_version(s, v) { \
s->security_parameters.pversion = version_to_entry(v); \
}
diff --git a/lib/gnutls_priority.c b/lib/gnutls_priority.c
index 912ec856ad..14566b1570 100644
--- a/lib/gnutls_priority.c
+++ b/lib/gnutls_priority.c
@@ -338,11 +338,7 @@ static const int kx_priority_secure[] = {
0
};
-#ifndef ENABLE_FIPS140
-/* If GCM and AES acceleration is available then prefer
- * them over anything else.
- */
-static const int cipher_priority_performance[] = {
+static const int cipher_priority_performance_default[] = {
GNUTLS_CIPHER_ARCFOUR_128,
GNUTLS_CIPHER_AES_128_GCM,
GNUTLS_CIPHER_AES_256_GCM,
@@ -356,7 +352,10 @@ static const int cipher_priority_performance[] = {
0
};
-static const int cipher_priority_normal[] = {
+/* If GCM and AES acceleration is available then prefer
+ * them over anything else.
+ */
+static const int cipher_priority_normal_default[] = {
GNUTLS_CIPHER_AES_128_GCM,
GNUTLS_CIPHER_AES_256_GCM,
GNUTLS_CIPHER_CAMELLIA_128_GCM,
@@ -369,8 +368,8 @@ static const int cipher_priority_normal[] = {
GNUTLS_CIPHER_ARCFOUR_128,
0
};
-#else
-static const int cipher_priority_performance[] = {
+
+static const int cipher_priority_performance_fips[] = {
GNUTLS_CIPHER_AES_128_GCM,
GNUTLS_CIPHER_AES_256_GCM,
GNUTLS_CIPHER_AES_128_CBC,
@@ -379,7 +378,7 @@ static const int cipher_priority_performance[] = {
0
};
-static const int cipher_priority_normal[] = {
+static const int cipher_priority_normal_fips[] = {
GNUTLS_CIPHER_AES_128_GCM,
GNUTLS_CIPHER_AES_256_GCM,
GNUTLS_CIPHER_AES_128_CBC,
@@ -387,7 +386,7 @@ static const int cipher_priority_normal[] = {
GNUTLS_CIPHER_3DES_CBC,
0
};
-#endif
+
static const int cipher_priority_suiteb128[] = {
GNUTLS_CIPHER_AES_128_GCM,
@@ -480,17 +479,35 @@ static const int sign_priority_secure192[] = {
0
};
-static const int mac_priority_normal[] = {
+static const int mac_priority_normal_default[] = {
GNUTLS_MAC_SHA1,
GNUTLS_MAC_SHA256,
GNUTLS_MAC_SHA384,
GNUTLS_MAC_AEAD,
-#ifndef ENABLE_FIPS140
GNUTLS_MAC_MD5,
-#endif
0
};
+static const int mac_priority_normal_fips[] = {
+ GNUTLS_MAC_SHA1,
+ GNUTLS_MAC_SHA256,
+ GNUTLS_MAC_SHA384,
+ GNUTLS_MAC_AEAD,
+ 0
+};
+
+static const int * cipher_priority_performance = cipher_priority_performance_default;
+static const int * cipher_priority_normal = cipher_priority_normal_default;
+static const int * mac_priority_normal = mac_priority_normal_default;
+
+/* if called with replace the default priorities with the FIPS140 ones */
+void _gnutls_priority_update_fips(void)
+{
+ cipher_priority_performance = cipher_priority_performance_fips;
+ cipher_priority_normal = cipher_priority_normal_fips;
+ mac_priority_normal = mac_priority_normal_fips;
+}
+
static const int mac_priority_suiteb128[] = {
GNUTLS_MAC_AEAD,
0
diff --git a/lib/nettle/cipher.c b/lib/nettle/cipher.c
index e50f4726e6..f765b64264 100644
--- a/lib/nettle/cipher.c
+++ b/lib/nettle/cipher.c
@@ -36,6 +36,7 @@
#include <nettle/cbc.h>
#include <nettle/gcm.h>
#include <gcm-camellia.h>
+#include <fips.h>
/* Functions that refer to the nettle library.
*/
@@ -130,7 +131,7 @@ static int wrap_nettle_cipher_exists(gnutls_cipher_algorithm_t algo)
case GNUTLS_CIPHER_AES_192_CBC:
case GNUTLS_CIPHER_AES_256_CBC:
case GNUTLS_CIPHER_3DES_CBC:
-#ifndef ENABLE_FIPS140
+ return 1;
case GNUTLS_CIPHER_CAMELLIA_128_GCM:
case GNUTLS_CIPHER_CAMELLIA_256_GCM:
case GNUTLS_CIPHER_CAMELLIA_128_CBC:
@@ -142,8 +143,10 @@ static int wrap_nettle_cipher_exists(gnutls_cipher_algorithm_t algo)
case GNUTLS_CIPHER_ESTREAM_SALSA20_256:
case GNUTLS_CIPHER_ARCFOUR_40:
case GNUTLS_CIPHER_RC2_40_CBC:
-#endif
- return 1;
+ if (_gnutls_fips_mode_enabled() != 0)
+ return 0;
+ else
+ return 1;
default:
return 0;
}
@@ -193,9 +196,11 @@ wrap_nettle_cipher_init(gnutls_cipher_algorithm_t algo, void **_ctx,
ctx->ctx_ptr = &ctx->ctx.des3;
ctx->block_size = DES3_BLOCK_SIZE;
break;
-#ifndef ENABLE_FIPS140
case GNUTLS_CIPHER_CAMELLIA_128_GCM:
case GNUTLS_CIPHER_CAMELLIA_256_GCM:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
ctx->encrypt = _camellia_gcm_encrypt;
ctx->decrypt = _camellia_gcm_decrypt;
ctx->i_encrypt = (nettle_crypt_func *) camellia_crypt;
@@ -207,6 +212,9 @@ wrap_nettle_cipher_init(gnutls_cipher_algorithm_t algo, void **_ctx,
case GNUTLS_CIPHER_CAMELLIA_128_CBC:
case GNUTLS_CIPHER_CAMELLIA_192_CBC:
case GNUTLS_CIPHER_CAMELLIA_256_CBC:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
ctx->encrypt = cbc_encrypt;
ctx->decrypt = cbc_decrypt;
ctx->i_encrypt = (nettle_crypt_func *) camellia_crypt;
@@ -215,6 +223,9 @@ wrap_nettle_cipher_init(gnutls_cipher_algorithm_t algo, void **_ctx,
ctx->block_size = CAMELLIA_BLOCK_SIZE;
break;
case GNUTLS_CIPHER_DES_CBC:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
ctx->encrypt = cbc_encrypt;
ctx->decrypt = cbc_decrypt;
ctx->i_encrypt = (nettle_crypt_func *) des_encrypt;
@@ -224,6 +235,9 @@ wrap_nettle_cipher_init(gnutls_cipher_algorithm_t algo, void **_ctx,
break;
case GNUTLS_CIPHER_ARCFOUR_128:
case GNUTLS_CIPHER_ARCFOUR_40:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
ctx->encrypt = stream_encrypt;
ctx->decrypt = stream_encrypt;
ctx->i_encrypt = (nettle_crypt_func *) arcfour_crypt;
@@ -232,6 +246,9 @@ wrap_nettle_cipher_init(gnutls_cipher_algorithm_t algo, void **_ctx,
ctx->block_size = 1;
break;
case GNUTLS_CIPHER_SALSA20_256:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
ctx->encrypt = stream_encrypt;
ctx->decrypt = stream_encrypt;
ctx->i_encrypt = (nettle_crypt_func *) salsa20_crypt;
@@ -240,6 +257,9 @@ wrap_nettle_cipher_init(gnutls_cipher_algorithm_t algo, void **_ctx,
ctx->block_size = 1;
break;
case GNUTLS_CIPHER_ESTREAM_SALSA20_256:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
ctx->encrypt = stream_encrypt;
ctx->decrypt = stream_encrypt;
ctx->i_encrypt = (nettle_crypt_func *) salsa20r12_crypt;
@@ -248,6 +268,9 @@ wrap_nettle_cipher_init(gnutls_cipher_algorithm_t algo, void **_ctx,
ctx->block_size = 1;
break;
case GNUTLS_CIPHER_RC2_40_CBC:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
ctx->encrypt = cbc_encrypt;
ctx->decrypt = cbc_decrypt;
ctx->i_encrypt = (nettle_crypt_func *) arctwo_encrypt;
@@ -255,7 +278,6 @@ wrap_nettle_cipher_init(gnutls_cipher_algorithm_t algo, void **_ctx,
ctx->ctx_ptr = &ctx->ctx.arctwo;
ctx->block_size = ARCTWO_BLOCK_SIZE;
break;
-#endif
default:
gnutls_assert();
gnutls_free(ctx);
@@ -312,13 +334,18 @@ wrap_nettle_cipher_setkey(void *_ctx, const void *key, size_t keysize)
zeroize_temp_key(des_key, sizeof(des_key));
break;
-#ifndef ENABLE_FIPS140
case GNUTLS_CIPHER_CAMELLIA_128_GCM:
case GNUTLS_CIPHER_CAMELLIA_256_GCM:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
_gcm_camellia_set_key(&ctx->ctx.camellia_gcm, keysize,
key);
break;
case GNUTLS_CIPHER_DES_CBC:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
if (keysize != DES_KEY_SIZE) {
gnutls_assert();
return GNUTLS_E_INTERNAL_ERROR;
@@ -334,16 +361,24 @@ wrap_nettle_cipher_setkey(void *_ctx, const void *key, size_t keysize)
break;
case GNUTLS_CIPHER_ARCFOUR_128:
case GNUTLS_CIPHER_ARCFOUR_40:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
arcfour_set_key(ctx->ctx_ptr, keysize, key);
break;
case GNUTLS_CIPHER_SALSA20_256:
case GNUTLS_CIPHER_ESTREAM_SALSA20_256:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
salsa20_set_key(ctx->ctx_ptr, keysize, key);
break;
case GNUTLS_CIPHER_RC2_40_CBC:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
arctwo_set_key(ctx->ctx_ptr, keysize, key);
break;
-#endif
default:
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
@@ -366,7 +401,6 @@ wrap_nettle_cipher_setiv(void *_ctx, const void *iv, size_t ivsize)
gcm_aes_set_iv(&ctx->ctx.aes_gcm, GCM_DEFAULT_NONCE_SIZE,
iv);
break;
-#ifndef ENABLE_FIPS140
case GNUTLS_CIPHER_CAMELLIA_128_GCM:
case GNUTLS_CIPHER_CAMELLIA_256_GCM:
if (ivsize != GCM_DEFAULT_NONCE_SIZE)
@@ -382,7 +416,6 @@ wrap_nettle_cipher_setiv(void *_ctx, const void *iv, size_t ivsize)
salsa20_set_iv(&ctx->ctx.salsa20, iv);
break;
-#endif
default:
if (ivsize > ctx->block_size)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
diff --git a/lib/nettle/mac.c b/lib/nettle/mac.c
index 9e87a312e3..7b75cd4d7f 100644
--- a/lib/nettle/mac.c
+++ b/lib/nettle/mac.c
@@ -31,6 +31,7 @@
#include <nettle/sha.h>
#include <nettle/hmac.h>
#include <nettle/umac.h>
+#include <fips.h>
typedef void (*update_func) (void *, unsigned, const uint8_t *);
typedef void (*digest_func) (void *, unsigned, uint8_t *);
@@ -48,9 +49,7 @@ struct nettle_hash_ctx {
struct sha384_ctx sha384;
struct sha512_ctx sha512;
struct sha1_ctx sha1;
-#ifndef ENABLE_FIPS140
struct md2_ctx md2;
-#endif
} ctx;
void *ctx_ptr;
gnutls_digest_algorithm_t algo;
@@ -67,10 +66,8 @@ struct nettle_mac_ctx {
struct hmac_sha384_ctx sha384;
struct hmac_sha512_ctx sha512;
struct hmac_sha1_ctx sha1;
-#ifndef ENABLE_FIPS140
struct umac96_ctx umac96;
struct umac128_ctx umac128;
-#endif
} ctx;
void *ctx_ptr;
@@ -82,7 +79,6 @@ struct nettle_mac_ctx {
set_nonce_func set_nonce;
};
-#ifndef ENABLE_FIPS140
static void
_wrap_umac96_set_key(void *ctx, unsigned len, const uint8_t * key)
{
@@ -98,7 +94,6 @@ _wrap_umac128_set_key(void *ctx, unsigned len, const uint8_t * key)
abort();
umac128_set_key(ctx, key);
}
-#endif
static int _mac_ctx_init(gnutls_mac_algorithm_t algo,
struct nettle_mac_ctx *ctx)
@@ -147,8 +142,10 @@ static int _mac_ctx_init(gnutls_mac_algorithm_t algo,
ctx->ctx_ptr = &ctx->ctx.sha512;
ctx->length = SHA512_DIGEST_SIZE;
break;
-#ifndef ENABLE_FIPS140
case GNUTLS_MAC_UMAC_96:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
ctx->update = (update_func) umac96_update;
ctx->digest = (digest_func) umac96_digest;
ctx->set_key = _wrap_umac96_set_key;
@@ -157,6 +154,9 @@ static int _mac_ctx_init(gnutls_mac_algorithm_t algo,
ctx->length = 12;
break;
case GNUTLS_MAC_UMAC_128:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
ctx->update = (update_func) umac128_update;
ctx->digest = (digest_func) umac128_digest;
ctx->set_key = _wrap_umac128_set_key;
@@ -164,7 +164,6 @@ static int _mac_ctx_init(gnutls_mac_algorithm_t algo,
ctx->ctx_ptr = &ctx->ctx.umac128;
ctx->length = 16;
break;
-#endif
default:
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
@@ -206,11 +205,14 @@ static int wrap_nettle_mac_exists(gnutls_mac_algorithm_t algo)
case GNUTLS_MAC_SHA256:
case GNUTLS_MAC_SHA384:
case GNUTLS_MAC_SHA512:
-#ifndef ENABLE_FIPS140
+ return 1;
+
case GNUTLS_MAC_UMAC_96:
case GNUTLS_MAC_UMAC_128:
-#endif
- return 1;
+ if (_gnutls_fips_mode_enabled() != 0)
+ return 0;
+ else
+ return 1;
default:
return 0;
}
@@ -323,10 +325,12 @@ static int wrap_nettle_hash_exists(gnutls_digest_algorithm_t algo)
case GNUTLS_DIG_SHA256:
case GNUTLS_DIG_SHA384:
case GNUTLS_DIG_SHA512:
-#ifndef ENABLE_FIPS140
- case GNUTLS_DIG_MD2:
-#endif
return 1;
+ case GNUTLS_DIG_MD2:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return 0;
+ else
+ return 1;
default:
return 0;
}
@@ -378,15 +382,16 @@ static int _ctx_init(gnutls_digest_algorithm_t algo,
ctx->ctx_ptr = &ctx->ctx.sha512;
ctx->length = SHA512_DIGEST_SIZE;
break;
-#ifndef ENABLE_FIPS140
case GNUTLS_DIG_MD2:
+ if (_gnutls_fips_mode_enabled() != 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
md2_init(&ctx->ctx.md2);
ctx->update = (update_func) md2_update;
ctx->digest = (digest_func) md2_digest;
ctx->ctx_ptr = &ctx->ctx.md2;
ctx->length = MD2_DIGEST_SIZE;
break;
-#endif
default:
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;