Skip to content

Commit 3b33a00

Browse files
committed
ED25519 Service Indicator
1 parent 0f5d9c9 commit 3b33a00

File tree

3 files changed

+84
-3
lines changed

3 files changed

+84
-3
lines changed

crypto/fipsmodule/curve25519/curve25519.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ void ED25519_keypair(uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN],
112112
// description why this is useful.
113113
ED25519_keypair_from_seed(out_public_key, out_private_key, seed);
114114
OPENSSL_cleanse(seed, ED25519_SEED_LEN);
115+
116+
FIPS_service_indicator_update_state();
115117
}
116118

117119
int ED25519_sign(uint8_t out_sig[ED25519_SIGNATURE_LEN],
@@ -155,6 +157,8 @@ int ED25519_sign(uint8_t out_sig[ED25519_SIGNATURE_LEN],
155157

156158
// The signature is computed from the private key, but is public.
157159
CONSTTIME_DECLASSIFY(out_sig, 64);
160+
161+
FIPS_service_indicator_update_state();
158162
return 1;
159163
}
160164

@@ -212,8 +216,12 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
212216
#endif
213217

214218
// Comparison [S]B - [k]A' =? R_expected. Short-circuits if decoding failed.
215-
return (res == 1) &&
216-
CRYPTO_memcmp(R_computed_encoded, R_expected, sizeof(R_computed_encoded)) == 0;
219+
res = (res == 1) && CRYPTO_memcmp(R_computed_encoded, R_expected,
220+
sizeof(R_computed_encoded)) == 0;
221+
if(res) {
222+
FIPS_service_indicator_update_state();
223+
}
224+
return res;
217225
}
218226

219227

crypto/fipsmodule/service_indicator/service_indicator.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,14 @@ static void evp_md_ctx_verify_service_indicator(const EVP_MD_CTX *ctx,
222222
int (*md_ok)(int md_type,
223223
int pkey_type)) {
224224
if (EVP_MD_CTX_md(ctx) == NULL) {
225-
// Signature schemes without a prehash are currently never FIPS approved.
225+
if(ctx->pctx->pkey->type == EVP_PKEY_ED25519) {
226+
// FIPS 186-5:
227+
//. 7.6 EdDSA Signature Generation
228+
// 7.7 EdDSA Signature Verification
229+
FIPS_service_indicator_update_state();
230+
return;
231+
}
232+
// All other signature schemes without a prehash are currently never FIPS approved.
226233
goto err;
227234
}
228235

@@ -319,6 +326,8 @@ void EVP_PKEY_keygen_verify_service_indicator(const EVP_PKEY *pkey) {
319326
if (is_ec_fips_approved(curve_nid)) {
320327
FIPS_service_indicator_update_state();
321328
}
329+
} else if (pkey->type == EVP_PKEY_ED25519) {
330+
FIPS_service_indicator_update_state();
322331
}
323332
}
324333

crypto/fipsmodule/service_indicator/service_indicator_test.cc

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <openssl/cmac.h>
1212
#include <openssl/crypto.h>
1313
#include <openssl/ctrdrbg.h>
14+
#include <openssl/curve25519.h>
1415
#include <openssl/dh.h>
1516
#include <openssl/digest.h>
1617
#include <openssl/ec.h>
@@ -4557,6 +4558,69 @@ TEST_P(KBKDFCtrHmacIndicatorTest, KBKDF) {
45574558
ASSERT_EQ(vector.expectation, approved);
45584559
}
45594560

