Add ECDSA nonce-testing functions.

There are a few places where it is useful to run ECDSA with a specified
nonce:

- An ECDSA KAT in the module self-check

- Unit tests for particular test vectors

- Fuzzing the implementation (requested by the cryptofuzz project)

This replaces the fixed_k machinery with a separate function. Although
they are effectively the same, I've used two different functions.
One is internal and only used in the module self-check. The other is
exported for unit tests and cryptofuzz but marked with a for_testing.
(Chromium's presubmits flag uses of "for_testing" functions outside of
unit tests. The KAT version isn't in a test per se, so it's a separate
function.)

Bug: 391
Change-Id: I0f764d89bf0ac2081307e1079623d508fb0f2df7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/45867
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/fipsmodule/ec/ec_key.c b/crypto/fipsmodule/ec/ec_key.c
index bc09e0e..7a6daab 100644
--- a/crypto/fipsmodule/ec/ec_key.c
+++ b/crypto/fipsmodule/ec/ec_key.c
@@ -171,7 +171,6 @@
   EC_GROUP_free(r->group);
   EC_POINT_free(r->pub_key);
   ec_wrapped_scalar_free(r->priv_key);
-  BN_free(r->fixed_k);
 
   CRYPTO_free_ex_data(g_ec_ex_data_class_bss_get(), r, &r->ex_data);
 
diff --git a/crypto/fipsmodule/ec/internal.h b/crypto/fipsmodule/ec/internal.h
index 18aabb0..289c3aa 100644
--- a/crypto/fipsmodule/ec/internal.h
+++ b/crypto/fipsmodule/ec/internal.h
@@ -729,10 +729,6 @@
   EC_POINT *pub_key;
   EC_WRAPPED_SCALAR *priv_key;
 
-  // fixed_k may contain a specific value of 'k', to be used in ECDSA signing.
-  // This is only for the FIPS power-on tests.
-  BIGNUM *fixed_k;
-
   unsigned int enc_flag;
   point_conversion_form_t conv_form;
 
diff --git a/crypto/fipsmodule/ecdsa/ecdsa.c b/crypto/fipsmodule/ecdsa/ecdsa.c
index e519a69..591f1bc 100644
--- a/crypto/fipsmodule/ecdsa/ecdsa.c
+++ b/crypto/fipsmodule/ecdsa/ecdsa.c
@@ -61,9 +61,10 @@
 #include <openssl/sha.h>
 #include <openssl/type_check.h>
 
+#include "../../internal.h"
 #include "../bn/internal.h"
 #include "../ec/internal.h"
-#include "../../internal.h"
+#include "internal.h"
 
 
 // digest_to_scalar interprets |digest_len| bytes from |digest| as a scalar for
@@ -261,6 +262,41 @@
   return ret;
 }
 
