diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2013-12-09 11:03:25 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2013-12-09 11:08:59 +0100 |
commit | 80596228381b256eab9e4980295f32487e530454 (patch) | |
tree | 958a20e1e445e42b1e20ab57ce91606bda474662 /lib | |
parent | 49a856323097012a465334889310de1103c966ae (diff) | |
download | gnutls-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.c | 7 | ||||
-rw-r--r-- | lib/fips.c | 13 | ||||
-rw-r--r-- | lib/fips.h | 5 | ||||
-rw-r--r-- | lib/gnutls_global.c | 2 | ||||
-rw-r--r-- | lib/gnutls_int.h | 2 | ||||
-rw-r--r-- | lib/gnutls_priority.c | 43 | ||||
-rw-r--r-- | lib/nettle/cipher.c | 51 | ||||
-rw-r--r-- | lib/nettle/mac.c | 37 |
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; |