Add FIPS-compliant key generation that calls check_fips for RSA and EC.
Change-Id: Ie466b7b55bdd679c5baf2127bd8de4a5058fc3b7 Reviewed-on: https://boringssl-review.googlesource.com/16346 Commit-Queue: Steven Valdez <svaldez@google.com> Reviewed-by: Steven Valdez <svaldez@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
parent
1ac4f16fe9
commit
467d3220f8
@ -494,6 +494,10 @@ err:
|
||||
return ok;
|
||||
}
|
||||
|
||||
int EC_KEY_generate_key_fips(EC_KEY *eckey) {
|
||||
return EC_KEY_generate_key(eckey) && EC_KEY_check_fips(eckey);
|
||||
}
|
||||
|
||||
int EC_KEY_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
|
||||
CRYPTO_EX_dup *dup_func,
|
||||
CRYPTO_EX_free *free_func) {
|
||||
|
@ -314,13 +314,11 @@ TEST_P(ECCurveTest, SetAffine) {
|
||||
x.get(), y.get(), nullptr));
|
||||
}
|
||||
|
||||
TEST_P(ECCurveTest, CheckFIPS) {
|
||||
TEST_P(ECCurveTest, GenerateFIPS) {
|
||||
// Generate an EC_KEY.
|
||||
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
|
||||
ASSERT_TRUE(key);
|
||||
ASSERT_TRUE(EC_KEY_generate_key(key.get()));
|
||||
|
||||
EXPECT_TRUE(EC_KEY_check_fips(key.get()));
|
||||
ASSERT_TRUE(EC_KEY_generate_key_fips(key.get()));
|
||||
}
|
||||
|
||||
TEST_P(ECCurveTest, AddingEqualPoints) {
|
||||
|
@ -909,8 +909,8 @@ err:
|
||||
|
||||
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
|
||||
/* See FIPS 186-4 appendix B.3. This function implements a generalized version
|
||||
* of the FIPS algorithm. For FIPS compliance, the caller is responsible for
|
||||
* passing in 2048 or 3072 to |bits| and 65537 for |e_value|. */
|
||||
* of the FIPS algorithm. |RSA_generate_key_fips| performs additional checks
|
||||
* for FIPS-compliant key generation. */
|
||||
|
||||
/* Always generate RSA keys which are a multiple of 128 bits. Round |bits|
|
||||
* down as needed. */
|
||||
@ -1037,6 +1037,23 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RSA_generate_key_fips(RSA *rsa, int bits, BN_GENCB *cb) {
|
||||
/* FIPS 186-4 allows 2048-bit and 3072-bit RSA keys (1024-bit and 1536-bit
|
||||
* primes, respectively) with the prime generation method we use. */
|
||||
if (bits != 2048 && bits != 3072) {
|
||||
OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_RSA_PARAMETERS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BIGNUM *e = BN_new();
|
||||
int ret = e != NULL &&
|
||||
BN_set_word(e, RSA_F4) &&
|
||||
RSA_generate_key_ex(rsa, bits, e, cb) &&
|
||||
RSA_check_fips(rsa);
|
||||
BN_free(e);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_METHOD_FUNCTION(RSA_METHOD, RSA_default_method) {
|
||||
/* All of the methods are NULL to make it easier for the compiler/linker to
|
||||
* drop unused functions. The wrapper functions will select the appropriate
|
||||
|
@ -486,6 +486,30 @@ TEST(RSATest, CheckFIPS) {
|
||||
EXPECT_TRUE(RSA_check_fips(pub.get()));
|
||||
}
|
||||
|
||||
TEST(RSATest, GenerateFIPS) {
|
||||
bssl::UniquePtr<RSA> rsa(RSA_new());
|
||||
ASSERT_TRUE(rsa);
|
||||
|
||||
// RSA_generate_key_fips may only be used for 2048-bit and 3072-bit keys.
|
||||
EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 512, nullptr));
|
||||
EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 1024, nullptr));
|
||||
EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 2047, nullptr));
|
||||
EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 2049, nullptr));
|
||||
EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 3071, nullptr));
|
||||
EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 3073, nullptr));
|
||||
EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 4096, nullptr));
|
||||
ERR_clear_error();
|
||||
|
||||
// Test that we can generate 2048-bit and 3072-bit RSA keys.
|
||||
EXPECT_TRUE(RSA_generate_key_fips(rsa.get(), 2048, nullptr));
|
||||
EXPECT_EQ(2048u, BN_num_bits(rsa->n));
|
||||
|
||||
rsa.reset(RSA_new());
|
||||
ASSERT_TRUE(rsa);
|
||||
EXPECT_TRUE(RSA_generate_key_fips(rsa.get(), 3072, nullptr));
|
||||
EXPECT_EQ(3072u, BN_num_bits(rsa->n));
|
||||
}
|
||||
|
||||
TEST(RSATest, BadKey) {
|
||||
bssl::UniquePtr<RSA> key(RSA_new());
|
||||
bssl::UniquePtr<BIGNUM> e(BN_new());
|
||||
|
@ -48,7 +48,7 @@ static bool TestECDSA2KeyPair(FileTest *t, void *arg) {
|
||||
bssl::UniquePtr<BIGNUM> qx(BN_new()), qy(BN_new());
|
||||
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
|
||||
if (!key ||
|
||||
!EC_KEY_generate_key(key.get()) ||
|
||||
!EC_KEY_generate_key_fips(key.get()) ||
|
||||
!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
|
||||
EC_KEY_get0_public_key(key.get()),
|
||||
qx.get(), qy.get(), nullptr)) {
|
||||
|
@ -41,7 +41,7 @@ static bool TestECDSA2SigGenImpl(FileTest *t, bool is_component) {
|
||||
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
|
||||
std::vector<uint8_t> msg;
|
||||
if (!qx || !qy || !key ||
|
||||
!EC_KEY_generate_key(key.get()) ||
|
||||
!EC_KEY_generate_key_fips(key.get()) ||
|
||||
!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
|
||||
EC_KEY_get0_public_key(key.get()),
|
||||
qx.get(), qy.get(), nullptr) ||
|
||||
|
@ -41,12 +41,10 @@ static bool TestRSA2KeyGen(FileTest *t, void *arg) {
|
||||
size_t bits = strtoul(mod_str.c_str(), nullptr, 0);
|
||||
size_t count = strtoul(count_str.c_str(), nullptr, 0);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
bssl::UniquePtr<BIGNUM> gen_e(BN_new());
|
||||
bssl::UniquePtr<RSA> key(RSA_new());
|
||||
if (key == nullptr ||
|
||||
bits == 0 ||
|
||||
!BN_set_word(gen_e.get(), RSA_F4) ||
|
||||
!RSA_generate_key_ex(key.get(), bits, gen_e.get(), nullptr)) {
|
||||
!RSA_generate_key_fips(key.get(), bits, nullptr)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -50,21 +50,19 @@ static bool TestRSA2SigGen(FileTest *t, void *arg) {
|
||||
if (t->IsAtNewInstructionBlock()) {
|
||||
int mod_bits = strtoul(mod_str.c_str(), nullptr, 0);
|
||||
ctx->key = bssl::UniquePtr<RSA>(RSA_new());
|
||||
bssl::UniquePtr<BIGNUM> e(BN_new());
|
||||
if (ctx->key == nullptr ||
|
||||
mod_bits == 0 ||
|
||||
!BN_set_word(e.get(), RSA_F4) ||
|
||||
!RSA_generate_key_ex(ctx->key.get(), mod_bits, e.get(), nullptr)) {
|
||||
!RSA_generate_key_fips(ctx->key.get(), mod_bits, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const BIGNUM *n;
|
||||
RSA_get0_key(ctx->key.get(), &n, nullptr, nullptr);
|
||||
const BIGNUM *n, *e;
|
||||
RSA_get0_key(ctx->key.get(), &n, &e, nullptr);
|
||||
|
||||
std::vector<uint8_t> n_bytes(BN_num_bytes(n));
|
||||
std::vector<uint8_t> e_bytes(BN_num_bytes(e.get()));
|
||||
std::vector<uint8_t> e_bytes(BN_num_bytes(e));
|
||||
if (!BN_bn2bin_padded(n_bytes.data(), n_bytes.size(), n) ||
|
||||
!BN_bn2bin_padded(e_bytes.data(), e_bytes.size(), e.get())) {
|
||||
!BN_bn2bin_padded(e_bytes.data(), e_bytes.size(), e)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -177,6 +177,10 @@ OPENSSL_EXPORT int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key,
|
||||
* or zero otherwise. */
|
||||
OPENSSL_EXPORT int EC_KEY_generate_key(EC_KEY *key);
|
||||
|
||||
/* EC_KEY_generate_key_fips behaves like |EC_KEY_generate_key| but performs
|
||||
* additional checks for FIPS compliance. */
|
||||
OPENSSL_EXPORT int EC_KEY_generate_key_fips(EC_KEY *key);
|
||||
|
||||
|
||||
/* Serialisation. */
|
||||
|
||||
|
@ -122,6 +122,11 @@ OPENSSL_EXPORT void RSA_get0_crt_params(const RSA *rsa, const BIGNUM **out_dmp1,
|
||||
OPENSSL_EXPORT int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e,
|
||||
BN_GENCB *cb);
|
||||
|
||||
/* RSA_generate_key_fips behaves like |RSA_generate_key_ex| but performs
|
||||
* additional checks for FIPS compliance. The public exponent is always 65537
|
||||
* and |bits| must be either 2048 or 3072. */
|
||||
OPENSSL_EXPORT int RSA_generate_key_fips(RSA *rsa, int bits, BN_GENCB *cb);
|
||||
|
||||
|
||||
/* Encryption / Decryption */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user