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

Additional tests for failure modes for KEM API #1048

Merged
merged 6 commits into from
Jun 21, 2023
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
67 changes: 66 additions & 1 deletion crypto/evp_extra/evp_extra_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2121,6 +2121,37 @@ TEST_P(PerKEMTest, KeyGeneration) {
ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), sk_raw.data(), &sk_len));
EXPECT_EQ(pk_len, GetParam().public_key_len);
EXPECT_EQ(sk_len, GetParam().secret_key_len);

// ---- 4. Test failure modes for EVP_PKEY_CTX_kem_set_params. ----
// ctx is NULL.
ASSERT_FALSE(EVP_PKEY_CTX_kem_set_params(nullptr, kem_nid));
uint32_t err = ERR_get_error();
Comment on lines +2124 to +2128
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Should this start with a call to ERR_clear_error to ensure that the error retrieved is from the tested function.

EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(ERR_R_PASSED_NULL_PARAMETER, ERR_GET_REASON(err));

// ctx->data is NULL.
void *tmp = ctx.get()->data;
ctx.get()->data = nullptr;
ASSERT_FALSE(EVP_PKEY_CTX_kem_set_params(ctx.get(), kem_nid));
err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(ERR_R_PASSED_NULL_PARAMETER, ERR_GET_REASON(err));
ctx.get()->data = tmp;

// ctx->pkey is not NULL.
ASSERT_FALSE(EVP_PKEY_CTX_kem_set_params(ctx.get(), kem_nid));
err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_INVALID_OPERATION, ERR_GET_REASON(err));

// kem_nid is not a KEM.
tmp = (void*) ctx.get()->pkey;
ctx.get()->pkey = nullptr;
ASSERT_FALSE(EVP_PKEY_CTX_kem_set_params(ctx.get(), NID_secp521r1));
err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_UNSUPPORTED_ALGORITHM, ERR_GET_REASON(err));
ctx.get()->pkey = (EVP_PKEY*) tmp;
andrewhop marked this conversation as resolved.
Show resolved Hide resolved
}

// Helper function that:
Expand Down Expand Up @@ -2160,7 +2191,7 @@ TEST_P(PerKEMTest, Encapsulation) {
ASSERT_TRUE(ctx);

// ---- 2. Test basic encapsulation flow ----
// Alloc ciphertext and shared secret with the expected lenghts.
// Alloc ciphertext and shared secret with the expected lengths.
size_t ct_len = GetParam().ciphertext_len;
size_t ss_len = GetParam().shared_secret_len;
std::vector<uint8_t> ct(ct_len);
Expand Down Expand Up @@ -2221,6 +2252,17 @@ TEST_P(PerKEMTest, Encapsulation) {
ss_len = GetParam().shared_secret_len + 1;
ASSERT_TRUE(EVP_PKEY_encapsulate(ctx.get(), ct.data(), &ct_len, ss.data(), &ss_len));
EXPECT_EQ(ss_len, GetParam().shared_secret_len);

// ---- 5. Test more failure modes for EVP_PKEY_encapsulate. ----
ASSERT_FALSE(EVP_PKEY_encapsulate(nullptr, ct.data(), &ct_len, ss.data(), &ss_len));

void *tmp = (void*) ctx.get()->pmeth;
ctx.get()->pmeth = nullptr;
ASSERT_FALSE(EVP_PKEY_encapsulate(ctx.get(), ct.data(), &ct_len, ss.data(), &ss_len));
err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE, ERR_GET_REASON(err));
ctx.get()->pmeth = (EVP_PKEY_METHOD*) tmp;
andrewhop marked this conversation as resolved.
Show resolved Hide resolved
}

TEST_P(PerKEMTest, Decapsulation) {
Expand Down Expand Up @@ -2267,6 +2309,17 @@ TEST_P(PerKEMTest, Decapsulation) {
ss_len = GetParam().shared_secret_len + 1;
ASSERT_TRUE(EVP_PKEY_decapsulate(ctx.get(), nullptr, &ss_len, ct.data(), ct_len));
EXPECT_EQ(ss_len, GetParam().shared_secret_len);

// ---- 5. Test more failure modes for EVP_PKEY_encapsulate. ----
ASSERT_FALSE(EVP_PKEY_decapsulate(nullptr, ss.data(), &ss_len, ct.data(), ct_len));

void *tmp = (void*) ctx.get()->pmeth;
ctx.get()->pmeth = nullptr;
ASSERT_FALSE(EVP_PKEY_decapsulate(ctx.get(), ss.data(), &ss_len, ct.data(), ct_len));
err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE, ERR_GET_REASON(err));
ctx.get()->pmeth = (EVP_PKEY_METHOD*) tmp;
}

TEST_P(PerKEMTest, EndToEnd) {
Expand Down Expand Up @@ -2427,6 +2480,18 @@ TEST_P(PerKEMTest, RawKeyOperations) {
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE, ERR_GET_REASON(err));

void *tmp = (void*) pkey.get()->ameth;
pkey.get()->ameth = nullptr;
ASSERT_FALSE(EVP_PKEY_get_raw_public_key(pkey.get(), pk.data(), &pk_len));
err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE, ERR_GET_REASON(err));
andrewhop marked this conversation as resolved.
Show resolved Hide resolved
ASSERT_FALSE(EVP_PKEY_get_raw_private_key(pkey.get(), sk.data(), &sk_len));
err = ERR_get_error();
EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
EXPECT_EQ(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE, ERR_GET_REASON(err));
pkey.get()->ameth = (const EVP_PKEY_ASN1_METHOD*)(tmp);

// Invalid lengths.
pk_len = GetParam().public_key_len - 1;
ASSERT_FALSE(EVP_PKEY_get_raw_public_key(pkey.get(), pk.data(), &pk_len));
Expand Down
3 changes: 2 additions & 1 deletion crypto/evp_extra/p_kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,14 +203,15 @@ int EVP_PKEY_CTX_kem_set_params(EVP_PKEY_CTX *ctx, int nid) {
}

// It's not allowed to change context parameters if
// a PKEY is already associated with the contex.
// a PKEY is already associated with the context.
if (ctx->pkey != NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_OPERATION);
return 0;
}

const KEM *kem = KEM_find_kem_by_nid(nid);
if (kem == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}

Expand Down
10 changes: 4 additions & 6 deletions crypto/fipsmodule/evp/evp_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,9 +525,8 @@ int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **out_pkey) {
int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx,
uint8_t *ciphertext, size_t *ciphertext_len,
uint8_t *shared_secret, size_t *shared_secret_len) {
if (ctx == NULL ||
ctx->pmeth == NULL ||
ctx->pmeth->encapsulate == NULL) {
if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->encapsulate == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}

Expand All @@ -538,9 +537,8 @@ int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx,
int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx,
uint8_t *shared_secret, size_t *shared_secret_len,
uint8_t *ciphertext, size_t ciphertext_len) {
if (ctx == NULL ||
ctx->pmeth == NULL ||
ctx->pmeth->decapsulate == NULL) {
if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->decapsulate == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}

Expand Down