+ECDSA_SIG *ecdsa_sign_with_nonce_for_known_answer_test(const uint8_t *digest,
+                                                       size_t digest_len,
+                                                       const EC_KEY *eckey,
+                                                       const uint8_t *nonce,
+                                                       size_t nonce_len) {
+  if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
+    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
+    return NULL;
+  }
+
+  const EC_GROUP *group = EC_KEY_get0_group(eckey);
+  if (group == NULL || eckey->priv_key == NULL) {
+    OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER);
+    return NULL;
+  }
+  const EC_SCALAR *priv_key = &eckey->priv_key->scalar;
+
+  EC_SCALAR k;
+  if (!ec_scalar_from_bytes(group, &k, nonce, nonce_len)) {
+    return NULL;
+  }
+  int retry_ignored;
+  return ecdsa_sign_impl(group, &retry_ignored, priv_key, &k, digest,
+                         digest_len);
+}
+
+// This function is only exported for testing and is not called in production
+// code.
+ECDSA_SIG *ECDSA_sign_with_nonce_and_leak_private_key_for_testing(
+    const uint8_t *digest, size_t digest_len, const EC_KEY *eckey,
+    const uint8_t *nonce, size_t nonce_len) {
+  return ecdsa_sign_with_nonce_for_known_answer_test(digest, digest_len, eckey,
+                                                     nonce, nonce_len);
+}
+
 ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len,
                          const EC_KEY *eckey) {
   if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
@@ -276,30 +312,21 @@
   const BIGNUM *order = EC_GROUP_get0_order(group);
   const EC_SCALAR *priv_key = &eckey->priv_key->scalar;
 
+  // Pass a SHA512 hash of the private key and digest as additional data
+  // into the RBG. This is a hardening measure against entropy failure.
+  OPENSSL_STATIC_ASSERT(SHA512_DIGEST_LENGTH >= 32,
+                        "additional_data is too large for SHA-512");
+  SHA512_CTX sha;
+  uint8_t additional_data[SHA512_DIGEST_LENGTH];
+  SHA512_Init(&sha);
+  SHA512_Update(&sha, priv_key->words, order->width * sizeof(BN_ULONG));
+  SHA512_Update(&sha, digest, digest_len);
+  SHA512_Final(additional_data, &sha);
+
   for (;;) {
     EC_SCALAR k;
-    if (eckey->fixed_k != NULL) {
-      if (!ec_bignum_to_scalar(group, &k, eckey->fixed_k)) {
-        return NULL;
-      }
-      if (ec_scalar_is_zero(group, &k)) {
-        OPENSSL_PUT_ERROR(ECDSA, ERR_R_INTERNAL_ERROR);
-        return NULL;
-      }
-    } else {
-      // Pass a SHA512 hash of the private key and digest as additional data
-      // into the RBG. This is a hardening measure against entropy failure.
-      OPENSSL_STATIC_ASSERT(SHA512_DIGEST_LENGTH >= 32,
-                            "additional_data is too large for SHA-512");
-      SHA512_CTX sha;
-      uint8_t additional_data[SHA512_DIGEST_LENGTH];
-      SHA512_Init(&sha);
-      SHA512_Update(&sha, priv_key->words, order->width * sizeof(BN_ULONG));
-      SHA512_Update(&sha, digest, digest_len);
-      SHA512_Final(additional_data, &sha);
-      if (!ec_random_nonzero_scalar(group, &k, additional_data)) {
-        return NULL;
-      }
+    if (!ec_random_nonzero_scalar(group, &k, additional_data)) {
+      return NULL;
     }
 
     int retry;
diff --git a/crypto/fipsmodule/ecdsa/ecdsa_test.cc b/crypto/fipsmodule/ecdsa/ecdsa_test.cc
index 95e26cf..18fdb83 100644
--- a/crypto/fipsmodule/ecdsa/ecdsa_test.cc
+++ b/crypto/fipsmodule/ecdsa/ecdsa_test.cc
@@ -434,8 +434,8 @@
       ASSERT_TRUE(x);
       bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
       ASSERT_TRUE(y);
-      bssl::UniquePtr<BIGNUM> k = GetBIGNUM(t, "K");
-      ASSERT_TRUE(k);
+      std::vector<uint8_t> k;
+      ASSERT_TRUE(t->GetBytes(&k, "K"));
       bssl::UniquePtr<BIGNUM> r = GetBIGNUM(t, "R");
       ASSERT_TRUE(r);
       bssl::UniquePtr<BIGNUM> s = GetBIGNUM(t, "S");
@@ -454,10 +454,9 @@
       ASSERT_TRUE(EC_KEY_set_public_key(key.get(), pub_key.get()));
       ASSERT_TRUE(EC_KEY_check_key(key.get()));
 
-      // Set the fixed k for testing purposes.
-      key->fixed_k = k.release();
       bssl::UniquePtr<ECDSA_SIG> sig(
-          ECDSA_do_sign(digest.data(), digest.size(), key.get()));
+          ECDSA_sign_with_nonce_and_leak_private_key_for_testing(
+              digest.data(), digest.size(), key.get(), k.data(), k.size()));
       ASSERT_TRUE(sig);
 
       EXPECT_EQ(0, BN_cmp(r.get(), sig->r));
diff --git a/crypto/fipsmodule/ecdsa/internal.h b/crypto/fipsmodule/ecdsa/internal.h
new file mode 100644
index 0000000..5115dfa
--- /dev/null
+++ b/crypto/fipsmodule/ecdsa/internal.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2021, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_ECDSA_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_ECDSA_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+// ecdsa_sign_with_nonce_for_known_answer_test behaves like |ECDSA_do_sign| but
+// takes a fixed nonce. This function is used as part of known-answer tests in
+// the FIPS module.
+ECDSA_SIG *ecdsa_sign_with_nonce_for_known_answer_test(const uint8_t *digest,
+                                                       size_t digest_len,
+                                                       const EC_KEY *eckey,
+                                                       const uint8_t *nonce,
+                                                       size_t nonce_len);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif  // OPENSSL_HEADER_CRYPTO_FIPSMODULE_ECDSA_INTERNAL_H
diff --git a/crypto/fipsmodule/self_check/self_check.c b/crypto/fipsmodule/self_check/self_check.c
index 638500b..39570bd 100644
--- a/crypto/fipsmodule/self_check/self_check.c
+++ b/crypto/fipsmodule/self_check/self_check.c
@@ -32,6 +32,7 @@
 
 #include "../../internal.h"
 #include "../ec/internal.h"
+#include "../ecdsa/internal.h"
 #include "../rand/internal.h"
 #include "../tls/internal.h"
 
@@ -727,14 +728,12 @@
   // ECDSA Sign/Verify KAT
 
   // The 'k' value for ECDSA is fixed to avoid an entropy draw.
-  ec_key->fixed_k = BN_new();
-  if (ec_key->fixed_k == NULL ||
-      !BN_set_word(ec_key->fixed_k, 42)) {
-    fprintf(stderr, "Out of memory\n");
-    goto err;
-  }
+  uint8_t ecdsa_k[32] = {0};
+  ecdsa_k[31] = 42;
 
-  sig = ECDSA_do_sign(kPlaintextSHA256, sizeof(kPlaintextSHA256), ec_key);
+  sig = ecdsa_sign_with_nonce_for_known_answer_test(
+      kPlaintextSHA256, sizeof(kPlaintextSHA256), ec_key, ecdsa_k,
+      sizeof(ecdsa_k));
 
   uint8_t ecdsa_r_bytes[sizeof(kECDSASigR)];
   uint8_t ecdsa_s_bytes[sizeof(kECDSASigS)];
diff --git a/include/openssl/ecdsa.h b/include/openssl/ecdsa.h
index 9cd19a5..08950e3 100644
--- a/include/openssl/ecdsa.h
+++ b/include/openssl/ecdsa.h
@@ -162,6 +162,25 @@
 OPENSSL_EXPORT size_t ECDSA_SIG_max_len(size_t order_len);
 
 
+// Testing-only functions.
+
+// ECDSA_sign_with_nonce_and_leak_private_key_for_testing behaves like
+// |ECDSA_do_sign| but uses |nonce| for the ECDSA nonce 'k', instead of a random
+// value. |nonce| is interpreted as a big-endian integer. It must be reduced
+// modulo the group order and padded with zeros up to |BN_num_bytes(order)|
+// bytes.
+//
+// WARNING: This function is only exported for testing purposes, when using test
+// vectors or fuzzing strategies. It must not be used outside tests and may leak
+// any private keys it is used with.
+OPENSSL_EXPORT ECDSA_SIG *
+ECDSA_sign_with_nonce_and_leak_private_key_for_testing(const uint8_t *digest,
+                                                       size_t digest_len,
+                                                       const EC_KEY *eckey,
+                                                       const uint8_t *nonce,
+                                                       size_t nonce_len);
+
+
 // Deprecated functions.
 
 // d2i_ECDSA_SIG parses an ASN.1, DER-encoded, signature from |len| bytes at