From 8c617d0689bb54a1c25a1af511e5693428c64ce4 Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Thu, 22 Aug 2024 21:31:57 +0000 Subject: [PATCH 1/3] KBKDF_ctr_hmac FIPS indicator --- crypto/fipsmodule/kdf/kbkdf.c | 8 +++ .../fipsmodule/service_indicator/internal.h | 3 ++ .../service_indicator/service_indicator.c | 52 ++++++++++++------- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/crypto/fipsmodule/kdf/kbkdf.c b/crypto/fipsmodule/kdf/kbkdf.c index 02c3ded24e..ce94444caa 100644 --- a/crypto/fipsmodule/kdf/kbkdf.c +++ b/crypto/fipsmodule/kdf/kbkdf.c @@ -7,6 +7,10 @@ int KBKDF_ctr_hmac(uint8_t *out_key, size_t out_len, const EVP_MD *digest, const uint8_t *secret, size_t secret_len, const uint8_t *info, size_t info_len) { + // We have to avoid the underlying |HMAC_Final| services updating + // the indicator state, so we lock the state here. + FIPS_service_indicator_lock_state(); + int ret = 0; HMAC_CTX *hmac_ctx = NULL; @@ -96,5 +100,9 @@ int KBKDF_ctr_hmac(uint8_t *out_key, size_t out_len, const EVP_MD *digest, OPENSSL_cleanse(out_key, out_len); } HMAC_CTX_free(hmac_ctx); + FIPS_service_indicator_unlock_state(); + if (ret) { + KBKDF_ctr_hmac_verify_service_indicator(digest); + } return ret; } diff --git a/crypto/fipsmodule/service_indicator/internal.h b/crypto/fipsmodule/service_indicator/internal.h index e05c4d6201..69f48f6c3a 100644 --- a/crypto/fipsmodule/service_indicator/internal.h +++ b/crypto/fipsmodule/service_indicator/internal.h @@ -53,6 +53,7 @@ void PBKDF2_verify_service_indicator(const EVP_MD *evp_md, size_t password_len, void SSHKDF_verify_service_indicator(const EVP_MD *evp_md); void TLSKDF_verify_service_indicator(const EVP_MD *dgst, const char *label, size_t label_len); +void KBKDF_ctr_hmac_verify_service_indicator(const EVP_MD *dgst); #else @@ -116,6 +117,8 @@ OPENSSL_INLINE void TLSKDF_verify_service_indicator( OPENSSL_UNUSED const char *label, OPENSSL_UNUSED size_t label_len) {} +OPENSSL_INLINE void KBKDF_ctr_hmac_verify_service_indicator(OPENSSL_UNUSED const EVP_MD *dgst); + #endif // AWSLC_FIPS // is_fips_build is similar to |FIPS_mode| but returns 1 including in the case diff --git a/crypto/fipsmodule/service_indicator/service_indicator.c b/crypto/fipsmodule/service_indicator/service_indicator.c index 72d213808c..54d2a7638c 100644 --- a/crypto/fipsmodule/service_indicator/service_indicator.c +++ b/crypto/fipsmodule/service_indicator/service_indicator.c @@ -7,9 +7,7 @@ #include #include "internal.h" -const char* awslc_version_string(void) { - return AWSLC_VERSION_STRING; -} +const char *awslc_version_string(void) { return AWSLC_VERSION_STRING; } int is_fips_build(void) { #if defined(AWSLC_FIPS) @@ -42,9 +40,9 @@ struct fips_service_indicator_state { // FIPS 140-3 requires that the module should provide the service indicator // for approved services irrespective of whether the user queries it or not. // Hence, it is lazily initialized in any call to an approved service. -static struct fips_service_indicator_state * service_indicator_get(void) { - struct fips_service_indicator_state *indicator = CRYPTO_get_thread_local( - AWSLC_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE); +static struct fips_service_indicator_state *service_indicator_get(void) { + struct fips_service_indicator_state *indicator = + CRYPTO_get_thread_local(AWSLC_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE); if (indicator == NULL) { indicator = malloc(sizeof(struct fips_service_indicator_state)); @@ -56,8 +54,7 @@ static struct fips_service_indicator_state * service_indicator_get(void) { indicator->counter = 0; if (!CRYPTO_set_thread_local( - AWSLC_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE, indicator, - free)) { + AWSLC_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE, indicator, free)) { OPENSSL_PUT_ERROR(CRYPTO, ERR_R_INTERNAL_ERROR); return NULL; } @@ -214,7 +211,8 @@ static int is_md_fips_approved_for_verifying(int md_type, int pkey_type) { static void evp_md_ctx_verify_service_indicator(const EVP_MD_CTX *ctx, int rsa_1024_ok, - int (*md_ok)(int md_type, int pkey_type)) { + int (*md_ok)(int md_type, + int pkey_type)) { if (EVP_MD_CTX_md(ctx) == NULL) { // Signature schemes without a prehash are currently never FIPS approved. goto err; @@ -272,7 +270,7 @@ static void evp_md_ctx_verify_service_indicator(const EVP_MD_CTX *ctx, } } - err: +err: // Ensure that junk errors aren't left on the queue. ERR_clear_error(); } @@ -292,7 +290,7 @@ void ECDH_verify_service_indicator(const EC_KEY *ec_key) { } void EVP_PKEY_keygen_verify_service_indicator(const EVP_PKEY *pkey) { - if (pkey->type == EVP_PKEY_RSA || pkey->type== EVP_PKEY_RSA_PSS) { + if (pkey->type == EVP_PKEY_RSA || pkey->type == EVP_PKEY_RSA_PSS) { // 2048, 3072 and 4096 bit keys are approved for RSA key generation. // EVP_PKEY_size returns the size of the key in bytes. // Note: |EVP_PKEY_size| returns the length in bytes. @@ -346,7 +344,7 @@ void EVP_DigestSign_verify_service_indicator(const EVP_MD_CTX *ctx) { } void HMAC_verify_service_indicator(const EVP_MD *evp_md) { - switch (evp_md->type){ + switch (evp_md->type) { case NID_sha1: case NID_sha224: case NID_sha256: @@ -361,8 +359,8 @@ void HMAC_verify_service_indicator(const EVP_MD *evp_md) { } } -void HKDF_verify_service_indicator(const EVP_MD *evp_md, - const uint8_t *salt, size_t salt_len, size_t info_len) { +void HKDF_verify_service_indicator(const EVP_MD *evp_md, const uint8_t *salt, + size_t salt_len, size_t info_len) { // HKDF with SHA1, SHA224, SHA256, SHA384, and SHA512 are approved. // // FIPS 140 parameter requirements, per NIST SP 800-108 Rev. 1: @@ -412,7 +410,7 @@ void HKDFExpand_verify_service_indicator(const EVP_MD *evp_md) { } } void PBKDF2_verify_service_indicator(const EVP_MD *evp_md, size_t password_len, - size_t salt_len, unsigned iterations) { + size_t salt_len, unsigned iterations) { // PBKDF with SHA1, SHA224, SHA256, SHA384, and SHA512 are approved. // // FIPS 140 parameter requirements, per NIST SP800-132: @@ -456,7 +454,7 @@ void SSHKDF_verify_service_indicator(const EVP_MD *evp_md) { FIPS_service_indicator_update_state(); break; default: - break; + break; } } @@ -464,7 +462,7 @@ void TLSKDF_verify_service_indicator(const EVP_MD *dgst, const char *label, size_t label_len) { // HMAC-MD5/HMAC-SHA1 (both used concurrently) is approved for use in the KDF // in TLS 1.0/1.1. - if(dgst->type == NID_md5_sha1) { + if (dgst->type == NID_md5_sha1) { FIPS_service_indicator_update_state(); return; } @@ -479,7 +477,7 @@ void TLSKDF_verify_service_indicator(const EVP_MD *dgst, const char *label, if (label_len >= TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE && memcmp(label, TLS_MD_EXTENDED_MASTER_SECRET_CONST, TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE) == 0) { - FIPS_service_indicator_update_state(); + FIPS_service_indicator_update_state(); } break; default: @@ -487,6 +485,22 @@ void TLSKDF_verify_service_indicator(const EVP_MD *dgst, const char *label, } } +void KBKDF_ctr_hmac_verify_service_indicator(const EVP_MD *dgst) { + switch (dgst->type) { + case NID_sha1: + case NID_sha224: + case NID_sha256: + case NID_sha384: + case NID_sha512: + case NID_sha512_224: + case NID_sha512_256: + FIPS_service_indicator_update_state(); + break; + default: + break; + } +} + #else uint64_t FIPS_service_indicator_before_call(void) { return 0; } @@ -498,4 +512,4 @@ uint64_t FIPS_service_indicator_after_call(void) { return 1; } -#endif // AWSLC_FIPS +#endif // AWSLC_FIPS From 0984388a3b9621cbac7036730fe093bbf883ef49 Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Fri, 23 Aug 2024 21:01:12 +0000 Subject: [PATCH 2/3] Add KBKDF_ctr_hmac FIPS service indicator --- .../fipsmodule/service_indicator/internal.h | 2 +- .../service_indicator_test.cc | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/crypto/fipsmodule/service_indicator/internal.h b/crypto/fipsmodule/service_indicator/internal.h index 69f48f6c3a..cec9156778 100644 --- a/crypto/fipsmodule/service_indicator/internal.h +++ b/crypto/fipsmodule/service_indicator/internal.h @@ -117,7 +117,7 @@ OPENSSL_INLINE void TLSKDF_verify_service_indicator( OPENSSL_UNUSED const char *label, OPENSSL_UNUSED size_t label_len) {} -OPENSSL_INLINE void KBKDF_ctr_hmac_verify_service_indicator(OPENSSL_UNUSED const EVP_MD *dgst); +OPENSSL_INLINE void KBKDF_ctr_hmac_verify_service_indicator(OPENSSL_UNUSED const EVP_MD *dgst) {} #endif // AWSLC_FIPS diff --git a/crypto/fipsmodule/service_indicator/service_indicator_test.cc b/crypto/fipsmodule/service_indicator/service_indicator_test.cc index f600b8fc0d..94f60ffaa7 100644 --- a/crypto/fipsmodule/service_indicator/service_indicator_test.cc +++ b/crypto/fipsmodule/service_indicator/service_indicator_test.cc @@ -4317,6 +4317,65 @@ TEST(ServiceIndicatorTest, DRBG) { EXPECT_EQ(approved, AWSLC_APPROVED); } +static const struct KBKDFCtrHmacTestVector { + const EVP_MD *(*md)(); + const FIPSStatus expectation; +} kKBKDFCtrHmacTestVectors[] = {{ + &EVP_sha1, + AWSLC_APPROVED, + }, + { + &EVP_sha224, + AWSLC_APPROVED, + }, + { + &EVP_sha256, + AWSLC_APPROVED, + }, + { + &EVP_sha384, + AWSLC_APPROVED, + }, + { + &EVP_sha512, + AWSLC_APPROVED, + }, + { + &EVP_sha512_224, + AWSLC_APPROVED, + }, + { + &EVP_sha512_256, + AWSLC_APPROVED, + }, + { + &EVP_md5, + AWSLC_NOT_APPROVED, + }}; + +class KBKDFCtrHmacIndicatorTest : public TestWithNoErrors {}; + +INSTANTIATE_TEST_SUITE_P(All, KBKDFCtrHmacIndicatorTest, + testing::ValuesIn(kKBKDFCtrHmacTestVectors)); + +TEST_P(KBKDFCtrHmacIndicatorTest, KBKDF) { + const KBKDFCtrHmacTestVector &vector = GetParam(); + + const uint8_t secret[20] = {'A', 'W', 'S', '-', 'L', 'C', ' ', 'K', 'B', 'K', + 'D', 'F', '-', 'C', 'T', 'R', ' ', 'K', 'E', 'Y'}; + const uint8_t info[16] = {'A', 'W', 'S', '-', 'L', 'C', ' ', 'K', + 'B', 'K', 'D', 'F', '-', 'C', 'T', 'R'}; + uint8_t output[16] = {0}; + + FIPSStatus approved = AWSLC_NOT_APPROVED; + + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(KBKDF_ctr_hmac( + &output[0], sizeof(output), vector.md(), &secret[0], + sizeof(secret), &info[0], sizeof(info)))); + ASSERT_EQ(vector.expectation, approved); +} + // Verifies that the awslc_version_string is as expected. // Since this is running in FIPS mode it should end in FIPS // Update this when the AWS-LC version number is modified From c1504db7b69c5352cc728bb105629fb1be822497 Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Tue, 27 Aug 2024 20:18:51 +0000 Subject: [PATCH 3/3] Add indicator documentation --- crypto/fipsmodule/service_indicator/service_indicator.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crypto/fipsmodule/service_indicator/service_indicator.c b/crypto/fipsmodule/service_indicator/service_indicator.c index 54d2a7638c..e523244cc8 100644 --- a/crypto/fipsmodule/service_indicator/service_indicator.c +++ b/crypto/fipsmodule/service_indicator/service_indicator.c @@ -485,6 +485,14 @@ void TLSKDF_verify_service_indicator(const EVP_MD *dgst, const char *label, } } +// "For key derivation, this Recommendation approves the use of the keyed-Hash Message +// Authentication Code (HMAC) specified in FIPS 198-1". + +// * FIPS 198-1 references FIPS 180-3 which covers the SHA-1 and SHA-2* family of algorithms +// * NIST also provides ACVP vectors for SHA3-* family of algorithms but our HMAC does not support this +// +// Sourced from NIST SP 800-108r1-upd1 Section 3: Pseudorandom Function (PRF) +// https://doi.org/10.6028/NIST.SP.800-108r1-upd1 void KBKDF_ctr_hmac_verify_service_indicator(const EVP_MD *dgst) { switch (dgst->type) { case NID_sha1: