Skip to content
Open
2 changes: 1 addition & 1 deletion wrapper/rust/wolfssl-wolfcrypt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
2 changes: 1 addition & 1 deletion wrapper/rust/wolfssl-wolfcrypt/Makefile
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 2 additions & 0 deletions wrapper/rust/wolfssl-wolfcrypt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
111 changes: 106 additions & 5 deletions wrapper/rust/wolfssl-wolfcrypt/src/aes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -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)]
Expand Down
169 changes: 169 additions & 0 deletions wrapper/rust/wolfssl-wolfcrypt/src/blake2_digest.rs
Original file line number Diff line number Diff line change
@@ -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
}
Loading
Loading