Expose ECDSA_SIG_max_len to size a DER ECDSA-Sig-Value.

Also implement it without reference to crypto/asn1 or fake ASN1_INTEGERs and
add a test. Some platform crypto APIs only give back the key size, and not the
encoded signature length. No sense in implementing it twice.

BUG=347404,499653

Change-Id: I9aa27d52674375f8b036e57bb5850f091c9b25dd
Reviewed-on: https://boringssl-review.googlesource.com/5080
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/ecdsa/ecdsa_test.cc b/crypto/ecdsa/ecdsa_test.cc
index a6bd7a1..615741f 100644
--- a/crypto/ecdsa/ecdsa_test.cc
+++ b/crypto/ecdsa/ecdsa_test.cc
@@ -325,11 +325,50 @@
   return true;
 }
 
+static bool TestECDSA_SIG_max_len(size_t order_len) {
+  /* Create the largest possible |ECDSA_SIG| of the given constraints. */
+  ScopedECDSA_SIG sig(ECDSA_SIG_new());
+  if (!sig) {
+    return false;
+  }
+  std::vector<uint8_t> bytes(order_len, 0xff);
+  if (!BN_bin2bn(bssl::vector_data(&bytes), bytes.size(), sig->r) ||
+      !BN_bin2bn(bssl::vector_data(&bytes), bytes.size(), sig->s)) {
+    return false;
+  }
+  /* Serialize it. */
+  int len = i2d_ECDSA_SIG(sig.get(), nullptr);
+  if (len < 0) {
+    return false;
+  }
+  std::vector<uint8_t> der(len);
+  uint8_t *ptr = bssl::vector_data(&der);
+  len = i2d_ECDSA_SIG(sig.get(), &ptr);
+  if (len < 0) {
+    return false;
+  }
+  der.resize(len);
+
+  size_t max_len = ECDSA_SIG_max_len(order_len);
+  if (max_len != static_cast<size_t>(len)) {
+    fprintf(stderr, "ECDSA_SIG_max_len(%u) returned %u, wanted %d\n",
+            static_cast<unsigned>(order_len), static_cast<unsigned>(max_len),
+            len);
+    return false;
+  }
+  return true;
+}
+
 int main(void) {
   CRYPTO_library_init();
   ERR_load_crypto_strings();
 
-  if (!TestBuiltin(stdout)) {
+  if (!TestBuiltin(stdout) ||
+      !TestECDSA_SIG_max_len(224/8) ||
+      !TestECDSA_SIG_max_len(256/8) ||
+      !TestECDSA_SIG_max_len(384/8) ||
+      !TestECDSA_SIG_max_len(512/8) ||
+      !TestECDSA_SIG_max_len(10000)) {
     printf("\nECDSA test failed\n");
     ERR_print_errors_fp(stdout);
     return 1;