Switch CRYPTO_BUFFER_POOL to SipHash-2-4.

This hash table, in applications that use pooling, can dedup received
certificates in memory and thus should use a keyed hash.

Change-Id: Idc40dc8f7463025183121642b30ea0de43ebac0e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/51125
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/pool/internal.h b/crypto/pool/internal.h
index b39ee42..f9f4838 100644
--- a/crypto/pool/internal.h
+++ b/crypto/pool/internal.h
@@ -39,6 +39,7 @@
 struct crypto_buffer_pool_st {
   LHASH_OF(CRYPTO_BUFFER) *bufs;
   CRYPTO_MUTEX lock;
+  const uint64_t hash_key[2];
 };
 
 
diff --git a/crypto/pool/pool.c b/crypto/pool/pool.c
index 89bf4c2..e889f52 100644
--- a/crypto/pool/pool.c
+++ b/crypto/pool/pool.c
@@ -19,6 +19,8 @@
 
 #include <openssl/bytestring.h>
 #include <openssl/mem.h>
+#include <openssl/rand.h>
+#include <openssl/siphash.h>
 #include <openssl/thread.h>
 
 #include "../internal.h"
@@ -26,10 +28,13 @@
 
 
 static uint32_t CRYPTO_BUFFER_hash(const CRYPTO_BUFFER *buf) {
-  return OPENSSL_hash32(buf->data, buf->len);
+  return (uint32_t)SIPHASH_24(buf->pool->hash_key, buf->data, buf->len);
 }
 
 static int CRYPTO_BUFFER_cmp(const CRYPTO_BUFFER *a, const CRYPTO_BUFFER *b) {
+  // Only |CRYPTO_BUFFER|s from the same pool have compatible hashes.
+  assert(a->pool != NULL);
+  assert(a->pool == b->pool);
   if (a->len != b->len) {
     return 1;
   }
@@ -50,6 +55,7 @@
   }
 
   CRYPTO_MUTEX_init(&pool->lock);
+  RAND_bytes((uint8_t *)&pool->hash_key, sizeof(pool->hash_key));
 
   return pool;
 }
@@ -84,6 +90,7 @@
     CRYPTO_BUFFER tmp;
     tmp.data = (uint8_t *) data;
     tmp.len = len;
+    tmp.pool = pool;
 
     CRYPTO_MUTEX_lock_read(&pool->lock);
     CRYPTO_BUFFER *duplicate = lh_CRYPTO_BUFFER_retrieve(pool->bufs, &tmp);
diff --git a/tool/speed.cc b/tool/speed.cc
index b91a4ce..c12ebb2 100644
--- a/tool/speed.cc
+++ b/tool/speed.cc
@@ -41,6 +41,7 @@
 #include <openssl/nid.h>
 #include <openssl/rand.h>
 #include <openssl/rsa.h>
+#include <openssl/siphash.h>
 #include <openssl/trust_token.h>
 
 #if defined(OPENSSL_WINDOWS)
@@ -561,20 +562,20 @@
 static bool SpeedHashChunk(const EVP_MD *md, std::string name,
                            size_t chunk_len) {
   bssl::ScopedEVP_MD_CTX ctx;
-  uint8_t scratch[16384];
+  uint8_t input[16384] = {0};
 
-  if (chunk_len > sizeof(scratch)) {
+  if (chunk_len > sizeof(input)) {
     return false;
   }
 
   name += ChunkLenSuffix(chunk_len);
   TimeResults results;
-  if (!TimeFunction(&results, [&ctx, md, chunk_len, &scratch]() -> bool {
+  if (!TimeFunction(&results, [&ctx, md, chunk_len, &input]() -> bool {
         uint8_t digest[EVP_MAX_MD_SIZE];
         unsigned int md_len;
 
         return EVP_DigestInit_ex(ctx.get(), md, NULL /* ENGINE */) &&
-               EVP_DigestUpdate(ctx.get(), scratch, chunk_len) &&
+               EVP_DigestUpdate(ctx.get(), input, chunk_len) &&
                EVP_DigestFinal_ex(ctx.get(), digest, &md_len);
       })) {
     fprintf(stderr, "EVP_DigestInit_ex failed.\n");
@@ -1035,6 +1036,29 @@
   return true;
 }
 
+static bool SpeedSipHash(const std::string &selected) {
+  if (!selected.empty() && selected.find("siphash") == std::string::npos) {
+    return true;
+  }
+
+  uint64_t key[2] = {0};
+  for (size_t len : g_chunk_lengths) {
+    std::vector<uint8_t> input(len);
+    TimeResults results;
+    if (!TimeFunction(&results, [&]() -> bool {
+          SIPHASH_24(key, input.data(), input.size());
+          return true;
+        })) {
+      fprintf(stderr, "SIPHASH_24 failed.\n");
+      ERR_print_errors_fp(stderr);
+      return false;
+    }
+    results.PrintWithBytes("SipHash-2-4" + ChunkLenSuffix(len), len);
+  }
+
+  return true;
+}
+
 static TRUST_TOKEN_PRETOKEN *trust_token_pretoken_dup(
     TRUST_TOKEN_PRETOKEN *in) {
   TRUST_TOKEN_PRETOKEN *out =
@@ -1434,7 +1458,8 @@
                        TRUST_TOKEN_experiment_v2_pmb(), 1, selected) ||
       !SpeedTrustToken("TrustToken-Exp2PMB-Batch10",
                        TRUST_TOKEN_experiment_v2_pmb(), 10, selected) ||
-      !SpeedBase64(selected)) {
+      !SpeedBase64(selected) ||
+      !SpeedSipHash(selected)) {
     return false;
   }
 #if defined(BORINGSSL_FIPS)