Fix up EVP_DigestSign implementation for Ed25519.

The lengths involve an annoying input/output calling convention.

Change-Id: I848c8821604891f6a86099ced20287979a1143dd
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/35804
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/evp/evp_extra_test.cc b/crypto/evp/evp_extra_test.cc
index 1f6a61d..423661d 100644
--- a/crypto/evp/evp_extra_test.cc
+++ b/crypto/evp/evp_extra_test.cc
@@ -637,6 +637,18 @@
   EXPECT_FALSE(EVP_DigestVerifyUpdate(ctx.get(), nullptr, 0));
   EXPECT_FALSE(EVP_DigestVerifyFinal(ctx.get(), nullptr, 0));
   ERR_clear_error();
+
+  // The buffer length to |EVP_DigestSign| is an input/output parameter and
+  // should be checked before signing.
+  ctx.Reset();
+  ASSERT_TRUE(
+      EVP_DigestSignInit(ctx.get(), nullptr, nullptr, nullptr, privkey.get()));
+  uint8_t buf[16];
+  len = sizeof(buf);
+  EXPECT_FALSE(EVP_DigestSign(ctx.get(), buf, &len, nullptr /* msg */, 0));
+  err = ERR_get_error();
+  EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err));
+  EXPECT_EQ(EVP_R_BUFFER_TOO_SMALL, ERR_GET_REASON(err));
 }
 
 static void ExpectECGroupOnly(const EVP_PKEY *pkey, int nid) {
diff --git a/crypto/evp/p_ed25519.c b/crypto/evp/p_ed25519.c
index 062ea45..db89389 100644
--- a/crypto/evp/p_ed25519.c
+++ b/crypto/evp/p_ed25519.c
@@ -32,12 +32,22 @@
     return 0;
   }
 
-  *siglen = 64;
   if (sig == NULL) {
+    *siglen = 64;
     return 1;
   }
 
-  return ED25519_sign(sig, tbs, tbslen, key->key.priv);
+  if (*siglen < 64) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
+    return 0;
+  }
+
+  if (!ED25519_sign(sig, tbs, tbslen, key->key.priv)) {
+    return 0;
+  }
+
+  *siglen = 64;
+  return 1;
 }
 
 static int pkey_ed25519_verify_message(EVP_PKEY_CTX *ctx, const uint8_t *sig,