Skip to content

Commit 111faa7

Browse files
authored
Merge branch 'elligator2-ntor' into ctgt-fix
2 parents 10f829a + 924988a commit 111faa7

28 files changed

+454
-114
lines changed

curve25519-dalek/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
Entries are listed in reverse chronological order per undeprecated
44
major series.
55

6+
## Unreleased
7+
8+
* Move AVX-512 backend selection logic to a separate CFG flag that requires nightly
9+
610
## 4.x series
711

812
### 4.1.3

curve25519-dalek/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ ff = { version = "0.13", default-features = false, optional = true }
5454
group = { version = "0.13", default-features = false, optional = true }
5555
rand_core = { version = "0.6.4", default-features = false, optional = true }
5656
digest = { version = "0.10", default-features = false, optional = true }
57-
subtle = { version = "2.6.0", default-features = false }
57+
subtle = { version = "2.6.0", default-features = false, features = ["const-generics"]}
5858
serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] }
5959
zeroize = { version = "1", default-features = false, optional = true }
6060

@@ -81,7 +81,7 @@ curve25519-dalek-derive = { version = "0.1", path = "../curve25519-dalek-derive"
8181
level = "warn"
8282
check-cfg = [
8383
'cfg(allow_unused_unsafe)',
84-
'cfg(curve25519_dalek_backend, values("fiat", "serial", "simd"))',
84+
'cfg(curve25519_dalek_backend, values("fiat", "serial", "simd", "unstable_avx512"))',
8585
'cfg(curve25519_dalek_diagnostics, values("build"))',
8686
'cfg(curve25519_dalek_bits, values("32", "64"))',
8787
'cfg(nightly)',

curve25519-dalek/README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,12 @@ This release also does a lot of dependency updates and relaxations to unblock up
9191

9292
Curve arithmetic is implemented and used by one of the following backends:
9393

94-
| Backend | Selection | Implementation | Bits / Word sizes |
95-
| :--- | :--- | :--- | :--- |
96-
| `serial` | Automatic | An optimized, non-parllel implementation | `32` and `64` |
97-
| `fiat` | Manual | Formally verified field arithmetic from [fiat-crypto] | `32` and `64` |
98-
| `simd` | Automatic | Intel AVX2 / AVX512 IFMA accelerated backend | `64` only |
94+
| Backend | Selection | Implementation | Bits / Word sizes |
95+
| :--- | :--- | :--- | :--- |
96+
| `serial` | Automatic | An optimized, non-parllel implementation | `32` and `64` |
97+
| `fiat` | Manual | Formally verified field arithmetic from [fiat-crypto] | `32` and `64` |
98+
| `simd` | Automatic | Intel AVX2 accelerated backend | `64` only |
99+
| `unstable_avx512` | Manual | Intel AVX512 IFMA accelerated backend (requires nightly) | `64` only |
99100

100101
At runtime, `curve25519-dalek` selects an arithmetic backend from the set of backends it was compiled to support. For Intel x86-64 targets, unless otherwise specified, it will build itself with `simd` support, and default to `serial` at runtime if the appropriate CPU features aren't detected. See [SIMD backend] for more details.
101102

@@ -149,16 +150,16 @@ $ cargo build --target i686-unknown-linux-gnu
149150

150151
## SIMD backend
151152

152-
The specific SIMD backend (AVX512 / AVX2 / `serial` default) is selected automatically at runtime, depending on the currently available CPU features, and whether Rust nightly is being used for compilation. The precise conditions are specified below.
153+
When the `simd` backend is selected, the AVX2 or `serial` implementation is selected automatically at runtime, depending on the currently available CPU features. Similarly, when the `unstable_avx512` backend is selected, the AVX512 implementation is selected automatically at runtime if available, or else selection falls through to the aforementioned `simd` backend logic.
153154

154155
For a given CPU feature, you can also specify an appropriate `-C target_feature` to build a binary which assumes the required SIMD instructions are always available. Don't do this if you don't have a good reason.
155156

156157
| Backend | `RUSTFLAGS` | Requires nightly? |
157158
| :--- | :--- | :--- |
158-
| avx2 | `-C target_feature=+avx2` | no |
159-
| avx512 | `-C target_feature=+avx512ifma,+avx512vl` | yes |
159+
| AVX2 | `-C target_feature=+avx2` | no |
160+
| AVX512 | `-C target_feature=+avx512ifma,+avx512vl` | yes |
160161

161-
If compiled on a non-nightly compiler, `curve25519-dalek` will not include AVX512 code, and therefore will never select it at runtime.
162+
To reiterate, the `simd` backend will NOT use AVX512 code under any circumstance. The only way to enable AVX512 currently is to select the `unstable_avx512` backend and use a nightly compiler.
162163

163164
# Documentation
164165

curve25519-dalek/build.rs

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,16 @@ fn main() {
3535

3636
println!("cargo:rustc-cfg=curve25519_dalek_bits=\"{curve25519_dalek_bits}\"");
3737

38-
if rustc_version::version_meta()
38+
let nightly = if rustc_version::version_meta()
3939
.expect("failed to detect rustc version")
4040
.channel
4141
== rustc_version::Channel::Nightly
4242
{
4343
println!("cargo:rustc-cfg=nightly");
44-
}
44+
true
45+
} else {
46+
false
47+
};
4548

4649
let rustc_version = rustc_version::version().expect("failed to detect rustc version");
4750
if rustc_version.major == 1 && rustc_version.minor <= 64 {
@@ -51,25 +54,44 @@ fn main() {
5154
}
5255

5356
// Backend overrides / defaults
54-
let curve25519_dalek_backend =
55-
match std::env::var("CARGO_CFG_CURVE25519_DALEK_BACKEND").as_deref() {
56-
Ok("fiat") => "fiat",
57-
Ok("serial") => "serial",
58-
Ok("simd") => {
59-
// simd can only be enabled on x86_64 & 64bit target_pointer_width
60-
match is_capable_simd(&target_arch, curve25519_dalek_bits) {
61-
true => "simd",
62-
// If override is not possible this must result to compile error
63-
// See: issues/532
64-
false => panic!("Could not override curve25519_dalek_backend to simd"),
57+
let curve25519_dalek_backend = match std::env::var("CARGO_CFG_CURVE25519_DALEK_BACKEND")
58+
.as_deref()
59+
{
60+
Ok("fiat") => "fiat",
61+
Ok("serial") => "serial",
62+
Ok("simd") => {
63+
// simd can only be enabled on x86_64 & 64bit target_pointer_width
64+
match is_capable_simd(&target_arch, curve25519_dalek_bits) {
65+
true => "simd",
66+
// If override is not possible this must result to compile error
67+
// See: issues/532
68+
false => panic!("Could not override curve25519_dalek_backend to simd"),
69+
}
70+
}
71+
Ok("unstable_avx512") if nightly => {
72+
// simd can only be enabled on x86_64 & 64bit target_pointer_width
73+
match is_capable_simd(&target_arch, curve25519_dalek_bits) {
74+
true => {
75+
// In addition enable Avx2 fallback through simd stable backend
76+
// NOTE: Compiler permits duplicate / multi value on the same key
77+
println!("cargo:rustc-cfg=curve25519_dalek_backend=\"simd\"");
78+
79+
"unstable_avx512"
6580
}
81+
// If override is not possible this must result to compile error
82+
// See: issues/532
83+
false => panic!("Could not override curve25519_dalek_backend to unstable_avx512"),
6684
}
67-
// default between serial / simd (if potentially capable)
68-
_ => match is_capable_simd(&target_arch, curve25519_dalek_bits) {
69-
true => "simd",
70-
false => "serial",
71-
},
72-
};
85+
}
86+
Ok("unstable_avx512") if !nightly => {
87+
panic!("Could not override curve25519_dalek_backend to unstable_avx512, as this is nigthly only");
88+
}
89+
// default between serial / simd (if potentially capable)
90+
_ => match is_capable_simd(&target_arch, curve25519_dalek_bits) {
91+
true => "simd",
92+
false => "serial",
93+
},
94+
};
7395
println!("cargo:rustc-cfg=curve25519_dalek_backend=\"{curve25519_dalek_backend}\"");
7496
}
7597

curve25519-dalek/src/backend/mod.rs

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,14 @@ pub mod vector;
4646
enum BackendKind {
4747
#[cfg(curve25519_dalek_backend = "simd")]
4848
Avx2,
49-
#[cfg(all(curve25519_dalek_backend = "simd", nightly))]
49+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
5050
Avx512,
5151
Serial,
5252
}
5353

5454
#[inline]
5555
fn get_selected_backend() -> BackendKind {
56-
#[cfg(all(curve25519_dalek_backend = "simd", nightly))]
56+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
5757
{
5858
cpufeatures::new!(cpuid_avx512, "avx512ifma", "avx512vl");
5959
let token_avx512: cpuid_avx512::InitToken = cpuid_avx512::init();
@@ -88,7 +88,7 @@ where
8888
#[cfg(curve25519_dalek_backend = "simd")]
8989
BackendKind::Avx2 =>
9090
vector::scalar_mul::pippenger::spec_avx2::Pippenger::optional_multiscalar_mul::<I, J>(scalars, points),
91-
#[cfg(all(curve25519_dalek_backend = "simd", nightly))]
91+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
9292
BackendKind::Avx512 =>
9393
vector::scalar_mul::pippenger::spec_avx512ifma_avx512vl::Pippenger::optional_multiscalar_mul::<I, J>(scalars, points),
9494
BackendKind::Serial =>
@@ -100,7 +100,7 @@ where
100100
pub(crate) enum VartimePrecomputedStraus {
101101
#[cfg(curve25519_dalek_backend = "simd")]
102102
Avx2(vector::scalar_mul::precomputed_straus::spec_avx2::VartimePrecomputedStraus),
103-
#[cfg(all(curve25519_dalek_backend = "simd", nightly))]
103+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
104104
Avx512ifma(
105105
vector::scalar_mul::precomputed_straus::spec_avx512ifma_avx512vl::VartimePrecomputedStraus,
106106
),
@@ -120,14 +120,40 @@ impl VartimePrecomputedStraus {
120120
#[cfg(curve25519_dalek_backend = "simd")]
121121
BackendKind::Avx2 =>
122122
VartimePrecomputedStraus::Avx2(vector::scalar_mul::precomputed_straus::spec_avx2::VartimePrecomputedStraus::new(static_points)),
123-
#[cfg(all(curve25519_dalek_backend = "simd", nightly))]
123+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
124124
BackendKind::Avx512 =>
125125
VartimePrecomputedStraus::Avx512ifma(vector::scalar_mul::precomputed_straus::spec_avx512ifma_avx512vl::VartimePrecomputedStraus::new(static_points)),
126126
BackendKind::Serial =>
127127
VartimePrecomputedStraus::Scalar(serial::scalar_mul::precomputed_straus::VartimePrecomputedStraus::new(static_points))
128128
}
129129
}
130130

131+
/// Return the number of static points in the precomputation.
132+
pub fn len(&self) -> usize {
133+
use crate::traits::VartimePrecomputedMultiscalarMul;
134+
135+
match self {
136+
#[cfg(curve25519_dalek_backend = "simd")]
137+
VartimePrecomputedStraus::Avx2(inner) => inner.len(),
138+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
139+
VartimePrecomputedStraus::Avx512ifma(inner) => inner.len(),
140+
VartimePrecomputedStraus::Scalar(inner) => inner.len(),
141+
}
142+
}
143+
144+
/// Determine if the precomputation is empty.
145+
pub fn is_empty(&self) -> bool {
146+
use crate::traits::VartimePrecomputedMultiscalarMul;
147+
148+
match self {
149+
#[cfg(curve25519_dalek_backend = "simd")]
150+
VartimePrecomputedStraus::Avx2(inner) => inner.is_empty(),
151+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
152+
VartimePrecomputedStraus::Avx512ifma(inner) => inner.is_empty(),
153+
VartimePrecomputedStraus::Scalar(inner) => inner.is_empty(),
154+
}
155+
}
156+
131157
pub fn optional_mixed_multiscalar_mul<I, J, K>(
132158
&self,
133159
static_scalars: I,
@@ -150,7 +176,7 @@ impl VartimePrecomputedStraus {
150176
dynamic_scalars,
151177
dynamic_points,
152178
),
153-
#[cfg(all(curve25519_dalek_backend = "simd", nightly))]
179+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
154180
VartimePrecomputedStraus::Avx512ifma(inner) => inner.optional_mixed_multiscalar_mul(
155181
static_scalars,
156182
dynamic_scalars,
@@ -181,7 +207,7 @@ where
181207
BackendKind::Avx2 => {
182208
vector::scalar_mul::straus::spec_avx2::Straus::multiscalar_mul::<I, J>(scalars, points)
183209
}
184-
#[cfg(all(curve25519_dalek_backend = "simd", nightly))]
210+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
185211
BackendKind::Avx512 => {
186212
vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::multiscalar_mul::<I, J>(
187213
scalars, points,
@@ -210,7 +236,7 @@ where
210236
scalars, points,
211237
)
212238
}
213-
#[cfg(all(curve25519_dalek_backend = "simd", nightly))]
239+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
214240
BackendKind::Avx512 => {
215241
vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::optional_multiscalar_mul::<
216242
I,
@@ -228,7 +254,7 @@ pub fn variable_base_mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint
228254
match get_selected_backend() {
229255
#[cfg(curve25519_dalek_backend = "simd")]
230256
BackendKind::Avx2 => vector::scalar_mul::variable_base::spec_avx2::mul(point, scalar),
231-
#[cfg(all(curve25519_dalek_backend = "simd", nightly))]
257+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
232258
BackendKind::Avx512 => {
233259
vector::scalar_mul::variable_base::spec_avx512ifma_avx512vl::mul(point, scalar)
234260
}
@@ -242,7 +268,7 @@ pub fn vartime_double_base_mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> Edwa
242268
match get_selected_backend() {
243269
#[cfg(curve25519_dalek_backend = "simd")]
244270
BackendKind::Avx2 => vector::scalar_mul::vartime_double_base::spec_avx2::mul(a, A, b),
245-
#[cfg(all(curve25519_dalek_backend = "simd", nightly))]
271+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
246272
BackendKind::Avx512 => {
247273
vector::scalar_mul::vartime_double_base::spec_avx512ifma_avx512vl::mul(a, A, b)
248274
}

curve25519-dalek/src/backend/serial/fiat_u32/field.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,6 @@ impl FieldElement2625 {
280280
let mut gt_i: bool;
281281
let mut eq_i: bool;
282282

283-
// start from least significant go to most significant
284283
for i in 0..10 {
285284
_ul = self.0[i];
286285
_vl = other.0[i];

curve25519-dalek/src/backend/serial/scalar_mul/precomputed_straus.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ impl VartimePrecomputedMultiscalarMul for VartimePrecomputedStraus {
4646
}
4747
}
4848

49+
fn len(&self) -> usize {
50+
self.static_lookup_tables.len()
51+
}
52+
53+
fn is_empty(&self) -> bool {
54+
self.static_lookup_tables.is_empty()
55+
}
56+
4957
fn optional_mixed_multiscalar_mul<I, J, K>(
5058
&self,
5159
static_scalars: I,
@@ -75,7 +83,7 @@ impl VartimePrecomputedMultiscalarMul for VartimePrecomputedStraus {
7583

7684
let sp = self.static_lookup_tables.len();
7785
let dp = dynamic_lookup_tables.len();
78-
assert_eq!(sp, static_nafs.len());
86+
assert!(sp >= static_nafs.len());
7987
assert_eq!(dp, dynamic_nafs.len());
8088

8189
// We could save some doublings by looking for the highest
@@ -99,7 +107,7 @@ impl VartimePrecomputedMultiscalarMul for VartimePrecomputedStraus {
99107
}
100108

101109
#[allow(clippy::needless_range_loop)]
102-
for i in 0..sp {
110+
for i in 0..static_nafs.len() {
103111
let t_ij = static_nafs[i][j];
104112
match t_ij.cmp(&0) {
105113
Ordering::Greater => {

curve25519-dalek/src/backend/serial/u64/field.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ impl FieldElement51 {
601601
/// Returns 1 if self is greater than the other and 0 otherwise
602602
// strategy: check if b-a overflows. if it does not overflow, then a was larger
603603
pub(crate) fn mpn_sub_n(&self, other: &Self) -> Choice {
604+
604605
let mut _ul = 0_u64;
605606
let mut _vl = 0_u64;
606607
let mut _rl = 0_u64;

curve25519-dalek/src/backend/vector/avx2/edwards.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//! This module currently has two point types:
1515
//!
1616
//! * `ExtendedPoint`: a point stored in vector-friendly format, with
17-
//! vectorized doubling and addition;
17+
//! vectorized doubling and addition;
1818
//!
1919
//! * `CachedPoint`: used for readdition.
2020
//!

curve25519-dalek/src/backend/vector/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub mod packed_simd;
1616

1717
pub mod avx2;
1818

19-
#[cfg(nightly)]
19+
#[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
2020
pub mod ifma;
2121

2222
pub mod scalar_mul;

0 commit comments

Comments
 (0)