Fix EVP_PKEY_CTX_dup with EC generation
gen_group wasn't copied over.
Change-Id: If5341dce69fe0297b6bd9a5fb7ed34d546201604
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/67167
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/evp/evp_extra_test.cc b/crypto/evp/evp_extra_test.cc
index dac6986..0b57dc9 100644
--- a/crypto/evp/evp_extra_test.cc
+++ b/crypto/evp/evp_extra_test.cc
@@ -1018,40 +1018,60 @@
}
TEST(EVPExtraTest, ECKeygen) {
- // |EVP_PKEY_paramgen| may be used as an extremely roundabout way to get an
- // |EC_GROUP|.
- bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr));
- ASSERT_TRUE(ctx);
- ASSERT_TRUE(EVP_PKEY_paramgen_init(ctx.get()));
- ASSERT_TRUE(
- EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), NID_X9_62_prime256v1));
- EVP_PKEY *raw = nullptr;
- ASSERT_TRUE(EVP_PKEY_paramgen(ctx.get(), &raw));
- bssl::UniquePtr<EVP_PKEY> pkey(raw);
- raw = nullptr;
- ExpectECGroupOnly(pkey.get(), NID_X9_62_prime256v1);
+ for (bool copy : {false, true}) {
+ SCOPED_TRACE(copy);
- // That resulting |EVP_PKEY| may be used as a template for key generation.
- ctx.reset(EVP_PKEY_CTX_new(pkey.get(), nullptr));
- ASSERT_TRUE(ctx);
- ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
- raw = nullptr;
- ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));
- pkey.reset(raw);
- raw = nullptr;
- ExpectECGroupAndKey(pkey.get(), NID_X9_62_prime256v1);
+ auto maybe_copy = [&](bssl::UniquePtr<EVP_PKEY_CTX> *ctx) -> bool {
+ if (copy) {
+ ctx->reset(EVP_PKEY_CTX_dup(ctx->get()));
+ }
+ return *ctx != nullptr;
+ };
- // |EVP_PKEY_paramgen| may also be skipped.
- ctx.reset(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr));
- ASSERT_TRUE(ctx);
- ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
- ASSERT_TRUE(
- EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), NID_X9_62_prime256v1));
- raw = nullptr;
- ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));
- pkey.reset(raw);
- raw = nullptr;
- ExpectECGroupAndKey(pkey.get(), NID_X9_62_prime256v1);
+ // |EVP_PKEY_paramgen| may be used as an extremely roundabout way to get an
+ // |EC_GROUP|.
+ bssl::UniquePtr<EVP_PKEY_CTX> ctx(
+ EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr));
+ ASSERT_TRUE(ctx);
+ ASSERT_TRUE(maybe_copy(&ctx));
+ ASSERT_TRUE(EVP_PKEY_paramgen_init(ctx.get()));
+ ASSERT_TRUE(maybe_copy(&ctx));
+ ASSERT_TRUE(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(),
+ NID_X9_62_prime256v1));
+ ASSERT_TRUE(maybe_copy(&ctx));
+ EVP_PKEY *raw = nullptr;
+ ASSERT_TRUE(EVP_PKEY_paramgen(ctx.get(), &raw));
+ bssl::UniquePtr<EVP_PKEY> pkey(raw);
+ raw = nullptr;
+ ExpectECGroupOnly(pkey.get(), NID_X9_62_prime256v1);
+
+ // That resulting |EVP_PKEY| may be used as a template for key generation.
+ ctx.reset(EVP_PKEY_CTX_new(pkey.get(), nullptr));
+ ASSERT_TRUE(ctx);
+ ASSERT_TRUE(maybe_copy(&ctx));
+ ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
+ ASSERT_TRUE(maybe_copy(&ctx));
+ raw = nullptr;
+ ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));
+ pkey.reset(raw);
+ raw = nullptr;
+ ExpectECGroupAndKey(pkey.get(), NID_X9_62_prime256v1);
+
+ // |EVP_PKEY_paramgen| may also be skipped.
+ ctx.reset(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr));
+ ASSERT_TRUE(ctx);
+ ASSERT_TRUE(maybe_copy(&ctx));
+ ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
+ ASSERT_TRUE(maybe_copy(&ctx));
+ ASSERT_TRUE(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(),
+ NID_X9_62_prime256v1));
+ ASSERT_TRUE(maybe_copy(&ctx));
+ raw = nullptr;
+ ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));
+ pkey.reset(raw);
+ raw = nullptr;
+ ExpectECGroupAndKey(pkey.get(), NID_X9_62_prime256v1);
+ }
}
// Test that |EVP_PKEY_keygen| works for Ed25519.
diff --git a/crypto/evp/p_ec.c b/crypto/evp/p_ec.c
index 0e4349f..7e1594e 100644
--- a/crypto/evp/p_ec.c
+++ b/crypto/evp/p_ec.c
@@ -90,15 +90,14 @@
}
static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
- EC_PKEY_CTX *dctx, *sctx;
if (!pkey_ec_init(dst)) {
return 0;
}
- sctx = src->data;
- dctx = dst->data;
+ const EC_PKEY_CTX *sctx = src->data;
+ EC_PKEY_CTX *dctx = dst->data;
dctx->md = sctx->md;
-
+ dctx->gen_group = sctx->gen_group;
return 1;
}