Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add KDA OneStep (SSKDF_digest and SSKDF_hmac) to FIPS indicator #1793

Merged
merged 3 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions crypto/fipsmodule/kdf/sskdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,15 @@ static int SSKDF(const sskdf_variant *variant, sskdf_variant_ctx *ctx,
int SSKDF_digest(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 |EVP_DigestFinal| services updating
// the indicator state, so we lock the state here.
FIPS_service_indicator_lock_state();

sskdf_variant_ctx ctx = {0};
int ret = 0;

if (!sskdf_variant_digest_ctx_init(&ctx, digest)) {
FIPS_service_indicator_unlock_state();
return 0;
}

Expand All @@ -305,16 +310,25 @@ int SSKDF_digest(uint8_t *out_key, size_t out_len, const EVP_MD *digest,

end:
sskdf_variant_digest_ctx_cleanup(&ctx);
FIPS_service_indicator_unlock_state();
if (ret) {
SSKDF_digest_verify_service_indicator(digest);
}
return ret;
}

int SSKDF_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, const uint8_t *salt, size_t salt_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();

sskdf_variant_ctx ctx = {0};
int ret = 0;

if (!sskdf_variant_hmac_ctx_init(&ctx, digest, salt, salt_len)) {
FIPS_service_indicator_unlock_state();
return 0;
}

Expand All @@ -327,5 +341,9 @@ int SSKDF_hmac(uint8_t *out_key, size_t out_len, const EVP_MD *digest,

end:
sskdf_variant_hmac_ctx_cleanup(&ctx);
FIPS_service_indicator_unlock_state();
if(ret) {
SSKDF_hmac_verify_service_indicator(digest);
}
return ret;
}
8 changes: 8 additions & 0 deletions crypto/fipsmodule/service_indicator/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ 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 SSKDF_digest_verify_service_indicator(const EVP_MD *dgst);
void SSKDF_hmac_verify_service_indicator(const EVP_MD *dgst);
void KBKDF_ctr_hmac_verify_service_indicator(const EVP_MD *dgst);

#else
Expand Down Expand Up @@ -117,6 +119,12 @@ OPENSSL_INLINE void TLSKDF_verify_service_indicator(
OPENSSL_UNUSED const char *label,
OPENSSL_UNUSED size_t label_len) {}

OPENSSL_INLINE void SSKDF_digest_verify_service_indicator(
OPENSSL_UNUSED const EVP_MD *dgst) {}

OPENSSL_INLINE void SSKDF_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
Expand Down
54 changes: 54 additions & 0 deletions crypto/fipsmodule/service_indicator/service_indicator.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,60 @@ void TLSKDF_verify_service_indicator(const EVP_MD *dgst, const char *label,
}
}

// "Whenever a hash function is employed (including as the primitive used by HMAC), an
// approved hash function shall be used. FIPS 180 and FIPS 202 specify approved hash
// functions"
//
// * FIPS 180 covers the SHA-1 and SHA-2* family of algorithms
// * FIPS 202 covers the SHA3-* family of algorithms
//
// Sourced from NIST.SP.800-56Cr2 Section 7: Selecting Hash Functions and MAC Algorithms
// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdf
void SSKDF_digest_verify_service_indicator(const EVP_MD *dgst) {
skmcgrail marked this conversation as resolved.
Show resolved Hide resolved
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:
case NID_sha3_224:
case NID_sha3_256:
case NID_sha3_384:
case NID_sha3_512:
FIPS_service_indicator_update_state();
break;
default:
break;
}
}

// "Whenever a hash function is employed (including as the primitive used by HMAC), an
// approved hash function shall be used. FIPS 180 and FIPS 202 specify approved hash
// functions"
//
// * FIPS 180 covers the SHA-1 and SHA-2* family of algorithms
// * FIPS 202 covers the SHA3-* family of algorithms (Note: AWS-LC does not currently support SHA-3 with HMAC)
WillChilds-Klein marked this conversation as resolved.
Show resolved Hide resolved
//
// Sourced from NIST.SP.800-56Cr2 Section 7: Selecting Hash Functions and MAC Algorithms
// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdf
void SSKDF_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;
}
}

