diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index 8887df791e..0115800367 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -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 diff --git a/crypto/bn_extra/convert.c b/crypto/bn_extra/convert.c index 942a422467..1c775c4875 100644 --- a/crypto/bn_extra/convert.c +++ b/crypto/bn_extra/convert.c @@ -193,6 +193,11 @@ static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_ for (i = 0; want_char((unsigned char)in[i]) && i + neg < INT_MAX; i++) {} + if(i == 0) { + OPENSSL_PUT_ERROR(BN, BN_R_INVALID_INPUT); + return 0; + } + num = i + neg; if (outp == NULL) { return num; diff --git a/crypto/evp_extra/p_dh.c b/crypto/evp_extra/p_dh.c index a0e57d0ec6..2ae75f9293 100644 --- a/crypto/evp_extra/p_dh.c +++ b/crypto/evp_extra/p_dh.c @@ -7,6 +7,7 @@ * https://www.openssl.org/source/license.html */ +#include #include #include @@ -121,6 +122,29 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { } } +static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, + const char *value) { + // We don't support: + // * dh_paramgen_prime_len + // * dh_rfc5114 + // * dh_param + // * dh_paramgen_generator + // * dh_paramgen_subprime_len + // * dh_paramgen_type + + if (strcmp(type, "dh_pad") == 0) { + char* str_end = NULL; + long pad = strtol(value, &str_end, 10); + if(str_end == value || pad < 0 || pad > INT_MAX) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_OPERATION); + return 0; + } + return EVP_PKEY_CTX_set_dh_pad(ctx, pad); + } + return -2; +} + + const EVP_PKEY_METHOD dh_pkey_meth = { .pkey_id = EVP_PKEY_DH, .init = pkey_dh_init, @@ -129,7 +153,7 @@ const EVP_PKEY_METHOD dh_pkey_meth = { .keygen = pkey_dh_keygen, .derive = pkey_dh_derive, .ctrl = pkey_dh_ctrl, - .ctrl_str = NULL + .ctrl_str = pkey_dh_ctrl_str }; int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad) { diff --git a/crypto/fipsmodule/evp/evp_ctx_test.cc b/crypto/fipsmodule/evp/evp_ctx_test.cc new file mode 100644 index 0000000000..7c54416674 --- /dev/null +++ b/crypto/fipsmodule/evp/evp_ctx_test.cc @@ -0,0 +1,349 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +#include "internal.h" + +#include +#include +#include +#include +#include +#include + +#include "../../internal.h" +#include "internal.h" + +class EvpPkeyCtxCtrlStrTest : public ::testing::Test { + protected: + void SetUp() override {} + + void TearDown() override {} +}; + +class EvpPkeyCtxCtrlStrParamTest : public testing::TestWithParam { +protected: + void SetUp() override {} + + void TearDown() override {} +}; + +static bssl::UniquePtr gen_RSA() { + EVP_PKEY *raw = nullptr; + bssl::UniquePtr 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; + } + bssl::UniquePtr pkey(raw); + return bssl::UniquePtr(EVP_PKEY_CTX_new(pkey.get(), nullptr)); +} + +TEST_F(EvpPkeyCtxCtrlStrTest, RsaMissingValue) { + // Create a EVP_PKEY_CTX with a newly generated RSA key + bssl::UniquePtr 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 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 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 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 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 + bssl::UniquePtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr)); + ASSERT_TRUE(ctx); + ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get())); +#if defined(BORINGSSL_FIPS) + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_keygen_pubexp", "729"), 0); +#else + EVP_PKEY *raw = nullptr; + 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 pkey(raw); + ASSERT_TRUE(pkey); + + bssl::UniquePtr 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); +#endif +} + +TEST_F(EvpPkeyCtxCtrlStrTest, RsaMgf1Md) { + bssl::UniquePtr 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 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 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"), 0); + + 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); +} + +TEST_P(EvpPkeyCtxCtrlStrParamTest, EcParamgenCurve) { + const char* name = GetParam(); + + // Create a EVP_PKEY_CTX with a newly generated EC key + EVP_PKEY *raw = nullptr; + bssl::UniquePtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr)); + ASSERT_TRUE(ctx); + ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get())); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "ec_paramgen_curve", name), 1); + + ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw)); + bssl::UniquePtr pkey(raw); + ASSERT_TRUE(pkey); + + const EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get()); + ASSERT_TRUE(ec_key != nullptr); + const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key); + ASSERT_TRUE(ec_group != nullptr); + ASSERT_EQ(NID_X9_62_prime256v1, EC_GROUP_get_curve_name(ec_group)); +} + +INSTANTIATE_TEST_SUITE_P(EcParamgenCurve, + EvpPkeyCtxCtrlStrParamTest, + testing::Values("P-256", "prime256v1")); + + +TEST_F(EvpPkeyCtxCtrlStrTest, EcParamEnc) { + // Create a EVP_PKEY_CTX with a newly generated EC key + bssl::UniquePtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr)); + ASSERT_TRUE(ctx); + ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get())); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "ec_param_enc", "named_curve"), 1); + + // The `EVP_PKEY_CTX_set_ec_param_enc` function that is called does not + // alter any state, so there's nothing to verify afterward. +} + +TEST_F(EvpPkeyCtxCtrlStrTest, DhPad) { + // Create a EVP_PKEY_CTX with a newly generated DH + bssl::UniquePtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DH, nullptr)); + ASSERT_TRUE(ctx); + ASSERT_TRUE(EVP_PKEY_derive_init(ctx.get())); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "dh_pad", "17"), 1); + + // There is no function to retrieve the DH pad value. +} + +static const char *hkdf_hexsalt = "000102030405060708090a0b0c"; +static const char *hkdf_hexinfo = "f0f1f2f3f4f5f6f7f8f9"; +static const char *hkdf_hexkey = "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"; +static const char *hkdf_hex_expected_okm = + "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5" + "b887185865"; +static const char *hkdf_hex_expected_prk = + "077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"; + +TEST_F(EvpPkeyCtxCtrlStrTest, HkdfHex) { + // Test Cases from RFC 5869. + + bssl::UniquePtr ctx( + EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr)); + ASSERT_TRUE(ctx); + ASSERT_TRUE(EVP_PKEY_derive_init(ctx.get())); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "mode", "EXTRACT_AND_EXPAND"), 1); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "md", "SHA256"), 1); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "hexsalt", hkdf_hexsalt), 1); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "hexinfo", hkdf_hexinfo), 1); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "hexkey", hkdf_hexkey), 1); + + size_t okm_len; + bssl::UniquePtr expected_okm( + OPENSSL_hexstr2buf(hkdf_hex_expected_okm, &okm_len)); + ASSERT_TRUE(expected_okm); + + bssl::UniquePtr actual_okm( + static_cast(OPENSSL_zalloc(okm_len))); + ASSERT_TRUE(actual_okm); + + ASSERT_TRUE(EVP_PKEY_derive(ctx.get(), actual_okm.get(), &okm_len)); + + ASSERT_EQ(OPENSSL_memcmp(actual_okm.get(), expected_okm.get(), okm_len), 0); +} + +TEST_F(EvpPkeyCtxCtrlStrTest, HkdfRaw) { + // Test Cases from RFC 5869. + + bssl::UniquePtr ctx( + EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr)); + ASSERT_TRUE(ctx); + ASSERT_TRUE(EVP_PKEY_derive_init(ctx.get())); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "mode", "EXTRACT_AND_EXPAND"), 1); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "md", "SHA256"), 1); + + // The salt in the KAT contains a 0-byte so "salt" cannot be used. + ASSERT_EQ( + EVP_PKEY_CTX_ctrl_str(ctx.get(), "hexsalt", "000102030405060708090a0b0c"), + 1); + + + size_t len; + bssl::UniquePtr info_parsed(OPENSSL_hexstr2buf(hkdf_hexinfo, &len)); + bssl::UniquePtr info((uint8_t*)OPENSSL_zalloc(len+1)); + OPENSSL_memcpy(info.get(), info_parsed.get(), len); + + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "info", + reinterpret_cast(info.get())), + 1); + bssl::UniquePtr key_parsed(OPENSSL_hexstr2buf(hkdf_hexkey, &len)); + bssl::UniquePtr key((uint8_t*)OPENSSL_zalloc(len+1)); + OPENSSL_memcpy(key.get(), key_parsed.get(), len); + + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "key", + reinterpret_cast(key.get())), + 1); + + size_t okm_len; + bssl::UniquePtr expected_okm( + OPENSSL_hexstr2buf(hkdf_hex_expected_okm, &okm_len)); + ASSERT_TRUE(expected_okm); + + bssl::UniquePtr actual_okm( + static_cast(OPENSSL_zalloc(okm_len))); + ASSERT_TRUE(actual_okm); + + ASSERT_TRUE(EVP_PKEY_derive(ctx.get(), actual_okm.get(), &okm_len)); + + ASSERT_EQ(OPENSSL_memcmp(actual_okm.get(), expected_okm.get(), okm_len), 0); +} + +TEST_F(EvpPkeyCtxCtrlStrTest, HkdfExtract) { + // Test Cases from RFC 5869. + + bssl::UniquePtr ctx( + EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr)); + ASSERT_TRUE(ctx); + ASSERT_TRUE(EVP_PKEY_derive_init(ctx.get())); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "mode", "EXTRACT_ONLY"), 1); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "md", "SHA256"), 1); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "hexsalt", hkdf_hexsalt), 1); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "hexinfo", hkdf_hexinfo), 1); + ASSERT_EQ(EVP_PKEY_CTX_ctrl_str(ctx.get(), "hexkey", hkdf_hexkey), 1); + + size_t prk_len; + bssl::UniquePtr expected_prk( + OPENSSL_hexstr2buf(hkdf_hex_expected_prk, &prk_len)); + ASSERT_TRUE(expected_prk); + + bssl::UniquePtr actual_prk( + static_cast(OPENSSL_zalloc(prk_len))); + ASSERT_TRUE(actual_prk); + + ASSERT_TRUE(EVP_PKEY_derive(ctx.get(), actual_prk.get(), &prk_len)); + + ASSERT_EQ(OPENSSL_memcmp(actual_prk.get(), expected_prk.get(), prk_len), 0); +} diff --git a/crypto/fipsmodule/evp/p_ec.c b/crypto/fipsmodule/evp/p_ec.c index d473f9bdeb..0138a3d5ac 100644 --- a/crypto/fipsmodule/evp/p_ec.c +++ b/crypto/fipsmodule/evp/p_ec.c @@ -226,6 +226,39 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { } } +static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, + const char *value) { + if (strcmp(type, "ec_paramgen_curve") == 0) { + int nid; + nid = EC_curve_nist2nid(value); + if (nid == NID_undef) { + nid = OBJ_sn2nid(value); + } + if (nid == NID_undef) { + nid = OBJ_ln2nid(value); + } + if (nid == NID_undef) { + OPENSSL_PUT_ERROR(EVP, EC_R_INVALID_ENCODING); + return 0; + } + return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); + } + if (strcmp(type, "ec_param_enc") == 0) { + int param_enc; + // We don't support "explicit" + if (strcmp(value, "named_curve") == 0) { + param_enc = OPENSSL_EC_NAMED_CURVE; + } else { + return -2; + } + return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); + } + + // We don't support "ecdh_kdf_md" nor "ecdh_cofactor_mode" + + return -2; +} + static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { int ret = 0; EC_PKEY_CTX *dctx = ctx->data; @@ -289,7 +322,7 @@ DEFINE_METHOD_FUNCTION(EVP_PKEY_METHOD, EVP_PKEY_ec_pkey_meth) { out->derive = pkey_ec_derive; out->paramgen = pkey_ec_paramgen; out->ctrl = pkey_ec_ctrl; - out->ctrl_str = NULL; + out->ctrl_str = pkey_ec_ctrl_str; } int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid) { diff --git a/crypto/fipsmodule/evp/p_hkdf.c b/crypto/fipsmodule/evp/p_hkdf.c index 04316a88bb..7a6314b15c 100644 --- a/crypto/fipsmodule/evp/p_hkdf.c +++ b/crypto/fipsmodule/evp/p_hkdf.c @@ -179,6 +179,85 @@ static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { } } +static int pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, + const char *value) { + if (strcmp(type, "mode") == 0) { + int mode; + + if (strcmp(value, "EXTRACT_AND_EXPAND") == 0) { + mode = EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND; + } else if (strcmp(value, "EXTRACT_ONLY") == 0) { + mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY; + } else if (strcmp(value, "EXPAND_ONLY") == 0) { + mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY; + } else { + return 0; + } + + return EVP_PKEY_CTX_hkdf_mode(ctx, mode); + } + + if (strcmp(type, "md") == 0) { + OPENSSL_BEGIN_ALLOW_DEPRECATED + return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_MD, + value); + OPENSSL_END_ALLOW_DEPRECATED + } + + if (strcmp(type, "salt") == 0) { + // What if the salt contains a 0-byte? + const size_t saltlen = OPENSSL_strnlen(value, INT16_MAX); + return EVP_PKEY_CTX_set1_hkdf_salt(ctx, (const uint8_t *)value, saltlen); + } + + if (strcmp(type, "hexsalt") == 0) { + size_t hex_saltlen = 0; + uint8_t *salt = OPENSSL_hexstr2buf(value, &hex_saltlen); + if (salt == NULL) { + return 0; + } + int result = EVP_PKEY_CTX_set1_hkdf_salt(ctx, salt, hex_saltlen); + OPENSSL_free(salt); + return result; + } + + if (strcmp(type, "key") == 0) { + // What if the key contains a 0-byte? + const size_t keylen = OPENSSL_strnlen(value, INT16_MAX); + return EVP_PKEY_CTX_set1_hkdf_key(ctx, (const uint8_t *)value, keylen); + } + + if (strcmp(type, "hexkey") == 0) { + size_t hex_keylen = 0; + uint8_t *key = OPENSSL_hexstr2buf(value, &hex_keylen); + if (key == NULL) { + return 0; + } + int result = EVP_PKEY_CTX_set1_hkdf_key(ctx, key, hex_keylen); + OPENSSL_free(key); + return result; + } + + if (strcmp(type, "info") == 0) { + // What if info contains a 0-byte? + const size_t infolen = OPENSSL_strnlen(value, INT16_MAX); + return EVP_PKEY_CTX_add1_hkdf_info(ctx, (const uint8_t *)value, infolen); + } + + if (strcmp(type, "hexinfo") == 0) { + size_t hex_infolen = 0; + uint8_t *info = OPENSSL_hexstr2buf(value, &hex_infolen); + if (info == NULL) { + return 0; + } + int result = EVP_PKEY_CTX_add1_hkdf_info(ctx, info, hex_infolen); + OPENSSL_free(info); + return result; + } + + return -2; +} + DEFINE_METHOD_FUNCTION(EVP_PKEY_METHOD, EVP_PKEY_hkdf_pkey_meth) { out->pkey_id = EVP_PKEY_HKDF; out->init = pkey_hkdf_init; @@ -197,7 +276,7 @@ DEFINE_METHOD_FUNCTION(EVP_PKEY_METHOD, EVP_PKEY_hkdf_pkey_meth) { out->derive = pkey_hkdf_derive; out->paramgen = NULL; /* paramgen */ out->ctrl = pkey_hkdf_ctrl; - out->ctrl_str = NULL; + out->ctrl_str = pkey_hkdf_ctrl_str; } int EVP_PKEY_CTX_hkdf_mode(EVP_PKEY_CTX *ctx, int mode) { diff --git a/crypto/fipsmodule/evp/p_rsa.c b/crypto/fipsmodule/evp/p_rsa.c index 3f2cb12d80..a93b3d2382 100644 --- a/crypto/fipsmodule/evp/p_rsa.c +++ b/crypto/fipsmodule/evp/p_rsa.c @@ -558,12 +558,17 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { return 1; case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP: +#if defined(AWSLC_FIPS) + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_OPERATION); + return 0; +#else if (!p2) { return 0; } BN_free(rctx->pub_exp); rctx->pub_exp = p2; return 1; +#endif case EVP_PKEY_CTRL_RSA_OAEP_MD: case EVP_PKEY_CTRL_GET_RSA_OAEP_MD: @@ -685,6 +690,108 @@ 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 = 0; + + uint8_t *lab = OPENSSL_hexstr2buf(value, &lablen); + if (lab == NULL) { + return 0; + } + + int 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; @@ -703,7 +810,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) { @@ -724,7 +831,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) {