Add an ECDH Wycheproof driver.

Unfortunately, this driver suffers a lot from Wycheproof's Java
heritgate, but so it goes. Their test formats bake in a lot of Java API
mistakes.

Change-Id: I3299e85efb58e99e4fa34841709c3bea6518968d
Reviewed-on: https://boringssl-review.googlesource.com/27865
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/test/wycheproof_util.cc b/crypto/test/wycheproof_util.cc
index 3ff132f..8f7dfeb 100644
--- a/crypto/test/wycheproof_util.cc
+++ b/crypto/test/wycheproof_util.cc
@@ -14,6 +14,7 @@
 
 #include "./wycheproof_util.h"
 
+#include <openssl/bn.h>
 #include <openssl/digest.h>
 #include <openssl/ec.h>
 #include <openssl/nid.h>
@@ -89,3 +90,35 @@
   }
   return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(nid));
 }
+
+bssl::UniquePtr<BIGNUM> GetWycheproofBIGNUM(FileTest *t, const char *key,
+                                            bool instruction) {
+  std::string value;
+  bool ok = instruction ? t->GetInstruction(&value, key)
+                        : t->GetAttribute(&value, key);
+  if (!ok) {
+    return nullptr;
+  }
+  BIGNUM *bn = nullptr;
+  if (BN_hex2bn(&bn, value.c_str()) != static_cast<int>(value.size())) {
+    BN_free(bn);
+    t->PrintLine("Could not decode value '%s'", value.c_str());
+    return nullptr;
+  }
+  bssl::UniquePtr<BIGNUM> ret(bn);
+  if (!value.empty()) {
+    // If the high bit is one, this is a negative number in Wycheproof.
+    // Wycheproof's tests generally mimic Java APIs, including all their
+    // mistakes. See
+    // https://github.com/google/wycheproof/blob/0329f5b751ef102bd6b7b7181b6e049522a887f5/java/com/google/security/wycheproof/JsonUtil.java#L62.
+    if ('0' > value[0] || value[0] > '7') {
+      bssl::UniquePtr<BIGNUM> tmp(BN_new());
+      if (!tmp ||
+          !BN_set_bit(tmp.get(), value.size() * 4) ||
+          !BN_sub(ret.get(), ret.get(), tmp.get())) {
+        return nullptr;
+      }
+    }
+  }
+  return ret;
+}
diff --git a/crypto/test/wycheproof_util.h b/crypto/test/wycheproof_util.h
index cf50b8e..4d8a14c 100644
--- a/crypto/test/wycheproof_util.h
+++ b/crypto/test/wycheproof_util.h
@@ -41,5 +41,10 @@
 bssl::UniquePtr<EC_GROUP> GetWycheproofCurve(FileTest *t, const char *key,
                                              bool instruction);
 
+// GetWycheproofBIGNUM returns a BIGNUM in the Wycheproof format, or nullptr on
+// error.
+bssl::UniquePtr<BIGNUM> GetWycheproofBIGNUM(FileTest *t, const char *key,
+                                            bool instruction);
+
 
 #endif  // OPENSSL_HEADER_CRYPTO_TEST_WYCHEPROOF_UTIL_H