// "For key derivation, this Recommendation approves the use of the keyed-Hash Message
// Authentication Code (HMAC) specified in FIPS 198-1".

Expand Down
141 changes: 141 additions & 0 deletions crypto/fipsmodule/service_indicator/service_indicator_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4317,6 +4317,147 @@ TEST(ServiceIndicatorTest, DRBG) {
EXPECT_EQ(approved, AWSLC_APPROVED);
}

static const struct SSKDFDigestTestVector {
const EVP_MD *(*md)();
const FIPSStatus expectation;
} kSSKDFDigestTestVectors[] = {{
&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_sha3_224,
AWSLC_APPROVED,
},
{
&EVP_sha3_256,
AWSLC_APPROVED,
},
{
&EVP_sha3_384,
AWSLC_APPROVED,
},
{
&EVP_sha3_512,
AWSLC_APPROVED,
},
{
&EVP_md5,
AWSLC_NOT_APPROVED,
}};

class SSKDFDigestIndicatorTest : public TestWithNoErrors<SSKDFDigestTestVector> {};

INSTANTIATE_TEST_SUITE_P(All, SSKDFDigestIndicatorTest,
testing::ValuesIn(kSSKDFDigestTestVectors));


TEST_P(SSKDFDigestIndicatorTest, SSKDF) {
const SSKDFDigestTestVector &vector = GetParam();

const uint8_t secret[23] = {'A', 'W', 'S', '-', 'L', 'C', ' ', 'S',
'S', 'K', 'D', 'F', '-', 'D', 'I', 'G',
'E', 'S', 'T', ' ', 'K', 'E', 'Y'};
const uint8_t info[19] = {'A', 'W', 'S', '-', 'L', 'C', ' ', 'S', 'S', 'K',
'D', 'F', '-', 'D', 'I', 'G', 'E', 'S', 'T'};
uint8_t output[16] = {0};

FIPSStatus approved = AWSLC_NOT_APPROVED;

CALL_SERVICE_AND_CHECK_APPROVED(
approved, ASSERT_TRUE(SSKDF_digest(
&output[0], sizeof(output), vector.md(), &secret[0],
sizeof(secret), &info[0], sizeof(info))));
ASSERT_EQ(vector.expectation, approved);
}

static const struct SSKDFHmacTestVector {
const EVP_MD *(*md)();
const FIPSStatus expectation;
} kSSKDFHmacTestVectors[] = {{
&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 SSKDFHmacIndicatorTest : public TestWithNoErrors<SSKDFHmacTestVector> {};

INSTANTIATE_TEST_SUITE_P(All, SSKDFHmacIndicatorTest,
testing::ValuesIn(kSSKDFHmacTestVectors));


TEST_P(SSKDFHmacIndicatorTest, SSKDF) {
const SSKDFHmacTestVector &vector = GetParam();

const uint8_t secret[21] = {'A', 'W', 'S', '-', 'L', 'C', ' ',
'S', 'S', 'K', 'D', 'F', '-', 'H',
'M', 'A', 'C', ' ', 'K', 'E', 'Y'};
const uint8_t info[17] = {'A', 'W', 'S', '-', 'L', 'C', ' ', 'S', 'S', 'K',
'D', 'F', '-', 'H', 'M', 'A', 'C'};
const uint8_t salt[22] = {'A', 'W', 'S', '-', 'L', 'C', ' ', 'S',
'S', 'K', 'D', 'F', '-', 'H', 'M', 'A',
'C', ' ', 'S', 'A', 'L', 'T'};
uint8_t output[16] = {0};

FIPSStatus approved = AWSLC_NOT_APPROVED;

CALL_SERVICE_AND_CHECK_APPROVED(
approved, ASSERT_TRUE(SSKDF_hmac(&output[0], sizeof(output), vector.md(),
&secret[0], sizeof(secret), &info[0],
sizeof(info), &salt[0], sizeof(salt))));
ASSERT_EQ(vector.expectation, approved);
}

static const struct KBKDFCtrHmacTestVector {
const EVP_MD *(*md)();
const FIPSStatus expectation;
Expand Down
Loading