Make EVP_PKEY_keygen work for Ed25519. For cryptography.io. Change-Id: I90d0a7526cd1283126400568a4596444457136ca Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/36105 Commit-Queue: David Benjamin <davidben@google.com> Commit-Queue: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/evp/evp_extra_test.cc b/crypto/evp/evp_extra_test.cc index d033343..f520598 100644 --- a/crypto/evp/evp_extra_test.cc +++ b/crypto/evp/evp_extra_test.cc
@@ -756,3 +756,29 @@ raw = nullptr; ExpectECGroupAndKey(pkey.get(), NID_X9_62_prime256v1); } + +// Test that |EVP_PKEY_keygen| works for Ed25519. +TEST(EVPExtraTest, Ed25519Keygen) { + bssl::UniquePtr<EVP_PKEY_CTX> pctx( + EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, nullptr)); + ASSERT_TRUE(pctx); + ASSERT_TRUE(EVP_PKEY_keygen_init(pctx.get())); + EVP_PKEY *raw = nullptr; + ASSERT_TRUE(EVP_PKEY_keygen(pctx.get(), &raw)); + bssl::UniquePtr<EVP_PKEY> pkey(raw); + + // Round-trip a signature to sanity-check the key is good. + bssl::ScopedEVP_MD_CTX ctx; + ASSERT_TRUE( + EVP_DigestSignInit(ctx.get(), nullptr, nullptr, nullptr, pkey.get())); + uint8_t sig[64]; + size_t len = sizeof(sig); + ASSERT_TRUE(EVP_DigestSign(ctx.get(), sig, &len, + reinterpret_cast<const uint8_t *>("hello"), 5)); + + ctx.Reset(); + ASSERT_TRUE( + EVP_DigestVerifyInit(ctx.get(), nullptr, nullptr, nullptr, pkey.get())); + ASSERT_TRUE(EVP_DigestVerify(ctx.get(), sig, len, + reinterpret_cast<const uint8_t *>("hello"), 5)); +}
diff --git a/crypto/evp/p_ed25519.c b/crypto/evp/p_ed25519.c index db89389..9149afb 100644 --- a/crypto/evp/p_ed25519.c +++ b/crypto/evp/p_ed25519.c
@@ -16,6 +16,7 @@ #include <openssl/curve25519.h> #include <openssl/err.h> +#include <openssl/mem.h> #include "internal.h" @@ -23,6 +24,27 @@ // Ed25519 has no parameters to copy. static int pkey_ed25519_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { return 1; } +static int pkey_ed25519_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { + ED25519_KEY *key = OPENSSL_malloc(sizeof(ED25519_KEY)); + if (key == NULL) { + OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!EVP_PKEY_set_type(pkey, EVP_PKEY_ED25519)) { + OPENSSL_free(key); + return 0; + } + + uint8_t pubkey_unused[32]; + ED25519_keypair(pubkey_unused, key->key.priv); + key->has_private = 1; + + OPENSSL_free(pkey->pkey.ptr); + pkey->pkey.ptr = key; + return 1; +} + static int pkey_ed25519_sign_message(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen, const uint8_t *tbs, size_t tbslen) { @@ -68,7 +90,7 @@ NULL /* init */, pkey_ed25519_copy, NULL /* cleanup */, - NULL /* keygen */, + pkey_ed25519_keygen, NULL /* sign */, pkey_ed25519_sign_message, NULL /* verify */,