Merge pull request #10402 from holtrop-wolfssl/rust-crate-updates-2026-05-05

Rust wrapper: ensure memory safety for C RNG struct
This commit is contained in:
JacobBarthelmeh
2026-05-28 10:06:05 -06:00
committed by GitHub
30 changed files with 1542 additions and 531 deletions
+1 -1
View File
@@ -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"]
+1 -1
View File
@@ -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
+2
View File
@@ -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.
+3
View File
@@ -371,6 +371,9 @@ fn scan_cfg() -> Result<()> {
check_cfg(&binding, "wc_Dh_ffdhe6144_Get", "dh_ffdhe_6144");
check_cfg(&binding, "wc_Dh_ffdhe8192_Get", "dh_ffdhe_8192");
/* crypto callback */
check_cfg(&binding, "wc_CryptoCb_RegisterDevice", "wolf_crypto_cb");
/* ecc */
check_cfg(&binding, "wc_ecc_init", "ecc");
check_cfg(&binding, "wc_ecc_export_point_der_compressed", "ecc_comp_key");
+106 -5
View File
@@ -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>) -> 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<Self>,
associated_data: &[u8],
buffer: &mut [u8],
) -> Result<aead::Tag<Self>, aead::Error> {
let mut tag = aead::Tag::<Self>::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<Self>,
associated_data: &[u8],
buffer: &mut [u8],
tag: &aead::Tag<Self>,
) -> 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>) -> 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<Self>,
associated_data: &[u8],
buffer: &mut [u8],
) -> Result<aead::Tag<Self>, aead::Error> {
let mut tag = aead::Tag::<Self>::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<Self>,
associated_data: &[u8],
buffer: &mut [u8],
tag: &aead::Tag<Self>,
) -> 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)]
@@ -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<Self>) {
<$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<Self>) {
<$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
}
@@ -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 {
Self {
blake2: <$wc_ty>::new_with_key($digest_size, key.as_slice())
.expect("wolfCrypt BLAKE2 init failed"),
}
}
fn new_from_slice(key: &[u8]) -> Result<Self, digest::InvalidLength> {
if key.len() > <Self as digest::common::KeySizeUser>::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<Self>) {
<$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
}
@@ -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<RngHandle>,
}
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<Self, i32> {
pub fn generate(rng: &RNG) -> Result<Self, i32> {
let mut wc_key: MaybeUninit<sys::curve25519_key> = 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::rc::Rc<RNG>) -> 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.
+8 -8
View File
@@ -194,7 +194,7 @@ impl DH {
/// }
/// ```
#[cfg(all(dh_keygen, random))]
pub fn generate(rng: &mut RNG, modulus_size: i32) -> Result<Self, i32> {
pub fn generate(rng: &RNG, modulus_size: i32) -> Result<Self, i32> {
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<i32>) -> Result<Self, i32> {
pub fn generate_ex(rng: &RNG, modulus_size: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let mut wc_dhkey: MaybeUninit<sys::DhKey> = 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<Self, i32> {
pub fn new_from_pgq_with_check(p: &[u8], g: &[u8], q: &[u8], trusted: i32, rng: &RNG) -> Result<Self, i32> {
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<i32>) -> Result<Self, i32> {
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<i32>) -> Result<Self, i32> {
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)
};
@@ -159,7 +159,7 @@ impl Dilithium {
/// }
/// ```
#[cfg(all(dilithium_make_key, random))]
pub fn generate(level: u8, rng: &mut RNG) -> Result<Self, i32> {
pub fn generate(level: u8, rng: &RNG) -> Result<Self, i32> {
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<i32>,
) -> Result<Self, i32> {
@@ -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<usize, i32> {
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<usize, i32> {
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<usize, i32> {
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 {
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -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::<sys::ecc_key>() 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::<sys::ecc_key>() as u32,
)
};
@@ -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<Self, i32> {
pub fn generate(rng: &RNG) -> Result<Self, i32> {
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<i32>) -> Result<Self, i32> {
pub fn generate_ex(rng: &RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let mut ws_key: MaybeUninit<sys::ed25519_key> = 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 {
+3 -3
View File
@@ -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<Self, i32> {
pub fn generate(rng: &RNG) -> Result<Self, i32> {
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<i32>) -> Result<Self, i32> {
pub fn generate_ex(rng: &RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let mut ws_key: MaybeUninit<sys::ed448_key> = 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 {
@@ -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<sys::Hmac> = 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.
///
@@ -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,
}
@@ -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<T>(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"))]
+2 -2
View File
@@ -442,8 +442,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);
}
+5 -5
View File
@@ -123,7 +123,7 @@ impl MlKem {
/// }
/// ```
#[cfg(random)]
pub fn generate(key_type: i32, rng: &mut RNG) -> Result<Self, i32> {
pub fn generate(key_type: i32, rng: &RNG) -> Result<Self, i32> {
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<i32>,
) -> Result<Self, i32> {
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 {
+46 -32
View File
@@ -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 of a single RNG struct must implement
// their own locking.
/// 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::rc::Rc<RNG>),
}
impl RNG {
@@ -97,7 +121,7 @@ impl RNG {
return Err(rc);
}
}
let mut wc_rng: MaybeUninit<sys::WC_RNG> = 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<sys::WC_RNG> = 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<u8, i32> {
pub fn generate_byte(&self) -> Result<u8, i32> {
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<T: PrimInt>(&mut self, buf: &mut [T]) -> Result<(), i32> {
pub fn generate_block<T: PrimInt>(&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); }
}
}
+148 -98
View File
@@ -29,26 +29,26 @@ wolfSSL `RsaKey` object. It ensures proper initialization and deallocation.
```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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
let key_path = "../../../certs/client-keyPub.der";
let der: Vec<u8> = 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::rc::Rc::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<u8> = 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::rc::Rc::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<RngHandle>,
}
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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
/// let key_path = "../../../certs/client-keyPub.der";
/// let der: Vec<u8> = 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::rc::Rc::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<u8> = 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::rc::Rc::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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
/// let key_path = "../../../certs/client-keyPub.der";
/// let der: Vec<u8> = 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::rc::Rc::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<u8> = 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::rc::Rc::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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
/// let key_path = "../../../certs/client-keyPub.der";
/// let der: Vec<u8> = 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::rc::Rc::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<u8> = 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::rc::Rc::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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
/// let key_path = "../../../certs/client-keyPub.der";
/// let der: Vec<u8> = 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::rc::Rc::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<u8> = 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::rc::Rc::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<Self, i32> {
pub fn generate(size: i32, e: i32, rng: &RNG) -> Result<Self, i32> {
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<i32>) -> Result<Self, i32> {
pub fn generate_ex(size: i32, e: i32, rng: &RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let mut wc_rsakey: MaybeUninit<sys::RsaKey> = 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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
/// let key_path = "../../../certs/client-keyPub.der";
/// let der: Vec<u8> = 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::rc::Rc::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<u8> = 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::rc::Rc::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<usize, i32> {
pub fn public_encrypt(&mut self, din: &[u8], dout: &mut [u8], rng: &RNG) -> Result<usize, i32> {
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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
/// let key_path = "../../../certs/client-keyPub.der";
/// let der: Vec<u8> = 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::rc::Rc::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<u8> = 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::rc::Rc::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());
@@ -849,26 +869,26 @@ impl RSA {
/// # Example
///
/// ```rust
/// #[cfg(all(random, rsa_pss))]
/// #[cfg(all(random, rsa_pss, 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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
///
/// let key_path = "../../../certs/client-key.der";
/// let der: Vec<u8> = 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<u8> = 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::rc::Rc::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<usize, i32> {
pub fn pss_sign(&mut self, din: &[u8], dout: &mut [u8], hash_algo: u32, mgf: i32, rng: &RNG) -> Result<usize, i32> {
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);
@@ -912,26 +932,26 @@ impl RSA {
/// # Example
///
/// ```rust
/// #[cfg(all(random, rsa_pss, rsa_const_api))]
/// #[cfg(all(random, rsa_pss, rsa_const_api, 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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
///
/// let key_path = "../../../certs/client-key.der";
/// let der: Vec<u8> = 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<u8> = 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::rc::Rc::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()");
@@ -978,26 +998,26 @@ impl RSA {
/// # Example
///
/// ```rust
/// #[cfg(all(random, rsa_pss, rsa_const_api))]
/// #[cfg(all(random, rsa_pss, rsa_const_api, 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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
///
/// let key_path = "../../../certs/client-key.der";
/// let der: Vec<u8> = 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<u8> = 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::rc::Rc::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()");
@@ -1049,26 +1069,26 @@ impl RSA {
/// # Example
///
/// ```rust
/// #[cfg(all(random, rsa_pss, rsa_const_api))]
/// #[cfg(all(random, rsa_pss, rsa_const_api, 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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
///
/// let key_path = "../../../certs/client-key.der";
/// let der: Vec<u8> = 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<u8> = 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::rc::Rc::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<u8> = 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<usize, i32> {
pub fn rsa_direct(&mut self, din: &[u8], dout: &mut [u8], typ: i32, rng: &RNG) -> Result<usize, i32> {
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
///
@@ -1183,19 +1202,19 @@ impl RSA {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::rsa::RSA;
///
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let key_path = "../../../certs/client-keyPub.der";
/// let der: Vec<u8> = 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_rng(RNG::new().expect("Error creating RNG")).expect("Error with set_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_rng = RNG::new().expect("Error creating RNG");
/// let enc_len = rsa.public_encrypt(plain, &mut enc, &enc_rng).expect("Error with public_encrypt()");
/// assert!(enc_len > 0 && enc_len <= 512);
/// let key_path = "../../../certs/client-key.der";
/// let der: Vec<u8> = 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_rng(RNG::new().expect("Error creating RNG")).expect("Error with set_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, &mut rng.wc_rng)
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 `Rc<RNG>` 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::rc::Rc<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::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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
///
/// let key_path = "../../../certs/client-key.der";
/// let der: Vec<u8> = 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<u8> = 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::rc::Rc::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<usize, i32> {
pub fn ssl_sign(&mut self, din: &[u8], dout: &mut [u8], rng: &RNG) -> Result<usize, i32> {
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::rc::Rc::new(RNG::new().expect("Error creating RNG"));
///
/// let key_path = "../../../certs/client-key.der";
/// let der: Vec<u8> = 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<u8> = 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::rc::Rc::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()");
@@ -149,9 +149,9 @@ pub struct SigningKey<H: Hash, const N: usize> {
impl<H: Hash, const N: usize> SigningKey<H, N> {
/// Generate a fresh `N * 8`-bit RSA key with public exponent 65537.
#[cfg(rsa_keygen)]
pub fn generate(mut rng: RNG) -> Result<Self, i32> {
pub fn generate(rng: RNG) -> Result<Self, i32> {
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<H: Hash, const N: usize> SignerMut<Signature<N>> for SigningKey<H, N> {
sig.as_mut_ptr(), &mut sig_len,
&mut self.inner.wc_rsakey as *mut _ as *mut c_void,
size_of::<sys::RsaKey>() as u32,
&mut self.rng.wc_rng,
self.rng.wc_rng,
)
};
if rc != 0 || sig_len as usize != N {
@@ -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<Aes192Gcm> = 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<Aes192Ccm> = 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))]
@@ -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<D: Digest + BlockSizeUser + FixedOutputReset + Default>(
input: &[u8],
expected: &[u8],
expected_block_size: usize,
) {
assert_eq!(<D as Digest>::output_size(), expected.len());
assert_eq!(<D as BlockSizeUser>::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::<Blake2b512>(
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::<Blake2b384>(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::<Blake2b256>(b"abc", &expected, 128);
}
#[test]
#[cfg(blake2s)]
fn test_digest_blake2s_256() {
use wolfssl_wolfcrypt::blake2_digest::Blake2s256;
common::setup();
check_digest::<Blake2s256>(
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::<Blake2s192>(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::<Blake2s128>(b"abc", &expected, 64);
}
@@ -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<u8> = (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());
}
@@ -1,5 +1,7 @@
#![cfg(all(curve25519, random))]
#[cfg(curve25519_blinding)]
use std::rc::Rc;
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 = Rc::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(Rc::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(Rc::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 = Rc::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(Rc::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(Rc::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()");
@@ -4,9 +4,13 @@ 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::rc::Rc;
use wolfssl_wolfcrypt::ecc::*;
#[cfg(random)]
use wolfssl_wolfcrypt::random::RNG;
#[cfg(ecc_import)]
use wolfssl_wolfcrypt::sys;
#[test]
#[cfg(random)]
@@ -134,7 +138,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 +146,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 = Rc::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(Rc::clone(&rng)).expect("Error with set_shared_rng()");
ecc1.set_shared_rng(Rc::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);
@@ -290,6 +294,33 @@ fn test_ecc_import_unsigned() {
assert_eq!(valid, true);
}
#[test]
#[cfg(ecc_import)]
fn test_ecc_import_unsigned_short_slices() {
common::setup();
let curve_id = ECC::SECP256R1;
let qx = [0u8; 32];
let qy = [0u8; 32];
let d = [0u8; 32];
let empty: [u8; 0] = [];
let cases: [(&[u8], &[u8], &[u8]); 6] = [
(&qx[..31], &qy, &d ),
(&qx, &qy[..31], &d ),
(&qx, &qy, &d[..31] ),
(&empty, &qy, &d ),
(&qx, &empty, &d ),
(&qx, &qy, &empty ),
];
for (qx, qy, d) in cases {
match ECC::import_unsigned(qx, qy, d, curve_id, None, None) {
Ok(_) => panic!("import_unsigned() should fail with short slice"),
Err(rc) => assert_eq!(rc, sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG),
}
}
}
#[test]
#[cfg(random)]
fn test_ecc_make_pub() {
@@ -365,6 +396,38 @@ 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, empty, d, curve_name, None, None).is_err());
assert!(ECC::import_raw(qx, qy, empty, 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(empty, qy, d, ECC::SECP256R1, None, None).is_err());
assert!(ECC::import_raw_ex(qx, empty, d, 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();
@@ -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";
@@ -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()");
}
@@ -5,6 +5,8 @@ mod common;
#[cfg(any(all(sha256, random, rsa_pss), random, rsa_direct))]
use std::fs;
#[cfg(random)]
use std::rc::Rc;
#[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 = Rc::new(RNG::new().expect("Error creating RNG"));
let key_path = "../../../certs/client-keyPub.der";
let der: Vec<u8> = 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(Rc::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<u8> = 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(Rc::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 = Rc::new(RNG::new().expect("Error creating RNG"));
let key_path = "../../../certs/client-key.der";
let der: Vec<u8> = 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<u8> = 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(Rc::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<u8> = 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 = Rc::new(RNG::new().expect("Error creating RNG"));
let key_path = "../../../certs/client-key.der";
let der: Vec<u8> = 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<u8> = 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(Rc::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()");