gmcrypto_simd/lib.rs
1//! SIMD backends for `gmcrypto-core` (v0.5 W4 phase 2 / v0.6 W6).
2//!
3//! This crate quarantines the unavoidable SIMD `unsafe` (AVX2
4//! intrinsics on `x86_64`, NEON on `aarch64`) so that
5//! `gmcrypto-core` itself can keep `unsafe_code = "forbid"`. The
6//! posture mirrors the established [`gmcrypto-c`] precedent (FFI
7//! shim with `unsafe_code = "warn"`).
8//!
9//! **No stable Rust API.** The crate exposes a small Rust-internal API
10//! surface only (no raw pointers, no C ABI), present solely for
11//! `gmcrypto-core`'s cross-crate use. Every public entry point is
12//! `#[doc(hidden)]` and **not covered by SemVer** — it may change or be
13//! removed in any release without notice. It is `rlib`-only; the supported
14//! downstream surfaces are the `gmcrypto-core` Rust API and the
15//! [`gmcrypto-c`] C ABI. Internal cross-crate use stays sound via the
16//! workspace's lockstep publishing policy (sibling crates release together;
17//! exact-version sibling pins enforced at the 1.0 publish).
18//!
19//! # v0.5 W4 phase 2 scope
20//!
21//! - x86_64 AVX2 8-way packed bitsliced SM4 S-box
22//! ([`sm4::sbox_x8::sbox_x8`]), with runtime AVX2 detection via
23//! the `cpufeatures` crate and silent scalar fallback on non-AVX2
24//! CPUs. 8 input bytes occupy the low lanes of the 256-bit
25//! register; the upper 24 lanes are unused.
26//!
27//! # v0.6 W6 (phase 3) scope
28//!
29//! - x86_64 AVX2 32-byte full-width packed bitsliced S-box
30//! ([`sm4::sbox_x32::sbox_x32`]). The intended consumer is an
31//! 8-block CBC-decrypt batch fanout in `gmcrypto-core` (8 SM4
32//! blocks × 4 `tau` bytes per round = 32 bytes per call, zero
33//! wasted lanes).
34//! - aarch64 NEON 16-byte packed bitsliced S-box
35//! ([`sm4::sbox_x16::sbox_x16`]). NEON is the architectural
36//! baseline on aarch64 (Q5.12 / Q6.3 of the v0.5 / v0.6 scope
37//! docs); compile-time gated, no runtime detect.
38//!
39//! # Issue #163 — serial `tau` repair
40//!
41//! - [`sm4::sbox_x4::sbox_x4`]: four independent S-box bytes for
42//! single-block / key-schedule `tau`. `AArch64` reuses one NEON x16
43//! invocation; other targets use four scalar calls. The one-byte
44//! `sbox_x8` broadcast adapter in `gmcrypto-core` is removed.
45//!
46//! [`gmcrypto-c`]: https://docs.rs/gmcrypto-c
47
48#![no_std]
49// v0.5 W4 phase 2 / v0.6 W6 — this crate is the SIMD-intrinsic
50// backend (mirroring `gmcrypto-c`'s FFI-shim posture).
51// `core::arch::*` intrinsics are all `unsafe fn`, and
52// `#[target_feature(enable = "...")] unsafe fn` is the only
53// stable-Rust path on MSRV 1.85 to combine runtime CPU dispatch
54// with intrinsic calls. Every `unsafe` block / fn declaration
55// carries a `// SAFETY:` comment naming the architectural /
56// runtime-detect precondition. The Cargo.toml lint
57// `unsafe_code = "warn"` documents intent; this crate-level
58// `allow` keeps the per-decl noise out of the review surface
59// (same pattern as `gmcrypto-c`'s `src/lib.rs`).
60// `gmcrypto-core` itself stays `unsafe_code = "forbid"`.
61#![allow(unsafe_code)]
62
63// v0.21 (Q21.5 of `docs/v0.21-scope.md`) — internal-backend contract. Every
64// item below is `pub` only so `gmcrypto-core` can call it across the crate
65// boundary; it is NOT a stable Rust API. All entry points are `#[doc(hidden)]`
66// (kept out of rustdoc + the committed public-api baseline) and not covered by
67// SemVer for any external consumer. Internal cross-crate use stays sound via the
68// workspace's lockstep publishing policy (sibling crates release together;
69// exact-version sibling pins enforced at the 1.0 publish).
70#[doc(hidden)]
71pub mod ghash;
72#[doc(hidden)]
73pub mod sm4;
74
75mod detect;
76
77#[doc(hidden)]
78pub use detect::{has_avx2, has_pclmulqdq, has_pmull};
79#[doc(hidden)]
80pub use ghash::ghash_mul;