diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000000..b9ea2b819fb6 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[target.wasm32-unknown-emscripten] +rustflags = ["-C", "link-arg=-sSTACK_SIZE=1048576"] \ No newline at end of file diff --git a/.github/workflows/cross.yml b/.github/workflows/cross.yml index cf971aa0c935..b9a90673f0f8 100644 --- a/.github/workflows/cross.yml +++ b/.github/workflows/cross.yml @@ -63,6 +63,7 @@ jobs: - [ riscv64gc-unknown-linux-gnu, 0, 0, 1] - [ s390x-unknown-linux-gnu, 0, 0, 1] - [ x86_64-pc-windows-gnu, 0, 0, 1] # Requires release build. See: https://github.com/rust-lang/rust/issues/139380 + - [ wasm32-unknown-emscripten, 0, 0, 0] - [ x86_64-unknown-illumos, 0, 0, 1] - [ x86_64-unknown-linux-musl, 0, 0, 1] steps: diff --git a/Cross.toml b/Cross.toml index 0bd24c8e8522..f622b45f9df5 100644 --- a/Cross.toml +++ b/Cross.toml @@ -41,6 +41,9 @@ image = "ghcr.io/cross-rs/mips64-unknown-linux-muslabi64:edge" build-std = true image = "ghcr.io/cross-rs/mips64el-unknown-linux-muslabi64:edge" +[target.wasm32-unknown-emscripten.dockerfile] +file = "./docker/emscripten/Dockerfile" + [build.env] passthrough = [ "AWS_LC_FIPS_SYS_EXTERNAL_BINDGEN", diff --git a/aws-lc-rs/Cross.toml b/aws-lc-rs/Cross.toml deleted file mode 100644 index 11424db862c7..000000000000 --- a/aws-lc-rs/Cross.toml +++ /dev/null @@ -1,10 +0,0 @@ -[build] -dockerfile = "../docker/linux-cross/Dockerfile" - -[build.env] -passthrough = [ - "CROSS_CMAKE_SYSTEM_PROCESSOR", - "RUST_BACKTRACE", - "RUST_LOG", - "AWS_LC_RS_DISABLE_SLOW_TESTS", -] diff --git a/aws-lc-rs/src/signature.rs b/aws-lc-rs/src/signature.rs index 45f2553c775b..97cee521b8cc 100644 --- a/aws-lc-rs/src/signature.rs +++ b/aws-lc-rs/src/signature.rs @@ -226,11 +226,13 @@ //! } //! //! fn main() { +//! # if !cfg!(target_arch = "wasm32") { //! let private_key_path = //! std::path::Path::new("tests/data/signature_rsa_example_private_key.der"); //! let public_key_path = //! std::path::Path::new("tests/data/signature_rsa_example_public_key.der"); //! sign_and_verify_rsa(&private_key_path, &public_key_path).unwrap() +//! # } //! } //! ``` use crate::aws_lc::EVP_PKEY; diff --git a/aws-lc-rs/tests/aead_test.rs b/aws-lc-rs/tests/aead_test.rs index 0a8f18a55c5e..8c6b6e80c572 100644 --- a/aws-lc-rs/tests/aead_test.rs +++ b/aws-lc-rs/tests/aead_test.rs @@ -570,6 +570,7 @@ fn test_aead_traits() { } #[test] +#[cfg(not(target_arch = "wasm32"))] fn test_aead_thread_safeness() { lazy_static::lazy_static! { /// Compute the Initial salt once, as the seed is constant diff --git a/aws-lc-rs/tests/digest_test.rs b/aws-lc-rs/tests/digest_test.rs index 54034e78e2e7..7ede9fe46599 100644 --- a/aws-lc-rs/tests/digest_test.rs +++ b/aws-lc-rs/tests/digest_test.rs @@ -79,9 +79,6 @@ mod digest_shavs { }; use aws_lc_rs::{digest, test_file}; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - #[test] fn short_msg_known_answer_test() { run_known_answer_test( diff --git a/aws-lc-rs/tests/hkdf_test.rs b/aws-lc-rs/tests/hkdf_test.rs index b3b67403b27f..afeeb5a8bf7e 100644 --- a/aws-lc-rs/tests/hkdf_test.rs +++ b/aws-lc-rs/tests/hkdf_test.rs @@ -176,6 +176,7 @@ fn hkdf_clone_tests() { } #[test] +#[cfg(not(target_arch = "wasm32"))] fn hkdf_thread_safeness() { use std::thread; diff --git a/aws-lc-rs/tests/hmac_test.rs b/aws-lc-rs/tests/hmac_test.rs index a3136196c600..966eac2e9b66 100644 --- a/aws-lc-rs/tests/hmac_test.rs +++ b/aws-lc-rs/tests/hmac_test.rs @@ -102,6 +102,7 @@ fn hmac_traits() { } #[test] +#[cfg(not(target_arch = "wasm32"))] fn hmac_thread_safeness() { use std::thread; lazy_static::lazy_static! { diff --git a/aws-lc-rs/tests/rand_test.rs b/aws-lc-rs/tests/rand_test.rs index e3cef0bd5bef..ca88d141c4ca 100644 --- a/aws-lc-rs/tests/rand_test.rs +++ b/aws-lc-rs/tests/rand_test.rs @@ -6,12 +6,6 @@ use aws_lc_rs::rand::{self, SecureRandom as _}; use aws_lc_rs::test; -#[cfg(target_arch = "wasm32")] -use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure}; - -#[cfg(target_arch = "wasm32")] -wasm_bindgen_test_configure!(run_in_browser); - #[test] fn test_system_random_lengths() { const LINUX_LIMIT: usize = 256; diff --git a/builder/cc_builder.rs b/builder/cc_builder.rs index 95cacb048373..8f413731ce71 100644 --- a/builder/cc_builder.rs +++ b/builder/cc_builder.rs @@ -17,6 +17,8 @@ mod win_aarch64; mod win_x86; mod win_x86_64; +use cc::Build; + use crate::nasm_builder::NasmBuilder; use crate::{ cargo_env, disable_jitter_entropy, emit_warning, env_name_for_target, env_var_to_bool, @@ -294,14 +296,14 @@ impl CcBuilder { if !is_like_msvc { build_options.push(BuildOption::flag("-Wno-unused-parameter")); build_options.push(BuildOption::flag("-pthread")); - if target_os() == "linux" { + if target_os() == "linux" || target_os() == "emscripten" { build_options.push(BuildOption::define("_XOPEN_SOURCE", "700")); } else if target_vendor() != "apple" { // Needed by illumos build_options.push(BuildOption::define("__EXTENSIONS__", "1")); } } - if Some(true) == disable_jitter_entropy() { + if disable_jitter_entropy() { build_options.push(BuildOption::define("DISABLE_CPU_JITTER_ENTROPY", "1")); } self.add_includes(&mut build_options); @@ -339,7 +341,7 @@ impl CcBuilder { .join("include"), )); - if Some(true) != disable_jitter_entropy() { + if !disable_jitter_entropy() { build_options.push(BuildOption::include( self.manifest_dir .join("aws-lc") @@ -506,18 +508,23 @@ impl CcBuilder { )); s2n_bignum_builder.define("S2N_BN_HIDE_SYMBOLS", "1"); - // CPU Jitter Entropy is compiled separately due to needing specific flags - let mut jitter_entropy_builder = - self.prepare_jitter_entropy_builder(compiler.is_like_msvc()); - jitter_entropy_builder.flag(format!( - "{}{}", - force_include_option, - self.manifest_dir - .join("generated-include") - .join("openssl") - .join("boringssl_prefix_symbols.h") - .display() - )); + let mut jitter_entropy_builder = if disable_jitter_entropy() { + Build::new() + } else { + // CPU Jitter Entropy is compiled separately due to needing specific flags + let mut jitter_entropy_builder = + self.prepare_jitter_entropy_builder(compiler.is_like_msvc()); + jitter_entropy_builder.flag(format!( + "{}{}", + force_include_option, + self.manifest_dir + .join("generated-include") + .join("openssl") + .join("boringssl_prefix_symbols.h") + .display() + )); + jitter_entropy_builder + }; let mut build_options = vec![]; self.add_includes(&mut build_options); @@ -561,7 +568,7 @@ impl CcBuilder { } } else if is_jitter_entropy { // Only compile if not disabled. - if Some(true) != disable_jitter_entropy() { + if !disable_jitter_entropy() { jitter_entropy_builder.file(source_path); } } else if source_path.extension() == Some("asm".as_ref()) { @@ -575,7 +582,7 @@ impl CcBuilder { for object in s2n_bignum_object_files { cc_build.object(object); } - if Some(true) != disable_jitter_entropy() { + if !disable_jitter_entropy() { let _je_cflags_guard = Self::jitter_entropy_cflags_guard(compiler.is_like_msvc()); let jitter_entropy_object_files = jitter_entropy_builder.compile_intermediates(); for object in jitter_entropy_object_files { diff --git a/builder/cmake_builder.rs b/builder/cmake_builder.rs index 7461b13dd5bf..ba5d93181678 100644 --- a/builder/cmake_builder.rs +++ b/builder/cmake_builder.rs @@ -171,7 +171,7 @@ impl CmakeBuilder { cmake_cfg.define("DISABLE_PERL", "ON"); cmake_cfg.define("DISABLE_GO", "ON"); } - if Some(true) == disable_jitter_entropy() { + if disable_jitter_entropy() { cmake_cfg.define("DISABLE_CPU_JITTER_ENTROPY", "ON"); } diff --git a/builder/main.rs b/builder/main.rs index 66a012da84c7..44ff93fb31c4 100644 --- a/builder/main.rs +++ b/builder/main.rs @@ -702,8 +702,11 @@ fn is_no_pregenerated_src() -> bool { unsafe { SYS_NO_PREGENERATED_SRC } } -fn disable_jitter_entropy() -> Option { - unsafe { SYS_NO_JITTER_ENTROPY } +fn disable_jitter_entropy() -> bool { + match unsafe { SYS_NO_JITTER_ENTROPY } { + Some(x) => x, + None => target_arch().starts_with("wasm"), + } } fn use_no_u1_bindings() -> Option { diff --git a/docker/emscripten/Dockerfile b/docker/emscripten/Dockerfile new file mode 100644 index 000000000000..6da008bbbda1 --- /dev/null +++ b/docker/emscripten/Dockerfile @@ -0,0 +1,46 @@ +ARG CROSS_BASE_IMAGE=ghcr.io/cross-rs/wasm32-unknown-emscripten:main +FROM $CROSS_BASE_IMAGE + +ARG DEBIAN_FRONTEND=noninteractive +ARG GO_VERSION=1.23.8 +ARG EMSDK_VERSION=3.1.74 +ARG NODE_VERSION=20.18.0 + +# Install system dependencies and Go +RUN apt-get update && \ + apt-get install --assume-yes --no-install-recommends \ + build-essential cmake clang ca-certificates curl git python3 xz-utils && \ + ARCH=$(dpkg --print-architecture) && \ + curl -sL "https://go.dev/dl/go${GO_VERSION}.linux-${ARCH}.tar.gz" | tar -C /usr/local -xz && \ + git config --global --add safe.directory '*' && \ + rm -rf /var/lib/apt/lists/* /tmp/* + +# Install Node.js 20 LTS +# The cross-rs base image bundles an older Node.js that doesn't support the +# WebAssembly Exception Handling proposal, which modern Rust compilers generate +# for the wasm32-unknown-emscripten target. +RUN ARCH=$(uname -m | sed 's/x86_64/x64/' | sed 's/aarch64/arm64/') && \ + curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${ARCH}.tar.xz" | \ + tar -xJ -C /usr/local --strip-components=1 + +# Install a fresh Emscripten SDK (the base image's /emsdk is not a git repo) +RUN rm -rf /emsdk && \ + git clone https://github.com/emscripten-core/emsdk.git /emsdk && \ + cd /emsdk && \ + ./emsdk install ${EMSDK_VERSION} && \ + ./emsdk activate ${EMSDK_VERSION} && \ + chmod -R a+rwX /emsdk + +# Ensure the newly installed Node.js is used by Emscripten and the test runner +# rather than the older version bundled with the SDK +ENV EMSDK_NODE=/usr/local/bin/node +ENV PATH="/usr/local/bin:/usr/local/go/bin:${PATH}" + +# Install bindgen-cli +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable && \ + . $HOME/.cargo/env && \ + cargo install --force --locked bindgen-cli && \ + mv $HOME/.cargo/bin/bindgen /usr/bin && \ + rm -rf $HOME/.cargo + +ENV GOCACHE=/tmp \ No newline at end of file