Skip to content

Commit

Permalink
Added support PQC in the browser with the target wasm32-wasi now supp…
Browse files Browse the repository at this point in the history
…orted (#26)

* Added support for PQC with WebAssembly using target wasm32-wasi

* Added a WASM.md file that explains how to compile this routine for WebAssembly

* Fixed a linking error on the randombytes call when using wasm32-wasi compile target

* Updated the documentation so the user knows how to setup the sysroot

* Now using the WASI_SDK_DIR environment variable for the location of sysroot

* Removed common.h and duplicated the include lines instead

* Did some negative testing on the path change and noticed I'd missed some of the sysroot references, got them all now

* Reverted a bunch of the include file updates back to the originals

* Fix randombytes implementation

* Fix build.rs in pqcrypto-internals for cross-compilation

* Refactor pqcrypto-templates build.rs.j2 and ffi.rs.j2

* Resolved merge conflicts

* Update from PQClean

* Tests should now run on pull requests which will help you do code reviews

* Added WASI builds to CI/CD

* Fixing a typo in the WASI tests

* Fixed a bug in the rust install command

* The WASI tests now install the WASI SDK

* Fixing some exports on the WASI tests

* Added a fix so the submodules are properly pulled

* Fixed some mistakes in the CI/CD

* More mistakes in the CI/CD that are now fixed

* Update WASM.md

Co-authored-by: Thom Wiggers <[email protected]>

* Update WASM.md

Co-authored-by: Thom Wiggers <[email protected]>

* Update WASM.md

Co-authored-by: Thom Wiggers <[email protected]>

* Update WASM.md

Co-authored-by: Thom Wiggers <[email protected]>

* CI/CD will now trigger on all pull requests rather than just to master

* Removed a typo on the code blocks

Co-authored-by: Thom Wiggers <[email protected]>
Co-authored-by: Robin Winzler <[email protected]>
Co-authored-by: Thom Wiggers <[email protected]>
  • Loading branch information
4 people authored Dec 1, 2021
1 parent e1a156c commit 4bc2ea4
Show file tree
Hide file tree
Showing 15 changed files with 255 additions and 3 deletions.
39 changes: 38 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
on: push
on:
push:
pull_request:

name: Continuous integration

Expand All @@ -12,6 +14,7 @@ jobs:
- beta
- nightly
env:
CARGO_TERM_COLOR: always
# 20 MiB stack
RUST_MIN_STACK: 20971520

Expand Down Expand Up @@ -50,4 +53,38 @@ jobs:
command: clippy
args: -- -D warnings

wasi:
name: wasi
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
- beta
- nightly
env:
CARGO_TERM_COLOR: always
# 20 MiB stack
RUST_MIN_STACK: 20971520
steps:
- uses: actions/checkout@v2
with:
submodules: true
- name: Install WASI
run: cargo install cargo-wasi
- name: Install wasmtime
run: curl https://wasmtime.dev/install.sh -sSf | bash
- name: Install WASI SDK
run: |
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sysroot-12.0.tar.gz
tar -xvzf wasi-sysroot-12.0.tar.gz
rm wasi-sysroot-12.0.tar.gz
- name: Run tests
run: |
export WASI_SDK_DIR="$(pwd)/wasi-sysroot"
export WASMTIME_HOME="$(pwd)/.wasmtime"
export PATH="$WASMTIME_HOME/bin:$PATH"
cargo wasi build
#cargo wasi test -- --nocapture
# vim: set ft=yaml ts=2 sw=2 tw=0 et :
39 changes: 39 additions & 0 deletions WASM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Support for WebAssembly
=======================

# Summary

Due to the need for a standard library to build these quantum routines it is not
possible to compile them as pure no-std WASM. However by using wasi and its standard
library, it becomes possible.

# Steps

Download the wasm32-wasi sysroot build from https://github.com/WebAssembly/wasi-sdk
and set the environment variable to point to it. This example installs it globally and makes it
available system-wide. You may also consider adding it to your profile's environment variables
or exporting the environment variable each time manually.

```sh
sudo mkdir -p /opt/wasi
cd /opt/wasi
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sysroot-12.0.tar.gz -O /tmp/wasi-sysroot-12.0.tar.gz
sudo tar -xvzf /tmp/wasi-sysroot-12.0.tar.gz
rm /tmp/wasi-sysroot-12.0.tar.gz

sudo tee /etc/profile.d/wasi.sh <<EOF
export WASI_SDK_DIR="/opt/wasi/wasi-sysroot"
EOF
source /etc/profile.d/wasi.sh
```

Note: While the source command brings the WASI export variables into your current
terminal any new terminals will miss this until you log out and back in.

You can now compile the library for linking with WebAssembly using the following
command or via cargo dependencies with the same specifics.

```sh
cd pqcrypto
cargo build --no-default-features --target wasm32-wasi --features avx2,serialization
```
21 changes: 21 additions & 0 deletions pqcrypto-classicmceliece/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ macro_rules! build_vec {
let mut builder = cc::Build::new();
let target_dir: PathBuf = ["pqclean", "crypto_kem", $variant, "vec"].iter().collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap();

builder
Expand All @@ -37,6 +44,13 @@ macro_rules! build_clean {
.iter()
.collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap();

builder
Expand All @@ -60,6 +74,13 @@ macro_rules! build_avx {
let mut builder = cc::Build::new();
let target_dir: PathBuf = ["pqclean", "crypto_kem", $variant, "avx"].iter().collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap();
if cfg!(target_env = "msvc") {
builder.flag("/arch:AVX2");
Expand Down
14 changes: 14 additions & 0 deletions pqcrypto-dilithium/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ macro_rules! build_clean {
.iter()
.collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap();

builder
Expand All @@ -39,6 +46,13 @@ macro_rules! build_avx2 {
.iter()
.collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap();
if cfg!(target_env = "msvc") {
builder.flag("/arch:AVX2");
Expand Down
14 changes: 14 additions & 0 deletions pqcrypto-falcon/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ macro_rules! build_clean {
.iter()
.collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap();

builder
Expand All @@ -39,6 +46,13 @@ macro_rules! build_avx2 {
.iter()
.collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap();
if cfg!(target_env = "msvc") {
builder.flag("/arch:AVX2");
Expand Down
14 changes: 14 additions & 0 deletions pqcrypto-frodo/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ macro_rules! build_opt {
let mut builder = cc::Build::new();
let target_dir: PathBuf = ["pqclean", "crypto_kem", $variant, "opt"].iter().collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap();

builder
Expand All @@ -37,6 +44,13 @@ macro_rules! build_clean {
.iter()
.collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap();

builder
Expand Down
7 changes: 7 additions & 0 deletions pqcrypto-hqc/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ macro_rules! build_clean {
.iter()
.collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap();

builder
Expand Down
20 changes: 18 additions & 2 deletions pqcrypto-internals/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ fn main() {
cfiledir.join("sp800-185.c"),
];

cc::Build::new()
let mut build = cc::Build::new();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
build.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

build
.include(&includepath)
.files(common_files.into_iter())
.compile("pqclean_common");
Expand All @@ -25,6 +34,13 @@ fn main() {
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
if target_arch == "x86" || target_arch == "x86_64" {
let mut builder = cc::Build::new();

if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
if target_os == "windows" {
builder.flag("/arch:AVX2");
Expand All @@ -38,6 +54,6 @@ fn main() {
.join("KeccakP-1600-times4-SIMD256.c"),
)
.compile("keccak4x");
println!("cargo:rustc-link-lib=keccak4x");
println!("cargo:rustc-link-lib=keccak4x")
}
}
14 changes: 14 additions & 0 deletions pqcrypto-kyber/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ macro_rules! build_clean {
.iter()
.collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap();

builder
Expand All @@ -37,6 +44,13 @@ macro_rules! build_avx2 {
let mut builder = cc::Build::new();
let target_dir: PathBuf = ["pqclean", "crypto_kem", $variant, "avx2"].iter().collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap();
if cfg!(target_env = "msvc") {
builder.flag("/arch:AVX2");
Expand Down
14 changes: 14 additions & 0 deletions pqcrypto-ntru/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ macro_rules! build_clean {
.iter()
.collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap();

builder
Expand All @@ -37,6 +44,13 @@ macro_rules! build_avx2 {
let mut builder = cc::Build::new();
let target_dir: PathBuf = ["pqclean", "crypto_kem", $variant, "avx2"].iter().collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap();
if cfg!(target_env = "msvc") {
builder.flag("/arch:AVX2");
Expand Down
14 changes: 14 additions & 0 deletions pqcrypto-ntruprime/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ macro_rules! build_clean {
.iter()
.collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap();

builder
Expand All @@ -37,6 +44,13 @@ macro_rules! build_avx2 {
let mut builder = cc::Build::new();
let target_dir: PathBuf = ["pqclean", "crypto_kem", $variant, "avx2"].iter().collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap();
if cfg!(target_env = "msvc") {
builder.flag("/arch:AVX2");
Expand Down
7 changes: 7 additions & 0 deletions pqcrypto-rainbow/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ macro_rules! build_clean {
.iter()
.collect();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "wasi" {
let wasi_sdk_path =
&std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR");
builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str());
}

let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap();

builder
Expand Down
Loading

0 comments on commit 4bc2ea4

Please sign in to comment.