Skip to content

Commit

Permalink
EVP_PKEY_CTX_ctrl_str w/ RSA
Browse files Browse the repository at this point in the history
  • Loading branch information
justsmth committed Sep 11, 2024
1 parent 9ad4cad commit 72144b5
Show file tree
Hide file tree
Showing 3 changed files with 287 additions and 3 deletions.
1 change: 1 addition & 0 deletions crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,7 @@ if(BUILD_TESTING)
fipsmodule/ec/ec_test.cc
fipsmodule/ec/p256-nistz_test.cc
fipsmodule/ecdsa/ecdsa_test.cc
fipsmodule/evp/evp_ctx_test.cc
fipsmodule/kdf/kdf_test.cc
fipsmodule/md5/md5_test.cc
fipsmodule/modes/gcm_test.cc
Expand Down
179 changes: 179 additions & 0 deletions crypto/fipsmodule/evp/evp_ctx_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

#include "internal.h"

#include <gtest/gtest.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>

#include "../../internal.h"
#include "internal.h"

class EvpPkeyCtxCtrlStrTest : public ::testing::Test {
protected:
void SetUp() override {}

void TearDown() override {}
};

static bssl::UniquePtr<EVP_PKEY_CTX> gen_RSA() {
EVP_PKEY *raw = nullptr;
bssl::UniquePtr<EVP_PKEY_CTX> keygen_ctx(
EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr));
if (!EVP_PKEY_keygen_init(keygen_ctx.get()) ||
!EVP_PKEY_CTX_set_rsa_keygen_bits(keygen_ctx.get(), 2048) ||
!EVP_PKEY_keygen(keygen_ctx.get(), &raw)) {
return nullptr;
}
return bssl::UniquePtr<EVP_PKEY_CTX>(EVP_PKEY_CTX_new(raw, nullptr));
}

TEST_F(EvpPkeyCtxCtrlStrTest, RsaMissingValue) {
// Create a EVP_PKEY_CTX with a newly generated RSA key
bssl::UniquePtr<EVP_PKEY_CTX> ctx = gen_RSA();
ASSERT_TRUE(ctx);
EXPECT_FALSE(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_padding_mode", nullptr));
unsigned long err = ERR_get_error();
EXPECT_EQ(ERR_GET_LIB(err), ERR_LIB_EVP);
EXPECT_EQ(ERR_GET_REASON(err), RSA_R_VALUE_MISSING);
}

TEST_F(EvpPkeyCtxCtrlStrTest, RsaPaddingModeValid) {
bssl::UniquePtr<EVP_PKEY_CTX> ctx = gen_RSA();
ASSERT_TRUE(ctx);

int padding = 0;

// Padding for sign
ASSERT_TRUE(EVP_PKEY_sign_init(ctx.get()));

EXPECT_TRUE(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_padding_mode", "pkcs1"));
EXPECT_TRUE(EVP_PKEY_CTX_get_rsa_padding(ctx.get(), &padding));
EXPECT_EQ(padding, RSA_PKCS1_PADDING);

EXPECT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_padding_mode", "none"), 1);
EXPECT_TRUE(EVP_PKEY_CTX_get_rsa_padding(ctx.get(), &padding));
EXPECT_EQ(padding, RSA_NO_PADDING);

EXPECT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_padding_mode", "pss"), 1);
EXPECT_TRUE(EVP_PKEY_CTX_get_rsa_padding(ctx.get(), &padding));
EXPECT_EQ(padding, RSA_PKCS1_PSS_PADDING);

// Padding for encrypt
ASSERT_TRUE(EVP_PKEY_encrypt_init(ctx.get()));

EXPECT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_padding_mode", "oaep"), 1);
EXPECT_TRUE(EVP_PKEY_CTX_get_rsa_padding(ctx.get(), &padding));
EXPECT_EQ(padding, RSA_PKCS1_OAEP_PADDING);

EXPECT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_padding_mode", "oeap"), 1);
EXPECT_TRUE(EVP_PKEY_CTX_get_rsa_padding(ctx.get(), &padding));
EXPECT_EQ(padding, RSA_PKCS1_OAEP_PADDING);

EXPECT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_padding_mode", "nonsense"),
-2);
}

TEST_F(EvpPkeyCtxCtrlStrTest, RsaPssSaltlen) {
// Create a EVP_PKEY_CTX with a newly generated RSA key
bssl::UniquePtr<EVP_PKEY_CTX> ctx = gen_RSA();
ASSERT_TRUE(ctx);

ASSERT_TRUE(EVP_PKEY_sign_init(ctx.get()));
EXPECT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_padding_mode", "pss"), 1);
EXPECT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_pss_saltlen", "128"), 1);

int saltlen = 0;
EXPECT_EQ(EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx.get(), &saltlen), 1);
EXPECT_EQ(saltlen, 128);

EXPECT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_pss_saltlen", "digest"), 1);
EXPECT_EQ(EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx.get(), &saltlen), 1);
EXPECT_EQ(saltlen, -1);

