├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── Cargo.toml ├── Pipfile ├── Pipfile.lock ├── README.md ├── SECURITY.md ├── WASM.md ├── generate-implementations.py ├── implementations.yaml ├── pqcrypto-classicmceliece ├── Cargo.toml ├── README.md ├── build.rs ├── pqclean └── src │ ├── ffi.rs │ ├── lib.rs │ ├── mceliece348864.rs │ ├── mceliece348864f.rs │ ├── mceliece460896.rs │ ├── mceliece460896f.rs │ ├── mceliece6688128.rs │ ├── mceliece6688128f.rs │ ├── mceliece6960119.rs │ ├── mceliece6960119f.rs │ ├── mceliece8192128.rs │ └── mceliece8192128f.rs ├── pqcrypto-falcon ├── Cargo.toml ├── README.md ├── build.rs ├── pqclean └── src │ ├── falcon1024.rs │ ├── falcon512.rs │ ├── falconpadded1024.rs │ ├── falconpadded512.rs │ ├── ffi.rs │ └── lib.rs ├── pqcrypto-hqc ├── Cargo.toml ├── README.md ├── build.rs ├── pqclean └── src │ ├── ffi.rs │ ├── hqc128.rs │ ├── hqc192.rs │ ├── hqc256.rs │ └── lib.rs ├── pqcrypto-internals ├── Cargo.toml ├── build.rs ├── cfiles │ ├── aes.c │ ├── fips202.c │ ├── keccak2x │ │ ├── feat.S │ │ ├── fips202x2.c │ │ └── fips202x2.h │ ├── keccak4x │ │ ├── KeccakP-1600-times4-SIMD256.c │ │ ├── KeccakP-1600-times4-SnP.h │ │ ├── KeccakP-1600-unrolling.macros │ │ ├── Makefile │ │ ├── Makefile.Microsoft_nmake │ │ ├── SIMD256-config.h │ │ ├── align.h │ │ └── brg_endian.h │ ├── nistseedexpander.c │ ├── randombytes.c │ ├── sha2.c │ └── sp800-185.c ├── include │ ├── aes.h │ ├── fips202.h │ ├── nistseedexpander.h │ ├── randombytes.h │ ├── sha2.h │ └── sp800-185.h └── src │ └── lib.rs ├── pqcrypto-mldsa ├── Cargo.toml ├── README.md ├── build.rs ├── pqclean └── src │ ├── ffi.rs │ ├── lib.rs │ ├── mldsa44.rs │ ├── mldsa65.rs │ └── mldsa87.rs ├── pqcrypto-mlkem ├── Cargo.toml ├── README.md ├── build.rs ├── pqclean └── src │ ├── ffi.rs │ ├── lib.rs │ ├── mlkem1024.rs │ ├── mlkem512.rs │ └── mlkem768.rs ├── pqcrypto-sphincsplus ├── Cargo.toml ├── README.md ├── build.rs ├── pqclean └── src │ ├── ffi.rs │ ├── lib.rs │ ├── sphincssha2128fsimple.rs │ ├── sphincssha2128ssimple.rs │ ├── sphincssha2192fsimple.rs │ ├── sphincssha2192ssimple.rs │ ├── sphincssha2256fsimple.rs │ ├── sphincssha2256ssimple.rs │ ├── sphincsshake128fsimple.rs │ ├── sphincsshake128ssimple.rs │ ├── sphincsshake192fsimple.rs │ ├── sphincsshake192ssimple.rs │ ├── sphincsshake256fsimple.rs │ └── sphincsshake256ssimple.rs ├── pqcrypto-template ├── pqcrypto │ ├── Cargo.toml.j2 │ ├── README.md.j2 │ ├── examples │ │ ├── keygen.rs │ │ ├── signer.rs │ │ └── verifier.rs │ └── src │ │ └── lib.rs.j2 ├── scheme │ ├── Cargo.toml.j2 │ ├── README.md.j2 │ ├── build.rs.j2 │ └── src │ │ ├── ffi.rs.j2 │ │ ├── lib.rs.j2 │ │ └── scheme.rs.j2 └── workspace-Cargo.toml.j2 ├── pqcrypto-traits ├── Cargo.toml └── src │ ├── kem.rs │ ├── lib.rs │ └── sign.rs ├── pqcrypto ├── Cargo.toml ├── README.md ├── examples │ ├── keygen.rs │ ├── signer.rs │ └── verifier.rs └── src │ └── lib.rs └── release.sh /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | pull_request: 4 | 5 | name: Continuous integration 6 | 7 | jobs: 8 | ci: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | rust: 13 | - stable 14 | - beta 15 | - nightly 16 | env: 17 | CARGO_TERM_COLOR: always 18 | # 20 MiB stack 19 | RUST_MIN_STACK: 20971520 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | submodules: true 25 | 26 | - name: Install Rust 27 | run: | 28 | rustup set auto-self-update disable 29 | rustup toolchain install ${{ matrix.rust }} --profile minimal --component rustfmt,clippy 30 | rustup default ${{ matrix.rust }} 31 | echo CARGO_TERM_COLOR=always >> $GITHUB_ENV 32 | echo CARGO_INCREMENTAL=0 >> $GITHUB_ENV 33 | echo RUST_BACKTRACE=1 >> $GITHUB_ENV 34 | 35 | - name: build with cryptographically-insecure turned on (if available) 36 | run: cargo build --features cryptographically-insecure 37 | 38 | - name: Run tests with cryptographically-insecure turned on 39 | run: cargo test --features cryptographically-insecure 40 | 41 | - name: Run cargo check with all features 42 | run: cargo check --all-features 43 | 44 | - name: Run cargo fmt 45 | run: cargo fmt --all -- --check 46 | 47 | - name: run Cargo clippy 48 | run: cargo clippy -- -D warnings -A deprecated 49 | 50 | android: 51 | runs-on: ubuntu-latest 52 | strategy: 53 | matrix: 54 | rust: 55 | - stable 56 | - beta 57 | - nightly 58 | env: 59 | CARGO_TERM_COLOR: always 60 | # 20 MiB stack 61 | RUST_MIN_STACK: 20971520 62 | 63 | steps: 64 | - uses: actions/checkout@v4 65 | with: 66 | submodules: true 67 | 68 | - name: Install Rust 69 | run: | 70 | rustup set auto-self-update disable 71 | rustup toolchain install ${{ matrix.rust }} --profile minimal --component rustfmt,clippy 72 | rustup target add aarch64-linux-android 73 | echo CARGO_TERM_COLOR=always >> $GITHUB_ENV 74 | echo CARGO_INCREMENTAL=0 >> $GITHUB_ENV 75 | echo RUST_BACKTRACE=1 >> $GITHUB_ENV 76 | 77 | - name: Setup Android SDK 78 | uses: android-actions/setup-android@07976c6290703d34c16d382cb36445f98bb43b1f #3.2.0 79 | 80 | - name: Setup Android NDK 81 | run: sdkmanager "ndk;26.1.10909125" 82 | 83 | - name: Compile for Android 84 | run: | 85 | cargo install cargo-ndk 86 | cargo ndk -t aarch64-linux-android build 87 | 88 | # wasi: 89 | # name: wasi 90 | # runs-on: ubuntu-latest 91 | # strategy: 92 | # matrix: 93 | # rust: 94 | # - stable 95 | # - beta 96 | # - nightly 97 | # env: 98 | # # 20 MiB stack 99 | # RUST_MIN_STACK: 20971520 100 | # steps: 101 | # - uses: actions/checkout@v4 102 | # with: 103 | # submodules: true 104 | 105 | # - name: Install Rust 106 | # run: | 107 | # rustup set auto-self-update disable 108 | # rustup toolchain install ${{ matrix.rust }} --profile minimal --component rustfmt clippy 109 | # rustup default ${{ matrix.rust }} 110 | # echo CARGO_TERM_COLOR=always >> $GITHUB_ENV 111 | # echo CARGO_INCREMENTAL=0 >> $GITHUB_ENV 112 | # echo RUST_BACKTRACE=1 >> $GITHUB_ENV 113 | 114 | # - name: Install WASI 115 | # run: cargo install cargo-wasi 116 | # - name: Install wasmtime 117 | # run: curl https://wasmtime.dev/install.sh -sSf | bash 118 | # - name: Install WASI SDK 119 | # run: | 120 | # wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sysroot-12.0.tar.gz 121 | # tar -xvzf wasi-sysroot-12.0.tar.gz 122 | # rm wasi-sysroot-12.0.tar.gz 123 | # - name: Run tests 124 | # run: | 125 | # export WASI_SDK_DIR="$(pwd)/wasi-sysroot" 126 | # export WASMTIME_HOME="$(pwd)/.wasmtime" 127 | # export PATH="$WASMTIME_HOME/bin:$PATH" 128 | # cargo wasi build --features cryptographically-insecure 129 | # #cargo wasi test -- --nocapture 130 | 131 | # vim: set ft=yaml ts=2 sw=2 tw=0 et : 132 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | 4 | /target 5 | **/*.rs.bk 6 | Cargo.lock 7 | 8 | .vscode/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "pqclean"] 2 | path = pqclean 3 | url = https://github.com/pqclean/PQClean.git 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | # This file has been generated by generate-implementations.py 2 | [workspace] 3 | members=[ 4 | "pqcrypto", 5 | "pqcrypto-traits", 6 | "pqcrypto-internals", 7 | "pqcrypto-mlkem", 8 | "pqcrypto-classicmceliece", 9 | "pqcrypto-hqc", 10 | "pqcrypto-mldsa", 11 | "pqcrypto-falcon", 12 | "pqcrypto-sphincsplus", 13 | ] 14 | resolver="2" -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | pyyaml = "*" 8 | jinja2 = "*" 9 | 10 | [dev-packages] 11 | 12 | [requires] 13 | python_version = "3.13" 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bindings to quantum-safe cryptographic libraries 2 | 3 | [![dependency status](https://deps.rs/repo/github/rustpq/pqcrypto/status.svg)](https://deps.rs/repo/github/rustpq/pqcrypto) 4 | 5 | This repository contains bindings to C implementations of cryptographic algorithms part of the [NIST competition][nist]. 6 | These bindings are generated based on the [PQClean][pqclean] project, which aims to collect 'clean' implementations of cryptographic algorithms. 7 | 8 | ## How to generate the bindings 9 | 10 | The `pqcrypto-templates` folder contains the master copies of the Rust files. 11 | The binding libraries are generated from the PQClean meta files and PQClean specified API. 12 | The file `implementations.yaml` controls the version numbers and included variants of each scheme. 13 | The generation of the different pq-crates is done by the `generate-implementation.py` script. 14 | 15 | ## Documentation 16 | 17 | See the [documentation of the master project on docs.rs][docsrs]. 18 | 19 | [nist]: https://nist.gov/pqcrypto 20 | [pqclean]: https://github.com/pqclean/pqclean/ 21 | [docsrs]: https://docs.rs/pqcrypto/ 22 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # A note on the security of the included implementations and schemes 2 | 3 | This project contains (reference) implementations of cryptographic libraries. 4 | We do not make any security claims about the code included in [PQClean][pqclean] or packaged by [rustpq][rustpq]. 5 | In the current state, we distribute reference implementations with minor modifications. 6 | We did not perform any extensive security analyses. 7 | This code is suitable for experimental or scientific use. 8 | We recommend careful expert code review before using any of the included implementations in production environments. 9 | 10 | See also the [NIST PQC Forum][forum] for discussion about the cryptographic schemes included in PQClean. 11 | 12 | [pqclean]: https://github.com/PQClean/ 13 | [forum]: https://csrc.nist.gov/Projects/Post-Quantum-Cryptography/Email-List 14 | [rustpq]: https://github.com/rustpq/ 15 | -------------------------------------------------------------------------------- /WASM.md: -------------------------------------------------------------------------------- 1 | Support for WebAssembly 2 | ======================= 3 | 4 | # Summary 5 | 6 | Due to the need for a standard library to build these quantum routines it is not 7 | possible to compile them as pure no-std WASM. However by using wasi and its standard 8 | library, it becomes possible. 9 | 10 | # Steps 11 | 12 | Download the wasm32-wasi sysroot build from https://github.com/WebAssembly/wasi-sdk 13 | and set the environment variable to point to it. This example installs it globally and makes it 14 | available system-wide. You may also consider adding it to your profile's environment variables 15 | or exporting the environment variable each time manually. 16 | 17 | ```sh 18 | sudo mkdir -p /opt/wasi 19 | cd /opt/wasi 20 | 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 21 | sudo tar -xvzf /tmp/wasi-sysroot-12.0.tar.gz 22 | rm /tmp/wasi-sysroot-12.0.tar.gz 23 | 24 | sudo tee /etc/profile.d/wasi.sh <"] 7 | edition = "2021" 8 | license = "MIT OR Apache-2.0" 9 | homepage = "https://github.com/rustpq/" 10 | repository = "https://github.com/rustpq/pqcrypto/" 11 | keywords = ["cryptography", "post-quantum", "security"] 12 | categories = ["cryptography", "no-std"] 13 | 14 | [dependencies] 15 | pqcrypto-internals = { path = "../pqcrypto-internals", version = "0.2.6" } 16 | pqcrypto-traits = { path = "../pqcrypto-traits", version = "0.3.5", default-features = false } 17 | libc = "0.2.0" 18 | serde = { version = "1.0", features = ["derive"], optional = true } 19 | serde-big-array = { version = "0.5.1", optional = true } 20 | 21 | [features] 22 | default = ["avx2", "std"] 23 | avx2 = ["std"] 24 | std = ["pqcrypto-traits/std"] 25 | serialization = ["serde", "serde-big-array"] 26 | 27 | [dev-dependencies] 28 | 29 | [build-dependencies] 30 | cc = { version = "1.0", features = ["parallel"] } 31 | glob = "0.3.0" 32 | 33 | [badges] 34 | travis-ci = { repository = "rustpq/pqcrypto", branch = "master" } 35 | maintenance = { status = "actively-developed" } 36 | 37 | -------------------------------------------------------------------------------- /pqcrypto-classicmceliece/README.md: -------------------------------------------------------------------------------- 1 | # classicmceliece 2 | 3 | 4 | This crate contains bindings to the C implementations of the following schemes, 5 | from [PQClean][pqclean]. 6 | 7 | This project packages Post-Quantum cryptographic algorithms that participate in 8 | the [NIST PQC standardization effort][nistpqc]. It is currently a collection of 9 | wrappers around C implementations from the [PQClean][pqclean] project. 10 | 11 | ## Serialization 12 | 13 | If you want `serde` support, enable the `serialization` feature. 14 | 15 | ## Included implementations from PQClean 16 | 17 | Below is a list of the included schemes and the corresponding implementations 18 | sourced from [PQClean][pqclean]. The "default" implementation is used in the 19 | Rust-friendly interface, alternative implementations are exposed as ``ffi`` 20 | methods only. 21 | 22 | * ``mceliece348864`` 23 | * ``clean`` 24 | * ``avx2`` (if supported) 25 | * ``mceliece348864f`` 26 | * ``clean`` 27 | * ``avx2`` (if supported) 28 | * ``mceliece460896`` 29 | * ``clean`` 30 | * ``avx2`` (if supported) 31 | * ``mceliece460896f`` 32 | * ``clean`` 33 | * ``avx2`` (if supported) 34 | * ``mceliece6688128`` 35 | * ``clean`` 36 | * ``avx2`` (if supported) 37 | * ``mceliece6688128f`` 38 | * ``clean`` 39 | * ``avx2`` (if supported) 40 | * ``mceliece6960119`` 41 | * ``clean`` 42 | * ``avx2`` (if supported) 43 | * ``mceliece6960119f`` 44 | * ``clean`` 45 | * ``avx2`` (if supported) 46 | * ``mceliece8192128`` 47 | * ``clean`` 48 | * ``avx2`` (if supported) 49 | * ``mceliece8192128f`` 50 | * ``clean`` 51 | * ``avx2`` (if supported) 52 | 53 | ## Notes 54 | 55 | This implementation requires a lot of stack space. 56 | You need to specify ``RUST_MIN_STACK=800000000``, probably. 57 | 58 | 59 | ## License 60 | 61 | The wrappers and wrapper generation scripts in this project are covered by the 62 | MIT or Apache 2.0 licenses, at your choice. 63 | 64 | The implementations we link to are not, however. Please see the [PQClean][pqclean] 65 | project for the appropriate licenses. 66 | 67 | [pqclean]: https://github.com/PQClean/PQClean/ 68 | [nistpqc]: https://nist.gov/pqc/ -------------------------------------------------------------------------------- /pqcrypto-classicmceliece/build.rs: -------------------------------------------------------------------------------- 1 | extern crate cc; 2 | extern crate glob; 3 | 4 | use std::env; 5 | use std::path::{Path, PathBuf}; 6 | 7 | macro_rules! build_clean { 8 | ($variant:expr) => { 9 | let internals_include_path = &std::env::var("DEP_PQCRYPTO_INTERNALS_INCLUDEPATH").unwrap(); 10 | let common_dir = Path::new("pqclean/common"); 11 | 12 | let mut builder = cc::Build::new(); 13 | let target_dir: PathBuf = ["pqclean", "crypto_kem", $variant, "clean"] 14 | .iter() 15 | .collect(); 16 | 17 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 18 | if target_os == "wasi" { 19 | let wasi_sdk_path = 20 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 21 | builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str()); 22 | } 23 | 24 | let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap(); 25 | 26 | builder 27 | .include(internals_include_path) 28 | .include(&common_dir) 29 | .include(target_dir) 30 | .files( 31 | scheme_files 32 | .into_iter() 33 | .map(|p| p.unwrap().to_string_lossy().into_owned()), 34 | ); 35 | builder.compile(format!("{}_clean", $variant).as_str()); 36 | }; 37 | } 38 | 39 | macro_rules! build_avx2 { 40 | ($variant:expr) => { 41 | let internals_include_path = &std::env::var("DEP_PQCRYPTO_INTERNALS_INCLUDEPATH").unwrap(); 42 | let common_dir = Path::new("pqclean/common"); 43 | 44 | let mut builder = cc::Build::new(); 45 | let target_dir: PathBuf = ["pqclean", "crypto_kem", $variant, "avx2"].iter().collect(); 46 | 47 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 48 | if target_os == "wasi" { 49 | let wasi_sdk_path = 50 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 51 | builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str()); 52 | } 53 | 54 | let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap(); 55 | let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); 56 | if target_env == "msvc" { 57 | builder.flag("/arch:AVX2"); 58 | } else { 59 | builder 60 | .flag("-mavx2") 61 | .flag("-mbmi2") 62 | .flag("-mbmi") 63 | .flag("-maes") 64 | .flag("-mpopcnt") 65 | .flag("-mpclmul"); 66 | } 67 | 68 | builder 69 | .include(internals_include_path) 70 | .include(&common_dir) 71 | .include(target_dir) 72 | .files( 73 | scheme_files 74 | .into_iter() 75 | .map(|p| p.unwrap().to_string_lossy().into_owned()), 76 | ); 77 | builder.compile(format!("{}_avx2", $variant).as_str()); 78 | }; 79 | } 80 | 81 | fn main() { 82 | #[allow(unused_variables)] 83 | let aes_enabled = env::var("CARGO_FEATURE_AES").is_ok(); 84 | #[allow(unused_variables)] 85 | let avx2_enabled = env::var("CARGO_FEATURE_AVX2").is_ok(); 86 | #[allow(unused_variables)] 87 | let neon_enabled = env::var("CARGO_FEATURE_NEON").is_ok(); 88 | #[allow(unused_variables)] 89 | let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); 90 | #[allow(unused_variables)] 91 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 92 | #[allow(unused_variables)] 93 | let is_windows = target_os == "windows"; 94 | #[allow(unused_variables)] 95 | let is_macos = target_os == "macos"; 96 | 97 | build_clean!("mceliece348864"); 98 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 99 | build_avx2!("mceliece348864"); 100 | } 101 | build_clean!("mceliece348864f"); 102 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 103 | build_avx2!("mceliece348864f"); 104 | } 105 | build_clean!("mceliece460896"); 106 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 107 | build_avx2!("mceliece460896"); 108 | } 109 | build_clean!("mceliece460896f"); 110 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 111 | build_avx2!("mceliece460896f"); 112 | } 113 | build_clean!("mceliece6688128"); 114 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 115 | build_avx2!("mceliece6688128"); 116 | } 117 | build_clean!("mceliece6688128f"); 118 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 119 | build_avx2!("mceliece6688128f"); 120 | } 121 | build_clean!("mceliece6960119"); 122 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 123 | build_avx2!("mceliece6960119"); 124 | } 125 | build_clean!("mceliece6960119f"); 126 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 127 | build_avx2!("mceliece6960119f"); 128 | } 129 | build_clean!("mceliece8192128"); 130 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 131 | build_avx2!("mceliece8192128"); 132 | } 133 | build_clean!("mceliece8192128f"); 134 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 135 | build_avx2!("mceliece8192128f"); 136 | } 137 | 138 | println!("cargo::rustc-check-cfg=cfg(enable_x86_avx2)"); 139 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 140 | // Print enableing flag for AVX2 implementation 141 | println!("cargo:rustc-cfg=enable_x86_avx2"); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /pqcrypto-classicmceliece/pqclean: -------------------------------------------------------------------------------- 1 | ../pqclean -------------------------------------------------------------------------------- /pqcrypto-classicmceliece/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # classicmceliece 2 | //! 3 | //! This crate provides bindings to and wrappers around the following 4 | //! implementations from [PQClean][pqc]: 5 | //! 6 | //! * mceliece348864 - clean 7 | //! * mceliece348864f - clean 8 | //! * mceliece460896 - clean 9 | //! * mceliece460896f - clean 10 | //! * mceliece6688128 - clean 11 | //! * mceliece6688128f - clean 12 | //! * mceliece6960119 - clean 13 | //! * mceliece6960119f - clean 14 | //! * mceliece8192128 - clean 15 | //! * mceliece8192128f - clean 16 | //! 17 | //! [pqc]: https://github.com/pqclean/pqclean/ 18 | //! 19 | //! # Notes 20 | //! This implementation requires a lot of stack space. You need to specify 21 | //! ``RUST_MIN_STACK=800000000``, probably. 22 | 23 | #![no_std] 24 | #![allow(clippy::len_without_is_empty)] 25 | 26 | // For no-std vectors 27 | extern crate alloc; 28 | 29 | // For tests 30 | #[cfg(feature = "std")] 31 | extern crate std; 32 | 33 | pub mod ffi; 34 | pub mod mceliece348864; 35 | pub mod mceliece348864f; 36 | pub mod mceliece460896; 37 | pub mod mceliece460896f; 38 | pub mod mceliece6688128; 39 | pub mod mceliece6688128f; 40 | pub mod mceliece6960119; 41 | pub mod mceliece6960119f; 42 | pub mod mceliece8192128; 43 | pub mod mceliece8192128f; 44 | 45 | pub use crate::mceliece348864::{ 46 | ciphertext_bytes as mceliece348864_ciphertext_bytes, decapsulate as mceliece348864_decapsulate, 47 | encapsulate as mceliece348864_encapsulate, keypair as mceliece348864_keypair, 48 | public_key_bytes as mceliece348864_public_key_bytes, 49 | secret_key_bytes as mceliece348864_secret_key_bytes, 50 | shared_secret_bytes as mceliece348864_shared_secret_bytes, 51 | }; 52 | pub use crate::mceliece348864f::{ 53 | ciphertext_bytes as mceliece348864f_ciphertext_bytes, 54 | decapsulate as mceliece348864f_decapsulate, encapsulate as mceliece348864f_encapsulate, 55 | keypair as mceliece348864f_keypair, public_key_bytes as mceliece348864f_public_key_bytes, 56 | secret_key_bytes as mceliece348864f_secret_key_bytes, 57 | shared_secret_bytes as mceliece348864f_shared_secret_bytes, 58 | }; 59 | pub use crate::mceliece460896::{ 60 | ciphertext_bytes as mceliece460896_ciphertext_bytes, decapsulate as mceliece460896_decapsulate, 61 | encapsulate as mceliece460896_encapsulate, keypair as mceliece460896_keypair, 62 | public_key_bytes as mceliece460896_public_key_bytes, 63 | secret_key_bytes as mceliece460896_secret_key_bytes, 64 | shared_secret_bytes as mceliece460896_shared_secret_bytes, 65 | }; 66 | pub use crate::mceliece460896f::{ 67 | ciphertext_bytes as mceliece460896f_ciphertext_bytes, 68 | decapsulate as mceliece460896f_decapsulate, encapsulate as mceliece460896f_encapsulate, 69 | keypair as mceliece460896f_keypair, public_key_bytes as mceliece460896f_public_key_bytes, 70 | secret_key_bytes as mceliece460896f_secret_key_bytes, 71 | shared_secret_bytes as mceliece460896f_shared_secret_bytes, 72 | }; 73 | pub use crate::mceliece6688128::{ 74 | ciphertext_bytes as mceliece6688128_ciphertext_bytes, 75 | decapsulate as mceliece6688128_decapsulate, encapsulate as mceliece6688128_encapsulate, 76 | keypair as mceliece6688128_keypair, public_key_bytes as mceliece6688128_public_key_bytes, 77 | secret_key_bytes as mceliece6688128_secret_key_bytes, 78 | shared_secret_bytes as mceliece6688128_shared_secret_bytes, 79 | }; 80 | pub use crate::mceliece6688128f::{ 81 | ciphertext_bytes as mceliece6688128f_ciphertext_bytes, 82 | decapsulate as mceliece6688128f_decapsulate, encapsulate as mceliece6688128f_encapsulate, 83 | keypair as mceliece6688128f_keypair, public_key_bytes as mceliece6688128f_public_key_bytes, 84 | secret_key_bytes as mceliece6688128f_secret_key_bytes, 85 | shared_secret_bytes as mceliece6688128f_shared_secret_bytes, 86 | }; 87 | pub use crate::mceliece6960119::{ 88 | ciphertext_bytes as mceliece6960119_ciphertext_bytes, 89 | decapsulate as mceliece6960119_decapsulate, encapsulate as mceliece6960119_encapsulate, 90 | keypair as mceliece6960119_keypair, public_key_bytes as mceliece6960119_public_key_bytes, 91 | secret_key_bytes as mceliece6960119_secret_key_bytes, 92 | shared_secret_bytes as mceliece6960119_shared_secret_bytes, 93 | }; 94 | pub use crate::mceliece6960119f::{ 95 | ciphertext_bytes as mceliece6960119f_ciphertext_bytes, 96 | decapsulate as mceliece6960119f_decapsulate, encapsulate as mceliece6960119f_encapsulate, 97 | keypair as mceliece6960119f_keypair, public_key_bytes as mceliece6960119f_public_key_bytes, 98 | secret_key_bytes as mceliece6960119f_secret_key_bytes, 99 | shared_secret_bytes as mceliece6960119f_shared_secret_bytes, 100 | }; 101 | pub use crate::mceliece8192128::{ 102 | ciphertext_bytes as mceliece8192128_ciphertext_bytes, 103 | decapsulate as mceliece8192128_decapsulate, encapsulate as mceliece8192128_encapsulate, 104 | keypair as mceliece8192128_keypair, public_key_bytes as mceliece8192128_public_key_bytes, 105 | secret_key_bytes as mceliece8192128_secret_key_bytes, 106 | shared_secret_bytes as mceliece8192128_shared_secret_bytes, 107 | }; 108 | pub use crate::mceliece8192128f::{ 109 | ciphertext_bytes as mceliece8192128f_ciphertext_bytes, 110 | decapsulate as mceliece8192128f_decapsulate, encapsulate as mceliece8192128f_encapsulate, 111 | keypair as mceliece8192128f_keypair, public_key_bytes as mceliece8192128f_public_key_bytes, 112 | secret_key_bytes as mceliece8192128f_secret_key_bytes, 113 | shared_secret_bytes as mceliece8192128f_shared_secret_bytes, 114 | }; 115 | -------------------------------------------------------------------------------- /pqcrypto-classicmceliece/src/mceliece348864.rs: -------------------------------------------------------------------------------- 1 | //! mceliece348864 2 | //! 3 | //! These bindings use the clean version from [PQClean][pqc] 4 | //! 5 | //! # Example 6 | //! ``` 7 | //! // if using pqcrypto-classicmceliece 8 | //! use pqcrypto_classicmceliece::mceliece348864::*; 9 | //! // or if using the pqcrypto crate: 10 | //! // use pqcrypto::kem::mceliece348864::*; 11 | //! let (pk, sk) = keypair(); 12 | //! let (ss1, ct) = encapsulate(&pk); 13 | //! let ss2 = decapsulate(&ct, &sk); 14 | //! assert!(ss1 == ss2); 15 | //! ``` 16 | //! 17 | //! [pqc]: https://github.com/pqclean/pqclean/ 18 | 19 | // This file is generated. 20 | 21 | #[cfg(feature = "serialization")] 22 | use serde::{Deserialize, Serialize}; 23 | #[cfg(feature = "serialization")] 24 | use serde_big_array::BigArray; 25 | 26 | use crate::ffi; 27 | use pqcrypto_traits::kem as primitive; 28 | use pqcrypto_traits::{Error, Result}; 29 | 30 | macro_rules! simple_struct { 31 | ($type: ident, $size: expr) => { 32 | #[derive(Clone, Copy)] 33 | #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 34 | pub struct $type( 35 | #[cfg_attr(feature = "serialization", serde(with = "BigArray"))] [u8; $size], 36 | ); 37 | 38 | impl $type { 39 | /// Generates an uninitialized object 40 | /// 41 | /// Used to pass to ``ffi`` interfaces. 42 | /// 43 | /// Internal use only! 44 | fn new() -> Self { 45 | $type([0u8; $size]) 46 | } 47 | } 48 | 49 | impl primitive::$type for $type { 50 | /// Get this object as a byte slice 51 | #[inline] 52 | fn as_bytes(&self) -> &[u8] { 53 | &self.0 54 | } 55 | 56 | /// Construct this object from a byte slice 57 | fn from_bytes(bytes: &[u8]) -> Result { 58 | if bytes.len() != $size { 59 | Err(Error::BadLength { 60 | name: stringify!($type), 61 | actual: bytes.len(), 62 | expected: $size, 63 | }) 64 | } else { 65 | let mut array = [0u8; $size]; 66 | array.copy_from_slice(bytes); 67 | Ok($type(array)) 68 | } 69 | } 70 | } 71 | 72 | impl PartialEq for $type { 73 | /// By no means constant time comparison 74 | fn eq(&self, other: &Self) -> bool { 75 | self.0 76 | .iter() 77 | .zip(other.0.iter()) 78 | .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) }) 79 | .is_ok() 80 | } 81 | } 82 | }; 83 | } 84 | 85 | simple_struct!( 86 | PublicKey, 87 | ffi::PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_PUBLICKEYBYTES 88 | ); 89 | simple_struct!( 90 | SecretKey, 91 | ffi::PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_SECRETKEYBYTES 92 | ); 93 | simple_struct!( 94 | Ciphertext, 95 | ffi::PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_CIPHERTEXTBYTES 96 | ); 97 | simple_struct!(SharedSecret, ffi::PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_BYTES); 98 | 99 | /// Get the number of bytes for a public key 100 | pub const fn public_key_bytes() -> usize { 101 | ffi::PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_PUBLICKEYBYTES 102 | } 103 | 104 | /// Get the number of bytes for a secret key 105 | pub const fn secret_key_bytes() -> usize { 106 | ffi::PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_SECRETKEYBYTES 107 | } 108 | 109 | /// Get the number of bytes for the encapsulated ciphertext 110 | pub const fn ciphertext_bytes() -> usize { 111 | ffi::PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_CIPHERTEXTBYTES 112 | } 113 | 114 | /// Get the number of bytes for the shared secret 115 | pub const fn shared_secret_bytes() -> usize { 116 | ffi::PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_BYTES 117 | } 118 | 119 | macro_rules! gen_keypair { 120 | ($variant:ident) => {{ 121 | let mut pk = PublicKey::new(); 122 | let mut sk = SecretKey::new(); 123 | assert_eq!( 124 | unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) }, 125 | 0 126 | ); 127 | (pk, sk) 128 | }}; 129 | } 130 | 131 | /// Generate a mceliece348864 keypair 132 | pub fn keypair() -> (PublicKey, SecretKey) { 133 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 134 | { 135 | if std::is_x86_feature_detected!("avx2") { 136 | return gen_keypair!(PQCLEAN_MCELIECE348864_AVX2_crypto_kem_keypair); 137 | } 138 | } 139 | gen_keypair!(PQCLEAN_MCELIECE348864_CLEAN_crypto_kem_keypair) 140 | } 141 | 142 | macro_rules! encap { 143 | ($variant:ident, $pk:ident) => {{ 144 | let mut ss = SharedSecret::new(); 145 | let mut ct = Ciphertext::new(); 146 | assert_eq!( 147 | unsafe { ffi::$variant(ct.0.as_mut_ptr(), ss.0.as_mut_ptr(), $pk.0.as_ptr()) }, 148 | 0, 149 | ); 150 | (ss, ct) 151 | }}; 152 | } 153 | 154 | /// Encapsulate to a mceliece348864 public key 155 | pub fn encapsulate(pk: &PublicKey) -> (SharedSecret, Ciphertext) { 156 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 157 | { 158 | if std::is_x86_feature_detected!("avx2") { 159 | return encap!(PQCLEAN_MCELIECE348864_AVX2_crypto_kem_enc, pk); 160 | } 161 | } 162 | encap!(PQCLEAN_MCELIECE348864_CLEAN_crypto_kem_enc, pk) 163 | } 164 | 165 | macro_rules! decap { 166 | ($variant:ident, $ct:ident, $sk:ident) => {{ 167 | let mut ss = SharedSecret::new(); 168 | assert_eq!( 169 | unsafe { ffi::$variant(ss.0.as_mut_ptr(), $ct.0.as_ptr(), $sk.0.as_ptr(),) }, 170 | 0 171 | ); 172 | ss 173 | }}; 174 | } 175 | 176 | /// Decapsulate the received mceliece348864 ciphertext 177 | pub fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> SharedSecret { 178 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 179 | { 180 | if std::is_x86_feature_detected!("avx2") { 181 | return decap!(PQCLEAN_MCELIECE348864_AVX2_crypto_kem_dec, ct, sk); 182 | } 183 | } 184 | decap!(PQCLEAN_MCELIECE348864_CLEAN_crypto_kem_dec, ct, sk) 185 | } 186 | 187 | #[cfg(test)] 188 | mod test { 189 | use super::*; 190 | 191 | #[test] 192 | pub fn test_kem() { 193 | let (pk, sk) = keypair(); 194 | let (ss1, ct) = encapsulate(&pk); 195 | let ss2 = decapsulate(&ct, &sk); 196 | assert_eq!(&ss1.0[..], &ss2.0[..], "Difference in shared secrets!"); 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /pqcrypto-classicmceliece/src/mceliece348864f.rs: -------------------------------------------------------------------------------- 1 | //! mceliece348864f 2 | //! 3 | //! These bindings use the clean version from [PQClean][pqc] 4 | //! 5 | //! # Example 6 | //! ``` 7 | //! // if using pqcrypto-classicmceliece 8 | //! use pqcrypto_classicmceliece::mceliece348864f::*; 9 | //! // or if using the pqcrypto crate: 10 | //! // use pqcrypto::kem::mceliece348864f::*; 11 | //! let (pk, sk) = keypair(); 12 | //! let (ss1, ct) = encapsulate(&pk); 13 | //! let ss2 = decapsulate(&ct, &sk); 14 | //! assert!(ss1 == ss2); 15 | //! ``` 16 | //! 17 | //! [pqc]: https://github.com/pqclean/pqclean/ 18 | 19 | // This file is generated. 20 | 21 | #[cfg(feature = "serialization")] 22 | use serde::{Deserialize, Serialize}; 23 | #[cfg(feature = "serialization")] 24 | use serde_big_array::BigArray; 25 | 26 | use crate::ffi; 27 | use pqcrypto_traits::kem as primitive; 28 | use pqcrypto_traits::{Error, Result}; 29 | 30 | macro_rules! simple_struct { 31 | ($type: ident, $size: expr) => { 32 | #[derive(Clone, Copy)] 33 | #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 34 | pub struct $type( 35 | #[cfg_attr(feature = "serialization", serde(with = "BigArray"))] [u8; $size], 36 | ); 37 | 38 | impl $type { 39 | /// Generates an uninitialized object 40 | /// 41 | /// Used to pass to ``ffi`` interfaces. 42 | /// 43 | /// Internal use only! 44 | fn new() -> Self { 45 | $type([0u8; $size]) 46 | } 47 | } 48 | 49 | impl primitive::$type for $type { 50 | /// Get this object as a byte slice 51 | #[inline] 52 | fn as_bytes(&self) -> &[u8] { 53 | &self.0 54 | } 55 | 56 | /// Construct this object from a byte slice 57 | fn from_bytes(bytes: &[u8]) -> Result { 58 | if bytes.len() != $size { 59 | Err(Error::BadLength { 60 | name: stringify!($type), 61 | actual: bytes.len(), 62 | expected: $size, 63 | }) 64 | } else { 65 | let mut array = [0u8; $size]; 66 | array.copy_from_slice(bytes); 67 | Ok($type(array)) 68 | } 69 | } 70 | } 71 | 72 | impl PartialEq for $type { 73 | /// By no means constant time comparison 74 | fn eq(&self, other: &Self) -> bool { 75 | self.0 76 | .iter() 77 | .zip(other.0.iter()) 78 | .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) }) 79 | .is_ok() 80 | } 81 | } 82 | }; 83 | } 84 | 85 | simple_struct!( 86 | PublicKey, 87 | ffi::PQCLEAN_MCELIECE348864F_CLEAN_CRYPTO_PUBLICKEYBYTES 88 | ); 89 | simple_struct!( 90 | SecretKey, 91 | ffi::PQCLEAN_MCELIECE348864F_CLEAN_CRYPTO_SECRETKEYBYTES 92 | ); 93 | simple_struct!( 94 | Ciphertext, 95 | ffi::PQCLEAN_MCELIECE348864F_CLEAN_CRYPTO_CIPHERTEXTBYTES 96 | ); 97 | simple_struct!( 98 | SharedSecret, 99 | ffi::PQCLEAN_MCELIECE348864F_CLEAN_CRYPTO_BYTES 100 | ); 101 | 102 | /// Get the number of bytes for a public key 103 | pub const fn public_key_bytes() -> usize { 104 | ffi::PQCLEAN_MCELIECE348864F_CLEAN_CRYPTO_PUBLICKEYBYTES 105 | } 106 | 107 | /// Get the number of bytes for a secret key 108 | pub const fn secret_key_bytes() -> usize { 109 | ffi::PQCLEAN_MCELIECE348864F_CLEAN_CRYPTO_SECRETKEYBYTES 110 | } 111 | 112 | /// Get the number of bytes for the encapsulated ciphertext 113 | pub const fn ciphertext_bytes() -> usize { 114 | ffi::PQCLEAN_MCELIECE348864F_CLEAN_CRYPTO_CIPHERTEXTBYTES 115 | } 116 | 117 | /// Get the number of bytes for the shared secret 118 | pub const fn shared_secret_bytes() -> usize { 119 | ffi::PQCLEAN_MCELIECE348864F_CLEAN_CRYPTO_BYTES 120 | } 121 | 122 | macro_rules! gen_keypair { 123 | ($variant:ident) => {{ 124 | let mut pk = PublicKey::new(); 125 | let mut sk = SecretKey::new(); 126 | assert_eq!( 127 | unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) }, 128 | 0 129 | ); 130 | (pk, sk) 131 | }}; 132 | } 133 | 134 | /// Generate a mceliece348864f keypair 135 | pub fn keypair() -> (PublicKey, SecretKey) { 136 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 137 | { 138 | if std::is_x86_feature_detected!("avx2") { 139 | return gen_keypair!(PQCLEAN_MCELIECE348864F_AVX2_crypto_kem_keypair); 140 | } 141 | } 142 | gen_keypair!(PQCLEAN_MCELIECE348864F_CLEAN_crypto_kem_keypair) 143 | } 144 | 145 | macro_rules! encap { 146 | ($variant:ident, $pk:ident) => {{ 147 | let mut ss = SharedSecret::new(); 148 | let mut ct = Ciphertext::new(); 149 | assert_eq!( 150 | unsafe { ffi::$variant(ct.0.as_mut_ptr(), ss.0.as_mut_ptr(), $pk.0.as_ptr()) }, 151 | 0, 152 | ); 153 | (ss, ct) 154 | }}; 155 | } 156 | 157 | /// Encapsulate to a mceliece348864f public key 158 | pub fn encapsulate(pk: &PublicKey) -> (SharedSecret, Ciphertext) { 159 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 160 | { 161 | if std::is_x86_feature_detected!("avx2") { 162 | return encap!(PQCLEAN_MCELIECE348864F_AVX2_crypto_kem_enc, pk); 163 | } 164 | } 165 | encap!(PQCLEAN_MCELIECE348864F_CLEAN_crypto_kem_enc, pk) 166 | } 167 | 168 | macro_rules! decap { 169 | ($variant:ident, $ct:ident, $sk:ident) => {{ 170 | let mut ss = SharedSecret::new(); 171 | assert_eq!( 172 | unsafe { ffi::$variant(ss.0.as_mut_ptr(), $ct.0.as_ptr(), $sk.0.as_ptr(),) }, 173 | 0 174 | ); 175 | ss 176 | }}; 177 | } 178 | 179 | /// Decapsulate the received mceliece348864f ciphertext 180 | pub fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> SharedSecret { 181 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 182 | { 183 | if std::is_x86_feature_detected!("avx2") { 184 | return decap!(PQCLEAN_MCELIECE348864F_AVX2_crypto_kem_dec, ct, sk); 185 | } 186 | } 187 | decap!(PQCLEAN_MCELIECE348864F_CLEAN_crypto_kem_dec, ct, sk) 188 | } 189 | 190 | #[cfg(test)] 191 | mod test { 192 | use super::*; 193 | 194 | #[test] 195 | pub fn test_kem() { 196 | let (pk, sk) = keypair(); 197 | let (ss1, ct) = encapsulate(&pk); 198 | let ss2 = decapsulate(&ct, &sk); 199 | assert_eq!(&ss1.0[..], &ss2.0[..], "Difference in shared secrets!"); 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /pqcrypto-classicmceliece/src/mceliece460896.rs: -------------------------------------------------------------------------------- 1 | //! mceliece460896 2 | //! 3 | //! These bindings use the clean version from [PQClean][pqc] 4 | //! 5 | //! # Example 6 | //! ``` 7 | //! // if using pqcrypto-classicmceliece 8 | //! use pqcrypto_classicmceliece::mceliece460896::*; 9 | //! // or if using the pqcrypto crate: 10 | //! // use pqcrypto::kem::mceliece460896::*; 11 | //! let (pk, sk) = keypair(); 12 | //! let (ss1, ct) = encapsulate(&pk); 13 | //! let ss2 = decapsulate(&ct, &sk); 14 | //! assert!(ss1 == ss2); 15 | //! ``` 16 | //! 17 | //! [pqc]: https://github.com/pqclean/pqclean/ 18 | 19 | // This file is generated. 20 | 21 | #[cfg(feature = "serialization")] 22 | use serde::{Deserialize, Serialize}; 23 | #[cfg(feature = "serialization")] 24 | use serde_big_array::BigArray; 25 | 26 | use crate::ffi; 27 | use pqcrypto_traits::kem as primitive; 28 | use pqcrypto_traits::{Error, Result}; 29 | 30 | macro_rules! simple_struct { 31 | ($type: ident, $size: expr) => { 32 | #[derive(Clone, Copy)] 33 | #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 34 | pub struct $type( 35 | #[cfg_attr(feature = "serialization", serde(with = "BigArray"))] [u8; $size], 36 | ); 37 | 38 | impl $type { 39 | /// Generates an uninitialized object 40 | /// 41 | /// Used to pass to ``ffi`` interfaces. 42 | /// 43 | /// Internal use only! 44 | fn new() -> Self { 45 | $type([0u8; $size]) 46 | } 47 | } 48 | 49 | impl primitive::$type for $type { 50 | /// Get this object as a byte slice 51 | #[inline] 52 | fn as_bytes(&self) -> &[u8] { 53 | &self.0 54 | } 55 | 56 | /// Construct this object from a byte slice 57 | fn from_bytes(bytes: &[u8]) -> Result { 58 | if bytes.len() != $size { 59 | Err(Error::BadLength { 60 | name: stringify!($type), 61 | actual: bytes.len(), 62 | expected: $size, 63 | }) 64 | } else { 65 | let mut array = [0u8; $size]; 66 | array.copy_from_slice(bytes); 67 | Ok($type(array)) 68 | } 69 | } 70 | } 71 | 72 | impl PartialEq for $type { 73 | /// By no means constant time comparison 74 | fn eq(&self, other: &Self) -> bool { 75 | self.0 76 | .iter() 77 | .zip(other.0.iter()) 78 | .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) }) 79 | .is_ok() 80 | } 81 | } 82 | }; 83 | } 84 | 85 | simple_struct!( 86 | PublicKey, 87 | ffi::PQCLEAN_MCELIECE460896_CLEAN_CRYPTO_PUBLICKEYBYTES 88 | ); 89 | simple_struct!( 90 | SecretKey, 91 | ffi::PQCLEAN_MCELIECE460896_CLEAN_CRYPTO_SECRETKEYBYTES 92 | ); 93 | simple_struct!( 94 | Ciphertext, 95 | ffi::PQCLEAN_MCELIECE460896_CLEAN_CRYPTO_CIPHERTEXTBYTES 96 | ); 97 | simple_struct!(SharedSecret, ffi::PQCLEAN_MCELIECE460896_CLEAN_CRYPTO_BYTES); 98 | 99 | /// Get the number of bytes for a public key 100 | pub const fn public_key_bytes() -> usize { 101 | ffi::PQCLEAN_MCELIECE460896_CLEAN_CRYPTO_PUBLICKEYBYTES 102 | } 103 | 104 | /// Get the number of bytes for a secret key 105 | pub const fn secret_key_bytes() -> usize { 106 | ffi::PQCLEAN_MCELIECE460896_CLEAN_CRYPTO_SECRETKEYBYTES 107 | } 108 | 109 | /// Get the number of bytes for the encapsulated ciphertext 110 | pub const fn ciphertext_bytes() -> usize { 111 | ffi::PQCLEAN_MCELIECE460896_CLEAN_CRYPTO_CIPHERTEXTBYTES 112 | } 113 | 114 | /// Get the number of bytes for the shared secret 115 | pub const fn shared_secret_bytes() -> usize { 116 | ffi::PQCLEAN_MCELIECE460896_CLEAN_CRYPTO_BYTES 117 | } 118 | 119 | macro_rules! gen_keypair { 120 | ($variant:ident) => {{ 121 | let mut pk = PublicKey::new(); 122 | let mut sk = SecretKey::new(); 123 | assert_eq!( 124 | unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) }, 125 | 0 126 | ); 127 | (pk, sk) 128 | }}; 129 | } 130 | 131 | /// Generate a mceliece460896 keypair 132 | pub fn keypair() -> (PublicKey, SecretKey) { 133 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 134 | { 135 | if std::is_x86_feature_detected!("avx2") { 136 | return gen_keypair!(PQCLEAN_MCELIECE460896_AVX2_crypto_kem_keypair); 137 | } 138 | } 139 | gen_keypair!(PQCLEAN_MCELIECE460896_CLEAN_crypto_kem_keypair) 140 | } 141 | 142 | macro_rules! encap { 143 | ($variant:ident, $pk:ident) => {{ 144 | let mut ss = SharedSecret::new(); 145 | let mut ct = Ciphertext::new(); 146 | assert_eq!( 147 | unsafe { ffi::$variant(ct.0.as_mut_ptr(), ss.0.as_mut_ptr(), $pk.0.as_ptr()) }, 148 | 0, 149 | ); 150 | (ss, ct) 151 | }}; 152 | } 153 | 154 | /// Encapsulate to a mceliece460896 public key 155 | pub fn encapsulate(pk: &PublicKey) -> (SharedSecret, Ciphertext) { 156 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 157 | { 158 | if std::is_x86_feature_detected!("avx2") { 159 | return encap!(PQCLEAN_MCELIECE460896_AVX2_crypto_kem_enc, pk); 160 | } 161 | } 162 | encap!(PQCLEAN_MCELIECE460896_CLEAN_crypto_kem_enc, pk) 163 | } 164 | 165 | macro_rules! decap { 166 | ($variant:ident, $ct:ident, $sk:ident) => {{ 167 | let mut ss = SharedSecret::new(); 168 | assert_eq!( 169 | unsafe { ffi::$variant(ss.0.as_mut_ptr(), $ct.0.as_ptr(), $sk.0.as_ptr(),) }, 170 | 0 171 | ); 172 | ss 173 | }}; 174 | } 175 | 176 | /// Decapsulate the received mceliece460896 ciphertext 177 | pub fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> SharedSecret { 178 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 179 | { 180 | if std::is_x86_feature_detected!("avx2") { 181 | return decap!(PQCLEAN_MCELIECE460896_AVX2_crypto_kem_dec, ct, sk); 182 | } 183 | } 184 | decap!(PQCLEAN_MCELIECE460896_CLEAN_crypto_kem_dec, ct, sk) 185 | } 186 | 187 | #[cfg(test)] 188 | mod test { 189 | use super::*; 190 | 191 | #[test] 192 | pub fn test_kem() { 193 | let (pk, sk) = keypair(); 194 | let (ss1, ct) = encapsulate(&pk); 195 | let ss2 = decapsulate(&ct, &sk); 196 | assert_eq!(&ss1.0[..], &ss2.0[..], "Difference in shared secrets!"); 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /pqcrypto-classicmceliece/src/mceliece460896f.rs: -------------------------------------------------------------------------------- 1 | //! mceliece460896f 2 | //! 3 | //! These bindings use the clean version from [PQClean][pqc] 4 | //! 5 | //! # Example 6 | //! ``` 7 | //! // if using pqcrypto-classicmceliece 8 | //! use pqcrypto_classicmceliece::mceliece460896f::*; 9 | //! // or if using the pqcrypto crate: 10 | //! // use pqcrypto::kem::mceliece460896f::*; 11 | //! let (pk, sk) = keypair(); 12 | //! let (ss1, ct) = encapsulate(&pk); 13 | //! let ss2 = decapsulate(&ct, &sk); 14 | //! assert!(ss1 == ss2); 15 | //! ``` 16 | //! 17 | //! [pqc]: https://github.com/pqclean/pqclean/ 18 | 19 | // This file is generated. 20 | 21 | #[cfg(feature = "serialization")] 22 | use serde::{Deserialize, Serialize}; 23 | #[cfg(feature = "serialization")] 24 | use serde_big_array::BigArray; 25 | 26 | use crate::ffi; 27 | use pqcrypto_traits::kem as primitive; 28 | use pqcrypto_traits::{Error, Result}; 29 | 30 | macro_rules! simple_struct { 31 | ($type: ident, $size: expr) => { 32 | #[derive(Clone, Copy)] 33 | #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 34 | pub struct $type( 35 | #[cfg_attr(feature = "serialization", serde(with = "BigArray"))] [u8; $size], 36 | ); 37 | 38 | impl $type { 39 | /// Generates an uninitialized object 40 | /// 41 | /// Used to pass to ``ffi`` interfaces. 42 | /// 43 | /// Internal use only! 44 | fn new() -> Self { 45 | $type([0u8; $size]) 46 | } 47 | } 48 | 49 | impl primitive::$type for $type { 50 | /// Get this object as a byte slice 51 | #[inline] 52 | fn as_bytes(&self) -> &[u8] { 53 | &self.0 54 | } 55 | 56 | /// Construct this object from a byte slice 57 | fn from_bytes(bytes: &[u8]) -> Result { 58 | if bytes.len() != $size { 59 | Err(Error::BadLength { 60 | name: stringify!($type), 61 | actual: bytes.len(), 62 | expected: $size, 63 | }) 64 | } else { 65 | let mut array = [0u8; $size]; 66 | array.copy_from_slice(bytes); 67 | Ok($type(array)) 68 | } 69 | } 70 | } 71 | 72 | impl PartialEq for $type { 73 | /// By no means constant time comparison 74 | fn eq(&self, other: &Self) -> bool { 75 | self.0 76 | .iter() 77 | .zip(other.0.iter()) 78 | .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) }) 79 | .is_ok() 80 | } 81 | } 82 | }; 83 | } 84 | 85 | simple_struct!( 86 | PublicKey, 87 | ffi::PQCLEAN_MCELIECE460896F_CLEAN_CRYPTO_PUBLICKEYBYTES 88 | ); 89 | simple_struct!( 90 | SecretKey, 91 | ffi::PQCLEAN_MCELIECE460896F_CLEAN_CRYPTO_SECRETKEYBYTES 92 | ); 93 | simple_struct!( 94 | Ciphertext, 95 | ffi::PQCLEAN_MCELIECE460896F_CLEAN_CRYPTO_CIPHERTEXTBYTES 96 | ); 97 | simple_struct!( 98 | SharedSecret, 99 | ffi::PQCLEAN_MCELIECE460896F_CLEAN_CRYPTO_BYTES 100 | ); 101 | 102 | /// Get the number of bytes for a public key 103 | pub const fn public_key_bytes() -> usize { 104 | ffi::PQCLEAN_MCELIECE460896F_CLEAN_CRYPTO_PUBLICKEYBYTES 105 | } 106 | 107 | /// Get the number of bytes for a secret key 108 | pub const fn secret_key_bytes() -> usize { 109 | ffi::PQCLEAN_MCELIECE460896F_CLEAN_CRYPTO_SECRETKEYBYTES 110 | } 111 | 112 | /// Get the number of bytes for the encapsulated ciphertext 113 | pub const fn ciphertext_bytes() -> usize { 114 | ffi::PQCLEAN_MCELIECE460896F_CLEAN_CRYPTO_CIPHERTEXTBYTES 115 | } 116 | 117 | /// Get the number of bytes for the shared secret 118 | pub const fn shared_secret_bytes() -> usize { 119 | ffi::PQCLEAN_MCELIECE460896F_CLEAN_CRYPTO_BYTES 120 | } 121 | 122 | macro_rules! gen_keypair { 123 | ($variant:ident) => {{ 124 | let mut pk = PublicKey::new(); 125 | let mut sk = SecretKey::new(); 126 | assert_eq!( 127 | unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) }, 128 | 0 129 | ); 130 | (pk, sk) 131 | }}; 132 | } 133 | 134 | /// Generate a mceliece460896f keypair 135 | pub fn keypair() -> (PublicKey, SecretKey) { 136 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 137 | { 138 | if std::is_x86_feature_detected!("avx2") { 139 | return gen_keypair!(PQCLEAN_MCELIECE460896F_AVX2_crypto_kem_keypair); 140 | } 141 | } 142 | gen_keypair!(PQCLEAN_MCELIECE460896F_CLEAN_crypto_kem_keypair) 143 | } 144 | 145 | macro_rules! encap { 146 | ($variant:ident, $pk:ident) => {{ 147 | let mut ss = SharedSecret::new(); 148 | let mut ct = Ciphertext::new(); 149 | assert_eq!( 150 | unsafe { ffi::$variant(ct.0.as_mut_ptr(), ss.0.as_mut_ptr(), $pk.0.as_ptr()) }, 151 | 0, 152 | ); 153 | (ss, ct) 154 | }}; 155 | } 156 | 157 | /// Encapsulate to a mceliece460896f public key 158 | pub fn encapsulate(pk: &PublicKey) -> (SharedSecret, Ciphertext) { 159 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 160 | { 161 | if std::is_x86_feature_detected!("avx2") { 162 | return encap!(PQCLEAN_MCELIECE460896F_AVX2_crypto_kem_enc, pk); 163 | } 164 | } 165 | encap!(PQCLEAN_MCELIECE460896F_CLEAN_crypto_kem_enc, pk) 166 | } 167 | 168 | macro_rules! decap { 169 | ($variant:ident, $ct:ident, $sk:ident) => {{ 170 | let mut ss = SharedSecret::new(); 171 | assert_eq!( 172 | unsafe { ffi::$variant(ss.0.as_mut_ptr(), $ct.0.as_ptr(), $sk.0.as_ptr(),) }, 173 | 0 174 | ); 175 | ss 176 | }}; 177 | } 178 | 179 | /// Decapsulate the received mceliece460896f ciphertext 180 | pub fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> SharedSecret { 181 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 182 | { 183 | if std::is_x86_feature_detected!("avx2") { 184 | return decap!(PQCLEAN_MCELIECE460896F_AVX2_crypto_kem_dec, ct, sk); 185 | } 186 | } 187 | decap!(PQCLEAN_MCELIECE460896F_CLEAN_crypto_kem_dec, ct, sk) 188 | } 189 | 190 | #[cfg(test)] 191 | mod test { 192 | use super::*; 193 | 194 | #[test] 195 | pub fn test_kem() { 196 | let (pk, sk) = keypair(); 197 | let (ss1, ct) = encapsulate(&pk); 198 | let ss2 = decapsulate(&ct, &sk); 199 | assert_eq!(&ss1.0[..], &ss2.0[..], "Difference in shared secrets!"); 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /pqcrypto-classicmceliece/src/mceliece6688128.rs: -------------------------------------------------------------------------------- 1 | //! mceliece6688128 2 | //! 3 | //! These bindings use the clean version from [PQClean][pqc] 4 | //! 5 | //! # Example 6 | //! ```no_run 7 | //! // if using pqcrypto-classicmceliece 8 | //! use pqcrypto_classicmceliece::mceliece6688128::*; 9 | //! // or if using the pqcrypto crate: 10 | //! // use pqcrypto::kem::mceliece6688128::*; 11 | //! let (pk, sk) = keypair(); 12 | //! let (ss1, ct) = encapsulate(&pk); 13 | //! let ss2 = decapsulate(&ct, &sk); 14 | //! assert!(ss1 == ss2); 15 | //! ``` 16 | //! 17 | //! [pqc]: https://github.com/pqclean/pqclean/ 18 | 19 | // This file is generated. 20 | 21 | #[cfg(feature = "serialization")] 22 | use serde::{Deserialize, Serialize}; 23 | #[cfg(feature = "serialization")] 24 | use serde_big_array::BigArray; 25 | 26 | use crate::ffi; 27 | use pqcrypto_traits::kem as primitive; 28 | use pqcrypto_traits::{Error, Result}; 29 | 30 | macro_rules! simple_struct { 31 | ($type: ident, $size: expr) => { 32 | #[derive(Clone, Copy)] 33 | #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 34 | pub struct $type( 35 | #[cfg_attr(feature = "serialization", serde(with = "BigArray"))] [u8; $size], 36 | ); 37 | 38 | impl $type { 39 | /// Generates an uninitialized object 40 | /// 41 | /// Used to pass to ``ffi`` interfaces. 42 | /// 43 | /// Internal use only! 44 | fn new() -> Self { 45 | $type([0u8; $size]) 46 | } 47 | } 48 | 49 | impl primitive::$type for $type { 50 | /// Get this object as a byte slice 51 | #[inline] 52 | fn as_bytes(&self) -> &[u8] { 53 | &self.0 54 | } 55 | 56 | /// Construct this object from a byte slice 57 | fn from_bytes(bytes: &[u8]) -> Result { 58 | if bytes.len() != $size { 59 | Err(Error::BadLength { 60 | name: stringify!($type), 61 | actual: bytes.len(), 62 | expected: $size, 63 | }) 64 | } else { 65 | let mut array = [0u8; $size]; 66 | array.copy_from_slice(bytes); 67 | Ok($type(array)) 68 | } 69 | } 70 | } 71 | 72 | impl PartialEq for $type { 73 | /// By no means constant time comparison 74 | fn eq(&self, other: &Self) -> bool { 75 | self.0 76 | .iter() 77 | .zip(other.0.iter()) 78 | .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) }) 79 | .is_ok() 80 | } 81 | } 82 | }; 83 | } 84 | 85 | simple_struct!( 86 | PublicKey, 87 | ffi::PQCLEAN_MCELIECE6688128_CLEAN_CRYPTO_PUBLICKEYBYTES 88 | ); 89 | simple_struct!( 90 | SecretKey, 91 | ffi::PQCLEAN_MCELIECE6688128_CLEAN_CRYPTO_SECRETKEYBYTES 92 | ); 93 | simple_struct!( 94 | Ciphertext, 95 | ffi::PQCLEAN_MCELIECE6688128_CLEAN_CRYPTO_CIPHERTEXTBYTES 96 | ); 97 | simple_struct!( 98 | SharedSecret, 99 | ffi::PQCLEAN_MCELIECE6688128_CLEAN_CRYPTO_BYTES 100 | ); 101 | 102 | /// Get the number of bytes for a public key 103 | pub const fn public_key_bytes() -> usize { 104 | ffi::PQCLEAN_MCELIECE6688128_CLEAN_CRYPTO_PUBLICKEYBYTES 105 | } 106 | 107 | /// Get the number of bytes for a secret key 108 | pub const fn secret_key_bytes() -> usize { 109 | ffi::PQCLEAN_MCELIECE6688128_CLEAN_CRYPTO_SECRETKEYBYTES 110 | } 111 | 112 | /// Get the number of bytes for the encapsulated ciphertext 113 | pub const fn ciphertext_bytes() -> usize { 114 | ffi::PQCLEAN_MCELIECE6688128_CLEAN_CRYPTO_CIPHERTEXTBYTES 115 | } 116 | 117 | /// Get the number of bytes for the shared secret 118 | pub const fn shared_secret_bytes() -> usize { 119 | ffi::PQCLEAN_MCELIECE6688128_CLEAN_CRYPTO_BYTES 120 | } 121 | 122 | macro_rules! gen_keypair { 123 | ($variant:ident) => {{ 124 | let mut pk = PublicKey::new(); 125 | let mut sk = SecretKey::new(); 126 | assert_eq!( 127 | unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) }, 128 | 0 129 | ); 130 | (pk, sk) 131 | }}; 132 | } 133 | 134 | /// Generate a mceliece6688128 keypair 135 | pub fn keypair() -> (PublicKey, SecretKey) { 136 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 137 | { 138 | if std::is_x86_feature_detected!("avx2") { 139 | return gen_keypair!(PQCLEAN_MCELIECE6688128_AVX2_crypto_kem_keypair); 140 | } 141 | } 142 | gen_keypair!(PQCLEAN_MCELIECE6688128_CLEAN_crypto_kem_keypair) 143 | } 144 | 145 | macro_rules! encap { 146 | ($variant:ident, $pk:ident) => {{ 147 | let mut ss = SharedSecret::new(); 148 | let mut ct = Ciphertext::new(); 149 | assert_eq!( 150 | unsafe { ffi::$variant(ct.0.as_mut_ptr(), ss.0.as_mut_ptr(), $pk.0.as_ptr()) }, 151 | 0, 152 | ); 153 | (ss, ct) 154 | }}; 155 | } 156 | 157 | /// Encapsulate to a mceliece6688128 public key 158 | pub fn encapsulate(pk: &PublicKey) -> (SharedSecret, Ciphertext) { 159 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 160 | { 161 | if std::is_x86_feature_detected!("avx2") { 162 | return encap!(PQCLEAN_MCELIECE6688128_AVX2_crypto_kem_enc, pk); 163 | } 164 | } 165 | encap!(PQCLEAN_MCELIECE6688128_CLEAN_crypto_kem_enc, pk) 166 | } 167 | 168 | macro_rules! decap { 169 | ($variant:ident, $ct:ident, $sk:ident) => {{ 170 | let mut ss = SharedSecret::new(); 171 | assert_eq!( 172 | unsafe { ffi::$variant(ss.0.as_mut_ptr(), $ct.0.as_ptr(), $sk.0.as_ptr(),) }, 173 | 0 174 | ); 175 | ss 176 | }}; 177 | } 178 | 179 | /// Decapsulate the received mceliece6688128 ciphertext 180 | pub fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> SharedSecret { 181 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 182 | { 183 | if std::is_x86_feature_detected!("avx2") { 184 | return decap!(PQCLEAN_MCELIECE6688128_AVX2_crypto_kem_dec, ct, sk); 185 | } 186 | } 187 | decap!(PQCLEAN_MCELIECE6688128_CLEAN_crypto_kem_dec, ct, sk) 188 | } 189 | 190 | #[cfg(test)] 191 | mod test { 192 | use super::*; 193 | 194 | #[test] 195 | pub fn test_kem() { 196 | let (pk, sk) = keypair(); 197 | let (ss1, ct) = encapsulate(&pk); 198 | let ss2 = decapsulate(&ct, &sk); 199 | assert_eq!(&ss1.0[..], &ss2.0[..], "Difference in shared secrets!"); 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /pqcrypto-classicmceliece/src/mceliece6960119.rs: -------------------------------------------------------------------------------- 1 | //! mceliece6960119 2 | //! 3 | //! These bindings use the clean version from [PQClean][pqc] 4 | //! 5 | //! # Example 6 | //! ```no_run 7 | //! // if using pqcrypto-classicmceliece 8 | //! use pqcrypto_classicmceliece::mceliece6960119::*; 9 | //! // or if using the pqcrypto crate: 10 | //! // use pqcrypto::kem::mceliece6960119::*; 11 | //! let (pk, sk) = keypair(); 12 | //! let (ss1, ct) = encapsulate(&pk); 13 | //! let ss2 = decapsulate(&ct, &sk); 14 | //! assert!(ss1 == ss2); 15 | //! ``` 16 | //! 17 | //! [pqc]: https://github.com/pqclean/pqclean/ 18 | 19 | // This file is generated. 20 | 21 | #[cfg(feature = "serialization")] 22 | use serde::{Deserialize, Serialize}; 23 | #[cfg(feature = "serialization")] 24 | use serde_big_array::BigArray; 25 | 26 | use crate::ffi; 27 | use pqcrypto_traits::kem as primitive; 28 | use pqcrypto_traits::{Error, Result}; 29 | 30 | macro_rules! simple_struct { 31 | ($type: ident, $size: expr) => { 32 | #[derive(Clone, Copy)] 33 | #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 34 | pub struct $type( 35 | #[cfg_attr(feature = "serialization", serde(with = "BigArray"))] [u8; $size], 36 | ); 37 | 38 | impl $type { 39 | /// Generates an uninitialized object 40 | /// 41 | /// Used to pass to ``ffi`` interfaces. 42 | /// 43 | /// Internal use only! 44 | fn new() -> Self { 45 | $type([0u8; $size]) 46 | } 47 | } 48 | 49 | impl primitive::$type for $type { 50 | /// Get this object as a byte slice 51 | #[inline] 52 | fn as_bytes(&self) -> &[u8] { 53 | &self.0 54 | } 55 | 56 | /// Construct this object from a byte slice 57 | fn from_bytes(bytes: &[u8]) -> Result { 58 | if bytes.len() != $size { 59 | Err(Error::BadLength { 60 | name: stringify!($type), 61 | actual: bytes.len(), 62 | expected: $size, 63 | }) 64 | } else { 65 | let mut array = [0u8; $size]; 66 | array.copy_from_slice(bytes); 67 | Ok($type(array)) 68 | } 69 | } 70 | } 71 | 72 | impl PartialEq for $type { 73 | /// By no means constant time comparison 74 | fn eq(&self, other: &Self) -> bool { 75 | self.0 76 | .iter() 77 | .zip(other.0.iter()) 78 | .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) }) 79 | .is_ok() 80 | } 81 | } 82 | }; 83 | } 84 | 85 | simple_struct!( 86 | PublicKey, 87 | ffi::PQCLEAN_MCELIECE6960119_CLEAN_CRYPTO_PUBLICKEYBYTES 88 | ); 89 | simple_struct!( 90 | SecretKey, 91 | ffi::PQCLEAN_MCELIECE6960119_CLEAN_CRYPTO_SECRETKEYBYTES 92 | ); 93 | simple_struct!( 94 | Ciphertext, 95 | ffi::PQCLEAN_MCELIECE6960119_CLEAN_CRYPTO_CIPHERTEXTBYTES 96 | ); 97 | simple_struct!( 98 | SharedSecret, 99 | ffi::PQCLEAN_MCELIECE6960119_CLEAN_CRYPTO_BYTES 100 | ); 101 | 102 | /// Get the number of bytes for a public key 103 | pub const fn public_key_bytes() -> usize { 104 | ffi::PQCLEAN_MCELIECE6960119_CLEAN_CRYPTO_PUBLICKEYBYTES 105 | } 106 | 107 | /// Get the number of bytes for a secret key 108 | pub const fn secret_key_bytes() -> usize { 109 | ffi::PQCLEAN_MCELIECE6960119_CLEAN_CRYPTO_SECRETKEYBYTES 110 | } 111 | 112 | /// Get the number of bytes for the encapsulated ciphertext 113 | pub const fn ciphertext_bytes() -> usize { 114 | ffi::PQCLEAN_MCELIECE6960119_CLEAN_CRYPTO_CIPHERTEXTBYTES 115 | } 116 | 117 | /// Get the number of bytes for the shared secret 118 | pub const fn shared_secret_bytes() -> usize { 119 | ffi::PQCLEAN_MCELIECE6960119_CLEAN_CRYPTO_BYTES 120 | } 121 | 122 | macro_rules! gen_keypair { 123 | ($variant:ident) => {{ 124 | let mut pk = PublicKey::new(); 125 | let mut sk = SecretKey::new(); 126 | assert_eq!( 127 | unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) }, 128 | 0 129 | ); 130 | (pk, sk) 131 | }}; 132 | } 133 | 134 | /// Generate a mceliece6960119 keypair 135 | pub fn keypair() -> (PublicKey, SecretKey) { 136 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 137 | { 138 | if std::is_x86_feature_detected!("avx2") { 139 | return gen_keypair!(PQCLEAN_MCELIECE6960119_AVX2_crypto_kem_keypair); 140 | } 141 | } 142 | gen_keypair!(PQCLEAN_MCELIECE6960119_CLEAN_crypto_kem_keypair) 143 | } 144 | 145 | macro_rules! encap { 146 | ($variant:ident, $pk:ident) => {{ 147 | let mut ss = SharedSecret::new(); 148 | let mut ct = Ciphertext::new(); 149 | assert_eq!( 150 | unsafe { ffi::$variant(ct.0.as_mut_ptr(), ss.0.as_mut_ptr(), $pk.0.as_ptr()) }, 151 | 0, 152 | ); 153 | (ss, ct) 154 | }}; 155 | } 156 | 157 | /// Encapsulate to a mceliece6960119 public key 158 | pub fn encapsulate(pk: &PublicKey) -> (SharedSecret, Ciphertext) { 159 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 160 | { 161 | if std::is_x86_feature_detected!("avx2") { 162 | return encap!(PQCLEAN_MCELIECE6960119_AVX2_crypto_kem_enc, pk); 163 | } 164 | } 165 | encap!(PQCLEAN_MCELIECE6960119_CLEAN_crypto_kem_enc, pk) 166 | } 167 | 168 | macro_rules! decap { 169 | ($variant:ident, $ct:ident, $sk:ident) => {{ 170 | let mut ss = SharedSecret::new(); 171 | assert_eq!( 172 | unsafe { ffi::$variant(ss.0.as_mut_ptr(), $ct.0.as_ptr(), $sk.0.as_ptr(),) }, 173 | 0 174 | ); 175 | ss 176 | }}; 177 | } 178 | 179 | /// Decapsulate the received mceliece6960119 ciphertext 180 | pub fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> SharedSecret { 181 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 182 | { 183 | if std::is_x86_feature_detected!("avx2") { 184 | return decap!(PQCLEAN_MCELIECE6960119_AVX2_crypto_kem_dec, ct, sk); 185 | } 186 | } 187 | decap!(PQCLEAN_MCELIECE6960119_CLEAN_crypto_kem_dec, ct, sk) 188 | } 189 | 190 | #[cfg(test)] 191 | mod test { 192 | use super::*; 193 | 194 | #[test] 195 | pub fn test_kem() { 196 | let (pk, sk) = keypair(); 197 | let (ss1, ct) = encapsulate(&pk); 198 | let ss2 = decapsulate(&ct, &sk); 199 | assert_eq!(&ss1.0[..], &ss2.0[..], "Difference in shared secrets!"); 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /pqcrypto-classicmceliece/src/mceliece8192128.rs: -------------------------------------------------------------------------------- 1 | //! mceliece8192128 2 | //! 3 | //! These bindings use the clean version from [PQClean][pqc] 4 | //! 5 | //! # Example 6 | //! ```no_run 7 | //! // if using pqcrypto-classicmceliece 8 | //! use pqcrypto_classicmceliece::mceliece8192128::*; 9 | //! // or if using the pqcrypto crate: 10 | //! // use pqcrypto::kem::mceliece8192128::*; 11 | //! let (pk, sk) = keypair(); 12 | //! let (ss1, ct) = encapsulate(&pk); 13 | //! let ss2 = decapsulate(&ct, &sk); 14 | //! assert!(ss1 == ss2); 15 | //! ``` 16 | //! 17 | //! [pqc]: https://github.com/pqclean/pqclean/ 18 | 19 | // This file is generated. 20 | 21 | #[cfg(feature = "serialization")] 22 | use serde::{Deserialize, Serialize}; 23 | #[cfg(feature = "serialization")] 24 | use serde_big_array::BigArray; 25 | 26 | use crate::ffi; 27 | use pqcrypto_traits::kem as primitive; 28 | use pqcrypto_traits::{Error, Result}; 29 | 30 | macro_rules! simple_struct { 31 | ($type: ident, $size: expr) => { 32 | #[derive(Clone, Copy)] 33 | #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 34 | pub struct $type( 35 | #[cfg_attr(feature = "serialization", serde(with = "BigArray"))] [u8; $size], 36 | ); 37 | 38 | impl $type { 39 | /// Generates an uninitialized object 40 | /// 41 | /// Used to pass to ``ffi`` interfaces. 42 | /// 43 | /// Internal use only! 44 | fn new() -> Self { 45 | $type([0u8; $size]) 46 | } 47 | } 48 | 49 | impl primitive::$type for $type { 50 | /// Get this object as a byte slice 51 | #[inline] 52 | fn as_bytes(&self) -> &[u8] { 53 | &self.0 54 | } 55 | 56 | /// Construct this object from a byte slice 57 | fn from_bytes(bytes: &[u8]) -> Result { 58 | if bytes.len() != $size { 59 | Err(Error::BadLength { 60 | name: stringify!($type), 61 | actual: bytes.len(), 62 | expected: $size, 63 | }) 64 | } else { 65 | let mut array = [0u8; $size]; 66 | array.copy_from_slice(bytes); 67 | Ok($type(array)) 68 | } 69 | } 70 | } 71 | 72 | impl PartialEq for $type { 73 | /// By no means constant time comparison 74 | fn eq(&self, other: &Self) -> bool { 75 | self.0 76 | .iter() 77 | .zip(other.0.iter()) 78 | .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) }) 79 | .is_ok() 80 | } 81 | } 82 | }; 83 | } 84 | 85 | simple_struct!( 86 | PublicKey, 87 | ffi::PQCLEAN_MCELIECE8192128_CLEAN_CRYPTO_PUBLICKEYBYTES 88 | ); 89 | simple_struct!( 90 | SecretKey, 91 | ffi::PQCLEAN_MCELIECE8192128_CLEAN_CRYPTO_SECRETKEYBYTES 92 | ); 93 | simple_struct!( 94 | Ciphertext, 95 | ffi::PQCLEAN_MCELIECE8192128_CLEAN_CRYPTO_CIPHERTEXTBYTES 96 | ); 97 | simple_struct!( 98 | SharedSecret, 99 | ffi::PQCLEAN_MCELIECE8192128_CLEAN_CRYPTO_BYTES 100 | ); 101 | 102 | /// Get the number of bytes for a public key 103 | pub const fn public_key_bytes() -> usize { 104 | ffi::PQCLEAN_MCELIECE8192128_CLEAN_CRYPTO_PUBLICKEYBYTES 105 | } 106 | 107 | /// Get the number of bytes for a secret key 108 | pub const fn secret_key_bytes() -> usize { 109 | ffi::PQCLEAN_MCELIECE8192128_CLEAN_CRYPTO_SECRETKEYBYTES 110 | } 111 | 112 | /// Get the number of bytes for the encapsulated ciphertext 113 | pub const fn ciphertext_bytes() -> usize { 114 | ffi::PQCLEAN_MCELIECE8192128_CLEAN_CRYPTO_CIPHERTEXTBYTES 115 | } 116 | 117 | /// Get the number of bytes for the shared secret 118 | pub const fn shared_secret_bytes() -> usize { 119 | ffi::PQCLEAN_MCELIECE8192128_CLEAN_CRYPTO_BYTES 120 | } 121 | 122 | macro_rules! gen_keypair { 123 | ($variant:ident) => {{ 124 | let mut pk = PublicKey::new(); 125 | let mut sk = SecretKey::new(); 126 | assert_eq!( 127 | unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) }, 128 | 0 129 | ); 130 | (pk, sk) 131 | }}; 132 | } 133 | 134 | /// Generate a mceliece8192128 keypair 135 | pub fn keypair() -> (PublicKey, SecretKey) { 136 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 137 | { 138 | if std::is_x86_feature_detected!("avx2") { 139 | return gen_keypair!(PQCLEAN_MCELIECE8192128_AVX2_crypto_kem_keypair); 140 | } 141 | } 142 | gen_keypair!(PQCLEAN_MCELIECE8192128_CLEAN_crypto_kem_keypair) 143 | } 144 | 145 | macro_rules! encap { 146 | ($variant:ident, $pk:ident) => {{ 147 | let mut ss = SharedSecret::new(); 148 | let mut ct = Ciphertext::new(); 149 | assert_eq!( 150 | unsafe { ffi::$variant(ct.0.as_mut_ptr(), ss.0.as_mut_ptr(), $pk.0.as_ptr()) }, 151 | 0, 152 | ); 153 | (ss, ct) 154 | }}; 155 | } 156 | 157 | /// Encapsulate to a mceliece8192128 public key 158 | pub fn encapsulate(pk: &PublicKey) -> (SharedSecret, Ciphertext) { 159 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 160 | { 161 | if std::is_x86_feature_detected!("avx2") { 162 | return encap!(PQCLEAN_MCELIECE8192128_AVX2_crypto_kem_enc, pk); 163 | } 164 | } 165 | encap!(PQCLEAN_MCELIECE8192128_CLEAN_crypto_kem_enc, pk) 166 | } 167 | 168 | macro_rules! decap { 169 | ($variant:ident, $ct:ident, $sk:ident) => {{ 170 | let mut ss = SharedSecret::new(); 171 | assert_eq!( 172 | unsafe { ffi::$variant(ss.0.as_mut_ptr(), $ct.0.as_ptr(), $sk.0.as_ptr(),) }, 173 | 0 174 | ); 175 | ss 176 | }}; 177 | } 178 | 179 | /// Decapsulate the received mceliece8192128 ciphertext 180 | pub fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> SharedSecret { 181 | #[cfg(all(enable_x86_avx2, feature = "avx2"))] 182 | { 183 | if std::is_x86_feature_detected!("avx2") { 184 | return decap!(PQCLEAN_MCELIECE8192128_AVX2_crypto_kem_dec, ct, sk); 185 | } 186 | } 187 | decap!(PQCLEAN_MCELIECE8192128_CLEAN_crypto_kem_dec, ct, sk) 188 | } 189 | 190 | #[cfg(test)] 191 | mod test { 192 | use super::*; 193 | 194 | #[test] 195 | pub fn test_kem() { 196 | let (pk, sk) = keypair(); 197 | let (ss1, ct) = encapsulate(&pk); 198 | let ss2 = decapsulate(&ct, &sk); 199 | assert_eq!(&ss1.0[..], &ss2.0[..], "Difference in shared secrets!"); 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /pqcrypto-falcon/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pqcrypto-falcon" 3 | description = "Post-Quantum Signature Scheme falcon" 4 | readme = "README.md" 5 | version = "0.4.0" 6 | authors = ["Thom Wiggers "] 7 | edition = "2021" 8 | license = "MIT OR Apache-2.0" 9 | homepage = "https://github.com/rustpq/" 10 | repository = "https://github.com/rustpq/pqcrypto/" 11 | keywords = ["cryptography", "post-quantum", "security"] 12 | categories = ["cryptography", "no-std"] 13 | 14 | [dependencies] 15 | pqcrypto-internals = { path = "../pqcrypto-internals", version = "0.2.6" } 16 | pqcrypto-traits = { path = "../pqcrypto-traits", version = "0.3.5", default-features = false } 17 | libc = "0.2.0" 18 | serde = { version = "1.0", features = ["derive"], optional = true } 19 | serde-big-array = { version = "0.5.1", optional = true } 20 | 21 | [features] 22 | default = ["avx2", "neon", "std"] 23 | avx2 = ["std"] 24 | neon = ["std"] 25 | std = ["pqcrypto-traits/std"] 26 | serialization = ["serde", "serde-big-array"] 27 | 28 | [dev-dependencies] 29 | rand = "0.8.5" 30 | 31 | [build-dependencies] 32 | cc = { version = "1.0", features = ["parallel"] } 33 | glob = "0.3.0" 34 | 35 | [badges] 36 | travis-ci = { repository = "rustpq/pqcrypto", branch = "master" } 37 | maintenance = { status = "actively-developed" } 38 | 39 | -------------------------------------------------------------------------------- /pqcrypto-falcon/README.md: -------------------------------------------------------------------------------- 1 | # falcon 2 | 3 | 4 | This crate contains bindings to the C implementations of the following schemes, 5 | from [PQClean][pqclean]. 6 | 7 | This project packages Post-Quantum cryptographic algorithms that participate in 8 | the [NIST PQC standardization effort][nistpqc]. It is currently a collection of 9 | wrappers around C implementations from the [PQClean][pqclean] project. 10 | 11 | ## Serialization 12 | 13 | If you want `serde` support, enable the `serialization` feature. 14 | 15 | ## Included implementations from PQClean 16 | 17 | Below is a list of the included schemes and the corresponding implementations 18 | sourced from [PQClean][pqclean]. The "default" implementation is used in the 19 | Rust-friendly interface, alternative implementations are exposed as ``ffi`` 20 | methods only. 21 | 22 | * ``falcon-512`` 23 | * ``clean`` 24 | * ``avx2`` (if supported) 25 | * ``aarch64`` (if supported) 26 | * ``falcon-padded-512`` 27 | * ``clean`` 28 | * ``avx2`` (if supported) 29 | * ``aarch64`` (if supported) 30 | * ``falcon-1024`` 31 | * ``clean`` 32 | * ``avx2`` (if supported) 33 | * ``aarch64`` (if supported) 34 | * ``falcon-padded-1024`` 35 | * ``clean`` 36 | * ``avx2`` (if supported) 37 | * ``aarch64`` (if supported) 38 | 39 | 40 | ## License 41 | 42 | The wrappers and wrapper generation scripts in this project are covered by the 43 | MIT or Apache 2.0 licenses, at your choice. 44 | 45 | The implementations we link to are not, however. Please see the [PQClean][pqclean] 46 | project for the appropriate licenses. 47 | 48 | [pqclean]: https://github.com/PQClean/PQClean/ 49 | [nistpqc]: https://nist.gov/pqc/ -------------------------------------------------------------------------------- /pqcrypto-falcon/pqclean: -------------------------------------------------------------------------------- 1 | ../pqclean -------------------------------------------------------------------------------- /pqcrypto-falcon/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # falcon 2 | //! 3 | //! This crate provides bindings to and wrappers around the following 4 | //! implementations from [PQClean][pqc]: 5 | //! 6 | //! * falcon-512 - clean 7 | //! * falcon-padded-512 - clean 8 | //! * falcon-1024 - clean 9 | //! * falcon-padded-1024 - clean 10 | //! 11 | //! [pqc]: https://github.com/pqclean/pqclean/ 12 | //! 13 | 14 | #![no_std] 15 | #![allow(clippy::len_without_is_empty)] 16 | 17 | // For no-std vectors 18 | extern crate alloc; 19 | 20 | // For tests 21 | #[cfg(feature = "std")] 22 | extern crate std; 23 | 24 | pub mod falcon1024; 25 | pub mod falcon512; 26 | pub mod falconpadded1024; 27 | pub mod falconpadded512; 28 | pub mod ffi; 29 | 30 | pub use crate::falcon1024::{ 31 | detached_sign as falcon1024_detached_sign, keypair as falcon1024_keypair, 32 | open as falcon1024_open, public_key_bytes as falcon1024_public_key_bytes, 33 | secret_key_bytes as falcon1024_secret_key_bytes, sign as falcon1024_sign, 34 | signature_bytes as falcon1024_signature_bytes, 35 | verify_detached_signature as falcon1024_verify_detached_signature, 36 | }; 37 | pub use crate::falcon512::{ 38 | detached_sign as falcon512_detached_sign, keypair as falcon512_keypair, open as falcon512_open, 39 | public_key_bytes as falcon512_public_key_bytes, secret_key_bytes as falcon512_secret_key_bytes, 40 | sign as falcon512_sign, signature_bytes as falcon512_signature_bytes, 41 | verify_detached_signature as falcon512_verify_detached_signature, 42 | }; 43 | pub use crate::falconpadded1024::{ 44 | detached_sign as falconpadded1024_detached_sign, keypair as falconpadded1024_keypair, 45 | open as falconpadded1024_open, public_key_bytes as falconpadded1024_public_key_bytes, 46 | secret_key_bytes as falconpadded1024_secret_key_bytes, sign as falconpadded1024_sign, 47 | signature_bytes as falconpadded1024_signature_bytes, 48 | verify_detached_signature as falconpadded1024_verify_detached_signature, 49 | }; 50 | pub use crate::falconpadded512::{ 51 | detached_sign as falconpadded512_detached_sign, keypair as falconpadded512_keypair, 52 | open as falconpadded512_open, public_key_bytes as falconpadded512_public_key_bytes, 53 | secret_key_bytes as falconpadded512_secret_key_bytes, sign as falconpadded512_sign, 54 | signature_bytes as falconpadded512_signature_bytes, 55 | verify_detached_signature as falconpadded512_verify_detached_signature, 56 | }; 57 | -------------------------------------------------------------------------------- /pqcrypto-hqc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pqcrypto-hqc" 3 | description = "Post-Quantum Key-Encapsulation Mechanism hqc" 4 | readme = "README.md" 5 | version = "0.2.1" 6 | authors = ["Thom Wiggers "] 7 | edition = "2021" 8 | license = "MIT OR Apache-2.0" 9 | homepage = "https://github.com/rustpq/" 10 | repository = "https://github.com/rustpq/pqcrypto/" 11 | keywords = ["cryptography", "post-quantum", "security"] 12 | categories = ["cryptography", "no-std"] 13 | 14 | [dependencies] 15 | pqcrypto-internals = { path = "../pqcrypto-internals", version = "0.2.6" } 16 | pqcrypto-traits = { path = "../pqcrypto-traits", version = "0.3.5", default-features = false } 17 | libc = "0.2.0" 18 | serde = { version = "1.0", features = ["derive"], optional = true } 19 | serde-big-array = { version = "0.5.1", optional = true } 20 | 21 | [features] 22 | default = ["std"] 23 | std = ["pqcrypto-traits/std"] 24 | serialization = ["serde", "serde-big-array"] 25 | 26 | [dev-dependencies] 27 | 28 | [build-dependencies] 29 | cc = { version = "1.0", features = ["parallel"] } 30 | glob = "0.3.0" 31 | 32 | [badges] 33 | travis-ci = { repository = "rustpq/pqcrypto", branch = "master" } 34 | maintenance = { status = "actively-developed" } 35 | 36 | -------------------------------------------------------------------------------- /pqcrypto-hqc/README.md: -------------------------------------------------------------------------------- 1 | # hqc 2 | 3 | 4 | This crate contains bindings to the C implementations of the following schemes, 5 | from [PQClean][pqclean]. 6 | 7 | This project packages Post-Quantum cryptographic algorithms that participate in 8 | the [NIST PQC standardization effort][nistpqc]. It is currently a collection of 9 | wrappers around C implementations from the [PQClean][pqclean] project. 10 | 11 | ## Serialization 12 | 13 | If you want `serde` support, enable the `serialization` feature. 14 | 15 | ## Included implementations from PQClean 16 | 17 | Below is a list of the included schemes and the corresponding implementations 18 | sourced from [PQClean][pqclean]. The "default" implementation is used in the 19 | Rust-friendly interface, alternative implementations are exposed as ``ffi`` 20 | methods only. 21 | 22 | * ``hqc-128`` 23 | * ``clean`` 24 | * ``hqc-192`` 25 | * ``clean`` 26 | * ``hqc-256`` 27 | * ``clean`` 28 | 29 | 30 | ## License 31 | 32 | The wrappers and wrapper generation scripts in this project are covered by the 33 | MIT or Apache 2.0 licenses, at your choice. 34 | 35 | The implementations we link to are not, however. Please see the [PQClean][pqclean] 36 | project for the appropriate licenses. 37 | 38 | [pqclean]: https://github.com/PQClean/PQClean/ 39 | [nistpqc]: https://nist.gov/pqc/ -------------------------------------------------------------------------------- /pqcrypto-hqc/build.rs: -------------------------------------------------------------------------------- 1 | extern crate cc; 2 | extern crate glob; 3 | 4 | use std::env; 5 | use std::path::{Path, PathBuf}; 6 | 7 | macro_rules! build_clean { 8 | ($variant:expr) => { 9 | let internals_include_path = &std::env::var("DEP_PQCRYPTO_INTERNALS_INCLUDEPATH").unwrap(); 10 | let common_dir = Path::new("pqclean/common"); 11 | 12 | let mut builder = cc::Build::new(); 13 | let target_dir: PathBuf = ["pqclean", "crypto_kem", $variant, "clean"] 14 | .iter() 15 | .collect(); 16 | 17 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 18 | if target_os == "wasi" { 19 | let wasi_sdk_path = 20 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 21 | builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str()); 22 | } 23 | 24 | let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap(); 25 | 26 | builder 27 | .include(internals_include_path) 28 | .include(&common_dir) 29 | .include(target_dir) 30 | .files( 31 | scheme_files 32 | .into_iter() 33 | .map(|p| p.unwrap().to_string_lossy().into_owned()), 34 | ); 35 | builder.compile(format!("{}_clean", $variant).as_str()); 36 | }; 37 | } 38 | 39 | fn main() { 40 | #[allow(unused_variables)] 41 | let aes_enabled = env::var("CARGO_FEATURE_AES").is_ok(); 42 | #[allow(unused_variables)] 43 | let avx2_enabled = env::var("CARGO_FEATURE_AVX2").is_ok(); 44 | #[allow(unused_variables)] 45 | let neon_enabled = env::var("CARGO_FEATURE_NEON").is_ok(); 46 | #[allow(unused_variables)] 47 | let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); 48 | #[allow(unused_variables)] 49 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 50 | #[allow(unused_variables)] 51 | let is_windows = target_os == "windows"; 52 | #[allow(unused_variables)] 53 | let is_macos = target_os == "macos"; 54 | 55 | build_clean!("hqc-128"); 56 | build_clean!("hqc-192"); 57 | build_clean!("hqc-256"); 58 | } 59 | -------------------------------------------------------------------------------- /pqcrypto-hqc/pqclean: -------------------------------------------------------------------------------- 1 | ../pqclean -------------------------------------------------------------------------------- /pqcrypto-hqc/src/ffi.rs: -------------------------------------------------------------------------------- 1 | //! Foreign function interfaces 2 | //! 3 | //! This module defines the foreign function interface for the following 4 | //! crypto implementations from PQClean: 5 | //! 6 | //! * hqc-128 7 | //! * hqc-192 8 | //! * hqc-256 9 | // This file has been generated from PQClean. 10 | // Find the templates in pqcrypto-template 11 | use libc::c_int; 12 | 13 | // ensures we link correctly 14 | #[allow(unused_imports)] 15 | use pqcrypto_internals::*; 16 | 17 | pub const PQCLEAN_HQC128_CLEAN_CRYPTO_SECRETKEYBYTES: usize = 2305; 18 | pub const PQCLEAN_HQC128_CLEAN_CRYPTO_PUBLICKEYBYTES: usize = 2249; 19 | pub const PQCLEAN_HQC128_CLEAN_CRYPTO_CIPHERTEXTBYTES: usize = 4433; 20 | pub const PQCLEAN_HQC128_CLEAN_CRYPTO_BYTES: usize = 64; 21 | 22 | pub const PQCLEAN_HQC192_CLEAN_CRYPTO_SECRETKEYBYTES: usize = 4586; 23 | pub const PQCLEAN_HQC192_CLEAN_CRYPTO_PUBLICKEYBYTES: usize = 4522; 24 | pub const PQCLEAN_HQC192_CLEAN_CRYPTO_CIPHERTEXTBYTES: usize = 8978; 25 | pub const PQCLEAN_HQC192_CLEAN_CRYPTO_BYTES: usize = 64; 26 | 27 | pub const PQCLEAN_HQC256_CLEAN_CRYPTO_SECRETKEYBYTES: usize = 7317; 28 | pub const PQCLEAN_HQC256_CLEAN_CRYPTO_PUBLICKEYBYTES: usize = 7245; 29 | pub const PQCLEAN_HQC256_CLEAN_CRYPTO_CIPHERTEXTBYTES: usize = 14421; 30 | pub const PQCLEAN_HQC256_CLEAN_CRYPTO_BYTES: usize = 64; 31 | 32 | #[link(name = "hqc-128_clean")] 33 | extern "C" { 34 | pub fn PQCLEAN_HQC128_CLEAN_crypto_kem_keypair(pk: *mut u8, sk: *mut u8) -> c_int; 35 | pub fn PQCLEAN_HQC128_CLEAN_crypto_kem_enc(ct: *mut u8, ss: *mut u8, pk: *const u8) -> c_int; 36 | pub fn PQCLEAN_HQC128_CLEAN_crypto_kem_dec(ss: *mut u8, ct: *const u8, sk: *const u8) -> c_int; 37 | } 38 | 39 | #[link(name = "hqc-192_clean")] 40 | extern "C" { 41 | pub fn PQCLEAN_HQC192_CLEAN_crypto_kem_keypair(pk: *mut u8, sk: *mut u8) -> c_int; 42 | pub fn PQCLEAN_HQC192_CLEAN_crypto_kem_enc(ct: *mut u8, ss: *mut u8, pk: *const u8) -> c_int; 43 | pub fn PQCLEAN_HQC192_CLEAN_crypto_kem_dec(ss: *mut u8, ct: *const u8, sk: *const u8) -> c_int; 44 | } 45 | 46 | #[link(name = "hqc-256_clean")] 47 | extern "C" { 48 | pub fn PQCLEAN_HQC256_CLEAN_crypto_kem_keypair(pk: *mut u8, sk: *mut u8) -> c_int; 49 | pub fn PQCLEAN_HQC256_CLEAN_crypto_kem_enc(ct: *mut u8, ss: *mut u8, pk: *const u8) -> c_int; 50 | pub fn PQCLEAN_HQC256_CLEAN_crypto_kem_dec(ss: *mut u8, ct: *const u8, sk: *const u8) -> c_int; 51 | } 52 | 53 | #[cfg(test)] 54 | mod test_hqc128_clean { 55 | use super::*; 56 | use alloc::vec; 57 | 58 | #[test] 59 | fn test_ffi() { 60 | unsafe { 61 | let mut pk = vec![0u8; PQCLEAN_HQC128_CLEAN_CRYPTO_PUBLICKEYBYTES]; 62 | let mut sk = vec![0u8; PQCLEAN_HQC128_CLEAN_CRYPTO_SECRETKEYBYTES]; 63 | let mut ct = vec![0u8; PQCLEAN_HQC128_CLEAN_CRYPTO_CIPHERTEXTBYTES]; 64 | let mut ss1 = vec![0u8; PQCLEAN_HQC128_CLEAN_CRYPTO_BYTES]; 65 | let mut ss2 = vec![0u8; PQCLEAN_HQC128_CLEAN_CRYPTO_BYTES]; 66 | 67 | assert_eq!( 68 | 0, 69 | PQCLEAN_HQC128_CLEAN_crypto_kem_keypair(pk.as_mut_ptr(), sk.as_mut_ptr()) 70 | ); 71 | assert_eq!( 72 | 0, 73 | PQCLEAN_HQC128_CLEAN_crypto_kem_enc(ct.as_mut_ptr(), ss1.as_mut_ptr(), pk.as_ptr()) 74 | ); 75 | assert_eq!( 76 | 0, 77 | PQCLEAN_HQC128_CLEAN_crypto_kem_dec(ss2.as_mut_ptr(), ct.as_ptr(), sk.as_ptr()) 78 | ); 79 | assert_eq!(&ss1[..], &ss2[..], "Shared secrets should be equal"); 80 | } 81 | } 82 | } 83 | 84 | #[cfg(test)] 85 | mod test_hqc192_clean { 86 | use super::*; 87 | use alloc::vec; 88 | 89 | #[test] 90 | fn test_ffi() { 91 | unsafe { 92 | let mut pk = vec![0u8; PQCLEAN_HQC192_CLEAN_CRYPTO_PUBLICKEYBYTES]; 93 | let mut sk = vec![0u8; PQCLEAN_HQC192_CLEAN_CRYPTO_SECRETKEYBYTES]; 94 | let mut ct = vec![0u8; PQCLEAN_HQC192_CLEAN_CRYPTO_CIPHERTEXTBYTES]; 95 | let mut ss1 = vec![0u8; PQCLEAN_HQC192_CLEAN_CRYPTO_BYTES]; 96 | let mut ss2 = vec![0u8; PQCLEAN_HQC192_CLEAN_CRYPTO_BYTES]; 97 | 98 | assert_eq!( 99 | 0, 100 | PQCLEAN_HQC192_CLEAN_crypto_kem_keypair(pk.as_mut_ptr(), sk.as_mut_ptr()) 101 | ); 102 | assert_eq!( 103 | 0, 104 | PQCLEAN_HQC192_CLEAN_crypto_kem_enc(ct.as_mut_ptr(), ss1.as_mut_ptr(), pk.as_ptr()) 105 | ); 106 | assert_eq!( 107 | 0, 108 | PQCLEAN_HQC192_CLEAN_crypto_kem_dec(ss2.as_mut_ptr(), ct.as_ptr(), sk.as_ptr()) 109 | ); 110 | assert_eq!(&ss1[..], &ss2[..], "Shared secrets should be equal"); 111 | } 112 | } 113 | } 114 | 115 | #[cfg(test)] 116 | mod test_hqc256_clean { 117 | use super::*; 118 | use alloc::vec; 119 | 120 | #[test] 121 | fn test_ffi() { 122 | unsafe { 123 | let mut pk = vec![0u8; PQCLEAN_HQC256_CLEAN_CRYPTO_PUBLICKEYBYTES]; 124 | let mut sk = vec![0u8; PQCLEAN_HQC256_CLEAN_CRYPTO_SECRETKEYBYTES]; 125 | let mut ct = vec![0u8; PQCLEAN_HQC256_CLEAN_CRYPTO_CIPHERTEXTBYTES]; 126 | let mut ss1 = vec![0u8; PQCLEAN_HQC256_CLEAN_CRYPTO_BYTES]; 127 | let mut ss2 = vec![0u8; PQCLEAN_HQC256_CLEAN_CRYPTO_BYTES]; 128 | 129 | assert_eq!( 130 | 0, 131 | PQCLEAN_HQC256_CLEAN_crypto_kem_keypair(pk.as_mut_ptr(), sk.as_mut_ptr()) 132 | ); 133 | assert_eq!( 134 | 0, 135 | PQCLEAN_HQC256_CLEAN_crypto_kem_enc(ct.as_mut_ptr(), ss1.as_mut_ptr(), pk.as_ptr()) 136 | ); 137 | assert_eq!( 138 | 0, 139 | PQCLEAN_HQC256_CLEAN_crypto_kem_dec(ss2.as_mut_ptr(), ct.as_ptr(), sk.as_ptr()) 140 | ); 141 | assert_eq!(&ss1[..], &ss2[..], "Shared secrets should be equal"); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /pqcrypto-hqc/src/hqc128.rs: -------------------------------------------------------------------------------- 1 | //! hqc-128 2 | //! 3 | //! These bindings use the clean version from [PQClean][pqc] 4 | //! 5 | //! # Example 6 | //! ``` 7 | //! // if using pqcrypto-hqc 8 | //! use pqcrypto_hqc::hqc128::*; 9 | //! // or if using the pqcrypto crate: 10 | //! // use pqcrypto::kem::hqc128::*; 11 | //! let (pk, sk) = keypair(); 12 | //! let (ss1, ct) = encapsulate(&pk); 13 | //! let ss2 = decapsulate(&ct, &sk); 14 | //! assert!(ss1 == ss2); 15 | //! ``` 16 | //! 17 | //! [pqc]: https://github.com/pqclean/pqclean/ 18 | 19 | // This file is generated. 20 | 21 | #[cfg(feature = "serialization")] 22 | use serde::{Deserialize, Serialize}; 23 | #[cfg(feature = "serialization")] 24 | use serde_big_array::BigArray; 25 | 26 | use crate::ffi; 27 | use pqcrypto_traits::kem as primitive; 28 | use pqcrypto_traits::{Error, Result}; 29 | 30 | macro_rules! simple_struct { 31 | ($type: ident, $size: expr) => { 32 | #[derive(Clone, Copy)] 33 | #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 34 | pub struct $type( 35 | #[cfg_attr(feature = "serialization", serde(with = "BigArray"))] [u8; $size], 36 | ); 37 | 38 | impl $type { 39 | /// Generates an uninitialized object 40 | /// 41 | /// Used to pass to ``ffi`` interfaces. 42 | /// 43 | /// Internal use only! 44 | fn new() -> Self { 45 | $type([0u8; $size]) 46 | } 47 | } 48 | 49 | impl primitive::$type for $type { 50 | /// Get this object as a byte slice 51 | #[inline] 52 | fn as_bytes(&self) -> &[u8] { 53 | &self.0 54 | } 55 | 56 | /// Construct this object from a byte slice 57 | fn from_bytes(bytes: &[u8]) -> Result { 58 | if bytes.len() != $size { 59 | Err(Error::BadLength { 60 | name: stringify!($type), 61 | actual: bytes.len(), 62 | expected: $size, 63 | }) 64 | } else { 65 | let mut array = [0u8; $size]; 66 | array.copy_from_slice(bytes); 67 | Ok($type(array)) 68 | } 69 | } 70 | } 71 | 72 | impl PartialEq for $type { 73 | /// By no means constant time comparison 74 | fn eq(&self, other: &Self) -> bool { 75 | self.0 76 | .iter() 77 | .zip(other.0.iter()) 78 | .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) }) 79 | .is_ok() 80 | } 81 | } 82 | }; 83 | } 84 | 85 | simple_struct!(PublicKey, ffi::PQCLEAN_HQC128_CLEAN_CRYPTO_PUBLICKEYBYTES); 86 | simple_struct!(SecretKey, ffi::PQCLEAN_HQC128_CLEAN_CRYPTO_SECRETKEYBYTES); 87 | simple_struct!(Ciphertext, ffi::PQCLEAN_HQC128_CLEAN_CRYPTO_CIPHERTEXTBYTES); 88 | simple_struct!(SharedSecret, ffi::PQCLEAN_HQC128_CLEAN_CRYPTO_BYTES); 89 | 90 | /// Get the number of bytes for a public key 91 | pub const fn public_key_bytes() -> usize { 92 | ffi::PQCLEAN_HQC128_CLEAN_CRYPTO_PUBLICKEYBYTES 93 | } 94 | 95 | /// Get the number of bytes for a secret key 96 | pub const fn secret_key_bytes() -> usize { 97 | ffi::PQCLEAN_HQC128_CLEAN_CRYPTO_SECRETKEYBYTES 98 | } 99 | 100 | /// Get the number of bytes for the encapsulated ciphertext 101 | pub const fn ciphertext_bytes() -> usize { 102 | ffi::PQCLEAN_HQC128_CLEAN_CRYPTO_CIPHERTEXTBYTES 103 | } 104 | 105 | /// Get the number of bytes for the shared secret 106 | pub const fn shared_secret_bytes() -> usize { 107 | ffi::PQCLEAN_HQC128_CLEAN_CRYPTO_BYTES 108 | } 109 | 110 | macro_rules! gen_keypair { 111 | ($variant:ident) => {{ 112 | let mut pk = PublicKey::new(); 113 | let mut sk = SecretKey::new(); 114 | assert_eq!( 115 | unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) }, 116 | 0 117 | ); 118 | (pk, sk) 119 | }}; 120 | } 121 | 122 | /// Generate a hqc-128 keypair 123 | pub fn keypair() -> (PublicKey, SecretKey) { 124 | gen_keypair!(PQCLEAN_HQC128_CLEAN_crypto_kem_keypair) 125 | } 126 | 127 | macro_rules! encap { 128 | ($variant:ident, $pk:ident) => {{ 129 | let mut ss = SharedSecret::new(); 130 | let mut ct = Ciphertext::new(); 131 | assert_eq!( 132 | unsafe { ffi::$variant(ct.0.as_mut_ptr(), ss.0.as_mut_ptr(), $pk.0.as_ptr()) }, 133 | 0, 134 | ); 135 | (ss, ct) 136 | }}; 137 | } 138 | 139 | /// Encapsulate to a hqc-128 public key 140 | pub fn encapsulate(pk: &PublicKey) -> (SharedSecret, Ciphertext) { 141 | encap!(PQCLEAN_HQC128_CLEAN_crypto_kem_enc, pk) 142 | } 143 | 144 | macro_rules! decap { 145 | ($variant:ident, $ct:ident, $sk:ident) => {{ 146 | let mut ss = SharedSecret::new(); 147 | assert_eq!( 148 | unsafe { ffi::$variant(ss.0.as_mut_ptr(), $ct.0.as_ptr(), $sk.0.as_ptr(),) }, 149 | 0 150 | ); 151 | ss 152 | }}; 153 | } 154 | 155 | /// Decapsulate the received hqc-128 ciphertext 156 | pub fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> SharedSecret { 157 | decap!(PQCLEAN_HQC128_CLEAN_crypto_kem_dec, ct, sk) 158 | } 159 | 160 | #[cfg(test)] 161 | mod test { 162 | use super::*; 163 | 164 | #[test] 165 | pub fn test_kem() { 166 | let (pk, sk) = keypair(); 167 | let (ss1, ct) = encapsulate(&pk); 168 | let ss2 = decapsulate(&ct, &sk); 169 | assert_eq!(&ss1.0[..], &ss2.0[..], "Difference in shared secrets!"); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /pqcrypto-hqc/src/hqc192.rs: -------------------------------------------------------------------------------- 1 | //! hqc-192 2 | //! 3 | //! These bindings use the clean version from [PQClean][pqc] 4 | //! 5 | //! # Example 6 | //! ``` 7 | //! // if using pqcrypto-hqc 8 | //! use pqcrypto_hqc::hqc192::*; 9 | //! // or if using the pqcrypto crate: 10 | //! // use pqcrypto::kem::hqc192::*; 11 | //! let (pk, sk) = keypair(); 12 | //! let (ss1, ct) = encapsulate(&pk); 13 | //! let ss2 = decapsulate(&ct, &sk); 14 | //! assert!(ss1 == ss2); 15 | //! ``` 16 | //! 17 | //! [pqc]: https://github.com/pqclean/pqclean/ 18 | 19 | // This file is generated. 20 | 21 | #[cfg(feature = "serialization")] 22 | use serde::{Deserialize, Serialize}; 23 | #[cfg(feature = "serialization")] 24 | use serde_big_array::BigArray; 25 | 26 | use crate::ffi; 27 | use pqcrypto_traits::kem as primitive; 28 | use pqcrypto_traits::{Error, Result}; 29 | 30 | macro_rules! simple_struct { 31 | ($type: ident, $size: expr) => { 32 | #[derive(Clone, Copy)] 33 | #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 34 | pub struct $type( 35 | #[cfg_attr(feature = "serialization", serde(with = "BigArray"))] [u8; $size], 36 | ); 37 | 38 | impl $type { 39 | /// Generates an uninitialized object 40 | /// 41 | /// Used to pass to ``ffi`` interfaces. 42 | /// 43 | /// Internal use only! 44 | fn new() -> Self { 45 | $type([0u8; $size]) 46 | } 47 | } 48 | 49 | impl primitive::$type for $type { 50 | /// Get this object as a byte slice 51 | #[inline] 52 | fn as_bytes(&self) -> &[u8] { 53 | &self.0 54 | } 55 | 56 | /// Construct this object from a byte slice 57 | fn from_bytes(bytes: &[u8]) -> Result { 58 | if bytes.len() != $size { 59 | Err(Error::BadLength { 60 | name: stringify!($type), 61 | actual: bytes.len(), 62 | expected: $size, 63 | }) 64 | } else { 65 | let mut array = [0u8; $size]; 66 | array.copy_from_slice(bytes); 67 | Ok($type(array)) 68 | } 69 | } 70 | } 71 | 72 | impl PartialEq for $type { 73 | /// By no means constant time comparison 74 | fn eq(&self, other: &Self) -> bool { 75 | self.0 76 | .iter() 77 | .zip(other.0.iter()) 78 | .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) }) 79 | .is_ok() 80 | } 81 | } 82 | }; 83 | } 84 | 85 | simple_struct!(PublicKey, ffi::PQCLEAN_HQC192_CLEAN_CRYPTO_PUBLICKEYBYTES); 86 | simple_struct!(SecretKey, ffi::PQCLEAN_HQC192_CLEAN_CRYPTO_SECRETKEYBYTES); 87 | simple_struct!(Ciphertext, ffi::PQCLEAN_HQC192_CLEAN_CRYPTO_CIPHERTEXTBYTES); 88 | simple_struct!(SharedSecret, ffi::PQCLEAN_HQC192_CLEAN_CRYPTO_BYTES); 89 | 90 | /// Get the number of bytes for a public key 91 | pub const fn public_key_bytes() -> usize { 92 | ffi::PQCLEAN_HQC192_CLEAN_CRYPTO_PUBLICKEYBYTES 93 | } 94 | 95 | /// Get the number of bytes for a secret key 96 | pub const fn secret_key_bytes() -> usize { 97 | ffi::PQCLEAN_HQC192_CLEAN_CRYPTO_SECRETKEYBYTES 98 | } 99 | 100 | /// Get the number of bytes for the encapsulated ciphertext 101 | pub const fn ciphertext_bytes() -> usize { 102 | ffi::PQCLEAN_HQC192_CLEAN_CRYPTO_CIPHERTEXTBYTES 103 | } 104 | 105 | /// Get the number of bytes for the shared secret 106 | pub const fn shared_secret_bytes() -> usize { 107 | ffi::PQCLEAN_HQC192_CLEAN_CRYPTO_BYTES 108 | } 109 | 110 | macro_rules! gen_keypair { 111 | ($variant:ident) => {{ 112 | let mut pk = PublicKey::new(); 113 | let mut sk = SecretKey::new(); 114 | assert_eq!( 115 | unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) }, 116 | 0 117 | ); 118 | (pk, sk) 119 | }}; 120 | } 121 | 122 | /// Generate a hqc-192 keypair 123 | pub fn keypair() -> (PublicKey, SecretKey) { 124 | gen_keypair!(PQCLEAN_HQC192_CLEAN_crypto_kem_keypair) 125 | } 126 | 127 | macro_rules! encap { 128 | ($variant:ident, $pk:ident) => {{ 129 | let mut ss = SharedSecret::new(); 130 | let mut ct = Ciphertext::new(); 131 | assert_eq!( 132 | unsafe { ffi::$variant(ct.0.as_mut_ptr(), ss.0.as_mut_ptr(), $pk.0.as_ptr()) }, 133 | 0, 134 | ); 135 | (ss, ct) 136 | }}; 137 | } 138 | 139 | /// Encapsulate to a hqc-192 public key 140 | pub fn encapsulate(pk: &PublicKey) -> (SharedSecret, Ciphertext) { 141 | encap!(PQCLEAN_HQC192_CLEAN_crypto_kem_enc, pk) 142 | } 143 | 144 | macro_rules! decap { 145 | ($variant:ident, $ct:ident, $sk:ident) => {{ 146 | let mut ss = SharedSecret::new(); 147 | assert_eq!( 148 | unsafe { ffi::$variant(ss.0.as_mut_ptr(), $ct.0.as_ptr(), $sk.0.as_ptr(),) }, 149 | 0 150 | ); 151 | ss 152 | }}; 153 | } 154 | 155 | /// Decapsulate the received hqc-192 ciphertext 156 | pub fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> SharedSecret { 157 | decap!(PQCLEAN_HQC192_CLEAN_crypto_kem_dec, ct, sk) 158 | } 159 | 160 | #[cfg(test)] 161 | mod test { 162 | use super::*; 163 | 164 | #[test] 165 | pub fn test_kem() { 166 | let (pk, sk) = keypair(); 167 | let (ss1, ct) = encapsulate(&pk); 168 | let ss2 = decapsulate(&ct, &sk); 169 | assert_eq!(&ss1.0[..], &ss2.0[..], "Difference in shared secrets!"); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /pqcrypto-hqc/src/hqc256.rs: -------------------------------------------------------------------------------- 1 | //! hqc-256 2 | //! 3 | //! These bindings use the clean version from [PQClean][pqc] 4 | //! 5 | //! # Example 6 | //! ``` 7 | //! // if using pqcrypto-hqc 8 | //! use pqcrypto_hqc::hqc256::*; 9 | //! // or if using the pqcrypto crate: 10 | //! // use pqcrypto::kem::hqc256::*; 11 | //! let (pk, sk) = keypair(); 12 | //! let (ss1, ct) = encapsulate(&pk); 13 | //! let ss2 = decapsulate(&ct, &sk); 14 | //! assert!(ss1 == ss2); 15 | //! ``` 16 | //! 17 | //! [pqc]: https://github.com/pqclean/pqclean/ 18 | 19 | // This file is generated. 20 | 21 | #[cfg(feature = "serialization")] 22 | use serde::{Deserialize, Serialize}; 23 | #[cfg(feature = "serialization")] 24 | use serde_big_array::BigArray; 25 | 26 | use crate::ffi; 27 | use pqcrypto_traits::kem as primitive; 28 | use pqcrypto_traits::{Error, Result}; 29 | 30 | macro_rules! simple_struct { 31 | ($type: ident, $size: expr) => { 32 | #[derive(Clone, Copy)] 33 | #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 34 | pub struct $type( 35 | #[cfg_attr(feature = "serialization", serde(with = "BigArray"))] [u8; $size], 36 | ); 37 | 38 | impl $type { 39 | /// Generates an uninitialized object 40 | /// 41 | /// Used to pass to ``ffi`` interfaces. 42 | /// 43 | /// Internal use only! 44 | fn new() -> Self { 45 | $type([0u8; $size]) 46 | } 47 | } 48 | 49 | impl primitive::$type for $type { 50 | /// Get this object as a byte slice 51 | #[inline] 52 | fn as_bytes(&self) -> &[u8] { 53 | &self.0 54 | } 55 | 56 | /// Construct this object from a byte slice 57 | fn from_bytes(bytes: &[u8]) -> Result { 58 | if bytes.len() != $size { 59 | Err(Error::BadLength { 60 | name: stringify!($type), 61 | actual: bytes.len(), 62 | expected: $size, 63 | }) 64 | } else { 65 | let mut array = [0u8; $size]; 66 | array.copy_from_slice(bytes); 67 | Ok($type(array)) 68 | } 69 | } 70 | } 71 | 72 | impl PartialEq for $type { 73 | /// By no means constant time comparison 74 | fn eq(&self, other: &Self) -> bool { 75 | self.0 76 | .iter() 77 | .zip(other.0.iter()) 78 | .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) }) 79 | .is_ok() 80 | } 81 | } 82 | }; 83 | } 84 | 85 | simple_struct!(PublicKey, ffi::PQCLEAN_HQC256_CLEAN_CRYPTO_PUBLICKEYBYTES); 86 | simple_struct!(SecretKey, ffi::PQCLEAN_HQC256_CLEAN_CRYPTO_SECRETKEYBYTES); 87 | simple_struct!(Ciphertext, ffi::PQCLEAN_HQC256_CLEAN_CRYPTO_CIPHERTEXTBYTES); 88 | simple_struct!(SharedSecret, ffi::PQCLEAN_HQC256_CLEAN_CRYPTO_BYTES); 89 | 90 | /// Get the number of bytes for a public key 91 | pub const fn public_key_bytes() -> usize { 92 | ffi::PQCLEAN_HQC256_CLEAN_CRYPTO_PUBLICKEYBYTES 93 | } 94 | 95 | /// Get the number of bytes for a secret key 96 | pub const fn secret_key_bytes() -> usize { 97 | ffi::PQCLEAN_HQC256_CLEAN_CRYPTO_SECRETKEYBYTES 98 | } 99 | 100 | /// Get the number of bytes for the encapsulated ciphertext 101 | pub const fn ciphertext_bytes() -> usize { 102 | ffi::PQCLEAN_HQC256_CLEAN_CRYPTO_CIPHERTEXTBYTES 103 | } 104 | 105 | /// Get the number of bytes for the shared secret 106 | pub const fn shared_secret_bytes() -> usize { 107 | ffi::PQCLEAN_HQC256_CLEAN_CRYPTO_BYTES 108 | } 109 | 110 | macro_rules! gen_keypair { 111 | ($variant:ident) => {{ 112 | let mut pk = PublicKey::new(); 113 | let mut sk = SecretKey::new(); 114 | assert_eq!( 115 | unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) }, 116 | 0 117 | ); 118 | (pk, sk) 119 | }}; 120 | } 121 | 122 | /// Generate a hqc-256 keypair 123 | pub fn keypair() -> (PublicKey, SecretKey) { 124 | gen_keypair!(PQCLEAN_HQC256_CLEAN_crypto_kem_keypair) 125 | } 126 | 127 | macro_rules! encap { 128 | ($variant:ident, $pk:ident) => {{ 129 | let mut ss = SharedSecret::new(); 130 | let mut ct = Ciphertext::new(); 131 | assert_eq!( 132 | unsafe { ffi::$variant(ct.0.as_mut_ptr(), ss.0.as_mut_ptr(), $pk.0.as_ptr()) }, 133 | 0, 134 | ); 135 | (ss, ct) 136 | }}; 137 | } 138 | 139 | /// Encapsulate to a hqc-256 public key 140 | pub fn encapsulate(pk: &PublicKey) -> (SharedSecret, Ciphertext) { 141 | encap!(PQCLEAN_HQC256_CLEAN_crypto_kem_enc, pk) 142 | } 143 | 144 | macro_rules! decap { 145 | ($variant:ident, $ct:ident, $sk:ident) => {{ 146 | let mut ss = SharedSecret::new(); 147 | assert_eq!( 148 | unsafe { ffi::$variant(ss.0.as_mut_ptr(), $ct.0.as_ptr(), $sk.0.as_ptr(),) }, 149 | 0 150 | ); 151 | ss 152 | }}; 153 | } 154 | 155 | /// Decapsulate the received hqc-256 ciphertext 156 | pub fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> SharedSecret { 157 | decap!(PQCLEAN_HQC256_CLEAN_crypto_kem_dec, ct, sk) 158 | } 159 | 160 | #[cfg(test)] 161 | mod test { 162 | use super::*; 163 | 164 | #[test] 165 | pub fn test_kem() { 166 | let (pk, sk) = keypair(); 167 | let (ss1, ct) = encapsulate(&pk); 168 | let ss2 = decapsulate(&ct, &sk); 169 | assert_eq!(&ss1.0[..], &ss2.0[..], "Difference in shared secrets!"); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /pqcrypto-hqc/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # hqc 2 | //! 3 | //! This crate provides bindings to and wrappers around the following 4 | //! implementations from [PQClean][pqc]: 5 | //! 6 | //! * hqc-128 - clean 7 | //! * hqc-192 - clean 8 | //! * hqc-256 - clean 9 | //! 10 | //! [pqc]: https://github.com/pqclean/pqclean/ 11 | //! 12 | 13 | #![no_std] 14 | #![allow(clippy::len_without_is_empty)] 15 | 16 | // For no-std vectors 17 | extern crate alloc; 18 | 19 | // For tests 20 | #[cfg(feature = "std")] 21 | extern crate std; 22 | 23 | pub mod ffi; 24 | pub mod hqc128; 25 | pub mod hqc192; 26 | pub mod hqc256; 27 | 28 | pub use crate::hqc128::{ 29 | ciphertext_bytes as hqc128_ciphertext_bytes, decapsulate as hqc128_decapsulate, 30 | encapsulate as hqc128_encapsulate, keypair as hqc128_keypair, 31 | public_key_bytes as hqc128_public_key_bytes, secret_key_bytes as hqc128_secret_key_bytes, 32 | shared_secret_bytes as hqc128_shared_secret_bytes, 33 | }; 34 | pub use crate::hqc192::{ 35 | ciphertext_bytes as hqc192_ciphertext_bytes, decapsulate as hqc192_decapsulate, 36 | encapsulate as hqc192_encapsulate, keypair as hqc192_keypair, 37 | public_key_bytes as hqc192_public_key_bytes, secret_key_bytes as hqc192_secret_key_bytes, 38 | shared_secret_bytes as hqc192_shared_secret_bytes, 39 | }; 40 | pub use crate::hqc256::{ 41 | ciphertext_bytes as hqc256_ciphertext_bytes, decapsulate as hqc256_decapsulate, 42 | encapsulate as hqc256_encapsulate, keypair as hqc256_keypair, 43 | public_key_bytes as hqc256_public_key_bytes, secret_key_bytes as hqc256_secret_key_bytes, 44 | shared_secret_bytes as hqc256_shared_secret_bytes, 45 | }; 46 | -------------------------------------------------------------------------------- /pqcrypto-internals/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pqcrypto-internals" 3 | version = "0.2.11" 4 | edition = "2021" 5 | description = "bindings to common cryptography" 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/rustpq/pqcrypto" 8 | 9 | links = "pqcrypto_internals" 10 | 11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 12 | 13 | [build-dependencies] 14 | cc = { version = "1.0", features = ["parallel"] } 15 | dunce = "1.0" 16 | 17 | [dependencies] 18 | getrandom = "0.3" 19 | libc = "0.2" 20 | -------------------------------------------------------------------------------- /pqcrypto-internals/build.rs: -------------------------------------------------------------------------------- 1 | extern crate cc; 2 | extern crate dunce; 3 | 4 | use std::env; 5 | use std::path::Path; 6 | 7 | fn main() { 8 | let includepath = dunce::canonicalize(Path::new("include")).unwrap(); 9 | println!("cargo:includepath={}", includepath.to_str().unwrap()); 10 | 11 | let cfiledir = Path::new("cfiles"); 12 | let common_files = vec![ 13 | cfiledir.join("fips202.c"), 14 | cfiledir.join("aes.c"), 15 | cfiledir.join("sha2.c"), 16 | cfiledir.join("nistseedexpander.c"), 17 | cfiledir.join("sp800-185.c"), 18 | ]; 19 | 20 | println!("cargo:rerun-if-changed=cfiles/"); 21 | println!("cargo:rerun-if-changed=build.rs"); 22 | println!("cargo:rerun-if-changed=src/"); 23 | 24 | let mut build = cc::Build::new(); 25 | 26 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 27 | if target_os == "wasi" { 28 | let wasi_sdk_path = 29 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 30 | build.flag(format!("--sysroot={wasi_sdk_path}").as_str()); 31 | } 32 | 33 | build 34 | .include(&includepath) 35 | .files(common_files) 36 | .compile("pqclean_common"); 37 | println!("cargo:rustc-link-lib=pqclean_common"); 38 | 39 | let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default(); 40 | let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default(); 41 | let mut builder = cc::Build::new(); 42 | 43 | if target_os == "wasi" { 44 | let wasi_sdk_path = 45 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 46 | builder.flag(format!("--sysroot={wasi_sdk_path}").as_str()); 47 | } 48 | 49 | if target_arch == "x86" || target_arch == "x86_64" { 50 | if target_env == "msvc" { 51 | builder.flag("/arch:AVX2"); 52 | } else { 53 | builder.flag("-mavx2"); 54 | } 55 | builder 56 | .file( 57 | cfiledir 58 | .join("keccak4x") 59 | .join("KeccakP-1600-times4-SIMD256.c"), 60 | ) 61 | .compile("keccak4x"); 62 | println!("cargo:rustc-link-lib=keccak4x") 63 | } else if target_arch == "aarch64" && target_env != "msvc" { 64 | builder 65 | .flag("-march=armv8.2-a+sha3") 66 | .file(cfiledir.join("keccak2x").join("fips202x2.c")) 67 | .file(cfiledir.join("keccak2x").join("feat.S")) 68 | .compile("keccak2x"); 69 | println!("cargo:rustc-link-lib=keccak2x") 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /pqcrypto-internals/cfiles/keccak2x/feat.S: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | MIT License 4 | 5 | Copyright (c) 2020 Bas Westerbaan 6 | Copyright (c) 2023: Hanno Becker, Vincent Hwang, Matthias J. Kannwischer, Bo-Yin Yang, and Shang-Yi Yang 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | */ 26 | 27 | #if (__APPLE__ && __ARM_FEATURE_CRYPTO) || (__ARM_FEATURE_SHA3) 28 | 29 | .macro round 30 | // Execute theta, but without xoring into the state yet. 31 | // Compute parities p[i] = a[i] ^ a[5+i] ^ ... ^ a[20+i]. 32 | eor3 v25.16b, v0.16b, v5.16b, v10.16b 33 | eor3 v26.16b, v1.16b, v6.16b, v11.16b 34 | eor3 v27.16b, v2.16b, v7.16b, v12.16b 35 | eor3 v28.16b, v3.16b, v8.16b, v13.16b 36 | eor3 v29.16b, v4.16b, v9.16b, v14.16b 37 | 38 | eor3 v25.16b, v25.16b, v15.16b, v20.16b 39 | eor3 v26.16b, v26.16b, v16.16b, v21.16b 40 | eor3 v27.16b, v27.16b, v17.16b, v22.16b 41 | eor3 v28.16b, v28.16b, v18.16b, v23.16b 42 | eor3 v29.16b, v29.16b, v19.16b, v24.16b 43 | 44 | rax1 v30.2d, v29.2d, v26.2d // d[0] = rotl(p[1], 1) ^ p[4] 45 | rax1 v29.2d, v27.2d, v29.2d // d[3] = rotl(p[4], 1) ^ p[2] 46 | rax1 v27.2d, v25.2d, v27.2d // d[1] = rotl(p[2], 1) ^ p[0] 47 | rax1 v25.2d, v28.2d, v25.2d // d[4] = rotl(p[0], 1) ^ p[3] 48 | rax1 v28.2d, v26.2d, v28.2d // d[2] = rotl(p[3], 1) ^ p[1] 49 | 50 | // Xor parities from step theta into the state at the same time 51 | // as executing rho and pi. 52 | eor v0.16b, v0.16b, v30.16b 53 | mov v31.16b, v1.16b 54 | xar v1.2d, v6.2d, v27.2d, 20 55 | xar v6.2d, v9.2d, v25.2d, 44 56 | xar v9.2d, v22.2d, v28.2d, 3 57 | xar v22.2d, v14.2d, v25.2d, 25 58 | xar v14.2d, v20.2d, v30.2d, 46 59 | xar v20.2d, v2.2d, v28.2d, 2 60 | xar v2.2d, v12.2d, v28.2d, 21 61 | xar v12.2d, v13.2d, v29.2d, 39 62 | xar v13.2d, v19.2d, v25.2d, 56 63 | xar v19.2d, v23.2d, v29.2d, 8 64 | xar v23.2d, v15.2d, v30.2d, 23 65 | xar v15.2d, v4.2d, v25.2d, 37 66 | xar v4.2d, v24.2d, v25.2d, 50 67 | xar v24.2d, v21.2d, v27.2d, 62 68 | xar v21.2d, v8.2d, v29.2d, 9 69 | xar v8.2d, v16.2d, v27.2d, 19 70 | xar v16.2d, v5.2d, v30.2d, 28 71 | xar v5.2d, v3.2d, v29.2d, 36 72 | xar v3.2d, v18.2d, v29.2d, 43 73 | xar v18.2d, v17.2d, v28.2d, 49 74 | xar v17.2d, v11.2d, v27.2d, 54 75 | xar v11.2d, v7.2d, v28.2d, 58 76 | xar v7.2d, v10.2d, v30.2d, 61 77 | xar v10.2d, v31.2d, v27.2d, 63 78 | 79 | // Chi 80 | bcax v25.16b, v0.16b, v2.16b, v1.16b 81 | bcax v26.16b, v1.16b, v3.16b, v2.16b 82 | bcax v2.16b, v2.16b, v4.16b, v3.16b 83 | bcax v3.16b, v3.16b, v0.16b, v4.16b 84 | bcax v4.16b, v4.16b, v1.16b, v0.16b 85 | mov v0.16b, v25.16b 86 | mov v1.16b, v26.16b 87 | 88 | bcax v25.16b, v5.16b, v7.16b, v6.16b 89 | bcax v26.16b, v6.16b, v8.16b, v7.16b 90 | bcax v7.16b, v7.16b, v9.16b, v8.16b 91 | bcax v8.16b, v8.16b, v5.16b, v9.16b 92 | bcax v9.16b, v9.16b, v6.16b, v5.16b 93 | mov v5.16b, v25.16b 94 | mov v6.16b, v26.16b 95 | 96 | bcax v25.16b, v10.16b, v12.16b, v11.16b 97 | bcax v26.16b, v11.16b, v13.16b, v12.16b 98 | bcax v12.16b, v12.16b, v14.16b, v13.16b 99 | bcax v13.16b, v13.16b, v10.16b, v14.16b 100 | bcax v14.16b, v14.16b, v11.16b, v10.16b 101 | mov v10.16b, v25.16b 102 | mov v11.16b, v26.16b 103 | 104 | bcax v25.16b, v15.16b, v17.16b, v16.16b 105 | bcax v26.16b, v16.16b, v18.16b, v17.16b 106 | bcax v17.16b, v17.16b, v19.16b, v18.16b 107 | bcax v18.16b, v18.16b, v15.16b, v19.16b 108 | bcax v19.16b, v19.16b, v16.16b, v15.16b 109 | mov v15.16b, v25.16b 110 | mov v16.16b, v26.16b 111 | 112 | bcax v25.16b, v20.16b, v22.16b, v21.16b 113 | bcax v26.16b, v21.16b, v23.16b, v22.16b 114 | bcax v22.16b, v22.16b, v24.16b, v23.16b 115 | bcax v23.16b, v23.16b, v20.16b, v24.16b 116 | bcax v24.16b, v24.16b, v21.16b, v20.16b 117 | mov v20.16b, v25.16b 118 | mov v21.16b, v26.16b 119 | 120 | // iota 121 | ld1r {v25.2d}, [x1], #8 122 | eor v0.16b, v0.16b, v25.16b 123 | .endm 124 | 125 | .align 4 126 | .global f1600x2 127 | .global _f1600x2 128 | f1600x2: 129 | _f1600x2: 130 | stp d8, d9, [sp,#-16]! 131 | stp d10, d11, [sp,#-16]! 132 | stp d12, d13, [sp,#-16]! 133 | stp d14, d15, [sp,#-16]! 134 | 135 | mov x2, x0 136 | mov x3, #24 137 | 138 | ld1 {v0.2d, v1.2d, v2.2d, v3.2d}, [x0], #64 139 | ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [x0], #64 140 | ld1 {v8.2d, v9.2d, v10.2d, v11.2d}, [x0], #64 141 | ld1 {v12.2d, v13.2d, v14.2d, v15.2d}, [x0], #64 142 | ld1 {v16.2d, v17.2d, v18.2d, v19.2d}, [x0], #64 143 | ld1 {v20.2d, v21.2d, v22.2d, v23.2d}, [x0], #64 144 | ld1 {v24.2d}, [x0] 145 | 146 | loop: 147 | round 148 | 149 | subs x3, x3, #1 150 | cbnz x3, loop 151 | 152 | mov x0, x2 153 | st1 {v0.2d, v1.2d, v2.2d, v3.2d}, [x0], #64 154 | st1 {v4.2d, v5.2d, v6.2d, v7.2d}, [x0], #64 155 | st1 {v8.2d, v9.2d, v10.2d, v11.2d}, [x0], #64 156 | st1 {v12.2d, v13.2d, v14.2d, v15.2d}, [x0], #64 157 | st1 {v16.2d, v17.2d, v18.2d, v19.2d}, [x0], #64 158 | st1 {v20.2d, v21.2d, v22.2d, v23.2d}, [x0], #64 159 | st1 {v24.2d}, [x0] 160 | 161 | ldp d14, d15, [sp], #16 162 | ldp d12, d13, [sp], #16 163 | ldp d10, d11, [sp], #16 164 | ldp d8, d9, [sp], #16 165 | 166 | ret lr 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /pqcrypto-internals/cfiles/keccak2x/fips202x2.h: -------------------------------------------------------------------------------- 1 | #ifndef FIPS202X2_H 2 | #define FIPS202X2_H 3 | 4 | /* 5 | * This file is licensed 6 | * under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0.html) 7 | * at https://github.com/GMUCERG/PQC_NEON/blob/main/neon/kyber or 8 | * public domain at https://github.com/cothan/kyber/blob/master/neon 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | typedef uint64x2_t v128; 16 | 17 | #define SHAKE128_RATE 168 18 | #define SHAKE256_RATE 136 19 | #define SHA3_256_RATE 136 20 | #define SHA3_512_RATE 72 21 | 22 | typedef struct { 23 | v128 s[25]; 24 | } keccakx2_state; 25 | 26 | void shake128x2_absorb(keccakx2_state *state, 27 | const uint8_t *in0, 28 | const uint8_t *in1, 29 | size_t inlen); 30 | 31 | void shake128x2_squeezeblocks(uint8_t *out0, 32 | uint8_t *out1, 33 | size_t nblocks, 34 | keccakx2_state *state); 35 | 36 | void shake256x2_absorb(keccakx2_state *state, 37 | const uint8_t *in0, 38 | const uint8_t *in1, 39 | size_t inlen); 40 | 41 | void shake256x2_squeezeblocks(uint8_t *out0, 42 | uint8_t *out1, 43 | size_t nblocks, 44 | keccakx2_state *state); 45 | 46 | void shake128x2(uint8_t *out0, 47 | uint8_t *out1, 48 | size_t outlen, 49 | const uint8_t *in0, 50 | const uint8_t *in1, 51 | size_t inlen); 52 | 53 | void shake256x2(uint8_t *out0, 54 | uint8_t *out1, 55 | size_t outlen, 56 | const uint8_t *in0, 57 | const uint8_t *in1, 58 | size_t inlen); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /pqcrypto-internals/cfiles/keccak4x/KeccakP-1600-times4-SnP.h: -------------------------------------------------------------------------------- 1 | /* 2 | Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, 3 | Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby 4 | denoted as "the implementer". 5 | 6 | For more information, feedback or questions, please refer to our websites: 7 | http://keccak.noekeon.org/ 8 | http://keyak.noekeon.org/ 9 | http://ketje.noekeon.org/ 10 | 11 | To the extent possible under law, the implementer has waived all copyright 12 | and related or neighboring rights to the source code in this file. 13 | http://creativecommons.org/publicdomain/zero/1.0/ 14 | */ 15 | 16 | #ifndef _KeccakP_1600_times4_SnP_h_ 17 | #define _KeccakP_1600_times4_SnP_h_ 18 | 19 | /** For the documentation, see PlSnP-documentation.h. 20 | */ 21 | 22 | #include "SIMD256-config.h" 23 | 24 | #define KeccakP1600times4_implementation "256-bit SIMD implementation (" KeccakP1600times4_implementation_config ")" 25 | #define KeccakP1600times4_statesSizeInBytes 800 26 | #define KeccakP1600times4_statesAlignment 32 27 | #define KeccakF1600times4_FastLoop_supported 28 | #define KeccakP1600times4_12rounds_FastLoop_supported 29 | 30 | #include 31 | 32 | #define KeccakP1600times4_StaticInitialize() 33 | void KeccakP1600times4_InitializeAll(void *states); 34 | #define KeccakP1600times4_AddByte(states, instanceIndex, byte, offset) \ 35 | ((unsigned char*)(states))[(instanceIndex)*8 + ((offset)/8)*4*8 + (offset)%8] ^= (byte) 36 | void KeccakP1600times4_AddBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length); 37 | void KeccakP1600times4_AddLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset); 38 | void KeccakP1600times4_OverwriteBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length); 39 | void KeccakP1600times4_OverwriteLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset); 40 | void KeccakP1600times4_OverwriteWithZeroes(void *states, unsigned int instanceIndex, unsigned int byteCount); 41 | void KeccakP1600times4_PermuteAll_12rounds(void *states); 42 | void KeccakP1600times4_PermuteAll_24rounds(void *states); 43 | void KeccakP1600times4_ExtractBytes(const void *states, unsigned int instanceIndex, unsigned char *data, unsigned int offset, unsigned int length); 44 | void KeccakP1600times4_ExtractLanesAll(const void *states, unsigned char *data, unsigned int laneCount, unsigned int laneOffset); 45 | void KeccakP1600times4_ExtractAndAddBytes(const void *states, unsigned int instanceIndex, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length); 46 | void KeccakP1600times4_ExtractAndAddLanesAll(const void *states, const unsigned char *input, unsigned char *output, unsigned int laneCount, unsigned int laneOffset); 47 | size_t KeccakF1600times4_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen); 48 | size_t KeccakP1600times4_12rounds_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /pqcrypto-internals/cfiles/keccak4x/Makefile: -------------------------------------------------------------------------------- 1 | KeccakP-1600-times4-SIMD256.o: KeccakP-1600-times4-SIMD256.c \ 2 | align.h brg_endian.h KeccakP-1600-times4-SnP.h \ 3 | KeccakP-1600-unrolling.macros SIMD256-config.h 4 | $(CC) -O3 -mavx2 -c $< -o $@ 5 | 6 | .PHONY: clean 7 | clean: 8 | $(RM) KeccakP-1600-times4-SIMD256.o 9 | -------------------------------------------------------------------------------- /pqcrypto-internals/cfiles/keccak4x/Makefile.Microsoft_nmake: -------------------------------------------------------------------------------- 1 | KeccakP-1600-times4-SIMD256.obj: KeccakP-1600-times4-SIMD256.c \ 2 | align.h brg_endian.h KeccakP-1600-times4-SnP.h \ 3 | KeccakP-1600-unrolling.macros SIMD256-config.h 4 | $(CC) /nologo /c /O2 /W4 /WX /arch:AVX2 KeccakP-1600-times4-SIMD256.c 5 | 6 | .PHONY: clean 7 | clean: 8 | $(RM) KeccakP-1600-times4-SIMD256.obj 9 | -------------------------------------------------------------------------------- /pqcrypto-internals/cfiles/keccak4x/SIMD256-config.h: -------------------------------------------------------------------------------- 1 | #define KeccakP1600times4_implementation_config "AVX2, all rounds unrolled" 2 | #define KeccakP1600times4_fullUnrolling 3 | #define KeccakP1600times4_useAVX2 4 | -------------------------------------------------------------------------------- /pqcrypto-internals/cfiles/keccak4x/align.h: -------------------------------------------------------------------------------- 1 | /* 2 | Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, 3 | Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby 4 | denoted as "the implementer". 5 | 6 | For more information, feedback or questions, please refer to our websites: 7 | http://keccak.noekeon.org/ 8 | http://keyak.noekeon.org/ 9 | http://ketje.noekeon.org/ 10 | 11 | To the extent possible under law, the implementer has waived all copyright 12 | and related or neighboring rights to the source code in this file. 13 | http://creativecommons.org/publicdomain/zero/1.0/ 14 | */ 15 | 16 | #ifndef _align_h_ 17 | #define _align_h_ 18 | 19 | /* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */ 20 | #ifdef ALIGN 21 | #undef ALIGN 22 | #endif 23 | 24 | #if defined(__GNUC__) 25 | #define ALIGN(x) __attribute__ ((aligned(x))) 26 | #elif defined(_MSC_VER) 27 | #define ALIGN(x) __declspec(align(x)) 28 | #elif defined(__ARMCC_VERSION) 29 | #define ALIGN(x) __align(x) 30 | #else 31 | #define ALIGN(x) 32 | #endif 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /pqcrypto-internals/cfiles/keccak4x/brg_endian.h: -------------------------------------------------------------------------------- 1 | /* 2 | --------------------------------------------------------------------------- 3 | Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. 4 | 5 | LICENSE TERMS 6 | 7 | The redistribution and use of this software (with or without changes) 8 | is allowed without the payment of fees or royalties provided that: 9 | 10 | 1. source code distributions include the above copyright notice, this 11 | list of conditions and the following disclaimer; 12 | 13 | 2. binary distributions include the above copyright notice, this list 14 | of conditions and the following disclaimer in their documentation; 15 | 16 | 3. the name of the copyright holder is not used to endorse products 17 | built using this software without specific written permission. 18 | 19 | DISCLAIMER 20 | 21 | This software is provided 'as is' with no explicit or implied warranties 22 | in respect of its properties, including, but not limited to, correctness 23 | and/or fitness for purpose. 24 | --------------------------------------------------------------------------- 25 | Issue Date: 20/12/2007 26 | Changes for ARM 9/9/2010 27 | */ 28 | 29 | #ifndef _BRG_ENDIAN_H 30 | #define _BRG_ENDIAN_H 31 | 32 | #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ 33 | #define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ 34 | 35 | #if 0 36 | /* Include files where endian defines and byteswap functions may reside */ 37 | #if defined( __sun ) 38 | # include 39 | #elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) 40 | # include 41 | #elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \ 42 | defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ ) 43 | # include 44 | #elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ ) 45 | # if !defined( __MINGW32__ ) && !defined( _AIX ) 46 | # include 47 | # if !defined( __BEOS__ ) 48 | # include 49 | # endif 50 | # endif 51 | #endif 52 | #endif 53 | 54 | /* Now attempt to set the define for platform byte order using any */ 55 | /* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */ 56 | /* seem to encompass most endian symbol definitions */ 57 | 58 | #if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN ) 59 | # if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN 60 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 61 | # elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN 62 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 63 | # endif 64 | #elif defined( BIG_ENDIAN ) 65 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 66 | #elif defined( LITTLE_ENDIAN ) 67 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 68 | #endif 69 | 70 | #if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN ) 71 | # if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN 72 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 73 | # elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN 74 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 75 | # endif 76 | #elif defined( _BIG_ENDIAN ) 77 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 78 | #elif defined( _LITTLE_ENDIAN ) 79 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 80 | #endif 81 | 82 | #if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN ) 83 | # if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN 84 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 85 | # elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN 86 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 87 | # endif 88 | #elif defined( __BIG_ENDIAN ) 89 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 90 | #elif defined( __LITTLE_ENDIAN ) 91 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 92 | #endif 93 | 94 | #if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ ) 95 | # if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__ 96 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 97 | # elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__ 98 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 99 | # endif 100 | #elif defined( __BIG_ENDIAN__ ) 101 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 102 | #elif defined( __LITTLE_ENDIAN__ ) 103 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 104 | #endif 105 | 106 | /* if the platform byte order could not be determined, then try to */ 107 | /* set this define using common machine defines */ 108 | #if !defined(PLATFORM_BYTE_ORDER) 109 | 110 | #if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \ 111 | defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \ 112 | defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \ 113 | defined( vax ) || defined( vms ) || defined( VMS ) || \ 114 | defined( __VMS ) || defined( _M_X64 ) 115 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 116 | 117 | #elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \ 118 | defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \ 119 | defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \ 120 | defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \ 121 | defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \ 122 | defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \ 123 | defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) 124 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 125 | 126 | #elif defined(__arm__) 127 | # ifdef __BIG_ENDIAN 128 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 129 | # else 130 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 131 | # endif 132 | #elif 1 /* **** EDIT HERE IF NECESSARY **** */ 133 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 134 | #elif 0 /* **** EDIT HERE IF NECESSARY **** */ 135 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 136 | #else 137 | # error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order 138 | #endif 139 | 140 | #endif 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /pqcrypto-internals/cfiles/nistseedexpander.c: -------------------------------------------------------------------------------- 1 | // 2 | // rng.c 3 | // 4 | // Created by Bassham, Lawrence E (Fed) on 8/29/17. 5 | // Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. 6 | // Modified for PQClean by Sebastian Verschoor 7 | // 8 | 9 | #include "nistseedexpander.h" 10 | #include "aes.h" 11 | #include 12 | 13 | /* 14 | seedexpander_init() 15 | ctx - stores the current state of an instance of the seed expander 16 | seed - a 32 byte random value 17 | diversifier - an 8 byte diversifier 18 | maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier 19 | */ 20 | int 21 | seedexpander_init(AES_XOF_struct *ctx, 22 | const uint8_t *seed, 23 | const uint8_t *diversifier, 24 | size_t maxlen) 25 | { 26 | ctx->length_remaining = maxlen; 27 | 28 | memcpy(ctx->key, seed, 32); 29 | memcpy(ctx->ctr, diversifier, 8); 30 | 31 | ctx->ctr[11] = maxlen % 256; 32 | maxlen >>= 8; 33 | ctx->ctr[10] = maxlen % 256; 34 | maxlen >>= 8; 35 | ctx->ctr[9] = maxlen % 256; 36 | maxlen >>= 8; 37 | ctx->ctr[8] = maxlen % 256; 38 | memset(ctx->ctr+12, 0x00, 4); 39 | 40 | ctx->buffer_pos = 16; 41 | memset(ctx->buffer, 0x00, 16); 42 | 43 | return RNG_SUCCESS; 44 | } 45 | 46 | static void AES256_ECB(uint8_t *key, uint8_t *ctr, uint8_t *buffer) { 47 | aes256ctx ctx; 48 | aes256_ecb_keyexp(&ctx, key); 49 | aes256_ecb(buffer, ctr, 1, &ctx); 50 | aes256_ctx_release(&ctx); 51 | } 52 | 53 | /* 54 | seedexpander() 55 | ctx - stores the current state of an instance of the seed expander 56 | x - returns the XOF data 57 | xlen - number of bytes to return 58 | */ 59 | int 60 | seedexpander(AES_XOF_struct *ctx, uint8_t *x, size_t xlen) 61 | { 62 | size_t offset; 63 | 64 | if ( x == NULL ) { 65 | return RNG_BAD_OUTBUF; 66 | } 67 | if ( xlen >= ctx->length_remaining ) { 68 | return RNG_BAD_REQ_LEN; 69 | } 70 | 71 | ctx->length_remaining -= xlen; 72 | 73 | offset = 0; 74 | while ( xlen > 0 ) { 75 | if ( xlen <= (16-ctx->buffer_pos) ) { // buffer has what we need 76 | memcpy(x+offset, ctx->buffer+ctx->buffer_pos, xlen); 77 | ctx->buffer_pos += xlen; 78 | 79 | return RNG_SUCCESS; 80 | } 81 | 82 | // take what's in the buffer 83 | memcpy(x+offset, ctx->buffer+ctx->buffer_pos, 16-ctx->buffer_pos); 84 | xlen -= 16-ctx->buffer_pos; 85 | offset += 16-ctx->buffer_pos; 86 | 87 | AES256_ECB(ctx->key, ctx->ctr, ctx->buffer); 88 | ctx->buffer_pos = 0; 89 | 90 | //increment the counter 91 | for (size_t i=15; i>=12; i--) { 92 | if ( ctx->ctr[i] == 0xff ) { 93 | ctx->ctr[i] = 0x00; 94 | } else { 95 | ctx->ctr[i]++; 96 | break; 97 | } 98 | } 99 | 100 | } 101 | 102 | return RNG_SUCCESS; 103 | } 104 | -------------------------------------------------------------------------------- /pqcrypto-internals/cfiles/sp800-185.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "sp800-185.h" 5 | 6 | static size_t left_encode(uint8_t *encbuf, size_t value) { 7 | size_t n, i, v; 8 | 9 | for (v = value, n = 0; v && (n < sizeof(size_t)); n++, v >>= 8) { 10 | ; /* empty */ 11 | } 12 | if (n == 0) { 13 | n = 1; 14 | } 15 | for (i = 1; i <= n; i++) { 16 | encbuf[i] = (uint8_t)(value >> (8 * (n-i))); 17 | } 18 | encbuf[0] = (uint8_t)n; 19 | return n + 1; 20 | } 21 | 22 | void cshake128_inc_init(shake128incctx *state, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen) { 23 | uint8_t encbuf[sizeof(size_t)+1]; 24 | 25 | shake128_inc_init(state); 26 | 27 | shake128_inc_absorb(state, encbuf, left_encode(encbuf, SHAKE128_RATE)); 28 | 29 | shake128_inc_absorb(state, encbuf, left_encode(encbuf, namelen * 8)); 30 | shake128_inc_absorb(state, name, namelen); 31 | 32 | shake128_inc_absorb(state, encbuf, left_encode(encbuf, cstmlen * 8)); 33 | shake128_inc_absorb(state, cstm, cstmlen); 34 | 35 | if (state->ctx[25] != 0) { 36 | state->ctx[25] = SHAKE128_RATE - 1; 37 | encbuf[0] = 0; 38 | shake128_inc_absorb(state, encbuf, 1); 39 | } 40 | } 41 | 42 | void cshake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen) { 43 | shake128_inc_absorb(state, input, inlen); 44 | } 45 | 46 | void cshake128_inc_finalize(shake128incctx *state) { 47 | state->ctx[state->ctx[25] >> 3] ^= (uint64_t)0x04 << (8 * (state->ctx[25] & 0x07)); 48 | state->ctx[(SHAKE128_RATE - 1) >> 3] ^= (uint64_t)128 << (8 * ((SHAKE128_RATE - 1) & 0x07)); 49 | state->ctx[25] = 0; 50 | } 51 | 52 | void cshake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state) { 53 | shake128_inc_squeeze(output, outlen, state); 54 | } 55 | 56 | void cshake128_inc_ctx_release(shake128incctx *state) { 57 | shake128_inc_ctx_release(state); 58 | } 59 | 60 | void cshake128_inc_ctx_clone(shake128incctx *dest, const shake128incctx *src) { 61 | shake128_inc_ctx_clone(dest, src); 62 | } 63 | 64 | void cshake256_inc_init(shake256incctx *state, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen) { 65 | uint8_t encbuf[sizeof(size_t)+1]; 66 | 67 | shake256_inc_init(state); 68 | 69 | shake256_inc_absorb(state, encbuf, left_encode(encbuf, SHAKE256_RATE)); 70 | 71 | shake256_inc_absorb(state, encbuf, left_encode(encbuf, namelen * 8)); 72 | shake256_inc_absorb(state, name, namelen); 73 | 74 | shake256_inc_absorb(state, encbuf, left_encode(encbuf, cstmlen * 8)); 75 | shake256_inc_absorb(state, cstm, cstmlen); 76 | 77 | if (state->ctx[25] != 0) { 78 | state->ctx[25] = SHAKE256_RATE - 1; 79 | encbuf[0] = 0; 80 | shake256_inc_absorb(state, encbuf, 1); 81 | } 82 | } 83 | 84 | void cshake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen) { 85 | shake256_inc_absorb(state, input, inlen); 86 | } 87 | 88 | void cshake256_inc_finalize(shake256incctx *state) { 89 | state->ctx[state->ctx[25] >> 3] ^= (uint64_t)0x04 << (8 * (state->ctx[25] & 0x07)); 90 | state->ctx[(SHAKE256_RATE - 1) >> 3] ^= (uint64_t)128 << (8 * ((SHAKE256_RATE - 1) & 0x07)); 91 | state->ctx[25] = 0; 92 | } 93 | 94 | void cshake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state) { 95 | shake256_inc_squeeze(output, outlen, state); 96 | } 97 | 98 | void cshake256_inc_ctx_release(shake256incctx *state) { 99 | shake256_inc_ctx_release(state); 100 | } 101 | 102 | void cshake256_inc_ctx_clone(shake256incctx *dest, const shake256incctx *src) { 103 | shake256_inc_ctx_clone(dest, src); 104 | } 105 | 106 | /************************************************* 107 | * Name: cshake128 108 | * 109 | * Description: cSHAKE128 XOF with non-incremental API 110 | * 111 | * Arguments: - uint8_t *output: pointer to output 112 | * - size_t outlen: requested output length in bytes 113 | * - const uint8_t *name: pointer to function-name string 114 | * - size_t namelen: length of function-name string in bytes 115 | * - const uint8_t *cstm: pointer to non-empty customization string 116 | * - size_t cstmlen: length of customization string in bytes 117 | * - const uint8_t *input: pointer to input 118 | * - size_t inlen: length of input in bytes 119 | **************************************************/ 120 | void cshake128(uint8_t *output, size_t outlen, 121 | const uint8_t *name, size_t namelen, 122 | const uint8_t *cstm, size_t cstmlen, 123 | const uint8_t *input, size_t inlen) { 124 | shake128incctx state; 125 | cshake128_inc_init(&state, name, namelen, cstm, cstmlen); 126 | cshake128_inc_absorb(&state, input, inlen); 127 | cshake128_inc_finalize(&state); 128 | cshake128_inc_squeeze(output, outlen, &state); 129 | cshake128_inc_ctx_release(&state); 130 | } 131 | 132 | /************************************************* 133 | * Name: cshake256 134 | * 135 | * Description: cSHAKE256 XOF with non-incremental API 136 | * 137 | * Arguments: - uint8_t *output: pointer to output 138 | * - size_t outlen: requested output length in bytes 139 | * - const uint8_t *name: pointer to function-name string 140 | * - size_t namelen: length of function-name string in bytes 141 | * - const uint8_t *cstm: pointer to non-empty customization string 142 | * - size_t cstmlen: length of customization string in bytes 143 | * - const uint8_t *input: pointer to input 144 | * - size_t inlen: length of input in bytes 145 | **************************************************/ 146 | void cshake256(uint8_t *output, size_t outlen, 147 | const uint8_t *name, size_t namelen, 148 | const uint8_t *cstm, size_t cstmlen, 149 | const uint8_t *input, size_t inlen) { 150 | shake256incctx state; 151 | cshake256_inc_init(&state, name, namelen, cstm, cstmlen); 152 | cshake256_inc_absorb(&state, input, inlen); 153 | cshake256_inc_finalize(&state); 154 | cshake256_inc_squeeze(output, outlen, &state); 155 | cshake256_inc_ctx_release(&state); 156 | } 157 | -------------------------------------------------------------------------------- /pqcrypto-internals/include/aes.h: -------------------------------------------------------------------------------- 1 | #ifndef AES_H 2 | #define AES_H 3 | 4 | #include 5 | #include 6 | 7 | #define AES128_KEYBYTES 16 8 | #define AES192_KEYBYTES 24 9 | #define AES256_KEYBYTES 32 10 | #define AESCTR_NONCEBYTES 12 11 | #define AES_BLOCKBYTES 16 12 | 13 | // We've put these states on the heap to make sure ctx_release is used. 14 | #define PQC_AES128_STATESIZE 88 15 | typedef struct { 16 | uint64_t sk_exp[PQC_AES128_STATESIZE]; 17 | } aes128ctx; 18 | 19 | #define PQC_AES192_STATESIZE 104 20 | typedef struct { 21 | uint64_t sk_exp[PQC_AES192_STATESIZE]; 22 | } aes192ctx; 23 | 24 | #define PQC_AES256_STATESIZE 120 25 | typedef struct { 26 | uint64_t sk_exp[PQC_AES256_STATESIZE]; 27 | } aes256ctx; 28 | 29 | 30 | 31 | /** Initializes the context **/ 32 | void aes128_ecb_keyexp(aes128ctx *r, const unsigned char *key); 33 | 34 | void aes128_ctr_keyexp(aes128ctx *r, const unsigned char *key); 35 | 36 | void aes128_ecb(unsigned char *out, const unsigned char *in, size_t nblocks, const aes128ctx *ctx); 37 | 38 | void aes128_ctr(unsigned char *out, size_t outlen, const unsigned char *iv, const aes128ctx *ctx); 39 | 40 | /** Frees the context **/ 41 | void aes128_ctx_release(aes128ctx *r); 42 | 43 | 44 | /** Initializes the context **/ 45 | void aes192_ecb_keyexp(aes192ctx *r, const unsigned char *key); 46 | 47 | void aes192_ctr_keyexp(aes192ctx *r, const unsigned char *key); 48 | 49 | void aes192_ecb(unsigned char *out, const unsigned char *in, size_t nblocks, const aes192ctx *ctx); 50 | 51 | void aes192_ctr(unsigned char *out, size_t outlen, const unsigned char *iv, const aes192ctx *ctx); 52 | 53 | void aes192_ctx_release(aes192ctx *r); 54 | 55 | 56 | /** Initializes the context **/ 57 | void aes256_ecb_keyexp(aes256ctx *r, const unsigned char *key); 58 | 59 | void aes256_ctr_keyexp(aes256ctx *r, const unsigned char *key); 60 | 61 | void aes256_ecb(unsigned char *out, const unsigned char *in, size_t nblocks, const aes256ctx *ctx); 62 | 63 | void aes256_ctr(unsigned char *out, size_t outlen, const unsigned char *iv, const aes256ctx *ctx); 64 | 65 | /** Frees the context **/ 66 | void aes256_ctx_release(aes256ctx *r); 67 | 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /pqcrypto-internals/include/fips202.h: -------------------------------------------------------------------------------- 1 | #ifndef FIPS202_H 2 | #define FIPS202_H 3 | 4 | #include 5 | #include 6 | 7 | #define SHAKE128_RATE 168 8 | #define SHAKE256_RATE 136 9 | #define SHA3_256_RATE 136 10 | #define SHA3_384_RATE 104 11 | #define SHA3_512_RATE 72 12 | 13 | #define PQC_SHAKEINCCTX_BYTES (sizeof(uint64_t)*26) 14 | #define PQC_SHAKECTX_BYTES (sizeof(uint64_t)*25) 15 | 16 | // Context for incremental API 17 | typedef struct { 18 | uint64_t ctx[26]; 19 | } shake128incctx; 20 | 21 | // Context for non-incremental API 22 | typedef struct { 23 | uint64_t ctx[25]; 24 | } shake128ctx; 25 | 26 | // Context for incremental API 27 | typedef struct { 28 | uint64_t ctx[26]; 29 | } shake256incctx; 30 | 31 | // Context for non-incremental API 32 | typedef struct { 33 | uint64_t ctx[25]; 34 | } shake256ctx; 35 | 36 | // Context for incremental API 37 | typedef struct { 38 | uint64_t ctx[26]; 39 | } sha3_256incctx; 40 | 41 | // Context for incremental API 42 | typedef struct { 43 | uint64_t ctx[26]; 44 | } sha3_384incctx; 45 | 46 | // Context for incremental API 47 | typedef struct { 48 | uint64_t ctx[26]; 49 | } sha3_512incctx; 50 | 51 | /* Initialize the state and absorb the provided input. 52 | * 53 | * This function does not support being called multiple times 54 | * with the same state. 55 | */ 56 | void shake128_absorb(shake128ctx *state, const uint8_t *input, size_t inlen); 57 | /* Squeeze output out of the sponge. 58 | * 59 | * Supports being called multiple times 60 | */ 61 | void shake128_squeezeblocks(uint8_t *output, size_t nblocks, shake128ctx *state); 62 | /* Free the state */ 63 | void shake128_ctx_release(shake128ctx *state); 64 | /* Copy the state. */ 65 | void shake128_ctx_clone(shake128ctx *dest, const shake128ctx *src); 66 | 67 | /* Initialize incremental hashing API */ 68 | void shake128_inc_init(shake128incctx *state); 69 | /* Absorb more information into the XOF. 70 | * 71 | * Can be called multiple times. 72 | */ 73 | void shake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen); 74 | /* Finalize the XOF for squeezing */ 75 | void shake128_inc_finalize(shake128incctx *state); 76 | /* Squeeze output out of the sponge. 77 | * 78 | * Supports being called multiple times 79 | */ 80 | void shake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state); 81 | /* Copy the context of the SHAKE128 XOF */ 82 | void shake128_inc_ctx_clone(shake128incctx* dest, const shake128incctx *src); 83 | /* Free the context of the SHAKE128 XOF */ 84 | void shake128_inc_ctx_release(shake128incctx *state); 85 | 86 | /* Initialize the state and absorb the provided input. 87 | * 88 | * This function does not support being called multiple times 89 | * with the same state. 90 | */ 91 | void shake256_absorb(shake256ctx *state, const uint8_t *input, size_t inlen); 92 | /* Squeeze output out of the sponge. 93 | * 94 | * Supports being called multiple times 95 | */ 96 | void shake256_squeezeblocks(uint8_t *output, size_t nblocks, shake256ctx *state); 97 | /* Free the context held by this XOF */ 98 | void shake256_ctx_release(shake256ctx *state); 99 | /* Copy the context held by this XOF */ 100 | void shake256_ctx_clone(shake256ctx *dest, const shake256ctx *src); 101 | 102 | /* Initialize incremental hashing API */ 103 | void shake256_inc_init(shake256incctx *state); 104 | void shake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen); 105 | /* Prepares for squeeze phase */ 106 | void shake256_inc_finalize(shake256incctx *state); 107 | /* Squeeze output out of the sponge. 108 | * 109 | * Supports being called multiple times 110 | */ 111 | void shake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state); 112 | /* Copy the state */ 113 | void shake256_inc_ctx_clone(shake256incctx* dest, const shake256incctx *src); 114 | /* Free the state */ 115 | void shake256_inc_ctx_release(shake256incctx *state); 116 | 117 | /* One-stop SHAKE128 call */ 118 | void shake128(uint8_t *output, size_t outlen, 119 | const uint8_t *input, size_t inlen); 120 | 121 | /* One-stop SHAKE256 call */ 122 | void shake256(uint8_t *output, size_t outlen, 123 | const uint8_t *input, size_t inlen); 124 | 125 | /* Initialize the incremental hashing state */ 126 | void sha3_256_inc_init(sha3_256incctx *state); 127 | /* Absorb blocks into SHA3 */ 128 | void sha3_256_inc_absorb(sha3_256incctx *state, const uint8_t *input, size_t inlen); 129 | /* Obtain the output of the function and free `state` */ 130 | void sha3_256_inc_finalize(uint8_t *output, sha3_256incctx *state); 131 | /* Copy the context */ 132 | void sha3_256_inc_ctx_clone(sha3_256incctx *dest, const sha3_256incctx *src); 133 | /* Release the state, don't use if `_finalize` has been used */ 134 | void sha3_256_inc_ctx_release(sha3_256incctx *state); 135 | 136 | void sha3_256(uint8_t *output, const uint8_t *input, size_t inlen); 137 | 138 | /* Initialize the incremental hashing state */ 139 | void sha3_384_inc_init(sha3_384incctx *state); 140 | /* Absorb blocks into SHA3 */ 141 | void sha3_384_inc_absorb(sha3_384incctx *state, const uint8_t *input, size_t inlen); 142 | /* Obtain the output of the function and free `state` */ 143 | void sha3_384_inc_finalize(uint8_t *output, sha3_384incctx *state); 144 | /* Copy the context */ 145 | void sha3_384_inc_ctx_clone(sha3_384incctx *dest, const sha3_384incctx *src); 146 | /* Release the state, don't use if `_finalize` has been used */ 147 | void sha3_384_inc_ctx_release(sha3_384incctx *state); 148 | 149 | /* One-stop SHA3-384 shop */ 150 | void sha3_384(uint8_t *output, const uint8_t *input, size_t inlen); 151 | 152 | /* Initialize the incremental hashing state */ 153 | void sha3_512_inc_init(sha3_512incctx *state); 154 | /* Absorb blocks into SHA3 */ 155 | void sha3_512_inc_absorb(sha3_512incctx *state, const uint8_t *input, size_t inlen); 156 | /* Obtain the output of the function and free `state` */ 157 | void sha3_512_inc_finalize(uint8_t *output, sha3_512incctx *state); 158 | /* Copy the context */ 159 | void sha3_512_inc_ctx_clone(sha3_512incctx *dest, const sha3_512incctx *src); 160 | /* Release the state, don't use if `_finalize` has been used */ 161 | void sha3_512_inc_ctx_release(sha3_512incctx *state); 162 | 163 | /* One-stop SHA3-512 shop */ 164 | void sha3_512(uint8_t *output, const uint8_t *input, size_t inlen); 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /pqcrypto-internals/include/nistseedexpander.h: -------------------------------------------------------------------------------- 1 | #ifndef NISTSEEDEXPANDER_H 2 | #define NISTSEEDEXPANDER_H 3 | 4 | // 5 | // rng.h 6 | // 7 | // Created by Bassham, Lawrence E (Fed) on 8/29/17. 8 | // Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. 9 | // Modified for PQClean by Sebastian Verschoor 10 | // 11 | 12 | #include 13 | #include 14 | 15 | #define NISTSEEDEXPANDER_SEED_LEN 32 16 | 17 | #define RNG_SUCCESS ( 0) 18 | #define RNG_BAD_MAXLEN (-1) 19 | #define RNG_BAD_OUTBUF (-2) 20 | #define RNG_BAD_REQ_LEN (-3) 21 | 22 | typedef struct { 23 | uint8_t buffer[16]; 24 | size_t buffer_pos; 25 | size_t length_remaining; 26 | uint8_t key[NISTSEEDEXPANDER_SEED_LEN]; 27 | uint8_t ctr[16]; 28 | } AES_XOF_struct; 29 | 30 | int 31 | seedexpander_init(AES_XOF_struct *ctx, 32 | const uint8_t *seed, 33 | const uint8_t *diversifier, 34 | size_t maxlen); 35 | 36 | int 37 | seedexpander(AES_XOF_struct *ctx, uint8_t *x, size_t xlen); 38 | 39 | #endif /* NISTSEEDEXPANDER_H */ 40 | -------------------------------------------------------------------------------- /pqcrypto-internals/include/randombytes.h: -------------------------------------------------------------------------------- 1 | #ifndef RANDOMBYTES_H 2 | #define RANDOMBYTES_H 3 | #include 4 | 5 | #ifdef _WIN32 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | #define randombytes PQCRYPTO_RUST_randombytes 12 | int randombytes(uint8_t *buf, size_t n); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /pqcrypto-internals/include/sha2.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA2_H 2 | #define SHA2_H 3 | 4 | #include 5 | #include 6 | 7 | /* The incremental API allows hashing of individual input blocks; these blocks 8 | must be exactly 64 bytes each. 9 | Use the 'finalize' functions for any remaining bytes (possibly over 64). */ 10 | 11 | #define PQC_SHA256CTX_BYTES 40 12 | /* Structure for the incremental API */ 13 | typedef struct { 14 | uint8_t ctx[PQC_SHA256CTX_BYTES]; 15 | } sha224ctx; 16 | 17 | /* Structure for the incremental API */ 18 | typedef struct { 19 | uint8_t ctx[PQC_SHA256CTX_BYTES]; 20 | } sha256ctx; 21 | 22 | #define PQC_SHA512CTX_BYTES 72 23 | /* Structure for the incremental API */ 24 | typedef struct { 25 | uint8_t ctx[PQC_SHA512CTX_BYTES]; 26 | } sha384ctx; 27 | 28 | /* Structure for the incremental API */ 29 | typedef struct { 30 | uint8_t ctx[PQC_SHA512CTX_BYTES]; 31 | } sha512ctx; 32 | 33 | /* ====== SHA224 API ==== */ 34 | 35 | /** 36 | * Initialize the incremental hashing API. 37 | * 38 | * Can't be called multiple times. 39 | */ 40 | void sha224_inc_init(sha224ctx *state); 41 | 42 | /** 43 | * Copy the hashing state 44 | */ 45 | void sha224_inc_ctx_clone(sha224ctx *stateout, const sha224ctx *statein); 46 | 47 | /** 48 | * Absorb blocks 49 | */ 50 | void sha224_inc_blocks(sha224ctx *state, const uint8_t *in, size_t inblocks); 51 | 52 | /** 53 | * Finalize and obtain the digest 54 | * 55 | * If applicable, this function will free the memory associated with the sha224ctx. 56 | * 57 | * If not calling this function, call `sha224_inc_ctx_release` 58 | */ 59 | void sha224_inc_finalize(uint8_t *out, sha224ctx *state, const uint8_t *in, size_t inlen); 60 | 61 | /** 62 | * Destroy the state. Make sure to use this, as this API may not always be stack-based. 63 | */ 64 | void sha224_inc_ctx_release(sha224ctx *state); 65 | 66 | /** 67 | * All-in-one sha224 function 68 | */ 69 | void sha224(uint8_t *out, const uint8_t *in, size_t inlen); 70 | 71 | /* ====== SHA256 API ==== */ 72 | 73 | /** 74 | * Initialize the incremental hashing API 75 | */ 76 | void sha256_inc_init(sha256ctx *state); 77 | 78 | /** 79 | * Copy the hashing state 80 | */ 81 | void sha256_inc_ctx_clone(sha256ctx *stateout, const sha256ctx *statein); 82 | 83 | /** 84 | * Absorb blocks 85 | */ 86 | void sha256_inc_blocks(sha256ctx *state, const uint8_t *in, size_t inblocks); 87 | 88 | /** 89 | * Finalize and obtain the digest 90 | * 91 | * If applicable, this function will free the memory associated with the sha256ctx. 92 | */ 93 | void sha256_inc_finalize(uint8_t *out, sha256ctx *state, const uint8_t *in, size_t inlen); 94 | 95 | /** 96 | * Destroy the state. Make sure to use this, as this API may not always be stack-based. 97 | */ 98 | void sha256_inc_ctx_release(sha256ctx *state); 99 | 100 | /** 101 | * All-in-one sha256 function 102 | */ 103 | void sha256(uint8_t *out, const uint8_t *in, size_t inlen); 104 | 105 | /* ====== SHA384 API ==== */ 106 | 107 | /** 108 | * Initialize the incremental hashing API 109 | */ 110 | void sha384_inc_init(sha384ctx *state); 111 | 112 | /** 113 | * Copy the hashing state 114 | */ 115 | void sha384_inc_ctx_clone(sha384ctx *stateout, const sha384ctx *statein); 116 | 117 | /** 118 | * Absorb blocks 119 | */ 120 | void sha384_inc_blocks(sha384ctx *state, const uint8_t *in, size_t inblocks); 121 | 122 | /** 123 | * Finalize and obtain the digest. 124 | * 125 | * If applicable, this function will free the memory associated with the sha384ctx. 126 | */ 127 | void sha384_inc_finalize(uint8_t *out, sha384ctx *state, const uint8_t *in, size_t inlen); 128 | 129 | /** 130 | * Destroy the state. Make sure to use this if not calling finalize, as this API may not always be stack-based. 131 | */ 132 | void sha384_inc_ctx_release(sha384ctx *state); 133 | 134 | /** 135 | * All-in-one sha384 function 136 | */ 137 | void sha384(uint8_t *out, const uint8_t *in, size_t inlen); 138 | 139 | 140 | /* ====== SHA512 API ==== */ 141 | 142 | /** 143 | * Initialize the incremental hashing API 144 | */ 145 | void sha512_inc_init(sha512ctx *state); 146 | 147 | /** 148 | * Copy the hashing state 149 | */ 150 | void sha512_inc_ctx_clone(sha512ctx *stateout, const sha512ctx *statein); 151 | 152 | /** 153 | * Absorb blocks 154 | */ 155 | void sha512_inc_blocks(sha512ctx *state, const uint8_t *in, size_t inblocks); 156 | 157 | /** 158 | * Finalize and obtain the digest 159 | * 160 | * If applicable, this function will free the memory associated with the sha512ctx. 161 | */ 162 | void sha512_inc_finalize(uint8_t *out, sha512ctx *state, const uint8_t *in, size_t inlen); 163 | 164 | /** 165 | * Destroy the state. Make sure to use this if not calling finalize, as this API may not always be stack-based. 166 | */ 167 | void sha512_inc_ctx_release(sha512ctx *state); 168 | 169 | /** 170 | * All-in-one sha512 function 171 | */ 172 | void sha512(uint8_t *out, const uint8_t *in, size_t inlen); 173 | 174 | #endif 175 | -------------------------------------------------------------------------------- /pqcrypto-internals/include/sp800-185.h: -------------------------------------------------------------------------------- 1 | #ifndef SP800_185_H 2 | #define SP800_185_H 3 | 4 | #include 5 | #include 6 | 7 | #include "fips202.h" 8 | 9 | void cshake128_inc_init(shake128incctx *state, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen); 10 | void cshake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen); 11 | void cshake128_inc_finalize(shake128incctx *state); 12 | void cshake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state); 13 | void cshake128_inc_ctx_release(shake128incctx *state); 14 | void cshake128_inc_ctx_clone(shake128incctx *dest, const shake128incctx *src); 15 | 16 | void cshake128(uint8_t *output, size_t outlen, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen, const uint8_t *input, size_t inlen); 17 | 18 | void cshake256_inc_init(shake256incctx *state, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen); 19 | void cshake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen); 20 | void cshake256_inc_finalize(shake256incctx *state); 21 | void cshake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state); 22 | void cshake256_inc_ctx_release(shake256incctx *state); 23 | void cshake256_inc_ctx_clone(shake256incctx *dest, const shake256incctx *src); 24 | 25 | void cshake256(uint8_t *output, size_t outlen, const uint8_t *name, size_t namelen, const uint8_t* cstm, size_t cstmlen, const uint8_t *input, size_t inlen); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /pqcrypto-internals/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | use core::slice; 4 | 5 | /// Get random bytes; exposed for PQClean implementations. 6 | /// 7 | /// # Safety 8 | /// Assumes inputs are valid and may panic over FFI boundary if rng failed. 9 | /// 10 | /// # Example 11 | /// ```rust 12 | /// use pqcrypto_internals::*; 13 | /// let mut buf = [0u8;10]; 14 | /// unsafe { 15 | /// PQCRYPTO_RUST_randombytes(buf.as_mut_ptr(), buf.len()); 16 | /// } 17 | /// ``` 18 | #[no_mangle] 19 | pub unsafe extern "C" fn PQCRYPTO_RUST_randombytes(buf: *mut u8, len: libc::size_t) -> libc::c_int { 20 | let buf = slice::from_raw_parts_mut(buf, len); 21 | getrandom::fill(buf).expect("RNG Failed"); 22 | 0 23 | } 24 | -------------------------------------------------------------------------------- /pqcrypto-mldsa/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pqcrypto-mldsa" 3 | description = "Post-Quantum Signature Scheme mldsa" 4 | readme = "README.md" 5 | version = "0.1.1" 6 | authors = ["Thom Wiggers "] 7 | edition = "2021" 8 | license = "MIT OR Apache-2.0" 9 | homepage = "https://github.com/rustpq/" 10 | repository = "https://github.com/rustpq/pqcrypto/" 11 | keywords = ["cryptography", "post-quantum", "security"] 12 | categories = ["cryptography", "no-std"] 13 | 14 | [dependencies] 15 | pqcrypto-internals = { path = "../pqcrypto-internals", version = "0.2.6" } 16 | pqcrypto-traits = { path = "../pqcrypto-traits", version = "0.3.5", default-features = false } 17 | libc = "0.2.0" 18 | serde = { version = "1.0", features = ["derive"], optional = true } 19 | serde-big-array = { version = "0.5.1", optional = true } 20 | paste = "1.0" 21 | 22 | [features] 23 | default = ["avx2", "neon", "std"] 24 | avx2 = ["std"] 25 | neon = ["std"] 26 | std = ["pqcrypto-traits/std"] 27 | serialization = ["serde", "serde-big-array"] 28 | 29 | [dev-dependencies] 30 | rand = "0.8.5" 31 | 32 | [build-dependencies] 33 | cc = { version = "1.0", features = ["parallel"] } 34 | glob = "0.3.0" 35 | 36 | [badges] 37 | travis-ci = { repository = "rustpq/pqcrypto", branch = "master" } 38 | maintenance = { status = "actively-developed" } 39 | 40 | -------------------------------------------------------------------------------- /pqcrypto-mldsa/README.md: -------------------------------------------------------------------------------- 1 | # mldsa 2 | 3 | 4 | This crate contains bindings to the C implementations of the following schemes, 5 | from [PQClean][pqclean]. 6 | 7 | This project packages Post-Quantum cryptographic algorithms that participate in 8 | the [NIST PQC standardization effort][nistpqc]. It is currently a collection of 9 | wrappers around C implementations from the [PQClean][pqclean] project. 10 | 11 | ## Serialization 12 | 13 | If you want `serde` support, enable the `serialization` feature. 14 | 15 | ## Included implementations from PQClean 16 | 17 | Below is a list of the included schemes and the corresponding implementations 18 | sourced from [PQClean][pqclean]. The "default" implementation is used in the 19 | Rust-friendly interface, alternative implementations are exposed as ``ffi`` 20 | methods only. 21 | 22 | * ``ml-dsa-44`` 23 | * ``clean`` 24 | * ``avx2`` (if supported) 25 | * ``aarch64`` (if supported) 26 | * ``ml-dsa-65`` 27 | * ``clean`` 28 | * ``avx2`` (if supported) 29 | * ``aarch64`` (if supported) 30 | * ``ml-dsa-87`` 31 | * ``clean`` 32 | * ``avx2`` (if supported) 33 | * ``aarch64`` (if supported) 34 | 35 | 36 | ## License 37 | 38 | The wrappers and wrapper generation scripts in this project are covered by the 39 | MIT or Apache 2.0 licenses, at your choice. 40 | 41 | The implementations we link to are not, however. Please see the [PQClean][pqclean] 42 | project for the appropriate licenses. 43 | 44 | [pqclean]: https://github.com/PQClean/PQClean/ 45 | [nistpqc]: https://nist.gov/pqc/ -------------------------------------------------------------------------------- /pqcrypto-mldsa/build.rs: -------------------------------------------------------------------------------- 1 | extern crate cc; 2 | extern crate glob; 3 | 4 | use std::env; 5 | use std::path::{Path, PathBuf}; 6 | 7 | macro_rules! build_clean { 8 | ($variant:expr) => { 9 | let internals_include_path = &std::env::var("DEP_PQCRYPTO_INTERNALS_INCLUDEPATH").unwrap(); 10 | let common_dir = Path::new("pqclean/common"); 11 | 12 | let mut builder = cc::Build::new(); 13 | let target_dir: PathBuf = ["pqclean", "crypto_sign", $variant, "clean"] 14 | .iter() 15 | .collect(); 16 | 17 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 18 | if target_os == "wasi" { 19 | let wasi_sdk_path = 20 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 21 | builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str()); 22 | } 23 | 24 | let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap(); 25 | 26 | builder 27 | .include(internals_include_path) 28 | .include(&common_dir) 29 | .include(target_dir) 30 | .files( 31 | scheme_files 32 | .into_iter() 33 | .map(|p| p.unwrap().to_string_lossy().into_owned()), 34 | ); 35 | builder.compile(format!("{}_clean", $variant).as_str()); 36 | }; 37 | } 38 | 39 | macro_rules! build_avx2 { 40 | ($variant:expr) => { 41 | let internals_include_path = &std::env::var("DEP_PQCRYPTO_INTERNALS_INCLUDEPATH").unwrap(); 42 | let common_dir = Path::new("pqclean/common"); 43 | 44 | let mut builder = cc::Build::new(); 45 | let target_dir: PathBuf = ["pqclean", "crypto_sign", $variant, "avx2"] 46 | .iter() 47 | .collect(); 48 | 49 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 50 | if target_os == "wasi" { 51 | let wasi_sdk_path = 52 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 53 | builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str()); 54 | } 55 | 56 | let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap(); 57 | let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); 58 | if target_env == "msvc" { 59 | builder.flag("/arch:AVX2"); 60 | } else { 61 | builder 62 | .flag("-mavx2") 63 | .flag("-mbmi2") 64 | .flag("-mbmi") 65 | .flag("-maes") 66 | .flag("-mpopcnt") 67 | .flag("-mpclmul"); 68 | } 69 | 70 | builder 71 | .include(internals_include_path) 72 | .include(&common_dir) 73 | .include(target_dir) 74 | .files( 75 | scheme_files 76 | .into_iter() 77 | .map(|p| p.unwrap().to_string_lossy().into_owned()), 78 | ); 79 | builder.compile(format!("{}_avx2", $variant).as_str()); 80 | }; 81 | } 82 | 83 | macro_rules! build_aarch64 { 84 | ($variant:expr) => { 85 | let internals_include_path = &std::env::var("DEP_PQCRYPTO_INTERNALS_INCLUDEPATH").unwrap(); 86 | let common_dir = Path::new("pqclean/common"); 87 | 88 | let mut builder = cc::Build::new(); 89 | let target_dir: PathBuf = ["pqclean", "crypto_sign", $variant, "aarch64"] 90 | .iter() 91 | .collect(); 92 | 93 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 94 | if target_os == "wasi" { 95 | let wasi_sdk_path = 96 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 97 | builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str()); 98 | } 99 | 100 | let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap(); 101 | builder.flag("-march=armv8-a"); 102 | 103 | builder 104 | .include(internals_include_path) 105 | .include(&common_dir) 106 | .include(target_dir) 107 | .files( 108 | scheme_files 109 | .into_iter() 110 | .map(|p| p.unwrap().to_string_lossy().into_owned()), 111 | ); 112 | builder.compile(format!("{}_aarch64", $variant).as_str()); 113 | }; 114 | } 115 | 116 | fn main() { 117 | #[allow(unused_variables)] 118 | let aes_enabled = env::var("CARGO_FEATURE_AES").is_ok(); 119 | #[allow(unused_variables)] 120 | let avx2_enabled = env::var("CARGO_FEATURE_AVX2").is_ok(); 121 | #[allow(unused_variables)] 122 | let neon_enabled = env::var("CARGO_FEATURE_NEON").is_ok(); 123 | #[allow(unused_variables)] 124 | let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); 125 | #[allow(unused_variables)] 126 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 127 | #[allow(unused_variables)] 128 | let is_windows = target_os == "windows"; 129 | #[allow(unused_variables)] 130 | let is_macos = target_os == "macos"; 131 | 132 | build_clean!("ml-dsa-44"); 133 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 134 | build_avx2!("ml-dsa-44"); 135 | } 136 | if target_arch == "aarch64" && neon_enabled { 137 | build_aarch64!("ml-dsa-44"); 138 | } 139 | build_clean!("ml-dsa-65"); 140 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 141 | build_avx2!("ml-dsa-65"); 142 | } 143 | if target_arch == "aarch64" && neon_enabled { 144 | build_aarch64!("ml-dsa-65"); 145 | } 146 | build_clean!("ml-dsa-87"); 147 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 148 | build_avx2!("ml-dsa-87"); 149 | } 150 | if target_arch == "aarch64" && neon_enabled { 151 | build_aarch64!("ml-dsa-87"); 152 | } 153 | 154 | println!("cargo::rustc-check-cfg=cfg(enable_x86_avx2)"); 155 | if target_arch == "x86_64" && avx2_enabled && !is_windows { 156 | // Print enableing flag for AVX2 implementation 157 | println!("cargo:rustc-cfg=enable_x86_avx2"); 158 | } 159 | println!("cargo::rustc-check-cfg=cfg(enable_aarch64_neon)"); 160 | if target_arch == "aarch64" && neon_enabled { 161 | // Print enableing flag for AARCH64 implementation 162 | println!("cargo:rustc-cfg=enable_aarch64_neon"); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /pqcrypto-mldsa/pqclean: -------------------------------------------------------------------------------- 1 | ../pqclean -------------------------------------------------------------------------------- /pqcrypto-mldsa/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # mldsa 2 | //! 3 | //! This crate provides bindings to and wrappers around the following 4 | //! implementations from [PQClean][pqc]: 5 | //! 6 | //! * ml-dsa-44 - clean 7 | //! * ml-dsa-65 - clean 8 | //! * ml-dsa-87 - clean 9 | //! 10 | //! [pqc]: https://github.com/pqclean/pqclean/ 11 | //! 12 | 13 | #![no_std] 14 | #![allow(clippy::len_without_is_empty)] 15 | 16 | // For no-std vectors 17 | extern crate alloc; 18 | 19 | // For tests 20 | #[cfg(feature = "std")] 21 | extern crate std; 22 | 23 | pub mod ffi; 24 | pub mod mldsa44; 25 | pub mod mldsa65; 26 | pub mod mldsa87; 27 | 28 | pub use crate::mldsa44::{ 29 | detached_sign as mldsa44_detached_sign, detached_sign_ctx as mldsa44_detached_sign_ctx, 30 | keypair as mldsa44_keypair, open as mldsa44_open, open_ctx as mldsa44_open_ctx, 31 | public_key_bytes as mldsa44_public_key_bytes, secret_key_bytes as mldsa44_secret_key_bytes, 32 | sign as mldsa44_sign, sign_ctx as mldsa44_sign_ctx, signature_bytes as mldsa44_signature_bytes, 33 | verify_detached_signature as mldsa44_verify_detached_signature, 34 | verify_detached_signature_ctx as mldsa44_verify_detached_signature_ctx, 35 | }; 36 | pub use crate::mldsa65::{ 37 | detached_sign as mldsa65_detached_sign, detached_sign_ctx as mldsa65_detached_sign_ctx, 38 | keypair as mldsa65_keypair, open as mldsa65_open, open_ctx as mldsa65_open_ctx, 39 | public_key_bytes as mldsa65_public_key_bytes, secret_key_bytes as mldsa65_secret_key_bytes, 40 | sign as mldsa65_sign, sign_ctx as mldsa65_sign_ctx, signature_bytes as mldsa65_signature_bytes, 41 | verify_detached_signature as mldsa65_verify_detached_signature, 42 | verify_detached_signature_ctx as mldsa65_verify_detached_signature_ctx, 43 | }; 44 | pub use crate::mldsa87::{ 45 | detached_sign as mldsa87_detached_sign, detached_sign_ctx as mldsa87_detached_sign_ctx, 46 | keypair as mldsa87_keypair, open as mldsa87_open, open_ctx as mldsa87_open_ctx, 47 | public_key_bytes as mldsa87_public_key_bytes, secret_key_bytes as mldsa87_secret_key_bytes, 48 | sign as mldsa87_sign, sign_ctx as mldsa87_sign_ctx, signature_bytes as mldsa87_signature_bytes, 49 | verify_detached_signature as mldsa87_verify_detached_signature, 50 | verify_detached_signature_ctx as mldsa87_verify_detached_signature_ctx, 51 | }; 52 | -------------------------------------------------------------------------------- /pqcrypto-mlkem/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pqcrypto-mlkem" 3 | description = "Post-Quantum Key-Encapsulation Mechanism mlkem" 4 | readme = "README.md" 5 | version = "0.1.0" 6 | authors = ["Thom Wiggers "] 7 | edition = "2021" 8 | license = "MIT OR Apache-2.0" 9 | homepage = "https://github.com/rustpq/" 10 | repository = "https://github.com/rustpq/pqcrypto/" 11 | keywords = ["cryptography", "post-quantum", "security"] 12 | categories = ["cryptography", "no-std"] 13 | 14 | [dependencies] 15 | pqcrypto-internals = { path = "../pqcrypto-internals", version = "0.2.6" } 16 | pqcrypto-traits = { path = "../pqcrypto-traits", version = "0.3.5", default-features = false } 17 | libc = "0.2.0" 18 | serde = { version = "1.0", features = ["derive"], optional = true } 19 | serde-big-array = { version = "0.5.1", optional = true } 20 | 21 | [features] 22 | default = ["avx2", "neon", "std"] 23 | avx2 = ["std"] 24 | neon = ["std"] 25 | std = ["pqcrypto-traits/std"] 26 | serialization = ["serde", "serde-big-array"] 27 | 28 | [dev-dependencies] 29 | 30 | [build-dependencies] 31 | cc = { version = "1.0", features = ["parallel"] } 32 | glob = "0.3.0" 33 | 34 | [badges] 35 | travis-ci = { repository = "rustpq/pqcrypto", branch = "master" } 36 | maintenance = { status = "actively-developed" } 37 | 38 | -------------------------------------------------------------------------------- /pqcrypto-mlkem/README.md: -------------------------------------------------------------------------------- 1 | # mlkem 2 | 3 | 4 | This crate contains bindings to the C implementations of the following schemes, 5 | from [PQClean][pqclean]. 6 | 7 | This project packages Post-Quantum cryptographic algorithms that participate in 8 | the [NIST PQC standardization effort][nistpqc]. It is currently a collection of 9 | wrappers around C implementations from the [PQClean][pqclean] project. 10 | 11 | ## Serialization 12 | 13 | If you want `serde` support, enable the `serialization` feature. 14 | 15 | ## Included implementations from PQClean 16 | 17 | Below is a list of the included schemes and the corresponding implementations 18 | sourced from [PQClean][pqclean]. The "default" implementation is used in the 19 | Rust-friendly interface, alternative implementations are exposed as ``ffi`` 20 | methods only. 21 | 22 | * ``ml-kem-512`` 23 | * ``clean`` 24 | * ``avx2`` (if supported) 25 | * ``aarch64`` (if supported) 26 | * ``ml-kem-768`` 27 | * ``clean`` 28 | * ``avx2`` (if supported) 29 | * ``aarch64`` (if supported) 30 | * ``ml-kem-1024`` 31 | * ``clean`` 32 | * ``avx2`` (if supported) 33 | * ``aarch64`` (if supported) 34 | 35 | 36 | ## License 37 | 38 | The wrappers and wrapper generation scripts in this project are covered by the 39 | MIT or Apache 2.0 licenses, at your choice. 40 | 41 | The implementations we link to are not, however. Please see the [PQClean][pqclean] 42 | project for the appropriate licenses. 43 | 44 | [pqclean]: https://github.com/PQClean/PQClean/ 45 | [nistpqc]: https://nist.gov/pqc/ -------------------------------------------------------------------------------- /pqcrypto-mlkem/build.rs: -------------------------------------------------------------------------------- 1 | extern crate cc; 2 | extern crate glob; 3 | 4 | use std::env; 5 | use std::path::{Path, PathBuf}; 6 | 7 | macro_rules! build_clean { 8 | ($variant:expr) => { 9 | let internals_include_path = &std::env::var("DEP_PQCRYPTO_INTERNALS_INCLUDEPATH").unwrap(); 10 | let common_dir = Path::new("pqclean/common"); 11 | 12 | let mut builder = cc::Build::new(); 13 | let target_dir: PathBuf = ["pqclean", "crypto_kem", $variant, "clean"] 14 | .iter() 15 | .collect(); 16 | 17 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 18 | if target_os == "wasi" { 19 | let wasi_sdk_path = 20 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 21 | builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str()); 22 | } 23 | 24 | let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap(); 25 | 26 | builder 27 | .include(internals_include_path) 28 | .include(&common_dir) 29 | .include(target_dir) 30 | .files( 31 | scheme_files 32 | .into_iter() 33 | .map(|p| p.unwrap().to_string_lossy().into_owned()), 34 | ); 35 | builder.compile(format!("{}_clean", $variant).as_str()); 36 | }; 37 | } 38 | 39 | macro_rules! build_avx2 { 40 | ($variant:expr) => { 41 | let internals_include_path = &std::env::var("DEP_PQCRYPTO_INTERNALS_INCLUDEPATH").unwrap(); 42 | let common_dir = Path::new("pqclean/common"); 43 | 44 | let mut builder = cc::Build::new(); 45 | let target_dir: PathBuf = ["pqclean", "crypto_kem", $variant, "avx2"].iter().collect(); 46 | 47 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 48 | if target_os == "wasi" { 49 | let wasi_sdk_path = 50 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 51 | builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str()); 52 | } 53 | 54 | let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap(); 55 | let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); 56 | if target_env == "msvc" { 57 | builder.flag("/arch:AVX2"); 58 | } else { 59 | builder 60 | .flag("-mavx2") 61 | .flag("-mbmi2") 62 | .flag("-mbmi") 63 | .flag("-maes") 64 | .flag("-mpopcnt") 65 | .flag("-mpclmul"); 66 | } 67 | 68 | builder 69 | .include(internals_include_path) 70 | .include(&common_dir) 71 | .include(target_dir) 72 | .files( 73 | scheme_files 74 | .into_iter() 75 | .map(|p| p.unwrap().to_string_lossy().into_owned()), 76 | ); 77 | builder.compile(format!("{}_avx2", $variant).as_str()); 78 | }; 79 | } 80 | 81 | macro_rules! build_aarch64 { 82 | ($variant:expr) => { 83 | let internals_include_path = &std::env::var("DEP_PQCRYPTO_INTERNALS_INCLUDEPATH").unwrap(); 84 | let common_dir = Path::new("pqclean/common"); 85 | 86 | let mut builder = cc::Build::new(); 87 | let target_dir: PathBuf = ["pqclean", "crypto_kem", $variant, "aarch64"] 88 | .iter() 89 | .collect(); 90 | 91 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 92 | if target_os == "wasi" { 93 | let wasi_sdk_path = 94 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 95 | builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str()); 96 | } 97 | 98 | let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap(); 99 | builder.flag("-march=armv8-a"); 100 | 101 | builder 102 | .include(internals_include_path) 103 | .include(&common_dir) 104 | .include(target_dir) 105 | .files( 106 | scheme_files 107 | .into_iter() 108 | .map(|p| p.unwrap().to_string_lossy().into_owned()), 109 | ); 110 | builder.compile(format!("{}_aarch64", $variant).as_str()); 111 | }; 112 | } 113 | 114 | fn main() { 115 | #[allow(unused_variables)] 116 | let aes_enabled = env::var("CARGO_FEATURE_AES").is_ok(); 117 | #[allow(unused_variables)] 118 | let avx2_enabled = env::var("CARGO_FEATURE_AVX2").is_ok(); 119 | #[allow(unused_variables)] 120 | let neon_enabled = env::var("CARGO_FEATURE_NEON").is_ok(); 121 | #[allow(unused_variables)] 122 | let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); 123 | #[allow(unused_variables)] 124 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 125 | #[allow(unused_variables)] 126 | let is_windows = target_os == "windows"; 127 | #[allow(unused_variables)] 128 | let is_macos = target_os == "macos"; 129 | 130 | build_clean!("ml-kem-512"); 131 | if target_arch == "x86_64" && avx2_enabled && !is_windows && !is_macos { 132 | build_avx2!("ml-kem-512"); 133 | } 134 | if target_arch == "aarch64" && neon_enabled { 135 | build_aarch64!("ml-kem-512"); 136 | } 137 | build_clean!("ml-kem-768"); 138 | if target_arch == "x86_64" && avx2_enabled && !is_windows && !is_macos { 139 | build_avx2!("ml-kem-768"); 140 | } 141 | if target_arch == "aarch64" && neon_enabled { 142 | build_aarch64!("ml-kem-768"); 143 | } 144 | build_clean!("ml-kem-1024"); 145 | if target_arch == "x86_64" && avx2_enabled && !is_windows && !is_macos { 146 | build_avx2!("ml-kem-1024"); 147 | } 148 | if target_arch == "aarch64" && neon_enabled { 149 | build_aarch64!("ml-kem-1024"); 150 | } 151 | 152 | println!("cargo::rustc-check-cfg=cfg(enable_x86_avx2)"); 153 | if target_arch == "x86_64" && avx2_enabled && !is_windows && !is_macos { 154 | // Print enableing flag for AVX2 implementation 155 | println!("cargo:rustc-cfg=enable_x86_avx2"); 156 | } 157 | println!("cargo::rustc-check-cfg=cfg(enable_aarch64_neon)"); 158 | if target_arch == "aarch64" && neon_enabled { 159 | // Print enableing flag for AARCH64 implementation 160 | println!("cargo:rustc-cfg=enable_aarch64_neon"); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /pqcrypto-mlkem/pqclean: -------------------------------------------------------------------------------- 1 | ../pqclean -------------------------------------------------------------------------------- /pqcrypto-mlkem/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # mlkem 2 | //! 3 | //! This crate provides bindings to and wrappers around the following 4 | //! implementations from [PQClean][pqc]: 5 | //! 6 | //! * ml-kem-512 - clean 7 | //! * ml-kem-768 - clean 8 | //! * ml-kem-1024 - clean 9 | //! 10 | //! [pqc]: https://github.com/pqclean/pqclean/ 11 | //! 12 | 13 | #![no_std] 14 | #![allow(clippy::len_without_is_empty)] 15 | 16 | // For no-std vectors 17 | extern crate alloc; 18 | 19 | // For tests 20 | #[cfg(feature = "std")] 21 | extern crate std; 22 | 23 | pub mod ffi; 24 | pub mod mlkem1024; 25 | pub mod mlkem512; 26 | pub mod mlkem768; 27 | 28 | pub use crate::mlkem1024::{ 29 | ciphertext_bytes as mlkem1024_ciphertext_bytes, decapsulate as mlkem1024_decapsulate, 30 | encapsulate as mlkem1024_encapsulate, keypair as mlkem1024_keypair, 31 | public_key_bytes as mlkem1024_public_key_bytes, secret_key_bytes as mlkem1024_secret_key_bytes, 32 | shared_secret_bytes as mlkem1024_shared_secret_bytes, 33 | }; 34 | pub use crate::mlkem512::{ 35 | ciphertext_bytes as mlkem512_ciphertext_bytes, decapsulate as mlkem512_decapsulate, 36 | encapsulate as mlkem512_encapsulate, keypair as mlkem512_keypair, 37 | public_key_bytes as mlkem512_public_key_bytes, secret_key_bytes as mlkem512_secret_key_bytes, 38 | shared_secret_bytes as mlkem512_shared_secret_bytes, 39 | }; 40 | pub use crate::mlkem768::{ 41 | ciphertext_bytes as mlkem768_ciphertext_bytes, decapsulate as mlkem768_decapsulate, 42 | encapsulate as mlkem768_encapsulate, keypair as mlkem768_keypair, 43 | public_key_bytes as mlkem768_public_key_bytes, secret_key_bytes as mlkem768_secret_key_bytes, 44 | shared_secret_bytes as mlkem768_shared_secret_bytes, 45 | }; 46 | -------------------------------------------------------------------------------- /pqcrypto-sphincsplus/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pqcrypto-sphincsplus" 3 | description = "Post-Quantum Signature Scheme sphincsplus" 4 | readme = "README.md" 5 | version = "0.7.1" 6 | authors = ["Thom Wiggers "] 7 | edition = "2021" 8 | license = "MIT OR Apache-2.0" 9 | homepage = "https://github.com/rustpq/" 10 | repository = "https://github.com/rustpq/pqcrypto/" 11 | keywords = ["cryptography", "post-quantum", "security"] 12 | categories = ["cryptography", "no-std"] 13 | 14 | [dependencies] 15 | pqcrypto-internals = { path = "../pqcrypto-internals", version = "0.2.6" } 16 | pqcrypto-traits = { path = "../pqcrypto-traits", version = "0.3.5", default-features = false } 17 | libc = "0.2.0" 18 | serde = { version = "1.0", features = ["derive"], optional = true } 19 | serde-big-array = { version = "0.5.1", optional = true } 20 | 21 | [features] 22 | default = ["avx2", "std"] 23 | avx2 = ["std"] 24 | std = ["pqcrypto-traits/std"] 25 | serialization = ["serde", "serde-big-array"] 26 | 27 | [dev-dependencies] 28 | rand = "0.8.5" 29 | 30 | [build-dependencies] 31 | cc = { version = "1.0", features = ["parallel"] } 32 | glob = "0.3.0" 33 | 34 | [badges] 35 | travis-ci = { repository = "rustpq/pqcrypto", branch = "master" } 36 | maintenance = { status = "actively-developed" } 37 | 38 | -------------------------------------------------------------------------------- /pqcrypto-sphincsplus/README.md: -------------------------------------------------------------------------------- 1 | # sphincsplus 2 | 3 | 4 | This crate contains bindings to the C implementations of the following schemes, 5 | from [PQClean][pqclean]. 6 | 7 | This project packages Post-Quantum cryptographic algorithms that participate in 8 | the [NIST PQC standardization effort][nistpqc]. It is currently a collection of 9 | wrappers around C implementations from the [PQClean][pqclean] project. 10 | 11 | ## Serialization 12 | 13 | If you want `serde` support, enable the `serialization` feature. 14 | 15 | ## Included implementations from PQClean 16 | 17 | Below is a list of the included schemes and the corresponding implementations 18 | sourced from [PQClean][pqclean]. The "default" implementation is used in the 19 | Rust-friendly interface, alternative implementations are exposed as ``ffi`` 20 | methods only. 21 | 22 | * ``sphincs-shake-128f-simple`` 23 | * ``clean`` 24 | * ``avx2`` (if supported) 25 | * ``sphincs-shake-128s-simple`` 26 | * ``clean`` 27 | * ``avx2`` (if supported) 28 | * ``sphincs-shake-192f-simple`` 29 | * ``clean`` 30 | * ``avx2`` (if supported) 31 | * ``sphincs-shake-192s-simple`` 32 | * ``clean`` 33 | * ``avx2`` (if supported) 34 | * ``sphincs-shake-256f-simple`` 35 | * ``clean`` 36 | * ``avx2`` (if supported) 37 | * ``sphincs-shake-256s-simple`` 38 | * ``clean`` 39 | * ``avx2`` (if supported) 40 | * ``sphincs-sha2-128f-simple`` 41 | * ``clean`` 42 | * ``avx2`` (if supported) 43 | * ``sphincs-sha2-128s-simple`` 44 | * ``clean`` 45 | * ``avx2`` (if supported) 46 | * ``sphincs-sha2-192f-simple`` 47 | * ``clean`` 48 | * ``avx2`` (if supported) 49 | * ``sphincs-sha2-192s-simple`` 50 | * ``clean`` 51 | * ``avx2`` (if supported) 52 | * ``sphincs-sha2-256f-simple`` 53 | * ``clean`` 54 | * ``avx2`` (if supported) 55 | * ``sphincs-sha2-256s-simple`` 56 | * ``clean`` 57 | * ``avx2`` (if supported) 58 | 59 | 60 | ## License 61 | 62 | The wrappers and wrapper generation scripts in this project are covered by the 63 | MIT or Apache 2.0 licenses, at your choice. 64 | 65 | The implementations we link to are not, however. Please see the [PQClean][pqclean] 66 | project for the appropriate licenses. 67 | 68 | [pqclean]: https://github.com/PQClean/PQClean/ 69 | [nistpqc]: https://nist.gov/pqc/ -------------------------------------------------------------------------------- /pqcrypto-sphincsplus/build.rs: -------------------------------------------------------------------------------- 1 | extern crate cc; 2 | extern crate glob; 3 | 4 | use std::env; 5 | use std::path::{Path, PathBuf}; 6 | 7 | macro_rules! build_clean { 8 | ($variant:expr) => { 9 | let internals_include_path = &std::env::var("DEP_PQCRYPTO_INTERNALS_INCLUDEPATH").unwrap(); 10 | let common_dir = Path::new("pqclean/common"); 11 | 12 | let mut builder = cc::Build::new(); 13 | let target_dir: PathBuf = ["pqclean", "crypto_sign", $variant, "clean"] 14 | .iter() 15 | .collect(); 16 | 17 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 18 | if target_os == "wasi" { 19 | let wasi_sdk_path = 20 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 21 | builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str()); 22 | } 23 | 24 | let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap(); 25 | 26 | builder 27 | .include(internals_include_path) 28 | .include(&common_dir) 29 | .include(target_dir) 30 | .files( 31 | scheme_files 32 | .into_iter() 33 | .map(|p| p.unwrap().to_string_lossy().into_owned()), 34 | ); 35 | builder.compile(format!("{}_clean", $variant).as_str()); 36 | }; 37 | } 38 | 39 | macro_rules! build_avx2 { 40 | ($variant:expr) => { 41 | let internals_include_path = &std::env::var("DEP_PQCRYPTO_INTERNALS_INCLUDEPATH").unwrap(); 42 | let common_dir = Path::new("pqclean/common"); 43 | 44 | let mut builder = cc::Build::new(); 45 | let target_dir: PathBuf = ["pqclean", "crypto_sign", $variant, "avx2"] 46 | .iter() 47 | .collect(); 48 | 49 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 50 | if target_os == "wasi" { 51 | let wasi_sdk_path = 52 | &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 53 | builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str()); 54 | } 55 | 56 | let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap(); 57 | let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); 58 | if target_env == "msvc" { 59 | builder.flag("/arch:AVX2"); 60 | } else { 61 | builder 62 | .flag("-mavx2") 63 | .flag("-mbmi2") 64 | .flag("-mbmi") 65 | .flag("-maes") 66 | .flag("-mpopcnt") 67 | .flag("-mpclmul"); 68 | } 69 | 70 | builder 71 | .include(internals_include_path) 72 | .include(&common_dir) 73 | .include(target_dir) 74 | .files( 75 | scheme_files 76 | .into_iter() 77 | .map(|p| p.unwrap().to_string_lossy().into_owned()), 78 | ); 79 | builder.compile(format!("{}_avx2", $variant).as_str()); 80 | }; 81 | } 82 | 83 | fn main() { 84 | #[allow(unused_variables)] 85 | let aes_enabled = env::var("CARGO_FEATURE_AES").is_ok(); 86 | #[allow(unused_variables)] 87 | let avx2_enabled = env::var("CARGO_FEATURE_AVX2").is_ok(); 88 | #[allow(unused_variables)] 89 | let neon_enabled = env::var("CARGO_FEATURE_NEON").is_ok(); 90 | #[allow(unused_variables)] 91 | let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); 92 | #[allow(unused_variables)] 93 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 94 | #[allow(unused_variables)] 95 | let is_windows = target_os == "windows"; 96 | #[allow(unused_variables)] 97 | let is_macos = target_os == "macos"; 98 | 99 | build_clean!("sphincs-shake-128f-simple"); 100 | if target_arch == "x86_64" && avx2_enabled { 101 | build_avx2!("sphincs-shake-128f-simple"); 102 | } 103 | build_clean!("sphincs-shake-128s-simple"); 104 | if target_arch == "x86_64" && avx2_enabled { 105 | build_avx2!("sphincs-shake-128s-simple"); 106 | } 107 | build_clean!("sphincs-shake-192f-simple"); 108 | if target_arch == "x86_64" && avx2_enabled { 109 | build_avx2!("sphincs-shake-192f-simple"); 110 | } 111 | build_clean!("sphincs-shake-192s-simple"); 112 | if target_arch == "x86_64" && avx2_enabled { 113 | build_avx2!("sphincs-shake-192s-simple"); 114 | } 115 | build_clean!("sphincs-shake-256f-simple"); 116 | if target_arch == "x86_64" && avx2_enabled { 117 | build_avx2!("sphincs-shake-256f-simple"); 118 | } 119 | build_clean!("sphincs-shake-256s-simple"); 120 | if target_arch == "x86_64" && avx2_enabled { 121 | build_avx2!("sphincs-shake-256s-simple"); 122 | } 123 | build_clean!("sphincs-sha2-128f-simple"); 124 | if target_arch == "x86_64" && avx2_enabled { 125 | build_avx2!("sphincs-sha2-128f-simple"); 126 | } 127 | build_clean!("sphincs-sha2-128s-simple"); 128 | if target_arch == "x86_64" && avx2_enabled { 129 | build_avx2!("sphincs-sha2-128s-simple"); 130 | } 131 | build_clean!("sphincs-sha2-192f-simple"); 132 | if target_arch == "x86_64" && avx2_enabled { 133 | build_avx2!("sphincs-sha2-192f-simple"); 134 | } 135 | build_clean!("sphincs-sha2-192s-simple"); 136 | if target_arch == "x86_64" && avx2_enabled { 137 | build_avx2!("sphincs-sha2-192s-simple"); 138 | } 139 | build_clean!("sphincs-sha2-256f-simple"); 140 | if target_arch == "x86_64" && avx2_enabled { 141 | build_avx2!("sphincs-sha2-256f-simple"); 142 | } 143 | build_clean!("sphincs-sha2-256s-simple"); 144 | if target_arch == "x86_64" && avx2_enabled { 145 | build_avx2!("sphincs-sha2-256s-simple"); 146 | } 147 | 148 | println!("cargo::rustc-check-cfg=cfg(enable_x86_avx2)"); 149 | if target_arch == "x86_64" && avx2_enabled { 150 | // Print enableing flag for AVX2 implementation 151 | println!("cargo:rustc-cfg=enable_x86_avx2"); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /pqcrypto-sphincsplus/pqclean: -------------------------------------------------------------------------------- 1 | ../pqclean -------------------------------------------------------------------------------- /pqcrypto-template/pqcrypto/Cargo.toml.j2: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pqcrypto" 3 | description = "Post-Quantum cryptographic primitives" 4 | readme = "README.md" 5 | version = "{{ version }}" 6 | authors = ["Thom Wiggers "] 7 | edition = "2021" 8 | license = "MIT OR Apache-2.0" 9 | homepage = "https://github.com/rustpq/" 10 | repository = "https://github.com/rustpq/pqcrypto/" 11 | keywords = ["cryptography", "post-quantum", "security"] 12 | categories = ["cryptography"] 13 | 14 | [dependencies] 15 | pqcrypto-traits = { path = "../pqcrypto-traits", version = "{{ traits_version }}" } 16 | {% for (name, props) in kems.items()|list + signs.items()|list %} 17 | pqcrypto-{{ name }} = { path = "../pqcrypto-{{ name }}", version = "{{ props.version }}", optional = true } 18 | {% endfor %} 19 | 20 | [features] 21 | default = [{% for (name, props) in kems.items()|list + signs.items()|list %}{% if not props.insecure|default(False) %}"pqcrypto-{{name}}",{% endif %}{% endfor %}] 22 | cryptographically-insecure = [{% for (name, props) in kems.items()|list + signs.items()|list %}{% if props.insecure|default(False) %}"pqcrypto-{{name}}/cryptographically-insecure",{% endif %}{% endfor %}] 23 | serialization = [{% for (name, props) in kems.items()|list + signs.items()|list %}"pqcrypto-{{name}}/serialization",{% endfor %}] 24 | 25 | [badges] 26 | travis-ci = { repository = "rustpq/pqcrypto", branch = "master" } 27 | maintenance = { status = "actively-developed" } 28 | 29 | [package.metadata.docs.rs] 30 | all-features = true 31 | -------------------------------------------------------------------------------- /pqcrypto-template/pqcrypto/README.md.j2: -------------------------------------------------------------------------------- 1 | # Post-Quantum cryptographic algorithms 2 | 3 | This project contains Post-Quantum cryptographic algorithms that participate in 4 | the [NIST PQC standardization effort][nistpqc]. It is currently a collection of 5 | wrappers around C implementations from the [PQClean][pqclean] project. 6 | 7 | {% if any_insecure %} 8 | ## Insecure algorithms 9 | 10 | This crate contains optional support for insecure algorithms. They can be enabled via the 11 | ``cryptographically-insecure`` flag. 12 | 13 | This crate also contains algorithms that have non-constant time implementations. 14 | Always check the relevant algorithms for their security details. 15 | {% endif %} 16 | 17 | ## Included algorithms 18 | 19 | This super-crate contains the following cryptographic algorithms: 20 | 21 | ## Key-Encapsulation Mechanisms 22 | 23 | {% for (name, props) in kems.items()|list %} 24 | * [``pqcrypto-{{ name }}``](https://crates.io/crates/pqcrypto-{{name}}) {% if props.insecure|default(False) %}(insecure, disabled by default){% endif %} 25 | 26 | {% endfor %} 27 | 28 | ## Signature Schemes 29 | 30 | {% for (name, props) in signs.items()|list %} 31 | * [``pqcrypto-{{ name }}``](https://crates.io/crates/pqcrypto-{{name}}) {% if props.insecure|default(False) %}(insecure, disabled by default){% endif %} 32 | 33 | {% endfor %} 34 | 35 | ## Serialization 36 | 37 | If you want `serde` support, enable the `serialization` feature. 38 | You may also enable it for individual algorithms via `pqcrypto-{alg}/serialization`. 39 | 40 | ## License 41 | 42 | The wrappers and wrapper generation scripts in this project are covered by the 43 | MIT or Apache 2.0 licenses, at your choice. 44 | 45 | The implementations we link to are not, however. Please see the [PQClean][pqclean] 46 | project for the appropriate licenses. 47 | 48 | [pqclean]: https://github.com/PQClean/PQClean/ 49 | [nistpqc]: https://nist.gov/pqc/ 50 | -------------------------------------------------------------------------------- /pqcrypto-template/pqcrypto/examples/keygen.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::prelude::*; 3 | 4 | use pqcrypto::prelude::*; 5 | use pqcrypto::sign::mldsa44::*; 6 | 7 | 8 | fn main() -> std::io::Result<()> { 9 | let mut pubfile = File::create("publickey.bin")?; 10 | let mut secfile = File::create("secretkey.bin")?; 11 | let (pk, sk) = keypair(); 12 | pubfile.write_all(pk.as_bytes())?; 13 | secfile.write_all(sk.as_bytes())?; 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /pqcrypto-template/pqcrypto/examples/signer.rs: -------------------------------------------------------------------------------- 1 | use std::fs::{self, File}; 2 | use std::io::prelude::*; 3 | 4 | use pqcrypto::prelude::*; 5 | use pqcrypto::sign::mldsa44::*; 6 | 7 | fn parseargs() -> (String, String, String) { 8 | let args: Vec = std::env::args().collect(); 9 | if args.len() != 4 { 10 | panic!("Usage: {} sk in out", args[0]); 11 | } 12 | (args[1].clone(), args[2].clone(), args[3].clone()) 13 | } 14 | 15 | fn main() -> Result<(), Box> { 16 | let (sk_filename, in_filename, sig_filename) = parseargs(); 17 | let mut sigfile= File::create(sig_filename)?; 18 | 19 | let sk = SecretKey::from_bytes(&fs::read(sk_filename)?)?; 20 | let signature = detached_sign(&fs::read(in_filename)?, &sk); 21 | 22 | sigfile.write_all(signature.as_bytes())?; 23 | 24 | Ok(()) 25 | } 26 | -------------------------------------------------------------------------------- /pqcrypto-template/pqcrypto/examples/verifier.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | 3 | use pqcrypto::prelude::*; 4 | use pqcrypto::sign::mldsa44::*; 5 | 6 | fn parseargs() -> (String, String, String) { 7 | let args: Vec = std::env::args().collect(); 8 | if args.len() != 4 { 9 | panic!("Usage: {} pk msg sig", args[0]); 10 | } 11 | (args[1].clone(), args[2].clone(), args[3].clone()) 12 | } 13 | 14 | fn main() -> Result<(), Box> { 15 | let (pk_filename, in_filename, sig_filename) = parseargs(); 16 | let pk = PublicKey::from_bytes(&fs::read(pk_filename)?)?; 17 | let msg = &fs::read(in_filename)?; 18 | let sig = DetachedSignature::from_bytes(&fs::read(sig_filename)?)?; 19 | 20 | if let Ok(()) = verify_detached_signature(&sig, msg, &pk) { 21 | println!("Verification success!"); 22 | } else { 23 | println!("Verification failed!"); 24 | } 25 | 26 | Ok(()) 27 | } 28 | -------------------------------------------------------------------------------- /pqcrypto-template/pqcrypto/src/lib.rs.j2: -------------------------------------------------------------------------------- 1 | /// Post-Quantum cryptographic primitives 2 | /// 3 | /// Packages the [PQClean][pqclean] project as Rust crates 4 | /// 5 | /// [pqclean]: https://github.com/PQClean/PQClean/ 6 | pub use pqcrypto_traits as traits; 7 | 8 | pub mod prelude { 9 | pub use pqcrypto_traits::sign::{ 10 | SecretKey as _, 11 | PublicKey as _, 12 | SignedMessage as _, 13 | DetachedSignature as _, 14 | }; 15 | pub use pqcrypto_traits::kem::{ 16 | Ciphertext as _, 17 | PublicKey as _, 18 | SecretKey as _, 19 | SharedSecret as _, 20 | }; 21 | } 22 | 23 | pub mod kem { 24 | {% for kem in kems.keys() %} 25 | #[cfg(feature = "pqcrypto-{{kem}}")] 26 | pub use pqcrypto_{{ kem }}::{ 27 | {% for scheme in kems[kem]['schemes'] %} 28 | {{ scheme['name']|nameize }}, 29 | {% endfor %} 30 | }; 31 | {% endfor %} 32 | } 33 | 34 | pub mod sign { 35 | {% for sign in signs.keys() %} 36 | #[cfg(feature = "pqcrypto-{{sign}}")] 37 | pub use pqcrypto_{{ sign }}::{ 38 | {% for scheme in signs[sign]['schemes'] %} 39 | {{ scheme['name']|nameize }}, 40 | {% endfor %} 41 | }; 42 | {% endfor %} 43 | } 44 | -------------------------------------------------------------------------------- /pqcrypto-template/scheme/Cargo.toml.j2: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pqcrypto-{{ name }}" 3 | description = "Post-Quantum {% if type == "kem" %}Key-Encapsulation Mechanism{% else %}Signature Scheme{% endif %} {{ name }}" 4 | readme = "README.md" 5 | version = "{{ version }}" 6 | authors = ["Thom Wiggers "] 7 | edition = "2021" 8 | license = "MIT OR Apache-2.0" 9 | homepage = "https://github.com/rustpq/" 10 | repository = "https://github.com/rustpq/pqcrypto/" 11 | keywords = ["cryptography", "post-quantum", "security"] 12 | categories = ["cryptography", "no-std"] 13 | 14 | [dependencies] 15 | pqcrypto-internals = { path = "../pqcrypto-internals", version = "0.2.6" } 16 | pqcrypto-traits = { path = "../pqcrypto-traits", version = "{{ traits_version }}", default-features = false } 17 | libc = "0.2.0" 18 | serde = { version = "1.0", features = ["derive"], optional = true } 19 | serde-big-array = { version = "0.5.1", optional = true } 20 | {% if supports_context %} 21 | paste = "1.0" 22 | {% endif %} 23 | 24 | [features] 25 | default = [{% if 'avx2' in implementations or 'avx' in implementations %}"avx2", {% endif %}{% if 'aesni' in implementations %}"aes", {% endif %}{% if 'aarch64' in implementations %}"neon", {% endif %}"std"] 26 | {% if 'avx2' in implementations or 'avx' in implementations %} 27 | avx2 = ["std"] 28 | {% endif %} 29 | {% if 'aesni' in implementations %} 30 | aes = ["std"] 31 | {% endif %} 32 | {% if 'aarch64' in implementations %} 33 | neon = ["std"] 34 | {% endif %} 35 | std = ["pqcrypto-traits/std"] 36 | serialization = ["serde", "serde-big-array"] 37 | {% if insecure %} 38 | cryptographically-insecure = [] 39 | {% endif %} 40 | 41 | [dev-dependencies] 42 | {% if type == "sign" %} 43 | rand = "0.9" 44 | {% endif %} 45 | 46 | [build-dependencies] 47 | cc = { version = "1.0", features = ["parallel"] } 48 | glob = "0.3.0" 49 | 50 | [badges] 51 | travis-ci = { repository = "rustpq/pqcrypto", branch = "master" } 52 | maintenance = { status = "actively-developed" } 53 | 54 | {% if insecure %} 55 | [package.metadata.docs.rs] 56 | features = ["cryptographically-insecure"] 57 | {% endif %} 58 | -------------------------------------------------------------------------------- /pqcrypto-template/scheme/README.md.j2: -------------------------------------------------------------------------------- 1 | # {{ name }} 2 | 3 | {% if insecure %} 4 | This (implementation of an) cryptographic algorithm is insecure. 5 | This crate will only compile if you enable the "cryptographically-insecure" feature. 6 | 7 | Only use this crate and algorithm for research and educational purposes. 8 | {% endif %} 9 | 10 | This crate contains bindings to the C implementations of the following schemes, 11 | from [PQClean][pqclean]. 12 | 13 | This project packages Post-Quantum cryptographic algorithms that participate in 14 | the [NIST PQC standardization effort][nistpqc]. It is currently a collection of 15 | wrappers around C implementations from the [PQClean][pqclean] project. 16 | 17 | ## Serialization 18 | 19 | If you want `serde` support, enable the `serialization` feature. 20 | 21 | ## Included implementations from PQClean 22 | 23 | Below is a list of the included schemes and the corresponding implementations 24 | sourced from [PQClean][pqclean]. The "default" implementation is used in the 25 | Rust-friendly interface, alternative implementations are exposed as ``ffi`` 26 | methods only. 27 | 28 | {% for scheme in schemes %} 29 | * ``{{ scheme.name }}`` 30 | {% for implementation in scheme.implementations %} 31 | {% if implementation == 'avx2' or implementation == 'avx' or implementation == 'aesni' or implementation == 'aarch64' %} 32 | * ``{{ implementation }}`` (if supported) 33 | {% else %} 34 | * ``{{ implementation }}`` 35 | {% endif %} 36 | {% endfor %}{# implementations #} 37 | {% endfor %}{# schemes #} 38 | 39 | {% if notes %} 40 | ## Notes 41 | 42 | {{ notes }} 43 | {% endif %} 44 | 45 | ## License 46 | 47 | The wrappers and wrapper generation scripts in this project are covered by the 48 | MIT or Apache 2.0 licenses, at your choice. 49 | 50 | The implementations we link to are not, however. Please see the [PQClean][pqclean] 51 | project for the appropriate licenses. 52 | 53 | [pqclean]: https://github.com/PQClean/PQClean/ 54 | [nistpqc]: https://nist.gov/pqc/ 55 | -------------------------------------------------------------------------------- /pqcrypto-template/scheme/build.rs.j2: -------------------------------------------------------------------------------- 1 | extern crate cc; 2 | extern crate glob; 3 | 4 | use std::env; 5 | use std::path::{Path, PathBuf}; 6 | 7 | {% set globals = namespace() %} 8 | {% set globals.x86_aes = False %} 9 | {% set globals.x86_avx2 = False %} 10 | {% set globals.aarch64_neon = False %} 11 | 12 | {% for implementation in implementations %} 13 | macro_rules! build_{{ implementation }} { 14 | ($variant:expr) => { 15 | let internals_include_path = &std::env::var("DEP_PQCRYPTO_INTERNALS_INCLUDEPATH").unwrap(); 16 | let common_dir = Path::new("pqclean/common"); 17 | 18 | let mut builder = cc::Build::new(); 19 | let target_dir: PathBuf = ["pqclean", "crypto_{{ type }}", $variant, "{{ implementation }}"] 20 | .iter() 21 | .collect(); 22 | 23 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 24 | if target_os == "wasi" { 25 | let wasi_sdk_path = &std::env::var("WASI_SDK_DIR").expect("missing environment variable: WASI_SDK_DIR"); 26 | builder.flag(format!("--sysroot={}", wasi_sdk_path).as_str()); 27 | } 28 | 29 | {% if implementation == 'avx2' or implementation == 'avx' %} 30 | {% set globals.x86_avx2 = True %} 31 | let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap(); 32 | let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); 33 | if target_env == "msvc" { 34 | builder.flag("/arch:AVX2"); 35 | } else { 36 | builder 37 | .flag("-mavx2") 38 | .flag("-mbmi2") 39 | .flag("-mbmi") 40 | .flag("-maes") 41 | .flag("-mpopcnt") 42 | .flag("-mpclmul"); 43 | } 44 | {% elif implementation == 'aesni' %} 45 | {% set globals.x86_aes = True %} 46 | let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap(); 47 | let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); 48 | if target_env == "msvc" { 49 | builder.flag("/arch:AVX2"); 50 | } else { 51 | builder 52 | .flag("-maes"); 53 | } 54 | {% elif implementation == 'aarch64' %} 55 | {% set globals.aarch64_neon = True %} 56 | let scheme_files = glob::glob(target_dir.join("*.[csS]").to_str().unwrap()).unwrap(); 57 | builder.flag("-march=armv8-a"); 58 | {% else %} 59 | let scheme_files = glob::glob(target_dir.join("*.c").to_str().unwrap()).unwrap(); 60 | {% endif %} 61 | 62 | builder 63 | .include(internals_include_path) 64 | .include(&common_dir) 65 | .include(target_dir) 66 | .files( 67 | scheme_files 68 | .into_iter() 69 | .map(|p| p.unwrap().to_string_lossy().into_owned()), 70 | ); 71 | builder.compile(format!("{}_{{ implementation }}", $variant).as_str()); 72 | }; 73 | } 74 | 75 | {% endfor %} 76 | 77 | fn main() { 78 | #[allow(unused_variables)] 79 | let aes_enabled = env::var("CARGO_FEATURE_AES").is_ok(); 80 | #[allow(unused_variables)] 81 | let avx2_enabled = env::var("CARGO_FEATURE_AVX2").is_ok(); 82 | #[allow(unused_variables)] 83 | let neon_enabled = env::var("CARGO_FEATURE_NEON").is_ok(); 84 | #[allow(unused_variables)] 85 | let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); 86 | #[allow(unused_variables)] 87 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 88 | #[allow(unused_variables)] 89 | let is_windows = target_os == "windows"; 90 | #[allow(unused_variables)] 91 | let is_macos = target_os == "macos"; 92 | 93 | {% for scheme in schemes %} 94 | {% for implementation in scheme.implementations %} 95 | {% if implementation == 'avx2' or implementation == 'avx' %} 96 | if {{ x86_avx2_guard }} { 97 | build_{{ implementation }}!("{{ scheme.name }}"); 98 | } 99 | {% elif implementation == 'aesni' %} 100 | if {{ x86_aes_guard }} { 101 | build_{{ implementation }}!("{{ scheme.name }}"); 102 | } 103 | {% elif implementation == 'aarch64' %} 104 | if {{ aarch64_neon_guard }} { 105 | build_{{ implementation }}!("{{ scheme.name }}"); 106 | } 107 | {% else %} 108 | build_{{ implementation }}!("{{ scheme.name }}"); 109 | {% endif %} 110 | {% endfor %} 111 | {% endfor %} 112 | 113 | {% if globals.x86_avx2 %} 114 | println!("cargo::rustc-check-cfg=cfg(enable_x86_avx2)"); 115 | if {{ x86_avx2_guard }} { 116 | // Print enableing flag for AVX2 implementation 117 | println!("cargo:rustc-cfg=enable_x86_avx2"); 118 | } 119 | {% endif %} 120 | {% if globals.x86_aes %} 121 | println!("cargo::rustc-check-cfg=cfg(enable_x86_aes)"); 122 | if {{ x86_aes_guard }} { 123 | // Print enableing flag for AES implementation 124 | println!("cargo:rustc-cfg=enable_x86_aes"); 125 | } 126 | {% endif %} 127 | {% if globals.aarch64_neon %} 128 | println!("cargo::rustc-check-cfg=cfg(enable_aarch64_neon)"); 129 | if {{ aarch64_neon_guard }} { 130 | // Print enableing flag for AARCH64 implementation 131 | println!("cargo:rustc-cfg=enable_aarch64_neon"); 132 | } 133 | {% endif %} 134 | } 135 | -------------------------------------------------------------------------------- /pqcrypto-template/scheme/src/lib.rs.j2: -------------------------------------------------------------------------------- 1 | //! # {{ name }} 2 | //! 3 | //! This crate provides bindings to and wrappers around the following 4 | //! implementations from [PQClean][pqc]: 5 | //! 6 | {% for scheme in schemes %}//! * {{ scheme.name }} - {{ scheme.implementations[0] }} 7 | {% endfor %} 8 | //! 9 | //! [pqc]: https://github.com/pqclean/pqclean/ 10 | //! 11 | {% if notes %}//! # Notes 12 | {% for line in notes|split('\n')|join(' ')|wordwrap(width=70)|split('\n') %} 13 | //! {{ line }} 14 | {% endfor %} 15 | {% endif %} 16 | 17 | #![no_std] 18 | #![allow(clippy::len_without_is_empty)] 19 | 20 | // For no-std vectors 21 | extern crate alloc; 22 | 23 | // For tests 24 | #[cfg(feature = "std")] 25 | extern crate std; 26 | 27 | {% if insecure %} 28 | #[cfg_attr(not(feature = "cryptographically-insecure"), deny(deprecated))] 29 | {% endif %} 30 | 31 | pub mod ffi; 32 | {% for scheme in schemes %} 33 | pub mod {{ scheme.name|nameize }}; 34 | {% endfor %} 35 | 36 | {% for scheme in schemes %} 37 | {% set scheme_name = scheme.name|nameize %} 38 | pub use crate::{{ scheme_name }}::{ 39 | keypair as {{ scheme_name }}_keypair, 40 | public_key_bytes as {{ scheme_name }}_public_key_bytes, 41 | secret_key_bytes as {{ scheme_name }}_secret_key_bytes, 42 | {% if type == "kem" %} 43 | encapsulate as {{ scheme_name }}_encapsulate, 44 | decapsulate as {{ scheme_name }}_decapsulate, 45 | ciphertext_bytes as {{ scheme_name }}_ciphertext_bytes, 46 | shared_secret_bytes as {{ scheme_name }}_shared_secret_bytes, 47 | {% else %} 48 | signature_bytes as {{ scheme_name }}_signature_bytes, 49 | sign as {{ scheme_name }}_sign, 50 | open as {{ scheme_name }}_open, 51 | detached_sign as {{ scheme_name }}_detached_sign, 52 | verify_detached_signature as {{ scheme_name }}_verify_detached_signature, 53 | {% if supports_context %} 54 | sign_ctx as {{ scheme_name }}_sign_ctx, 55 | open_ctx as {{ scheme_name }}_open_ctx, 56 | detached_sign_ctx as {{ scheme_name }}_detached_sign_ctx, 57 | verify_detached_signature_ctx as {{ scheme_name }}_verify_detached_signature_ctx, 58 | {% endif %} 59 | {% endif %} 60 | }; 61 | {% endfor %} 62 | -------------------------------------------------------------------------------- /pqcrypto-template/workspace-Cargo.toml.j2: -------------------------------------------------------------------------------- 1 | # This file has been generated by generate-implementations.py 2 | [workspace] 3 | members=[ 4 | "pqcrypto", 5 | "pqcrypto-traits", 6 | "pqcrypto-internals", 7 | {% for name in names %} 8 | "{{ name }}", 9 | {% endfor %} 10 | ] 11 | resolver="2" 12 | -------------------------------------------------------------------------------- /pqcrypto-traits/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pqcrypto-traits" 3 | version = "0.3.5" 4 | authors = ["Thom Wiggers "] 5 | edition = "2021" 6 | description = "Shared traits for post-quantum cryptographic primitives" 7 | license = "MIT OR Apache-2.0" 8 | homepage = "https://github.com/rustpq/" 9 | repository = "https://github.com/rustpq/pqclean/" 10 | keywords = ["cryptography", "post-quantum", "security"] 11 | categories = ["cryptography", "no-std"] 12 | 13 | [dependencies] 14 | 15 | [features] 16 | default = ["std"] 17 | std = [] 18 | -------------------------------------------------------------------------------- /pqcrypto-traits/src/kem.rs: -------------------------------------------------------------------------------- 1 | /// Traits for Key-Encapsulation Mechanisms 2 | use crate::Result; 3 | 4 | /// A public key for a KEM 5 | pub trait PublicKey { 6 | fn as_bytes(&self) -> &[u8]; 7 | fn from_bytes(bytes: &[u8]) -> Result 8 | where 9 | Self: Sized + Clone; 10 | } 11 | 12 | /// A secret key for a KEM 13 | pub trait SecretKey { 14 | fn as_bytes(&self) -> &[u8]; 15 | fn from_bytes(bytes: &[u8]) -> Result 16 | where 17 | Self: Sized + Clone; 18 | } 19 | 20 | /// The ciphertext to be sent to the other party to decapsulate. 21 | pub trait Ciphertext { 22 | fn as_bytes(&self) -> &[u8]; 23 | fn from_bytes(bytes: &[u8]) -> Result 24 | where 25 | Self: Sized + Clone + Copy; 26 | } 27 | 28 | /// The shared secret that should be agreed on. 29 | pub trait SharedSecret { 30 | fn as_bytes(&self) -> &[u8]; 31 | fn from_bytes(bytes: &[u8]) -> Result 32 | where 33 | Self: Sized + Clone + Copy; 34 | } 35 | -------------------------------------------------------------------------------- /pqcrypto-traits/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Supporting Traits for the pqcrypto crates. 2 | 3 | #![no_std] 4 | 5 | #[cfg(feature = "std")] 6 | extern crate std; 7 | 8 | /// Convenience wrapper for Result 9 | pub type Result = core::result::Result; 10 | 11 | /// Errors that may arise when constructing keys or signatures. 12 | #[derive(Clone, Copy, Debug)] 13 | #[non_exhaustive] 14 | pub enum Error { 15 | BadLength { 16 | name: &'static str, 17 | actual: usize, 18 | expected: usize, 19 | }, 20 | } 21 | 22 | impl core::fmt::Display for Error { 23 | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { 24 | match self { 25 | Error::BadLength { 26 | name, 27 | actual, 28 | expected, 29 | } => write!( 30 | f, 31 | "error: {} expected {} bytes, got {}", 32 | name, expected, actual 33 | ), 34 | } 35 | } 36 | } 37 | 38 | #[cfg(feature = "std")] 39 | impl std::error::Error for Error {} 40 | 41 | pub mod kem; 42 | pub mod sign; 43 | -------------------------------------------------------------------------------- /pqcrypto-traits/src/sign.rs: -------------------------------------------------------------------------------- 1 | /// Traits for signature schemes 2 | use crate::Result; 3 | 4 | /// A public key for a signature scheme 5 | pub trait PublicKey { 6 | fn as_bytes(&self) -> &[u8]; 7 | fn from_bytes(bytes: &[u8]) -> Result 8 | where 9 | Self: Sized; 10 | } 11 | 12 | /// A secret key for a signature scheme 13 | pub trait SecretKey { 14 | fn as_bytes(&self) -> &[u8]; 15 | fn from_bytes(bytes: &[u8]) -> Result 16 | where 17 | Self: Sized; 18 | } 19 | 20 | /// A signed message. 21 | /// 22 | /// This object contains both the signed message and the signature on it. 23 | /// If you use this struct, you no longer should send the plain text along 24 | /// with it. The [`open`] methods make sure that you will not 25 | /// process invalid ciphertexts by not returning the plain text if the signature 26 | /// is invalid. 27 | /// 28 | /// [`open`]: https://docs.rs/pqcrypto/0.7.0/pqcrypto/sign/sphincsshake256128ssimple/fn.open.html 29 | pub trait SignedMessage { 30 | fn as_bytes(&self) -> &[u8]; 31 | fn from_bytes(bytes: &[u8]) -> Result 32 | where 33 | Self: Sized; 34 | } 35 | 36 | /// A detached signature 37 | /// 38 | /// This signature does not include the message it certifies; this means that to verify it you also 39 | /// need the message. 40 | /// 41 | /// If you can get away with it, use the [`SignedMessage`] API, which ensures you won't use the message 42 | /// before having authenticated it. 43 | pub trait DetachedSignature { 44 | fn as_bytes(&self) -> &[u8]; 45 | fn from_bytes(bytes: &[u8]) -> Result 46 | where 47 | Self: Sized; 48 | } 49 | 50 | /// Errors that may arise when verifying a signature 51 | #[derive(Clone, Copy, Debug)] 52 | #[non_exhaustive] 53 | pub enum VerificationError { 54 | InvalidSignature, 55 | UnknownVerificationError, 56 | } 57 | 58 | impl core::fmt::Display for VerificationError { 59 | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> { 60 | match self { 61 | VerificationError::InvalidSignature => write!(f, "error: verification failed"), 62 | VerificationError::UnknownVerificationError => write!(f, "unknown error"), 63 | } 64 | } 65 | } 66 | 67 | #[cfg(feature = "std")] 68 | impl std::error::Error for VerificationError {} 69 | -------------------------------------------------------------------------------- /pqcrypto/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pqcrypto" 3 | description = "Post-Quantum cryptographic primitives" 4 | readme = "README.md" 5 | version = "0.18.1" 6 | authors = ["Thom Wiggers "] 7 | edition = "2021" 8 | license = "MIT OR Apache-2.0" 9 | homepage = "https://github.com/rustpq/" 10 | repository = "https://github.com/rustpq/pqcrypto/" 11 | keywords = ["cryptography", "post-quantum", "security"] 12 | categories = ["cryptography"] 13 | 14 | [dependencies] 15 | pqcrypto-traits = { path = "../pqcrypto-traits", version = "0.3.5" } 16 | pqcrypto-mlkem = { path = "../pqcrypto-mlkem", version = "0.1.0", optional = true } 17 | pqcrypto-classicmceliece = { path = "../pqcrypto-classicmceliece", version = "0.2.0", optional = true } 18 | pqcrypto-hqc = { path = "../pqcrypto-hqc", version = "0.2.1", optional = true } 19 | pqcrypto-mldsa = { path = "../pqcrypto-mldsa", version = "0.1.1", optional = true } 20 | pqcrypto-falcon = { path = "../pqcrypto-falcon", version = "0.4.0", optional = true } 21 | pqcrypto-sphincsplus = { path = "../pqcrypto-sphincsplus", version = "0.7.1", optional = true } 22 | 23 | [features] 24 | default = ["pqcrypto-mlkem","pqcrypto-classicmceliece","pqcrypto-hqc","pqcrypto-mldsa","pqcrypto-falcon","pqcrypto-sphincsplus",] 25 | cryptographically-insecure = [] 26 | serialization = ["pqcrypto-mlkem/serialization","pqcrypto-classicmceliece/serialization","pqcrypto-hqc/serialization","pqcrypto-mldsa/serialization","pqcrypto-falcon/serialization","pqcrypto-sphincsplus/serialization",] 27 | 28 | [badges] 29 | travis-ci = { repository = "rustpq/pqcrypto", branch = "master" } 30 | maintenance = { status = "actively-developed" } 31 | 32 | [package.metadata.docs.rs] 33 | all-features = true -------------------------------------------------------------------------------- /pqcrypto/README.md: -------------------------------------------------------------------------------- 1 | # Post-Quantum cryptographic algorithms 2 | 3 | This project contains Post-Quantum cryptographic algorithms that participate in 4 | the [NIST PQC standardization effort][nistpqc]. It is currently a collection of 5 | wrappers around C implementations from the [PQClean][pqclean] project. 6 | 7 | 8 | ## Included algorithms 9 | 10 | This super-crate contains the following cryptographic algorithms: 11 | 12 | ## Key-Encapsulation Mechanisms 13 | 14 | * [``pqcrypto-mlkem``](https://crates.io/crates/pqcrypto-mlkem) 15 | * [``pqcrypto-classicmceliece``](https://crates.io/crates/pqcrypto-classicmceliece) 16 | * [``pqcrypto-hqc``](https://crates.io/crates/pqcrypto-hqc) 17 | 18 | ## Signature Schemes 19 | 20 | * [``pqcrypto-mldsa``](https://crates.io/crates/pqcrypto-mldsa) 21 | * [``pqcrypto-falcon``](https://crates.io/crates/pqcrypto-falcon) 22 | * [``pqcrypto-sphincsplus``](https://crates.io/crates/pqcrypto-sphincsplus) 23 | 24 | ## Serialization 25 | 26 | If you want `serde` support, enable the `serialization` feature. 27 | You may also enable it for individual algorithms via `pqcrypto-{alg}/serialization`. 28 | 29 | ## License 30 | 31 | The wrappers and wrapper generation scripts in this project are covered by the 32 | MIT or Apache 2.0 licenses, at your choice. 33 | 34 | The implementations we link to are not, however. Please see the [PQClean][pqclean] 35 | project for the appropriate licenses. 36 | 37 | [pqclean]: https://github.com/PQClean/PQClean/ 38 | [nistpqc]: https://nist.gov/pqc/ -------------------------------------------------------------------------------- /pqcrypto/examples/keygen.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::prelude::*; 3 | 4 | use pqcrypto::prelude::*; 5 | use pqcrypto::sign::mldsa44::*; 6 | 7 | fn main() -> std::io::Result<()> { 8 | let mut pubfile = File::create("publickey.bin")?; 9 | let mut secfile = File::create("secretkey.bin")?; 10 | let (pk, sk) = keypair(); 11 | pubfile.write_all(pk.as_bytes())?; 12 | secfile.write_all(sk.as_bytes())?; 13 | Ok(()) 14 | } 15 | -------------------------------------------------------------------------------- /pqcrypto/examples/signer.rs: -------------------------------------------------------------------------------- 1 | use std::fs::{self, File}; 2 | use std::io::prelude::*; 3 | 4 | use pqcrypto::prelude::*; 5 | use pqcrypto::sign::mldsa44::*; 6 | 7 | fn parseargs() -> (String, String, String) { 8 | let args: Vec = std::env::args().collect(); 9 | if args.len() != 4 { 10 | panic!("Usage: {} sk in out", args[0]); 11 | } 12 | (args[1].clone(), args[2].clone(), args[3].clone()) 13 | } 14 | 15 | fn main() -> Result<(), Box> { 16 | let (sk_filename, in_filename, sig_filename) = parseargs(); 17 | let mut sigfile = File::create(sig_filename)?; 18 | 19 | let sk = SecretKey::from_bytes(&fs::read(sk_filename)?)?; 20 | let signature = detached_sign(&fs::read(in_filename)?, &sk); 21 | 22 | sigfile.write_all(signature.as_bytes())?; 23 | 24 | Ok(()) 25 | } 26 | -------------------------------------------------------------------------------- /pqcrypto/examples/verifier.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | 3 | use pqcrypto::prelude::*; 4 | use pqcrypto::sign::mldsa44::*; 5 | 6 | fn parseargs() -> (String, String, String) { 7 | let args: Vec = std::env::args().collect(); 8 | if args.len() != 4 { 9 | panic!("Usage: {} pk msg sig", args[0]); 10 | } 11 | (args[1].clone(), args[2].clone(), args[3].clone()) 12 | } 13 | 14 | fn main() -> Result<(), Box> { 15 | let (pk_filename, in_filename, sig_filename) = parseargs(); 16 | let pk = PublicKey::from_bytes(&fs::read(pk_filename)?)?; 17 | let msg = &fs::read(in_filename)?; 18 | let sig = DetachedSignature::from_bytes(&fs::read(sig_filename)?)?; 19 | 20 | if let Ok(()) = verify_detached_signature(&sig, msg, &pk) { 21 | println!("Verification success!"); 22 | } else { 23 | println!("Verification failed!"); 24 | } 25 | 26 | Ok(()) 27 | } 28 | -------------------------------------------------------------------------------- /pqcrypto/src/lib.rs: -------------------------------------------------------------------------------- 1 | /// Post-Quantum cryptographic primitives 2 | /// 3 | /// Packages the [PQClean][pqclean] project as Rust crates 4 | /// 5 | /// [pqclean]: https://github.com/PQClean/PQClean/ 6 | pub use pqcrypto_traits as traits; 7 | 8 | pub mod prelude { 9 | pub use pqcrypto_traits::kem::{ 10 | Ciphertext as _, PublicKey as _, SecretKey as _, SharedSecret as _, 11 | }; 12 | pub use pqcrypto_traits::sign::{ 13 | DetachedSignature as _, PublicKey as _, SecretKey as _, SignedMessage as _, 14 | }; 15 | } 16 | 17 | pub mod kem { 18 | #[cfg(feature = "pqcrypto-classicmceliece")] 19 | pub use pqcrypto_classicmceliece::{ 20 | mceliece348864, mceliece348864f, mceliece460896, mceliece460896f, mceliece6688128, 21 | mceliece6688128f, mceliece6960119, mceliece6960119f, mceliece8192128, mceliece8192128f, 22 | }; 23 | #[cfg(feature = "pqcrypto-hqc")] 24 | pub use pqcrypto_hqc::{hqc128, hqc192, hqc256}; 25 | #[cfg(feature = "pqcrypto-mlkem")] 26 | pub use pqcrypto_mlkem::{mlkem1024, mlkem512, mlkem768}; 27 | } 28 | 29 | pub mod sign { 30 | #[cfg(feature = "pqcrypto-falcon")] 31 | pub use pqcrypto_falcon::{falcon1024, falcon512, falconpadded1024, falconpadded512}; 32 | #[cfg(feature = "pqcrypto-mldsa")] 33 | pub use pqcrypto_mldsa::{mldsa44, mldsa65, mldsa87}; 34 | #[cfg(feature = "pqcrypto-sphincsplus")] 35 | pub use pqcrypto_sphincsplus::{ 36 | sphincssha2128fsimple, sphincssha2128ssimple, sphincssha2192fsimple, sphincssha2192ssimple, 37 | sphincssha2256fsimple, sphincssha2256ssimple, sphincsshake128fsimple, 38 | sphincsshake128ssimple, sphincsshake192fsimple, sphincsshake192ssimple, 39 | sphincsshake256fsimple, sphincsshake256ssimple, 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CARGO="cargo +nightly" 4 | 5 | publish() { 6 | pushd $1 7 | ${CARGO} publish 8 | popd 9 | } 10 | 11 | env | grep CARGO 12 | sleep 10 13 | 14 | publish pqcrypto-traits 15 | publish pqcrypto-internals 16 | sleep 2 17 | echo "Waiting a little bit for the pqcrypto-traits package to settle on crates.io" 18 | publish pqcrypto-mlkem 19 | publish pqcrypto-hqc 20 | publish pqcrypto-sphincsplus 21 | publish pqcrypto-mldsa 22 | publish pqcrypto-falcon 23 | publish pqcrypto-classicmceliece 24 | 25 | echo "Waiting a little bit for the packages to settle on crates.io" 26 | 27 | sleep 30 28 | publish pqcrypto 29 | --------------------------------------------------------------------------------