Skip to content

Adding static feature to replace dynamic feature #88

New issue

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

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

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/build_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,18 @@ jobs:
- name: Release build
run: cargo build --release --locked --verbose --target ${{ matrix.target }}

- name: Run tests (Debug, dynamic)
- name: Run tests (Debug, static)
if: matrix.run-tests
run: cargo test --locked --verbose --all-features --target ${{ matrix.target }}

- name: Run tests (Release, dynamic)
- name: Run tests (Release, static)
if: matrix.run-tests
run: cargo test --release --locked --verbose --all-features --target ${{ matrix.target }}

- name: Run test (Debug, static)
- name: Run test (Debug, dynamic)
if: matrix.run-tests
run: cargo test --features ${{ env.FEATURES_TO_TEST }} --locked --target ${{ matrix.target }}

- name: Run test (Release, static)
- name: Run test (Release, dynamic)
if: matrix.run-tests
run: cargo test --features ${{ env.FEATURES_TO_TEST }} --locked --target ${{ matrix.target }}
8 changes: 4 additions & 4 deletions .github/workflows/build_windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,18 @@ jobs:
- name: Release build
run: cargo build --release --locked --verbose --target ${{ matrix.target }}

- name: Run tests (Debug, dynamic)
- name: Run tests (Debug, static)
if: matrix.run-tests
run: cargo test --locked --verbose --all-features --target ${{ matrix.target }}

- name: Run tests (Release, dynamic)
- name: Run tests (Release, static)
if: matrix.run-tests
run: cargo test --release --locked --verbose --all-features --target ${{ matrix.target }}

- name: Run test (Debug, static)
- name: Run test (Debug, dynamic)
if: matrix.run-tests
run: cargo test --features ${{ env.FEATURES_TO_TEST }} --locked --target ${{ matrix.target }}

- name: Run test (Release, static)
- name: Run test (Release, dynamic)
if: matrix.run-tests
run: cargo test --features ${{ env.FEATURES_TO_TEST }} --locked --target ${{ matrix.target }}
2 changes: 2 additions & 0 deletions .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions rust-symcrypt/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "symcrypt"
authors = ["nnmkhang"]
version = "0.5.1"
version = "0.6.0"
license = "MIT OR Apache-2.0"
description = "Friendly and Idiomatic Wrappers for SymCrypt"
edition.workspace = true
Expand All @@ -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"

Expand All @@ -24,7 +24,7 @@ default = []
md5 = []
sha1 = []
pkcs1-encrypt-decrypt = []
dynamic = ["symcrypt-sys/dynamic"]
static = ["symcrypt-sys/static"]

[dev-dependencies]
hex = "0.4.3"
30 changes: 13 additions & 17 deletions rust-symcrypt/INSTALL.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,44 @@
# 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 "<your-path-to-symcrypt-lib-folder>"`

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 "<your-path-to-symcrypt-lib-folder>"`; `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`.

**Note:** While the `symcrypt` crate has only been tested on `Ubuntu`, working with other distros should be similar. 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. The path may be different depending on your flavour of Linux, and architecture.
75 changes: 49 additions & 26 deletions rust-symcrypt/README.md
Original file line number Diff line number Diff line change
@@ -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 **only** meant to be used for rapid development and testing. Static linking is highly experimental, not optimized, does not offer FIPS and is **not to be used in 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

Expand Down Expand Up @@ -62,69 +64,90 @@ 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. Dynamic linking is enabled by default.

---
## Dynamic Linking:


Dynamic linking is set by default, meaning if you do not explicitly set the `static` feature, 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.


### 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 "<your-path-to-symcrypt-lib-folder>"`

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.
For Ubuntu, you can install SymCrypt via package manager by connecting to PMC ( Example shown for Ubuntu `24.04` ):

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`

1. [Connect to PMC](https://learn.microsoft.com/en-us/linux/packages)
2. `sudo apt-get install symcrypt`
For more info on connecting to PMC please see: [Connecting to PMC](https://learn.microsoft.com/en-us/linux/packages)

Alternatively, you can manually install the lib files:
If you want to try connecting with another flavour of Linux, or for more info please see `INSTALL.md`

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`.
---
## Static Linking:

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: Static linking is highly experimental and should not be used in production and or release builds. If you are Microsoft employee please contact the SymCrypt team for more info.**