EXPECT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_pss_saltlen", "-3"), -2);
}

TEST_F(EvpPkeyCtxCtrlStrTest, RsaKeygenBits) {
// Create a EVP_PKEY_CTX with a newly generated RSA key
EVP_PKEY *raw = nullptr;
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr));
ASSERT_TRUE(ctx);
ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_keygen_bits", "2048"), 1);
ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_keygen_bits", "-3"), -2);
ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));
bssl::UniquePtr<EVP_PKEY> pkey(raw);
ASSERT_TRUE(pkey);

ASSERT_EQ(EVP_PKEY_bits(pkey.get()), 2048);
}

TEST_F(EvpPkeyCtxCtrlStrTest, RsaKeygenPubexp) {
// Create a EVP_PKEY_CTX with a newly generated RSA key
EVP_PKEY *raw = nullptr;
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr));
ASSERT_TRUE(ctx);
ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_keygen_pubexp", "729"), 1);
ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_keygen_pubexp", "gg"), -2);
ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));
bssl::UniquePtr<EVP_PKEY> pkey(raw);
ASSERT_TRUE(pkey);

bssl::UniquePtr<RSA> rsa_key(EVP_PKEY_get1_RSA(pkey.get()));
ASSERT_TRUE(rsa_key);
const BIGNUM *const_pe_bn = RSA_get0_e(rsa_key.get());
ASSERT_TRUE(const_pe_bn != nullptr);

const uint64_t expected_pe = 729;
uint64_t pe_u64;
ASSERT_TRUE(BN_get_u64(const_pe_bn, &pe_u64));
EXPECT_EQ(pe_u64, expected_pe);
}

TEST_F(EvpPkeyCtxCtrlStrTest, RsaMgf1Md) {
bssl::UniquePtr<EVP_PKEY_CTX> ctx = gen_RSA();
ASSERT_TRUE(ctx);

ASSERT_TRUE(EVP_PKEY_sign_init(ctx.get()));
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PSS_PADDING));
ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_mgf1_md", "sha256"), 1);

const EVP_MD *out_md;
ASSERT_TRUE(EVP_PKEY_CTX_get_rsa_mgf1_md(ctx.get(), &out_md));
ASSERT_STREQ(EVP_MD_name(out_md), "SHA256");
}

// rsa_oaep_md
TEST_F(EvpPkeyCtxCtrlStrTest, RsaOaepMd) {
bssl::UniquePtr<EVP_PKEY_CTX> ctx = gen_RSA();
ASSERT_TRUE(ctx);

ASSERT_TRUE(EVP_PKEY_encrypt_init(ctx.get()));
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING));
ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_oaep_md", "sha256"), 1);

const EVP_MD *out_md;
ASSERT_TRUE(EVP_PKEY_CTX_get_rsa_oaep_md(ctx.get(), &out_md));
ASSERT_STREQ(EVP_MD_name(out_md), "SHA256");
}

TEST_F(EvpPkeyCtxCtrlStrTest, RsaOaepLabel) {
bssl::UniquePtr<EVP_PKEY_CTX> ctx = gen_RSA();
ASSERT_TRUE(ctx);

ASSERT_TRUE(EVP_PKEY_encrypt_init(ctx.get()));
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING));
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_oaep_md(ctx.get(), EVP_sha256()));
ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_oaep_label", "aabb11"), 1);
ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_oaep_label", "gg"), -2);

const char expected_label[4] = "\xaa\xbb\x11";
const uint8_t *actual_label;
ASSERT_TRUE(EVP_PKEY_CTX_get0_rsa_oaep_label(ctx.get(), &actual_label));

ASSERT_TRUE(OPENSSL_memcmp(actual_label, expected_label, 3) == 0);
}
110 changes: 107 additions & 3 deletions crypto/fipsmodule/evp/p_rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,110 @@ static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
return ret;
}

