Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cpufeatures/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Linux, iOS, and macOS/ARM only (ARM64 does not support OS-independent feature de
Target features:

- `aes`*
- `crc`
- `sha2`*
- `sha3`*

Expand Down
31 changes: 24 additions & 7 deletions cpufeatures/src/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ macro_rules! __expand_check_macro {
#[cfg(any(target_os = "linux", target_os = "android"))]
__expand_check_macro! {
("aes", AES), // Enable AES support.
("crc", CRC32), // Enable CRC32 support.
("dit", DIT), // Enable DIT support.
("sha2", SHA2), // Enable SHA1 and SHA256 support.
("sha3", SHA3), // Enable SHA512 and SHA3 support.
Expand All @@ -85,6 +86,7 @@ pub mod hwcaps {
use libc::c_ulong;

pub const AES: c_ulong = libc::HWCAP_AES | libc::HWCAP_PMULL;
pub const CRC32: c_ulong = libc::HWCAP_CRC32;
pub const DIT: c_ulong = libc::HWCAP_DIT;
pub const SHA2: c_ulong = libc::HWCAP_SHA2;
pub const SHA3: c_ulong = libc::HWCAP_SHA3 | libc::HWCAP_SHA512;
Expand All @@ -109,10 +111,19 @@ macro_rules! check {
("aes") => {
true
};
("crc") => {
unsafe {
// `hw.optional.armv8_crc32` is the legacy name,
// `hw.optional.arm.FEAT_CRC32` is the newer FEAT_ name.
// Either one reporting present means CRC32 is available.
$crate::aarch64::try_sysctlbyname(b"hw.optional.armv8_crc32\0")
|| $crate::aarch64::try_sysctlbyname(b"hw.optional.arm.FEAT_CRC32\0")
}
};
("dit") => {
// https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Enable-DIT-for-constant-time-cryptographic-operations
unsafe {
$crate::aarch64::sysctlbyname(b"hw.optional.arm.FEAT_DIT\0")
$crate::aarch64::try_sysctlbyname(b"hw.optional.arm.FEAT_DIT\0")
}
};
("sha2") => {
Expand All @@ -121,8 +132,8 @@ macro_rules! check {
("sha3") => {
unsafe {
// `sha3` target feature implies SHA-512 as well
$crate::aarch64::sysctlbyname(b"hw.optional.armv8_2_sha512\0")
&& $crate::aarch64::sysctlbyname(b"hw.optional.armv8_2_sha3\0")
$crate::aarch64::try_sysctlbyname(b"hw.optional.armv8_2_sha512\0")
&& $crate::aarch64::try_sysctlbyname(b"hw.optional.armv8_2_sha3\0")
}
};
("sm4") => {
Expand All @@ -132,13 +143,17 @@ macro_rules! check {

/// Apple helper function for calling `sysctlbyname`.
///
/// Returns `false` when the named key does not exist
/// or has an unexpected size, so renamed keys across OS versions degrade
/// to "unsupported" instead of aborting.
///
/// <https://developer.apple.com/documentation/kernel/1387446-sysctlbyname>
///
/// # Panics
/// If `name` is not NUL terminated
#[cfg(target_vendor = "apple")]
#[must_use]
pub unsafe fn sysctlbyname(name: &[u8]) -> bool {
pub unsafe fn try_sysctlbyname(name: &[u8]) -> bool {
assert_eq!(
name.last().cloned(),
Some(0),
Expand All @@ -153,10 +168,11 @@ pub unsafe fn sysctlbyname(name: &[u8]) -> bool {
// - `name` is being cast from a valid byte slice we asserted was NUL terminated above.
// - `value` is a properly-aligned, writable integer.
// - `size` is initialized to the size of `value` (4-bytes).
// - The last two arguments,`newp` and `newlen`, are for setting system parameters, which we
// - The last two arguments, `newp` and `newlen`, are for setting system parameters, which we
// aren't doing here (and requires root privileges). The docs say the following:
// - `newp`: "Specify NULL if you don’t want to set the attribute’s value"
// - `newlen`: "Specify 0 if you don’t want to set the attribute’s value"
// A nonzero return code (unknown key) or unexpected size maps to `false`.
let rc = unsafe {
libc::sysctlbyname(
name.as_ptr().cast::<i8>(),
Expand All @@ -167,8 +183,9 @@ pub unsafe fn sysctlbyname(name: &[u8]) -> bool {
)
};

assert_eq!(size, 4, "unexpected sysctlbyname(3) result size");
assert_eq!(rc, 0, "sysctlbyname returned error code: {}", rc);
if rc != 0 || size != 4 {
return false;
}
value != 0
}

Expand Down
2 changes: 1 addition & 1 deletion cpufeatures/tests/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#![cfg(target_arch = "aarch64")]

cpufeatures::new!(armcaps, "aes", "sha2", "sha3", "sm4");
cpufeatures::new!(armcaps, "aes", "crc", "sha2", "sha3", "sm4");

#[test]
fn init() {
Expand Down