4561+
TEST(ServiceIndicatorTest, ED25519KeyGen) {
4562+
FIPSStatus approved = AWSLC_NOT_APPROVED;
4563+
uint8_t private_key[ED25519_PRIVATE_KEY_LEN] = {0};
4564+
uint8_t public_key[ED25519_PUBLIC_KEY_LEN] = {0};
4565+
CALL_SERVICE_AND_CHECK_APPROVED(approved,
4566+
ED25519_keypair(public_key, private_key));
4567+
ASSERT_EQ(AWSLC_APPROVED, approved);
4568+
4569+
approved = AWSLC_NOT_APPROVED;
4570+
4571+
bssl::UniquePtr<EVP_PKEY_CTX> ctx(
4572+
EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, nullptr));
4573+
EVP_PKEY *raw = nullptr;
4574+
bssl::UniquePtr<EVP_PKEY> pkey(raw);
4575+
ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
4576+
CALL_SERVICE_AND_CHECK_APPROVED(
4577+
approved, ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw)));
4578+
ASSERT_EQ(AWSLC_APPROVED, approved);
4579+
pkey.reset(raw);
4580+
}
4581+
4582+
TEST(ServiceIndicatorTest, ED25519SigGenVerify) {
4583+
const uint8_t MESSAGE[15] = {'E', 'D', '2', '5', '5', '1', '9', ' ',
4584+
'M', 'E', 'S', 'S', 'A', 'G', 'E'};
4585+
uint8_t private_key[ED25519_PRIVATE_KEY_LEN] = {0};
4586+
uint8_t public_key[ED25519_PUBLIC_KEY_LEN] = {0};
4587+
uint8_t signature[ED25519_SIGNATURE_LEN] = {0};
4588+
ED25519_keypair(public_key, private_key);
4589+
4590+
FIPSStatus approved = AWSLC_NOT_APPROVED;
4591+
CALL_SERVICE_AND_CHECK_APPROVED(
4592+
approved, ASSERT_TRUE(ED25519_sign(&signature[0], &MESSAGE[0],
4593+
sizeof(MESSAGE), private_key)));
4594+
ASSERT_EQ(AWSLC_APPROVED, approved);
4595+
4596+
approved = AWSLC_NOT_APPROVED;
4597+
CALL_SERVICE_AND_CHECK_APPROVED(
4598+
approved, ASSERT_TRUE(ED25519_verify(&MESSAGE[0], sizeof(MESSAGE),
4599+
signature, public_key)));
4600+
ASSERT_EQ(AWSLC_APPROVED, approved);
4601+
4602+
bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new_raw_private_key(
4603+
EVP_PKEY_ED25519, NULL, &private_key[0], ED25519_PRIVATE_KEY_SEED_LEN));
4604+
4605+
bssl::UniquePtr<EVP_MD_CTX> mdctx(EVP_MD_CTX_new());
4606+
ASSERT_TRUE(EVP_DigestSignInit(mdctx.get(), NULL, NULL, NULL, pkey.get()));
4607+
size_t sig_out_len = sizeof(signature);
4608+
CALL_SERVICE_AND_CHECK_APPROVED(
4609+
approved,
4610+
ASSERT_TRUE(EVP_DigestSign(mdctx.get(), &signature[0], &sig_out_len,
4611+
&MESSAGE[0], sizeof(MESSAGE))));
4612+
ASSERT_EQ(AWSLC_APPROVED, approved);
4613+
ASSERT_EQ(sizeof(signature), sig_out_len);
4614+
4615+
mdctx.reset(EVP_MD_CTX_new());
4616+
ASSERT_TRUE(EVP_DigestVerifyInit(mdctx.get(), NULL, NULL, NULL, pkey.get()));
4617+
CALL_SERVICE_AND_CHECK_APPROVED(
4618+
approved, ASSERT_TRUE(EVP_DigestVerify(mdctx.get(), &signature[0],
4619+
sizeof(signature), &MESSAGE[0],
4620+
sizeof(MESSAGE))));
4621+
ASSERT_EQ(AWSLC_APPROVED, approved);
4622+
}
4623+
45604624
// Verifies that the awslc_version_string is as expected.
45614625
// Since this is running in FIPS mode it should end in FIPS
45624626
// Update this when the AWS-LC version number is modified

0 commit comments

Comments
 (0)