diff --git a/.github/test-workspace/provider-Cargo.toml b/.github/test-workspace/provider-Cargo.toml index 62a9aea..18ef9f8 100644 --- a/.github/test-workspace/provider-Cargo.toml +++ b/.github/test-workspace/provider-Cargo.toml @@ -5,21 +5,15 @@ edition = "2021" [dependencies] rustls = { path = "../../rustls/rustls", default-features = false, features = ["tls12"] } -chacha20poly1305 = { version = "0.10", default-features = false, features = ["alloc"] } -der = { version = "0.7", default-features = false } -ecdsa = { version = "0.16.9", default-features = false, features = ["alloc"] } -hmac = { version = "0.12", default-features = false } +der = { version = "0.7", default-features = false } pkcs8 = { version = "0.10.2", default-features = false } -rand_core = { version = "0.6", default-features = false, features = ["getrandom", "alloc"] } -rsa = { version = "0.9", features = ["sha2"], default-features = false } -sha2 = { version = "0.10", default-features = false } signature = { version = "2", default-features = false } webpki = { package = "rustls-webpki", version = "0.102", features = ["alloc"], default-features = false } foreign-types = { version = "0.5.0", default-features = false } rustls-pki-types = { version = "1.11.0", default-features = false } log = { version = "0.4.25", default-features = false } env_logger = { version = "0.11.6", default-features = false } -wolfcrypt-rs = { path = "../wolfcrypt-rs" } +wolfssl-wolfcrypt = { git = "https://github.com/wolfSSL/wolfssl" } rustls-pemfile = { version = "2.2.0", default-features = false } hex = { version = "0.4.3", default-features = false, features = ["alloc"]} wycheproof = { version = "0.6.0", default-features = false, features = [ @@ -45,7 +39,7 @@ rustls-test = {workspace = true} [features] default = [] -std = ["pkcs8/std", "rustls/std", "wolfcrypt-rs/std"] +std = ["pkcs8/std", "rustls/std"] quic = [] [profile.release] diff --git a/.github/workflows/macos-build.yml b/.github/workflows/macos-build.yml index 9faa126..13ecad2 100644 --- a/.github/workflows/macos-build.yml +++ b/.github/workflows/macos-build.yml @@ -10,6 +10,11 @@ jobs: macos-build: name: Build and Test (macOS) runs-on: macos-latest + env: + WOLFSSL_SRC: ${{ github.workspace }}/wolfssl + WOLFSSL_PREFIX: ${{ github.workspace }}/wolfssl-install + WOLFSSL_SERVER: ${{ github.workspace }}/wolfssl/examples/server/server + DYLD_LIBRARY_PATH: ${{ github.workspace }}/wolfssl-install/lib steps: - uses: actions/checkout@v4 @@ -35,11 +40,27 @@ jobs: restore-keys: | macos-cargo- - - name: Build and Test wolfcrypt-rs + - name: Checkout wolfSSL master + uses: actions/checkout@v4 + with: + repository: wolfSSL/wolfssl + path: wolfssl + + - name: Build and install wolfSSL + working-directory: wolfssl run: | - cd wolfcrypt-rs - make build - make test + ./autogen.sh + ./configure --prefix="$WOLFSSL_PREFIX" \ + --enable-all-crypto --enable-shared --disable-static \ + CPPFLAGS=-DWOLFSSL_RSA_KEY_CHECK + make -j"$(sysctl -n hw.ncpu)" + make install + + - name: Use the wolfCrypt crate from wolfSSL master + run: | + mkdir -p .cargo + printf '[patch."https://github.com/wolfSSL/wolfssl"]\nwolfssl-wolfcrypt = { path = "%s/wrapper/rust/wolfssl-wolfcrypt" }\n' \ + "$WOLFSSL_SRC" > .cargo/config.toml - name: Build and Test rustls-wolfcrypt-provider run: | @@ -47,17 +68,14 @@ jobs: make build make test make test-quic + make test-std - name: Check formatting run: | - cd wolfcrypt-rs - cargo fmt --all -- --check - cd ../rustls-wolfcrypt-provider + cd rustls-wolfcrypt-provider cargo fmt --all -- --check - name: Run clippy run: | - cd wolfcrypt-rs - cargo clippy -- -D warnings -A unnecessary-transmutes - cd ../rustls-wolfcrypt-provider + cd rustls-wolfcrypt-provider cargo clippy --all-features -- -D warnings diff --git a/.github/workflows/macos-rustls-tests.yml b/.github/workflows/macos-rustls-tests.yml index 590ae2f..f970315 100644 --- a/.github/workflows/macos-rustls-tests.yml +++ b/.github/workflows/macos-rustls-tests.yml @@ -10,6 +10,10 @@ jobs: macos-build: name: Build and Test (macOS) runs-on: macos-latest + env: + WOLFSSL_SRC: ${{ github.workspace }}/wolfssl + WOLFSSL_PREFIX: ${{ github.workspace }}/wolfssl-install + DYLD_LIBRARY_PATH: ${{ github.workspace }}/wolfssl-install/lib steps: - uses: actions/checkout@v4 @@ -35,6 +39,28 @@ jobs: restore-keys: | macos-cargo- + - name: Checkout wolfSSL master + uses: actions/checkout@v4 + with: + repository: wolfSSL/wolfssl + path: wolfssl + + - name: Build and install wolfSSL + working-directory: wolfssl + run: | + ./autogen.sh + ./configure --prefix="$WOLFSSL_PREFIX" \ + --enable-all-crypto --enable-shared --disable-static \ + CPPFLAGS=-DWOLFSSL_RSA_KEY_CHECK + make -j"$(sysctl -n hw.ncpu)" + make install + + - name: Use the wolfCrypt crate from wolfSSL master + run: | + mkdir -p .cargo + printf '[patch."https://github.com/wolfSSL/wolfssl"]\nwolfssl-wolfcrypt = { path = "%s/wrapper/rust/wolfssl-wolfcrypt" }\n' \ + "$WOLFSSL_SRC" > .cargo/config.toml + - name: Checkout rustls v0.23.35 uses: actions/checkout@v4 with: @@ -58,15 +84,10 @@ jobs: cp "$GITHUB_WORKSPACE/.github/test-workspace/workspace-Cargo.toml" Cargo.toml mkdir -p rustls-wolfcrypt-provider - cp -r "$GITHUB_WORKSPACE/wolfcrypt-rs" rustls-wolfcrypt-provider/ cp -r "$GITHUB_WORKSPACE/rustls-wolfcrypt-provider" rustls-wolfcrypt-provider/ cp "$GITHUB_WORKSPACE/.github/test-workspace/provider-Cargo.toml" \ rustls-wolfcrypt-provider/rustls-wolfcrypt-provider/Cargo.toml - - name: Build wolfcrypt-rs - working-directory: rustlsv0.23.35-test-workspace/rustls-wolfcrypt-provider/wolfcrypt-rs - run: make build - - name: Build rustls-wolfcrypt-provider working-directory: rustlsv0.23.35-test-workspace/rustls-wolfcrypt-provider/rustls-wolfcrypt-provider run: cargo build --all-features --release diff --git a/.github/workflows/ubuntu-build.yml b/.github/workflows/ubuntu-build.yml index fb90acd..a31d26d 100644 --- a/.github/workflows/ubuntu-build.yml +++ b/.github/workflows/ubuntu-build.yml @@ -10,6 +10,11 @@ jobs: ubuntu-build: name: Build and Test (Ubuntu) runs-on: ubuntu-latest + env: + WOLFSSL_SRC: ${{ github.workspace }}/wolfssl + WOLFSSL_PREFIX: ${{ github.workspace }}/wolfssl-install + WOLFSSL_SERVER: ${{ github.workspace }}/wolfssl/examples/server/server + LD_LIBRARY_PATH: ${{ github.workspace }}/wolfssl-install/lib steps: - uses: actions/checkout@v4 @@ -35,11 +40,27 @@ jobs: restore-keys: | ubuntu-cargo- - - name: Build and Test wolfcrypt-rs + - name: Checkout wolfSSL master + uses: actions/checkout@v4 + with: + repository: wolfSSL/wolfssl + path: wolfssl + + - name: Build and install wolfSSL + working-directory: wolfssl run: | - cd wolfcrypt-rs - make build - make test + ./autogen.sh + ./configure --prefix="$WOLFSSL_PREFIX" \ + --enable-all-crypto --enable-shared --disable-static \ + CPPFLAGS=-DWOLFSSL_RSA_KEY_CHECK + make -j"$(nproc)" + make install + + - name: Use the wolfCrypt crate from wolfSSL master + run: | + mkdir -p .cargo + printf '[patch."https://github.com/wolfSSL/wolfssl"]\nwolfssl-wolfcrypt = { path = "%s/wrapper/rust/wolfssl-wolfcrypt" }\n' \ + "$WOLFSSL_SRC" > .cargo/config.toml - name: Build and Test rustls-wolfcrypt-provider run: | @@ -47,18 +68,15 @@ jobs: make build make test make test-quic + make test-std - name: Check formatting run: | - cd wolfcrypt-rs - cargo fmt --all -- --check - cd ../rustls-wolfcrypt-provider + cd rustls-wolfcrypt-provider cargo fmt --all -- --check - name: Run clippy run: | - cd wolfcrypt-rs - cargo clippy --all-features -- -D warnings - cd ../rustls-wolfcrypt-provider + cd rustls-wolfcrypt-provider cargo clippy --all-features -- -D warnings diff --git a/.github/workflows/ubuntu-rustls-tests.yml b/.github/workflows/ubuntu-rustls-tests.yml index a06764f..dd0c948 100644 --- a/.github/workflows/ubuntu-rustls-tests.yml +++ b/.github/workflows/ubuntu-rustls-tests.yml @@ -10,6 +10,10 @@ jobs: ubuntu-build: name: Build and Test (Ubuntu) runs-on: ubuntu-latest + env: + WOLFSSL_SRC: ${{ github.workspace }}/wolfssl + WOLFSSL_PREFIX: ${{ github.workspace }}/wolfssl-install + LD_LIBRARY_PATH: ${{ github.workspace }}/wolfssl-install/lib steps: - uses: actions/checkout@v4 @@ -35,6 +39,28 @@ jobs: restore-keys: | ubuntu-cargo- + - name: Checkout wolfSSL master + uses: actions/checkout@v4 + with: + repository: wolfSSL/wolfssl + path: wolfssl + + - name: Build and install wolfSSL + working-directory: wolfssl + run: | + ./autogen.sh + ./configure --prefix="$WOLFSSL_PREFIX" \ + --enable-all-crypto --enable-shared --disable-static \ + CPPFLAGS=-DWOLFSSL_RSA_KEY_CHECK + make -j"$(nproc)" + make install + + - name: Use the wolfCrypt crate from wolfSSL master + run: | + mkdir -p .cargo + printf '[patch."https://github.com/wolfSSL/wolfssl"]\nwolfssl-wolfcrypt = { path = "%s/wrapper/rust/wolfssl-wolfcrypt" }\n' \ + "$WOLFSSL_SRC" > .cargo/config.toml + - name: Checkout rustls v0.23.35 uses: actions/checkout@v4 with: @@ -58,15 +84,10 @@ jobs: cp "$GITHUB_WORKSPACE/.github/test-workspace/workspace-Cargo.toml" Cargo.toml mkdir -p rustls-wolfcrypt-provider - cp -r "$GITHUB_WORKSPACE/wolfcrypt-rs" rustls-wolfcrypt-provider/ cp -r "$GITHUB_WORKSPACE/rustls-wolfcrypt-provider" rustls-wolfcrypt-provider/ cp "$GITHUB_WORKSPACE/.github/test-workspace/provider-Cargo.toml" \ rustls-wolfcrypt-provider/rustls-wolfcrypt-provider/Cargo.toml - - name: Build wolfcrypt-rs - working-directory: rustlsv0.23.35-test-workspace/rustls-wolfcrypt-provider/wolfcrypt-rs - run: make build - - name: Build rustls-wolfcrypt-provider working-directory: rustlsv0.23.35-test-workspace/rustls-wolfcrypt-provider/rustls-wolfcrypt-provider run: cargo build --all-features --release diff --git a/.gitignore b/.gitignore index 3b77375..b26e3b4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ /rustls-wolfcrypt-provider/target -/wolfcrypt-rs/target -/wolfcrypt-rs/wolfssl-*/ /rustlsv0.23.35-test-workspace/ diff --git a/README.md b/README.md index f826852..4bfba42 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,13 @@ provider itself operates independently of `std`. ## Status This is in an alpha stage, particularly because the Rustls API is not yet stable. -This code currently works with Rustls = 0.23.22. +This code currently works with Rustls = 0.23.45. ## Repo Structure - **rustls-wolfcrypt-provider**: Crate containing the code that lets you use rustls with wolfcrypt as a crypto provider. -- **wolfcrypt-rs**: Low-level unsafe bindings for wolfcrypt generated using bindgen. + +It calls wolfCrypt through the official [`wolfssl-wolfcrypt`](https://github.com/wolfSSL/wolfssl/tree/master/wrapper/rust/wolfssl-wolfcrypt) crate, which links an installed wolfSSL. ## Cipher Suites (Currently) Supported @@ -35,7 +36,7 @@ For more details about the supported curves, verification/signing methods, and a ## Usage ### Initial Setup and Installation -*Rustc 1.77+ is required.* +*Rustc 1.85+ is required.* 1. Clone the repository: ``` @@ -43,19 +44,26 @@ For more details about the supported curves, verification/signing methods, and a cd rustls-wolfcrypt-provider/ ``` -2. Build the wolfcrypt-rs crate to correctly generate the bindings and make sure - the build was successful by running the sanity check(s): +2. Build and install wolfSSL as a shared library (from a checkout of + [wolfSSL](https://github.com/wolfSSL/wolfssl)): ``` - cd wolfcrypt-rs/ - make build - make test + ./autogen.sh + ./configure --prefix= --enable-all-crypto --enable-shared \ + --disable-static CPPFLAGS=-DWOLFSSL_RSA_KEY_CHECK + make + make install ``` - Then change the current directory to the rustls-wolfcrypt-provider, build - the crate, followed by running the test to make sure everything is running - smoothly: +3. Build the crate and run the tests. `WOLFSSL_PREFIX` tells the wolfCrypt + crate where wolfSSL is installed, and the library directory must be on the + loader path. The end-to-end tests run wolfSSL's example server + (`WOLFSSL_SERVER`) from the wolfSSL source tree (`WOLFSSL_SRC`): ``` - cd ../rustls-wolfcrypt-provider/ + export WOLFSSL_PREFIX= + export LD_LIBRARY_PATH=$WOLFSSL_PREFIX/lib # DYLD_LIBRARY_PATH on macOS + export WOLFSSL_SRC= + export WOLFSSL_SERVER=$WOLFSSL_SRC/examples/server/server + cd rustls-wolfcrypt-provider/ make build make test ``` diff --git a/rustls-wolfcrypt-provider/Cargo.lock b/rustls-wolfcrypt-provider/Cargo.lock index 762a6ee..b6156cd 100644 --- a/rustls-wolfcrypt-provider/Cargo.lock +++ b/rustls-wolfcrypt-provider/Cargo.lock @@ -2,16 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common 0.1.7", - "generic-array", -] - [[package]] name = "aho-corasick" version = "1.1.4" @@ -35,9 +25,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.16.2" +version = "1.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +checksum = "faac5829c2b74c28f830747e7818ccfb684261b5f48a1118b1e2a13d36dfab13" dependencies = [ "aws-lc-sys", "zeroize", @@ -45,22 +35,17 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.39.1" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +checksum = "f1622d8446a2d4b2ce0c7eefc73dd43a99779028d5ee5c2dd8073a658ba8a2bc" dependencies = [ "cc", "cmake", "dunce", "fs_extra", + "pkg-config", ] -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - [[package]] name = "base64" version = "0.22.1" @@ -75,9 +60,9 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bindgen" -version = "0.71.1" +version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ "bitflags", "cexpr", @@ -99,24 +84,6 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" -dependencies = [ - "hybrid-array", -] - [[package]] name = "bytes" version = "1.11.1" @@ -150,41 +117,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures 0.2.17", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common 0.1.7", - "inout", - "zeroize", -] - [[package]] name = "clang-sys" version = "1.8.1" @@ -211,30 +143,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "const-oid" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "cpufeatures" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" -dependencies = [ - "libc", -] - [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -260,37 +168,6 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "crypto-common" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" -dependencies = [ - "hybrid-array", -] - [[package]] name = "data-encoding" version = "2.10.0" @@ -303,7 +180,7 @@ version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "const-oid 0.9.6", + "const-oid", "zeroize", ] @@ -316,71 +193,18 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "const-oid 0.9.6", - "crypto-common 0.1.7", - "subtle", -] - -[[package]] -name = "digest" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" -dependencies = [ - "block-buffer 0.12.0", - "const-oid 0.10.2", - "crypto-common 0.2.1", -] - [[package]] name = "dunce" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "elliptic-curve", - "signature", - "spki", -] - [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "pkcs8", - "rand_core", - "sec1", - "subtle", - "zeroize", -] - [[package]] name = "env_filter" version = "1.0.1" @@ -400,16 +224,6 @@ dependencies = [ "log", ] -[[package]] -name = "ff" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" -dependencies = [ - "rand_core", - "subtle", -] - [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -449,17 +263,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - [[package]] name = "getrandom" version = "0.2.17" @@ -489,17 +292,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core", - "subtle", -] - [[package]] name = "hermit-abi" version = "0.5.2" @@ -518,33 +310,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "hybrid-array" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" -dependencies = [ - "typenum", -] - -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "generic-array", -] - [[package]] name = "itertools" version = "0.13.0" @@ -575,9 +340,6 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin", -] [[package]] name = "libc" @@ -595,12 +357,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - [[package]] name = "lock_api" version = "0.4.14" @@ -649,48 +405,12 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "num-bigint-dig" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" -dependencies = [ - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand", - "smallvec", - "zeroize", -] - [[package]] name = "num-conv" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -698,7 +418,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -717,12 +436,6 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - [[package]] name = "parking_lot" version = "0.12.5" @@ -762,17 +475,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - [[package]] name = "pkcs8" version = "0.10.2" @@ -784,15 +486,10 @@ dependencies = [ ] [[package]] -name = "poly1305" -version = "0.8.0" +name = "pkg-config" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures 0.2.17", - "opaque-debug", - "universal-hash", -] +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" [[package]] name = "powerfmt" @@ -800,15 +497,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "prettyplease" version = "0.2.37" @@ -843,35 +531,6 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "rand" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", -] - [[package]] name = "rayon" version = "1.11.0" @@ -957,27 +616,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rsa" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" -dependencies = [ - "const-oid 0.9.6", - "digest 0.10.7", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core", - "sha2 0.10.9", - "signature", - "spki", - "subtle", - "zeroize", -] - [[package]] name = "rustc-hash" version = "2.1.2" @@ -986,9 +624,9 @@ checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustls" -version = "0.23.37" +version = "0.23.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" dependencies = [ "aws-lc-rs", "log", @@ -1019,9 +657,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.13" +version = "0.103.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" dependencies = [ "aws-lc-rs", "ring", @@ -1034,32 +672,26 @@ name = "rustls-wolfcrypt-provider" version = "0.1.0" dependencies = [ "anyhow", - "chacha20poly1305", "der", - "ecdsa", "env_logger", "foreign-types", "hex", "hex-literal", - "hmac", "lazy_static", "log", "num_cpus", "pkcs8", - "rand_core", "rayon", "rcgen", - "rsa", "rustls", "rustls-pemfile", "rustls-pki-types", "rustls-webpki", "serial_test", - "sha2 0.10.9", "signature", "tokio", "webpki-roots 0.26.11", - "wolfcrypt-rs", + "wolfssl-wolfcrypt", "wycheproof", "zeroize", ] @@ -1085,20 +717,6 @@ version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - [[package]] name = "serde" version = "1.0.228" @@ -1165,28 +783,6 @@ dependencies = [ "syn", ] -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "digest 0.11.2", -] - [[package]] name = "shlex" version = "1.3.0" @@ -1198,10 +794,6 @@ name = "signature" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core", -] [[package]] name = "smallvec" @@ -1219,12 +811,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - [[package]] name = "spki" version = "0.7.3" @@ -1297,40 +883,18 @@ dependencies = [ "syn", ] -[[package]] -name = "typenum" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" - [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common 0.1.7", - "subtle", -] - [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -1459,11 +1023,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] -name = "wolfcrypt-rs" -version = "0.1.0" +name = "wolfssl-wolfcrypt" +version = "2.2.0" +source = "git+https://github.com/wolfSSL/wolfssl#a4800697f84478482a8f9fea015a2d5b84b19c46" dependencies = [ "bindgen", - "sha2 0.11.0", + "num-traits", + "regex", + "zeroize", ] [[package]] @@ -1486,26 +1053,6 @@ dependencies = [ "time", ] -[[package]] -name = "zerocopy" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zeroize" version = "1.8.2" diff --git a/rustls-wolfcrypt-provider/Cargo.toml b/rustls-wolfcrypt-provider/Cargo.toml index 5c809e3..a061ce6 100644 --- a/rustls-wolfcrypt-provider/Cargo.toml +++ b/rustls-wolfcrypt-provider/Cargo.toml @@ -2,23 +2,18 @@ name = "rustls-wolfcrypt-provider" version = "0.1.0" edition = "2021" +rust-version = "1.85" [dependencies] -rustls = { version = "0.23.22", default-features = false, features = ["tls12"] } -chacha20poly1305 = { version = "0.10", default-features = false, features = ["alloc"] } -der = { version = "0.7", default-features = false } -ecdsa = { version = "0.16.9", default-features = false, features = ["alloc"] } -hmac = { version = "0.12", default-features = false } +rustls = { version = "0.23.45", default-features = false, features = ["tls12"] } +der = { version = "0.7", default-features = false } pkcs8 = { version = "0.10.2", default-features = false } -rand_core = { version = "0.6", default-features = false, features = ["getrandom", "alloc"] } -rsa = { version = "0.9", features = ["sha2"], default-features = false } -sha2 = { version = "0.10", default-features = false } signature = { version = "2", default-features = false } webpki = { package = "rustls-webpki", version = "0.103.13", features = ["alloc"], default-features = false } foreign-types = { version = "0.5.0", default-features = false } rustls-pki-types = { version = "1.11.0", default-features = false } log = { version = "0.4.25", default-features = false } -wolfcrypt-rs = { path = "../wolfcrypt-rs" } +wolfssl-wolfcrypt = { git = "https://github.com/wolfSSL/wolfssl" } zeroize = { version = "1", default-features = false, features = ["alloc", "derive"] } [dev-dependencies] @@ -37,12 +32,12 @@ rcgen = { version = "0.13" } serial_test = { version = "3.2.0", default-features = false } tokio = { version = "1.43", features = ["macros", "rt", "net", "io-util", "io-std"], default-features = false } webpki-roots = { version = "0.26", default-features = false } -rustls = { version = "0.23.22", features = ["std", "tls12"] } +rustls = { version = "0.23.45", features = ["std", "tls12"] } rustls-pemfile = { version = "2.2.0", default-features = false, features = ["std"]} [features] default = [] -std = ["pkcs8/std", "rustls/std", "wolfcrypt-rs/std"] +std = ["pkcs8/std", "rustls/std"] quic = [] [profile.release] diff --git a/rustls-wolfcrypt-provider/Makefile b/rustls-wolfcrypt-provider/Makefile index 9aa6973..a7fe26b 100644 --- a/rustls-wolfcrypt-provider/Makefile +++ b/rustls-wolfcrypt-provider/Makefile @@ -6,6 +6,10 @@ test: test-quic: @cargo test --features quic +.PHONY: test-std +test-std: + @cargo test --features std + .PHONY: build build: @cargo build --release diff --git a/rustls-wolfcrypt-provider/src/aead/aes128gcm.rs b/rustls-wolfcrypt-provider/src/aead/aes128gcm.rs index 585dfa5..6d02992 100644 --- a/rustls-wolfcrypt-provider/src/aead/aes128gcm.rs +++ b/rustls-wolfcrypt-provider/src/aead/aes128gcm.rs @@ -15,7 +15,7 @@ use zeroize::Zeroizing; use alloc::vec::Vec; use core::ptr; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; const GCM_NONCE_LENGTH: usize = 12; const GCM_TAG_LENGTH: usize = 16; diff --git a/rustls-wolfcrypt-provider/src/aead/aes256gcm.rs b/rustls-wolfcrypt-provider/src/aead/aes256gcm.rs index 6f1f7bd..afce7c4 100644 --- a/rustls-wolfcrypt-provider/src/aead/aes256gcm.rs +++ b/rustls-wolfcrypt-provider/src/aead/aes256gcm.rs @@ -15,7 +15,7 @@ use zeroize::Zeroizing; use alloc::vec::Vec; use core::ptr; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; const GCM_NONCE_LENGTH: usize = 12; const GCM_TAG_LENGTH: usize = 16; diff --git a/rustls-wolfcrypt-provider/src/aead/chacha20.rs b/rustls-wolfcrypt-provider/src/aead/chacha20.rs index 6dd3072..e9c5e68 100644 --- a/rustls-wolfcrypt-provider/src/aead/chacha20.rs +++ b/rustls-wolfcrypt-provider/src/aead/chacha20.rs @@ -1,7 +1,6 @@ use alloc::boxed::Box; use alloc::vec; use alloc::vec::Vec; -use chacha20poly1305::KeySizeUser; use core::mem; use rustls::crypto::cipher::{ make_tls12_aad, make_tls13_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, @@ -10,7 +9,7 @@ use rustls::crypto::cipher::{ UnsupportedOperationError, NONCE_LEN, }; use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion}; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; use crate::error::check_if_zero; use zeroize::Zeroizing; @@ -202,7 +201,7 @@ impl Tls13AeadAlgorithm for Chacha20Poly1305 { } fn key_len(&self) -> usize { - chacha20poly1305::ChaCha20Poly1305::key_size() + CHACHA20_POLY1305_AEAD_KEYSIZE as usize } fn extract_keys( diff --git a/rustls-wolfcrypt-provider/src/aead/quic.rs b/rustls-wolfcrypt-provider/src/aead/quic.rs index 4aeb23b..46c4dd5 100644 --- a/rustls-wolfcrypt-provider/src/aead/quic.rs +++ b/rustls-wolfcrypt-provider/src/aead/quic.rs @@ -17,7 +17,7 @@ use core::ptr; use rustls::crypto::cipher::{Iv, Nonce}; use rustls::quic::Tag; use rustls::{crypto::cipher::AeadKey, quic, Error}; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; type PktEncFn = fn(packet_cipher: &Cipher, nonce: &[u8], aad: &[u8], in_out: &mut [u8]) -> Result; @@ -117,10 +117,8 @@ fn generate_mask_aes(hp_cipher: &Cipher, sample: &[u8]) -> Result<[u8; MASK_LEN] }; let mut mask = mask_array!(); - match aes_cipher.encrypt_sample(sample) { - Ok(output) => mask.copy_from_slice(&output[..5]), - Err(e) => return Err(e), - } + let output = aes_cipher.encrypt_sample(sample)?; + mask.copy_from_slice(&output[..5]); Ok(mask) } @@ -145,10 +143,8 @@ fn generate_mask_chacha20(hp_cipher: &Cipher, sample: &[u8]) -> Result<[u8; MASK }; let mut mask = mask_array!(); - match chacha20_cipher.encrypt_sample(sample) { - Ok(output) => mask.copy_from_slice(&output[..5]), - Err(e) => return Err(e), - } + let output = chacha20_cipher.encrypt_sample(sample)?; + mask.copy_from_slice(&output[..5]); Ok(mask) } diff --git a/rustls-wolfcrypt-provider/src/hash/sha256.rs b/rustls-wolfcrypt-provider/src/hash/sha256.rs index c544187..4984efc 100644 --- a/rustls-wolfcrypt-provider/src/hash/sha256.rs +++ b/rustls-wolfcrypt-provider/src/hash/sha256.rs @@ -5,7 +5,7 @@ use core::mem; use foreign_types::ForeignType; use rustls::crypto::hash; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; pub struct WCSha256; diff --git a/rustls-wolfcrypt-provider/src/hash/sha384.rs b/rustls-wolfcrypt-provider/src/hash/sha384.rs index c42953d..e054528 100644 --- a/rustls-wolfcrypt-provider/src/hash/sha384.rs +++ b/rustls-wolfcrypt-provider/src/hash/sha384.rs @@ -2,7 +2,7 @@ use alloc::boxed::Box; use core::mem; use foreign_types::ForeignType; use rustls::crypto::hash; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; use crate::error::check_if_zero; use crate::types::*; diff --git a/rustls-wolfcrypt-provider/src/hkdf.rs b/rustls-wolfcrypt-provider/src/hkdf.rs index 0e5a414..738fb24 100644 --- a/rustls-wolfcrypt-provider/src/hkdf.rs +++ b/rustls-wolfcrypt-provider/src/hkdf.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use core::mem; use foreign_types::ForeignType; use rustls::crypto::tls13::{self, Hkdf as RustlsHkdf}; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; use crate::error::check_if_zero; use crate::hmac::WCShaHmac; @@ -35,7 +35,7 @@ impl RustlsHkdf for WCHkdfUsingHmac { let ret = unsafe { wc_HKDF_Extract( - self.0.hash_type().try_into().unwrap(), + self.0.hash_type(), salt_bytes.as_ptr(), salt_bytes.len() as u32, ikm.as_ptr(), @@ -47,7 +47,7 @@ impl RustlsHkdf for WCHkdfUsingHmac { Box::new(WolfHkdfExpander::new( Zeroizing::new(extracted_key), - self.0.hash_type().try_into().unwrap(), + self.0.hash_type(), self.0.hash_len(), )) } @@ -58,7 +58,7 @@ impl RustlsHkdf for WCHkdfUsingHmac { ) -> Box { Box::new(WolfHkdfExpander { extracted_key: Zeroizing::new(okm.as_ref().to_vec()), - hash_type: self.0.hash_type().try_into().unwrap(), + hash_type: self.0.hash_type(), hash_len: self.0.hash_len(), }) } @@ -75,7 +75,7 @@ impl RustlsHkdf for WCHkdfUsingHmac { let mut ret = unsafe { wc_HmacSetKey( hmac_object.as_ptr(), - self.0.hash_type().try_into().unwrap(), + self.0.hash_type(), key.as_ref().as_ptr(), key.as_ref().len() as u32, ) @@ -173,7 +173,7 @@ mod tests { "34007208d5b887185865" ); - let hkdf = WCHkdfUsingHmac(WCShaHmac::new(wc_HashType_WC_HASH_TYPE_SHA256)); + let hkdf = WCHkdfUsingHmac(WCShaHmac::Sha256); let expander = hkdf.extract_from_secret(Some(&salt), &ikm); let mut okm = vec![0u8; 42]; // Length from test vector @@ -191,7 +191,7 @@ mod tests { let salt = hex!("000102030405060708090a0b0c"); let info = hex!("f0f1f2f3f4f5f6f7f8f9"); - let hkdf = WCHkdfUsingHmac(WCShaHmac::new(wc_HashType_WC_HASH_TYPE_SHA384)); + let hkdf = WCHkdfUsingHmac(WCShaHmac::Sha384); let expander = hkdf.extract_from_secret(Some(&salt), &ikm); let mut okm = vec![0u8; 48]; // SHA384 output length @@ -205,7 +205,7 @@ mod tests { /// The limit is 255 times the hash length as specified in RFC 5869 #[test] fn test_hkdf_output_length_limit() { - let hkdf = WCHkdfUsingHmac(WCShaHmac::new(wc_HashType_WC_HASH_TYPE_SHA256)); + let hkdf = WCHkdfUsingHmac(WCShaHmac::Sha256); let expander = hkdf.extract_from_zero_ikm(None); // Maximum allowed length (255 * hash_len) @@ -222,7 +222,7 @@ mod tests { /// This is important for TLS 1.3 which sometimes requires derivation from zero IKM #[test] fn test_hkdf_zero_ikm() { - let hkdf = WCHkdfUsingHmac(WCShaHmac::new(wc_HashType_WC_HASH_TYPE_SHA256)); + let hkdf = WCHkdfUsingHmac(WCShaHmac::Sha256); let salt = hex!("000102030405060708090a0b0c"); let info = hex!("f0f1f2f3f4f5f6f7f8f9"); @@ -243,7 +243,7 @@ mod tests { /// Verifies that passing multiple info slices produces the same result as their concatenation #[test] fn test_hkdf_multiple_info_components() { - let hkdf = WCHkdfUsingHmac(WCShaHmac::new(wc_HashType_WC_HASH_TYPE_SHA256)); + let hkdf = WCHkdfUsingHmac(WCShaHmac::Sha256); let salt = hex!("000102030405060708090a0b0c"); let info1 = hex!("f0f1f2f3"); let info2 = hex!("f4f5f6f7"); diff --git a/rustls-wolfcrypt-provider/src/hmac/mod.rs b/rustls-wolfcrypt-provider/src/hmac/mod.rs index 9c214b9..b617b92 100644 --- a/rustls-wolfcrypt-provider/src/hmac/mod.rs +++ b/rustls-wolfcrypt-provider/src/hmac/mod.rs @@ -4,7 +4,8 @@ use alloc::{boxed::Box, vec, vec::Vec}; use core::mem; use foreign_types::ForeignType; use rustls::crypto; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::hmac::HMAC; +use wolfssl_wolfcrypt::sys::*; use zeroize::Zeroizing; #[derive(Clone, Copy)] @@ -21,25 +22,10 @@ impl WCShaHmac { } } - fn algorithm(&self) -> i32 { + pub fn hash_type(&self) -> i32 { match self { - WCShaHmac::Sha256 => wc_HashType_WC_HASH_TYPE_SHA256.try_into().unwrap(), - WCShaHmac::Sha384 => wc_HashType_WC_HASH_TYPE_SHA384.try_into().unwrap(), - } - } - - pub fn new(hash_type: wc_HashType) -> Self { - match hash_type { - wolfcrypt_rs::wc_HashType_WC_HASH_TYPE_SHA256 => WCShaHmac::Sha256, - wolfcrypt_rs::wc_HashType_WC_HASH_TYPE_SHA384 => WCShaHmac::Sha384, - _ => panic!("Unsupported hash type"), - } - } - - pub fn hash_type(&self) -> wc_HashType { - match self { - WCShaHmac::Sha256 => wc_HashType_WC_HASH_TYPE_SHA256, - WCShaHmac::Sha384 => wc_HashType_WC_HASH_TYPE_SHA384, + WCShaHmac::Sha256 => HMAC::TYPE_SHA256, + WCShaHmac::Sha384 => HMAC::TYPE_SHA384, } } @@ -94,7 +80,7 @@ impl WCHmacKey { let ret = unsafe { wc_HmacSetKey( hmac_object.as_ptr(), - self.variant.algorithm(), + self.variant.hash_type(), self.key.as_ptr(), self.key.len() as word32, ) diff --git a/rustls-wolfcrypt-provider/src/kx/sec256r1.rs b/rustls-wolfcrypt-provider/src/kx/sec256r1.rs index c9c08cc..e0d6e56 100644 --- a/rustls-wolfcrypt-provider/src/kx/sec256r1.rs +++ b/rustls-wolfcrypt-provider/src/kx/sec256r1.rs @@ -3,7 +3,7 @@ use alloc::boxed::Box; use core::mem; use core::ptr; use foreign_types::ForeignType; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; use zeroize::Zeroizing; pub struct KeyExchangeSecP256r1 { diff --git a/rustls-wolfcrypt-provider/src/kx/sec384r1.rs b/rustls-wolfcrypt-provider/src/kx/sec384r1.rs index a9a178d..3e2242e 100644 --- a/rustls-wolfcrypt-provider/src/kx/sec384r1.rs +++ b/rustls-wolfcrypt-provider/src/kx/sec384r1.rs @@ -4,7 +4,7 @@ use alloc::boxed::Box; use core::mem; use core::ptr; use foreign_types::ForeignType; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; use zeroize::Zeroizing; pub struct KeyExchangeSecP384r1 { diff --git a/rustls-wolfcrypt-provider/src/kx/sec521r1.rs b/rustls-wolfcrypt-provider/src/kx/sec521r1.rs index df06a55..0c44051 100644 --- a/rustls-wolfcrypt-provider/src/kx/sec521r1.rs +++ b/rustls-wolfcrypt-provider/src/kx/sec521r1.rs @@ -3,7 +3,7 @@ use alloc::boxed::Box; use core::mem; use core::ptr; use foreign_types::ForeignType; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; use zeroize::Zeroizing; pub struct KeyExchangeSecP521r1 { diff --git a/rustls-wolfcrypt-provider/src/kx/x25519.rs b/rustls-wolfcrypt-provider/src/kx/x25519.rs index 5042a72..91e797a 100644 --- a/rustls-wolfcrypt-provider/src/kx/x25519.rs +++ b/rustls-wolfcrypt-provider/src/kx/x25519.rs @@ -1,165 +1,61 @@ -use crate::{error::check_if_zero, types::*}; use alloc::boxed::Box; -use core::mem; -use foreign_types::ForeignType; -use wolfcrypt_rs::*; -use zeroize::Zeroizing; +use wolfssl_wolfcrypt::curve25519::Curve25519Key; +use wolfssl_wolfcrypt::random::RNG; + +/// The generated key, kept for the whole exchange along with the RNG it was +/// generated with, which wolfSSL uses when curve25519 blinding is built in. +struct X25519Key(Curve25519Key); + +// SAFETY: the key owns everything its pointers refer to (including its RNG), +// and is only used through `&mut`. +unsafe impl Send for X25519Key {} +unsafe impl Sync for X25519Key {} pub struct KeyExchangeX25519 { pub_key_bytes: Box<[u8]>, - priv_key_bytes: Zeroizing>, + key: X25519Key, } impl KeyExchangeX25519 { pub fn use_curve25519() -> Result { - let mut key: curve25519_key = unsafe { mem::zeroed() }; - let key_object = Curve25519KeyObject::new(&mut key); - let mut rng: WC_RNG = unsafe { mem::zeroed() }; - let rng_object = WCRngObject::new(&mut rng); - let mut ret; - let mut pub_key_raw: [u8; 32] = [0; 32]; - let mut pub_key_raw_len: word32 = pub_key_raw.len() as word32; - // Export the private key straight into a zeroizing heap buffer so the - // raw secret never lives in an un-wiped stack array. - let mut priv_key_raw: Zeroizing> = - Zeroizing::new(alloc::vec![0u8; 32].into_boxed_slice()); - let mut priv_key_raw_len: word32 = priv_key_raw.len() as word32; - let endian: u32 = EC25519_LITTLE_ENDIAN; - - // We initialize the curve25519 key object. - key_object - .init() - .map_err(|_| rustls::Error::General("wc_curve25519_init failed".into()))?; - - // We initialize the rng object. - rng_object - .init() - .map_err(|_| rustls::Error::General("wc_InitRng failed".into()))?; - - // This function generates a Curve25519 key using the given random number generator, rng, - // of the size given (keysize), and stores it in the given curve25519_key structure. - ret = unsafe { wc_curve25519_make_key(rng_object.as_ptr(), 32, key_object.as_ptr()) }; - check_if_zero(ret) + let rng = RNG::new().map_err(|_| rustls::Error::General("wc_InitRng failed".into()))?; + let mut key = Curve25519Key::generate(rng) .map_err(|_| rustls::Error::General("wc_curve25519_make_key failed".into()))?; - // Export curve25519 key pair. Big or little endian. - ret = unsafe { - wc_curve25519_export_key_raw_ex( - key_object.as_ptr(), - priv_key_raw.as_mut_ptr(), - &mut priv_key_raw_len, - pub_key_raw.as_mut_ptr(), - &mut pub_key_raw_len, - endian.try_into().unwrap(), - ) - }; - check_if_zero(ret) - .map_err(|_| rustls::Error::General("wc_curve25519_export_key_raw_ex failed".into()))?; + let mut pub_key_raw = [0u8; Curve25519Key::KEYSIZE]; + key.export_public_ex(&mut pub_key_raw, false) + .map_err(|_| rustls::Error::General("wc_curve25519_export_public_ex failed".into()))?; Ok(KeyExchangeX25519 { pub_key_bytes: Box::new(pub_key_raw), - priv_key_bytes: priv_key_raw, + key: X25519Key(key), }) } - pub fn derive_shared_secret(&self, peer_pub_key: &[u8]) -> Result, rustls::Error> { - if peer_pub_key.len() != 32 { + pub fn derive_shared_secret( + &mut self, + peer_pub_key: &[u8], + ) -> Result, rustls::Error> { + if peer_pub_key.len() != Curve25519Key::KEYSIZE { return Err(rustls::Error::General( "Invalid peer public key length".into(), )); } - let mut ret; - let endian: u32 = EC25519_LITTLE_ENDIAN; - let mut pub_key_provided: curve25519_key = unsafe { mem::zeroed() }; - let pub_key_provided_object = Curve25519KeyObject::new(&mut pub_key_provided); - let mut out: [u8; 32] = [0; 32]; - let mut out_len: word32 = out.len() as word32; - let mut private_key: curve25519_key = unsafe { mem::zeroed() }; - let private_key_object = Curve25519KeyObject::new(&mut private_key); - - // This function checks that a public key buffer holds a valid - // Curve25519 key value given the endian ordering. - ret = unsafe { - wc_curve25519_check_public( - peer_pub_key.as_ptr(), - peer_pub_key.len() as word32, - endian.try_into().unwrap(), - ) - }; - check_if_zero(ret) + Curve25519Key::check_public(peer_pub_key, false) .map_err(|_| rustls::Error::General("Invalid Curve25519 public key".into()))?; - // We initialize the curve25519 key object before we import the public key in it. - pub_key_provided_object - .init() - .map_err(|_| rustls::Error::General("wc_curve25519_init failed".into()))?; - - // This function imports a public key from the given input buffer - // and stores it in the curve25519_key structure. - ret = unsafe { - wc_curve25519_import_public_ex( - peer_pub_key.as_ptr(), - peer_pub_key.len() as word32, - pub_key_provided_object.as_ptr(), - endian.try_into().unwrap(), - ) - }; - check_if_zero(ret) + let mut peer_key = Curve25519Key::import_public_ex(peer_pub_key, false) .map_err(|_| rustls::Error::General("Failed to import Curve25519 public key".into()))?; - // We initialize the curve25519 key object before we import the private key in it. - private_key_object - .init() - .map_err(|_| rustls::Error::General("wc_curve25519_init failed".into()))?; - - // This function imports a private key from the given input buffer - // and stores it in the the curve25519_key structure. - ret = unsafe { - wc_curve25519_import_private_ex( - self.priv_key_bytes.as_ptr(), - self.priv_key_bytes.len() as word32, - private_key_object.as_ptr(), - endian.try_into().unwrap(), - ) - }; - check_if_zero(ret).map_err(|_| { - rustls::Error::General("Failed to import Curve25519 private key".into()) - })?; - - // When wolfSSL is built with curve25519 blinding (pure-C builds, e.g. - // Apple Silicon where no asm backend is selected), the shared-secret - // scalar multiplication draws random values to blind the private - // scalar. An imported key has no RNG attached, so we must supply one; - // otherwise wc_curve25519_shared_secret_ex returns BAD_FUNC_ARG (-173). - // On non-blinding (asm) builds curve25519_set_rng is a no-op. - let mut rng: WC_RNG = unsafe { mem::zeroed() }; - let rng_object = WCRngObject::new(&mut rng); - rng_object - .init() - .map_err(|_| rustls::Error::General("wc_InitRng failed".into()))?; - - ret = unsafe { curve25519_set_rng(private_key_object.as_ptr(), rng_object.as_ptr()) }; - check_if_zero(ret).map_err(|_| { - rustls::Error::General("Failed to set RNG on Curve25519 private key".into()) - })?; - - // This function computes a shared secret key given a secret private key and - // a received public key. Stores the generated secret in the buffer out. - ret = unsafe { - wc_curve25519_shared_secret_ex( - private_key_object.as_ptr(), - pub_key_provided_object.as_ptr(), - out.as_mut_ptr(), - &mut out_len, - endian.try_into().unwrap(), - ) - }; - check_if_zero(ret).map_err(|_| { - rustls::Error::General(alloc::format!( - "Failed to compute Curve25519 shared secret (ret = {ret})" - )) - })?; + let mut out = [0u8; Curve25519Key::KEYSIZE]; + Curve25519Key::shared_secret_ex(&mut self.key.0, &mut peer_key, &mut out, false).map_err( + |ret| { + rustls::Error::General(alloc::format!( + "Failed to compute Curve25519 shared secret (ret = {ret})" + )) + }, + )?; Ok(Box::new(out)) } @@ -167,7 +63,7 @@ impl KeyExchangeX25519 { impl rustls::crypto::ActiveKeyExchange for KeyExchangeX25519 { fn complete( - self: Box, + mut self: Box, peer_pub_key: &[u8], ) -> Result { // We derive the shared secret with our private key and @@ -193,12 +89,14 @@ mod tests { #[test] fn test_curve25519_kx() { - let alice = Box::new(KeyExchangeX25519::use_curve25519().unwrap()); - let bob = Box::new(KeyExchangeX25519::use_curve25519().unwrap()); + let mut alice = Box::new(KeyExchangeX25519::use_curve25519().unwrap()); + let mut bob = Box::new(KeyExchangeX25519::use_curve25519().unwrap()); + let alice_pub = alice.pub_key().to_vec(); + let bob_pub = bob.pub_key().to_vec(); assert_eq!( - alice.derive_shared_secret(bob.pub_key()).unwrap(), - bob.derive_shared_secret(alice.pub_key()).unwrap(), + alice.derive_shared_secret(&bob_pub).unwrap(), + bob.derive_shared_secret(&alice_pub).unwrap(), ) } } diff --git a/rustls-wolfcrypt-provider/src/lib.rs b/rustls-wolfcrypt-provider/src/lib.rs index 0d5ae81..49eef77 100644 --- a/rustls-wolfcrypt-provider/src/lib.rs +++ b/rustls-wolfcrypt-provider/src/lib.rs @@ -1,7 +1,7 @@ #![cfg_attr(not(test), no_std)] extern crate alloc; -#[cfg(test)] +#[cfg(any(test, feature = "std"))] extern crate std; use alloc::boxed::Box; diff --git a/rustls-wolfcrypt-provider/src/prf.rs b/rustls-wolfcrypt-provider/src/prf.rs index 5da8ac7..182d65d 100644 --- a/rustls-wolfcrypt-provider/src/prf.rs +++ b/rustls-wolfcrypt-provider/src/prf.rs @@ -1,6 +1,6 @@ use alloc::boxed::Box; use rustls::crypto; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; use crate::error::check_if_zero; use crate::hmac::*; diff --git a/rustls-wolfcrypt-provider/src/random.rs b/rustls-wolfcrypt-provider/src/random.rs index a629b71..6f7d881 100644 --- a/rustls-wolfcrypt-provider/src/random.rs +++ b/rustls-wolfcrypt-provider/src/random.rs @@ -1,9 +1,46 @@ use crate::error::*; +#[cfg(not(feature = "std"))] use crate::types::*; +#[cfg(not(feature = "std"))] use core::mem; +#[cfg(not(feature = "std"))] use foreign_types::ForeignType; -use wolfcrypt_rs::*; +#[cfg(not(feature = "std"))] +use wolfssl_wolfcrypt::sys::*; +// wolfCrypt rejects larger requests (RNG_MAX_BLOCK_LEN). +#[cfg(feature = "std")] +const MAX_CHUNK: usize = 0xFFFF; + +#[cfg(feature = "std")] +std::thread_local! { + static THREAD_RNG: std::cell::RefCell> = + const { std::cell::RefCell::new(None) }; +} + +/// With `std`, one wolfCrypt RNG per thread, created on first use, instead of a +/// new one (seeded from the OS) on every call. A failed creation is retried on +/// the next call. +#[cfg(feature = "std")] +pub fn wolfcrypt_random_buffer_generator(buff: &mut [u8]) -> WCResult { + use wolfssl_wolfcrypt::random::RNG; + + let result = THREAD_RNG + .try_with(|cell| { + let mut cell = cell.borrow_mut(); + if cell.is_none() { + *cell = Some(RNG::new()?); + } + let rng = cell.as_ref().unwrap(); + buff.chunks_mut(MAX_CHUNK) + .try_for_each(|chunk| rng.generate_block(chunk)) + }) + .unwrap_or(Err(-1)); + + check_if_zero(result.err().unwrap_or(0)) +} + +#[cfg(not(feature = "std"))] pub fn wolfcrypt_random_buffer_generator(buff: &mut [u8]) -> WCResult { let mut rng_c_type: WC_RNG = unsafe { mem::zeroed() }; let rng_object = WCRngObject::new(&mut rng_c_type); @@ -38,4 +75,24 @@ mod tests { assert_ne!(buff_1, buff_2); } + + #[cfg(feature = "std")] + #[test] + fn test_random_reuses_thread_rng() { + let mut buff = [0u8; 10]; + wolfcrypt_random_buffer_generator(&mut buff).unwrap(); + + assert!(super::THREAD_RNG.with(|cell| cell.borrow().is_some())); + } + + #[cfg(feature = "std")] + #[test] + fn test_random_larger_than_one_chunk() { + let mut buff = std::vec![0u8; 2 * super::MAX_CHUNK + 10]; + wolfcrypt_random_buffer_generator(&mut buff).unwrap(); + + for chunk in buff.chunks(super::MAX_CHUNK) { + assert!(chunk.iter().any(|&b| b != 0)); + } + } } diff --git a/rustls-wolfcrypt-provider/src/sign/ecdsa.rs b/rustls-wolfcrypt-provider/src/sign/ecdsa.rs index c178e80..f828ac1 100644 --- a/rustls-wolfcrypt-provider/src/sign/ecdsa.rs +++ b/rustls-wolfcrypt-provider/src/sign/ecdsa.rs @@ -14,7 +14,7 @@ use rustls::pki_types::PrivateKeyDer; use rustls::sign::{Signer, SigningKey}; use rustls::{SignatureAlgorithm, SignatureScheme}; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; use zeroize::Zeroizing; /// A unified ECDSA signing key that supports P-256, P-384, P-521. diff --git a/rustls-wolfcrypt-provider/src/sign/eddsa.rs b/rustls-wolfcrypt-provider/src/sign/eddsa.rs index 111bdea..a7c6c40 100644 --- a/rustls-wolfcrypt-provider/src/sign/eddsa.rs +++ b/rustls-wolfcrypt-provider/src/sign/eddsa.rs @@ -7,15 +7,21 @@ use alloc::vec::Vec; use core::fmt; use core::mem; use foreign_types::ForeignType; +use pkcs8::der::asn1::OctetStringRef; +use pkcs8::der::Decode; +use pkcs8::{ObjectIdentifier, PrivateKeyInfo}; use rustls::pki_types::PrivateKeyDer; use rustls::sign::{Signer, SigningKey}; use rustls::{SignatureAlgorithm, SignatureScheme}; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; use zeroize::Zeroizing; const ALL_EDDSA_SCHEMES: &[SignatureScheme] = &[SignatureScheme::ED25519]; +/// id-Ed25519 (RFC 8410). +const ED25519_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.101.112"); + /// An ED25519 private key with its optional embedded public key. type Ed25519KeyPair = (Zeroizing>, Option<[u8; 32]>); @@ -36,74 +42,29 @@ impl fmt::Debug for Ed25519PrivateKey { impl Ed25519PrivateKey { /// Extract ED25519 private and if available public key values from a PKCS#8 DER formatted key fn extract_key_pair(input_key: &[u8]) -> Result { - let mut private_key_raw: Zeroizing> = - Zeroizing::new(alloc::vec![0u8; ED25519_KEY_SIZE as usize]); - let mut private_key_raw_len: word32 = private_key_raw.len() as word32; - // Scratch buffer for the optional embedded public key. DecodeAsymKey - // reports it either as the bare 32-byte key, or as the raw DER BIT STRING - // body (a leading 0x00 "unused bits" octet + the 32-byte key = 33 bytes), - // so 33 bytes is the largest form we ever need to hold here. - let mut public_key_scratch: [u8; ED25519_PUB_KEY_SIZE as usize + 1] = - [0; ED25519_PUB_KEY_SIZE as usize + 1]; - let mut public_key_scratch_len: word32 = public_key_scratch.len() as word32; - let mut idx: word32 = 0; - - // Parse the PKCS#8 structure with wolfSSL's own ASN parser. This is the - // same parser wc_Ed25519PrivateKeyDecode uses internally, but calling it - // directly lets us normalise the embedded public key before it is imported. - // - // For an RFC 5958 (PKCS#8 v2) key that carries the optional public key, - // DecodeAsymKey hands back the [1] field as the raw DER BIT STRING body: - // a leading "unused bits" 0x00 octet followed by the 32-byte key (33 bytes - // total). wc_Ed25519PrivateKeyDecode passes that body verbatim to - // wc_ed25519_import_public_ex, which expects the key material itself, - // which is a bare 32-byte key (or a 0x40-prefixed 33-byte form). - // The 0x00-led 33-byte body matches neither, so it is rejected - // with BAD_FUNC_ARG (-173). So we strip the 0x00 octet here and - // hand on the bare 32-byte key instead. - let ret = unsafe { - DecodeAsymKey( - input_key.as_ptr(), - &mut idx, - input_key.len() as word32, - private_key_raw.as_mut_ptr(), - &mut private_key_raw_len, - public_key_scratch.as_mut_ptr(), - &mut public_key_scratch_len, - Key_Sum_ED25519k as i32, - ) - }; - check_if_zero(ret) - .map_err(|_| rustls::Error::General("DecodeAsymKey (ED25519) failed".into()))?; - - // Normalise the optional public key based on the length the parser reported. - let pub_key: Option<[u8; 32]> = match public_key_scratch_len { - // No embedded public key; the caller derives it from the private seed. - 0 => None, - // Bare 32-byte public key. - len if len == ED25519_PUB_KEY_SIZE => Some( - public_key_scratch[..ED25519_PUB_KEY_SIZE as usize] - .try_into() - .map_err(|_| { - rustls::Error::General("Unexpected ED25519 public key encoding".into()) - })?, - ), - // BIT STRING body: leading 0x00 "unused bits" octet + 32-byte key. - len if len == ED25519_PUB_KEY_SIZE + 1 && public_key_scratch[0] == 0x00 => Some( - public_key_scratch[1..1 + ED25519_PUB_KEY_SIZE as usize] - .try_into() - .map_err(|_| { - rustls::Error::General("Unexpected ED25519 public key encoding".into()) - })?, - ), - _ => { - return Err(rustls::Error::General( - "Unexpected ED25519 public key encoding".into(), - )) - } - }; + let bad_key = || rustls::Error::General("Invalid ED25519 PKCS#8 key".into()); + + // Parsed in Rust rather than with wc_Ed25519PrivateKeyDecode, which passes + // the embedded public key on with its leading BIT STRING "unused bits" + // octet, so the import rejects it. The pkcs8 crate strips that octet and + // checks that only a v2 key carries a public key. + let info = PrivateKeyInfo::try_from(input_key).map_err(|_| bad_key())?; + if info.algorithm.oid != ED25519_OID { + return Err(bad_key()); + } + + // The private key field holds the 32-byte key wrapped in an OCTET STRING. + let private_key = OctetStringRef::from_der(info.private_key).map_err(|_| bad_key())?; + if private_key.as_bytes().len() != ED25519_KEY_SIZE as usize { + return Err(bad_key()); + } + + let pub_key = info + .public_key + .map(|pk| pk.try_into().map_err(|_| bad_key())) + .transpose()?; - Ok((private_key_raw, pub_key)) + Ok((Zeroizing::new(private_key.as_bytes().to_vec()), pub_key)) } } @@ -261,3 +222,38 @@ impl Signer for Ed25519Signer { self.scheme } } + +#[cfg(test)] +mod tests { + use super::*; + use rustls::pki_types::PrivatePkcs8KeyDer; + + /// RFC 8410 section 10.3 example key (no embedded public key), with the + /// given PKCS#8 version: 0 is v1, 1 is v2. + fn pkcs8_without_public_key(version: u8) -> Vec { + let mut der = alloc::vec![ + 0x30, 0x2e, 0x02, 0x01, version, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x04, 0x22, + 0x04, 0x20, + ]; + der.extend_from_slice(&[ + 0xd4, 0xee, 0x72, 0xdb, 0xf9, 0x13, 0x58, 0x4a, 0xd5, 0xb6, 0xd8, 0xf1, 0xf7, 0x69, + 0xf8, 0xad, 0x3a, 0xfe, 0x7c, 0x28, 0xcb, 0xf1, 0xd4, 0xfb, 0xe0, 0x97, 0xa8, 0x8f, + 0x44, 0x75, 0x58, 0x42, + ]); + der + } + + fn load(der: &[u8]) -> Result { + Ed25519PrivateKey::try_from(&PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(der))) + } + + #[test] + fn test_v1_without_public_key_is_accepted() { + assert!(load(&pkcs8_without_public_key(0)).is_ok()); + } + + #[test] + fn test_v2_without_public_key_is_rejected() { + assert!(load(&pkcs8_without_public_key(1)).is_err()); + } +} diff --git a/rustls-wolfcrypt-provider/src/sign/rsa.rs b/rustls-wolfcrypt-provider/src/sign/rsa.rs index 2135be1..5c3b86e 100644 --- a/rustls-wolfcrypt-provider/src/sign/rsa.rs +++ b/rustls-wolfcrypt-provider/src/sign/rsa.rs @@ -13,7 +13,7 @@ use rustls::sign::{Signer, SigningKey}; use rustls::{SignatureAlgorithm, SignatureScheme}; use core::ptr; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; use zeroize::Zeroizing; const ALL_RSA_SCHEMES: &[SignatureScheme] = &[ diff --git a/rustls-wolfcrypt-provider/src/types/mod.rs b/rustls-wolfcrypt-provider/src/types/mod.rs index a9ca9a6..789ac0a 100644 --- a/rustls-wolfcrypt-provider/src/types/mod.rs +++ b/rustls-wolfcrypt-provider/src/types/mod.rs @@ -3,7 +3,7 @@ use core::ptr::NonNull; use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; use log::error; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; macro_rules! define_foreign_type { ($struct_name:ident, $ref_name:ident, $c_type:ty, $init_function:ident) => { @@ -181,7 +181,7 @@ define_foreign_type_no_copy!(RsaKeyObject, RsaKeyObjectRef, RsaKey, drop(wc_Free define_foreign_type_no_copy!( HmacObject, HmacObjectRef, - wolfcrypt_rs::Hmac, + wolfssl_wolfcrypt::sys::Hmac, drop_void(wc_HmacFree) ); define_foreign_type_no_copy!(AesObject, AesObjectRef, Aes, drop_void(wc_AesFree)); diff --git a/rustls-wolfcrypt-provider/src/verify/ecdsa.rs b/rustls-wolfcrypt-provider/src/verify/ecdsa.rs index a0d861d..8ca0c49 100644 --- a/rustls-wolfcrypt-provider/src/verify/ecdsa.rs +++ b/rustls-wolfcrypt-provider/src/verify/ecdsa.rs @@ -6,7 +6,7 @@ use foreign_types::ForeignType; use rustls::pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; use rustls::SignatureScheme; use rustls_pki_types::alg_id; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; /// A unified ECDSA verifier for P-256, P-384, and P-521. /// We store the `SignatureScheme` and switch logic accordingly. diff --git a/rustls-wolfcrypt-provider/src/verify/eddsa.rs b/rustls-wolfcrypt-provider/src/verify/eddsa.rs index 5728f81..122f9aa 100644 --- a/rustls-wolfcrypt-provider/src/verify/eddsa.rs +++ b/rustls-wolfcrypt-provider/src/verify/eddsa.rs @@ -3,7 +3,7 @@ use core::mem; use foreign_types::ForeignType; use rustls::pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; use rustls_pki_types::alg_id; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; #[derive(Debug)] pub struct Ed25519; diff --git a/rustls-wolfcrypt-provider/src/verify/rsapkcs1.rs b/rustls-wolfcrypt-provider/src/verify/rsapkcs1.rs index dd73fe7..cab0f9f 100644 --- a/rustls-wolfcrypt-provider/src/verify/rsapkcs1.rs +++ b/rustls-wolfcrypt-provider/src/verify/rsapkcs1.rs @@ -8,7 +8,7 @@ use rustls::pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerifica use core::ptr; use rustls_pki_types::alg_id; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; #[derive(Debug)] pub struct RsaPkcs1Sha256Verify; diff --git a/rustls-wolfcrypt-provider/src/verify/rsapss.rs b/rustls-wolfcrypt-provider/src/verify/rsapss.rs index 21513f0..52bb5c0 100644 --- a/rustls-wolfcrypt-provider/src/verify/rsapss.rs +++ b/rustls-wolfcrypt-provider/src/verify/rsapss.rs @@ -6,7 +6,7 @@ use core::ptr; use foreign_types::ForeignType; use rustls::pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; use rustls_pki_types::alg_id; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; #[derive(Debug)] pub struct RsaPssSha256Verify; diff --git a/rustls-wolfcrypt-provider/tests/e2e.rs b/rustls-wolfcrypt-provider/tests/e2e.rs index a054bc7..d5606b4 100644 --- a/rustls-wolfcrypt-provider/tests/e2e.rs +++ b/rustls-wolfcrypt-provider/tests/e2e.rs @@ -21,7 +21,7 @@ use std::process::{Child, Command}; use std::sync::Once; use std::sync::{Arc, Mutex}; use std::thread; -use wolfcrypt_rs::*; +use wolfssl_wolfcrypt::sys::*; /* * Version config used by the server to specify @@ -57,27 +57,29 @@ fn init_thread_pool() { /* * Starts background job for wolfssl server (localhost:4443). + * WOLFSSL_SERVER is the path to wolfSSL's examples/server/server, and + * WOLFSSL_SRC the wolfSSL source tree, which the server loads its default + * certificates from. * */ fn start_wolfssl_server(current_dir_string: String, tls_version: &str) -> Child { - if let Err(e) = env::set_current_dir("../wolfcrypt-rs/wolfssl-5.9.1-stable/") { - panic!("Error changing directory: {}", e); - } else { - println!("Changed directory to wolfssl-5.9.1-stable."); - - Command::new("./examples/server/server") - .arg("-d") - .arg("-c") - .arg(current_dir_string.clone() + "/tests/certs/localhost.pem") - .arg("-k") - .arg(current_dir_string.clone() + "/tests/certs/localhost.key") - .arg("-p") - .arg("4443") - .arg(tls_version) - .stdout(std::process::Stdio::null()) - .stderr(std::process::Stdio::null()) - .spawn() - .expect("Failed to start wolfssl server.") - } + let server = env::var("WOLFSSL_SERVER") + .expect("WOLFSSL_SERVER must be set to wolfSSL's examples/server/server"); + let wolfssl_src = env::var("WOLFSSL_SRC").expect("WOLFSSL_SRC must be set"); + + Command::new(server) + .current_dir(wolfssl_src) + .arg("-d") + .arg("-c") + .arg(current_dir_string.clone() + "/tests/certs/localhost.pem") + .arg("-k") + .arg(current_dir_string.clone() + "/tests/certs/localhost.key") + .arg("-p") + .arg("4443") + .arg(tls_version) + .stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()) + .spawn() + .expect("Failed to start wolfssl server.") } #[cfg(test)] diff --git a/wolfcrypt-rs/Cargo.lock b/wolfcrypt-rs/Cargo.lock deleted file mode 100644 index 6feccc4..0000000 --- a/wolfcrypt-rs/Cargo.lock +++ /dev/null @@ -1,299 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - -[[package]] -name = "bindgen" -version = "0.71.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn", -] - -[[package]] -name = "bitflags" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" - -[[package]] -name = "block-buffer" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "const-oid" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" - -[[package]] -name = "cpufeatures" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-common" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "digest" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" -dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "glob" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" - -[[package]] -name = "hybrid-array" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" -dependencies = [ - "typenum", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "libc" -version = "0.2.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" - -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link", -] - -[[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "memchr" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "regex" -version = "1.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" - -[[package]] -name = "rustc-hash" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" - -[[package]] -name = "sha2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "syn" -version = "2.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "typenum" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "wolfcrypt-rs" -version = "0.1.0" -dependencies = [ - "bindgen", - "sha2", -] diff --git a/wolfcrypt-rs/Cargo.toml b/wolfcrypt-rs/Cargo.toml deleted file mode 100644 index 98a6fc0..0000000 --- a/wolfcrypt-rs/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "wolfcrypt-rs" -version = "0.1.0" -edition = "2021" - -[features] -std = [] - -[build-dependencies] -bindgen = "0.71.1" -sha2 = "0.11.0" - -[profile.release] -strip = true -opt-level = "s" -lto = true -codegen-units = 1 -panic = "abort" diff --git a/wolfcrypt-rs/Makefile b/wolfcrypt-rs/Makefile deleted file mode 100644 index 85642b9..0000000 --- a/wolfcrypt-rs/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -.PHONY: test -test: - @cargo test - -.PHONY: build -build: - @cargo build --release - @strip target/release/libwolfcrypt_rs.rlib 2>/dev/null || echo "Strip failed" - -.PHONY: clean -clean: - @cargo clean - @rm -rf wolfssl-* diff --git a/wolfcrypt-rs/build.rs b/wolfcrypt-rs/build.rs deleted file mode 100644 index 1330a07..0000000 --- a/wolfcrypt-rs/build.rs +++ /dev/null @@ -1,260 +0,0 @@ -extern crate bindgen; - -use sha2::{Digest, Sha256}; -use std::env; -use std::fs; -use std::io::{self, Read, Result}; -use std::path::PathBuf; -use std::process::Command; - -/// Version-related constants for WolfSSL -const WOLFSSL_DIR: &str = "wolfssl-5.9.1-stable"; -const WOLFSSL_ZIP: &str = "wolfssl-5.9.1-stable.zip"; -const WOLFSSL_URL: &str = "https://github.com/wolfSSL/wolfssl/archive/refs/tags/v5.9.1-stable.zip"; -const WOLFSSL_SHA256: &str = "a91ccbf742391db95d5f1821273c59841f54a5306b9d2caea0cd7a8f2fbe0a5c"; - -/// Entry point for the build script. -/// Handles the main build process and exits with an error code if anything fails. -fn main() { - if let Err(e) = run_build() { - eprintln!("Build failed: {e}"); - std::process::exit(1); - } -} - -/// Orchestrates the entire build process. -/// -/// This function: -/// 1. Checks if WolfSSL needs to be set up -/// 2. Sets up WolfSSL if necessary -/// 3. Generates Rust bindings for the WolfSSL library -/// -/// Returns `Ok(())` if successful, or an error if any step fails. -fn run_build() -> Result<()> { - let prefix = install_prefix(); - if fs::metadata(WOLFSSL_DIR).is_err() || fs::metadata(prefix.join("lib")).is_err() { - setup_wolfssl()?; - } - - generate_bindings()?; - Ok(()) -} - -/// Generates Rust bindings for the WolfSSL library using bindgen. -/// -/// This function: -/// 1. Sets up the library and include paths -/// 2. Configures the build environment -/// 3. Generates Rust bindings using bindgen -/// 4. Writes the bindings to a file -/// -/// Returns `Ok(())` if successful, or an error if binding generation fails. -fn install_prefix() -> PathBuf { - PathBuf::from(env::var("OUT_DIR").unwrap()).join("wolfssl-install") -} - -fn generate_bindings() -> Result<()> { - let prefix = install_prefix(); - let wolfssl_lib_dir = prefix.join("lib"); - let wolfssl_include_dir = prefix.join("include"); - - println!( - "cargo:rustc-link-search={}", - wolfssl_lib_dir.to_str().unwrap() - ); - println!("cargo:rustc-link-lib=static=wolfssl"); - - let bindings = bindgen::Builder::default() - .header("libraries.h") - .clang_arg(format!("-I{}/", wolfssl_include_dir.to_str().unwrap())) - .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) - .generate() - .map_err(|_| io::Error::other("Failed to generate bindings"))?; - - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - let bindings_file = out_path.join("bindings.rs"); - bindings - .write_to_file(&bindings_file) - .map_err(|e| io::Error::other(format!("Couldn't write bindings: {e}")))?; - - // wolfSSL only compiles wc_curve25519_set_rng when it builds the blinded, - // pure-C curve25519 implementation (WOLFSSL_CURVE25519_BLINDING, i.e. no asm - // backend). Detect it from the generated bindings and expose a cfg so the - // crate can pick the real call vs. a no-op. Declaring it with check-cfg - // keeps `-D warnings` (clippy) builds from failing on an unexpected cfg. - println!("cargo:rustc-check-cfg=cfg(curve25519_blinding)"); - let generated = fs::read_to_string(&bindings_file)?; - if generated.contains("wc_curve25519_set_rng") { - println!("cargo:rustc-cfg=curve25519_blinding"); - } - - Ok(()) -} - -/// Coordinates the complete setup process for WolfSSL. -/// -/// This function executes all necessary steps in sequence: -/// 1. Downloads the WolfSSL source -/// 2. Extracts the archive -/// 3. Removes the downloaded archive -/// 4. Builds WolfSSL from source -/// 5. Returns to the original directory -/// -/// Returns `Ok(())` if all steps complete successfully, or an error if any step fails. -fn setup_wolfssl() -> Result<()> { - download_wolfssl()?; - verify_download(WOLFSSL_ZIP, WOLFSSL_SHA256)?; - unzip_wolfssl()?; - remove_zip()?; - build_wolfssl()?; - change_back_to_root()?; - Ok(()) -} - -/// Downloads the WolfSSL source code archive using curl. -/// -/// Uses curl to download the specified version of WolfSSL from the official repository. -/// The download URL and filename are defined in the constants. -/// -/// Returns `Ok(())` if the download succeeds, or an error if the download fails. -fn download_wolfssl() -> Result<()> { - let output = Command::new("curl") - .arg("-L") - .arg("-o") - .arg(WOLFSSL_ZIP) - .arg(WOLFSSL_URL) - .output()?; - - if !output.status.success() { - return Err(io::Error::other(format!( - "Failed to download: {}", - String::from_utf8_lossy(&output.stderr) - ))); - } - println!("Download completed successfully."); - Ok(()) -} - -/// Verifies the SHA-256 hash of a downloaded file against an expected value. -/// -/// Returns `Ok(())` if the hash matches, or an error if it doesn't. -fn verify_download(path: &str, expected_sha256: &str) -> Result<()> { - let mut file = fs::File::open(path)?; - let mut hasher = Sha256::new(); - let mut buf = [0u8; 8192]; - loop { - let n = file.read(&mut buf)?; - if n == 0 { - break; - } - hasher.update(&buf[..n]); - } - let hash = hasher.finalize(); - let hex: String = hash.iter().map(|b| format!("{:02x}", b)).collect(); - if hex != expected_sha256 { - return Err(io::Error::other(format!( - "SHA-256 mismatch: expected {}, got {}", - expected_sha256, hex - ))); - } - println!("SHA-256 verification passed."); - Ok(()) -} - -/// Extracts the downloaded WolfSSL archive. -/// -/// Uses the unzip command to extract the contents of the downloaded ZIP file. -/// The archive name is defined in the constants. -/// -/// Returns `Ok(())` if extraction succeeds, or an error if it fails. -fn unzip_wolfssl() -> Result<()> { - let output = Command::new("unzip").arg("-o").arg(WOLFSSL_ZIP).output()?; - - if !output.status.success() { - return Err(io::Error::other(format!( - "Failed to unzip: {}", - String::from_utf8_lossy(&output.stderr) - ))); - } - println!("Unzipping completed successfully."); - Ok(()) -} - -/// Removes the downloaded ZIP file after extraction. -/// -/// This cleanup step removes the ZIP file to save disk space. -/// -/// Returns `Ok(())` if removal succeeds, or an error if it fails. -fn remove_zip() -> Result<()> { - fs::remove_file(WOLFSSL_ZIP)?; - println!("Removed ZIP file successfully."); - Ok(()) -} - -/// Builds WolfSSL from source. -/// -/// This function: -/// 1. Changes to the source directory -/// 2. Runs autogen.sh to generate build files -/// 3. Configures the build with specific options -/// 4. Builds the library -/// 5. Installs the library system-wide -/// -/// Returns `Ok(())` if all build steps succeed, or an error if any step fails. -fn build_wolfssl() -> Result<()> { - env::set_current_dir(WOLFSSL_DIR)?; - println!("Changed directory to {WOLFSSL_DIR}."); - - let prefix = install_prefix(); - let prefix_arg = format!("--prefix={}", prefix.to_str().unwrap()); - - run_command("./autogen.sh", &[])?; - run_command( - "./configure", - &[ - "--enable-all-crypto", - "--enable-debug", - "--disable-shared", - &prefix_arg, - ], - )?; - run_command("make", &[])?; - run_command("make", &["install"])?; - - Ok(()) -} - -/// Helper function to execute shell commands. -/// -/// Executes a command with given arguments and handles the output appropriately. -/// -/// # Arguments -/// * `cmd` - The command to execute -/// * `args` - Array of arguments for the command -/// -/// Returns `Ok(())` if the command executes successfully, or an error if it fails. -fn run_command(cmd: &str, args: &[&str]) -> Result<()> { - let output = Command::new(cmd).args(args).output()?; - - if !output.status.success() { - return Err(io::Error::other(format!( - "Failed to execute {}: {}", - cmd, - String::from_utf8_lossy(&output.stderr) - ))); - } - println!("{cmd} completed successfully."); - Ok(()) -} - -/// Changes the working directory back to the root directory. -/// -/// This function is called after building WolfSSL to return to the original -/// working directory for the rest of the build process. -/// -/// Returns `Ok(())` if the directory change succeeds, or an error if it fails. -fn change_back_to_root() -> Result<()> { - env::set_current_dir("../")?; - println!("Changed directory back to root."); - Ok(()) -} diff --git a/wolfcrypt-rs/libraries.h b/wolfcrypt-rs/libraries.h deleted file mode 100644 index f4d463b..0000000 --- a/wolfcrypt-rs/libraries.h +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include diff --git a/wolfcrypt-rs/src/bindings.rs b/wolfcrypt-rs/src/bindings.rs deleted file mode 100644 index 98533f3..0000000 --- a/wolfcrypt-rs/src/bindings.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Allow attributes to suppress warnings in bindgen-generated code. - * These warnings arise from: - * - Naming conventions that don't match Rust style (e.g. from C symbols) - * - Auto-generated unsafe code patterns - * - Type/casting patterns common in C FFI but discouraged in pure Rust - * - * Since this code is auto-generated, these warnings cannot be fixed manually - * and must be suppressed. - */ -#![allow(dead_code)] -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -#![allow(unnecessary_transmutes)] -#![allow(clippy::useless_transmute)] -#![allow(clippy::upper_case_acronyms)] -#![allow(clippy::too_many_arguments)] -#![allow(improper_ctypes)] -#![allow(clippy::missing_safety_doc)] -#![allow(clippy::ptr_offset_with_cast)] -include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/wolfcrypt-rs/src/lib.rs b/wolfcrypt-rs/src/lib.rs deleted file mode 100644 index f538270..0000000 --- a/wolfcrypt-rs/src/lib.rs +++ /dev/null @@ -1,116 +0,0 @@ -pub mod bindings; -pub use bindings::*; - -/// Attach an RNG to a curve25519 key so the blinded scalar multiplication has -/// entropy. wolfSSL only compiles wc_curve25519_set_rng when it builds the -/// blinded, pure-C curve25519 implementation (WOLFSSL_CURVE25519_BLINDING, -/// i.e. no asm backend). On asm builds the symbol is absent and blinding isn't -/// used, so this becomes a no-op. The curve25519_blinding cfg is emitted by -/// build.rs based on whether that symbol appears in the generated bindings. -/// -/// # Safety -/// key must point to an initialized curve25519_key, and rng to an -/// initialized WC_RNG that outlives the following shared-secret call. -#[cfg(curve25519_blinding)] -pub unsafe fn curve25519_set_rng(key: *mut curve25519_key, rng: *mut WC_RNG) -> i32 { - wc_curve25519_set_rng(key, rng) -} - -/// No-op variant: builds without curve25519 blinding don't attach an RNG. -/// -/// # Safety -/// Same contract as the blinding variant; the arguments are ignored. -#[cfg(not(curve25519_blinding))] -pub unsafe fn curve25519_set_rng(_key: *mut curve25519_key, _rng: *mut WC_RNG) -> i32 { - 0 -} - -#[cfg(test)] -mod tests { - use super::*; - use core::ffi::c_int; - use core::mem; - - #[test] - fn rsa_encrypt_decrypt() { - let mut rng: WC_RNG = unsafe { mem::zeroed() }; - let mut rsa_key: RsaKey = unsafe { mem::zeroed() }; - let input = "I use Turing Machines to ask questions"; - let input_length = input.len() as word32; - let mut out = [0u8; 256]; - let mut plain = [0u8; 256]; - - // Initialize RSA key - let ret = unsafe { wc_InitRsaKey(&mut rsa_key, std::ptr::null_mut()) }; - if ret != 0 { - panic!("Error while initializing Rsa key! Ret value: {}", ret); - } - - // Initialize RNG - let ret = unsafe { wc_InitRng(&mut rng) }; - if ret != 0 { - panic!("Error while initializing RNG!"); - } - - // Set RNG for RSA - let ret = unsafe { wc_RsaSetRNG(&mut rsa_key, &mut rng) }; - if ret != 0 { - panic!("Error while setting rng to Rsa key! Ret value: {}", ret); - } - - // Generate RSA key - let ret = unsafe { - wc_MakeRsaKey( - &mut rsa_key, - 2048 as c_int, - WC_RSA_EXPONENT.into(), - &mut rng, - ) - }; - if ret != 0 { - panic!("Error while creating the Rsa Key! Ret value: {}", ret); - } - - // Encrypt - let ret = unsafe { - wc_RsaPublicEncrypt( - input.as_ptr() as *mut u8, - input_length, - out.as_mut_ptr(), - out.len() as word32, - &mut rsa_key, - &mut rng, - ) - }; - if ret < 0 { - panic!("Error while encrypting with RSA! Ret value: {}", ret); - } - let encrypted_len = ret; - - // Decrypt - let ret = unsafe { - wc_RsaPrivateDecrypt( - out.as_mut_ptr(), - encrypted_len as word32, - plain.as_mut_ptr(), - plain.len() as word32, - &mut rsa_key, - ) - }; - if ret < 0 { - panic!("Error while decrypting with RSA! Ret value: {}", ret); - } - let decrypted_len = ret as usize; - - // Compare results - let decrypted_str = std::str::from_utf8(&plain[..decrypted_len]) - .expect("Failed to convert decrypted data to string"); - assert_eq!(decrypted_str, input); - - // Cleanup - unsafe { - wc_FreeRsaKey(&mut rsa_key); - wc_FreeRng(&mut rng); - } - } -}