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 */,