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>
fips-20220613
David Benjamin 3 years ago committed by Adam Langley
parent 50e7ea5f09
commit 345c86b1cf
  1. 1
      crypto/pool/internal.h
  2. 9
      crypto/pool/pool.c
  3. 35
      tool/speed.cc

@ -39,6 +39,7 @@ struct crypto_buffer_st {
struct crypto_buffer_pool_st { struct crypto_buffer_pool_st {
LHASH_OF(CRYPTO_BUFFER) *bufs; LHASH_OF(CRYPTO_BUFFER) *bufs;
CRYPTO_MUTEX lock; CRYPTO_MUTEX lock;
const uint64_t hash_key[2];
}; };

@ -19,6 +19,8 @@
#include <openssl/bytestring.h> #include <openssl/bytestring.h>
#include <openssl/mem.h> #include <openssl/mem.h>
#include <openssl/rand.h>
#include <openssl/siphash.h>
#include <openssl/thread.h> #include <openssl/thread.h>
#include "../internal.h" #include "../internal.h"
@ -26,10 +28,13 @@
static uint32_t CRYPTO_BUFFER_hash(const CRYPTO_BUFFER *buf) { 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) { 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) { if (a->len != b->len) {
return 1; return 1;
} }
@ -50,6 +55,7 @@ CRYPTO_BUFFER_POOL* CRYPTO_BUFFER_POOL_new(void) {
} }
CRYPTO_MUTEX_init(&pool->lock); CRYPTO_MUTEX_init(&pool->lock);
RAND_bytes((uint8_t *)&pool->hash_key, sizeof(pool->hash_key));
return pool; return pool;
} }
@ -84,6 +90,7 @@ static CRYPTO_BUFFER *crypto_buffer_new(const uint8_t *data, size_t len,
CRYPTO_BUFFER tmp; CRYPTO_BUFFER tmp;
tmp.data = (uint8_t *) data; tmp.data = (uint8_t *) data;
tmp.len = len; tmp.len = len;
tmp.pool = pool;
CRYPTO_MUTEX_lock_read(&pool->lock); CRYPTO_MUTEX_lock_read(&pool->lock);
CRYPTO_BUFFER *duplicate = lh_CRYPTO_BUFFER_retrieve(pool->bufs, &tmp); CRYPTO_BUFFER *duplicate = lh_CRYPTO_BUFFER_retrieve(pool->bufs, &tmp);

@ -41,6 +41,7 @@
#include <openssl/nid.h> #include <openssl/nid.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include <openssl/siphash.h>
#include <openssl/trust_token.h> #include <openssl/trust_token.h>
#if defined(OPENSSL_WINDOWS) #if defined(OPENSSL_WINDOWS)
@ -561,20 +562,20 @@ static bool SpeedAESBlock(const std::string &name, unsigned bits,
static bool SpeedHashChunk(const EVP_MD *md, std::string name, static bool SpeedHashChunk(const EVP_MD *md, std::string name,
size_t chunk_len) { size_t chunk_len) {
bssl::ScopedEVP_MD_CTX ctx; 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; return false;
} }
name += ChunkLenSuffix(chunk_len); name += ChunkLenSuffix(chunk_len);
TimeResults results; 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]; uint8_t digest[EVP_MAX_MD_SIZE];
unsigned int md_len; unsigned int md_len;
return EVP_DigestInit_ex(ctx.get(), md, NULL /* ENGINE */) && 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); EVP_DigestFinal_ex(ctx.get(), digest, &md_len);
})) { })) {
fprintf(stderr, "EVP_DigestInit_ex failed.\n"); fprintf(stderr, "EVP_DigestInit_ex failed.\n");
@ -1035,6 +1036,29 @@ static bool SpeedBase64(const std::string &selected) {
return true; 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( static TRUST_TOKEN_PRETOKEN *trust_token_pretoken_dup(
TRUST_TOKEN_PRETOKEN *in) { TRUST_TOKEN_PRETOKEN *in) {
TRUST_TOKEN_PRETOKEN *out = TRUST_TOKEN_PRETOKEN *out =
@ -1434,7 +1458,8 @@ bool Speed(const std::vector<std::string> &args) {
TRUST_TOKEN_experiment_v2_pmb(), 1, selected) || TRUST_TOKEN_experiment_v2_pmb(), 1, selected) ||
!SpeedTrustToken("TrustToken-Exp2PMB-Batch10", !SpeedTrustToken("TrustToken-Exp2PMB-Batch10",
TRUST_TOKEN_experiment_v2_pmb(), 10, selected) || TRUST_TOKEN_experiment_v2_pmb(), 10, selected) ||
!SpeedBase64(selected)) { !SpeedBase64(selected) ||
!SpeedSipHash(selected)) {
return false; return false;
} }
#if defined(BORINGSSL_FIPS) #if defined(BORINGSSL_FIPS)

Loading…
Cancel
Save