Precompute the PK.seed SHA-256 state in SLH-DSA-SHA2

In the SHA2 instantiation of SLH-DSA (FIPS 205, section 11.2), every
call to F, H, T_l, T_k and PRF starts by hashing
PK.seed || toByte(0, 64 - n). That is exactly one SHA-256 block, and it
is the same for every call made with a given key. The SPHINCS+ round
3.1 specification (section 8.1.6) pads PK.seed to a full block for this
reason, so that implementations can compute the state after that block
once instead of on every call.

Compute that state once per key generation, signing or verification
operation and keep it, with PK.seed, in a new slhdsa_hash_ctx. The
context replaces the raw PK.seed argument of the internal WOTS+, FORS,
XMSS and thash functions.

After the cached block, the rest of an F, H or PRF input (ADRSc and one
or two n-byte values) fits in a single block together with the SHA-256
padding. Build that block directly and process it with one call to
BCM_sha256_transform_blocks, rather than going through SHA256_Update
and SHA256_Final. For PRF calls the block contains SK.seed, and for F
calls it can contain secret WOTS+ or FORS values, so clear it with
OPENSSL_cleanse afterwards. Previously, SHA256_Final cleared the
equivalent buffer. T_l and T_k still use SHA256_Update and
SHA256_Final, starting from the precomputed state.

The output is unchanged, and so are the self-test known-answer values.
The fast path does not call SHA256_Final, so it does not update the
FIPS service indicator. Every SLH-DSA operation still calls
SHA256_Final at least once (for T_l, and for H_msg when signing or
verifying), so the indicator still moves during each operation, as it
did before. SLH-DSA-SHAKE-256f is not affected.

SLH-DSA-SHA2-128s on an Intel Xeon at 2.0 GHz without SHA-NI, median
of 15 runs:

           Before      After       Speedup
  keygen    158.3 ms    74.7 ms    2.12x
  sign     1204.6 ms   568.1 ms    2.12x
  verify    1.176 ms   0.565 ms    2.08x

Change-Id: Ib57a2fd38a113d65f2e0b3bbf03b884b616941ae
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/104029
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
9 files changed
tree: 68526bcae2a2ce95476c03ef546db87ab0a91ab0
  1. .agents/
  2. .bcr/
  3. .github/
  4. _agents/
  5. bench/
  6. cmake/
  7. crypto/
  8. decrepit/
  9. docs/
  10. fuzz/
  11. gen/
  12. include/
  13. infra/
  14. pki/
  15. rust/
  16. ssl/
  17. third_party/
  18. tool/
  19. util/
  20. .bazelignore
  21. .bazelrc
  22. .bazelversion
  23. .clang-format
  24. .clang-format-ignore
  25. .clangd
  26. .gitattributes
  27. .gitignore
  28. API-CONVENTIONS.md
  29. AUTHORS
  30. BREAKING-CHANGES.md
  31. BUILD.bazel
  32. build.json
  33. BUILDING.md
  34. CMakeLists.txt
  35. codereview.settings
  36. CONTRIBUTING.md
  37. FUZZING.md
  38. go.mod
  39. go.sum
  40. INCORPORATING.md
  41. LICENSE
  42. MODULE.bazel
  43. MODULE.bazel.lock
  44. PORTING.md
  45. PRESUBMIT.py
  46. PrivacyInfo.xcprivacy
  47. README.md
  48. SANDBOXING.md
  49. SECURITY.md
  50. STYLE.md
README.md

BoringSSL

BoringSSL is a fork of OpenSSL that is designed to meet Google's needs.

Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing so is likely to be frustrating because there are no guarantees of API or ABI stability.

Programs ship their own copies of BoringSSL when they use it and we update everything as needed when deciding to make API changes. This allows us to mostly avoid compromises in the name of compatibility. It works for us, but it may not work for you.

BoringSSL arose because Google used OpenSSL for many years in various ways and, over time, built up a large number of patches that were maintained while tracking upstream OpenSSL. As Google's product portfolio became more complex, more copies of OpenSSL sprung up and the effort involved in maintaining all these patches in multiple places was growing steadily.

Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's not part of the NDK) and a number of other apps/programs.

Project links:

To file a security issue, use the Chromium process and mention in the report this is for BoringSSL. You can ignore the parts of the process that are specific to Chromium/Chrome.

There are other files in this directory which might be helpful: