Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve conditional compilation around PerlAsm #1937

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
71 changes: 44 additions & 27 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,44 @@ const MACOS_ABI: &[&str] = &["ios", MACOS, "tvos"];
const MACOS: &str = "macos";
const WINDOWS: &str = "windows";

fn get_target(is_git: bool) -> Target {
let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let env = env::var("CARGO_CFG_TARGET_ENV").unwrap();

// Published builds are always built in release mode.
let is_debug = is_git && env::var("DEBUG").unwrap() != "false";

// During local development, force warnings in non-Rust code to be treated
// as errors. Since warnings are highly compiler-dependent and compilers
// don't maintain backward compatibility w.r.t. which warnings they issue,
// don't do this for packaged builds.
let force_warnings_into_errors = is_git;

Target {
arch,
os,
env,
is_debug,
force_warnings_into_errors,
}
}

fn find_asm_target(target: &Target) -> Option<&'static AsmTarget> {
ASM_TARGETS.iter().find(|asm_target| {
asm_target.arch == target.arch && asm_target.oss.contains(&target.os.as_ref())
})
}

fn main() {
// Avoid assuming the working directory is the same is the $CARGO_MANIFEST_DIR so that toolchains
// which may assume other working directories can still build this code.
let c_root_dir = PathBuf::from(
env::var_os("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR should always be set"),
);

let is_git = std::fs::metadata(c_root_dir.join(".git")).is_ok();

// Keep in sync with `core_name_and_version!` in prefixed.rs.
let core_name_and_version = [
&env::var("CARGO_PKG_NAME").unwrap(),
Expand All @@ -285,48 +316,30 @@ fn main() {
&core_name_and_version
);

match find_asm_target(&get_target(is_git)) {
Some(_) => println!("cargo:rustc-cfg=perlasm"),
None => println!("cargo:rustc-cfg=no_perlasm"),
}

const RING_PREGENERATE_ASM: &str = "RING_PREGENERATE_ASM";
match env::var_os(RING_PREGENERATE_ASM).as_deref() {
Some(s) if s == "1" => {
pregenerate_asm_main(&c_root_dir, &core_name_and_version);
}
None => ring_build_rs_main(&c_root_dir, &core_name_and_version),
None => ring_build_rs_main(&c_root_dir, &core_name_and_version, is_git),
_ => {
panic!("${} has an invalid value", RING_PREGENERATE_ASM);
}
}
}

fn ring_build_rs_main(c_root_dir: &Path, core_name_and_version: &str) {
fn ring_build_rs_main(c_root_dir: &Path, core_name_and_version: &str, is_git: bool) {
let out_dir = env::var_os("OUT_DIR").unwrap();
let out_dir = PathBuf::from(out_dir);

let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let env = env::var("CARGO_CFG_TARGET_ENV").unwrap();

let is_git = std::fs::metadata(c_root_dir.join(".git")).is_ok();

// Published builds are always built in release mode.
let is_debug = is_git && env::var("DEBUG").unwrap() != "false";

// During local development, force warnings in non-Rust code to be treated
// as errors. Since warnings are highly compiler-dependent and compilers
// don't maintain backward compatibility w.r.t. which warnings they issue,
// don't do this for packaged builds.
let force_warnings_into_errors = is_git;

let target = Target {
arch,
os,
env,
is_debug,
force_warnings_into_errors,
};
let target = get_target(is_git);

let asm_target = ASM_TARGETS.iter().find(|asm_target| {
asm_target.arch == target.arch && asm_target.oss.contains(&target.os.as_ref())
});
let asm_target = find_asm_target(&target);

// If `.git` exists then assume this is the "local hacking" case where
// we want to make it easy to build *ring* using `cargo build`/`cargo test`
Expand Down Expand Up @@ -591,6 +604,10 @@ fn configure_cc(c: &mut cc::Build, target: &Target, c_root_dir: &Path, include_d
if target.force_warnings_into_errors {
c.warnings_into_errors(true);
}

if find_asm_target(target).is_none() {
let _ = c.define("OPENSSL_NO_ASM", "1");
}
}

fn nasm(file: &Path, arch: &str, include_dir: &Path, out_dir: &Path, c_root_dir: &Path) {
Expand Down
1 change: 0 additions & 1 deletion crypto/fipsmodule/ec/p256_shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include "../bn/internal.h"

#if !defined(OPENSSL_NO_ASM) && \
(defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) && \
!defined(OPENSSL_SMALL)
# define OPENSSL_USE_NISTZ256
#endif
Expand Down
119 changes: 73 additions & 46 deletions src/aead/aes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,23 +176,29 @@ impl Key {
};

match detect_implementation(cpu_features) {
#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
#[cfg(all(
perlasm,
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
)
))]
// SAFETY: `aes_hw_set_encrypt_key` satisfies the `set_encrypt_key!`
// contract for these target architectures.
Implementation::HWAES => unsafe {
set_encrypt_key!(aes_hw_set_encrypt_key, bytes, &mut key, cpu_features)?;
},

#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
#[cfg(all(
perlasm,
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
)
))]
// SAFETY: `vpaes_set_encrypt_key` satisfies the `set_encrypt_key!`
// contract for these target architectures.
Expand All @@ -213,19 +219,25 @@ impl Key {
#[inline]
pub fn encrypt_block(&self, a: Block, cpu_features: cpu::Features) -> Block {
match detect_implementation(cpu_features) {
#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
#[cfg(all(
perlasm,
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
)
))]
Implementation::HWAES => encrypt_block!(aes_hw_encrypt, a, self),

