Skip to content

Commit 06a3e8a

Browse files
committed
aead: restore s390x fixslice AES test gate and migrate ChaCha20/Poly1305 AVX2/AVX-512 kernels to as_chunks
auth: gate ed25519 AVX2/IFMA point tests behind the ed25519 feature and migrate point chunking to as_chunks clippy: document missing # Safety on ct-binsec-harness AVX2/IFMA entrypoints Restoring strict cross-target and feature-matrix validation surfaced four latent CI failures: s390x test builds referenced the fixslice AES module after it was excluded from s390x test cfg, x25519-only builds pulled in ed25519-gated point_avx2 tests that were never feature-gated, and the new clippy::chunks_exact_to_as_chunks lint plus missing_safety_doc caught real gaps in the ChaCha20/Poly1305/Ed25519 SIMD kernels and the CT harness.
1 parent 15a0761 commit 06a3e8a

6 files changed

Lines changed: 25 additions & 23 deletions

File tree

src/aead/aes.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5766,6 +5766,7 @@ mod tests {
57665766
}
57675767

57685768
/// FIPS 197 Appendix C.1 against the table-free fixslice AES-128 path.
5769+
#[cfg(not(target_arch = "s390x"))]
57695770
#[test]
57705771
fn riscv64_fixslice_matches_nist_aes128_vector() {
57715772
let key: [u8; 16] = [
@@ -5784,6 +5785,7 @@ mod tests {
57845785
assert_eq!(block, expected);
57855786
}
57865787

5788+
#[cfg(not(target_arch = "s390x"))]
57875789
#[test]
57885790
fn riscv64_fixslice_128_4blocks_matches_portable() {
57895791
let key = [0xC4u8; KEY_SIZE_128];
@@ -5806,6 +5808,7 @@ mod tests {
58065808
assert_eq!(blocks, expected);
58075809
}
58085810

5811+
#[cfg(not(target_arch = "s390x"))]
58095812
#[test]
58105813
fn riscv64_fixslice_matches_nist_aes256_vector() {
58115814
let key: [u8; 32] = [
@@ -5825,6 +5828,7 @@ mod tests {
58255828
assert_eq!(block, expected);
58265829
}
58275830

5831+
#[cfg(not(target_arch = "s390x"))]
58285832
#[test]
58295833
fn riscv64_fixslice_4blocks_matches_portable() {
58305834
let key = [0x3cu8; KEY_SIZE];

src/aead/chacha20/x86_64_avx2.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ unsafe fn xor_keystream_impl(key: &[u8; KEY_SIZE], initial_counter: u32, nonce:
4444
);
4545

4646
let mut counter = initial_counter;
47-
let mut batches = buffer.chunks_exact_mut(BLOCK_SIZE * BLOCKS_PER_BATCH);
48-
for chunk in &mut batches {
47+
let (batches, remainder) = buffer.as_chunks_mut::<{ BLOCK_SIZE * BLOCKS_PER_BATCH }>();
48+
for chunk in batches {
4949
debug_assert!(counter.checked_add(COUNTERS_PER_BATCH.strict_sub(1)).is_some());
5050

5151
let mut x0 = _mm256_set1_epi32(0x6170_7865u32.cast_signed());
@@ -183,16 +183,14 @@ unsafe fn xor_keystream_impl(key: &[u8; KEY_SIZE], initial_counter: u32, nonce:
183183
counter = counter.wrapping_add(COUNTERS_PER_BATCH);
184184
}
185185

186-
let remainder = batches.into_remainder();
187-
let mut x4_batches = remainder.chunks_exact_mut(BLOCK_SIZE * x86_ssse3_x4::BLOCKS_PER_BATCH);
188-
for chunk in &mut x4_batches {
186+
let (x4_batches, remainder) = remainder.as_chunks_mut::<{ BLOCK_SIZE * x86_ssse3_x4::BLOCKS_PER_BATCH }>();
187+
for chunk in x4_batches {
189188
// SAFETY: AVX2-capable CPUs provide the SSSE3 instructions used by the
190189
// 4-block tail kernel, and `chunk` is exactly 4 ChaCha20 blocks.
191190
unsafe { x86_ssse3_x4::xor_blocks(key, counter, nonce, chunk) };
192191
counter = counter.wrapping_add(x86_ssse3_x4::COUNTERS_PER_BATCH);
193192
}
194193

195-
let remainder = x4_batches.into_remainder();
196194
if !remainder.is_empty() {
197195
xor_keystream_portable(key, counter, nonce, remainder);
198196
}

src/aead/chacha20/x86_64_avx512.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ pub(super) unsafe fn xor_keystream(
3636
#[target_feature(enable = "avx512f,avx512vl,avx512bw,avx512dq")]
3737
unsafe fn xor_keystream_impl(key: &[u8; KEY_SIZE], initial_counter: u32, nonce: &[u8; NONCE_SIZE], buffer: &mut [u8]) {
3838
let mut counter = initial_counter;
39-
let mut batches = buffer.chunks_exact_mut(BLOCK_SIZE * BLOCKS_PER_BATCH);
40-
for chunk in &mut batches {
39+
let (batches, remainder) = buffer.as_chunks_mut::<{ BLOCK_SIZE * BLOCKS_PER_BATCH }>();
40+
for chunk in batches {
4141
debug_assert!(counter.checked_add(COUNTERS_PER_BATCH.strict_sub(1)).is_some());
4242

4343
let mut x0 = _mm512_set1_epi32(0x6170_7865u32.cast_signed());
@@ -236,16 +236,14 @@ unsafe fn xor_keystream_impl(key: &[u8; KEY_SIZE], initial_counter: u32, nonce:
236236
counter = counter.wrapping_add(COUNTERS_PER_BATCH);
237237
}
238238

239-
let remainder = batches.into_remainder();
240-
let mut x4_batches = remainder.chunks_exact_mut(BLOCK_SIZE * x86_ssse3_x4::BLOCKS_PER_BATCH);
241-
for chunk in &mut x4_batches {
239+
let (x4_batches, remainder) = remainder.as_chunks_mut::<{ BLOCK_SIZE * x86_ssse3_x4::BLOCKS_PER_BATCH }>();
240+
for chunk in x4_batches {
242241
// SAFETY: AVX-512-ready CPUs provide the SSSE3 instructions used by the
243242
// 4-block tail kernel, and `chunk` is exactly 4 ChaCha20 blocks.
244243
unsafe { x86_ssse3_x4::xor_blocks(key, counter, nonce, chunk) };
245244
counter = counter.wrapping_add(x86_ssse3_x4::COUNTERS_PER_BATCH);
246245
}
247246

248-
let remainder = x4_batches.into_remainder();
249247
if !remainder.is_empty() {
250248
xor_keystream_portable(key, counter, nonce, remainder);
251249
}

src/aead/poly1305/x86_64_avx2_par4.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -703,15 +703,12 @@ pub(super) unsafe fn authenticate_aead_par4(
703703

704704
// Reimplements padded-segment logic from `update_padded_segment` for 4-way batching.
705705
for segment in [aad, ciphertext] {
706-
let mut chunks = segment.chunks_exact(16);
707-
for chunk in &mut chunks {
708-
let mut block = [0u8; 16];
709-
block.copy_from_slice(chunk);
706+
let (chunks, rem) = segment.as_chunks::<16>();
707+
for chunk in chunks {
710708
// SAFETY: the caller guarantees AVX2. The loop produces consecutive full blocks; `push_block` preserves
711709
// `num_cached < 4` and keeps the cache, powers, and accumulator in the same key stream.
712-
num_cached = unsafe { push_block(block, &mut cached, num_cached, &mut acc, r1, r2) };
710+
num_cached = unsafe { push_block(*chunk, &mut cached, num_cached, &mut acc, r1, r2) };
713711
}
714-
let rem = chunks.remainder();
715712
if !rem.is_empty() {
716713
let mut block = [0u8; 16];
717714
block[..rem.len()].copy_from_slice(rem);

src/auth/ed25519/point_avx2.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ pub unsafe fn diag_select_basepoint_cached_avx2_limb_digest(digit: i8) -> [u64;
490490
let selected = select_signed_cached_avx2(&BASEPOINT_RADIX16_TABLE[0], digit, &affine_k, &identity);
491491
let fields = selected.0.split();
492492
let mut out = [0u64; 20];
493-
for (chunk, field) in out.chunks_exact_mut(5).zip(fields.iter()) {
493+
for (chunk, field) in out.as_chunks_mut::<5>().0.iter_mut().zip(fields.iter()) {
494494
chunk.copy_from_slice(field.limbs());
495495
}
496496
out
@@ -914,7 +914,7 @@ pub unsafe fn diag_select_basepoint_cached_ifma_limb_digest(digit: i8) -> [u64;
914914
let selected = select_signed_cached_ifma(&BASEPOINT_RADIX16_TABLE[0], digit, &affine_k, &identity);
915915
let fields = selected.0.split();
916916
let mut out = [0u64; 20];
917-
for (chunk, field) in out.chunks_exact_mut(5).zip(fields.iter()) {
917+
for (chunk, field) in out.as_chunks_mut::<5>().0.iter_mut().zip(fields.iter()) {
918918
chunk.copy_from_slice(field.limbs());
919919
}
920920
out
@@ -1085,6 +1085,7 @@ pub(crate) unsafe fn straus_wnaf_vartime_ifma(s: &[u8; 32], h: &[u8; 32], a: &Ex
10851085

10861086
#[cfg(test)]
10871087
#[cfg(target_arch = "x86_64")]
1088+
#[cfg(feature = "ed25519")]
10881089
mod tests {
10891090
use super::{ExtendedPoint, *};
10901091

@@ -1320,7 +1321,6 @@ mod tests {
13201321
}
13211322
}
13221323

1323-
#[cfg(feature = "ed25519")]
13241324
#[test]
13251325
fn scalar_mul_basepoint_rfc8032_vector1() {
13261326
if !std::arch::is_x86_feature_detected!("avx2") {
@@ -1345,7 +1345,6 @@ mod tests {
13451345
}
13461346
}
13471347

1348-
#[cfg(feature = "ed25519")]
13491348
#[test]
13501349
fn straus_matches_scalar() {
13511350
if !std::arch::is_x86_feature_detected!("avx2") {
@@ -1371,7 +1370,6 @@ mod tests {
13711370
}
13721371
}
13731372

1374-
#[cfg(feature = "ed25519")]
13751373
#[test]
13761374
fn straus_matches_scalar_large_scalars() {
13771375
if !std::arch::is_x86_feature_detected!("avx2") {

tools/ct-binsec-harness/src/main.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,9 @@ pub extern "C" fn ct_binsec_rsa_private_component_validation_32() -> ! {
885885
#[unsafe(no_mangle)]
886886
#[inline(never)]
887887
#[target_feature(enable = "avx2")]
888+
/// # Safety
889+
///
890+
/// The caller must ensure AVX2 is available before invoking this entrypoint.
888891
pub unsafe extern "C" fn ct_binsec_ed25519_select_basepoint_cached_avx2() -> ! {
889892
// SAFETY: This pointer references a fixed harness global with static storage.
890893
let digit = unsafe { ptr::read_volatile(ptr::addr_of!(CT_BINSEC_ED25519_DIGIT)) };
@@ -905,6 +908,10 @@ pub unsafe extern "C" fn ct_binsec_ed25519_select_basepoint_cached_avx2() -> ! {
905908
#[unsafe(no_mangle)]
906909
#[inline(never)]
907910
#[target_feature(enable = "avx2,avx512ifma,avx512vl")]
911+
/// # Safety
912+
///
913+
/// The caller must ensure AVX2, AVX-512 IFMA, and AVX-512 VL are available
914+
/// before invoking this entrypoint.
908915
pub unsafe extern "C" fn ct_binsec_ed25519_select_basepoint_cached_ifma() -> ! {
909916
// SAFETY: This pointer references a fixed harness global with static storage.
910917
let digit = unsafe { ptr::read_volatile(ptr::addr_of!(CT_BINSEC_ED25519_DIGIT)) };

0 commit comments

Comments
 (0)