Skip to content

Commit 7b64aaf

Browse files
committed
sm4: simd support for armv8, x86_64
- x86_64: aesni, avx2 - armv8: crypto-extension, neon
1 parent fbb68f4 commit 7b64aaf

15 files changed

Lines changed: 1994 additions & 177 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sm4/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ categories = ["cryptography", "no-std"]
1414

1515
[dependencies]
1616
cipher = "=0.5.0-pre.8"
17+
cfg-if = "1"
18+
19+
[target.'cfg(any(target_arch = "aarch64", target_arch = "x86_64", target_arch = "x86"))'.dependencies]
20+
cpufeatures = "0.2.11"
1721

1822
[dev-dependencies]
1923
cipher = { version = "=0.5.0-pre.8", features = ["dev"] }

sm4/src/armv8/autodetect/linux.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#![allow(unsafe_code)]
2+
3+
use cipher::{
4+
consts::U16, AlgorithmName, BlockCipher, BlockClosure, BlockDecrypt, BlockEncrypt,
5+
BlockSizeUser, Key, KeyInit, KeySizeUser,
6+
};
7+
use core::{fmt, mem::ManuallyDrop};
8+
9+
use crate::armv8::{neon::Sm4 as NeonSm4, sm4e::Sm4 as CryptoExtensionSm4};
10+
11+
cpufeatures::new!(sm4_intrinsics, "sm4");
12+
13+
union Sm4Cipher {
14+
sm4: ManuallyDrop<CryptoExtensionSm4>,
15+
neon: ManuallyDrop<NeonSm4>,
16+
}
17+
18+
/// SM4 block cipher.
19+
pub struct Sm4 {
20+
cipher: Sm4Cipher,
21+
token: sm4_intrinsics::InitToken,
22+
}
23+
24+
impl KeySizeUser for Sm4 {
25+
type KeySize = U16;
26+
}
27+
28+
impl KeyInit for Sm4 {
29+
#[inline]
30+
fn new(key: &Key<Self>) -> Self {
31+
let (token, intrinsics_presense) = sm4_intrinsics::init_get();
32+
33+
let cipher = if intrinsics_presense {
34+
Sm4Cipher {
35+
sm4: ManuallyDrop::new(CryptoExtensionSm4::new(key)),
36+
}
37+
} else {
38+
Sm4Cipher {
39+
neon: ManuallyDrop::new(NeonSm4::new(key)),
40+
}
41+
};
42+
43+
Self { cipher, token }
44+
}
45+
}
46+
47+
impl Clone for Sm4 {
48+
fn clone(&self) -> Self {
49+
let cipher = if self.token.get() {
50+
Sm4Cipher {
51+
sm4: unsafe { self.cipher.sm4.clone() },
52+
}
53+
} else {
54+
Sm4Cipher {
55+
neon: unsafe { self.cipher.neon.clone() },
56+
}
57+
};
58+
59+
Self {
60+
cipher,
61+
token: self.token,
62+
}
63+
}
64+
}
65+
66+
impl BlockSizeUser for Sm4 {
67+
type BlockSize = U16;
68+
}
69+
70+
impl BlockCipher for Sm4 {}
71+
72+
impl BlockEncrypt for Sm4 {
73+
fn encrypt_with_backend(&self, f: impl BlockClosure<BlockSize = U16>) {
74+
unsafe {
75+
if self.token.get() {
76+
self.cipher.sm4.encrypt_with_backend(f);
77+
} else {
78+
self.cipher.neon.encrypt_with_backend(f);
79+
}
80+
}
81+
}
82+
}
83+
84+
impl BlockDecrypt for Sm4 {
85+
fn decrypt_with_backend(&self, f: impl BlockClosure<BlockSize = U16>) {
86+
unsafe {
87+
if self.token.get() {
88+
self.cipher.sm4.decrypt_with_backend(f);
89+
} else {
90+
self.cipher.neon.decrypt_with_backend(f);
91+
}
92+
}
93+
}
94+
}
95+
96+
impl fmt::Debug for Sm4 {
97+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
98+
f.write_str(concat!(stringify!(Sm4), " { .. }"))
99+
}
100+
}
101+
102+
impl AlgorithmName for Sm4 {
103+
fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
104+
f.write_str(stringify!(Sm4))
105+
}
106+
}
107+
108+
impl Drop for Sm4 {
109+
fn drop(&mut self) {
110+
#[allow(unsafe_code)]
111+
if self.token.get() {
112+
unsafe { ManuallyDrop::drop(&mut self.cipher.sm4) }
113+
} else {
114+
unsafe { ManuallyDrop::drop(&mut self.cipher.neon) }
115+
}
116+
}
117+
}

sm4/src/armv8/autodetect/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use cfg_if::cfg_if;
2+
3+
cfg_if! {
4+
if #[cfg(any(target_os = "linux", target_os = "android"))] {
5+
mod linux;
6+
pub use self::linux::*;
7+
} else {
8+
mod others;
9+
pub use self::others::*;
10+
}
11+
}

sm4/src/armv8/autodetect/others.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub use crate::armv8::neon::*;

sm4/src/armv8/intrinsics.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//! ARMv8 extension intrinsics
2+
3+
#![allow(unsafe_code)]
4+
5+
use core::arch::{aarch64::*, asm};
6+
7+
#[inline]
8+
#[target_feature(enable = "sm4")]
9+
pub(super) unsafe fn vsm4eq_u32(mut a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
10+
asm!(
11+
"SM4E {d:v}.4S, {n:v}.4S",
12+
d = inout(vreg) a,
13+
n = in(vreg) b,
14+
options(pure, nomem, nostack, preserves_flags)
15+
);
16+
a
17+
}
18+
19+
#[inline]
20+
#[target_feature(enable = "sm4")]
21+
pub(super) unsafe fn vsm4ekeyq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
22+
let mut key: uint32x4_t;
23+
asm!(
24+
"SM4EKEY {d:v}.4S, {n:v}.4S, {m:v}.4S",
25+
d = out(vreg) key,
26+
n = in(vreg) a,
27+
m = in(vreg) b,
28+
options(pure, nomem, nostack, preserves_flags)
29+
);
30+
key
31+
}

sm4/src/armv8/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub mod autodetect;
2+
mod intrinsics;
3+
mod neon;
4+
#[cfg(any(target_os = "linux", target_os = "android"))]
5+
mod sm4e;

0 commit comments

Comments
 (0)