diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 60d729207acc8efa0823432b1ca050ae7cadb494..4d2df5397bcd0290aee748d8af6ba2bb05c53c81 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -153,7 +153,7 @@ jobs: - false library: - name: boringssl - version: 5697a9202615925696f8dc7f4e286d44d474769e + version: 93e8d4463d59d671e9c5c6171226341f04b07907 - name: openssl version: vendored - name: openssl @@ -212,10 +212,6 @@ jobs: library: name: libressl version: 3.7.0 - exclude: - - library: - name: boringssl - bindgen: true name: ${{ matrix.target }}-${{ matrix.library.name }}-${{ matrix.library.version }}-${{ matrix.bindgen }} runs-on: ubuntu-latest env: @@ -308,16 +304,26 @@ jobs: make install_sw ;; "boringssl") - sed -i rust/CMakeLists.txt -e '1s%^%include_directories(../include)\n%' - cpu=`echo ${{ matrix.target }} | cut -d - -f 1` + mkdir build + cd build + echo "set(CMAKE_SYSTEM_NAME Linux)" > toolchain.cmake echo "set(CMAKE_SYSTEM_PROCESSOR $cpu)" >> toolchain.cmake echo "set(triple ${{ matrix.target }})" >> toolchain.cmake echo 'set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} '$OS_FLAGS '" CACHE STRING "c++ flags")' >> toolchain.cmake echo 'set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} '$OS_FLAGS '" CACHE STRING "c flags")' >> toolchain.cmake echo 'set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} '$OS_FLAGS '" CACHE STRING "asm flags")' >> toolchain.cmake - cmake -DRUST_BINDINGS="${{ matrix.target }}" -B $OPENSSL_DIR -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake - make -C $OPENSSL_DIR + + cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DRUST_BINDINGS="${{ matrix.target }}" -DCMAKE_INSTALL_PREFIX="${OPENSSL_DIR}" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake + make -j "$(nproc)" + make install + + # Copy stuff around so it's all as the build system expects. + cp -r rust/ "$OPENSSL_DIR/rust" + mkdir -p "$OPENSSL_DIR/crypto/" + mkdir -p "$OPENSSL_DIR/ssl/" + cp "$OPENSSL_DIR/lib/libcrypto.a" "$OPENSSL_DIR/crypto/" + cp "$OPENSSL_DIR/lib/libssl.a" "$OPENSSL_DIR/ssl/" esac if: matrix.library.version != 'vendored' && !steps.openssl-cache.outputs.cache-hit @@ -325,7 +331,7 @@ jobs: mkdir -p .cargo echo '[patch.crates-io]' > .cargo/config.toml echo 'bssl-sys = { path = "'$OPENSSL_DIR'/rust" }' >> .cargo/config.toml - if: matrix.library.name == 'boringssl' + if: matrix.library.name == 'boringssl' && !matrix.bindgen - uses: actions/cache@v3 with: path: ~/.cargo/registry/index @@ -347,14 +353,14 @@ jobs: if [[ "${{ matrix.library.version }}" == "vendored" ]]; then features="--features vendored" fi - if [[ "${{ matrix.bindgen }}" == "true" ]]; then + if [[ "${{ matrix.bindgen }}" == "true" && "${{ matrix.library.name }}" != "boringssl" ]]; then features="$features --features bindgen" fi cargo run --manifest-path=systest/Cargo.toml --target ${{ matrix.target }} $features if: matrix.library.name != 'boringssl' - name: Test openssl run: | - if [[ "${{ matrix.library.name }}" == "boringssl" ]]; then + if [[ "${{ matrix.library.name }}" == "boringssl" && "${{ matrix.bindgen }}" != "true" ]]; then features="--features unstable_boringssl" fi if [[ "${{ matrix.library.version }}" == "vendored" ]]; then diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 7b5c8104d8121a88b7afe52b39a050421a0b3809..4f057bf9faae094888d27ef2d18e04112b833ec7 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -23,7 +23,7 @@ libc = "0.2" bssl-sys = { version = "0.1.0", optional = true } [build-dependencies] -bindgen = { version = "0.60.1", optional = true } +bindgen = { version = "0.64.0", optional = true, features = ["experimental"] } cc = "1.0" openssl-src = { version = "111", optional = true } pkg-config = "0.3.9" diff --git a/openssl-sys/build/main.rs b/openssl-sys/build/main.rs index 262ea2cbabf46c969f7fa2170b06c3ca8e7fafa4..c5a68a630a940bf3afdc020813d290f321c24218 100644 --- a/openssl-sys/build/main.rs +++ b/openssl-sys/build/main.rs @@ -23,7 +23,6 @@ mod cfgs; mod find_normal; #[cfg(feature = "vendored")] mod find_vendored; -#[cfg(feature = "bindgen")] mod run_bindgen; #[derive(PartialEq)] @@ -32,6 +31,7 @@ enum Version { Openssl11x, Openssl10x, Libressl, + Boringssl, } fn env_inner(name: &str) -> Option { @@ -67,10 +67,9 @@ fn find_openssl(target: &str) -> (Vec, PathBuf) { fn check_ssl_kind() { if cfg!(feature = "unstable_boringssl") { println!("cargo:rustc-cfg=boringssl"); + println!("cargo:boringssl=true"); // BoringSSL does not have any build logic, exit early std::process::exit(0); - } else { - println!("cargo:rustc-cfg=openssl"); } } @@ -146,8 +145,12 @@ fn check_rustc_versions() { #[allow(clippy::let_and_return)] fn postprocess(include_dirs: &[PathBuf]) -> Version { let version = validate_headers(include_dirs); - #[cfg(feature = "bindgen")] - run_bindgen::run(&include_dirs); + + // Never run bindgen for BoringSSL, if it was needed we already ran it. + if version != Version::Boringssl { + #[cfg(feature = "bindgen")] + run_bindgen::run(&include_dirs); + } version } @@ -235,9 +238,15 @@ See rust-openssl documentation for more information: } if is_boringssl { - panic!("BoringSSL detected, but `unstable_boringssl` feature wasn't specified.") + println!("cargo:rustc-cfg=boringssl"); + println!("cargo:boringssl=true"); + run_bindgen::run_boringssl(include_dirs); + return Version::Boringssl; } + // We set this for any non-BoringSSL lib. + println!("cargo:rustc-cfg=openssl"); + for enabled in &enabled { println!("cargo:rustc-cfg=osslconf=\"{}\"", enabled); } diff --git a/openssl-sys/build/run_bindgen.rs b/openssl-sys/build/run_bindgen.rs index 9531e6e8bbd4313cd5d438d2c39cdbafb38d98e8..0c127ae5c602a8f86aeefc40726b48382f081667 100644 --- a/openssl-sys/build/run_bindgen.rs +++ b/openssl-sys/build/run_bindgen.rs @@ -1,13 +1,17 @@ +#[cfg(feature = "bindgen")] use bindgen::callbacks::{MacroParsingBehavior, ParseCallbacks}; -use bindgen::RustTarget; -use std::env; +#[cfg(feature = "bindgen")] +use bindgen::{MacroTypeVariation, RustTarget}; +use std::io::Write; use std::path::PathBuf; +#[cfg(not(feature = "bindgen"))] +use std::process; +use std::{env, fs}; const INCLUDES: &str = " #include #include #include -#include #include #include #include @@ -17,7 +21,6 @@ const INCLUDES: &str = " #include #include #include -#include #include #include #include @@ -35,10 +38,15 @@ const INCLUDES: &str = " // this must be included after ssl.h for libressl! #include -#if !defined(LIBRESSL_VERSION_NUMBER) +#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL) #include #endif +#if !defined(OPENSSL_IS_BORINGSSL) +#include +#include +#endif + #if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000 #include #endif @@ -48,6 +56,7 @@ const INCLUDES: &str = " #endif "; +#[cfg(feature = "bindgen")] pub fn run(include_dirs: &[PathBuf]) { let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); @@ -94,9 +103,107 @@ pub fn run(include_dirs: &[PathBuf]) { .unwrap(); } +#[cfg(feature = "bindgen")] +pub fn run_boringssl(include_dirs: &[PathBuf]) { + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let mut builder = bindgen::builder() + .rust_target(RustTarget::Stable_1_47) + .ctypes_prefix("::libc") + .derive_default(false) + .enable_function_attribute_detection() + .size_t_is_usize(true) + .default_macro_constant_type(MacroTypeVariation::Signed) + .rustified_enum("point_conversion_form_t") + .allowlist_file(".*/openssl/[^/]+\\.h") + .wrap_static_fns(true) + .wrap_static_fns_path(out_dir.join("boring_static_wrapper").display().to_string()) + .layout_tests(false) + .header_contents("includes.h", INCLUDES); + + for include_dir in include_dirs { + builder = builder + .clang_arg("-I") + .clang_arg(include_dir.display().to_string()); + } + + builder + .generate() + .unwrap() + .write_to_file(out_dir.join("bindgen.rs")) + .unwrap(); + + fs::File::create(out_dir.join("boring_static_wrapper.h")) + .expect("Failed to create boring_static_wrapper.h") + .write_all(INCLUDES.as_bytes()) + .expect("Failed to write contents to boring_static_wrapper.h"); + + cc::Build::new() + .file(out_dir.join("boring_static_wrapper.c")) + .includes(include_dirs) + .flag("-include") + .flag( + &out_dir + .join("boring_static_wrapper.h") + .display() + .to_string(), + ) + .compile("boring_static_wrapper"); +} + +#[cfg(not(feature = "bindgen"))] +pub fn run_boringssl(include_dirs: &[PathBuf]) { + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + fs::File::create(out_dir.join("boring_static_wrapper.h")) + .expect("Failed to create boring_static_wrapper.h") + .write_all(INCLUDES.as_bytes()) + .expect("Failed to write contents to boring_static_wrapper.h"); + + let mut bindgen_cmd = process::Command::new("bindgen"); + bindgen_cmd + .arg("-o") + .arg(out_dir.join("bindgen.rs")) + .arg("--rust-target=1.47") + .arg("--ctypes-prefix=::libc") + .arg("--no-derive-default") + .arg("--enable-function-attribute-detection") + .arg("--size_t-is-usize") + .arg("--default-macro-constant-type=signed") + .arg("--rustified-enum=point_conversion_form_t") + .arg("--allowlist-file=.*/openssl/[^/]+\\.h") + .arg("--experimental") + .arg("--wrap-static-fns") + .arg("--wrap-static-fns-path") + .arg(out_dir.join("boring_static_wrapper").display().to_string()) + .arg("--no-layout-tests") + .arg(out_dir.join("boring_static_wrapper.h")) + .arg("--") + .arg(format!("--target={}", env::var("TARGET").unwrap())); + + for include_dir in include_dirs { + bindgen_cmd.arg("-I").arg(include_dir.display().to_string()); + } + + let result = bindgen_cmd.status().expect("bindgen failed to execute"); + assert!(result.success()); + + cc::Build::new() + .file(out_dir.join("boring_static_wrapper.c")) + .includes(include_dirs) + .flag("-include") + .flag( + &out_dir + .join("boring_static_wrapper.h") + .display() + .to_string(), + ) + .compile("boring_static_wrapper"); +} + #[derive(Debug)] struct OpensslCallbacks; +#[cfg(feature = "bindgen")] impl ParseCallbacks for OpensslCallbacks { // for now we'll continue hand-writing constants fn will_parse_macro(&self, _name: &str) -> MacroParsingBehavior { diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index b1d51a858050531f517aab526d6096f6e1ec0b3d..c3084755cce60dd737377c4d2f756478e0a9e45c 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -16,11 +16,25 @@ extern crate libc; pub use libc::*; -#[cfg(boringssl)] +#[cfg(feature = "unstable_boringssl")] extern crate bssl_sys; -#[cfg(boringssl)] +#[cfg(feature = "unstable_boringssl")] pub use bssl_sys::*; +#[cfg(all(boringssl, not(feature = "unstable_boringssl")))] +#[path = "."] +mod boringssl { + include!(concat!(env!("OUT_DIR"), "/bindgen.rs")); + + pub fn init() { + unsafe { + CRYPTO_library_init(); + } + } +} +#[cfg(all(boringssl, not(feature = "unstable_boringssl")))] +pub use boringssl::*; + #[cfg(openssl)] #[path = "."] mod openssl { diff --git a/openssl/build.rs b/openssl/build.rs index 7651429f380c79703abaf2a8b4457a2853887a2a..5cddce90c267d4e1a9fe65ebb8682777703240df 100644 --- a/openssl/build.rs +++ b/openssl/build.rs @@ -11,7 +11,7 @@ fn main() { println!("cargo:rustc-cfg=libressl"); } - if env::var("CARGO_FEATURE_UNSTABLE_BORINGSSL").is_ok() { + if env::var("DEP_OPENSSL_BORINGSSL").is_ok() { println!("cargo:rustc-cfg=boringssl"); return; } diff --git a/openssl/src/bio.rs b/openssl/src/bio.rs index 6a72552adc5497712787278ea420cf089bf21045..0f54935a6be335d817310b9306c6de28d9007456 100644 --- a/openssl/src/bio.rs +++ b/openssl/src/bio.rs @@ -25,7 +25,7 @@ impl<'a> MemBioSlice<'a> { let bio = unsafe { cvt_p(BIO_new_mem_buf( buf.as_ptr() as *const _, - buf.len() as c_int, + buf.len() as crate::SLenType, ))? }; @@ -74,7 +74,7 @@ impl MemBio { } cfg_if! { - if #[cfg(ossl102)] { + if #[cfg(any(ossl102, boringssl))] { use ffi::BIO_new_mem_buf; } else { #[allow(bad_style)] diff --git a/openssl/src/dh.rs b/openssl/src/dh.rs index 12170b994e411a7c7280e899accf33a75a97ff5b..e781543e2732c0b75cef3f9a53de7e5d915e5303 100644 --- a/openssl/src/dh.rs +++ b/openssl/src/dh.rs @@ -239,7 +239,7 @@ where } cfg_if! { - if #[cfg(any(ossl110, libressl270))] { + if #[cfg(any(ossl110, libressl270, boringssl))] { use ffi::{DH_set0_pqg, DH_get0_pqg, DH_get0_key, DH_set0_key}; } else { #[allow(bad_style)] diff --git a/openssl/src/error.rs b/openssl/src/error.rs index 58b4d70a38c28111d4545ca8cc624a270ea01191..f9a7c54b8f9ee52a1ad85fcfab9d9db75bd8cdff 100644 --- a/openssl/src/error.rs +++ b/openssl/src/error.rs @@ -297,19 +297,24 @@ impl fmt::Debug for Error { } impl fmt::Display for Error { + // On BoringSSL ERR_GET_{LIB,FUNC,REASON} are `unsafe`, but on + // OpenSSL/LibreSSL they're safe. + #[allow(unused_unsafe)] fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { write!(fmt, "error:{:08X}", self.code())?; match self.library() { Some(l) => write!(fmt, ":{}", l)?, - None => write!(fmt, ":lib({})", ffi::ERR_GET_LIB(self.code()))?, + None => write!(fmt, ":lib({})", unsafe { ffi::ERR_GET_LIB(self.code()) })?, } match self.function() { Some(f) => write!(fmt, ":{}", f)?, - None => write!(fmt, ":func({})", ffi::ERR_GET_FUNC(self.code()))?, + None => write!(fmt, ":func({})", unsafe { ffi::ERR_GET_FUNC(self.code()) })?, } match self.reason() { Some(r) => write!(fmt, ":{}", r)?, - None => write!(fmt, ":reason({})", ffi::ERR_GET_REASON(self.code()))?, + None => write!(fmt, ":reason({})", unsafe { + ffi::ERR_GET_REASON(self.code()) + })?, } write!( fmt, diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 8988f4c3c03f28ea8ee58f86dfb28a4374df1530..5678298a038cd368d3a2991787b7d65209f34184 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -190,6 +190,11 @@ type LenType = libc::size_t; #[cfg(not(boringssl))] type LenType = libc::c_int; +#[cfg(boringssl)] +type SLenType = libc::ssize_t; +#[cfg(not(boringssl))] +type SLenType = libc::c_int; + #[inline] fn cvt_p(r: *mut T) -> Result<*mut T, ErrorStack> { if r.is_null() {