From aa709f291994a74271271b6dd61563cc3844e3ad Mon Sep 17 00:00:00 2001 From: Marius Tomaschewski Date: Tue, 16 Dec 2014 23:19:20 +0100 Subject: [PATCH] strongswan: filter algorithms for fips mode References: fate#316931,bnc#856322 diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c index 2ecdb4f..a858162 100644 --- a/src/libcharon/config/proposal.c +++ b/src/libcharon/config/proposal.c @@ -26,6 +26,11 @@ #include #include #include +#include +#include +#include +#include +#include ENUM(protocol_id_names, PROTO_NONE, PROTO_IPCOMP, "PROTO_NONE", @@ -185,6 +190,122 @@ METHOD(proposal_t, strip_dh, void, enumerator->destroy(enumerator); } +static bool kernel_fips_enabled(void) +{ + char buf[1] = { '\0' }; + int fd; + + fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY); + if (fd >= 0) { + while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR); + close(fd); + } + return buf[0] == '1'; +} + +static bool fips_enabled(void) +{ + static int enabled = -1; + if (enabled == -1) + enabled = kernel_fips_enabled(); + return enabled; +} + +static bool fips_filter(protocol_id_t protocol, transform_type_t type, u_int16_t alg) +{ + switch (protocol) + { + case PROTO_IKE: + case PROTO_ESP: + case PROTO_AH: + break; + default: + /* not applicable protocol */ + return TRUE; + } + + switch (type) + { + case ENCRYPTION_ALGORITHM: + switch (alg) + { + /* crypter */ + case ENCR_3DES: + case ENCR_AES_CBC: + case ENCR_AES_CTR: + /* aead */ + case ENCR_AES_GCM_ICV8: + case ENCR_AES_GCM_ICV12: + case ENCR_AES_GCM_ICV16: + case ENCR_AES_CCM_ICV8: + case ENCR_AES_CCM_ICV12: + case ENCR_AES_CCM_ICV16: + return TRUE; + default: + break; + } + break; + case INTEGRITY_ALGORITHM: + switch (alg) + { + case AUTH_HMAC_SHA1_96: + case AUTH_HMAC_SHA1_160: + case AUTH_HMAC_SHA2_256_96: + case AUTH_HMAC_SHA2_256_128: + case AUTH_HMAC_SHA2_384_192: + case AUTH_HMAC_SHA2_512_256: + case AUTH_AES_CMAC_96: + return TRUE; + default: + break; + } + break; + case PSEUDO_RANDOM_FUNCTION: + switch (alg) + { + case PRF_HMAC_SHA1: + case PRF_HMAC_SHA2_256: + case PRF_HMAC_SHA2_384: + case PRF_HMAC_SHA2_512: + case PRF_AES128_CMAC: + return TRUE; + default: + break; + } + break; + case DIFFIE_HELLMAN_GROUP: + switch (alg) + { + case MODP_2048_BIT: + case MODP_3072_BIT: + case MODP_4096_BIT: + case MODP_8192_BIT: + case MODP_2048_224: + case MODP_2048_256: + case ECP_224_BIT: + case ECP_256_BIT: + case ECP_384_BIT: + case ECP_521_BIT: + return TRUE; + default: + break; + } + break; + case EXTENDED_SEQUENCE_NUMBERS: + switch (alg) + { + case EXT_SEQ_NUMBERS: + case NO_EXT_SEQ_NUMBERS: + return TRUE; + default: + break; + } + default: + break; + } + return !fips_enabled(); +} + /** * Select a matching proposal from this and other, insert into selected. */ @@ -500,6 +621,11 @@ static bool add_string_algo(private_proposal_t *this, const char *alg) return FALSE; } + if (!fips_filter(this->protocol, token->type, token->algorithm)) + { + DBG1(DBG_CFG, "algorithm '%s' not permitted in fips mode", alg); + return FALSE; + } add_algorithm(this, token->type, token->algorithm, token->keysize); return TRUE; @@ -639,6 +765,8 @@ static void proposal_add_supported_ike(private_proposal_t *this) enumerator = lib->crypto->create_crypter_enumerator(lib->crypto); while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) { + if (!fips_filter(PROTO_IKE, ENCRYPTION_ALGORITHM, encryption)) + continue; switch (encryption) { case ENCR_AES_CBC: @@ -665,6 +793,9 @@ static void proposal_add_supported_ike(private_proposal_t *this) enumerator = lib->crypto->create_aead_enumerator(lib->crypto); while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) { + if (!fips_filter(PROTO_IKE, ENCRYPTION_ALGORITHM, encryption)) + continue; + switch (encryption) { case ENCR_AES_CCM_ICV8: @@ -690,6 +821,8 @@ static void proposal_add_supported_ike(private_proposal_t *this) enumerator = lib->crypto->create_signer_enumerator(lib->crypto); while (enumerator->enumerate(enumerator, &integrity, &plugin_name)) { + if (!fips_filter(PROTO_IKE, INTEGRITY_ALGORITHM, integrity)) + continue; switch (integrity) { case AUTH_HMAC_SHA1_96: @@ -710,6 +843,8 @@ static void proposal_add_supported_ike(private_proposal_t *this) enumerator = lib->crypto->create_prf_enumerator(lib->crypto); while (enumerator->enumerate(enumerator, &prf, &plugin_name)) { + if (!fips_filter(PROTO_IKE, PSEUDO_RANDOM_FUNCTION, prf)) + continue; switch (prf) { case PRF_HMAC_SHA1: @@ -730,6 +865,8 @@ static void proposal_add_supported_ike(private_proposal_t *this) enumerator = lib->crypto->create_dh_enumerator(lib->crypto); while (enumerator->enumerate(enumerator, &group, &plugin_name)) { + if (!fips_filter(PROTO_IKE, DIFFIE_HELLMAN_GROUP, group)) + continue; switch (group) { case MODP_NULL: @@ -776,31 +913,35 @@ proposal_t *proposal_create_default(protocol_id_t protocol) { private_proposal_t *this = (private_proposal_t*)proposal_create(protocol, 0); +#define fips_add_algorithm(this, type, alg, len) \ + if (fips_filter(this->protocol, type, alg)) \ + add_algorithm(this, type, alg, len); switch (protocol) { case PROTO_IKE: proposal_add_supported_ike(this); break; case PROTO_ESP: - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192); - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0); - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); - add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); + fips_add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); + fips_add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192); + fips_add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); + fips_add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0); + fips_add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256); + fips_add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); + fips_add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); + fips_add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); + fips_add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); break; case PROTO_AH: - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); - add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); + fips_add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); + fips_add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); + fips_add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); + fips_add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); break; default: break; } +#undef fips_add_algorithm return &this->public; } -- 2.2.0