#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
#[cfg(all(
perlasm,
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
)
))]
Implementation::VPAES_BSAES => encrypt_block!(vpaes_encrypt, a, self),

Expand All @@ -248,11 +260,14 @@ impl Key {
cpu_features: cpu::Features,
) {
match detect_implementation(cpu_features) {
#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
#[cfg(all(
perlasm,
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
)
))]
// SAFETY:
// * self.inner was initialized with `aes_hw_set_encrypt_key` above,
Expand All @@ -270,7 +285,10 @@ impl Key {
)
},

#[cfg(any(target_arch = "aarch64", target_arch = "arm", target_arch = "x86_64"))]
#[cfg(all(
perlasm,
any(target_arch = "aarch64", target_arch = "arm", target_arch = "x86_64")
))]
Implementation::VPAES_BSAES => {
#[cfg(target_arch = "arm")]
let in_out = {
Expand Down Expand Up @@ -357,7 +375,7 @@ impl Key {
[b0, b1, b2, b3, b4]
}

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
#[cfg(all(perlasm, any(target_arch = "x86_64", target_arch = "aarch64")))]
#[must_use]
pub fn is_aes_hw(&self, cpu_features: cpu::Features) -> bool {
matches!(detect_implementation(cpu_features), Implementation::HWAES)
Expand Down Expand Up @@ -436,20 +454,26 @@ pub(super) const ZERO_BLOCK: Block = [0u8; BLOCK_LEN];
#[derive(Clone, Copy)]
#[allow(clippy::upper_case_acronyms)]
pub enum Implementation {
#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
#[cfg(all(
perlasm,
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
)
))]
HWAES,

// On "arm" only, this indicates that the bsaes implementation may be used.
#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
#[cfg(all(
perlasm,
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
)
))]
VPAES_BSAES,

Expand All @@ -458,36 +482,39 @@ pub enum Implementation {

fn detect_implementation(cpu_features: cpu::Features) -> Implementation {
// `cpu_features` is only used for specific platforms.
#[cfg(not(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
#[cfg(not(all(
perlasm,
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
)
)))]
let _cpu_features = cpu_features;

#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
#[cfg(all(perlasm, any(target_arch = "aarch64", target_arch = "arm")))]
{
if cpu::arm::AES.available(cpu_features) {
return Implementation::HWAES;
}
}

#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
#[cfg(all(perlasm, any(target_arch = "x86_64", target_arch = "x86")))]
{
if cpu::intel::AES.available(cpu_features) {
return Implementation::HWAES;
}
}

#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
#[cfg(all(perlasm, any(target_arch = "x86_64", target_arch = "x86")))]
{
if cpu::intel::SSSE3.available(cpu_features) {
return Implementation::VPAES_BSAES;
}
}

#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
#[cfg(all(perlasm, any(target_arch = "aarch64", target_arch = "arm")))]
{
if cpu::arm::NEON.available(cpu_features) {
return Implementation::VPAES_BSAES;
Expand Down
8 changes: 4 additions & 4 deletions src/aead/aes_gcm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ fn aes_gcm_seal(
let mut ctr = Counter::one(nonce);
let tag_iv = ctr.increment();

#[cfg(target_arch = "x86_64")]
#[cfg(all(perlasm, target_arch = "x86_64"))]
let in_out = {
if !aes_key.is_aes_hw(cpu_features) || !auth.is_avx() {
in_out
Expand Down Expand Up @@ -124,7 +124,7 @@ fn aes_gcm_seal(

let (whole, remainder) = slice::as_chunks_mut(in_out);

#[cfg(target_arch = "aarch64")]
#[cfg(all(perlasm, target_arch = "aarch64"))]
let whole = {
if !aes_key.is_aes_hw(cpu_features) || !auth.is_clmul() {
whole
Expand Down Expand Up @@ -207,7 +207,7 @@ fn aes_gcm_open(

let in_prefix_len = src.start;

#[cfg(target_arch = "x86_64")]
#[cfg(all(perlasm, target_arch = "x86_64"))]
let in_out = {
if !aes_key.is_aes_hw(cpu_features) || !auth.is_avx() {
in_out
Expand Down Expand Up @@ -242,7 +242,7 @@ fn aes_gcm_open(
}
};

#[cfg(target_arch = "aarch64")]
#[cfg(all(perlasm, target_arch = "aarch64"))]
let in_out = {
if !aes_key.is_aes_hw(cpu_features) || !auth.is_clmul() {
in_out
Expand Down
Loading