Skip to content

Commit

Permalink
build.rs: Improve conditional compilation around PerlAsm.
Browse files Browse the repository at this point in the history
build.rs determines whether the target platform is supported by PerlAsm
using both target_arch and target_os. Instances of conditional
compilation in both src/ and crypto/ were using just target_arch to
determine whether PerlAsm symbols are present, resulting in link-time
build failures for certain targets, including, for example,
aarch64-unknown-none.

This commit fixes those instances of conditional compilation to align
with the build script.

I agree to license my contributions to each file under the terms given
at the top of each file I changed.
  • Loading branch information
nspin committed Apr 11, 2024
1 parent 6814023 commit 60a2951
Show file tree
Hide file tree
Showing 14 changed files with 274 additions and 180 deletions.
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 @@ -437,20 +455,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 = 1,

// 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 = 2,

Expand All @@ -459,36 +483,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 @@ -122,7 +122,7 @@ fn aes_gcm_seal(
}
};

#[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 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

0 comments on commit 60a2951

Please sign in to comment.