static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value) {
if (value == NULL) {
OPENSSL_PUT_ERROR(EVP, RSA_R_VALUE_MISSING);
return 0;
}
if (strcmp(type, "rsa_padding_mode") == 0) {
// "sslv23" and "x931" are not supported
int pm;

if (strcmp(value, "pkcs1") == 0) {
pm = RSA_PKCS1_PADDING;
} else if (strcmp(value, "none") == 0) {
pm = RSA_NO_PADDING;
// OpenSSL also supports the typo.
} else if (strcmp(value, "oeap") == 0) {
pm = RSA_PKCS1_OAEP_PADDING;
} else if (strcmp(value, "oaep") == 0) {
pm = RSA_PKCS1_OAEP_PADDING;
} else if (strcmp(value, "pss") == 0) {
pm = RSA_PKCS1_PSS_PADDING;
} else {
OPENSSL_PUT_ERROR(EVP, RSA_R_UNKNOWN_PADDING_TYPE);
return -2;
}
return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
}

if (strcmp(type, "rsa_pss_saltlen") == 0) {
// "max" and "auto" are not supported
long saltlen;

if (!strcmp(value, "digest")) {
saltlen = RSA_PSS_SALTLEN_DIGEST;
} else {
char* str_end;
saltlen = strtol(value, &str_end, 10);
if(str_end == value || saltlen < 0 || saltlen > INT_MAX) {
OPENSSL_PUT_ERROR(EVP, RSA_R_INTERNAL_ERROR);
return -2;
}
}
return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, (int)saltlen);
}

if (strcmp(type, "rsa_keygen_bits") == 0) {
char* str_end;
long nbits = strtol(value, &str_end, 10);
if (str_end == value || nbits <= 0 || nbits > INT_MAX) {
OPENSSL_PUT_ERROR(EVP, RSA_R_INTERNAL_ERROR);
return -2;
}
return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, (int)nbits);
}

if (strcmp(type, "rsa_keygen_pubexp") == 0) {
int ret;

BIGNUM *pubexp = NULL;
if (!BN_asc2bn(&pubexp, value)) {
return -2;
}
ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp);
if (ret <= 0) {
BN_free(pubexp);
}
return ret;
}

if (strcmp(type, "rsa_mgf1_md") == 0) {
OPENSSL_BEGIN_ALLOW_DEPRECATED
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_RSA_MGF1_MD, value);
OPENSSL_END_ALLOW_DEPRECATED
}

// rsa_pss_keygen_XXX options are not supported

if (strcmp(type, "rsa_oaep_md") == 0) {
OPENSSL_BEGIN_ALLOW_DEPRECATED
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_RSA_OAEP_MD, value);
OPENSSL_END_ALLOW_DEPRECATED
}
if (strcmp(type, "rsa_oaep_label") == 0) {
size_t lablen;
int ret;
uint8_t *lab;

lab = OPENSSL_hexstr2buf(value, &lablen);
if (lab == NULL) {
return -2;
}

ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen);
if (ret <= 0) {
OPENSSL_free(lab);
}
return ret;
}

return -2;
}

DEFINE_METHOD_FUNCTION(EVP_PKEY_METHOD, EVP_PKEY_rsa_pkey_meth) {
out->pkey_id = EVP_PKEY_RSA;
out->init = pkey_rsa_init;
Expand All @@ -703,7 +807,7 @@ DEFINE_METHOD_FUNCTION(EVP_PKEY_METHOD, EVP_PKEY_rsa_pkey_meth) {
out->derive = NULL;
out->paramgen = NULL;
out->ctrl = pkey_rsa_ctrl;
out->ctrl_str = NULL;
out->ctrl_str = pkey_rsa_ctrl_str;
}

DEFINE_METHOD_FUNCTION(EVP_PKEY_METHOD, EVP_PKEY_rsa_pss_pkey_meth) {
Expand All @@ -724,7 +828,7 @@ DEFINE_METHOD_FUNCTION(EVP_PKEY_METHOD, EVP_PKEY_rsa_pss_pkey_meth) {
out->derive = NULL;
out->paramgen = NULL;
out->ctrl = pkey_rsa_ctrl;
out->ctrl_str = NULL;
out->ctrl_str = pkey_rsa_ctrl_str;
}

int EVP_RSA_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2) {
Expand Down Expand Up @@ -799,7 +903,7 @@ int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {

int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
return EVP_RSA_PKEY_CTX_ctrl(ctx,
EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_OP_KEYGEN | EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void*) out_md);
}

Expand Down

0 comments on commit 72144b5

Please sign in to comment.