Skip to content

Commit 5dd4afe

Browse files
authored
p384: use crypto-bigint by default for field arithmetic (#1808)
When `p384_backend="bigint"` backend was added in #1548, it was made opt-in, as were similar features added to other crates. This was largely because the `crypto-bigint` code is relatively immature and the existing `fiat-crypto` backend is formally verified. However, the amount of code generated for `fiat-crypto` for a curve like P-384 is quite large. The 32-bit backends are >=10 klocs per field, and the 64-bit ones are nearly 4 klocs. This is large enough to have caused issues in the past: see #906, the upstream issue rust-lang/rust#113612, and its upstream issue llvm/llvm-project#76920. Another example is #1034. Part of the problem is `fiat-crypto` always unrolls all loops, even when the field modulus is quite large and it would make more sense both in terms of compile times and being more optimizer-friendly to reduce the generated code size by not unrolling loops. Switching to `p384` should make the implementation both faster to compile and faster at runtime, with the downside of potential bugs in the implementation. Below are some benchmarks showing the improvements: point operations/point-scalar mul time: [370.08 µs 370.73 µs 371.38 µs] change: [−19.596% −19.042% −18.501%] (p = 0.00 < 0.05) Performance has improved. scalar operations/generator-scalar mul time: [97.359 µs 97.552 µs 97.745 µs] change: [−13.964% −13.130% −12.088%] (p = 0.00 < 0.05) Performance has improved. scalar operations/generator-scalar mul (variable-time) time: [80.252 µs 80.407 µs 80.564 µs] change: [−17.652% −16.304% −15.270%] (p = 0.00 < 0.05) Performance has improved. scalar operations/invert time: [4.3291 µs 4.3379 µs 4.3463 µs] change: [−86.748% −86.646% −86.538%] (p = 0.00 < 0.05) Performance has improved.
1 parent f00bbc0 commit 5dd4afe

5 files changed

Lines changed: 22 additions & 21 deletions

File tree

.github/workflows/p384.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ jobs:
100100
- run: cargo test --release --target ${{ matrix.target }}
101101
- run: cargo test --release --target ${{ matrix.target }} --all-features
102102
- env:
103-
RUSTFLAGS: '--cfg p384_backend="bigint"'
104-
RUSTDOCFLAGS: '--cfg p384_backend="bigint"'
103+
RUSTFLAGS: '--cfg p384_backend="fiat"'
104+
RUSTDOCFLAGS: '--cfg p384_backend="fiat"'
105105
run: cargo test --release --target ${{ matrix.target }} --all-features
106106

107107
cross:

p384/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ primeorder = { version = "0.14.0-rc.11", optional = true }
2929
serdect = { version = "0.4", optional = true, default-features = false }
3030
sha2 = { version = "0.11", optional = true, default-features = false }
3131

32-
[target.'cfg(not(p384_backend = "bigint"))'.dependencies]
32+
[target.'cfg(p384_backend = "fiat")'.dependencies]
3333
fiat-crypto = { version = "0.3", default-features = false }
3434

3535
[dev-dependencies]

p384/src/arithmetic/field.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ use elliptic_curve::{
1919
// Default backend: fiat-crypto
2020
cpubits! {
2121
32 => {
22-
#[cfg(not(p384_backend = "bigint"))]
22+
#[cfg(p384_backend = "fiat")]
2323
use fiat_crypto::p384_32::*;
2424
}
2525
64 => {
26-
#[cfg(not(p384_backend = "bigint"))]
26+
#[cfg(p384_backend = "fiat")]
2727
use fiat_crypto::p384_64::*;
2828
}
2929
}
@@ -48,14 +48,14 @@ primefield::monty_field_element! {
4848
doc: "Element in the finite field modulo `p = 2^{384} − 2^{128} − 2^{96} + 2^{32} − 1`."
4949
}
5050

51-
#[cfg(p384_backend = "bigint")]
51+
#[cfg(not(p384_backend = "fiat"))]
5252
primefield::monty_field_arithmetic! {
5353
name: FieldElement,
5454
params: FieldParams,
5555
uint: U384
5656
}
5757

58-
#[cfg(not(p384_backend = "bigint"))]
58+
#[cfg(p384_backend = "fiat")]
5959
primefield::fiat_monty_field_arithmetic! {
6060
name: FieldElement,
6161
params: FieldParams,
@@ -78,15 +78,15 @@ primefield::fiat_monty_field_arithmetic! {
7878
#[cfg(test)]
7979
mod tests {
8080
use super::{FieldElement, U384};
81-
#[cfg(not(p384_backend = "bigint"))]
81+
#[cfg(p384_backend = "fiat")]
8282
use super::{
8383
FieldParams, fiat_p384_montgomery_domain_field_element, fiat_p384_msat,
8484
fiat_p384_non_montgomery_domain_field_element, fiat_p384_to_montgomery,
8585
};
8686

8787
primefield::test_primefield!(FieldElement, U384);
8888

89-
#[cfg(not(p384_backend = "bigint"))]
89+
#[cfg(p384_backend = "fiat")]
9090
primefield::test_fiat_monty_field_arithmetic!(
9191
name: FieldElement,
9292
params: FieldParams,

p384/src/arithmetic/scalar.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ use elliptic_curve::{
2222

2323
cpubits! {
2424
32 => {
25-
#[cfg(not(p384_backend = "bigint"))]
25+
#[cfg(p384_backend = "fiat")]
2626
use fiat_crypto::p384_scalar_32::*;
2727
}
2828
64 => {
29-
#[cfg(not(p384_backend = "bigint"))]
29+
#[cfg(p384_backend = "fiat")]
3030
use fiat_crypto::p384_scalar_64::*;
3131
}
3232
}
@@ -56,14 +56,14 @@ primefield::monty_field_element! {
5656
doc: "Element in the NIST P-384 scalar field modulo `n`."
5757
}
5858

59-
#[cfg(p384_backend = "bigint")]
59+
#[cfg(not(p384_backend = "fiat"))]
6060
primefield::monty_field_arithmetic! {
6161
name: Scalar,
6262
params: ScalarParams,
6363
uint: U384
6464
}
6565

66-
#[cfg(not(p384_backend = "bigint"))]
66+
#[cfg(p384_backend = "fiat")]
6767
primefield::fiat_monty_field_arithmetic! {
6868
name: Scalar,
6969
params: ScalarParams,
@@ -162,7 +162,7 @@ impl<'de> Deserialize<'de> for Scalar {
162162
#[cfg(test)]
163163
mod tests {
164164
use super::{Scalar, U384};
165-
#[cfg(not(p384_backend = "bigint"))]
165+
#[cfg(p384_backend = "fiat")]
166166
use super::{
167167
ScalarParams, fiat_p384_scalar_montgomery_domain_field_element, fiat_p384_scalar_msat,
168168
fiat_p384_scalar_non_montgomery_domain_field_element, fiat_p384_scalar_to_montgomery,
@@ -178,7 +178,7 @@ mod tests {
178178

179179
primefield::test_primefield!(Scalar, U384);
180180

181-
#[cfg(not(p384_backend = "bigint"))]
181+
#[cfg(p384_backend = "fiat")]
182182
primefield::test_fiat_monty_field_arithmetic!(
183183
name: Scalar,
184184
params: ScalarParams,

p384/src/lib.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,24 @@
1111
//! ## Backends
1212
//!
1313
//! This crate has support for two different field arithmetic backends which can be selected using
14-
//! `cfg(p384_backend)`, e.g. to select the `bigint` backend:
14+
//! `cfg(p384_backend)`, e.g. to select the formally verified `fiat` backend:
1515
//!
1616
//! ```console
17-
//! $ RUSTFLAGS='--cfg p384_backend="bigint"' cargo test
17+
//! $ RUSTFLAGS='--cfg p384_backend="fiat"' cargo test
1818
//! ```
1919
//!
2020
//! Or it can be set through [`.cargo/config`][buildrustflags]:
2121
//!
2222
//! ```toml
2323
//! [build]
24-
//! rustflags = ['--cfg', 'p384_backend="bigint"']
24+
//! rustflags = ['--cfg', 'p384_backend="fiat"']
2525
//! ```
2626
//!
2727
//! The available backends are:
28-
//! - `bigint`: experimental backend provided by [crypto-bigint]. May offer better performance in
29-
//! some cases along with smaller code size, but might also have bugs.
30-
//! - `fiat` (default): formally verified implementation synthesized by [fiat-crypto] which should
28+
//! - `bigint` (default): backend provided by [crypto-bigint], which should provide better
29+
//! performance as well as smaller code size and fewer dependencies, but isn't formally verified
30+
//! and may contain bugs
31+
//! - `fiat`: formally verified implementation synthesized by [fiat-crypto] which should
3132
//! be correct for all inputs (though there's a possibility of bugs in the code which glues to it)
3233
//!
3334
//! [buildrustflags]: https://doc.rust-lang.org/cargo/reference/config.html#buildrustflags

0 commit comments

Comments
 (0)