Pack SHA-512 and BLAKE2b a little more tightly. Honestly, we don't actually need to support hashing more than 2**64 bytes on a single machine, so we certainly don't need to support 2**128 bytes. Thus pack these structures a little better by supporting only 2**96 bytes. This removes 8 bytes from these structures and thus 24 bytes from an HMAC_CTX. It's possible to pack SHA-512 even tighter: the final byte of the block buffer isn't used between calls. It can be repurposed to store the buffer length (in the lower seven bits) and an "is SHA-384" flag in the MSB. That saves another eight bytes. But the same trick doesn't work for BLAKE2b because it hashes in a "final block" flag and thus needs to know whether there's more data coming before hashing a block. Thus it uses all 128 bytes for storage. So while we can pack SHA-512 tighter, BLAKE2b would still keep EVP_MAX_MD_DATA_SIZE the same. Pleasingly, this seems net-positive on benchmarks. (Or, at least, not negative.) Before: Did 49145000 SHA-512 (16 bytes) operations in 5000055us (9828891.9 ops/sec): 157.3 MB/s Did 17905000 SHA-512 (256 bytes) operations in 5000134us (3580904.0 ops/sec): 916.7 MB/s Did 5091000 SHA-512 (1350 bytes) operations in 5000183us (1018162.7 ops/sec): 1374.5 MB/s Did 871000 SHA-512 (8192 bytes) operations in 5004110us (174056.9 ops/sec): 1425.9 MB/s Did 440000 SHA-512 (16384 bytes) operations in 5008994us (87842.0 ops/sec): 1439.2 MB/s After: Did 50435000 SHA-512 (16 bytes) operations in 5000060us (10086879.0 ops/sec): 161.4 MB/s Did 18218000 SHA-512 (256 bytes) operations in 5000068us (3643550.4 ops/sec): 932.7 MB/s Did 5126000 SHA-512 (1350 bytes) operations in 5000588us (1025079.5 ops/sec): 1383.9 MB/s Did 872000 SHA-512 (8192 bytes) operations in 5002028us (174329.3 ops/sec): 1428.1 MB/s Did 440000 SHA-512 (16384 bytes) operations in 5004069us (87928.4 ops/sec): 1440.6 MB/s Change-Id: Ib996d82cff3e959993a9e553a688766c2e9052fb Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/79508 Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: Adam Langley <agl@google.com>
diff --git a/crypto/fipsmodule/digest/digest.cc.inc b/crypto/fipsmodule/digest/digest.cc.inc index 82cc00a..0b206be 100644 --- a/crypto/fipsmodule/digest/digest.cc.inc +++ b/crypto/fipsmodule/digest/digest.cc.inc
@@ -97,6 +97,10 @@ OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_INPUT_NOT_INITIALIZED); return 0; } + if (out == in) { + OPENSSL_PUT_ERROR(DIGEST, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } EVP_PKEY_CTX *pctx = NULL; assert(in->pctx == NULL || in->pctx_ops != NULL);
diff --git a/crypto/fipsmodule/sha/sha512.cc.inc b/crypto/fipsmodule/sha/sha512.cc.inc index 4254f23..0c46df1 100644 --- a/crypto/fipsmodule/sha/sha512.cc.inc +++ b/crypto/fipsmodule/sha/sha512.cc.inc
@@ -40,8 +40,8 @@ sha->h[6] = UINT64_C(0xdb0c2e0d64f98fa7); sha->h[7] = UINT64_C(0x47b5481dbefa4fa4); - sha->Nl = 0; - sha->Nh = 0; + sha->bytes_so_far_low = 0; + sha->bytes_so_far_high = 0; sha->num = 0; sha->md_len = BCM_SHA384_DIGEST_LENGTH; return bcm_infallible::approved; @@ -58,8 +58,8 @@ sha->h[6] = UINT64_C(0x1f83d9abfb41bd6b); sha->h[7] = UINT64_C(0x5be0cd19137e2179); - sha->Nl = 0; - sha->Nh = 0; + sha->bytes_so_far_low = 0; + sha->bytes_so_far_high = 0; sha->num = 0; sha->md_len = BCM_SHA512_DIGEST_LENGTH; return bcm_infallible::approved; @@ -75,8 +75,8 @@ sha->h[6] = UINT64_C(0x2b0199fc2c85b8aa); sha->h[7] = UINT64_C(0x0eb72ddc81c52ca2); - sha->Nl = 0; - sha->Nh = 0; + sha->bytes_so_far_low = 0; + sha->bytes_so_far_high = 0; sha->num = 0; sha->md_len = BCM_SHA512_256_DIGEST_LENGTH; return bcm_infallible::approved; @@ -124,7 +124,6 @@ bcm_infallible BCM_sha512_update(SHA512_CTX *c, const void *in_data, size_t len) { - uint64_t l; uint8_t *p = c->p; const uint8_t *data = reinterpret_cast<const uint8_t *>(in_data); @@ -132,14 +131,10 @@ return bcm_infallible::approved; } - l = (c->Nl + (((uint64_t)len) << 3)) & UINT64_C(0xffffffffffffffff); - if (l < c->Nl) { - c->Nh++; + c->bytes_so_far_low += len; + if (c->bytes_so_far_low < len) { + c->bytes_so_far_high++; } - if (sizeof(len) >= 8) { - c->Nh += (((uint64_t)len) >> 61); - } - c->Nl = l; if (c->num != 0) { size_t n = sizeof(c->p) - c->num; @@ -195,8 +190,11 @@ } OPENSSL_memset(p + n, 0, sizeof(sha->p) - 16 - n); - CRYPTO_store_u64_be(p + sizeof(sha->p) - 16, sha->Nh); - CRYPTO_store_u64_be(p + sizeof(sha->p) - 8, sha->Nl); + const uint64_t Nh = (uint64_t{sha->bytes_so_far_high} << 3) | + (sha->bytes_so_far_low >> (64 - 3)); + const uint64_t Nl = sha->bytes_so_far_low << 3; + CRYPTO_store_u64_be(p + sizeof(sha->p) - 16, Nh); + CRYPTO_store_u64_be(p + sizeof(sha->p) - 8, Nl); sha512_block_data_order(sha->h, p, 1);
diff --git a/include/openssl/bcm_public.h b/include/openssl/bcm_public.h index c5326e2..e2c0a93 100644 --- a/include/openssl/bcm_public.h +++ b/include/openssl/bcm_public.h
@@ -15,7 +15,7 @@ #ifndef OPENSSL_HEADER_BCM_PUBLIC_H_ #define OPENSSL_HEADER_BCM_PUBLIC_H_ -#include <openssl/base.h> // IWYU pragma: export +#include <openssl/base.h> // IWYU pragma: export #if defined(__cplusplus) extern "C" { @@ -69,9 +69,10 @@ struct sha512_state_st { uint64_t h[8]; - uint64_t Nl, Nh; + uint16_t num, md_len; + uint32_t bytes_so_far_high; + uint64_t bytes_so_far_low; uint8_t p[BCM_SHA512_CBLOCK]; - unsigned num, md_len; };
diff --git a/include/openssl/blake2.h b/include/openssl/blake2.h index 5378fc3..163869e 100644 --- a/include/openssl/blake2.h +++ b/include/openssl/blake2.h
@@ -15,7 +15,7 @@ #ifndef OPENSSL_HEADER_BLAKE2_H #define OPENSSL_HEADER_BLAKE2_H -#include <openssl/base.h> // IWYU pragma: export +#include <openssl/base.h> // IWYU pragma: export #if defined(__cplusplus) extern "C" { @@ -27,9 +27,10 @@ struct blake2b_state_st { uint64_t h[8]; - uint64_t t_low, t_high; + uint64_t t_low; + uint32_t t_high; + uint32_t block_used; uint8_t block[BLAKE2B_CBLOCK]; - size_t block_used; }; // BLAKE2B256_Init initialises |b2b| to perform a BLAKE2b-256 hash. There are no
diff --git a/include/openssl/digest.h b/include/openssl/digest.h index 2db31de..710c6e6 100644 --- a/include/openssl/digest.h +++ b/include/openssl/digest.h
@@ -290,7 +290,7 @@ // EVP_MAX_MD_DATA_SIZE is a private constant which specifies the size of the // largest digest state. SHA-512 and BLAKE2b are joint-largest. Consuming code // only uses this via the `EVP_MD_CTX` type. -#define EVP_MAX_MD_DATA_SIZE 216 +#define EVP_MAX_MD_DATA_SIZE 208 // env_md_ctx_st is typoed ("evp" -> "env"), but the typo comes from OpenSSL // and some consumers forward-declare these structures so we're leaving it