#[cfg(any(wolfssl_blake2b, wolfssl_blake2s))]
use crate::error::{check, len_as_u32, WolfCryptError};
#[cfg(any(wolfssl_blake2b, wolfssl_blake2s))]
use alloc::vec::Vec;
#[cfg(wolfssl_blake2b)]
pub struct Blake2b {
ctx: wolfcrypt_rs::WcBlake2b,
digest_size: u32,
}
#[cfg(wolfssl_blake2b)]
unsafe impl Send for Blake2b {}
#[cfg(wolfssl_blake2b)]
impl Drop for Blake2b {
fn drop(&mut self) {
use zeroize::Zeroize;
let bytes = unsafe {
core::slice::from_raw_parts_mut(
&mut self.ctx as *mut wolfcrypt_rs::WcBlake2b as *mut u8,
core::mem::size_of_val(&self.ctx),
)
};
bytes.zeroize();
}
}
#[cfg(wolfssl_blake2b)]
impl Blake2b {
pub const MAX_DIGEST_SIZE: usize = 64;
pub fn new(digest_size: usize) -> Result<Self, WolfCryptError> {
if digest_size == 0 || digest_size > Self::MAX_DIGEST_SIZE {
return Err(WolfCryptError::InvalidInput);
}
let mut ctx = wolfcrypt_rs::WcBlake2b::zeroed();
let rc = unsafe {
wolfcrypt_rs::wc_InitBlake2b(
&mut ctx as *mut wolfcrypt_rs::WcBlake2b,
digest_size as u32,
)
};
check(rc, "wc_InitBlake2b")?;
Ok(Self {
ctx,
digest_size: digest_size as u32,
})
}
pub fn new_keyed(key: &[u8], digest_size: usize) -> Result<Self, WolfCryptError> {
if digest_size == 0 || digest_size > Self::MAX_DIGEST_SIZE {
return Err(WolfCryptError::InvalidInput);
}
if key.is_empty() || key.len() > Self::MAX_DIGEST_SIZE {
return Err(WolfCryptError::InvalidInput);
}
let mut ctx = wolfcrypt_rs::WcBlake2b::zeroed();
let rc = unsafe {
wolfcrypt_rs::wc_InitBlake2b_WithKey(
&mut ctx as *mut wolfcrypt_rs::WcBlake2b,
digest_size as u32,
key.as_ptr(),
len_as_u32(key.len()),
)
};
check(rc, "wc_InitBlake2b_WithKey")?;
Ok(Self {
ctx,
digest_size: digest_size as u32,
})
}
pub fn update(&mut self, data: &[u8]) -> Result<(), WolfCryptError> {
if data.is_empty() {
return Ok(());
}
let rc = unsafe {
wolfcrypt_rs::wc_Blake2bUpdate(
&mut self.ctx as *mut wolfcrypt_rs::WcBlake2b,
data.as_ptr(),
len_as_u32(data.len()),
)
};
check(rc, "wc_Blake2bUpdate")
}
pub fn finalize(mut self) -> Result<Vec<u8>, WolfCryptError> {
let mut out = alloc::vec![0u8; self.digest_size as usize];
let rc = unsafe {
wolfcrypt_rs::wc_Blake2bFinal(
&mut self.ctx as *mut wolfcrypt_rs::WcBlake2b,
out.as_mut_ptr(),
self.digest_size,
)
};
check(rc, "wc_Blake2bFinal")?;
Ok(out)
}
}
#[cfg(wolfssl_blake2s)]
pub struct Blake2s {
ctx: wolfcrypt_rs::WcBlake2s,
digest_size: u32,
}
#[cfg(wolfssl_blake2s)]
unsafe impl Send for Blake2s {}
#[cfg(wolfssl_blake2s)]
impl Drop for Blake2s {
fn drop(&mut self) {
use zeroize::Zeroize;
let bytes = unsafe {
core::slice::from_raw_parts_mut(
&mut self.ctx as *mut wolfcrypt_rs::WcBlake2s as *mut u8,
core::mem::size_of_val(&self.ctx),
)
};
bytes.zeroize();
}
}
#[cfg(wolfssl_blake2s)]
impl Blake2s {
pub const MAX_DIGEST_SIZE: usize = 32;
pub fn new(digest_size: usize) -> Result<Self, WolfCryptError> {
if digest_size == 0 || digest_size > Self::MAX_DIGEST_SIZE {
return Err(WolfCryptError::InvalidInput);
}
let mut ctx = wolfcrypt_rs::WcBlake2s::zeroed();
let rc = unsafe {
wolfcrypt_rs::wc_InitBlake2s(
&mut ctx as *mut wolfcrypt_rs::WcBlake2s,
digest_size as u32,
)
};
check(rc, "wc_InitBlake2s")?;
Ok(Self {
ctx,
digest_size: digest_size as u32,
})
}
pub fn new_keyed(key: &[u8], digest_size: usize) -> Result<Self, WolfCryptError> {
if digest_size == 0 || digest_size > Self::MAX_DIGEST_SIZE {
return Err(WolfCryptError::InvalidInput);
}
if key.is_empty() || key.len() > Self::MAX_DIGEST_SIZE {
return Err(WolfCryptError::InvalidInput);
}
let mut ctx = wolfcrypt_rs::WcBlake2s::zeroed();
let rc = unsafe {
wolfcrypt_rs::wc_InitBlake2s_WithKey(
&mut ctx as *mut wolfcrypt_rs::WcBlake2s,
digest_size as u32,
key.as_ptr(),
len_as_u32(key.len()),
)
};
check(rc, "wc_InitBlake2s_WithKey")?;
Ok(Self {
ctx,
digest_size: digest_size as u32,
})
}
pub fn update(&mut self, data: &[u8]) -> Result<(), WolfCryptError> {
if data.is_empty() {
return Ok(());
}
let rc = unsafe {
wolfcrypt_rs::wc_Blake2sUpdate(
&mut self.ctx as *mut wolfcrypt_rs::WcBlake2s,
data.as_ptr(),
len_as_u32(data.len()),
)
};
check(rc, "wc_Blake2sUpdate")
}
pub fn finalize(mut self) -> Result<Vec<u8>, WolfCryptError> {
let mut out = alloc::vec![0u8; self.digest_size as usize];
let rc = unsafe {
wolfcrypt_rs::wc_Blake2sFinal(
&mut self.ctx as *mut wolfcrypt_rs::WcBlake2s,
out.as_mut_ptr(),
self.digest_size,
)
};
check(rc, "wc_Blake2sFinal")?;
Ok(out)
}
}