Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
justsmth committed Sep 11, 2024
1 parent a5a33f0 commit af79371
Show file tree
Hide file tree
Showing 3 changed files with 298 additions and 2 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
170 changes: 170 additions & 0 deletions crypto/fipsmodule/evp/evp_ctx_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

//
// Created by Smith, Justin on 9/10/24.
//

#include <iostream>

#include "internal.h"
using namespace std;

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

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

void TearDown() override {
}

};



static bssl::UniquePtr<EVP_PKEY_CTX> gen_RSA_inner(const int id) {
EVP_PKEY* raw = nullptr;
bssl::UniquePtr<EVP_PKEY_CTX> keygen_ctx(EVP_PKEY_CTX_new_id(id, 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));
}

static bssl::UniquePtr<EVP_PKEY_CTX> gen_RSA() {
return gen_RSA_inner(EVP_PKEY_RSA);
}

// static bssl::UniquePtr<EVP_PKEY_CTX> gen_RSA_PSS() {
// return gen_RSA_inner(EVP_PKEY_RSA_PSS);
// }

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);
}

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);
}

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_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));

ASSERT_EQ(EVP_PKEY_bits(raw), 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_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));

bssl::UniquePtr<RSA> rsa_key(EVP_PKEY_get1_RSA(raw));
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) {
// rsa_mgf1_md
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));
EXPECT_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));
EXPECT_STREQ(EVP_MD_name(out_md), "SHA256");
}

//rsa_pss_keygen_mgf1_md
TEST_F(EvpPkeyCtxCtrlStrTest, RsaPssKeygenMgf1Md) {
EVP_PKEY* raw = nullptr;
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA_PSS, nullptr));
ASSERT_TRUE(ctx);
ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));

EXPECT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_pss_keygen_mgf1_md", "sha256"), 1);

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

ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));
EVP_PKEY_free(raw);
}
129 changes: 127 additions & 2 deletions crypto/fipsmodule/evp/p_rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,131 @@ 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 {
saltlen = strtol(value, NULL, 10);
if(saltlen < 0 || saltlen > INT_MAX) {
OPENSSL_PUT_ERROR(EVP, RSA_R_INTERNAL_ERROR);
return 0;
}
}
return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, (int)saltlen);
}

if (strcmp(type, "rsa_keygen_bits") == 0) {
long nbits = strtol(value, NULL, 10);
if (nbits <= 0 || nbits > INT_MAX) {
OPENSSL_PUT_ERROR(EVP, RSA_R_INTERNAL_ERROR);
return 0;
}
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 0;
}
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
}

if (pkey_ctx_is_pss(ctx)) {
if (strcmp(type, "rsa_pss_keygen_mgf1_md") == 0) {
OPENSSL_BEGIN_ALLOW_DEPRECATED
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_RSA_MGF1_MD,
value);
OPENSSL_END_ALLOW_DEPRECATED
}

if (strcmp(type, "rsa_pss_keygen_md") == 0) {
OPENSSL_BEGIN_ALLOW_DEPRECATED
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_MD, value);
OPENSSL_END_ALLOW_DEPRECATED
}
if (strcmp(type, "rsa_pss_keygen_saltlen") == 0) {
long saltlen = strtol(value, NULL, 10);
if(saltlen < 0 || saltlen > INT_MAX) {
OPENSSL_PUT_ERROR(EVP, RSA_R_INTERNAL_ERROR);
return 0;
}

return EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, (int)saltlen);
}
}

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 0;
}

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 +828,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 +849,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

0 comments on commit af79371

Please sign in to comment.