This is software for a research prototype. Please do NOT use this code in production.
We only performed minimal testing that are necessary to ensure the validity of our benchmark claims (to the best of our knowledge), using only random inputs to select functions. Therefore, the software may contain (but is not limited to) memory leaks, memory errors (e.g., null pointer dereference), and other (security) bugs/vulnerabilities, especially when used as a library in untested use cases.
This is an artifact repository for "VROOM: Accelerating (Almost All) Number-Theoretic Cryptography Using Vectorization and the Residue Number System", a new modular multiplication algorithm to appear in USENIX Security 2026. You can find the most up-to-date full version of the paper here.
In this artifact, we forked commit 3fb010b from upstream BoringSSL, and modified it to use VROOM for modular multiplication.
This repository reproduces the CPU evaluation of the paper, specifically:
| Paper section | Claim | How to reproduce |
|---|---|---|
| 6.1 Modular multiplication | Latency vs. modulus size (figure) | ./reproduce.sh modmul |
| 6.2 Modular exponentiation | Public-e, secret-e, and RSA-CRT tables |
./reproduce.sh modexp and ./reproduce.sh rsacrt |
| 6.3 RSA signatures | RSA sign/verify latency table | ./reproduce.sh rsa |
It does not cover the elliptic-curve / pairing results (Section 6.4 onward) or
the GPU results; those live in separate repositories (see the paper's Open Science
appendix). All CPU numbers above come from a single benchmark binary,
./build/bssl_bench.
Baseline coverage. bssl_bench directly produces the VROOM, BoringSSL,
and FLINT columns of every table/figure above. The paper also reports an
OpenSSL column (all sections) and an Arkworks line (Section 6.1); those are
separate baselines — see Baselines below.
We tested on an AWS c7i.metal-24xl instance (Intel Xeon Platinum 8488C,
"Sapphire Rapids") running Amazon Linux 2023, with Clang 21.1.8 (the official
LLVM 21.1.8 prebuilt release, installed under $HOME by ./install_deps.sh; see
Prerequisites). The only hard hardware requirement is a CPU
with the AVX-512 IFMA instruction set (avx512ifma); without it the build's
RNS code path will not run. The relative speedups also reproduce on the much cheaper
c7i-flex.large instance (also AVX-512 IFMA), albeit with slightly slower absolute
times due to virtualization.
In addition to the standard BoringSSL build tooling (CMake ≥ 3.x, Ninja, a C/C++
toolchain), this repository benchmarks FLINT 3.2.1 as a
baseline, which requires FLINT and its dependency GMP (plus
MPFR) to be installed. Note that the VROOM code itself does not rely on GMP or
FLINT — it uses only (constant-time) BN_* subroutines from BoringSSL for
multiplication and radix↔RNS conversion, to the best of our knowledge.
On a fresh Amazon Linux 2023 machine you can install everything with:
./install_deps.sh
The script installs, without root, into your home directory: Clang 21.1.8
(the official LLVM prebuilt release, sha256-checked) under
$HOME/LLVM-21.1.8-Linux-X64, FLINT 3.2.1 plus Google Benchmark (the
latter only needed for the OpenSSL baseline below) built from source under
$HOME/.local, and Rust/cargo 1.86.0 (via rustup, only needed for the
Arkworks baseline below) under $HOME/.cargo and $HOME/.rustup. The only step
that uses sudo is installing the base OS build tooling and the GMP/MPFR
development headers via the system package manager. The script is idempotent and
skips anything already present.
When it finishes it prints the export lines (PATH, plus CMAKE_PREFIX_PATH,
PKG_CONFIG_PATH, LD_LIBRARY_PATH) that let subsequent builds find the
home-installed toolchain and libraries; load them into your shell with:
eval "$(./install_deps.sh --print)"
(./configure.sh and ./reproduce.sh also set these automatically.)
Build the benchmark binary with a single command from the repository root:
./configure.sh
This produces ./build/bssl_bench and takes roughly 2–5 minutes on the
evaluation machine. There is nothing else to memorize: configure.sh selects the
Release build type (required for accurate timings) and the home-installed
Clang 21.1.8 / FLINT for you. It is deliberately short — if you want to see exactly
which compiler and CMake flags are used, just read configure.sh
(it is under 20 lines). Override CC/CXX (or LLVM_PREFIX) if your toolchain
lives elsewhere.
All experiments are pinned to a single core with taskset -c 0, as in the paper.
The simplest path is the one-shot driver, which builds (if needed) and runs every CPU
experiment, with each block labelled by the paper section it corresponds to:
./reproduce.sh # all CPU sections; ~30 min (dominated by the 6.1 sweep)
./reproduce.sh modmul # Section 6.1 only (MODMUL_QUICK=1 for a ~1-min subset)
./reproduce.sh modexp # Section 6.2 generic exponentiation
./reproduce.sh rsacrt # Section 6.2 RSA-CRT exponentiation
./reproduce.sh rsa # Section 6.3 RSA sign/verify (~1 min)
./reproduce.sh arkworks # Section 6.1 Arkworks baseline (Rust/cargo from ./install_deps.sh)
If you prefer to invoke the binary directly, the relevant Google Benchmark filters are listed below. The benchmark name → paper-column mapping is:
Benchmark name (--benchmark_filter) |
Paper column | Section |
|---|---|---|
BM_RNSRingMultiplication<bits> |
VROOM | 6.1 |
BM_BSSLModMulMontgomery/bits |
BN_mod_mul_montgomery (BoringSSL/OpenSSL) |
6.1 |
BM_FLINTMPN<limbs> (≤1024-bit, mpn_mod_mul) + BM_FLINTFMPZRing/bits (fmpz_mod_mul) |
FLINT | 6.1 |
BM_RNSModExpRSAE/bits, BM_BSSLModExpRSAE/bits, BM_FLINTExponentiationRSAE/bits |
VROOM / BoringSSL / FLINT, public e=65537 |
6.2 |
BM_RNSExponentiation<bits, window>, BM_BSSLModExpConsttime/bits, BM_FLINTExponentiation/bits |
VROOM (best window) / BoringSSL / FLINT, secret exponent | 6.2 |
BM_SpeedRNSRSAModExpCRT/bits, BM_SpeedRSAModExpCRT/bits |
VROOM / BoringSSL, RSA-CRT | 6.2 |
BM_SpeedRNSRSASign/BM_SpeedRNSRSAVerify, BM_SpeedRSASign/BM_SpeedRSAVerify |
VROOM / BoringSSL, RSA sign/verify | 6.3 |
For example, the Section 6.3 table is produced by:
taskset -c 0 ./build/bssl_bench \
--benchmark_filter='BM_SpeedRSASign|BM_SpeedRNSRSASign|BM_SpeedRSAVerify|BM_SpeedRNSRSAVerify' \
--benchmark_time_unit=us
Absolute timings depend on the hardware and on small run-to-run variation; the relative speedup of VROOM over each baseline is the paper's claim. Resource use is modest (single core, well under 1 GB of RAM); the long pole is wall-clock time for the Section 6.1 sweep.
- VROOM, BoringSSL, FLINT — reproduced directly by
bssl_bench(above). - Arkworks (Section 6.1 only) — a separate Rust project under
baselines/arkworks; run it with./reproduce.sh arkworks(orcd baselines/arkworks && cargo bench --bench bench_arkworks). Eachmul <bits>Criterion result is one point of the Arkworks line in the figure. - OpenSSL (all sections) — a separate fork of OpenSSL under
baselines/openssl, which exposes a few internal symbols and adds a Google Benchmark harness so the exact OpenSSL functions the paper compares against can be measured (VROOM itself is not used there). Run it with./reproduce.sh openssl [section](wheresectionis one ofmodmul,modexp,rsacrt,rsa, orall); this fetches the baseline as a git submodule on demand the first time it is requested, builds OpenSSL and the benchmarks, and prints the OpenSSL column of each table/figure. Seebaselines/openssl/README.mdfor details and the benchmark-name → paper-column mapping.
The core VROOM code is in the subfolder rns/; the modular-arithmetic
benchmarks are in bench/. We also modified the BoringSSL library sources
that handle RSA signing/verification and Montgomery exponentiation to optionally use
VROOM (selected at runtime via BN_MONT_CTX_set_use_rns / RSA_set_use_rns), so the
BM_RNS* benchmarks and their non-RNS counterparts exercise the same code paths with
only the multiplication backend swapped.
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:
- PORTING.md: how to port OpenSSL-using code to BoringSSL.
- BUILDING.md: how to build BoringSSL
- INCORPORATING.md: how to incorporate BoringSSL into a project.
- API-CONVENTIONS.md: general API conventions for BoringSSL consumers and developers.
- STYLE.md: rules and guidelines for coding style.
- include/openssl: public headers with API documentation in comments. Also available online.
- FUZZING.md: information about fuzzing BoringSSL.
- CONTRIBUTING.md: how to contribute to BoringSSL.
- BREAKING-CHANGES.md: notes on potentially-breaking changes.
- SANDBOXING.md: notes on using BoringSSL in a sandboxed environment.