Skip to content

Commit dd566cc

Browse files
committed
merge main in rustcrypto-new-releases
2 parents 99decda + 8c0cf3a commit dd566cc

File tree

27 files changed

+294
-95
lines changed

27 files changed

+294
-95
lines changed

curve25519-dalek-derive/README.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,7 @@ to build out more elaborate abstractions it starts to become painful to use.
8181
This crate exposes an `#[unsafe_target_feature]` macro which works just like `#[target_feature]` except
8282
it moves the `unsafe` from the function prototype into the macro name, and can be used on safe functions.
8383

84-
```rust,compile_fail
85-
// ERROR: `#[target_feature(..)]` can only be applied to `unsafe` functions
86-
#[target_feature(enable = "avx2")]
87-
fn func() {}
88-
```
89-
9084
```rust
91-
// It works, but must be `unsafe`
9285
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
9386
#[target_feature(enable = "avx2")]
9487
unsafe fn func() {}

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: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ ff = { version = "=0.14.0-pre.0", default-features = false, optional = true }
5151
group = { version = "=0.14.0-pre.0", default-features = false, optional = true }
5252
rand_core = { version = "0.9", default-features = false, optional = true }
5353
digest = { version = "=0.11.0-pre.10", default-features = false, optional = true }
54-
subtle = { version = "2.6.0", default-features = false }
54+
subtle = { version = "2.6.0", default-features = false, features = ["const-generics"]}
5555
serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] }
5656
zeroize = { version = "1", default-features = false, optional = true }
5757

5858
[target.'cfg(target_arch = "x86_64")'.dependencies]
59-
cpufeatures = "0.2.6"
59+
cpufeatures = "0.2.17"
6060

6161
[target.'cfg(curve25519_dalek_backend = "fiat")'.dependencies]
6262
fiat-crypto = { version = "0.2.1", default-features = false }
@@ -76,7 +76,7 @@ curve25519-dalek-derive = { version = "0.1", path = "../curve25519-dalek-derive"
7676
level = "warn"
7777
check-cfg = [
7878
'cfg(allow_unused_unsafe)',
79-
'cfg(curve25519_dalek_backend, values("fiat", "serial", "simd"))',
79+
'cfg(curve25519_dalek_backend, values("fiat", "serial", "simd", "unstable_avx512"))',
8080
'cfg(curve25519_dalek_diagnostics, values("build"))',
8181
'cfg(curve25519_dalek_bits, values("32", "64"))',
8282
'cfg(nightly)',

curve25519-dalek/README.md

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

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

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

99100
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.
100101

@@ -148,16 +149,16 @@ $ cargo build --target i686-unknown-linux-gnu
148149

149150
## SIMD backend
150151

151-
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.
152+
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.
152153

153154
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.
154155

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

160-
If compiled on a non-nightly compiler, `curve25519-dalek` will not include AVX512 code, and therefore will never select it at runtime.
161+
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.
161162

162163
# Documentation
163164

curve25519-dalek/build.rs

Lines changed: 43 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,46 @@ 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!(
88+
"Could not override curve25519_dalek_backend to unstable_avx512, as this is nigthly only"
89+
);
90+
}
91+
// default between serial / simd (if potentially capable)
92+
_ => match is_capable_simd(&target_arch, curve25519_dalek_bits) {
93+
true => "simd",
94+
false => "serial",
95+
},
96+
};
7397
println!("cargo:rustc-cfg=curve25519_dalek_backend=\"{curve25519_dalek_backend}\"");
7498
}
7599

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/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/vector/avx2/field.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
// - isis agora lovecruft <isis@patternsinthevoid.net>
1010
// - Henry de Valence <hdevalence@hdevalence.ca>
1111

12+
// Nightly and stable currently disagree on the requirement of unsafe blocks when `unsafe_target_feature`
13+
// gets used.
14+
// See: https://github.com/rust-lang/rust/issues/132856
15+
#![allow(unused_unsafe)]
16+
1217
//! An implementation of 4-way vectorized 32bit field arithmetic using
1318
//! AVX2.
1419
//!

curve25519-dalek/src/backend/vector/ifma/field.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
// - isis agora lovecruft <isis@patternsinthevoid.net>
1010
// - Henry de Valence <hdevalence@hdevalence.ca>
1111

12+
// Nightly and stable currently disagree on the requirement of unsafe blocks when `unsafe_target_feature`
13+
// gets used.
14+
// See: https://github.com/rust-lang/rust/issues/132856
15+
#![allow(unused_unsafe)]
1216
#![allow(non_snake_case)]
1317

1418
use crate::backend::vector::packed_simd::u64x4;

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)