diff --git a/wrapper/rust/wolfssl-wolfcrypt/Cargo.toml b/wrapper/rust/wolfssl-wolfcrypt/Cargo.toml index 0e3ceed4438..6a38933619c 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/Cargo.toml +++ b/wrapper/rust/wolfssl-wolfcrypt/Cargo.toml @@ -11,7 +11,7 @@ categories = ["cryptography", "security", "api-bindings"] readme = "README.md" [features] -std = [] +alloc = [] rand_core = ["dep:rand_core"] aead = ["dep:aead"] cipher = ["dep:cipher"] diff --git a/wrapper/rust/wolfssl-wolfcrypt/Makefile b/wrapper/rust/wolfssl-wolfcrypt/Makefile index f705c4f8c02..0b7eac1d47e 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/Makefile +++ b/wrapper/rust/wolfssl-wolfcrypt/Makefile @@ -1,4 +1,4 @@ -FEATURES := rand_core,aead,cipher,digest,mac,signature,password-hash,kem +FEATURES := alloc,rand_core,aead,cipher,digest,mac,signature,password-hash,kem CARGO_FEATURE_FLAGS := --features $(FEATURES) .PHONY: all diff --git a/wrapper/rust/wolfssl-wolfcrypt/README.md b/wrapper/rust/wolfssl-wolfcrypt/README.md index d2509b508e5..ec4fea92219 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/README.md +++ b/wrapper/rust/wolfssl-wolfcrypt/README.md @@ -3,6 +3,8 @@ The `wolfssl-wolfcrypt` crate is a Rust wrapper for the wolfCrypt cryptographic algorithms portion of the wolfSSL C library. +This crate requires wolfSSL version 5.9.0 or newer. + ## Installation The `wolfssl` C library must be installed to be used by the Rust crate. diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs b/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs index 9aede174186..7d954d21647 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs @@ -33,13 +33,10 @@ use zeroize::{Zeroize, ZeroizeOnDrop}; use aead::{AeadCore, AeadInPlace, KeyInit, KeySizeUser}; #[cfg(feature = "aead")] -use aead::generic_array::typenum::{U0, U12, U16, U32}; +use aead::generic_array::typenum::{U0, U12, U16, U24, U32}; #[cfg(all(feature = "cipher", not(feature = "aead")))] -use cipher::typenum::consts::{U16, U32}; - -#[cfg(feature = "cipher")] -use cipher::typenum::consts::U24; +use cipher::typenum::consts::{U16, U24, U32}; #[cfg(feature = "cipher")] use cipher::{ @@ -557,6 +554,58 @@ impl AeadInPlace for Aes128Ccm { } } +/// AES-192-CCM authenticated encryption (12-byte nonce, 16-byte tag). +#[cfg(all(aes_ccm, feature = "aead"))] +#[derive(Zeroize, ZeroizeOnDrop)] +pub struct Aes192Ccm { + key: [u8; 24], +} + +#[cfg(all(aes_ccm, feature = "aead"))] +impl KeySizeUser for Aes192Ccm { + type KeySize = U24; +} + +#[cfg(all(aes_ccm, feature = "aead"))] +impl AeadCore for Aes192Ccm { + type NonceSize = U12; + type TagSize = U16; + type CiphertextOverhead = U0; +} + +#[cfg(all(aes_ccm, feature = "aead"))] +impl KeyInit for Aes192Ccm { + fn new(key: &aead::Key) -> Self { + let mut k = [0u8; 24]; + k.copy_from_slice(key.as_ref()); + Aes192Ccm { key: k } + } +} + +#[cfg(all(aes_ccm, feature = "aead"))] +impl AeadInPlace for Aes192Ccm { + fn encrypt_in_place_detached( + &self, + nonce: &aead::Nonce, + associated_data: &[u8], + buffer: &mut [u8], + ) -> Result, aead::Error> { + let mut tag = aead::Tag::::default(); + ccm_encrypt_in_place(&self.key, nonce.as_ref(), associated_data, buffer, tag.as_mut())?; + Ok(tag) + } + + fn decrypt_in_place_detached( + &self, + nonce: &aead::Nonce, + associated_data: &[u8], + buffer: &mut [u8], + tag: &aead::Tag, + ) -> Result<(), aead::Error> { + ccm_decrypt_in_place(&self.key, nonce.as_ref(), associated_data, buffer, tag.as_ref()) + } +} + /// AES-256-CCM authenticated encryption (12-byte nonce, 16-byte tag). #[cfg(all(aes_ccm, feature = "aead"))] #[derive(Zeroize, ZeroizeOnDrop)] @@ -1713,6 +1762,58 @@ impl AeadInPlace for Aes128Gcm { } } +/// AES-192-GCM authenticated encryption (12-byte nonce, 16-byte tag). +#[cfg(all(aes_gcm, feature = "aead"))] +#[derive(Zeroize, ZeroizeOnDrop)] +pub struct Aes192Gcm { + key: [u8; 24], +} + +#[cfg(all(aes_gcm, feature = "aead"))] +impl KeySizeUser for Aes192Gcm { + type KeySize = U24; +} + +#[cfg(all(aes_gcm, feature = "aead"))] +impl AeadCore for Aes192Gcm { + type NonceSize = U12; + type TagSize = U16; + type CiphertextOverhead = U0; +} + +#[cfg(all(aes_gcm, feature = "aead"))] +impl KeyInit for Aes192Gcm { + fn new(key: &aead::Key) -> Self { + let mut k = [0u8; 24]; + k.copy_from_slice(key.as_ref()); + Aes192Gcm { key: k } + } +} + +#[cfg(all(aes_gcm, feature = "aead"))] +impl AeadInPlace for Aes192Gcm { + fn encrypt_in_place_detached( + &self, + nonce: &aead::Nonce, + associated_data: &[u8], + buffer: &mut [u8], + ) -> Result, aead::Error> { + let mut tag = aead::Tag::::default(); + gcm_encrypt_in_place(&self.key, nonce.as_ref(), associated_data, buffer, tag.as_mut())?; + Ok(tag) + } + + fn decrypt_in_place_detached( + &self, + nonce: &aead::Nonce, + associated_data: &[u8], + buffer: &mut [u8], + tag: &aead::Tag, + ) -> Result<(), aead::Error> { + gcm_decrypt_in_place(&self.key, nonce.as_ref(), associated_data, buffer, tag.as_ref()) + } +} + /// AES-256-GCM authenticated encryption (12-byte nonce, 16-byte tag). #[cfg(all(aes_gcm, feature = "aead"))] #[derive(Zeroize, ZeroizeOnDrop)] diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/blake2_digest.rs b/wrapper/rust/wolfssl-wolfcrypt/src/blake2_digest.rs new file mode 100644 index 00000000000..133b66d97f7 --- /dev/null +++ b/wrapper/rust/wolfssl-wolfcrypt/src/blake2_digest.rs @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! +RustCrypto `digest` trait implementations for the wolfCrypt BLAKE2 hash +types. + +Because BLAKE2b and BLAKE2s have variable digest sizes, this module exposes +typed wrappers that pin the digest size of an underlying [`crate::blake2`] +instance to a specific value, matching the typed aliases provided by the +RustCrypto `blake2` crate (`Blake2b512`, `Blake2b256`, `Blake2s256`, etc.). + +Each typed wrapper implements the traits from the `digest` crate +(`HashMarker`, `OutputSizeUser`, `BlockSizeUser`, `Update`, `Reset`, +`FixedOutput`, and `FixedOutputReset`). With these implementations the +`digest::Digest` trait becomes available via its blanket implementation, +allowing these hashers to be used anywhere a RustCrypto `Digest` is +accepted. + +Any failure returned by the underlying wolfCrypt call in a trait method +will result in a panic, matching the infallible signatures required by the +RustCrypto traits. +*/ + +use digest::consts::{U16, U24, U32, U48, U64, U128}; + +macro_rules! impl_blake2_digest { + ( + $(#[$attr:meta])* + $name:ident, + wc_ty = $wc_ty:path, + digest_size = $digest_size:literal, + out = $out_size:ty, + block = $block_size:ty + ) => { + $(#[$attr])* + pub struct $name { + blake2: $wc_ty, + } + + $(#[$attr])* + impl Default for $name { + fn default() -> Self { + Self { + blake2: <$wc_ty>::new($digest_size) + .expect("wolfCrypt BLAKE2 init failed"), + } + } + } + + $(#[$attr])* + impl digest::HashMarker for $name {} + + $(#[$attr])* + impl digest::OutputSizeUser for $name { + type OutputSize = $out_size; + } + + $(#[$attr])* + impl digest::block_api::BlockSizeUser for $name { + type BlockSize = $block_size; + } + + $(#[$attr])* + impl digest::Update for $name { + fn update(&mut self, data: &[u8]) { + <$wc_ty>::update(&mut self.blake2, data) + .expect("wolfCrypt BLAKE2 update failed"); + } + } + + $(#[$attr])* + impl digest::Reset for $name { + fn reset(&mut self) { + self.blake2 = <$wc_ty>::new($digest_size) + .expect("wolfCrypt BLAKE2 init failed"); + } + } + + $(#[$attr])* + impl digest::FixedOutput for $name { + fn finalize_into(mut self, out: &mut digest::Output) { + <$wc_ty>::finalize(&mut self.blake2, out.as_mut_slice()) + .expect("wolfCrypt BLAKE2 finalize failed"); + } + } + + $(#[$attr])* + impl digest::FixedOutputReset for $name { + fn finalize_into_reset(&mut self, out: &mut digest::Output) { + <$wc_ty>::finalize(&mut self.blake2, out.as_mut_slice()) + .expect("wolfCrypt BLAKE2 finalize failed"); + self.blake2 = <$wc_ty>::new($digest_size) + .expect("wolfCrypt BLAKE2 init failed"); + } + } + }; +} + +impl_blake2_digest! { + #[cfg(blake2b)] + Blake2b256, + wc_ty = crate::blake2::BLAKE2b, + digest_size = 32, + out = U32, + block = U128 +} + +impl_blake2_digest! { + #[cfg(blake2b)] + Blake2b384, + wc_ty = crate::blake2::BLAKE2b, + digest_size = 48, + out = U48, + block = U128 +} + +impl_blake2_digest! { + #[cfg(blake2b)] + Blake2b512, + wc_ty = crate::blake2::BLAKE2b, + digest_size = 64, + out = U64, + block = U128 +} + +impl_blake2_digest! { + #[cfg(blake2s)] + Blake2s128, + wc_ty = crate::blake2::BLAKE2s, + digest_size = 16, + out = U16, + block = U64 +} + +impl_blake2_digest! { + #[cfg(blake2s)] + Blake2s192, + wc_ty = crate::blake2::BLAKE2s, + digest_size = 24, + out = U24, + block = U64 +} + +impl_blake2_digest! { + #[cfg(blake2s)] + Blake2s256, + wc_ty = crate::blake2::BLAKE2s, + digest_size = 32, + out = U32, + block = U64 +} diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/blake2_mac.rs b/wrapper/rust/wolfssl-wolfcrypt/src/blake2_mac.rs new file mode 100644 index 00000000000..561cba94980 --- /dev/null +++ b/wrapper/rust/wolfssl-wolfcrypt/src/blake2_mac.rs @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! +RustCrypto `digest::Mac` trait implementations for the wolfCrypt keyed +BLAKE2 types. + +These wrappers cover keyed BLAKE2 (the construction exposed by RustCrypto's +`blake2` crate as `Blake2bMac` / `Blake2sMac`), not the wolfCrypt-specific +HMAC-BLAKE2 construction. With these implementations the `digest::Mac` +trait becomes available via its blanket implementation, allowing these +types to be used anywhere a RustCrypto `Mac` is accepted. + +Each typed wrapper pins the digest size and the maximum key size to a +specific algorithm parameterization. The `Blake2sMac128`, `Blake2sMac192`, +and `Blake2sMac256` wrappers all accept keys of any length up to 32 bytes +(the BLAKE2s maximum), and the `Blake2bMac512` wrapper accepts keys of any +length up to 64 bytes (the BLAKE2b maximum), matching the variable-length +key behavior of the RustCrypto `blake2` crate's `Blake2sMac` / `Blake2bMac` +types. + +Any failure returned by the underlying wolfCrypt call in a trait method +will result in a panic, matching the infallible signatures required by the +RustCrypto traits. +*/ + +use digest::consts::{U16, U24, U32, U48, U64}; + +macro_rules! impl_blake2_mac { + ( + $(#[$attr:meta])* + $name:ident, + wc_ty = $wc_ty:path, + digest_size = $digest_size:literal, + out = $out_size:ty, + key = $key_size:ty + ) => { + $(#[$attr])* + pub struct $name { + blake2: $wc_ty, + } + + $(#[$attr])* + impl digest::MacMarker for $name {} + + $(#[$attr])* + impl digest::OutputSizeUser for $name { + type OutputSize = $out_size; + } + + $(#[$attr])* + impl digest::common::KeySizeUser for $name { + type KeySize = $key_size; + } + + $(#[$attr])* + impl digest::KeyInit for $name { + fn new(key: &digest::Key) -> Self { + Self { + blake2: <$wc_ty>::new_with_key($digest_size, key.as_slice()) + .expect("wolfCrypt BLAKE2 init failed"), + } + } + + fn new_from_slice(key: &[u8]) -> Result { + if key.len() > ::key_size() { + return Err(digest::InvalidLength); + } + Ok(Self { + blake2: <$wc_ty>::new_with_key($digest_size, key) + .map_err(|_| digest::InvalidLength)?, + }) + } + } + + $(#[$attr])* + impl digest::Update for $name { + fn update(&mut self, data: &[u8]) { + <$wc_ty>::update(&mut self.blake2, data) + .expect("wolfCrypt BLAKE2 update failed"); + } + } + + $(#[$attr])* + impl digest::FixedOutput for $name { + fn finalize_into(mut self, out: &mut digest::Output) { + <$wc_ty>::finalize(&mut self.blake2, out.as_mut_slice()) + .expect("wolfCrypt BLAKE2 finalize failed"); + } + } + }; +} + +impl_blake2_mac! { + #[cfg(blake2b)] + Blake2bMac256, + wc_ty = crate::blake2::BLAKE2b, + digest_size = 32, + out = U32, + key = U64 +} + +impl_blake2_mac! { + #[cfg(blake2b)] + Blake2bMac384, + wc_ty = crate::blake2::BLAKE2b, + digest_size = 48, + out = U48, + key = U64 +} + +impl_blake2_mac! { + #[cfg(blake2b)] + Blake2bMac512, + wc_ty = crate::blake2::BLAKE2b, + digest_size = 64, + out = U64, + key = U64 +} + +impl_blake2_mac! { + #[cfg(blake2s)] + Blake2sMac128, + wc_ty = crate::blake2::BLAKE2s, + digest_size = 16, + out = U16, + key = U32 +} + +impl_blake2_mac! { + #[cfg(blake2s)] + Blake2sMac192, + wc_ty = crate::blake2::BLAKE2s, + digest_size = 24, + out = U24, + key = U32 +} + +impl_blake2_mac! { + #[cfg(blake2s)] + Blake2sMac256, + wc_ty = crate::blake2::BLAKE2s, + digest_size = 32, + out = U32, + key = U32 +} diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs b/wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs index ef3c3ca8bd4..337c57dfed5 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs @@ -26,12 +26,15 @@ functionality. #![cfg(curve25519)] #[cfg(random)] -use crate::random::RNG; +use crate::random::{RNG, RngHandle}; use crate::sys; use core::mem::MaybeUninit; pub struct Curve25519Key { wc_key: sys::curve25519_key, + /// RNG bound via `set_rng`, kept alive while the C struct holds its pointer. + #[cfg(random)] + rng: Option, } impl Curve25519Key { @@ -73,7 +76,7 @@ impl Curve25519Key { /// Returns either Ok(curve25519key) on success or Err(e) containing the /// wolfSSL library error code value. #[cfg(random)] - pub fn generate(rng: &mut RNG) -> Result { + pub fn generate(rng: &RNG) -> Result { let mut wc_key: MaybeUninit = MaybeUninit::uninit(); let rc = unsafe { sys::wc_curve25519_init(wc_key.as_mut_ptr()) @@ -82,9 +85,13 @@ impl Curve25519Key { return Err(rc); } let wc_key = unsafe { wc_key.assume_init() }; - let mut curve25519key = Curve25519Key { wc_key }; + let mut curve25519key = Curve25519Key { + wc_key, + #[cfg(random)] + rng: None, + }; let rc = unsafe { - sys::wc_curve25519_make_key(&mut rng.wc_rng, Self::KEYSIZE as i32, + sys::wc_curve25519_make_key(rng.wc_rng, Self::KEYSIZE as i32, &mut curve25519key.wc_key) }; if rc != 0 { @@ -104,12 +111,12 @@ impl Curve25519Key { /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. #[cfg(random)] - pub fn generate_priv(rng: &mut RNG, out: &mut [u8]) -> Result<(), i32> { + pub fn generate_priv(rng: &RNG, out: &mut [u8]) -> Result<(), i32> { if out.len() != Self::KEYSIZE { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); } let rc = unsafe { - sys::wc_curve25519_make_priv(&mut rng.wc_rng, Self::KEYSIZE as i32, out.as_mut_ptr()) + sys::wc_curve25519_make_priv(rng.wc_rng, Self::KEYSIZE as i32, out.as_mut_ptr()) }; if rc != 0 { return Err(rc); @@ -137,7 +144,11 @@ impl Curve25519Key { return Err(rc); } let wc_key = unsafe { wc_key.assume_init() }; - let mut curve25519key = Curve25519Key { wc_key }; + let mut curve25519key = Curve25519Key { + wc_key, + #[cfg(random)] + rng: None, + }; let rc = unsafe { sys::wc_curve25519_import_private(private.as_ptr(), private_size, &mut curve25519key.wc_key) @@ -169,7 +180,11 @@ impl Curve25519Key { return Err(rc); } let wc_key = unsafe { wc_key.assume_init() }; - let mut curve25519key = Curve25519Key { wc_key }; + let mut curve25519key = Curve25519Key { + wc_key, + #[cfg(random)] + rng: None, + }; let endian = if big_endian {sys::EC25519_BIG_ENDIAN} else {sys::EC25519_LITTLE_ENDIAN}; let rc = unsafe { sys::wc_curve25519_import_private_ex(private.as_ptr(), @@ -203,7 +218,11 @@ impl Curve25519Key { return Err(rc); } let wc_key = unsafe { wc_key.assume_init() }; - let mut curve25519key = Curve25519Key { wc_key }; + let mut curve25519key = Curve25519Key { + wc_key, + #[cfg(random)] + rng: None, + }; let rc = unsafe { sys::wc_curve25519_import_private_raw(private.as_ptr(), private_size, public.as_ptr(), public_size, @@ -238,7 +257,11 @@ impl Curve25519Key { return Err(rc); } let wc_key = unsafe { wc_key.assume_init() }; - let mut curve25519key = Curve25519Key { wc_key }; + let mut curve25519key = Curve25519Key { + wc_key, + #[cfg(random)] + rng: None, + }; let endian = if big_endian {sys::EC25519_BIG_ENDIAN} else {sys::EC25519_LITTLE_ENDIAN}; let rc = unsafe { sys::wc_curve25519_import_private_raw_ex(private.as_ptr(), @@ -271,7 +294,11 @@ impl Curve25519Key { return Err(rc); } let wc_key = unsafe { wc_key.assume_init() }; - let mut curve25519key = Curve25519Key { wc_key }; + let mut curve25519key = Curve25519Key { + wc_key, + #[cfg(random)] + rng: None, + }; let rc = unsafe { sys::wc_curve25519_import_public(public.as_ptr(), public_size, &mut curve25519key.wc_key) @@ -303,7 +330,11 @@ impl Curve25519Key { return Err(rc); } let wc_key = unsafe { wc_key.assume_init() }; - let mut curve25519key = Curve25519Key { wc_key }; + let mut curve25519key = Curve25519Key { + wc_key, + #[cfg(random)] + rng: None, + }; let endian = if big_endian {sys::EC25519_BIG_ENDIAN} else {sys::EC25519_LITTLE_ENDIAN}; let rc = unsafe { sys::wc_curve25519_import_public_ex(public.as_ptr(), public_size, @@ -353,12 +384,12 @@ impl Curve25519Key { /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. #[cfg(all(curve25519_blinding, random))] - pub fn make_pub_blind(private: &[u8], public: &mut [u8], rng: &mut RNG) -> Result<(), i32> { + pub fn make_pub_blind(private: &[u8], public: &mut [u8], rng: &RNG) -> Result<(), i32> { let private_size = crate::buffer_len_to_i32(private.len())?; let public_size = crate::buffer_len_to_i32(public.len())?; let rc = unsafe { sys::wc_curve25519_make_pub_blind(public_size, public.as_mut_ptr(), - private_size, private.as_ptr(), &mut rng.wc_rng) + private_size, private.as_ptr(), rng.wc_rng) }; if rc != 0 { return Err(rc); @@ -408,14 +439,14 @@ impl Curve25519Key { /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. #[cfg(all(curve25519_blinding, random))] - pub fn make_pub_generic_blind(private: &[u8], public: &mut [u8], basepoint: &[u8], rng: &mut RNG) -> Result<(), i32> { + pub fn make_pub_generic_blind(private: &[u8], public: &mut [u8], basepoint: &[u8], rng: &RNG) -> Result<(), i32> { let private_size = crate::buffer_len_to_i32(private.len())?; let public_size = crate::buffer_len_to_i32(public.len())?; let basepoint_size = crate::buffer_len_to_i32(basepoint.len())?; let rc = unsafe { sys::wc_curve25519_generic_blind(public_size, public.as_mut_ptr(), private_size, private.as_ptr(), basepoint_size, basepoint.as_ptr(), - &mut rng.wc_rng) + rng.wc_rng) }; if rc != 0 { return Err(rc); @@ -454,27 +485,57 @@ impl Curve25519Key { /// This is necessary when generating a shared secret if wolfSSL is built /// with the `WOLFSSL_CURVE25519_BLINDING` build option enabled. /// + /// The key takes ownership of the RNG, so the underlying `WC_RNG` is + /// guaranteed to outlive this key. + /// /// # Parameters /// /// * `rng`: The `RNG` struct instance to associate with this - /// `Curve25519Key` instance. The `RNG` struct should not be moved in - /// memory after calling this method. + /// `Curve25519Key` instance. /// /// # Returns /// /// Returns Ok(()) on success or Err(e) containing the wolfSSL library /// error code value. #[cfg(all(curve25519_blinding, random))] - pub fn set_rng(&mut self, rng: &mut RNG) -> Result<(), i32> { + pub fn set_rng(&mut self, rng: RNG) -> Result<(), i32> { + let wc_rng = rng.wc_rng; let rc = unsafe { - sys::wc_curve25519_set_rng(&mut self.wc_key, &mut rng.wc_rng) + sys::wc_curve25519_set_rng(&mut self.wc_key, wc_rng) }; if rc != 0 { return Err(rc); } + self.rng = Some(RngHandle::Owned(rng)); Ok(()) } + /// Bind a shared `RNG` to this key. Available when the `alloc` feature + /// is enabled. + #[cfg(all(curve25519_blinding, random, feature = "alloc"))] + pub fn set_shared_rng(&mut self, rng: alloc::sync::Arc) -> Result<(), i32> { + let wc_rng = rng.wc_rng; + let rc = unsafe { + sys::wc_curve25519_set_rng(&mut self.wc_key, wc_rng) + }; + if rc != 0 { + return Err(rc); + } + self.rng = Some(RngHandle::Shared(rng)); + Ok(()) + } + + /// Borrow the RNG previously bound via `set_rng` or `set_shared_rng`. + #[cfg(random)] + pub fn rng(&self) -> Option<&RNG> { + match &self.rng { + Some(RngHandle::Owned(rng)) => Some(rng), + #[cfg(feature = "alloc")] + Some(RngHandle::Shared(rng)) => Some(rng), + None => None, + } + } + /// Compute a shared secret key given a secret private key and a received /// public key. It stores the generated secret key in the buffer out and /// returns the generated key size. Supports big or little endian. diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/dh.rs b/wrapper/rust/wolfssl-wolfcrypt/src/dh.rs index 36c4fca3fac..c6f2140f37e 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/dh.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/dh.rs @@ -194,7 +194,7 @@ impl DH { /// } /// ``` #[cfg(all(dh_keygen, random))] - pub fn generate(rng: &mut RNG, modulus_size: i32) -> Result { + pub fn generate(rng: &RNG, modulus_size: i32) -> Result { Self::generate_ex(rng, modulus_size, None, None) } @@ -225,7 +225,7 @@ impl DH { /// } /// ``` #[cfg(all(dh_keygen, random))] - pub fn generate_ex(rng: &mut RNG, modulus_size: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { + pub fn generate_ex(rng: &RNG, modulus_size: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_dhkey: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, @@ -242,7 +242,7 @@ impl DH { let wc_dhkey = unsafe { wc_dhkey.assume_init() }; let mut dh = DH { wc_dhkey }; let rc = unsafe { - sys::wc_DhGenerateParams(&mut rng.wc_rng, modulus_size, &mut dh.wc_dhkey) + sys::wc_DhGenerateParams(rng.wc_rng, modulus_size, &mut dh.wc_dhkey) }; if rc != 0 { return Err(rc); @@ -921,7 +921,7 @@ impl DH { /// } /// ``` #[cfg(random)] - pub fn new_from_pgq_with_check(p: &[u8], g: &[u8], q: &[u8], trusted: i32, rng: &mut RNG) -> Result { + pub fn new_from_pgq_with_check(p: &[u8], g: &[u8], q: &[u8], trusted: i32, rng: &RNG) -> Result { Self::new_from_pgq_with_check_ex(p, g, q, trusted, rng, None, None) } @@ -1030,7 +1030,7 @@ impl DH { /// } /// ``` #[cfg(random)] - pub fn new_from_pgq_with_check_ex(p: &[u8], g: &[u8], q: &[u8], trusted: i32, rng: &mut RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { + pub fn new_from_pgq_with_check_ex(p: &[u8], g: &[u8], q: &[u8], trusted: i32, rng: &RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let p_size = crate::buffer_len_to_u32(p.len())?; let g_size = crate::buffer_len_to_u32(g.len())?; let q_size = crate::buffer_len_to_u32(q.len())?; @@ -1050,7 +1050,7 @@ impl DH { let wc_dhkey = unsafe { wc_dhkey.assume_init() }; let mut dh = DH { wc_dhkey }; let rc = unsafe { - sys::wc_DhSetCheckKey(&mut dh.wc_dhkey, p.as_ptr(), p_size, g.as_ptr(), g_size, q.as_ptr(), q_size, trusted, &mut rng.wc_rng) + sys::wc_DhSetCheckKey(&mut dh.wc_dhkey, p.as_ptr(), p_size, g.as_ptr(), g_size, q.as_ptr(), q_size, trusted, rng.wc_rng) }; if rc != 0 { return Err(rc); @@ -1509,13 +1509,13 @@ impl DH { /// } /// ``` #[cfg(random)] - pub fn generate_key_pair(&mut self, rng: &mut RNG, + pub fn generate_key_pair(&mut self, rng: &RNG, private: &mut [u8], private_size: &mut u32, public: &mut [u8], public_size: &mut u32) -> Result<(), i32> { *private_size = crate::buffer_len_to_u32(private.len())?; *public_size = crate::buffer_len_to_u32(public.len())?; let rc = unsafe { - sys::wc_DhGenerateKeyPair(&mut self.wc_dhkey, &mut rng.wc_rng, + sys::wc_DhGenerateKeyPair(&mut self.wc_dhkey, rng.wc_rng, private.as_mut_ptr(), private_size, public.as_mut_ptr(), public_size) }; diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/dilithium.rs b/wrapper/rust/wolfssl-wolfcrypt/src/dilithium.rs index 00051478594..6e1ac0564c9 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/dilithium.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/dilithium.rs @@ -159,7 +159,7 @@ impl Dilithium { /// } /// ``` #[cfg(all(dilithium_make_key, random))] - pub fn generate(level: u8, rng: &mut RNG) -> Result { + pub fn generate(level: u8, rng: &RNG) -> Result { Self::generate_ex(level, rng, None, None) } @@ -193,7 +193,7 @@ impl Dilithium { #[cfg(all(dilithium_make_key, random))] pub fn generate_ex( level: u8, - rng: &mut RNG, + rng: &RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option, ) -> Result { @@ -202,7 +202,7 @@ impl Dilithium { if rc != 0 { return Err(rc); } - let rc = unsafe { sys::wc_dilithium_make_key(&mut key.ws_key, &mut rng.wc_rng) }; + let rc = unsafe { sys::wc_dilithium_make_key(&mut key.ws_key, rng.wc_rng) }; if rc != 0 { return Err(rc); } @@ -859,7 +859,7 @@ impl Dilithium { &mut self, msg: &[u8], sig: &mut [u8], - rng: &mut RNG, + rng: &RNG, ) -> Result { let msg_len = crate::buffer_len_to_u32(msg.len())?; let mut sig_len = crate::buffer_len_to_u32(sig.len())?; @@ -869,7 +869,7 @@ impl Dilithium { msg.as_ptr(), msg_len, sig.as_mut_ptr(), &mut sig_len, &mut self.ws_key, - &mut rng.wc_rng, + rng.wc_rng, ) }; if rc != 0 { @@ -917,7 +917,7 @@ impl Dilithium { ctx: &[u8], msg: &[u8], sig: &mut [u8], - rng: &mut RNG, + rng: &RNG, ) -> Result { if ctx.len() > 255 { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); @@ -931,7 +931,7 @@ impl Dilithium { msg.as_ptr(), msg_len, sig.as_mut_ptr(), &mut sig_len, &mut self.ws_key, - &mut rng.wc_rng, + rng.wc_rng, ) }; if rc != 0 { @@ -966,7 +966,7 @@ impl Dilithium { hash_alg: i32, hash: &[u8], sig: &mut [u8], - rng: &mut RNG, + rng: &RNG, ) -> Result { if ctx.len() > 255 { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); @@ -981,7 +981,7 @@ impl Dilithium { hash.as_ptr(), hash_len, sig.as_mut_ptr(), &mut sig_len, &mut self.ws_key, - &mut rng.wc_rng, + rng.wc_rng, ) }; if rc != 0 { diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs b/wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs index d154654a96a..021c0cd2d56 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs @@ -30,8 +30,7 @@ wolfSSL `ecc_key` object. It ensures proper initialization and deallocation. use crate::sys; #[cfg(random)] -use crate::random::RNG; -use core::mem::{MaybeUninit}; +use crate::random::{RNG, RngHandle}; /// Rust wrapper for wolfSSL `ecc_point` object. pub struct ECCPoint { @@ -290,13 +289,18 @@ impl Drop for ECCPoint { /// The `ECC` struct manages the lifecycle of a wolfSSL `ecc_key` object. /// -/// It ensures proper initialization and deallocation. +/// It ensures proper initialization and deallocation. The struct holds a +/// pointer to a `sys::ecc_key` allocated on the C heap. /// /// An instance can be created with `generate()`, `import_x963()`, /// `import_x963_ex()`, `import_private_key()`, `import_private_key_ex()`, /// `import_raw()`, or `import_raw_ex()`. pub struct ECC { - pub(crate) wc_ecc_key: sys::ecc_key, + pub(crate) wc_ecc_key: *mut sys::ecc_key, + /// RNG bound to this key via `set_rng`, kept alive for as long as the C + /// struct holds its pointer. + #[cfg(random)] + rng: Option, } #[cfg(ecc_curve_ids)] @@ -392,6 +396,20 @@ impl ECC { pub const FLAG_COFACTOR: i32 = sys::WC_ECC_FLAG_COFACTOR as i32; pub const FLAG_DEC_SIGN: i32 = sys::WC_ECC_FLAG_DEC_SIGN as i32; + /// Allocate and initialize a new `sys::ecc_key` on the C heap. + fn new_ecc_key(heap: *mut core::ffi::c_void, dev_id: i32) -> Result<*mut sys::ecc_key, i32> { + let key = unsafe { sys::wc_ecc_key_new(heap) }; + if key.is_null() { + return Err(sys::wolfCrypt_ErrorCodes_MEMORY_E); + } + let rc = unsafe { sys::wc_ecc_init_ex(key, heap, dev_id) }; + if rc != 0 { + unsafe { sys::wc_ecc_key_free(key); } + return Err(rc); + } + Ok(key) + } + /// Generate a new ECC key with the given size. /// /// # Parameters @@ -421,24 +439,17 @@ impl ECC { /// } /// ``` #[cfg(random)] - pub fn generate(size: i32, rng: &mut RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { - let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); - let heap = match heap { - Some(heap) => heap, - None => core::ptr::null_mut(), - }; - let dev_id = match dev_id { - Some(dev_id) => dev_id, - None => sys::INVALID_DEVID, + pub fn generate(size: i32, rng: &RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { + let heap = heap.unwrap_or(core::ptr::null_mut()); + let dev_id = dev_id.unwrap_or(sys::INVALID_DEVID); + let wc_ecc_key = Self::new_ecc_key(heap, dev_id)?; + let ecc = ECC { + wc_ecc_key, + #[cfg(random)] + rng: None, }; - let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; - if rc != 0 { - return Err(rc); - } - let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; - let mut ecc = ECC { wc_ecc_key }; let rc = unsafe { - sys::wc_ecc_make_key(&mut rng.wc_rng, size, &mut ecc.wc_ecc_key) + sys::wc_ecc_make_key(rng.wc_rng, size, ecc.wc_ecc_key) }; if rc != 0 { return Err(rc); @@ -478,24 +489,17 @@ impl ECC { /// } /// ``` #[cfg(random)] - pub fn generate_ex(size: i32, rng: &mut RNG, curve_id: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { - let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); - let heap = match heap { - Some(heap) => heap, - None => core::ptr::null_mut(), - }; - let dev_id = match dev_id { - Some(dev_id) => dev_id, - None => sys::INVALID_DEVID, + pub fn generate_ex(size: i32, rng: &RNG, curve_id: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { + let heap = heap.unwrap_or(core::ptr::null_mut()); + let dev_id = dev_id.unwrap_or(sys::INVALID_DEVID); + let wc_ecc_key = Self::new_ecc_key(heap, dev_id)?; + let ecc = ECC { + wc_ecc_key, + #[cfg(random)] + rng: None, }; - let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; - if rc != 0 { - return Err(rc); - } - let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; - let mut ecc = ECC { wc_ecc_key }; let rc = unsafe { - sys::wc_ecc_make_key_ex(&mut rng.wc_rng, size, &mut ecc.wc_ecc_key, curve_id) + sys::wc_ecc_make_key_ex(rng.wc_rng, size, ecc.wc_ecc_key, curve_id) }; if rc != 0 { return Err(rc); @@ -536,24 +540,17 @@ impl ECC { /// } /// ``` #[cfg(random)] - pub fn generate_ex2(size: i32, rng: &mut RNG, curve_id: i32, flags: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { - let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); - let heap = match heap { - Some(heap) => heap, - None => core::ptr::null_mut(), + pub fn generate_ex2(size: i32, rng: &RNG, curve_id: i32, flags: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { + let heap = heap.unwrap_or(core::ptr::null_mut()); + let dev_id = dev_id.unwrap_or(sys::INVALID_DEVID); + let wc_ecc_key = Self::new_ecc_key(heap, dev_id)?; + let ecc = ECC { + wc_ecc_key, + #[cfg(random)] + rng: None, }; - let dev_id = match dev_id { - Some(dev_id) => dev_id, - None => sys::INVALID_DEVID, - }; - let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; - if rc != 0 { - return Err(rc); - } - let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; - let mut ecc = ECC { wc_ecc_key }; let rc = unsafe { - sys::wc_ecc_make_key_ex2(&mut rng.wc_rng, size, &mut ecc.wc_ecc_key, curve_id, flags) + sys::wc_ecc_make_key_ex2(rng.wc_rng, size, ecc.wc_ecc_key, curve_id, flags) }; if rc != 0 { return Err(rc); @@ -624,25 +621,18 @@ impl ECC { /// } /// ``` pub fn import_der(der: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { - let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); - let heap = match heap { - Some(heap) => heap, - None => core::ptr::null_mut(), + let heap = heap.unwrap_or(core::ptr::null_mut()); + let dev_id = dev_id.unwrap_or(sys::INVALID_DEVID); + let wc_ecc_key = Self::new_ecc_key(heap, dev_id)?; + let ecc = ECC { + wc_ecc_key, + #[cfg(random)] + rng: None, }; - let dev_id = match dev_id { - Some(dev_id) => dev_id, - None => sys::INVALID_DEVID, - }; - let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; - if rc != 0 { - return Err(rc); - } - let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; - let mut ecc = ECC { wc_ecc_key }; let mut idx = 0u32; let der_size = crate::buffer_len_to_u32(der.len())?; let rc = unsafe { - sys::wc_EccPrivateKeyDecode(der.as_ptr(), &mut idx, &mut ecc.wc_ecc_key, der_size) + sys::wc_EccPrivateKeyDecode(der.as_ptr(), &mut idx, ecc.wc_ecc_key, der_size) }; if rc != 0 { return Err(rc); @@ -687,25 +677,18 @@ impl ECC { /// } /// ``` pub fn import_public_der(der: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { - let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); - let heap = match heap { - Some(heap) => heap, - None => core::ptr::null_mut(), - }; - let dev_id = match dev_id { - Some(dev_id) => dev_id, - None => sys::INVALID_DEVID, + let heap = heap.unwrap_or(core::ptr::null_mut()); + let dev_id = dev_id.unwrap_or(sys::INVALID_DEVID); + let wc_ecc_key = Self::new_ecc_key(heap, dev_id)?; + let ecc = ECC { + wc_ecc_key, + #[cfg(random)] + rng: None, }; - let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; - if rc != 0 { - return Err(rc); - } - let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; - let mut ecc = ECC { wc_ecc_key }; let mut idx = 0u32; let der_size = crate::buffer_len_to_u32(der.len())?; let rc = unsafe { - sys::wc_EccPublicKeyDecode(der.as_ptr(), &mut idx, &mut ecc.wc_ecc_key, der_size) + sys::wc_EccPublicKeyDecode(der.as_ptr(), &mut idx, ecc.wc_ecc_key, der_size) }; if rc != 0 { return Err(rc); @@ -756,27 +739,20 @@ impl ECC { /// ``` #[cfg(ecc_import)] pub fn import_private_key(priv_buf: &[u8], pub_buf: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { - let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); - let heap = match heap { - Some(heap) => heap, - None => core::ptr::null_mut(), - }; - let dev_id = match dev_id { - Some(dev_id) => dev_id, - None => sys::INVALID_DEVID, + let heap = heap.unwrap_or(core::ptr::null_mut()); + let dev_id = dev_id.unwrap_or(sys::INVALID_DEVID); + let wc_ecc_key = Self::new_ecc_key(heap, dev_id)?; + let ecc = ECC { + wc_ecc_key, + #[cfg(random)] + rng: None, }; - let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; - if rc != 0 { - return Err(rc); - } - let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; - let mut ecc = ECC { wc_ecc_key }; let priv_size = crate::buffer_len_to_u32(priv_buf.len())?; let pub_ptr = if pub_buf.is_empty() {core::ptr::null()} else {pub_buf.as_ptr()}; let pub_size = crate::buffer_len_to_u32(pub_buf.len())?; let rc = unsafe { sys::wc_ecc_import_private_key(priv_buf.as_ptr(), priv_size, - pub_ptr, pub_size, &mut ecc.wc_ecc_key) + pub_ptr, pub_size, ecc.wc_ecc_key) }; if rc != 0 { return Err(rc); @@ -830,27 +806,20 @@ impl ECC { /// ``` #[cfg(ecc_import)] pub fn import_private_key_ex(priv_buf: &[u8], pub_buf: &[u8], curve_id: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { - let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); - let heap = match heap { - Some(heap) => heap, - None => core::ptr::null_mut(), - }; - let dev_id = match dev_id { - Some(dev_id) => dev_id, - None => sys::INVALID_DEVID, + let heap = heap.unwrap_or(core::ptr::null_mut()); + let dev_id = dev_id.unwrap_or(sys::INVALID_DEVID); + let wc_ecc_key = Self::new_ecc_key(heap, dev_id)?; + let ecc = ECC { + wc_ecc_key, + #[cfg(random)] + rng: None, }; - let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; - if rc != 0 { - return Err(rc); - } - let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; - let mut ecc = ECC { wc_ecc_key }; let priv_size = crate::buffer_len_to_u32(priv_buf.len())?; let pub_ptr = if pub_buf.is_empty() {core::ptr::null()} else {pub_buf.as_ptr()}; let pub_size = crate::buffer_len_to_u32(pub_buf.len())?; let rc = unsafe { sys::wc_ecc_import_private_key_ex(priv_buf.as_ptr(), priv_size, - pub_ptr, pub_size, &mut ecc.wc_ecc_key, curve_id) + pub_ptr, pub_size, ecc.wc_ecc_key, curve_id) }; if rc != 0 { return Err(rc); @@ -889,27 +858,24 @@ impl ECC { /// ``` #[cfg(ecc_import)] pub fn import_raw(qx: &[u8], qy: &[u8], d: &[u8], curve_name: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { - let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); - let heap = match heap { - Some(heap) => heap, - None => core::ptr::null_mut(), - }; - let dev_id = match dev_id { - Some(dev_id) => dev_id, - None => sys::INVALID_DEVID, - }; - let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; - if rc != 0 { - return Err(rc); + if qx.is_empty() || qy.is_empty() || d.is_empty() || curve_name.is_empty() || + qx[qx.len() - 1] != 0 || qy[qy.len() - 1] != 0 || d[d.len() - 1] != 0 || curve_name[curve_name.len() - 1] != 0 { + return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG); } - let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; - let mut ecc = ECC { wc_ecc_key }; + let heap = heap.unwrap_or(core::ptr::null_mut()); + let dev_id = dev_id.unwrap_or(sys::INVALID_DEVID); + let wc_ecc_key = Self::new_ecc_key(heap, dev_id)?; + let ecc = ECC { + wc_ecc_key, + #[cfg(random)] + rng: None, + }; let qx_ptr = qx.as_ptr() as *const core::ffi::c_char; let qy_ptr = qy.as_ptr() as *const core::ffi::c_char; let d_ptr = d.as_ptr() as *const core::ffi::c_char; let curve_name_ptr = curve_name.as_ptr() as *const core::ffi::c_char; let rc = unsafe { - sys::wc_ecc_import_raw(&mut ecc.wc_ecc_key, qx_ptr, qy_ptr, d_ptr, + sys::wc_ecc_import_raw(ecc.wc_ecc_key, qx_ptr, qy_ptr, d_ptr, curve_name_ptr) }; if rc != 0 { @@ -949,26 +915,23 @@ impl ECC { /// ``` #[cfg(ecc_import)] pub fn import_raw_ex(qx: &[u8], qy: &[u8], d: &[u8], curve_id: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { - let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); - let heap = match heap { - Some(heap) => heap, - None => core::ptr::null_mut(), - }; - let dev_id = match dev_id { - Some(dev_id) => dev_id, - None => sys::INVALID_DEVID, - }; - let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; - if rc != 0 { - return Err(rc); + if qx.is_empty() || qy.is_empty() || d.is_empty() || + qx[qx.len() - 1] != 0 || qy[qy.len() - 1] != 0 || d[d.len() - 1] != 0 { + return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG); } - let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; - let mut ecc = ECC { wc_ecc_key }; + let heap = heap.unwrap_or(core::ptr::null_mut()); + let dev_id = dev_id.unwrap_or(sys::INVALID_DEVID); + let wc_ecc_key = Self::new_ecc_key(heap, dev_id)?; + let ecc = ECC { + wc_ecc_key, + #[cfg(random)] + rng: None, + }; let qx_ptr = qx.as_ptr() as *const core::ffi::c_char; let qy_ptr = qy.as_ptr() as *const core::ffi::c_char; let d_ptr = d.as_ptr() as *const core::ffi::c_char; let rc = unsafe { - sys::wc_ecc_import_raw_ex(&mut ecc.wc_ecc_key, qx_ptr, qy_ptr, + sys::wc_ecc_import_raw_ex(ecc.wc_ecc_key, qx_ptr, qy_ptr, d_ptr, curve_id) }; if rc != 0 { @@ -1017,23 +980,16 @@ impl ECC { /// ``` #[cfg(ecc_import)] pub fn import_unsigned(qx: &[u8], qy: &[u8], d: &[u8], curve_id: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { - let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); - let heap = match heap { - Some(heap) => heap, - None => core::ptr::null_mut(), + let heap = heap.unwrap_or(core::ptr::null_mut()); + let dev_id = dev_id.unwrap_or(sys::INVALID_DEVID); + let wc_ecc_key = Self::new_ecc_key(heap, dev_id)?; + let ecc = ECC { + wc_ecc_key, + #[cfg(random)] + rng: None, }; - let dev_id = match dev_id { - Some(dev_id) => dev_id, - None => sys::INVALID_DEVID, - }; - let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; - if rc != 0 { - return Err(rc); - } - let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; - let mut ecc = ECC { wc_ecc_key }; let rc = unsafe { - sys::wc_ecc_import_unsigned(&mut ecc.wc_ecc_key, qx.as_ptr(), + sys::wc_ecc_import_unsigned(ecc.wc_ecc_key, qx.as_ptr(), qy.as_ptr(), d.as_ptr(), curve_id) }; if rc != 0 { @@ -1076,23 +1032,16 @@ impl ECC { #[cfg(ecc_import)] pub fn import_x963(din: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; - let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); - let heap = match heap { - Some(heap) => heap, - None => core::ptr::null_mut(), - }; - let dev_id = match dev_id { - Some(dev_id) => dev_id, - None => sys::INVALID_DEVID, + let heap = heap.unwrap_or(core::ptr::null_mut()); + let dev_id = dev_id.unwrap_or(sys::INVALID_DEVID); + let wc_ecc_key = Self::new_ecc_key(heap, dev_id)?; + let ecc = ECC { + wc_ecc_key, + #[cfg(random)] + rng: None, }; - let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; - if rc != 0 { - return Err(rc); - } - let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; - let mut ecc = ECC { wc_ecc_key }; let rc = unsafe { - sys::wc_ecc_import_x963(din.as_ptr(), din_size, &mut ecc.wc_ecc_key) + sys::wc_ecc_import_x963(din.as_ptr(), din_size, ecc.wc_ecc_key) }; if rc != 0 { return Err(rc); @@ -1139,23 +1088,16 @@ impl ECC { #[cfg(ecc_import)] pub fn import_x963_ex(din: &[u8], curve_id: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; - let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); - let heap = match heap { - Some(heap) => heap, - None => core::ptr::null_mut(), - }; - let dev_id = match dev_id { - Some(dev_id) => dev_id, - None => sys::INVALID_DEVID, + let heap = heap.unwrap_or(core::ptr::null_mut()); + let dev_id = dev_id.unwrap_or(sys::INVALID_DEVID); + let wc_ecc_key = Self::new_ecc_key(heap, dev_id)?; + let ecc = ECC { + wc_ecc_key, + #[cfg(random)] + rng: None, }; - let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; - if rc != 0 { - return Err(rc); - } - let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; - let mut ecc = ECC { wc_ecc_key }; let rc = unsafe { - sys::wc_ecc_import_x963_ex(din.as_ptr(), din_size, &mut ecc.wc_ecc_key, curve_id) + sys::wc_ecc_import_x963_ex(din.as_ptr(), din_size, ecc.wc_ecc_key, curve_id) }; if rc != 0 { return Err(rc); @@ -1366,7 +1308,7 @@ impl ECC { /// } /// ``` pub fn check(&mut self) -> Result<(), i32> { - let rc = unsafe { sys::wc_ecc_check_key(&mut self.wc_ecc_key) }; + let rc = unsafe { sys::wc_ecc_check_key(self.wc_ecc_key) }; if rc != 0 { return Err(rc); } @@ -1414,7 +1356,7 @@ impl ECC { *qy_len = crate::buffer_len_to_u32(qy.len())?; *d_len = crate::buffer_len_to_u32(d.len())?; let rc = unsafe { - sys::wc_ecc_export_private_raw(&mut self.wc_ecc_key, + sys::wc_ecc_export_private_raw(self.wc_ecc_key, qx.as_mut_ptr(), qx_len, qy.as_mut_ptr(), qy_len, d.as_mut_ptr(), d_len) @@ -1477,7 +1419,7 @@ impl ECC { sys::WC_TYPE_UNSIGNED_BIN as i32 }; let rc = unsafe { - sys::wc_ecc_export_ex(&mut self.wc_ecc_key, + sys::wc_ecc_export_ex(self.wc_ecc_key, qx.as_mut_ptr(), qx_len, qy.as_mut_ptr(), qy_len, d.as_mut_ptr(), d_len, @@ -1518,7 +1460,7 @@ impl ECC { pub fn export_private(&mut self, d: &mut [u8]) -> Result { let mut d_size = crate::buffer_len_to_u32(d.len())?; let rc = unsafe { - sys::wc_ecc_export_private_only(&mut self.wc_ecc_key, + sys::wc_ecc_export_private_only(self.wc_ecc_key, d.as_mut_ptr(), &mut d_size) }; if rc != 0 { @@ -1563,7 +1505,7 @@ impl ECC { *qx_len = crate::buffer_len_to_u32(qx.len())?; *qy_len = crate::buffer_len_to_u32(qy.len())?; let rc = unsafe { - sys::wc_ecc_export_public_raw(&mut self.wc_ecc_key, + sys::wc_ecc_export_public_raw(self.wc_ecc_key, qx.as_mut_ptr(), qx_len, qy.as_mut_ptr(), qy_len) }; @@ -1601,7 +1543,7 @@ impl ECC { pub fn export_x963(&mut self, dout: &mut [u8]) -> Result { let mut out_len = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { - sys::wc_ecc_export_x963(&mut self.wc_ecc_key, dout.as_mut_ptr(), &mut out_len) + sys::wc_ecc_export_x963(self.wc_ecc_key, dout.as_mut_ptr(), &mut out_len) }; if rc != 0 { return Err(rc); @@ -1637,7 +1579,7 @@ impl ECC { pub fn export_x963_compressed(&mut self, dout: &mut [u8]) -> Result { let mut out_len = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { - sys::wc_ecc_export_x963_ex(&mut self.wc_ecc_key, dout.as_mut_ptr(), &mut out_len, 1) + sys::wc_ecc_export_x963_ex(self.wc_ecc_key, dout.as_mut_ptr(), &mut out_len, 1) }; if rc != 0 { return Err(rc); @@ -1674,13 +1616,13 @@ impl ECC { /// } /// ``` #[cfg(random)] - pub fn make_pub(&mut self, rng: Option<&mut RNG>) -> Result<(), i32> { + pub fn make_pub(&mut self, rng: Option<&RNG>) -> Result<(), i32> { let rng_ptr = match rng { - Some(rng) => &mut rng.wc_rng, + Some(rng) => rng.wc_rng, None => core::ptr::null_mut(), }; let rc = unsafe { - sys::wc_ecc_make_pub_ex(&mut self.wc_ecc_key, core::ptr::null_mut(), rng_ptr) + sys::wc_ecc_make_pub_ex(self.wc_ecc_key, core::ptr::null_mut(), rng_ptr) }; if rc != 0 { return Err(rc); @@ -1718,9 +1660,9 @@ impl ECC { /// } /// ``` #[cfg(random)] - pub fn make_pub_to_point(&mut self, rng: Option<&mut RNG>, heap: Option<*mut core::ffi::c_void>) -> Result { + pub fn make_pub_to_point(&mut self, rng: Option<&RNG>, heap: Option<*mut core::ffi::c_void>) -> Result { let rng_ptr = match rng { - Some(rng) => &mut rng.wc_rng, + Some(rng) => rng.wc_rng, None => core::ptr::null_mut(), }; let heap = match heap { @@ -1733,7 +1675,7 @@ impl ECC { } let ecc_point = ECCPoint { wc_ecc_point, heap }; let rc = unsafe { - sys::wc_ecc_make_pub_ex(&mut self.wc_ecc_key, wc_ecc_point, rng_ptr) + sys::wc_ecc_make_pub_ex(self.wc_ecc_key, wc_ecc_point, rng_ptr) }; if rc != 0 { return Err(rc); @@ -1749,8 +1691,7 @@ impl ECC { /// # Parameters /// /// * `rng`: The `RNG` struct instance to associate with this `ECC` - /// instance. The `RNG` struct should not be moved in memory after - /// calling this method. + /// instance. /// /// # Returns /// @@ -1765,22 +1706,51 @@ impl ECC { /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; - /// let mut rng = RNG::new().expect("Failed to create RNG"); - /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); - /// ecc.set_rng(&mut rng).expect("Error with set_rng()"); + /// let blinding_rng = RNG::new().expect("Failed to create RNG"); + /// let key_gen_rng = RNG::new().expect("Failed to create RNG"); + /// let mut ecc = ECC::generate(32, &key_gen_rng, None, None).expect("Error with generate()"); + /// ecc.set_rng(blinding_rng).expect("Error with set_rng()"); /// } /// ``` #[cfg(random)] - pub fn set_rng(&mut self, rng: &mut RNG) -> Result<(), i32> { + pub fn set_rng(&mut self, rng: RNG) -> Result<(), i32> { + let wc_rng = rng.wc_rng; let rc = unsafe { - sys::wc_ecc_set_rng(&mut self.wc_ecc_key, &mut rng.wc_rng) + sys::wc_ecc_set_rng(self.wc_ecc_key, wc_rng) }; if rc != 0 { return Err(rc); } + self.rng = Some(RngHandle::Owned(rng)); Ok(()) } + /// Bind a shared `RNG` to this key. Available when the `alloc` feature + /// is enabled. + #[cfg(all(random, feature = "alloc"))] + pub fn set_shared_rng(&mut self, rng: alloc::sync::Arc) -> Result<(), i32> { + let wc_rng = rng.wc_rng; + let rc = unsafe { + sys::wc_ecc_set_rng(self.wc_ecc_key, wc_rng) + }; + if rc != 0 { + return Err(rc); + } + self.rng = Some(RngHandle::Shared(rng)); + Ok(()) + } + + /// Borrow the RNG previously bound via `set_rng` or `set_shared_rng`. + #[cfg(random)] + pub fn rng(&self) -> Option<&RNG> { + match &self.rng { + Some(RngHandle::Owned(rng)) => Some(rng), + #[cfg(feature = "alloc")] + Some(RngHandle::Shared(rng)) => Some(rng), + None => None, + } + } + /// Compute the ECDH shared secret using this key's private component /// and the peer public key. /// @@ -1797,17 +1767,18 @@ impl ECC { /// # Example /// /// ```rust - /// #[cfg(all(ecc_dh, random))] + /// #[cfg(all(ecc_dh, random, feature = "alloc"))] /// { + /// use std::sync::Arc; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; - /// let mut rng = RNG::new().expect("Failed to create RNG"); - /// let mut ecc0 = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); - /// let mut ecc1 = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); + /// let rng = Arc::new(RNG::new().expect("Failed to create RNG")); + /// let mut ecc0 = ECC::generate(32, &rng, None, None).expect("Error with generate()"); + /// let mut ecc1 = ECC::generate(32, &rng, None, None).expect("Error with generate()"); /// let mut ss0 = [0u8; 128]; /// let mut ss1 = [0u8; 128]; - /// ecc0.set_rng(&mut rng).expect("Error with set_rng()"); - /// ecc1.set_rng(&mut rng).expect("Error with set_rng()"); + /// ecc0.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); + /// ecc1.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let ss0_size = ecc0.shared_secret(&mut ecc1, &mut ss0).expect("Error with shared_secret()"); /// let ss1_size = ecc1.shared_secret(&mut ecc0, &mut ss1).expect("Error with shared_secret()"); /// assert_eq!(ss0_size, ss1_size); @@ -1820,8 +1791,8 @@ impl ECC { pub fn shared_secret(&mut self, peer_key: &mut ECC, dout: &mut [u8]) -> Result { let mut out_len = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { - sys::wc_ecc_shared_secret(&mut self.wc_ecc_key, - &mut peer_key.wc_ecc_key, dout.as_mut_ptr(), &mut out_len) + sys::wc_ecc_shared_secret(self.wc_ecc_key, + peer_key.wc_ecc_key, dout.as_mut_ptr(), &mut out_len) }; if rc != 0 { return Err(rc); @@ -1846,18 +1817,19 @@ impl ECC { /// # Example /// /// ```rust - /// #[cfg(all(ecc_dh, random))] + /// #[cfg(all(ecc_dh, random, feature = "alloc"))] /// { + /// use std::sync::Arc; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; - /// let mut rng = RNG::new().expect("Failed to create RNG"); - /// let mut ecc0 = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); - /// let mut ecc1 = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); + /// let rng = Arc::new(RNG::new().expect("Failed to create RNG")); + /// let mut ecc0 = ECC::generate(32, &rng, None, None).expect("Error with generate()"); + /// let mut ecc1 = ECC::generate(32, &rng, None, None).expect("Error with generate()"); /// let ecc1_point = ecc1.make_pub_to_point(None, None).expect("Error with make_pub_to_point()"); /// let mut ss0 = [0u8; 128]; /// let mut ss1 = [0u8; 128]; - /// ecc0.set_rng(&mut rng).expect("Error with set_rng()"); - /// ecc1.set_rng(&mut rng).expect("Error with set_rng()"); + /// ecc0.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); + /// ecc1.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let ss0_size = ecc0.shared_secret_ex(&ecc1_point, &mut ss0).expect("Error with shared_secret_ex()"); /// let ss1_size = ecc1.shared_secret(&mut ecc0, &mut ss1).expect("Error with shared_secret()"); /// assert_eq!(ss0_size, ss1_size); @@ -1870,7 +1842,7 @@ impl ECC { pub fn shared_secret_ex(&mut self, peer: &ECCPoint, dout: &mut [u8]) -> Result { let mut out_len = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { - sys::wc_ecc_shared_secret_ex(&mut self.wc_ecc_key, + sys::wc_ecc_shared_secret_ex(self.wc_ecc_key, peer.wc_ecc_point, dout.as_mut_ptr(), &mut out_len) }; if rc != 0 { @@ -1910,12 +1882,12 @@ impl ECC { /// } /// ``` #[cfg(all(ecc_sign, random))] - pub fn sign_hash(&mut self, din: &[u8], dout: &mut [u8], rng: &mut RNG) -> Result { + pub fn sign_hash(&mut self, din: &[u8], dout: &mut [u8], rng: &RNG) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let mut dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_ecc_sign_hash(din.as_ptr(), din_size, dout.as_mut_ptr(), - &mut dout_size, &mut rng.wc_rng, &mut self.wc_ecc_key) + &mut dout_size, rng.wc_rng, self.wc_ecc_key) }; if rc != 0 { return Err(rc); @@ -1959,7 +1931,7 @@ impl ECC { let hash_len = crate::buffer_len_to_u32(hash.len())?; let rc = unsafe { sys::wc_ecc_verify_hash(sig.as_ptr(), sig_len, - hash.as_ptr(), hash_len, &mut res, &mut self.wc_ecc_key) + hash.as_ptr(), hash_len, &mut res, self.wc_ecc_key) }; if rc != 0 { return Err(rc); @@ -1968,22 +1940,16 @@ impl ECC { } } -impl ECC { - fn zeroize(&mut self) { - unsafe { crate::zeroize_raw(&mut self.wc_ecc_key); } - } -} - impl Drop for ECC { /// Safely free the underlying wolfSSL ECC context. /// - /// This calls the `wc_ecc_key_free()` wolfssl library function. + /// This calls the `wc_ecc_key_free()` wolfssl library function, which + /// frees the C-heap-allocated `ecc_key` object. /// /// The Rust Drop trait guarantees that this method is called when the ECC /// struct goes out of scope, automatically cleaning up resources and /// preventing memory leaks. fn drop(&mut self) { - unsafe { sys::wc_ecc_free(&mut self.wc_ecc_key); } - self.zeroize(); + unsafe { sys::wc_ecc_key_free(self.wc_ecc_key); } } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/ecdsa.rs b/wrapper/rust/wolfssl-wolfcrypt/src/ecdsa.rs index b771694b055..f3c06d451f9 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/ecdsa.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/ecdsa.rs @@ -252,9 +252,9 @@ macro_rules! define_ecdsa_curve { sys::wc_SignatureType_WC_SIGNATURE_TYPE_ECC, msg.as_ptr(), msg_len, der.as_mut_ptr(), &mut der_len, - &mut self.inner.wc_ecc_key as *mut _ as *mut c_void, + self.inner.wc_ecc_key as *mut c_void, size_of::() as u32, - &mut self.rng.wc_rng, + self.rng.wc_rng, ) }; if rc != 0 { @@ -313,7 +313,7 @@ macro_rules! define_ecdsa_curve { fn verify(&self, msg: &[u8], sig: &$signature) -> Result<(), Error> { let mut der = [0u8; $der_max]; let der_len = rs_to_der::<$field_size>(&sig.0, &mut der)?; - let mut key = ECC::import_x963_ex(&self.pub_bytes, $curve_id, None, None) + let key = ECC::import_x963_ex(&self.pub_bytes, $curve_id, None, None) .map_err(|_| Error::new())?; let msg_len: u32 = msg.len().try_into().map_err(|_| Error::new())?; let rc = unsafe { @@ -322,7 +322,7 @@ macro_rules! define_ecdsa_curve { sys::wc_SignatureType_WC_SIGNATURE_TYPE_ECC, msg.as_ptr(), msg_len, der.as_ptr(), der_len as u32, - &mut key.wc_ecc_key as *mut _ as *mut c_void, + key.wc_ecc_key as *mut c_void, size_of::() as u32, ) }; diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/ed25519.rs b/wrapper/rust/wolfssl-wolfcrypt/src/ed25519.rs index a0b91f1e279..5a950e729c9 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/ed25519.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/ed25519.rs @@ -72,7 +72,7 @@ impl Ed25519 { /// let mut rng = RNG::new().expect("Error creating RNG"); /// let ed = Ed25519::generate(&mut rng).expect("Error with generate()"); /// ``` - pub fn generate(rng: &mut RNG) -> Result { + pub fn generate(rng: &RNG) -> Result { Self::generate_ex(rng, None, None) } @@ -97,7 +97,7 @@ impl Ed25519 { /// let mut rng = RNG::new().expect("Error creating RNG"); /// let ed = Ed25519::generate_ex(&mut rng, None, None).expect("Error with generate_ex()"); /// ``` - pub fn generate_ex(rng: &mut RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { + pub fn generate_ex(rng: &RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut ws_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, @@ -114,7 +114,7 @@ impl Ed25519 { let ws_key = unsafe { ws_key.assume_init() }; let mut ed25519 = Ed25519 { ws_key }; let rc = unsafe { - sys::wc_ed25519_make_key(&mut rng.wc_rng, + sys::wc_ed25519_make_key(rng.wc_rng, sys::ED25519_KEY_SIZE as i32, &mut ed25519.ws_key) }; if rc != 0 { diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/ed448.rs b/wrapper/rust/wolfssl-wolfcrypt/src/ed448.rs index 0a77aa071e8..bb134ce7962 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/ed448.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/ed448.rs @@ -71,7 +71,7 @@ impl Ed448 { /// let mut rng = RNG::new().expect("Error creating RNG"); /// let ed = Ed448::generate(&mut rng).expect("Error with generate()"); /// ``` - pub fn generate(rng: &mut RNG) -> Result { + pub fn generate(rng: &RNG) -> Result { Self::generate_ex(rng, None, None) } @@ -96,7 +96,7 @@ impl Ed448 { /// let mut rng = RNG::new().expect("Error creating RNG"); /// let ed = Ed448::generate_ex(&mut rng, None, None).expect("Error with generate_ex()"); /// ``` - pub fn generate_ex(rng: &mut RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { + pub fn generate_ex(rng: &RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut ws_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, @@ -113,7 +113,7 @@ impl Ed448 { let ws_key = unsafe { ws_key.assume_init() }; let mut ed448 = Ed448 { ws_key }; let rc = unsafe { - sys::wc_ed448_make_key(&mut rng.wc_rng, + sys::wc_ed448_make_key(rng.wc_rng, sys::ED448_KEY_SIZE as i32, &mut ed448.ws_key) }; if rc != 0 { diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs b/wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs index b1d004006ce..11a05adbbd0 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs @@ -330,6 +330,24 @@ impl HMAC { } } +impl Clone for HMAC { + /// Deep-copy the HMAC state via `wc_HmacCopy()`. + /// + /// Panics if the underlying wolfSSL copy fails. + fn clone(&self) -> Self { + let mut wc_hmac: MaybeUninit = MaybeUninit::uninit(); + let rc = unsafe { + sys::wc_HmacCopy(&self.wc_hmac as *const _ as *mut _, + wc_hmac.as_mut_ptr()) + }; + if rc != 0 { + panic!("wc_HmacCopy() failed: {}", rc); + } + let wc_hmac = unsafe { wc_hmac.assume_init() }; + HMAC { wc_hmac } + } +} + impl Drop for HMAC { /// Safely free the underlying wolfSSL Hmac context. /// diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/hmac_mac.rs b/wrapper/rust/wolfssl-wolfcrypt/src/hmac_mac.rs index 452debaa22c..e5060d6f8dc 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/hmac_mac.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/hmac_mac.rs @@ -42,6 +42,7 @@ macro_rules! impl_hmac_mac { $name:ident, hmac_type = $hmac_type:expr, key = $key_size:ty, out = $out_size:ty ) => { $(#[$attr])* + #[derive(Clone)] pub struct $name { hmac: crate::hmac::HMAC, } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs b/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs index 1c6a23dcdd4..36dc42bd948 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs @@ -20,6 +20,9 @@ #![no_std] +#[cfg(feature = "alloc")] +extern crate alloc; + /* bindgen-generated bindings to the C library */ pub mod sys; @@ -42,6 +45,10 @@ pub(crate) unsafe fn zeroize_raw(val: &mut T) { pub mod aes; pub mod blake2; +#[cfg(all(any(blake2b, blake2s), feature = "digest"))] +pub mod blake2_digest; +#[cfg(all(any(blake2b, blake2s), feature = "mac"))] +pub mod blake2_mac; pub mod chacha20_poly1305; pub mod cmac; #[cfg(all(cmac, feature = "mac"))] diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/lms.rs b/wrapper/rust/wolfssl-wolfcrypt/src/lms.rs index d3be50dc876..5e002d2cc14 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/lms.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/lms.rs @@ -443,8 +443,8 @@ impl Lms { /// } /// ``` #[cfg(all(lms_make_key, random))] - pub fn make_key(&mut self, rng: &mut RNG) -> Result<(), i32> { - let rc = unsafe { sys::wc_LmsKey_MakeKey(&mut self.ws_key, &mut rng.wc_rng) }; + pub fn make_key(&mut self, rng: &RNG) -> Result<(), i32> { + let rc = unsafe { sys::wc_LmsKey_MakeKey(&mut self.ws_key, rng.wc_rng) }; if rc != 0 { return Err(rc); } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/mlkem.rs b/wrapper/rust/wolfssl-wolfcrypt/src/mlkem.rs index e63709dea5c..b2711fc9961 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/mlkem.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/mlkem.rs @@ -123,7 +123,7 @@ impl MlKem { /// } /// ``` #[cfg(random)] - pub fn generate(key_type: i32, rng: &mut RNG) -> Result { + pub fn generate(key_type: i32, rng: &RNG) -> Result { Self::generate_ex(key_type, rng, None, None) } @@ -157,12 +157,12 @@ impl MlKem { #[cfg(random)] pub fn generate_ex( key_type: i32, - rng: &mut RNG, + rng: &RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option, ) -> Result { let key = Self::new_ex(key_type, heap, dev_id)?; - let rc = unsafe { sys::wc_MlKemKey_MakeKey(key.ws_key, &mut rng.wc_rng) }; + let rc = unsafe { sys::wc_MlKemKey_MakeKey(key.ws_key, rng.wc_rng) }; if rc != 0 { return Err(rc); } @@ -472,7 +472,7 @@ impl MlKem { &mut self, ct: &mut [u8], ss: &mut [u8], - rng: &mut RNG, + rng: &RNG, ) -> Result<(), i32> { // Verify the cipher text length is as expected based on the parameter // set (key type) in use. @@ -489,7 +489,7 @@ impl MlKem { self.ws_key, ct.as_mut_ptr(), ss.as_mut_ptr(), - &mut rng.wc_rng, + rng.wc_rng, ) }; if rc != 0 { diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/random.rs b/wrapper/rust/wolfssl-wolfcrypt/src/random.rs index a5904daa40e..47319cf7699 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/random.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/random.rs @@ -31,7 +31,7 @@ wolfSSL `WC_RNG` object. It ensures proper initialization and deallocation. use wolfssl_wolfcrypt::random::RNG; // Create a RNG instance. -let mut rng = RNG::new().expect("Failed to create RNG"); +let rng = RNG::new().expect("Failed to create RNG"); // Generate a single random byte value. let byte = rng.generate_byte().expect("Failed to generate a single byte"); @@ -45,18 +45,42 @@ rng.generate_block(&mut buffer).expect("Failed to generate a block"); #![cfg(random)] use crate::sys; -use core::mem::{size_of_val, MaybeUninit}; +use core::mem::size_of_val; use num_traits::PrimInt; /// A cryptographically secure random number generator based on the wolfSSL /// library. /// -/// This struct wraps the wolfssl `WC_RNG` type, providing a high-level API -/// for generating random bytes and blocks of data. The `Drop` implementation -/// ensures that the underlying wolfSSL RNG context is correctly freed when the -/// `RNG` struct goes out of scope, preventing memory leaks. +/// This struct wraps a pointer to a wolfssl `WC_RNG` allocated on the C heap, +/// providing a high-level API for generating random bytes and blocks of data. +/// The `Drop` implementation ensures that the underlying wolfSSL RNG context is +/// correctly freed when the `RNG` struct goes out of scope, preventing memory +/// leaks. +/// +/// All generation methods take `&self`. The actual mutation of the DRBG state +/// happens through the raw pointer in the C library; the `RNG` struct itself +/// is logically immutable after construction. pub struct RNG { - pub(crate) wc_rng: sys::WC_RNG, + pub(crate) wc_rng: *mut sys::WC_RNG, +} + +// Safety: the only field of `RNG` is a non-null pointer to a `WC_RNG` that +// lives on the C heap and is never reassigned after construction. Moving the +// struct between threads is sound. +unsafe impl Send for RNG {} + +// Note: `RNG` is intentionally not `Sync`. The underlying C `WC_RNG` state is +// mutated by every call to a generation routine, with no internal locking. +// Callers that need cross-thread sharing must wrap the RNG in a `Mutex` +// (typically `Arc>`). + +/// Storage for an RNG that a consumer (e.g. `RSA`, `ECC`) has been bound to +/// via `set_rng`. The consumer keeps the `RngHandle` alive for as long as the +/// C struct holds its pointer, ensuring the `WC_RNG` outlives the consumer. +pub(crate) enum RngHandle { + Owned(RNG), + #[cfg(feature = "alloc")] + Shared(alloc::sync::Arc), } impl RNG { @@ -97,7 +121,7 @@ impl RNG { return Err(rc); } } - let mut wc_rng: MaybeUninit = MaybeUninit::uninit(); + let mut wc_rng: *mut sys::WC_RNG = core::ptr::null_mut(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), @@ -107,12 +131,10 @@ impl RNG { None => sys::INVALID_DEVID, }; let rc = unsafe { - sys::wc_InitRng_ex(wc_rng.as_mut_ptr(), heap, dev_id) + sys::wc_rng_new_ex(&mut wc_rng, core::ptr::null_mut(), 0, heap, dev_id) }; if rc == 0 { - let wc_rng = unsafe { wc_rng.assume_init() }; - let rng = RNG {wc_rng}; - Ok(rng) + Ok(RNG {wc_rng}) } else { Err(rc) } @@ -159,7 +181,7 @@ impl RNG { } let ptr = nonce.as_mut_ptr() as *mut u8; let size = crate::buffer_len_to_u32(size_of_val(nonce))?; - let mut wc_rng: MaybeUninit = MaybeUninit::uninit(); + let mut wc_rng: *mut sys::WC_RNG = core::ptr::null_mut(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), @@ -169,12 +191,10 @@ impl RNG { None => sys::INVALID_DEVID, }; let rc = unsafe { - sys::wc_InitRngNonce_ex(wc_rng.as_mut_ptr(), ptr, size, heap, dev_id) + sys::wc_rng_new_ex(&mut wc_rng, ptr, size, heap, dev_id) }; if rc == 0 { - let wc_rng = unsafe { wc_rng.assume_init() }; - let rng = RNG {wc_rng}; - Ok(rng) + Ok(RNG {wc_rng}) } else { Err(rc) } @@ -315,9 +335,9 @@ impl RNG { /// /// A `Result` which is `Ok(u8)` containing the random byte on success or /// an `Err` with the wolfssl library return code on failure. - pub fn generate_byte(&mut self) -> Result { + pub fn generate_byte(&self) -> Result { let mut b: u8 = 0; - let rc = unsafe { sys::wc_RNG_GenerateByte(&mut self.wc_rng, &mut b) }; + let rc = unsafe { sys::wc_RNG_GenerateByte(self.wc_rng, &mut b) }; if rc == 0 { Ok(b) } else { @@ -339,10 +359,10 @@ impl RNG { /// /// A `Result` which is `Ok(())` on success or an `Err` with the wolfssl /// library return code on failure. - pub fn generate_block(&mut self, buf: &mut [T]) -> Result<(), i32> { + pub fn generate_block(&self, buf: &mut [T]) -> Result<(), i32> { let ptr = buf.as_mut_ptr() as *mut u8; let size = crate::buffer_len_to_u32(size_of_val(buf))?; - let rc = unsafe { sys::wc_RNG_GenerateBlock(&mut self.wc_rng, ptr, size) }; + let rc = unsafe { sys::wc_RNG_GenerateBlock(self.wc_rng, ptr, size) }; if rc == 0 { Ok(()) } else { @@ -371,10 +391,10 @@ impl RNG { /// rng.reseed(&seed).expect("Error with reseed()"); /// ``` #[cfg(random_hashdrbg)] - pub fn reseed(&mut self, seed: &[u8]) -> Result<(), i32> { + pub fn reseed(&self, seed: &[u8]) -> Result<(), i32> { let seed_size = crate::buffer_len_to_u32(seed.len())?; let rc = unsafe { - sys::wc_RNG_DRBG_Reseed(&mut self.wc_rng, seed.as_ptr(), seed_size) + sys::wc_RNG_DRBG_Reseed(self.wc_rng, seed.as_ptr(), seed_size) }; if rc != 0 { return Err(rc); @@ -411,22 +431,16 @@ impl rand_core::TryRng for RNG { #[cfg(feature = "rand_core")] impl rand_core::TryCryptoRng for RNG {} -impl RNG { - fn zeroize(&mut self) { - unsafe { crate::zeroize_raw(&mut self.wc_rng); } - } -} - impl Drop for RNG { /// Safely free the underlying wolfSSL RNG context. /// - /// This calls the `wc_FreeRng` wolfssl library function. + /// This calls the `wc_rng_free` wolfssl library function, which frees the + /// C-heap-allocated `WC_RNG` object. /// /// The Rust Drop trait guarantees that this method is called when the RNG /// struct goes out of scope, automatically cleaning up resources and /// preventing memory leaks. fn drop(&mut self) { - unsafe { sys::wc_FreeRng(&mut self.wc_rng); } - self.zeroize(); + unsafe { sys::wc_rng_free(self.wc_rng); } } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs b/wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs index 3e89b79142a..6110bc2c1a9 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs @@ -35,20 +35,20 @@ use std::fs; use wolfssl_wolfcrypt::random::RNG; use wolfssl_wolfcrypt::rsa::RSA; -let mut rng = RNG::new().expect("Error creating RNG"); +let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); let key_path = "../../../certs/client-keyPub.der"; let der: Vec = fs::read(key_path).expect("Error reading key file"); let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); -rsa.set_rng(&mut rng).expect("Error with set_rng()"); +rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); let plain: &[u8] = b"Test message"; let mut enc: [u8; 512] = [0; 512]; -let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); +let enc_len = rsa.public_encrypt(plain, &mut enc, &rng).expect("Error with public_encrypt()"); assert!(enc_len > 0 && enc_len <= 512); let key_path = "../../../certs/client-key.der"; let der: Vec = fs::read(key_path).expect("Error reading key file"); let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); -rsa.set_rng(&mut rng).expect("Error with set_rng()"); +rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); let mut plain_out: [u8; 512] = [0; 512]; let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); assert!(dec_len as usize == plain.len()); @@ -61,7 +61,7 @@ assert_eq!(plain_out[0..dec_len], *plain); use crate::sys; #[cfg(random)] -use crate::random::RNG; +use crate::random::{RNG, RngHandle}; use core::mem::{MaybeUninit}; /// The `RSA` struct manages the lifecycle of a wolfSSL `RsaKey` object. @@ -72,6 +72,10 @@ use core::mem::{MaybeUninit}; /// or `generate()`. pub struct RSA { pub(crate) wc_rsakey: sys::RsaKey, + /// RNG bound to this key via `set_rng`. Kept alive here so the C struct's + /// internal `WC_RNG` pointer remains valid for as long as the key exists. + #[cfg(random)] + rng: Option, } impl RSA { @@ -143,26 +147,26 @@ impl RSA { /// /// ```rust /// # extern crate std; - /// #[cfg(random)] + /// #[cfg(all(random, feature = "alloc"))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; - /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); + /// let enc_len = rsa.public_encrypt(plain, &mut enc, &rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); @@ -191,26 +195,26 @@ impl RSA { /// /// ```rust /// # extern crate std; - /// #[cfg(random)] + /// #[cfg(all(random, feature = "alloc"))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; - /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); + /// let enc_len = rsa.public_encrypt(plain, &mut enc, &rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der_ex(&der, None, None).expect("Error with new_from_der_ex()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); @@ -241,7 +245,11 @@ impl RSA { unsafe { sys::wc_FreeRsaKey(&mut wc_rsakey); } return Err(rc); } - let rsa = RSA { wc_rsakey }; + let rsa = RSA { + wc_rsakey, + #[cfg(random)] + rng: None, + }; Ok(rsa) } @@ -260,26 +268,26 @@ impl RSA { /// /// ```rust /// # extern crate std; - /// #[cfg(random)] + /// #[cfg(all(random, feature = "alloc"))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; - /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); + /// let enc_len = rsa.public_encrypt(plain, &mut enc, &rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); @@ -308,26 +316,26 @@ impl RSA { /// /// ```rust /// # extern crate std; - /// #[cfg(random)] + /// #[cfg(all(random, feature = "alloc"))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der_ex(&der, None, None).expect("Error with new_public_from_der_ex()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; - /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); + /// let enc_len = rsa.public_encrypt(plain, &mut enc, &rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); @@ -358,7 +366,11 @@ impl RSA { unsafe { sys::wc_FreeRsaKey(&mut wc_rsakey); } return Err(rc); } - let rsa = RSA { wc_rsakey }; + let rsa = RSA { + wc_rsakey, + #[cfg(random)] + rng: None, + }; Ok(rsa) } @@ -411,7 +423,11 @@ impl RSA { unsafe { sys::wc_FreeRsaKey(&mut wc_rsakey); } return Err(rc); } - Ok(RSA { wc_rsakey }) + Ok(RSA { + wc_rsakey, + #[cfg(random)] + rng: None, + }) } /// Generate a new RSA key using the given size and exponent. @@ -446,15 +462,15 @@ impl RSA { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); - /// let mut rsa = RSA::generate(2048, 65537, &mut rng).expect("Error with generate()"); + /// let rng = RNG::new().expect("Error creating RNG"); + /// let mut rsa = RSA::generate(2048, 65537, &rng).expect("Error with generate()"); /// rsa.check().expect("Error with check()"); /// let encrypt_size = rsa.get_encrypt_size().expect("Error with get_encrypt_size()"); /// assert_eq!(encrypt_size, 256); /// } /// ``` #[cfg(all(random, rsa_keygen))] - pub fn generate(size: i32, e: i32, rng: &mut RNG) -> Result { + pub fn generate(size: i32, e: i32, rng: &RNG) -> Result { Self::generate_ex(size, e, rng, None, None) } @@ -493,15 +509,15 @@ impl RSA { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); - /// let mut rsa = RSA::generate_ex(2048, 65537, &mut rng, None, None).expect("Error with generate_ex()"); + /// let rng = RNG::new().expect("Error creating RNG"); + /// let mut rsa = RSA::generate_ex(2048, 65537, &rng, None, None).expect("Error with generate_ex()"); /// rsa.check().expect("Error with check()"); /// let encrypt_size = rsa.get_encrypt_size().expect("Error with get_encrypt_size()"); /// assert_eq!(encrypt_size, 256); /// } /// ``` #[cfg(all(random, rsa_keygen))] - pub fn generate_ex(size: i32, e: i32, rng: &mut RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { + pub fn generate_ex(size: i32, e: i32, rng: &RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_rsakey: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, @@ -518,13 +534,17 @@ impl RSA { let mut wc_rsakey = unsafe { wc_rsakey.assume_init() }; let e = e as core::ffi::c_long; let rc = unsafe { - sys::wc_MakeRsaKey(&mut wc_rsakey, size, e, &mut rng.wc_rng) + sys::wc_MakeRsaKey(&mut wc_rsakey, size, e, rng.wc_rng) }; if rc != 0 { unsafe { sys::wc_FreeRsaKey(&mut wc_rsakey); } return Err(rc); } - let rsa = RSA { wc_rsakey }; + let rsa = RSA { + wc_rsakey, + #[cfg(random)] + rng: None, + }; Ok(rsa) } @@ -556,8 +576,8 @@ impl RSA { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); - /// let mut rsa = RSA::generate(2048, 65537, &mut rng).expect("Error with generate()"); + /// let rng = RNG::new().expect("Error creating RNG"); + /// let mut rsa = RSA::generate(2048, 65537, &rng).expect("Error with generate()"); /// let mut e: [u8; 256] = [0; 256]; /// let mut e_size: u32 = 0; /// let mut n: [u8; 256] = [0; 256]; @@ -624,8 +644,8 @@ impl RSA { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); - /// let mut rsa = RSA::generate(2048, 65537, &mut rng).expect("Error with generate()"); + /// let rng = RNG::new().expect("Error creating RNG"); + /// let mut rsa = RSA::generate(2048, 65537, &rng).expect("Error with generate()"); /// let mut e: [u8; 256] = [0; 256]; /// let mut e_size: u32 = 0; /// let mut n: [u8; 256] = [0; 256]; @@ -667,8 +687,8 @@ impl RSA { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); - /// let mut rsa = RSA::generate(2048, 65537, &mut rng).expect("Error with generate()"); + /// let rng = RNG::new().expect("Error creating RNG"); + /// let mut rsa = RSA::generate(2048, 65537, &rng).expect("Error with generate()"); /// let encrypt_size = rsa.get_encrypt_size().expect("Error with get_encrypt_size()"); /// assert_eq!(encrypt_size, 256); /// } @@ -696,8 +716,8 @@ impl RSA { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); - /// let mut rsa = RSA::generate(2048, 65537, &mut rng).expect("Error with generate()"); + /// let rng = RNG::new().expect("Error creating RNG"); + /// let mut rsa = RSA::generate(2048, 65537, &rng).expect("Error with generate()"); /// rsa.check().expect("Error with check()"); /// } /// ``` @@ -729,26 +749,26 @@ impl RSA { /// /// ```rust /// # extern crate std; - /// #[cfg(random)] + /// #[cfg(all(random, feature = "alloc"))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; - /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); + /// let enc_len = rsa.public_encrypt(plain, &mut enc, &rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); @@ -756,13 +776,13 @@ impl RSA { /// } /// ``` #[cfg(random)] - pub fn public_encrypt(&mut self, din: &[u8], dout: &mut [u8], rng: &mut RNG) -> Result { + pub fn public_encrypt(&mut self, din: &[u8], dout: &mut [u8], rng: &RNG) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_RsaPublicEncrypt(din.as_ptr(), din_size, dout.as_mut_ptr(), dout_size, &mut self.wc_rsakey, - &mut rng.wc_rng) + rng.wc_rng) }; if rc < 0 { return Err(rc); @@ -788,26 +808,26 @@ impl RSA { /// /// ```rust /// # extern crate std; - /// #[cfg(random)] + /// #[cfg(all(random, feature = "alloc"))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; - /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); + /// let enc_len = rsa.public_encrypt(plain, &mut enc, &rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); @@ -855,20 +875,20 @@ impl RSA { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg: &[u8] = b"This is the string to be signed!"; /// let mut signature: [u8; 512] = [0; 512]; - /// let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &mut rng).expect("Error with pss_sign()"); + /// let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &rng).expect("Error with pss_sign()"); /// assert!(sig_len > 0 && sig_len <= 512); /// /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let signature = &signature[0..sig_len]; /// let mut verify_out: [u8; 512] = [0; 512]; /// let verify_out_size = rsa.pss_verify(signature, &mut verify_out, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify()"); @@ -880,12 +900,12 @@ impl RSA { /// } /// ``` #[cfg(all(random, rsa_pss))] - pub fn pss_sign(&mut self, din: &[u8], dout: &mut [u8], hash_algo: u32, mgf: i32, rng: &mut RNG) -> Result { + pub fn pss_sign(&mut self, din: &[u8], dout: &mut [u8], hash_algo: u32, mgf: i32, rng: &RNG) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_RsaPSS_Sign(din.as_ptr(), din_size, dout.as_mut_ptr(), dout_size, - hash_algo, mgf, &mut self.wc_rsakey, &mut rng.wc_rng) + hash_algo, mgf, &mut self.wc_rsakey, rng.wc_rng) }; if rc < 0 { return Err(rc); @@ -918,20 +938,20 @@ impl RSA { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg: &[u8] = b"This is the string to be signed!"; /// let mut signature: [u8; 512] = [0; 512]; - /// let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &mut rng).expect("Error with pss_sign()"); + /// let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &rng).expect("Error with pss_sign()"); /// assert!(sig_len > 0 && sig_len <= 512); /// /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let signature = &signature[0..sig_len]; /// let mut verify_out: [u8; 512] = [0; 512]; /// let verify_out_size = rsa.pss_verify(signature, &mut verify_out, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify()"); @@ -984,20 +1004,20 @@ impl RSA { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg: &[u8] = b"This is the string to be signed!"; /// let mut signature: [u8; 512] = [0; 512]; - /// let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &mut rng).expect("Error with pss_sign()"); + /// let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &rng).expect("Error with pss_sign()"); /// assert!(sig_len > 0 && sig_len <= 512); /// /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let signature = &signature[0..sig_len]; /// let mut verify_out: [u8; 512] = [0; 512]; /// let verify_out_size = rsa.pss_verify(signature, &mut verify_out, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify()"); @@ -1055,20 +1075,20 @@ impl RSA { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg: &[u8] = b"This is the string to be signed!"; /// let mut signature: [u8; 512] = [0; 512]; - /// let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &mut rng).expect("Error with pss_sign()"); + /// let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &rng).expect("Error with pss_sign()"); /// assert!(sig_len > 0 && sig_len <= 512); /// /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let signature = &signature[0..sig_len]; /// let mut verify_out: [u8; 512] = [0; 512]; /// let verify_out_size = rsa.pss_verify(signature, &mut verify_out, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify()"); @@ -1125,7 +1145,7 @@ impl RSA { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = RNG::new().expect("Error creating RNG"); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); @@ -1134,22 +1154,22 @@ impl RSA { /// let mut plain = [0u8; 256]; /// plain[..msg.len()].copy_from_slice(msg); /// let mut enc = [0u8; 256]; - /// let enc_len = rsa.rsa_direct(&plain, &mut enc, RSA::PRIVATE_ENCRYPT, &mut rng).expect("Error with rsa_direct()"); + /// let enc_len = rsa.rsa_direct(&plain, &mut enc, RSA::PRIVATE_ENCRYPT, &rng).expect("Error with rsa_direct()"); /// assert_eq!(enc_len, 256); /// let mut plain_out = [0u8; 256]; - /// let dec_len = rsa.rsa_direct(&enc, &mut plain_out, RSA::PUBLIC_DECRYPT, &mut rng).expect("Error with rsa_direct()"); + /// let dec_len = rsa.rsa_direct(&enc, &mut plain_out, RSA::PUBLIC_DECRYPT, &rng).expect("Error with rsa_direct()"); /// assert_eq!(dec_len, 256); /// assert_eq!(plain_out, plain); /// } /// ``` #[cfg(all(rsa_direct, rsa_const_api))] - pub fn rsa_direct(&mut self, din: &[u8], dout: &mut [u8], typ: i32, rng: &mut RNG) -> Result { + pub fn rsa_direct(&mut self, din: &[u8], dout: &mut [u8], typ: i32, rng: &RNG) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let mut dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_RsaDirect(din.as_ptr(), din_size, dout.as_mut_ptr(), &mut dout_size, - &mut self.wc_rsakey, typ, &mut rng.wc_rng) + &mut self.wc_rsakey, typ, rng.wc_rng) }; if rc < 0 { return Err(rc); @@ -1165,8 +1185,7 @@ impl RSA { /// # Parameters /// /// * `rng`: The `RNG` struct instance to associate with this `RSA` - /// instance. The `RNG` struct should not be moved in memory after - /// calling this method. + /// instance. /// /// # Returns /// @@ -1177,25 +1196,25 @@ impl RSA { /// /// ```rust /// # extern crate std; - /// #[cfg(random)] + /// #[cfg(all(random, feature = "alloc"))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; - /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); + /// let enc_len = rsa.public_encrypt(plain, &mut enc, &rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); @@ -1203,16 +1222,47 @@ impl RSA { /// } /// ``` #[cfg(random)] - pub fn set_rng(&mut self, rng: &mut RNG) -> Result<(), i32> { + pub fn set_rng(&mut self, rng: RNG) -> Result<(), i32> { + let wc_rng = rng.wc_rng; + let rc = unsafe { + sys::wc_RsaSetRNG(&mut self.wc_rsakey, wc_rng) + }; + if rc != 0 { + return Err(rc); + } + self.rng = Some(RngHandle::Owned(rng)); + Ok(()) + } + + /// Bind a shared `RNG` to this key for blinding during private operations. + /// + /// Like `set_rng`, but takes an `Arc` so the same RNG can be shared + /// among multiple consumers and used directly by the caller. Available + /// when the `alloc` feature is enabled. + #[cfg(all(random, feature = "alloc"))] + pub fn set_shared_rng(&mut self, rng: alloc::sync::Arc) -> Result<(), i32> { + let wc_rng = rng.wc_rng; let rc = unsafe { - sys::wc_RsaSetRNG(&mut self.wc_rsakey, &mut rng.wc_rng) + sys::wc_RsaSetRNG(&mut self.wc_rsakey, wc_rng) }; if rc != 0 { return Err(rc); } + self.rng = Some(RngHandle::Shared(rng)); Ok(()) } + /// Borrow the RNG previously bound via `set_rng` or `set_shared_rng`. + #[cfg(random)] + pub fn rng(&self) -> Option<&RNG> { + match &self.rng { + Some(RngHandle::Owned(rng)) => Some(rng), + #[cfg(feature = "alloc")] + Some(RngHandle::Shared(rng)) => Some(rng), + None => None, + } + } + /// Sign the provided data with the private key. /// /// # Parameters @@ -1233,26 +1283,26 @@ impl RSA { /// /// ```rust /// # extern crate std; - /// #[cfg(random)] + /// #[cfg(all(random, feature = "alloc"))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg: &[u8] = b"This is the string to be signed!"; /// let mut signature: [u8; 512] = [0; 512]; - /// let sig_len = rsa.ssl_sign(msg, &mut signature, &mut rng).expect("Error with ssl_sign()"); + /// let sig_len = rsa.ssl_sign(msg, &mut signature, &rng).expect("Error with ssl_sign()"); /// assert!(sig_len > 0 && sig_len <= 512); /// /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let signature = &signature[0..sig_len]; /// let mut verify_out: [u8; 512] = [0; 512]; /// let verify_out_size = rsa.ssl_verify(signature, &mut verify_out).expect("Error with ssl_verify()"); @@ -1260,13 +1310,13 @@ impl RSA { /// } /// ``` #[cfg(random)] - pub fn ssl_sign(&mut self, din: &[u8], dout: &mut [u8], rng: &mut RNG) -> Result { + pub fn ssl_sign(&mut self, din: &[u8], dout: &mut [u8], rng: &RNG) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_RsaSSL_Sign(din.as_ptr(), din_size, dout.as_mut_ptr(), dout_size, - &mut self.wc_rsakey, &mut rng.wc_rng) + &mut self.wc_rsakey, rng.wc_rng) }; if rc < 0 { return Err(rc); @@ -1295,26 +1345,26 @@ impl RSA { /// /// ```rust /// # extern crate std; - /// #[cfg(random)] + /// #[cfg(all(random, feature = "alloc"))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// - /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let rng = std::sync::Arc::new(RNG::new().expect("Error creating RNG")); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg: &[u8] = b"This is the string to be signed!"; /// let mut signature: [u8; 512] = [0; 512]; - /// let sig_len = rsa.ssl_sign(msg, &mut signature, &mut rng).expect("Error with ssl_sign()"); + /// let sig_len = rsa.ssl_sign(msg, &mut signature, &rng).expect("Error with ssl_sign()"); /// assert!(sig_len > 0 && sig_len <= 512); /// /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); + /// rsa.set_shared_rng(std::sync::Arc::clone(&rng)).expect("Error with set_shared_rng()"); /// let signature = &signature[0..sig_len]; /// let mut verify_out: [u8; 512] = [0; 512]; /// let verify_out_size = rsa.ssl_verify(signature, &mut verify_out).expect("Error with ssl_verify()"); diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/rsa_pkcs1v15.rs b/wrapper/rust/wolfssl-wolfcrypt/src/rsa_pkcs1v15.rs index 40314f95488..576f63e222d 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/rsa_pkcs1v15.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/rsa_pkcs1v15.rs @@ -149,9 +149,9 @@ pub struct SigningKey { impl SigningKey { /// Generate a fresh `N * 8`-bit RSA key with public exponent 65537. #[cfg(rsa_keygen)] - pub fn generate(mut rng: RNG) -> Result { + pub fn generate(rng: RNG) -> Result { let bits: i32 = (N * 8).try_into().map_err(|_| sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG)?; - let rsa = RSA::generate(bits, 65537, &mut rng)?; + let rsa = RSA::generate(bits, 65537, &rng)?; Ok(Self { inner: rsa, rng, _hash: PhantomData }) } @@ -186,7 +186,7 @@ impl SignerMut> for SigningKey { sig.as_mut_ptr(), &mut sig_len, &mut self.inner.wc_rsakey as *mut _ as *mut c_void, size_of::() as u32, - &mut self.rng.wc_rng, + self.rng.wc_rng, ) }; if rc != 0 || sig_len as usize != N { diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs index e215891691b..d5a171fd9ea 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs @@ -1030,6 +1030,29 @@ fn test_aes256gcm_nist_tc14_encrypt() { assert_eq!(&tag[..], &expected_tag); } +/// Roundtrip test for AES-192-GCM using `aead::Aead`. +#[test] +#[cfg(all(feature = "aead", aes_gcm))] +fn test_aes192gcm_aead_roundtrip() { + let key = [0x77u8; 24]; + let nonce_bytes = [0x88u8; 12]; + let aad = b"aes-192-gcm test"; + let plaintext = b"AES-192-GCM roundtrip test"; + + let cipher = Aes192Gcm::new_from_slice(&key).unwrap(); + let nonce: aead::Nonce = nonce_bytes.into(); + + let ciphertext = cipher + .encrypt(&nonce, Payload { msg: plaintext, aad }) + .expect("AES-192-GCM encrypt failed"); + + let recovered = cipher + .decrypt(&nonce, Payload { msg: &ciphertext, aad }) + .expect("AES-192-GCM decrypt failed"); + + assert_eq!(recovered, plaintext); +} + /// Roundtrip test for AES-256-GCM using `aead::Aead`. #[test] #[cfg(all(feature = "aead", aes_gcm))] @@ -1092,6 +1115,29 @@ fn test_aes128ccm_reject_tampered() { assert!(cipher.decrypt(&nonce, ct.as_slice()).is_err()); } +/// Roundtrip test for AES-192-CCM using `aead::Aead`. +#[test] +#[cfg(all(feature = "aead", aes_ccm))] +fn test_aes192ccm_aead_roundtrip() { + let key = [0x33u8; 24]; + let nonce_bytes = [0x44u8; 12]; + let aad = b"aes-192-ccm test"; + let plaintext = b"AES-192-CCM plaintext data"; + + let cipher = Aes192Ccm::new_from_slice(&key).unwrap(); + let nonce: aead::Nonce = nonce_bytes.into(); + + let ciphertext = cipher + .encrypt(&nonce, Payload { msg: plaintext, aad }) + .expect("AES-192-CCM encrypt failed"); + + let recovered = cipher + .decrypt(&nonce, Payload { msg: &ciphertext, aad }) + .expect("AES-192-CCM decrypt failed"); + + assert_eq!(recovered, plaintext); +} + /// Roundtrip test for AES-256-CCM using `aead::Aead`. #[test] #[cfg(all(feature = "aead", aes_ccm))] diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_blake2_digest.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_blake2_digest.rs new file mode 100644 index 00000000000..49d28c6fac1 --- /dev/null +++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_blake2_digest.rs @@ -0,0 +1,126 @@ +#![cfg(all(any(blake2b, blake2s), feature = "digest"))] + +use digest::{Digest, FixedOutputReset}; +use digest::block_api::BlockSizeUser; + +mod common; + +fn check_digest( + input: &[u8], + expected: &[u8], + expected_block_size: usize, +) { + assert_eq!(::output_size(), expected.len()); + assert_eq!(::block_size(), expected_block_size); + + /* One-shot digest via associated function. */ + let out = D::digest(input); + assert_eq!(out.as_slice(), expected); + + /* Streaming via Digest::update and finalize. */ + let mut hasher = D::new(); + Digest::update(&mut hasher, input); + let out = hasher.finalize(); + assert_eq!(out.as_slice(), expected); + + /* Split update via Default + Update + FixedOutputReset::finalize_reset. */ + let mut hasher = D::default(); + if input.len() >= 2 { + let mid = input.len() / 2; + Digest::update(&mut hasher, &input[..mid]); + Digest::update(&mut hasher, &input[mid..]); + } else { + Digest::update(&mut hasher, input); + } + let out = hasher.finalize_reset(); + assert_eq!(out.as_slice(), expected); + + /* After reset, the same hasher should produce the same result. */ + Digest::update(&mut hasher, input); + let out = hasher.finalize(); + assert_eq!(out.as_slice(), expected); +} + +#[test] +#[cfg(blake2b)] +fn test_digest_blake2b_512() { + use wolfssl_wolfcrypt::blake2_digest::Blake2b512; + common::setup(); + check_digest::( + b"abc", + b"\xBA\x80\xA5\x3F\x98\x1C\x4D\x0D\x6A\x27\x97\xB6\x9F\x12\xF6\xE9\x4C\x21\x2F\x14\x68\x5A\xC4\xB7\x4B\x12\xBB\x6F\xDB\xFF\xA2\xD1\x7D\x87\xC5\x39\x2A\xAB\x79\x2D\xC2\x52\xD5\xDE\x45\x33\xCC\x95\x18\xD3\x8A\xA8\xDB\xF1\x92\x5A\xB9\x23\x86\xED\xD4\x00\x99\x23", + 128, + ); +} + +#[test] +#[cfg(blake2b)] +fn test_digest_blake2b_384() { + use wolfssl_wolfcrypt::blake2::BLAKE2b; + use wolfssl_wolfcrypt::blake2_digest::Blake2b384; + common::setup(); + + let mut reference = BLAKE2b::new(48).expect("Error with new()"); + reference.update(b"abc").expect("Error with update()"); + let mut expected = [0u8; 48]; + reference.finalize(&mut expected).expect("Error with finalize()"); + + check_digest::(b"abc", &expected, 128); +} + +#[test] +#[cfg(blake2b)] +fn test_digest_blake2b_256() { + use wolfssl_wolfcrypt::blake2::BLAKE2b; + use wolfssl_wolfcrypt::blake2_digest::Blake2b256; + common::setup(); + + let mut reference = BLAKE2b::new(32).expect("Error with new()"); + reference.update(b"abc").expect("Error with update()"); + let mut expected = [0u8; 32]; + reference.finalize(&mut expected).expect("Error with finalize()"); + + check_digest::(b"abc", &expected, 128); +} + +#[test] +#[cfg(blake2s)] +fn test_digest_blake2s_256() { + use wolfssl_wolfcrypt::blake2_digest::Blake2s256; + common::setup(); + check_digest::( + b"abc", + b"\x50\x8C\x5E\x8C\x32\x7C\x14\xE2\xE1\xA7\x2B\xA3\x4E\xEB\x45\x2F\x37\x45\x8B\x20\x9E\xD6\x3A\x29\x4D\x99\x9B\x4C\x86\x67\x59\x82", + 64, + ); +} + +#[test] +#[cfg(blake2s)] +fn test_digest_blake2s_192() { + use wolfssl_wolfcrypt::blake2::BLAKE2s; + use wolfssl_wolfcrypt::blake2_digest::Blake2s192; + common::setup(); + + let mut reference = BLAKE2s::new(24).expect("Error with new()"); + reference.update(b"abc").expect("Error with update()"); + let mut expected = [0u8; 24]; + reference.finalize(&mut expected).expect("Error with finalize()"); + + check_digest::(b"abc", &expected, 64); +} + +#[test] +#[cfg(blake2s)] +fn test_digest_blake2s_128() { + use wolfssl_wolfcrypt::blake2::BLAKE2s; + use wolfssl_wolfcrypt::blake2_digest::Blake2s128; + common::setup(); + + let mut reference = BLAKE2s::new(16).expect("Error with new()"); + reference.update(b"abc").expect("Error with update()"); + let mut expected = [0u8; 16]; + reference.finalize(&mut expected).expect("Error with finalize()"); + + check_digest::(b"abc", &expected, 64); +} diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_blake2_mac.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_blake2_mac.rs new file mode 100644 index 00000000000..a25761a2bd4 --- /dev/null +++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_blake2_mac.rs @@ -0,0 +1,181 @@ +#![cfg(all(any(blake2b, blake2s), feature = "mac"))] + +use digest::{KeyInit, Mac}; + +#[test] +#[cfg(blake2b)] +fn test_blake2b_mac_512() { + use wolfssl_wolfcrypt::blake2::BLAKE2b; + use wolfssl_wolfcrypt::blake2_mac::Blake2bMac512; + + let key = [0x42u8; 64]; + let input = b"The quick brown fox jumps over the lazy dog"; + + let mut reference = BLAKE2b::new_with_key(64, &key) + .expect("Error with new_with_key()"); + reference.update(input).expect("Error with update()"); + let mut expected = [0u8; 64]; + reference.finalize(&mut expected) + .expect("Error with finalize()"); + + let mut mac = Blake2bMac512::new_from_slice(&key) + .expect("Blake2bMac512 init failed"); + mac.update(input); + let tag = mac.finalize(); + assert_eq!(tag.into_bytes().as_slice(), &expected); +} + +#[test] +#[cfg(blake2b)] +fn test_blake2b_mac_256() { + use wolfssl_wolfcrypt::blake2::BLAKE2b; + use wolfssl_wolfcrypt::blake2_mac::Blake2bMac256; + + let key = [0x33u8; 64]; + let input = b"libsodium crypto_generichash analog"; + + let mut reference = BLAKE2b::new_with_key(32, &key) + .expect("Error with new_with_key()"); + reference.update(input).expect("Error with update()"); + let mut expected = [0u8; 32]; + reference.finalize(&mut expected) + .expect("Error with finalize()"); + + let mut mac = Blake2bMac256::new_from_slice(&key) + .expect("Blake2bMac256 init failed"); + mac.update(input); + let tag = mac.finalize(); + assert_eq!(tag.into_bytes().as_slice(), &expected); +} + +#[test] +#[cfg(blake2b)] +fn test_blake2b_mac_384() { + use wolfssl_wolfcrypt::blake2::BLAKE2b; + use wolfssl_wolfcrypt::blake2_mac::Blake2bMac384; + + let key = [0x77u8; 64]; + let input = b"sha-384 sized blake2b mac"; + + let mut reference = BLAKE2b::new_with_key(48, &key) + .expect("Error with new_with_key()"); + reference.update(input).expect("Error with update()"); + let mut expected = [0u8; 48]; + reference.finalize(&mut expected) + .expect("Error with finalize()"); + + let mut mac = Blake2bMac384::new_from_slice(&key) + .expect("Blake2bMac384 init failed"); + mac.update(input); + let tag = mac.finalize(); + assert_eq!(tag.into_bytes().as_slice(), &expected); +} + +#[test] +#[cfg(blake2b)] +fn test_blake2b_mac_512_chunked() { + use wolfssl_wolfcrypt::blake2::BLAKE2b; + use wolfssl_wolfcrypt::blake2_mac::Blake2bMac512; + + let key = [0xA5u8; 64]; + let input: Vec = (0u8..200).collect(); + + let mut reference = BLAKE2b::new_with_key(64, &key) + .expect("Error with new_with_key()"); + reference.update(&input).expect("Error with update()"); + let mut expected = [0u8; 64]; + reference.finalize(&mut expected) + .expect("Error with finalize()"); + + let mut mac = Blake2bMac512::new_from_slice(&key) + .expect("Blake2bMac512 init failed"); + for chunk in input.chunks(17) { + mac.update(chunk); + } + mac.verify_slice(&expected) + .expect("Blake2bMac512 verify failed"); +} + +#[test] +#[cfg(blake2s)] +fn test_blake2s_mac_128() { + use wolfssl_wolfcrypt::blake2::BLAKE2s; + use wolfssl_wolfcrypt::blake2_mac::Blake2sMac128; + + let key = [0x55u8; 32]; + let input = b"short blake2s mac"; + + let mut reference = BLAKE2s::new_with_key(16, &key) + .expect("Error with new_with_key()"); + reference.update(input).expect("Error with update()"); + let mut expected = [0u8; 16]; + reference.finalize(&mut expected) + .expect("Error with finalize()"); + + let mut mac = Blake2sMac128::new_from_slice(&key) + .expect("Blake2sMac128 init failed"); + mac.update(input); + let tag = mac.finalize(); + assert_eq!(tag.into_bytes().as_slice(), &expected); +} + +#[test] +#[cfg(blake2s)] +fn test_blake2s_mac_192() { + use wolfssl_wolfcrypt::blake2::BLAKE2s; + use wolfssl_wolfcrypt::blake2_mac::Blake2sMac192; + + let key = [0x99u8; 32]; + let input = b"medium blake2s mac"; + + let mut reference = BLAKE2s::new_with_key(24, &key) + .expect("Error with new_with_key()"); + reference.update(input).expect("Error with update()"); + let mut expected = [0u8; 24]; + reference.finalize(&mut expected) + .expect("Error with finalize()"); + + let mut mac = Blake2sMac192::new_from_slice(&key) + .expect("Blake2sMac192 init failed"); + mac.update(input); + let tag = mac.finalize(); + assert_eq!(tag.into_bytes().as_slice(), &expected); +} + +#[test] +#[cfg(blake2s)] +fn test_blake2s_mac_256() { + use wolfssl_wolfcrypt::blake2::BLAKE2s; + use wolfssl_wolfcrypt::blake2_mac::Blake2sMac256; + + let key = [0x42u8; 32]; + let input = b"The quick brown fox jumps over the lazy dog"; + + let mut reference = BLAKE2s::new_with_key(32, &key) + .expect("Error with new_with_key()"); + reference.update(input).expect("Error with update()"); + let mut expected = [0u8; 32]; + reference.finalize(&mut expected) + .expect("Error with finalize()"); + + let mut mac = Blake2sMac256::new_from_slice(&key) + .expect("Blake2sMac256 init failed"); + mac.update(input); + let tag = mac.finalize(); + assert_eq!(tag.into_bytes().as_slice(), &expected); +} + +#[test] +#[cfg(blake2s)] +fn test_blake2s_mac_256_verify_fail() { + use wolfssl_wolfcrypt::blake2_mac::Blake2sMac256; + + let key = [0x0Bu8; 32]; + let input = b"hello"; + let wrong_tag = [0u8; 32]; + + let mut mac = Blake2sMac256::new_from_slice(&key) + .expect("Blake2sMac256 init failed"); + mac.update(input); + assert!(mac.verify_slice(&wrong_tag).is_err()); +} diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_curve25519.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_curve25519.rs index ce1e3cc39d2..98806b69ca8 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_curve25519.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_curve25519.rs @@ -1,5 +1,7 @@ #![cfg(all(curve25519, random))] +#[cfg(curve25519_blinding)] +use std::sync::Arc; use wolfssl_wolfcrypt::curve25519::*; use wolfssl_wolfcrypt::random::RNG; @@ -97,14 +99,17 @@ fn test_make_pub_blind() { #[test] fn test_shared_secret() { - let mut rng = RNG::new().expect("Error with new()"); - let mut key1 = Curve25519Key::generate(&mut rng).expect("Error with generate()"); - let mut key2 = Curve25519Key::generate(&mut rng).expect("Error with generate()"); + #[cfg(curve25519_blinding)] + let rng = Arc::new(RNG::new().expect("Error with new()")); + #[cfg(not(curve25519_blinding))] + let rng = RNG::new().expect("Error with new()"); + let mut key1 = Curve25519Key::generate(&rng).expect("Error with generate()"); + let mut key2 = Curve25519Key::generate(&rng).expect("Error with generate()"); #[cfg(curve25519_blinding)] - key1.set_rng(&mut rng).expect("Error with set_rng()"); + key1.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); #[cfg(curve25519_blinding)] - key2.set_rng(&mut rng).expect("Error with set_rng()"); + key2.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); let mut public_buffer = [0u8; Curve25519Key::KEYSIZE]; key1.export_public(&mut public_buffer).expect("Error with export_public()"); @@ -122,14 +127,17 @@ fn test_shared_secret() { #[test] fn test_shared_secret_ex() { - let mut rng = RNG::new().expect("Error with new()"); - let mut key1 = Curve25519Key::generate(&mut rng).expect("Error with generate()"); - let mut key2 = Curve25519Key::generate(&mut rng).expect("Error with generate()"); + #[cfg(curve25519_blinding)] + let rng = Arc::new(RNG::new().expect("Error with new()")); + #[cfg(not(curve25519_blinding))] + let rng = RNG::new().expect("Error with new()"); + let mut key1 = Curve25519Key::generate(&rng).expect("Error with generate()"); + let mut key2 = Curve25519Key::generate(&rng).expect("Error with generate()"); #[cfg(curve25519_blinding)] - key1.set_rng(&mut rng).expect("Error with set_rng()"); + key1.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); #[cfg(curve25519_blinding)] - key2.set_rng(&mut rng).expect("Error with set_rng()"); + key2.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); let mut public_buffer = [0u8; Curve25519Key::KEYSIZE]; key1.export_public(&mut public_buffer).expect("Error with export_public()"); diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_ecc.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_ecc.rs index 30d2d5b3fc1..423d5a8bbe6 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_ecc.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_ecc.rs @@ -4,6 +4,8 @@ mod common; #[cfg(any(all(ecc_import, ecc_export, ecc_sign, ecc_verify, random), random))] use std::fs; +#[cfg(all(ecc_dh, random))] +use std::sync::Arc; use wolfssl_wolfcrypt::ecc::*; #[cfg(random)] use wolfssl_wolfcrypt::random::RNG; @@ -134,7 +136,7 @@ fn test_ecc_import_export_sign_verify() { let valid = ecc.verify_hash(&signature, &hash).expect("Error with verify_hash()"); assert_eq!(valid, false); - ecc.set_rng(&mut rng).expect("Error with set_rng()"); + ecc.set_rng(rng).expect("Error with set_rng()"); } #[test] @@ -142,13 +144,13 @@ fn test_ecc_import_export_sign_verify() { fn test_ecc_shared_secret() { common::setup(); - let mut rng = RNG::new().expect("Failed to create RNG"); - let mut ecc0 = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); - let mut ecc1 = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); + let rng = Arc::new(RNG::new().expect("Failed to create RNG")); + let mut ecc0 = ECC::generate(32, &rng, None, None).expect("Error with generate()"); + let mut ecc1 = ECC::generate(32, &rng, None, None).expect("Error with generate()"); let mut ss0 = [0u8; 128]; let mut ss1 = [0u8; 128]; - ecc0.set_rng(&mut rng).expect("Error with set_rng()"); - ecc1.set_rng(&mut rng).expect("Error with set_rng()"); + ecc0.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); + ecc1.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); let ss0_size = ecc0.shared_secret(&mut ecc1, &mut ss0).expect("Error with shared_secret()"); let ss1_size = ecc1.shared_secret(&mut ecc0, &mut ss1).expect("Error with shared_secret()"); assert_eq!(ss0_size, ss1_size); @@ -365,6 +367,34 @@ fn test_ecc_import() { ECC::import_raw_ex(qx, qy, d, ECC::SECP256R1, None, None).expect("Error with import_raw_ex()"); } +#[test] +#[cfg(ecc_import)] +fn test_ecc_import_raw_not_null_terminated() { + common::setup(); + + let qx = b"7a4e287890a1a47ad3457e52f2f76a83ce46cbc947616d0cbaa82323818a793d\0"; + let qy = b"eec4084f5b29ebf29c44cce3b3059610922f8b30ea6e8811742ac7238fe87308\0"; + let d = b"8c14b793cb19137e323a6d2e2a870bca2e7a493ec1153b3a95feb8a4873f8d08\0"; + let qx_no_nul: &[u8] = &qx[..qx.len() - 1]; + let qy_no_nul: &[u8] = &qy[..qy.len() - 1]; + let d_no_nul: &[u8] = &d[..d.len() - 1]; + let curve_name = b"SECP256R1\0"; + let curve_name_no_nul: &[u8] = b"SECP256R1"; + let empty: &[u8] = b""; + + assert!(ECC::import_raw(qx_no_nul, qy, d, curve_name, None, None).is_err()); + assert!(ECC::import_raw(qx, qy_no_nul, d, curve_name, None, None).is_err()); + assert!(ECC::import_raw(qx, qy, d_no_nul, curve_name, None, None).is_err()); + assert!(ECC::import_raw(qx, qy, d, curve_name_no_nul, None, None).is_err()); + assert!(ECC::import_raw(empty, qy, d, curve_name, None, None).is_err()); + assert!(ECC::import_raw(qx, qy, d, empty, None, None).is_err()); + + assert!(ECC::import_raw_ex(qx_no_nul, qy, d, ECC::SECP256R1, None, None).is_err()); + assert!(ECC::import_raw_ex(qx, qy_no_nul, d, ECC::SECP256R1, None, None).is_err()); + assert!(ECC::import_raw_ex(qx, qy, d_no_nul, ECC::SECP256R1, None, None).is_err()); + assert!(ECC::import_raw_ex(qx, qy, empty, ECC::SECP256R1, None, None).is_err()); +} + #[test] fn test_ecc_rs_hex_to_sig_not_null_terminated() { common::setup(); diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_hmac_mac.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_hmac_mac.rs index 6a7067b0eee..fab799bae64 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_hmac_mac.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_hmac_mac.rs @@ -40,6 +40,27 @@ fn test_hmac_sha256_mac_finalize() { assert_eq!(result.as_bytes().as_slice(), expected); } +#[test] +fn test_hmac_sha256_mac_clone() { + let key = b"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; + let prefix = b"Hi "; + let suffix = b"There"; + let expected = b"\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7"; + + let mut mac = HmacSha256::new_from_slice(key) + .expect("HMAC init failed"); + mac.update(prefix); + + let mut forked = mac.clone(); + forked.update(suffix); + let forked_tag = forked.finalize(); + assert_eq!(forked_tag.as_bytes().as_slice(), expected); + + mac.update(suffix); + let original_tag = mac.finalize(); + assert_eq!(original_tag.as_bytes().as_slice(), expected); +} + #[test] fn test_hmac_sha256_mac_verify_fail() { let key = b"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_random.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_random.rs index bf7f1536a70..45977123ad9 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_random.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_random.rs @@ -52,7 +52,7 @@ fn test_test_seed() { fn test_rng_generate_byte() { // Since a single 0x00 or 0xFF could occur occasionally, we'll combine four // bytes into a u32 and make sure they aren't all 0x00 or all 0xFF. - let mut rng = RNG::new().expect("Failed to create RNG"); + let rng = RNG::new().expect("Failed to create RNG"); let mut v: u32 = 0; for _i in 0..4 { let byte = rng.generate_byte().expect("Failed to generate a single byte"); @@ -65,7 +65,7 @@ fn test_rng_generate_byte() { // Test that generate_block works for a slice of u8. #[test] fn test_rng_generate_block_u8() { - let mut rng = RNG::new().expect("Failed to create RNG"); + let rng = RNG::new().expect("Failed to create RNG"); let mut buffer = [0u8; 32]; rng.generate_block(&mut buffer).expect("Failed to generate a block of bytes"); @@ -77,7 +77,7 @@ fn test_rng_generate_block_u8() { // Test that generate_block works for a slice of u32. #[test] fn test_rng_generate_block_u32() { - let mut rng = RNG::new().expect("Failed to create RNG"); + let rng = RNG::new().expect("Failed to create RNG"); let mut buffer = [0u32; 8]; rng.generate_block(&mut buffer).expect("Failed to generate a block of u32"); @@ -93,7 +93,7 @@ fn test_rng_generate_block_u32() { #[test] #[cfg(random_hashdrbg)] fn test_rng_reseed() { - let mut rng = RNG::new().expect("Failed to create RNG"); + let rng = RNG::new().expect("Failed to create RNG"); let seed = [1u8, 2, 3, 4]; rng.reseed(&seed).expect("Error with reseed()"); } diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_rsa.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_rsa.rs index b8d19cfaec0..aa0b48d577e 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_rsa.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_rsa.rs @@ -5,6 +5,8 @@ mod common; #[cfg(any(all(sha256, random, rsa_pss), random, rsa_direct))] use std::fs; #[cfg(random)] +use std::sync::Arc; +#[cfg(random)] use wolfssl_wolfcrypt::random::RNG; #[cfg(any(random, rsa_direct, rsa_keygen))] use wolfssl_wolfcrypt::rsa::*; @@ -14,8 +16,8 @@ use wolfssl_wolfcrypt::rsa::*; fn test_rsa_generate() { common::setup(); - let mut rng = RNG::new().expect("Error creating RNG"); - let mut rsa = RSA::generate(2048, 65537, &mut rng).expect("Error with generate()"); + let rng = RNG::new().expect("Error creating RNG"); + let mut rsa = RSA::generate(2048, 65537, &rng).expect("Error with generate()"); rsa.check().expect("Error with check()"); let encrypt_size = rsa.get_encrypt_size().expect("Error with get_encrypt_size()"); @@ -58,20 +60,20 @@ fn test_rsa_generate() { #[test] #[cfg(random)] fn test_rsa_encrypt_decrypt() { - let mut rng = RNG::new().expect("Error creating RNG"); + let rng = Arc::new(RNG::new().expect("Error creating RNG")); let key_path = "../../../certs/client-keyPub.der"; let der: Vec = fs::read(key_path).expect("Error reading key file"); let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - rsa.set_rng(&mut rng).expect("Error with set_rng()"); + rsa.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); let plain: &[u8] = b"Test message"; let mut enc: [u8; 512] = [0; 512]; - let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); + let enc_len = rsa.public_encrypt(plain, &mut enc, &rng).expect("Error with public_encrypt()"); assert!(enc_len > 0 && enc_len <= 512); let key_path = "../../../certs/client-key.der"; let der: Vec = fs::read(key_path).expect("Error reading key file"); let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); - rsa.set_rng(&mut rng).expect("Error with set_rng()"); + rsa.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); let mut plain_out: [u8; 512] = [0; 512]; let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); assert!(dec_len as usize == plain.len()); @@ -81,20 +83,20 @@ fn test_rsa_encrypt_decrypt() { #[test] #[cfg(all(sha256, random, rsa_pss))] fn test_rsa_pss() { - let mut rng = RNG::new().expect("Error creating RNG"); + let rng = Arc::new(RNG::new().expect("Error creating RNG")); let key_path = "../../../certs/client-key.der"; let der: Vec = fs::read(key_path).expect("Error reading key file"); let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); let msg: &[u8] = b"This is the string to be signed!"; let mut signature: [u8; 512] = [0; 512]; - let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &mut rng).expect("Error with pss_sign()"); + let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &rng).expect("Error with pss_sign()"); assert!(sig_len > 0 && sig_len <= 512); let key_path = "../../../certs/client-keyPub.der"; let der: Vec = fs::read(key_path).expect("Error reading key file"); let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - rsa.set_rng(&mut rng).expect("Error with set_rng()"); + rsa.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); let signature = &signature[0..sig_len]; let mut verify_out: [u8; 512] = [0; 512]; let verify_out_size = rsa.pss_verify(signature, &mut verify_out, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify()"); @@ -108,7 +110,7 @@ fn test_rsa_pss() { #[test] #[cfg(rsa_direct)] fn test_rsa_direct() { - let mut rng = RNG::new().expect("Error creating RNG"); + let rng = RNG::new().expect("Error creating RNG"); let key_path = "../../../certs/client-key.der"; let der: Vec = fs::read(key_path).expect("Error reading key file"); @@ -117,10 +119,10 @@ fn test_rsa_direct() { let mut plain = [0u8; 256]; plain[..msg.len()].copy_from_slice(msg); let mut enc = [0u8; 256]; - let enc_len = rsa.rsa_direct(&plain, &mut enc, RSA::PRIVATE_ENCRYPT, &mut rng).expect("Error with rsa_direct()"); + let enc_len = rsa.rsa_direct(&plain, &mut enc, RSA::PRIVATE_ENCRYPT, &rng).expect("Error with rsa_direct()"); assert_eq!(enc_len, 256); let mut plain_out = [0u8; 256]; - let dec_len = rsa.rsa_direct(&enc, &mut plain_out, RSA::PUBLIC_DECRYPT, &mut rng).expect("Error with rsa_direct()"); + let dec_len = rsa.rsa_direct(&enc, &mut plain_out, RSA::PUBLIC_DECRYPT, &rng).expect("Error with rsa_direct()"); assert_eq!(dec_len, 256); assert_eq!(plain_out, plain); } @@ -128,20 +130,20 @@ fn test_rsa_direct() { #[test] #[cfg(random)] fn test_rsa_ssl() { - let mut rng = RNG::new().expect("Error creating RNG"); + let rng = Arc::new(RNG::new().expect("Error creating RNG")); let key_path = "../../../certs/client-key.der"; let der: Vec = fs::read(key_path).expect("Error reading key file"); let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); let msg: &[u8] = b"This is the string to be signed!"; let mut signature: [u8; 512] = [0; 512]; - let sig_len = rsa.ssl_sign(msg, &mut signature, &mut rng).expect("Error with ssl_sign()"); + let sig_len = rsa.ssl_sign(msg, &mut signature, &rng).expect("Error with ssl_sign()"); assert!(sig_len > 0 && sig_len <= 512); let key_path = "../../../certs/client-keyPub.der"; let der: Vec = fs::read(key_path).expect("Error reading key file"); let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); - rsa.set_rng(&mut rng).expect("Error with set_rng()"); + rsa.set_shared_rng(Arc::clone(&rng)).expect("Error with set_shared_rng()"); let signature = &signature[0..sig_len]; let mut verify_out: [u8; 512] = [0; 512]; let verify_out_size = rsa.ssl_verify(signature, &mut verify_out).expect("Error with ssl_verify()");