diff --git a/.github/workflows/bindgen.yml b/.github/workflows/bindgen.yml index 9b448ece..1783dc40 100644 --- a/.github/workflows/bindgen.yml +++ b/.github/workflows/bindgen.yml @@ -41,6 +41,8 @@ jobs: sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu } + - uses: Swatinem/rust-cache@v2 + - name: Generate bindings shell: pwsh run: | diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml new file mode 100644 index 00000000..eb00eb76 --- /dev/null +++ b/.github/workflows/build_linux.yml @@ -0,0 +1,77 @@ +name: Build Linux + +on: + push: + branches: [ "main" ] + pull_request: + +env: + CARGO_TERM_COLOR: always + FEATURES_TO_TEST: md5,sha1,pkcs1-encrypt-decrypt + +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - target: x86_64-unknown-linux-gnu + os: ubuntu-latest + runs-on: ubuntu-latest + run-tests: true + - target: aarch64-unknown-linux-gnu + os: ubuntu-24.04-arm + runs-on: ubuntu-24.04-arm + run-tests: true + + runs-on: ${{ matrix.os }} + name: ${{ matrix.target }} + env: + CARGO_BUILD_TARGET: ${{ matrix.target }} + + steps: + - uses: actions/checkout@v4 # Checks out SymCrypt based on Github submodule + with: + submodules: true + + - uses: Swatinem/rust-cache@v2 + + # Download SymCrypt via PMC + - name: Install SymCrypt via PMC + shell: bash + run: | + curl -sSL -O https://packages.microsoft.com/config/ubuntu/24.04/packages-microsoft-prod.deb + sudo dpkg -i packages-microsoft-prod.deb + sudo apt-get update + sudo apt-get install -y symcrypt + + - name: Install host target + shell: pwsh + run: | + rustup target add ${{ matrix.target }} + if ("${{ matrix.target }}" -match "aarch64-unknown-linux-gnu") { + sudo apt update + sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu + } + + - name: Debug build + run: cargo build --locked --verbose --target ${{ matrix.target }} + + - name: Release build + run: cargo build --release --locked --verbose --target ${{ matrix.target }} + + - name: Run tests (Debug, dynamic) + if: matrix.run-tests + run: cargo test --locked --verbose --all-features --target ${{ matrix.target }} + + - name: Run tests (Release, dynamic) + if: matrix.run-tests + run: cargo test --release --locked --verbose --all-features --target ${{ matrix.target }} + + - name: Run test (Debug, static) + if: matrix.run-tests + run: cargo test --features ${{ env.FEATURES_TO_TEST }} --locked --target ${{ matrix.target }} + + - name: Run test (Release, static) + if: matrix.run-tests + run: cargo test --features ${{ env.FEATURES_TO_TEST }} --locked --target ${{ matrix.target }} diff --git a/.github/workflows/build.yml b/.github/workflows/build_windows.yml similarity index 50% rename from .github/workflows/build.yml rename to .github/workflows/build_windows.yml index 5ccd4ed4..fd711e3b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build_windows.yml @@ -1,85 +1,76 @@ -name: Build - -on: - push: - branches: [ "main" ] - pull_request: - -env: - CARGO_TERM_COLOR: always - -jobs: - build: - strategy: - fail-fast: false - matrix: - include: - - target: x86_64-pc-windows-msvc - os: windows-latest - symcrypt: "https://github.com/microsoft/SymCrypt/releases/download/v103.8.0/symcrypt-windows-amd64-release-103.8.0-53be637d.zip" - run-tests: true - - target: aarch64-pc-windows-msvc - os: windows-latest - symcrypt: "https://github.com/microsoft/SymCrypt/releases/download/v103.8.0/symcrypt-windows-arm64-release-103.8.0-53be637d.zip" - run-tests: false # Windows doesn't support ARM64 emulation - - target: x86_64-unknown-linux-gnu - symcrypt: "https://github.com/microsoft/SymCrypt/releases/download/v103.8.0/symcrypt-linux-generic-amd64-release-103.8.0-53be637.tar.gz" - os: ubuntu-latest - run-tests: true - - target: aarch64-unknown-linux-gnu - os: ubuntu-latest - symcrypt: "https://github.com/microsoft/SymCrypt/releases/download/v103.8.0/symcrypt-linux-generic-arm64-release-103.8.0-53be637.tar.gz" - run-tests: false - - runs-on: ${{ matrix.os }} - name: ${{ matrix.target }} - env: - CARGO_BUILD_TARGET: ${{ matrix.target }} - - steps: - - uses: actions/checkout@v4 - - - name: Install host target - shell: pwsh - run: | - rustup target add ${{ matrix.target }} - if ("${{ matrix.target }}" -match "aarch64-unknown-linux-gnu") { - sudo apt update - sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu - } - - - name: Download SymCrypt - shell: pwsh - run: | - $dir = $(Get-Item .).FullName - if ("${{ matrix.symcrypt }}" -match "\.tar\.gz$") { - Invoke-WebRequest -Uri ${{ matrix.symcrypt }} -OutFile symcrypt.tar.gz - New-Item -ItemType Directory -Force -Path symcrypt - tar -xzf symcrypt.tar.gz -C symcrypt - echo "$dir/symcrypt/lib" >> $env:GITHUB_PATH - echo "LD_LIBRARY_PATH=$dir/symcrypt/lib:$env:LD_LIBRARY_PATH" >> $env:GITHUB_ENV - echo "LIBRARY_PATH=$dir/symcrypt/lib:$env:LIBRARY_PATH" >> $env:GITHUB_ENV - echo "SYMCRYPT_LIB_PATH=$dir/symcrypt/lib" >> $env:GITHUB_ENV - } else { - Invoke-WebRequest -Uri ${{ matrix.symcrypt }} -OutFile symcrypt.zip - New-Item -ItemType Directory -Force -Path symcrypt - Expand-Archive -Path symcrypt.zip -DestinationPath symcrypt - echo "$dir/symcrypt/dll" >> $env:GITHUB_PATH - echo "SYMCRYPT_LIB_PATH=$dir/symcrypt/dll" >> $env:GITHUB_ENV - } - - - name: Debug build - run: cargo build --locked --verbose --target ${{ matrix.target }} - - - name: Release build - run: cargo build --release --locked --verbose --target ${{ matrix.target }} - - - name: Run tests (Debug) - if: matrix.run-tests - shell: pwsh - run: cargo test --locked --verbose --all-features --target ${{ matrix.target }} - - - name: Run tests (Release) - if: matrix.run-tests - shell: pwsh - run: cargo test --release --locked --verbose --all-features --target ${{ matrix.target }} +name: Build Windows + +on: + push: + branches: [ "main" ] + pull_request: + +env: + CARGO_TERM_COLOR: always + FEATURES_TO_TEST: md5,sha1,pkcs1-encrypt-decrypt + +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - target: x86_64-pc-windows-msvc + os: windows-latest + runs-on: windows-latest + symcrypt: "https://github.com/microsoft/SymCrypt/releases/download/v103.8.0/symcrypt-windows-amd64-release-103.8.0-53be637d.zip" + run-tests: true + - target: aarch64-pc-windows-msvc + os: windows-latest + runs-on: windows-latest + symcrypt: "https://github.com/microsoft/SymCrypt/releases/download/v103.8.0/symcrypt-windows-arm64-release-103.8.0-53be637d.zip" + run-tests: false # Windows doesn't support ARM64 emulation + runs-on: ${{ matrix.os }} + name: ${{ matrix.target }} + env: + CARGO_BUILD_TARGET: ${{ matrix.target }} + + steps: + - uses: actions/checkout@v4 # Checks out SymCrypt based on Github submodule + with: + submodules: true + + - uses: Swatinem/rust-cache@v2 + + # Install host architecture, required for cross-compilation since there is no arm64-windows-msvc runner + - name: Install host target + shell: pwsh + run: | + rustup target add ${{ matrix.target }} + + - name: Download SymCrypt and Set Environment Variables + shell: pwsh + run: | + Invoke-WebRequest -Uri ${{ matrix.symcrypt }} -OutFile symcrypt.zip + New-Item -ItemType Directory -Force -Path symcrypt + Expand-Archive -Path symcrypt.zip -DestinationPath symcrypt + echo "$env:GITHUB_WORKSPACE\symcrypt\dll" >> $env:GITHUB_PATH + echo "SYMCRYPT_LIB_PATH=$env:GITHUB_WORKSPACE\symcrypt\dll" >> $env:GITHUB_ENV + echo "PATH=$env:GITHUB_WORKSPACE\symcrypt\dll;$env:PATH" >> $env:GITHUB_ENV + + - name: Debug build + run: cargo build --locked --verbose --target ${{ matrix.target }} + + - name: Release build + run: cargo build --release --locked --verbose --target ${{ matrix.target }} + + - name: Run tests (Debug, dynamic) + if: matrix.run-tests + run: cargo test --locked --verbose --all-features --target ${{ matrix.target }} + + - name: Run tests (Release, dynamic) + if: matrix.run-tests + run: cargo test --release --locked --verbose --all-features --target ${{ matrix.target }} + + - name: Run test (Debug, static) + if: matrix.run-tests + run: cargo test --features ${{ env.FEATURES_TO_TEST }} --locked --target ${{ matrix.target }} + + - name: Run test (Release, static) + if: matrix.run-tests + run: cargo test --features ${{ env.FEATURES_TO_TEST }} --locked --target ${{ matrix.target }} diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 763ba9e0..88a4b90f 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -22,6 +22,8 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v4 + with: + submodules: true - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable diff --git a/Cargo.lock b/Cargo.lock index afc44e85..f33a0e30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,6 +49,15 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +[[package]] +name = "cc" +version = "1.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" +dependencies = [ + "shlex", +] + [[package]] name = "cexpr" version = "0.6.0" @@ -372,7 +381,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "symcrypt" -version = "0.5.1" +version = "0.6.0" dependencies = [ "hex", "lazy_static", @@ -393,8 +402,9 @@ dependencies = [ [[package]] name = "symcrypt-sys" -version = "0.4.0" +version = "0.5.0" dependencies = [ + "cc", "libc", ] diff --git a/rust-symcrypt/Cargo.toml b/rust-symcrypt/Cargo.toml index 6cb1fd6d..b1364357 100644 --- a/rust-symcrypt/Cargo.toml +++ b/rust-symcrypt/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "symcrypt" -authors = ["nnmkhang"] -version = "0.5.1" +authors = ["Microsoft"] +version = "0.6.0" license = "MIT OR Apache-2.0" description = "Friendly and Idiomatic Wrappers for SymCrypt" edition.workspace = true @@ -15,7 +15,7 @@ readme = "README.md" [dependencies] # uses '../symcrypt-sys' when compiled locally, and uses # crates.io versioning when published -symcrypt-sys = {path = "../symcrypt-sys", version = "0.4.0"} +symcrypt-sys = {path = "../symcrypt-sys", version = "0.5.0"} libc = "0.2.0" lazy_static = "1.4.0" @@ -24,6 +24,7 @@ default = [] md5 = [] sha1 = [] pkcs1-encrypt-decrypt = [] +dynamic = ["symcrypt-sys/dynamic"] [dev-dependencies] hex = "0.4.3" diff --git a/rust-symcrypt/INSTALL.md b/rust-symcrypt/INSTALL.md index bc0c47fe..fffd1460 100644 --- a/rust-symcrypt/INSTALL.md +++ b/rust-symcrypt/INSTALL.md @@ -1,48 +1,42 @@ -# Detailed Build and Install +# Detailed Build and Install for Dynamic Linking -This page provides more detailed installation instructions +This page provides more detailed installation instructions for dynamic linking on Windows and Linux. -## Installation -For ease of use, the recommended usage is to obtain these binaries from the official SymCrypt [Repo](https://github.com/microsoft/SymCrypt/releases/tag/v103.4.2). +The `symcrypt` crate is a wrapper on top of the `SymCrypt` library, and requires access to the `SymCrypt` library during the build and execution stage for dynamic linking. For ease of use, the recommended way to configure your `SymCrypt` library dependancy is to obtain the required binaries from the official [SymCrypt Repo](https://github.com/microsoft/SymCrypt/releases/tag/v103.8.0). -**Note:** If you wish to build your own version please follow the [Build Instructions](https://github.com/microsoft/SymCrypt/blob/main/BUILD.md) that are provided by SymCrypt to install SymCrypt for your target architecture. - -Once SymCrypt is installed on your machine, we must configure your machine so that the SymCrypt crate's build script can easily find `symcrypt.dll` and `symcrypt.lib` which are needed on Windows, or the `libsymcrypt.so*` files which are needed for Linux. +However, If you wish to build your own version of the underlying `SymCrypt` library please follow the [Build Instructions](https://github.com/microsoft/SymCrypt/blob/main/BUILD.md) that are provided by SymCrypt to install SymCrypt for your target architecture. ### Windows Install -The `symcrypt.lib` can be found in the the following path after SymCrypt has been downloaded and unzipped. +The `symcrypt.lib` can be found in the the following path after `SymCrypt` has been downloaded and unzipped. `C:\Your-Path-To-SymCrypt-Release-Download\dll\` -The SymCrypt crate needs to link against the SymCrypt import library during build. +The SymCrypt crate needs to link against the `SymCrypt` import library during build. To do so you must set the `SYMCRYPT_LIB_PATH` environment variable. You can do this by using the following command: `setx SYMCRYPT_LIB_PATH ""` - The `symcrypt.dll` can be found in the the following path after SymCrypt has been downloaded and unzipped. - `C:\Your-Path-To-SymCrypt-Release-Download\dll\` - During runtime, Windows will handle finding all needed `dll`'s in order to run the intended program, this includes our `symcrypt.dll` file. The places Windows will look are: - 1. The folder from which the application loaded. 2. The system folder. Use the `GetSystemDirectory` function to retrieve the path of this folder. 3. The Windows folder. Use the `GetWindowsDirectory` function to get the path of this folder. 4. The current folder. 5. The directories listed in the PATH environment variable. - For more info please see: [Dynamic-link library search order](https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order) - Here are 2 recommended options to ensure your `symcrypt.dll` is found by Windows during runtime. - 1. Put the `symcrypt.dll` in the same folder as your output `.exe` file. If you are doing development (not release), the common path will be: `C:\your-project\target\debug\`. 2. Permanently add the `symcrypt.dll` path into your System PATH environment variable. Doing this will ensure that any project that uses the SymCrypt crate will be able to access `symcrypt.lib` +**NOTE:** By setting the `SYMCRYPT_LIB_PATH` via `setx SYMCRYPT_LIB_PATH ""`; `symcrypt.dll` will already be on the `PATH` and you will not have to do any additional configuration for your program. + ### Linux Install +Though the artifacts on the [SymCrypt Repo](https://github.com/microsoft/SymCrypt/releases/tag/v103.8.0). Have been built with `Ubuntu` in mind, the `SymCrypt` library has been built with very few standard library dependencies and should work on most Linux distributions. + After installing and unzipping SymCrypt on a Linux distro, the required `libsymcrypt.so*` files can be found in the following path: `~/Your-Path-To-SymCrypt-Release-Download/lib/` -The symcrypt crate needs to be able to link with these libs during build/run time. In order to mimic the installation path for other libraries, you must place the `libsymcrypt.so*` files into linker load path. The way that this is set will vary between distros. On most distros it set via the environment variable `$LD_LIBRARY_PATH`. +The `symcrypt` crate needs to be able to link with these libs during build/run time. In order to mimic the installation path for other libraries, you must place the `libsymcrypt.so*` files into linker load path. The way that this is set will vary between distros. On most distros it set via the environment variable `$LD_LIBRARY_PATH`. diff --git a/rust-symcrypt/README.md b/rust-symcrypt/README.md index 3468c3bd..ae4de4fe 100644 --- a/rust-symcrypt/README.md +++ b/rust-symcrypt/README.md @@ -1,21 +1,23 @@ # SymCrypt Rust Wrapper - This crate provides friendly and idiomatic Rust wrappers over [SymCrypt](https://github.com/microsoft/SymCrypt), an open-source cryptographic library. This crate has a dependency on `symcrypt-sys`, which utilizes `bindgen` to create Rust/C FFI bindings. -**`symcrypt` version `0.5.1` is based off of `SymCrypt v103.4.2`.**. You must use a version that is greater than or equal to `SymCrypt v103.4.2`. +**`symcrypt` version `0.6.0` is based off of `SymCrypt v103.8.0`.** You must use a version that is greater than or equal to `SymCrypt v103.8.0`. To view a detailed list of changes please see the [releases page](https://github.com/microsoft/rust-symcrypt/releases/). ### Supported Configurations +| Operating Environment | Architecture | Dynamic Linking | Static Linking | +| --------------------- | ----------------- | --------------- | -------------- | +| Windows user mode | AMD64, ARM64 | ✅ | ✅ ⚠️ | +| Ubuntu | AMD64, ARM64 | ✅ | ✅ ⚠️ | +| Azure Linux 3 | AMD64, ARM64 | ✅ | ✅ ⚠️ | + +**Note:** ⚠️ Static linking is meant to be used for rapid development and testing. Static linking does not offer FIPS and is **not to be used in Microsoft production or release builds.** For more information please see the `Quick Start Guide` below. -| Operating Environment | Architecture | Dynamic Linking | -| --------------------- | ----------------- | ----------- | -| Windows user mode | AMD64, ARM64 | ✅ | -| Ubuntu | AMD64, ARM64 | ✅ | -| Azure Linux 3 | AMD64, ARM64 | ✅ | +--- ## Supported APIs @@ -62,69 +64,88 @@ To enable either `Md5` or `Sha1`, or `Pkcs1 Encrypt/Decrypt` pass the `md5` or ` --- - ## Quick Start Guide -`symcrypt` requires the `SymCrypt` library to be present at both build time and run time. +As of version `0.6.0`, the `symcrypt` crate can take advantage of both static and dynamic linking. Static linking is enabled by default. + +--- +## Static Linking: + +**NOTE: Static linking should not be used in production and or release builds for Microsoft 1st Party. If you are Microsoft employee please contact the SymCrypt team for more info.** + +Static linking works by building the `SymCrypt` library from source and static linking to lib that is produced, this will result in longer build times and larger binaries but gives the added benefit of not worrying about the distribution of a dynamic library. Static linking is enabled by default. +--- + +## Dynamic Linking: + +Dynamic linking assumes is required for FIPS. If the `dynamic` flag is set, the `symcrypt` crate will operate under the assumption that you have followed following instructions for configuring your system to do a dynamic link of the `SymCrypt` library. + +```cargo +[dependencies] +symcrypt = {vesrion = "0.6.0", features = ["dynamic"]} +hex = "0.4.3" +``` ### Windows: Download the latest `symcrypt.dll` and `symcrypt.lib` for your corresponding CPU architecture from the [SymCrypt Releases Page](https://github.com/microsoft/SymCrypt/releases) and place them somewhere accessible on your machine. Set the required `SYMCRYPT_LIB_PATH` environment variable. You can do this by using the following command: - `setx SYMCRYPT_LIB_PATH ""` You will need to restart `terminal` / `cmd` after setting the environment variable. -For more information please see the `INSTALL.md` file on the [`rust-symcrypt`](https://github.com/microsoft/rust-symcrypt/tree/main/rust-symcrypt) page. +For more information please see `INSTALL.md`. ### Linux: #### Azure Linux 3: SymCrypt is pre-installed on Azure Linux 3 machines. Please ensure that you have the most up to date version of SymCrypt by updating via `tdnf`. - #### Other distros: -For Ubuntu, you can install SymCrypt via package manager by connecting to PMC. - -1. [Connect to PMC](https://learn.microsoft.com/en-us/linux/packages) -2. `sudo apt-get install symcrypt` +For Ubuntu, you can install SymCrypt via package manager by connecting to PMC ( Example shown for Ubuntu `24.04` ): -Alternatively, you can manually install the lib files: +1. `curl -sSL -O https://packages.microsoft.com/config/ubuntu/24.04/packages-microsoft-prod.deb` +2. `sudo dpkg -i packages-microsoft-prod.deb` +3. `sudo apt-get update` +4. `sudo apt-get install symcrypt` -Download the latest `libsymcrypt.so*` files for your corresponding CPU architecture from the [SymCrypt Releases Page](https://github.com/microsoft/SymCrypt/releases) and place them in your machines `$LD_LIBRARY_PATH`. +For more info on connecting to PMC please see: [Connecting to PMC](https://learn.microsoft.com/en-us/linux/packages) -For more information please see the `INSTALL.md` file on the [`rust-symcrypt`](https://github.com/microsoft/rust-symcrypt/tree/main/rust-symcrypt) page - -**Note:** This path may be different depending on your flavour of Linux, and architecture. The goal is to place the `libsymcrypt.so*` files in a location where the your Linux distro can find the required libs at build/run time. +If you want to try connecting with another flavour of Linux, or for more info please see `INSTALL.md` --- ## Usage There are unit tests attached to each file that show how to use each function. Included is some sample code to do a stateless Sha256 hash. - **Note:** This code snippet also uses the [hex](https://crates.io/crates/hex) crate. ### Instructions: -add symcrypt to your `Cargo.toml` file. +Add symcrypt to your `Cargo.toml` file. + +If static linking: +```cargo +[dependencies] +symcrypt = {vesrion = "0.6.0"} +hex = "0.4.3" +``` + +If dynamic linking: ```cargo [dependencies] -symcrypt = "0.5.1" +symcrypt = {vesrion = "0.6.0", features = ["dynamic"]} hex = "0.4.3" ``` -include symcrypt in your code +Include symcrypt in your code ```rust use symcrypt::hash::sha256; use hex; - let data = hex::decode("641ec2cf711e").unwrap(); let expected: &str = "cfdbd6c9acf9842ce04e8e6a0421838f858559cf22d2ea8a38bd07d5e4692233"; - let result = sha256(&data); assert_eq!(hex::encode(result), expected); ``` diff --git a/rust-symcrypt/STATIC_LINKING.md b/rust-symcrypt/STATIC_LINKING.md new file mode 100644 index 00000000..3d7c0564 --- /dev/null +++ b/rust-symcrypt/STATIC_LINKING.md @@ -0,0 +1,73 @@ +# Static Linking (Experimental) + +> **This feature is experimental and lives on the `experimental/static-linking` branch.** +> It is not part of any released version of `symcrypt`. APIs and behavior may change. + +> **NOTE: Static linking must not be used in production or release builds for Microsoft 1st Party. +> If you are a Microsoft employee please contact the SymCrypt team for more info.** + +Static linking does not offer FIPS compliance and is intended for rapid development and testing only. + +--- + +## Overview + +Static linking works by building the `SymCrypt` library from source and linking against the resulting static library. This results in longer build times and larger binaries, but removes the requirement to distribute or locate a dynamic library at runtime. + +Static linking is the default on this branch. To opt into dynamic linking instead, enable the `dynamic` feature flag (see below). + +### Supported Configurations + +| Operating Environment | Architecture | Static Linking | +| --------------------- | ------------ | -------------- | +| Windows user mode | AMD64, ARM64 | ✅ ⚠️ | +| Ubuntu | AMD64, ARM64 | ✅ ⚠️ | +| Azure Linux 3 | AMD64, ARM64 | ✅ ⚠️ | + +--- + +## Usage + +### Static linking (default on this branch) + +```cargo +[dependencies] +symcrypt = "0.6.0" +hex = "0.4.3" +``` + +### Dynamic linking + +If you need FIPS compliance or want to use a system-installed SymCrypt library, enable the `dynamic` feature: + +```cargo +[dependencies] +symcrypt = { version = "0.6.0", features = ["dynamic"] } +hex = "0.4.3" +``` + +For dynamic linking setup instructions see `INSTALL.md`. + +--- + +## Build Requirements + +Static linking requires the SymCrypt source to be available as a submodule. The build script in `symcrypt-sys/build/static_link.rs` handles compilation. Refer to `DEVELOPER.md` for submodule setup and regenerating bindings. + +### Windows + +No additional setup is required beyond a standard Rust + MSVC toolchain. + +### Linux + +The following packages are required: + +```bash +sudo apt-get install -y clang libclang-dev +``` + +For cross-compilation (ARM64): + +```bash +sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu +``` diff --git a/rust-symcrypt/src/lib.rs b/rust-symcrypt/src/lib.rs index 5ea0b00e..70607f32 100644 --- a/rust-symcrypt/src/lib.rs +++ b/rust-symcrypt/src/lib.rs @@ -15,23 +15,51 @@ pub mod rsa; fn symcrypt_init() { // Subsequent calls to `symcrypt_init()` after the first will not be invoked per .call_once docs https://doc.rust-lang.org/std/sync/struct.Once.html static INIT: Once = Once::new(); + + // `symcrypt_init` calls `SymCryptModuleInit` or `SymCryptInit` depending on the feature flag + // We have also set feature flags on the bindings themselves to only expose the functions we need. + // This is to try and eliminate footguns like calling SymCryptModuleInit on a statically linked module. unsafe { // SAFETY: FFI calls, blocking from being run again. + + #[cfg(feature = "dynamic")] INIT.call_once(|| { symcrypt_sys::SymCryptModuleInit( symcrypt_sys::SYMCRYPT_CODE_VERSION_API, symcrypt_sys::SYMCRYPT_CODE_VERSION_MINOR, ) }); + + #[cfg(not(feature = "dynamic"))] + INIT.call_once(|| { + symcrypt_sys::SymCryptInit(); + }); } } -/// Takes in a a buffer called `buff` and fills it with random bytes. This function cannot fail. +/// Takes in a buffer called `buff` and fills it with random bytes. This function +/// is never expected to fail, but failure (due to OS dependencies) will crash the application. +/// There is no recoverable failure mode. +/// +/// If calling `symcrypt_random` with a dynamically linked module, `SymCryptRandom` will be called. +/// +/// If calling `symcrypt_random` with a statically linked module, `SymCryptCallbackRandom` will be called. pub fn symcrypt_random(buff: &mut [u8]) { symcrypt_init(); + + // `symcrypt_random` calls `SymCryptRandom` or `SymCryptCallbackRandom` depending on the feature flag + // We have also set feature flags on the bindings themselves to only expose the functions we need. + // This is to try and eliminate footguns like calling SymCryptRandom on a statically linked module. unsafe { - // SAFETY: FFI calls + // SAFETY: FFI call + + // Call SymCryptRandom for dynamic linking + #[cfg(feature = "dynamic")] symcrypt_sys::SymCryptRandom(buff.as_mut_ptr(), buff.len() as symcrypt_sys::SIZE_T); + + // Call SymCryptCallbackRandom for static linking + #[cfg(not(feature = "dynamic"))] + symcrypt_sys::SymCryptCallbackRandom(buff.as_mut_ptr(), buff.len() as symcrypt_sys::SIZE_T); } } diff --git a/rust-symcrypt/src/rsa/mod.rs b/rust-symcrypt/src/rsa/mod.rs index 9819cbb8..4d1fba8f 100644 --- a/rust-symcrypt/src/rsa/mod.rs +++ b/rust-symcrypt/src/rsa/mod.rs @@ -549,7 +549,7 @@ mod test { .rev() .enumerate() .fold(0, |v, (byte_offset, byte)| { - v | (*byte as u64) << (8 * byte_offset) + v | ((*byte as u64) << (8 * byte_offset)) }); assert_eq!(pub_exp_exported, pub_exp); diff --git a/scripts/generate-all-bindings.ps1 b/scripts/generate-all-bindings.ps1 index 40fc153d..93388865 100644 --- a/scripts/generate-all-bindings.ps1 +++ b/scripts/generate-all-bindings.ps1 @@ -13,7 +13,8 @@ # # - Enter the WSL shell and run the following commands: # sudo apt update && sudo apt upgrade -# sudo apt install -y clang libclang-dev rustup +# sudo apt install -y clang libclang-dev +# curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # to install rust for WSL # sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu # for cross-compilation # # rustup update @@ -34,7 +35,6 @@ $PSNativeCommandUseErrorActionPreference = $True Push-Location "$PSScriptRoot/.." # Move to the root of the project git submodule update --init -git -C symcrypt-sys/symcrypt/3rdparty/jitterentropy-library submodule update --init python3 "./symcrypt-sys/symcrypt/scripts/version.py" --build-info mv -Force "./symcrypt-sys/symcrypt/inc/buildInfo.h" "./symcrypt-sys/inc/" diff --git a/symcrypt-bindgen/src/main.rs b/symcrypt-bindgen/src/main.rs index 0479305a..1f12bcd7 100644 --- a/symcrypt-bindgen/src/main.rs +++ b/symcrypt-bindgen/src/main.rs @@ -57,6 +57,7 @@ fn main() { // INIT FUNCTIONS .allowlist_function("SymCryptModuleInit") + .allowlist_function("SymCryptInit") .allowlist_var("^(SYMCRYPT_CODE_VERSION.*)$") // HASH FUNCTIONS .allowlist_function("^SymCrypt(?:Sha3_(?:256|384|512)|Sha(?:256|384|512|1)|Md5)(?:Init|Append|Result|StateCopy)?$") @@ -106,6 +107,7 @@ fn main() { // UTILITY FUNCTIONS .allowlist_function("SymCryptWipe") .allowlist_function("SymCryptRandom") + .allowlist_function("SymCryptCallbackRandom") .allowlist_function("SymCryptLoadMsbFirstUint64") .allowlist_function("SymCryptStoreMsbFirstUint64") @@ -118,6 +120,10 @@ fn main() { .write_to_file(&bindings_file) .expect("Couldn't write bindings!"); + // For dynamic linking, we expose SymCryptModuleInit, for static linking, we expose SymCryptInit. + fix_symcrypt_bindings(&bindings_file); + + // For dynamic linking, we need to add a link attribute to the bindings. fix_bindings_for_windows(triple, &bindings_file); } @@ -152,7 +158,8 @@ fn get_rust_version_from_cargo_metadata() -> String { fn fix_bindings_for_windows(triple: &str, bindings_file: &str) { if triple.contains("windows") { println!("Fixing bindings for Windows"); - let link_str = "#[link(name = \"symcrypt\", kind = \"dylib\")]"; + let link_str = + r#"#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))]"#; let regex_exp1 = regex::Regex::new(r"pub static \w+: \[SYMCRYPT_OID; \d+usize\];").unwrap(); let regex_exp2 = regex::Regex::new(r"pub static \w+: PCSYMCRYPT_\w+;").unwrap(); let bindings_content = @@ -178,3 +185,54 @@ fn fix_bindings_for_windows(triple: &str, bindings_file: &str) { .expect("Unable to write bindings file"); } } + +#[allow(clippy::collapsible_if)] +fn fix_symcrypt_bindings(bindings_file: &str) { + println!("Fixing bindings to expose SymCryptInit or SymCryptModuleInit and SymCryptRandom"); + + let bindings_content = + std::fs::read_to_string(bindings_file).expect("Unable to read bindings file"); + + let mut out_content = Vec::new(); + let lines: Vec<&str> = bindings_content.lines().collect(); + let mut i = 0; + + // With Dynamic, we want to expose SymCryptModuleInit and SymCryptRandom + // With Static, we want to expose SymCryptInit and SymCryptCallbackRandom + while i < lines.len() { + if lines[i].trim() == "extern \"C\" {" { + if i + 1 < lines.len() { + let next_line = lines[i + 1].trim(); + + let cfg_attr = match next_line { + line if line == "pub fn SymCryptInit();" + || line.starts_with("pub fn SymCryptCallbackRandom(") => + { + "#[cfg(not(feature = \"dynamic\"))]" + } + line if line.starts_with("pub fn SymCryptModuleInit(") + || line.starts_with("pub fn SymCryptRandom(") => + { + "#[cfg(feature = \"dynamic\")]" + } + _ => "", + }; + + if !cfg_attr.is_empty() { + out_content.push(cfg_attr.to_string()); + } + } + } + + out_content.push(lines[i].to_string()); + i += 1; + } + + // Append newline for linux bindings + if !out_content.last().unwrap_or(&String::new()).ends_with('\n') { + out_content.push("".to_string()); + } + + // Write the modified content back + std::fs::write(bindings_file, out_content.join("\n")).expect("Unable to write bindings file"); +} diff --git a/symcrypt-sys/Cargo.toml b/symcrypt-sys/Cargo.toml index ad71cf50..5ac4880b 100644 --- a/symcrypt-sys/Cargo.toml +++ b/symcrypt-sys/Cargo.toml @@ -1,18 +1,25 @@ [package] name = "symcrypt-sys" authors = ["Microsoft"] -version = "0.4.0" +version = "0.5.0" license = "MIT OR Apache-2.0" description = "Rust/C Bindings for SymCrypt" edition.workspace = true rust-version.workspace = true -build = "build.rs" +build = "build/main.rs" homepage = "https://github.com/microsoft/SymCrypt" repository = "https://github.com/microsoft/rust-symcrypt" readme = "README.md" -exclude = ["symcrypt/*", "inc/*"] +exclude = ["symcrypt/*", "inc/*"] # FIXME: update this before merging to main branch +#links = "symcrypt" # FIXME: uncomment this before merging to main branch # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +dynamic = [] + [dependencies] libc = "0.2.0" + +[build-dependencies] +cc = { version = "1.2.10" } # FIXME: enable parallel feature before merging to main branch diff --git a/symcrypt-sys/README.md b/symcrypt-sys/README.md index 0cd79b66..58ce29de 100644 --- a/symcrypt-sys/README.md +++ b/symcrypt-sys/README.md @@ -20,7 +20,7 @@ You must also configure your system to pick up the SymCrypt lib on your machine, In your `Cargo.toml` ```Rust -symcrypt-sys = "0.4.0" +symcrypt-sys = "0.5.0" ``` Then you can call the underlying SymCrypt code directly via the FFIs. ```Rust diff --git a/symcrypt-sys/build.rs b/symcrypt-sys/build/main.rs similarity index 52% rename from symcrypt-sys/build.rs rename to symcrypt-sys/build/main.rs index 309d8254..66acc7d9 100644 --- a/symcrypt-sys/build.rs +++ b/symcrypt-sys/build/main.rs @@ -1,13 +1,25 @@ -#[cfg(target_os = "windows")] -use std::env; +#[cfg(not(feature = "dynamic"))] +pub mod static_link; -fn main() { +#[cfg(not(feature = "dynamic"))] +pub mod triple; + +fn main() -> std::io::Result<()> { + #[cfg(feature = "dynamic")] + link_symcrypt_dynamically()?; + + #[cfg(not(feature = "dynamic"))] + static_link::compile_and_link_symcrypt()?; + + Ok(()) +} + +#[cfg(feature = "dynamic")] +fn link_symcrypt_dynamically() -> std::io::Result<()> { #[cfg(target_os = "windows")] { - // Look for the .lib file during link time. We are searching the Windows/System32 path which is set as a current default to match - // the long term placement of a Windows shipped symcrypt.dll - - let lib_path = env::var("SYMCRYPT_LIB_PATH") + // Look for the .lib file during link time. We are searching the PATH for symcrypt.dll + let lib_path = std::env::var("SYMCRYPT_LIB_PATH") .unwrap_or_else(|_| panic!("SYMCRYPT_LIB_PATH environment variable not set, for more information please see: https://github.com/microsoft/rust-symcrypt/tree/main/rust-symcrypt#quick-start-guide")); println!("cargo:rustc-link-search=native={}", lib_path); @@ -21,24 +33,18 @@ fn main() { // 5. The directories that are listed in the PATH environment variable. // For more info please see: https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order - - // For the least invasive usage, we suggest putting the symcrypt.dll inside of same folder as the .exe file. - - // Note: This process is a band-aid. Long-term SymCrypt will be shipped with Windows which will make this process much more - // streamlined. } #[cfg(target_os = "linux")] { - // Note: Linux support is based off of the Azure Linux distro. - // This has been tested on Ubuntu 22.04.03 LTS on WSL and has confirmed working but support for other distros - // aside from Azure Linux is not guaranteed so YMMV. println!("cargo:rustc-link-lib=dylib=symcrypt"); // the "lib" prefix for libsymcrypt is implied on Linux - // You must put the included symcrypt.so files in your usr/lib/x86_64-linux-gnu/ path. - // This is where the Linux ld linker will look for the symcrypt.so files. + // If you are using AL3, you can get the required symcrypt.so via tdnf + // If you are using Ubuntu, you can get the required symcrypt.so via PMC. Please see the quick start guide for more information. - // Note: This process is a band-aid. Long-term, our long term solution is to package manage SymCrypt for a subset of - // Linux distros. + // If you are using a different Linux distro, you will need to configure your distro's LD linker to find the required symcrypt.so files. + // As an example, on Ubuntu you can place your symcrypt.so files in your usr/lib/x86_64-linux-gnu/ path. } + + Ok(()) } diff --git a/symcrypt-sys/build/static_link.rs b/symcrypt-sys/build/static_link.rs new file mode 100644 index 00000000..143408b5 --- /dev/null +++ b/symcrypt-sys/build/static_link.rs @@ -0,0 +1,470 @@ +use super::triple::Triple; +use std::collections::HashSet; + +const LIB_NAME: &str = "symcrypt"; + +/// Compiles and links the SymCrypt library statically. +/// This is the entery point for building SymCrypt statically. +/// +/// - Determines the build configuration based on target architecture. +/// - Calls `compile_symcrypt_static()` to actually build SymCrypt. +/// - Outputs necessary metadata for Cargo (`cargo:rustc-link-lib=...`). +/// +/// Based on SymCrypt's `CMakeLists.txt`, but adapted for Rust. +pub fn compile_and_link_symcrypt() -> std::io::Result<()> { + let options = SymCryptOptions::new(); + println!("Build config: {:?}", options); + + // Rebuild if any of these files change + println!("cargo:rerun-if-changed=../symcrypt/lib/"); + println!("cargo:rerun-if-changed=../symcrypt/inc/"); + println!("cargo:rerun-if-changed=../inc/"); + + // Required Windows bcrypt dependency for BCryptGenRandom + const ADDITIONAL_DEPENDENCIES: &[&str] = &[ + #[cfg(windows)] + "bcrypt", + ]; + + println!("Compiling SymCrypt..."); + + // Compile and Build SymCrypt with provided SymCryptOptions + compile_symcrypt_static(LIB_NAME, &options)?; + println!("cargo:rustc-link-lib=static={LIB_NAME}"); + + // Link additional dependencies + for dep in ADDITIONAL_DEPENDENCIES { + println!("cargo:rustc-link-lib=dylib={dep}"); + } + + Ok(()) +} + +// TODO: update -symcrypt_fips_build comment + +/// Holds configuration options for compiling SymCrypt. +/// +/// - `triple`: The target triple +/// - `symcrypt_use_asm`: Whether to enable assembly optimizations. +/// - `symcrypt_fips_build`: Whether to build in FIPS mode PLACEHOLDER +/// - `preconfiged_cc`: Returns a Pre-configured `cc` object for the target triple. +#[derive(Debug)] +struct SymCryptOptions { + triple: Triple, + symcrypt_use_asm: bool, + //symcrypt_fips_build: bool, // TODO: Determine if we should expose FIPS build option? +} + +impl SymCryptOptions { + fn new() -> Self { + Self { + triple: Triple::get_target_triple(), + symcrypt_use_asm: false, // FIXME: Turn this to true when we get ASM checked in + //symcrypt_fips_build: false, // TODO: Determine if we should expose FIPS build option? + } + } + fn use_asm(&self) -> bool { + self.symcrypt_use_asm + } + fn triple(&self) -> Triple { + self.triple.clone() + } + + // Returns a cc object that has been preconfigured for the target triple + fn preconfigure_cc(&self) -> cc::Build { + let mut cc = cc::Build::new(); + cc.target(self.triple.to_triple()) + .include("inc") + .include("symcrypt/inc") + .include("symcrypt/lib") + .warnings(false); // Ignore noisy warnings from SymCrypt + + if !self.symcrypt_use_asm { + cc.define("SYMCRYPT_IGNORE_PLATFORM", None); // TODO: Fix when we get ASM + } + + // Set specific flags for operating system + + match self.triple { + // Target all Windows targets + Triple::x86_64_pc_windows_msvc | Triple::aarch64_pc_windows_msvc => { + // From SymCrypt-Platforms.cmake + cc.flag("/MP") // Multi-threaded compilation + .flag("/Zp8") // Structure packing alignment + .flag("/WX") // Treat warnings as errors + .flag("/guard:cf") // Control Flow Guard + .flag("/wd5105") // Disable warning caused by Windows SDK headers + .flag("/EHsc"); // Exception handling + // .flag("/dynamicbase"); // Enabling ASLR produces lots of warnings + + // From lib/CmakeLists.txt + // cc.asm_flag("/DSYMCRYPT_MASM"); // TODO: enable for ASM + } + + // Target all Linux targets + Triple::x86_64_unknown_linux_gnu | Triple::aarch64_unknown_linux_gnu => { + // From lib/CmakeLists.txt + // Stack Protection ON by default for linux + cc.flag("-fstack-protector-strong") + .flag("-Wstack-protector") + .flag("--param=ssp-buffer-size=4") + .flag("-fstack-clash-protection") + .flag("-Wno-incompatible-pointer-types"); // Ignore noisy SymCrypt errors + + // From lib/CmakeLists.txt + // cc.flag("-x assembler-with-cpp"); // TODO: enable for ASM + + // From SymCrypt-Platforms.cmake + cc.flag("-Wno-unknown-pragmas") + .flag("-Werror") + .flag("-Wno-deprecated-declarations") + .flag("-Wno-deprecated") + .flag("-g") + .flag("-Wno-multichar") + .flag("-fPIC") // PIC is enabled by default on Linux + .flag("-fno-plt") + .flag("-fno-builtin-bcmp") + .flag("-fno-unroll-loops"); + } + } + + // Set specific flags for each triple + match self.triple { + Triple::x86_64_pc_windows_msvc => { + // From SymCrypt-Platforms.cmake + cc.define("_AMD64_", None).flag("/Gz"); // Set default to __stdcall, only for X86 + } + Triple::aarch64_pc_windows_msvc => { + cc.define("_ARM64_", None); + } + Triple::x86_64_unknown_linux_gnu => { + // From SymCrypt-Platforms.cmake + // Only for x86_64_unknown_linux_gnu + cc.flag("-mssse3") + .flag("-mxsave") + .flag("-maes") + .flag("-mpclmul") + .flag("-msha") + .flag("-mrdrnd") + .flag("-mrdseed"); + } + Triple::aarch64_unknown_linux_gnu => { + // From SymCrypt-Platforms.cmake + cc.flag("-march=armv8-a+simd+crypto") // Enable a baseline of features for the compiler to support everywhere. + .flag("-flax-vector-conversions"); // Setting -flax-vector-conversions to build Arm64 intrinsics code with GCC. + } + } + + cc + } +} + +const SOURCE_DIR: &str = "symcrypt/lib"; +const SOURCES_COMMON: &str = " +3des.c +a_dispatch.c +aes-asm.c +aes-c.c +aes-default-bc.c +aes-default.c +aes-key.c +aes-neon.c +aes-selftest.c +aes-xmm.c +aes-ymm.c +aescmac.c +aesCtrDrbg.c +aeskw.c +AesTables.c +blockciphermodes.c +ccm.c +chacha20_poly1305.c +chacha20.c +cpuid_notry.c +cpuid_um.c +cpuid.c +crt.c +DesTables.c +desx.c +dh.c +dl_internal_groups.c +dlgroup.c +dlkey.c +dsa.c +ec_dh.c +ec_dispatch.c +ec_dsa.c +ec_internal_curves.c +ec_montgomery.c +ec_mul.c +ec_short_weierstrass.c +ec_twisted_edwards.c +eckey.c +ecpoint.c +ecurve.c +equal.c +FatalIntercept.c +fdef_general.c +fdef_int.c +fdef_mod.c +fdef369_mod.c +fips_selftest.c +gcm.c +gen_int.c +ghash.c +hash.c +hkdf_selftest.c +hkdf.c +hmac.c +hmacmd5.c +hmacsha1.c +hmacsha224.c +hmacsha256.c +hmacsha384.c +hmacsha512.c +hmacsha512_224.c +hmacsha512_256.c +hmacsha3_224.c +hmacsha3_256.c +hmacsha3_384.c +hmacsha3_512.c +kmac.c +libmain.c +lms.c +marvin32.c +md2.c +md4.c +md5.c +mldsa.c +mldsa_primitives.c +mlkem.c +mlkem_primitives.c +modexp.c +paddingPkcs7.c +parhash.c +pbkdf2_hmacsha1.c +pbkdf2_hmacsha256.c +pbkdf2.c +poly1305.c +primes.c +rc2.c +rc4.c +rdrand.c +rdseed.c +recoding.c +rsa_enc.c +rsa_padding.c +rsakey.c +ScsTable.c +scsTools.c +selftest.c +service_indicator.c +session.c +sha1.c +sha256.c +sha256Par.c +sha256Par-ymm.c +sha256-xmm.c +sha256-ymm.c +sha512.c +sha512Par.c +sha512Par-ymm.c +sha512-ymm.c +sha3.c +sha3_224.c +sha3_256.c +sha3_384.c +sha3_512.c +shake.c +sp800_108_hmacsha1.c +sp800_108_hmacsha256.c +sp800_108_hmacsha512.c +sp800_108.c +srtp_kdf.c +srtp_kdf_selftest.c +ssh_kdf.c +ssh_kdf_sha256.c +ssh_kdf_sha512.c +sskdf.c +sskdf_selftest.c +tlsCbcVerify.c +tlsprf_selftest.c +tlsprf.c +xmss.c +xtsaes.c +"; + +fn compile_symcrypt_static(lib_name: &str, options: &SymCryptOptions) -> std::io::Result<()> { + // Compile intermediates required this is currently only required for x86_64_unknown_linux_gnu + let (already_compiled_files, intermediates) = compile_symcrypt_intermediates(options); + + // Convert already compiled files to a HashSet for faster lookups + let already_compiled_set: HashSet<&str> = already_compiled_files.iter().cloned().collect(); + + // Prepares list of files to be compiled, excluding already compiled files for x86_64_unknown_linux_gnu + let mut base_files: Vec<&'static str> = SOURCES_COMMON + .lines() + .map(str::trim) // Trim once instead of inside filter + .filter(|line| { + !line.is_empty() && !line.starts_with("#") && !already_compiled_set.contains(line) + }) + .collect(); + + base_files.push("env_generic.c"); // symcrypt_generic + + // Add module-specific files for each target + let mut module_files = vec![]; + + match options.triple() { + Triple::x86_64_pc_windows_msvc | Triple::aarch64_pc_windows_msvc => { + base_files.push("env_windowsUserModeWin8_1.c"); + base_files.push("IEEE802_11SaeCustom.c"); + module_files.push("inc/static_WindowsDefault.c"); + } + Triple::x86_64_unknown_linux_gnu => { + base_files.push("linux/intrinsics.c"); // Only needed for x86_64_unknown_linux_gnu + base_files.push("env_posixUserMode.c"); + module_files.push("inc/static_LinuxDefault.c"); + } + Triple::aarch64_unknown_linux_gnu => { + base_files.push("env_posixUserMode.c"); + module_files.push("inc/static_LinuxDefault.c"); + } + } + + // Add assembly pre generated ASM files to be compiled + // ASM files come from lib/CMakeLists.txt + let asm_files = match options.triple() { + Triple::x86_64_pc_windows_msvc => vec![ + "aesasm-gas.asm", + "fdef_asm-gas.asm", + "fdef369_asm-gas.asm", + "fdef_mulx-gas.asm", + "wipe-gas.asm", + "sha256xmm_asm-gas.asm", + "sha256ymm_asm-gas.asm", + "sha512ymm_asm-gas.asm", + "sha512ymm_avx512vl_asm-gas.asm", + ], + Triple::aarch64_pc_windows_msvc => { + vec!["fdef_asm-gas.asm", "fdef369_asm-gas.asm", "wipe-gas.asm"] + } + Triple::x86_64_unknown_linux_gnu => vec![ + "aesasm-gas.asm", + "fdef_asm-gas.asm", + "fdef369_asm-gas.asm", + "fdef_mulx-gas.asm", + "wipe-gas.asm", + "sha256xmm_asm-gas.asm", + "sha256ymm_asm-gas.asm", + "sha512ymm_asm-gas.asm", + "sha512ymm_avx512vl_asm-gas.asm", + ], + Triple::aarch64_unknown_linux_gnu => { + vec!["fdef_asm-gas.asm", "fdef369_asm-gas.asm", "wipe-gas.asm"] + } + }; + + // Pre-Configure the cc compiler based on the target triple + let mut cc = options.preconfigure_cc(); + + // Add in the intermediates that were previously compiled, will be empty for most targets + cc.objects(intermediates); + + // Add base files to be compiled + for file in base_files { + cc.file(format!("{SOURCE_DIR}/{file}")); + } + + // Add assembly files to be compiled + if options.use_asm() { + for file in asm_files { + cc.file(format!( + "{SOURCE_DIR}/asm/{}/{file}", // TODO: replace with right file path when ASM checked in. + options.triple.to_triple() + )); + } + } + + // Add module-specific files to be compiled + cc.files(module_files); + + println!("Files to compile: {}", cc.get_files().count()); + + // Compiles all files and returns the compiled library + cc.compile(lib_name); + + Ok(()) +} + +// Special compile files for x86_64_unknown_linux_gnu +const X86_64_LINUX_CUSTOM_COMPILE_FILES: &str = r#" +aes-ymm.c "-mavx;-mavx2;-mvaes;-mvpclmulqdq" +sha256Par-ymm.c "-mavx;-mavx2" +sha512Par-ymm.c "-mavx;-mavx2" +sha256-xmm.c "-mssse3" +sha256-ymm.c "-mavx;-mavx2;-mbmi2" +sha512-ymm.c "-mavx;-mavx2;-mbmi2" +"#; + +//set_source_files_properties(sha512-ymm.c PROPERTIES COMPILE_OPTIONS "-mavx;-mavx2;-mbmi2") + +/// Compiles the SymCrypt custom intermediates +/// +/// Currently this is only required for x86_64_unknown_linux_gnu, +/// but can be modified to include other targets as needed. +/// +/// If the target is not `x86_64_unknown_linux_gnu`, it returns empty vectors +fn compile_symcrypt_intermediates( + symcrypt_options: &SymCryptOptions, +) -> (Vec<&'static str>, Vec) { + let mut files = vec![]; + let mut intermediates = vec![]; + + // Only compile intermediates for x86_64_unknown_linux_gnu. + // Can modify with additional targets as needed. + if symcrypt_options.triple() != Triple::x86_64_unknown_linux_gnu { + return (files, intermediates); // No intermediates to compile + } + + // Fetch preconfigured cc based on the target triple. + let mut cc = symcrypt_options.preconfigure_cc(); + + for line in X86_64_LINUX_CUSTOM_COMPILE_FILES.lines() { + if line.trim().is_empty() || line.trim().starts_with("#") { + continue; + } + + // Example of parts: + // [aes-ymm.c, "-mavx;-mavx2;-mvaes;-mvpclmulqdq"] + let parts: Vec<&str> = line.split_whitespace().collect(); + if parts.len() < 2 { + continue; + } + + let file = parts[0]; + println!("Compiling {file} with custom options: {}", parts[1]); + + // Isolate the compile options + let options = parts[1] + .trim_matches('"') + .split(';') + .filter(|s| !s.is_empty()); + + // Push intermediates to the cc object to be compiled + cc.file(format!("{SOURCE_DIR}/{file}")); + for option in options { + cc.flag(option); + } + + // Add the file to the list of files to be replaced by compiled intermediates. + files.push(file); + } + + // Use cc's compile_intermediates() to batch generate intermediate files without linking + let mut result = cc.compile_intermediates(); + intermediates.append(&mut result); + + // Return files to be replaced by intermediates. + (files, intermediates) +} diff --git a/symcrypt-sys/build/triple.rs b/symcrypt-sys/build/triple.rs new file mode 100644 index 00000000..590a45a3 --- /dev/null +++ b/symcrypt-sys/build/triple.rs @@ -0,0 +1,34 @@ +#[allow(non_camel_case_types)] +#[derive(Debug, PartialEq, Eq, Clone)] + +/// The `Triple` enum represents the target architecture and operating system. +pub enum Triple { + x86_64_pc_windows_msvc, + aarch64_pc_windows_msvc, + x86_64_unknown_linux_gnu, + aarch64_unknown_linux_gnu, +} + +impl Triple { + pub fn get_target_triple() -> Self { + // Extract target OS and architecture from environment variables + let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap(); + let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap(); + + match (target_os.as_str(), target_arch.as_str()) { + ("windows", "x86_64") => Triple::x86_64_pc_windows_msvc, + ("windows", "aarch64") => Triple::aarch64_pc_windows_msvc, + ("linux", "x86_64") => Triple::x86_64_unknown_linux_gnu, + ("linux", "aarch64") => Triple::aarch64_unknown_linux_gnu, + _ => panic!("unsupported target. OS: {target_os}, Arch: {target_arch}"), + } + } + pub fn to_triple(&self) -> &'static str { + match self { + Triple::x86_64_pc_windows_msvc => "x86_64-pc-windows-msvc", + Triple::aarch64_pc_windows_msvc => "aarch64-pc-windows-msvc", + Triple::x86_64_unknown_linux_gnu => "x86_64-unknown-linux-gnu", + Triple::aarch64_unknown_linux_gnu => "aarch64-unknown-linux-gnu", + } + } +} diff --git a/symcrypt-sys/inc/buildInfo.h b/symcrypt-sys/inc/buildInfo.h index fb984057..c93659e2 100644 --- a/symcrypt-sys/inc/buildInfo.h +++ b/symcrypt-sys/inc/buildInfo.h @@ -1,8 +1,8 @@ -#include "symcrypt_internal_shared.inc" - -#define _SYMCRYPT_STRING_INT(a) #a -#define _SYMCRYPT_STRING(a) _SYMCRYPT_STRING_INT(a) -#define SYMCRYPT_BUILD_INFO_BRANCH "" -#define SYMCRYPT_BUILD_INFO_COMMIT "2025-01-28T01:44:15+01:00_53be637" -#define SYMCRYPT_BUILD_INFO_VERSION _SYMCRYPT_STRING(SYMCRYPT_CODE_VERSION_API) "." _SYMCRYPT_STRING(SYMCRYPT_CODE_VERSION_MINOR) "." _SYMCRYPT_STRING(SYMCRYPT_CODE_VERSION_PATCH) -#define SYMCRYPT_BUILD_INFO_TIMESTAMP "2025-01-31T15:53:40" +#include "symcrypt_internal_shared.inc" + +#define _SYMCRYPT_STRING_INT(a) #a +#define _SYMCRYPT_STRING(a) _SYMCRYPT_STRING_INT(a) +#define SYMCRYPT_BUILD_INFO_BRANCH "" +#define SYMCRYPT_BUILD_INFO_COMMIT "2025-01-28T01:44:15+01:00_53be637" +#define SYMCRYPT_BUILD_INFO_VERSION _SYMCRYPT_STRING(SYMCRYPT_CODE_VERSION_API) "." _SYMCRYPT_STRING(SYMCRYPT_CODE_VERSION_MINOR) "." _SYMCRYPT_STRING(SYMCRYPT_CODE_VERSION_PATCH) +#define SYMCRYPT_BUILD_INFO_TIMESTAMP "2025-02-07T14:10:46" diff --git a/symcrypt-sys/inc/static_LinuxDefault.c b/symcrypt-sys/inc/static_LinuxDefault.c new file mode 100644 index 00000000..7f0a9bad --- /dev/null +++ b/symcrypt-sys/inc/static_LinuxDefault.c @@ -0,0 +1,63 @@ +// +// static_LinuxDefault.c +// Default implementation for Linux static shared object. +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include +#include +#include +#include + +#include "wrapper.h" +#include +#include + +SYMCRYPT_ENVIRONMENT_POSIX_USERMODE; + +PVOID +SYMCRYPT_CALL +SymCryptCallbackAlloc( SIZE_T nBytes ) +{ + // aligned_alloc requires size to be integer multiple of alignment + SIZE_T cbAllocation = (nBytes + (SYMCRYPT_ASYM_ALIGN_VALUE - 1)) & ~(SYMCRYPT_ASYM_ALIGN_VALUE - 1); + + return aligned_alloc(SYMCRYPT_ASYM_ALIGN_VALUE, cbAllocation); +} + +VOID +SYMCRYPT_CALL +SymCryptCallbackFree( VOID * pMem ) +{ + free( pMem ); +} + +// From Linux docs on getrandom: +// RETURN VALUE top +// On success, getrandom() returns the number of bytes that were +// copied to the buffer buf. This may be less than the number of +// bytes requested via buflen if either GRND_RANDOM was specified in +// flags and insufficient entropy was present in the random source or +// the system call was interrupted by a signal. +// On error, -1 is returned, and errno is set to indicate the error. +SYMCRYPT_ERROR +SYMCRYPT_CALL +SymCryptCallbackRandom(unsigned char *pbBuffer, size_t cbBuffer) +{ + size_t total_received = 0; + ssize_t result; + + while (total_received < cbBuffer) { + result = getrandom(pbBuffer + total_received, cbBuffer - total_received, 0); + if (result < 0) { + if (errno == EINTR) { + // Buffer is not yet full, continue to get more entropy + continue; + } + return SYMCRYPT_EXTERNAL_FAILURE; + } + total_received += (size_t)result; + } + return SYMCRYPT_NO_ERROR; +} diff --git a/symcrypt-sys/inc/static_WindowsDefault.c b/symcrypt-sys/inc/static_WindowsDefault.c new file mode 100644 index 00000000..6d9e618c --- /dev/null +++ b/symcrypt-sys/inc/static_WindowsDefault.c @@ -0,0 +1,43 @@ +// +// static_WindowsDefault.c +// Default implementation for Windows static shared object. +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) + +// Ensure that windows.h doesn't re-define the status_* symbols +#define WIN32_NO_STATUS +#include +#include +#include +#include +#include + +SYMCRYPT_ENVIRONMENT_WINDOWS_USERMODE_LATEST; + +PVOID +SYMCRYPT_CALL +SymCryptCallbackAlloc( SIZE_T nBytes ) +{ + return _aligned_malloc( nBytes, SYMCRYPT_ASYM_ALIGN_VALUE ); +} + +VOID +SYMCRYPT_CALL +SymCryptCallbackFree(PVOID ptr) +{ + _aligned_free( ptr ); +} + +SYMCRYPT_ERROR +SYMCRYPT_CALL +SymCryptCallbackRandom( + _Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer, + SIZE_T cbBuffer ) +{ + NTSTATUS status = BCryptGenRandom( BCRYPT_RNG_ALG_HANDLE, pbBuffer, (ULONG) cbBuffer, 0 ); + + return NT_SUCCESS( status ) ? SYMCRYPT_NO_ERROR : SYMCRYPT_EXTERNAL_FAILURE; +} diff --git a/symcrypt-sys/inc/symcrypt_internal_shared.inc b/symcrypt-sys/inc/symcrypt_internal_shared.inc index f89b662f..f60f9924 100644 --- a/symcrypt-sys/inc/symcrypt_internal_shared.inc +++ b/symcrypt-sys/inc/symcrypt_internal_shared.inc @@ -1,33 +1,33 @@ -// -// symcrypt_internal_shared.inc -// Copyright (c) Microsoft Corporation. Licensed under the MIT license. -// -// This is the file that contains the SymCrypt version information and defines SYMCRYPT_DEBUG. -// It is included in both C and ASM such that the values are the same on both sides. -// We use the C preprocessor to set ASM constants, as we already need to use the C preprocessor for -// symcryptasm processing (see scripts/symcryptasm_processor.py). -// -// In previous releases we had a numbering system with major/minor version number. -// This worked well with the sequential servicing imposed by SourceDepot. -// With the switch to Git this no longer works due to having multiple branches. -// We move to having the version here only specify the API and minor version number -// These will NOT be changed for every build. The API version only changes when there are -// breaking changes to the API in symcrypt.h. (Note: symcrypt_low_level.h is not stable and can change -// at any time.) The minor version is changed at regular intervals, but not necessarily at -// every build of the library. -// -// Separate from these numbers the build system includes information about the branch, -// last commit, build time, etc. -// -// The API numbering starts at 100 to avoid number conflicts with the old system. -// - -#define SYMCRYPT_CODE_VERSION_API 103 -#define SYMCRYPT_CODE_VERSION_MINOR 8 -#define SYMCRYPT_CODE_VERSION_PATCH 0 - -#if defined(DBG) -#define SYMCRYPT_DEBUG 1 -#else -#define SYMCRYPT_DEBUG 0 -#endif +// +// symcrypt_internal_shared.inc +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// +// This is the file that contains the SymCrypt version information and defines SYMCRYPT_DEBUG. +// It is included in both C and ASM such that the values are the same on both sides. +// We use the C preprocessor to set ASM constants, as we already need to use the C preprocessor for +// symcryptasm processing (see scripts/symcryptasm_processor.py). +// +// In previous releases we had a numbering system with major/minor version number. +// This worked well with the sequential servicing imposed by SourceDepot. +// With the switch to Git this no longer works due to having multiple branches. +// We move to having the version here only specify the API and minor version number +// These will NOT be changed for every build. The API version only changes when there are +// breaking changes to the API in symcrypt.h. (Note: symcrypt_low_level.h is not stable and can change +// at any time.) The minor version is changed at regular intervals, but not necessarily at +// every build of the library. +// +// Separate from these numbers the build system includes information about the branch, +// last commit, build time, etc. +// +// The API numbering starts at 100 to avoid number conflicts with the old system. +// + +#define SYMCRYPT_CODE_VERSION_API 103 +#define SYMCRYPT_CODE_VERSION_MINOR 8 +#define SYMCRYPT_CODE_VERSION_PATCH 0 + +#if defined(DBG) +#define SYMCRYPT_DEBUG 1 +#else +#define SYMCRYPT_DEBUG 0 +#endif diff --git a/symcrypt-sys/src/bindings/aarch64_pc_windows_msvc.rs b/symcrypt-sys/src/bindings/aarch64_pc_windows_msvc.rs index ee1327b4..4e013c7e 100644 --- a/symcrypt-sys/src/bindings/aarch64_pc_windows_msvc.rs +++ b/symcrypt-sys/src/bindings/aarch64_pc_windows_msvc.rs @@ -1227,35 +1227,35 @@ impl Default for _SYMCRYPT_OID { } pub type SYMCRYPT_OID = _SYMCRYPT_OID; pub type PCSYMCRYPT_OID = *const SYMCRYPT_OID; -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptMd5OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha1OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha256OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha384OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha512OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha3_256OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha3_384OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha3_512OidList: [SYMCRYPT_OID; 2usize]; } @@ -4474,6 +4474,11 @@ extern "C" { extern "C" { pub fn SymCryptStoreMsbFirstUint64(src: UINT64, pbDst: PBYTE, cbDst: SIZE_T) -> SYMCRYPT_ERROR; } +#[cfg(not(feature = "dynamic"))] +extern "C" { + pub fn SymCryptInit(); +} +#[cfg(feature = "dynamic")] extern "C" { pub fn SymCryptModuleInit(api: UINT32, minor: UINT32); } @@ -4492,7 +4497,7 @@ extern "C" { extern "C" { pub fn SymCryptMd5StateCopy(pSrc: PCSYMCRYPT_MD5_STATE, pDst: PSYMCRYPT_MD5_STATE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptMd5Algorithm: PCSYMCRYPT_HASH; } @@ -4511,7 +4516,7 @@ extern "C" { extern "C" { pub fn SymCryptSha1StateCopy(pSrc: PCSYMCRYPT_SHA1_STATE, pDst: PSYMCRYPT_SHA1_STATE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha1Algorithm: PCSYMCRYPT_HASH; } @@ -4530,7 +4535,7 @@ extern "C" { extern "C" { pub fn SymCryptSha256StateCopy(pSrc: PCSYMCRYPT_SHA256_STATE, pDst: PSYMCRYPT_SHA256_STATE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha256Algorithm: PCSYMCRYPT_HASH; } @@ -4549,7 +4554,7 @@ extern "C" { extern "C" { pub fn SymCryptSha384StateCopy(pSrc: PCSYMCRYPT_SHA384_STATE, pDst: PSYMCRYPT_SHA384_STATE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha384Algorithm: PCSYMCRYPT_HASH; } @@ -4568,7 +4573,7 @@ extern "C" { extern "C" { pub fn SymCryptSha512StateCopy(pSrc: PCSYMCRYPT_SHA512_STATE, pDst: PSYMCRYPT_SHA512_STATE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha512Algorithm: PCSYMCRYPT_HASH; } @@ -4590,7 +4595,7 @@ extern "C" { pDst: PSYMCRYPT_SHA3_256_STATE, ); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha3_256Algorithm: PCSYMCRYPT_HASH; } @@ -4612,7 +4617,7 @@ extern "C" { pDst: PSYMCRYPT_SHA3_384_STATE, ); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha3_384Algorithm: PCSYMCRYPT_HASH; } @@ -4634,7 +4639,7 @@ extern "C" { pDst: PSYMCRYPT_SHA3_512_STATE, ); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha3_512Algorithm: PCSYMCRYPT_HASH; } @@ -4672,7 +4677,7 @@ extern "C" { extern "C" { pub fn SymCryptHmacMd5Result(pState: PSYMCRYPT_HMAC_MD5_STATE, pbResult: PBYTE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptHmacMd5Algorithm: PCSYMCRYPT_MAC; } @@ -4714,7 +4719,7 @@ extern "C" { extern "C" { pub fn SymCryptHmacSha1Result(pState: PSYMCRYPT_HMAC_SHA1_STATE, pbResult: PBYTE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptHmacSha1Algorithm: PCSYMCRYPT_MAC; } @@ -4756,7 +4761,7 @@ extern "C" { extern "C" { pub fn SymCryptHmacSha256Result(pState: PSYMCRYPT_HMAC_SHA256_STATE, pbResult: PBYTE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptHmacSha256Algorithm: PCSYMCRYPT_MAC; } @@ -4798,7 +4803,7 @@ extern "C" { extern "C" { pub fn SymCryptHmacSha384Result(pState: PSYMCRYPT_HMAC_SHA384_STATE, pbResult: PBYTE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptHmacSha384Algorithm: PCSYMCRYPT_MAC; } @@ -4840,7 +4845,7 @@ extern "C" { extern "C" { pub fn SymCryptHmacSha512Result(pState: PSYMCRYPT_HMAC_SHA512_STATE, pbResult: PBYTE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptHmacSha512Algorithm: PCSYMCRYPT_MAC; } @@ -4899,7 +4904,7 @@ extern "C" { cbData: SIZE_T, ); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptAesBlockCipher: PCSYMCRYPT_BLOCKCIPHER; } @@ -5078,9 +5083,14 @@ extern "C" { extern "C" { pub fn SymCryptHkdfSelfTest(); } +#[cfg(feature = "dynamic")] extern "C" { pub fn SymCryptRandom(pbRandom: PBYTE, cbRandom: SIZE_T); } +#[cfg(not(feature = "dynamic"))] +extern "C" { + pub fn SymCryptCallbackRandom(pbBuffer: PBYTE, cbBuffer: SIZE_T) -> SYMCRYPT_ERROR; +} pub const _SYMCRYPT_NUMBER_FORMAT_SYMCRYPT_NUMBER_FORMAT_LSB_FIRST: _SYMCRYPT_NUMBER_FORMAT = 1; pub const _SYMCRYPT_NUMBER_FORMAT_SYMCRYPT_NUMBER_FORMAT_MSB_FIRST: _SYMCRYPT_NUMBER_FORMAT = 2; pub type _SYMCRYPT_NUMBER_FORMAT = ::std::os::raw::c_int; @@ -5327,19 +5337,19 @@ extern "C" { extern "C" { pub fn SymCryptEcurveSizeofFieldElement(pCurve: PCSYMCRYPT_ECURVE) -> UINT32; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptEcurveParamsNistP256: PCSYMCRYPT_ECURVE_PARAMS; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptEcurveParamsNistP384: PCSYMCRYPT_ECURVE_PARAMS; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptEcurveParamsNistP521: PCSYMCRYPT_ECURVE_PARAMS; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptEcurveParamsCurve25519: PCSYMCRYPT_ECURVE_PARAMS; } diff --git a/symcrypt-sys/src/bindings/aarch64_unknown_linux_gnu.rs b/symcrypt-sys/src/bindings/aarch64_unknown_linux_gnu.rs index b1c9e4df..ff90d93e 100644 --- a/symcrypt-sys/src/bindings/aarch64_unknown_linux_gnu.rs +++ b/symcrypt-sys/src/bindings/aarch64_unknown_linux_gnu.rs @@ -4198,6 +4198,11 @@ extern "C" { extern "C" { pub fn SymCryptStoreMsbFirstUint64(src: UINT64, pbDst: PBYTE, cbDst: SIZE_T) -> SYMCRYPT_ERROR; } +#[cfg(not(feature = "dynamic"))] +extern "C" { + pub fn SymCryptInit(); +} +#[cfg(feature = "dynamic")] extern "C" { pub fn SymCryptModuleInit(api: UINT32, minor: UINT32); } @@ -4788,9 +4793,14 @@ extern "C" { extern "C" { pub fn SymCryptHkdfSelfTest(); } +#[cfg(feature = "dynamic")] extern "C" { pub fn SymCryptRandom(pbRandom: PBYTE, cbRandom: SIZE_T); } +#[cfg(not(feature = "dynamic"))] +extern "C" { + pub fn SymCryptCallbackRandom(pbBuffer: PBYTE, cbBuffer: SIZE_T) -> SYMCRYPT_ERROR; +} pub const _SYMCRYPT_NUMBER_FORMAT_SYMCRYPT_NUMBER_FORMAT_LSB_FIRST: _SYMCRYPT_NUMBER_FORMAT = 1; pub const _SYMCRYPT_NUMBER_FORMAT_SYMCRYPT_NUMBER_FORMAT_MSB_FIRST: _SYMCRYPT_NUMBER_FORMAT = 2; pub type _SYMCRYPT_NUMBER_FORMAT = ::std::os::raw::c_uint; diff --git a/symcrypt-sys/src/bindings/x86_64_pc_windows_msvc.rs b/symcrypt-sys/src/bindings/x86_64_pc_windows_msvc.rs index 07970b27..bbbedfb9 100644 --- a/symcrypt-sys/src/bindings/x86_64_pc_windows_msvc.rs +++ b/symcrypt-sys/src/bindings/x86_64_pc_windows_msvc.rs @@ -1228,35 +1228,35 @@ impl Default for _SYMCRYPT_OID { } pub type SYMCRYPT_OID = _SYMCRYPT_OID; pub type PCSYMCRYPT_OID = *const SYMCRYPT_OID; -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptMd5OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha1OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha256OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha384OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha512OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha3_256OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha3_384OidList: [SYMCRYPT_OID; 2usize]; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha3_512OidList: [SYMCRYPT_OID; 2usize]; } @@ -4208,6 +4208,11 @@ extern "C" { extern "C" { pub fn SymCryptStoreMsbFirstUint64(src: UINT64, pbDst: PBYTE, cbDst: SIZE_T) -> SYMCRYPT_ERROR; } +#[cfg(not(feature = "dynamic"))] +extern "C" { + pub fn SymCryptInit(); +} +#[cfg(feature = "dynamic")] extern "C" { pub fn SymCryptModuleInit(api: UINT32, minor: UINT32); } @@ -4226,7 +4231,7 @@ extern "C" { extern "C" { pub fn SymCryptMd5StateCopy(pSrc: PCSYMCRYPT_MD5_STATE, pDst: PSYMCRYPT_MD5_STATE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptMd5Algorithm: PCSYMCRYPT_HASH; } @@ -4245,7 +4250,7 @@ extern "C" { extern "C" { pub fn SymCryptSha1StateCopy(pSrc: PCSYMCRYPT_SHA1_STATE, pDst: PSYMCRYPT_SHA1_STATE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha1Algorithm: PCSYMCRYPT_HASH; } @@ -4264,7 +4269,7 @@ extern "C" { extern "C" { pub fn SymCryptSha256StateCopy(pSrc: PCSYMCRYPT_SHA256_STATE, pDst: PSYMCRYPT_SHA256_STATE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha256Algorithm: PCSYMCRYPT_HASH; } @@ -4283,7 +4288,7 @@ extern "C" { extern "C" { pub fn SymCryptSha384StateCopy(pSrc: PCSYMCRYPT_SHA384_STATE, pDst: PSYMCRYPT_SHA384_STATE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha384Algorithm: PCSYMCRYPT_HASH; } @@ -4302,7 +4307,7 @@ extern "C" { extern "C" { pub fn SymCryptSha512StateCopy(pSrc: PCSYMCRYPT_SHA512_STATE, pDst: PSYMCRYPT_SHA512_STATE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha512Algorithm: PCSYMCRYPT_HASH; } @@ -4324,7 +4329,7 @@ extern "C" { pDst: PSYMCRYPT_SHA3_256_STATE, ); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha3_256Algorithm: PCSYMCRYPT_HASH; } @@ -4346,7 +4351,7 @@ extern "C" { pDst: PSYMCRYPT_SHA3_384_STATE, ); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha3_384Algorithm: PCSYMCRYPT_HASH; } @@ -4368,7 +4373,7 @@ extern "C" { pDst: PSYMCRYPT_SHA3_512_STATE, ); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptSha3_512Algorithm: PCSYMCRYPT_HASH; } @@ -4406,7 +4411,7 @@ extern "C" { extern "C" { pub fn SymCryptHmacMd5Result(pState: PSYMCRYPT_HMAC_MD5_STATE, pbResult: PBYTE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptHmacMd5Algorithm: PCSYMCRYPT_MAC; } @@ -4448,7 +4453,7 @@ extern "C" { extern "C" { pub fn SymCryptHmacSha1Result(pState: PSYMCRYPT_HMAC_SHA1_STATE, pbResult: PBYTE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptHmacSha1Algorithm: PCSYMCRYPT_MAC; } @@ -4490,7 +4495,7 @@ extern "C" { extern "C" { pub fn SymCryptHmacSha256Result(pState: PSYMCRYPT_HMAC_SHA256_STATE, pbResult: PBYTE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptHmacSha256Algorithm: PCSYMCRYPT_MAC; } @@ -4532,7 +4537,7 @@ extern "C" { extern "C" { pub fn SymCryptHmacSha384Result(pState: PSYMCRYPT_HMAC_SHA384_STATE, pbResult: PBYTE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptHmacSha384Algorithm: PCSYMCRYPT_MAC; } @@ -4574,7 +4579,7 @@ extern "C" { extern "C" { pub fn SymCryptHmacSha512Result(pState: PSYMCRYPT_HMAC_SHA512_STATE, pbResult: PBYTE); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptHmacSha512Algorithm: PCSYMCRYPT_MAC; } @@ -4633,7 +4638,7 @@ extern "C" { cbData: SIZE_T, ); } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptAesBlockCipher: PCSYMCRYPT_BLOCKCIPHER; } @@ -4812,9 +4817,14 @@ extern "C" { extern "C" { pub fn SymCryptHkdfSelfTest(); } +#[cfg(feature = "dynamic")] extern "C" { pub fn SymCryptRandom(pbRandom: PBYTE, cbRandom: SIZE_T); } +#[cfg(not(feature = "dynamic"))] +extern "C" { + pub fn SymCryptCallbackRandom(pbBuffer: PBYTE, cbBuffer: SIZE_T) -> SYMCRYPT_ERROR; +} pub const _SYMCRYPT_NUMBER_FORMAT_SYMCRYPT_NUMBER_FORMAT_LSB_FIRST: _SYMCRYPT_NUMBER_FORMAT = 1; pub const _SYMCRYPT_NUMBER_FORMAT_SYMCRYPT_NUMBER_FORMAT_MSB_FIRST: _SYMCRYPT_NUMBER_FORMAT = 2; pub type _SYMCRYPT_NUMBER_FORMAT = ::std::os::raw::c_int; @@ -5061,19 +5071,19 @@ extern "C" { extern "C" { pub fn SymCryptEcurveSizeofFieldElement(pCurve: PCSYMCRYPT_ECURVE) -> UINT32; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptEcurveParamsNistP256: PCSYMCRYPT_ECURVE_PARAMS; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptEcurveParamsNistP384: PCSYMCRYPT_ECURVE_PARAMS; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptEcurveParamsNistP521: PCSYMCRYPT_ECURVE_PARAMS; } -#[link(name = "symcrypt", kind = "dylib")] +#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))] extern "C" { pub static SymCryptEcurveParamsCurve25519: PCSYMCRYPT_ECURVE_PARAMS; } diff --git a/symcrypt-sys/src/bindings/x86_64_unknown_linux_gnu.rs b/symcrypt-sys/src/bindings/x86_64_unknown_linux_gnu.rs index 8bda4666..cb35fa3c 100644 --- a/symcrypt-sys/src/bindings/x86_64_unknown_linux_gnu.rs +++ b/symcrypt-sys/src/bindings/x86_64_unknown_linux_gnu.rs @@ -4198,6 +4198,11 @@ extern "C" { extern "C" { pub fn SymCryptStoreMsbFirstUint64(src: UINT64, pbDst: PBYTE, cbDst: SIZE_T) -> SYMCRYPT_ERROR; } +#[cfg(not(feature = "dynamic"))] +extern "C" { + pub fn SymCryptInit(); +} +#[cfg(feature = "dynamic")] extern "C" { pub fn SymCryptModuleInit(api: UINT32, minor: UINT32); } @@ -4788,9 +4793,14 @@ extern "C" { extern "C" { pub fn SymCryptHkdfSelfTest(); } +#[cfg(feature = "dynamic")] extern "C" { pub fn SymCryptRandom(pbRandom: PBYTE, cbRandom: SIZE_T); } +#[cfg(not(feature = "dynamic"))] +extern "C" { + pub fn SymCryptCallbackRandom(pbBuffer: PBYTE, cbBuffer: SIZE_T) -> SYMCRYPT_ERROR; +} pub const _SYMCRYPT_NUMBER_FORMAT_SYMCRYPT_NUMBER_FORMAT_LSB_FIRST: _SYMCRYPT_NUMBER_FORMAT = 1; pub const _SYMCRYPT_NUMBER_FORMAT_SYMCRYPT_NUMBER_FORMAT_MSB_FIRST: _SYMCRYPT_NUMBER_FORMAT = 2; pub type _SYMCRYPT_NUMBER_FORMAT = ::std::os::raw::c_uint;