**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.
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.

If you want to enable the `static` feature for rapid development and ease of use, please add the `static` feature in your `Cargo.toml`

```cargo
[dependencies]
symcrypt = {vesrion = "0.6.0", features = ["static"]}
hex = "0.4.3"
```
---

## 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 = "0.5.1"
symcrypt = {vesrion = "0.6.0", features = ["static"]}
hex = "0.4.3"
```

include symcrypt in your code

If dynamic linking:
```cargo
[dependencies]
symcrypt = {vesrion = "0.6.0"}
hex = "0.4.3"
```

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);
```
12 changes: 6 additions & 6 deletions rust-symcrypt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ fn symcrypt_init() {
unsafe {
// SAFETY: FFI calls, blocking from being run again.

#[cfg(feature = "dynamic")]
#[cfg(not(feature = "static"))]
INIT.call_once(|| {
symcrypt_sys::SymCryptModuleInit(
symcrypt_sys::SYMCRYPT_CODE_VERSION_API,
symcrypt_sys::SYMCRYPT_CODE_VERSION_MINOR,
)
});

#[cfg(not(feature = "dynamic"))]
#[cfg(feature = "static")]
INIT.call_once(|| {
symcrypt_sys::SymCryptInit();
});
Expand All @@ -53,12 +53,12 @@ pub fn symcrypt_random(buff: &mut [u8]) {
unsafe {
// SAFETY: FFI call

// Call SymCryptRandom for dynamic linking
#[cfg(feature = "dynamic")]
// Call SymCryptRandom when dynamic linking
#[cfg(not(feature = "static"))]
symcrypt_sys::SymCryptRandom(buff.as_mut_ptr(), buff.len() as symcrypt_sys::SIZE_T);

// Call SymCryptCallbackRandom for static linking
#[cfg(not(feature = "dynamic"))]
// Call SymCryptCallbackRandom when static linking
#[cfg(feature = "static")]
symcrypt_sys::SymCryptCallbackRandom(buff.as_mut_ptr(), buff.len() as symcrypt_sys::SIZE_T);
}
}
Expand Down
6 changes: 3 additions & 3 deletions symcrypt-bindgen/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ fn fix_bindings_for_windows(triple: &str, bindings_file: &str) {
if triple.contains("windows") {
println!("Fixing bindings for Windows");
let link_str =
r#"#[cfg_attr(feature = "dynamic", link(name = "symcrypt", kind = "dylib"))]"#;
r#"#[cfg_attr(not(feature = "static"), 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 =
Expand Down Expand Up @@ -208,12 +208,12 @@ fn fix_symcrypt_bindings(bindings_file: &str) {
line if line == "pub fn SymCryptInit();"
|| line.starts_with("pub fn SymCryptCallbackRandom(") =>
{
"#[cfg(not(feature = \"dynamic\"))]"
"#[cfg(feature = \"static\")]"
}
line if line.starts_with("pub fn SymCryptModuleInit(")
|| line.starts_with("pub fn SymCryptRandom(") =>
{
"#[cfg(feature = \"dynamic\")]"
"#[cfg(not(feature = \"static\"))]"
}
_ => "",
};
Expand Down
4 changes: 2 additions & 2 deletions symcrypt-sys/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[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
Expand All @@ -16,7 +16,7 @@ exclude = ["symcrypt/*", "inc/*"] # FIXME: update this before merging to main br
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
dynamic = []
static = []

[dependencies]
libc = "0.2.0"
Expand Down
2 changes: 1 addition & 1 deletion symcrypt-sys/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading