/* * 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 */ /*! This module provides a Rust wrapper for the wolfCrypt library's Secure Hash Algorithm (SHA) functionality. */ use crate::sys; use core::mem::MaybeUninit; /// Context for SHA-1 computation. #[cfg(sha)] pub struct SHA { wc_sha: sys::wc_Sha, } #[cfg(sha)] impl SHA { /// SHA-1 digest size in bytes. pub const DIGEST_SIZE: usize = sys::WC_SHA_DIGEST_SIZE as usize; /// Build a new SHA instance. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA; /// let sha = SHA::new().expect("Error with new()"); /// ``` pub fn new() -> Result { Self::new_ex(None, None) } /// Build a new SHA instance with optional heap and device ID. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA; /// let sha = SHA::new_ex(None, None).expect("Error with new_ex()"); /// ``` pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_sha: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha_ex(wc_sha.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_sha = unsafe { wc_sha.assume_init() }; let sha = SHA { wc_sha }; Ok(sha) } /// Reinitialize a SHA instance for a new hash calculation. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA; /// let mut sha = SHA::new().expect("Error with new()"); /// sha.init().expect("Error with init()"); /// ``` pub fn init(&mut self) -> Result<(), i32> { self.init_ex(None, None) } /// Reinitialize a SHA instance for a new hash calculation with optional /// heap and device ID. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA; /// let mut sha = SHA::new().expect("Error with new()"); /// sha.init_ex(None, None).expect("Error with init_ex()"); /// ``` pub fn init_ex(&mut self, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result<(), i32> { let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha_ex(&mut self.wc_sha, heap, dev_id) }; if rc != 0 { return Err(rc); } Ok(()) } /// Update the SHA calculation by feeding in more input data. /// /// # Parameters /// /// * `data`: Input data. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA; /// let mut sha = SHA::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// ``` pub fn update(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_ShaUpdate(&mut self.wc_sha, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Finalize the SHA calculation and retrieve the calculated hash. /// /// # Parameters /// /// * `hash`: Buffer in which to store the calculated hash. The length /// should be SHA::DIGEST_SIZE. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA; /// let mut sha = SHA::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// let mut hash = [0u8; SHA::DIGEST_SIZE]; /// sha.finalize(&mut hash).expect("Error with finalize()"); /// ``` pub fn finalize(&mut self, hash: &mut [u8]) -> Result<(), i32> { if hash.len() != Self::DIGEST_SIZE { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); } let rc = unsafe { sys::wc_ShaFinal(&mut self.wc_sha, hash.as_mut_ptr()) }; if rc != 0 { return Err(rc); } Ok(()) } } #[cfg(sha)] impl SHA { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_sha); } } } #[cfg(sha)] impl Drop for SHA { /// Safely free the underlying wolfSSL SHA context. /// /// This calls the `wc_ShaFree` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the SHA /// struct goes out of scope, automatically cleaning up resources and /// preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_ShaFree(&mut self.wc_sha); } self.zeroize(); } } /// Context for SHA-224 (SHA-2) computation. #[cfg(sha224)] pub struct SHA224 { wc_sha224: sys::wc_Sha224, } #[cfg(sha224)] impl SHA224 { /// SHA-224 digest size in bytes. pub const DIGEST_SIZE: usize = sys::WC_SHA224_DIGEST_SIZE as usize; /// Build a new SHA224 instance. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA224 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA224; /// let sha = SHA224::new().expect("Error with new()"); /// ``` pub fn new() -> Result { Self::new_ex(None, None) } /// Build a new SHA224 instance with optional heap and device ID. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA224 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA224; /// let sha = SHA224::new_ex(None, None).expect("Error with new_ex()"); /// ``` pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_sha224: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha224_ex(wc_sha224.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_sha224 = unsafe { wc_sha224.assume_init() }; let sha224 = SHA224 { wc_sha224 }; Ok(sha224) } /// Reinitialize a SHA224 instance for a new hash calculation. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA224; /// let mut sha = SHA224::new().expect("Error with new()"); /// sha.init().expect("Error with init()"); /// ``` pub fn init(&mut self) -> Result<(), i32> { self.init_ex(None, None) } /// Reinitialize a SHA224 instance for a new hash calculation with optional /// heap and device ID. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA224; /// let mut sha = SHA224::new().expect("Error with new()"); /// sha.init_ex(None, None).expect("Error with init_ex()"); /// ``` pub fn init_ex(&mut self, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result<(), i32> { let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha224_ex(&mut self.wc_sha224, heap, dev_id) }; if rc != 0 { return Err(rc); } Ok(()) } /// Update the SHA-224 calculation by feeding in more input data. /// /// # Parameters /// /// * `data`: Input data. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA224; /// let mut sha = SHA224::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// ``` pub fn update(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_Sha224Update(&mut self.wc_sha224, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Finalize the SHA-224 calculation and retrieve the calculated hash. /// /// # Parameters /// /// * `hash`: Buffer in which to store the calculated hash. The length /// should be SHA224::DIGEST_SIZE. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA224; /// let mut sha = SHA224::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// let mut hash = [0u8; SHA224::DIGEST_SIZE]; /// sha.finalize(&mut hash).expect("Error with finalize()"); /// ``` pub fn finalize(&mut self, hash: &mut [u8]) -> Result<(), i32> { if hash.len() != Self::DIGEST_SIZE { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); } let rc = unsafe { sys::wc_Sha224Final(&mut self.wc_sha224, hash.as_mut_ptr()) }; if rc != 0 { return Err(rc); } Ok(()) } } #[cfg(sha224)] impl SHA224 { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_sha224); } } } #[cfg(sha224)] impl Drop for SHA224 { /// Safely free the underlying wolfSSL SHA224 context. /// /// This calls the `wc_Sha224Free` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the /// SHA224 struct goes out of scope, automatically cleaning up resources /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha224Free(&mut self.wc_sha224); } self.zeroize(); } } /// Context for SHA-256 (SHA-2) computation. #[cfg(sha256)] pub struct SHA256 { wc_sha256: sys::wc_Sha256, } #[cfg(sha256)] impl SHA256 { /// SHA-256 digest size in bytes. pub const DIGEST_SIZE: usize = sys::WC_SHA256_DIGEST_SIZE as usize; /// Build a new SHA256 instance. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA256 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA256; /// let sha = SHA256::new().expect("Error with new()"); /// ``` pub fn new() -> Result { Self::new_ex(None, None) } /// Build a new SHA256 instance with optional heap and device ID. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA256 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA256; /// let sha = SHA256::new_ex(None, None).expect("Error with new_ex()"); /// ``` pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_sha256: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha256_ex(wc_sha256.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_sha256 = unsafe { wc_sha256.assume_init() }; let sha256 = SHA256 { wc_sha256 }; Ok(sha256) } /// Reinitialize a SHA256 instance for a new hash calculation. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA256; /// let mut sha = SHA256::new().expect("Error with new()"); /// sha.init().expect("Error with init()"); /// ``` pub fn init(&mut self) -> Result<(), i32> { self.init_ex(None, None) } /// Reinitialize a SHA256 instance for a new hash calculation with optional /// heap and device ID. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA256; /// let mut sha = SHA256::new().expect("Error with new()"); /// sha.init_ex(None, None).expect("Error with init_ex()"); /// ``` pub fn init_ex(&mut self, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result<(), i32> { let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha256_ex(&mut self.wc_sha256, heap, dev_id) }; if rc != 0 { return Err(rc); } Ok(()) } /// Update the SHA-256 calculation by feeding in more input data. /// /// # Parameters /// /// * `data`: Input data. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA256; /// let mut sha = SHA256::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// ``` pub fn update(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_Sha256Update(&mut self.wc_sha256, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Finalize the SHA-256 calculation and retrieve the calculated hash. /// /// # Parameters /// /// * `hash`: Buffer in which to store the calculated hash. The length /// should be SHA256::DIGEST_SIZE. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA256; /// let mut sha = SHA256::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// let mut hash = [0u8; SHA256::DIGEST_SIZE]; /// sha.finalize(&mut hash).expect("Error with finalize()"); /// ``` pub fn finalize(&mut self, hash: &mut [u8]) -> Result<(), i32> { if hash.len() != Self::DIGEST_SIZE { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); } let rc = unsafe { sys::wc_Sha256Final(&mut self.wc_sha256, hash.as_mut_ptr()) }; if rc != 0 { return Err(rc); } Ok(()) } } #[cfg(sha256)] impl SHA256 { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_sha256); } } } #[cfg(sha256)] impl Drop for SHA256 { /// Safely free the underlying wolfSSL SHA256 context. /// /// This calls the `wc_Sha256Free` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the /// SHA256 struct goes out of scope, automatically cleaning up resources /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha256Free(&mut self.wc_sha256); } self.zeroize(); } } /// Context for SHA-384 (SHA-2) computation. #[cfg(sha384)] pub struct SHA384 { wc_sha384: sys::wc_Sha384, } #[cfg(sha384)] impl SHA384 { /// SHA-384 digest size in bytes. pub const DIGEST_SIZE: usize = sys::WC_SHA384_DIGEST_SIZE as usize; /// Build a new SHA384 instance. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA384 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA384; /// let sha = SHA384::new().expect("Error with new()"); /// ``` pub fn new() -> Result { Self::new_ex(None, None) } /// Build a new SHA384 instance with optional heap and device ID. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA384 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA384; /// let sha = SHA384::new_ex(None, None).expect("Error with new_ex()"); /// ``` pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_sha384: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha384_ex(wc_sha384.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_sha384 = unsafe { wc_sha384.assume_init() }; let sha384 = SHA384 { wc_sha384 }; Ok(sha384) } /// Reinitialize a SHA384 instance for a new hash calculation. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA384; /// let mut sha = SHA384::new().expect("Error with new()"); /// sha.init().expect("Error with init()"); /// ``` pub fn init(&mut self) -> Result<(), i32> { self.init_ex(None, None) } /// Reinitialize a SHA384 instance for a new hash calculation with optional /// heap and device ID. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA384; /// let mut sha = SHA384::new().expect("Error with new()"); /// sha.init_ex(None, None).expect("Error with init_ex()"); /// ``` pub fn init_ex(&mut self, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result<(), i32> { let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha384_ex(&mut self.wc_sha384, heap, dev_id) }; if rc != 0 { return Err(rc); } Ok(()) } /// Update the SHA-384 calculation by feeding in more input data. /// /// # Parameters /// /// * `data`: Input data. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA384; /// let mut sha = SHA384::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// ``` pub fn update(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_Sha384Update(&mut self.wc_sha384, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Finalize the SHA-384 calculation and retrieve the calculated hash. /// /// # Parameters /// /// * `hash`: Buffer in which to store the calculated hash. The length /// should be SHA384::DIGEST_SIZE. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA384; /// let mut sha = SHA384::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// let mut hash = [0u8; SHA384::DIGEST_SIZE]; /// sha.finalize(&mut hash).expect("Error with finalize()"); /// ``` pub fn finalize(&mut self, hash: &mut [u8]) -> Result<(), i32> { if hash.len() != Self::DIGEST_SIZE { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); } let rc = unsafe { sys::wc_Sha384Final(&mut self.wc_sha384, hash.as_mut_ptr()) }; if rc != 0 { return Err(rc); } Ok(()) } } #[cfg(sha384)] impl SHA384 { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_sha384); } } } #[cfg(sha384)] impl Drop for SHA384 { /// Safely free the underlying wolfSSL SHA384 context. /// /// This calls the `wc_Sha384Free` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the /// SHA384 struct goes out of scope, automatically cleaning up resources /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha384Free(&mut self.wc_sha384); } self.zeroize(); } } /// Context for SHA-512 (SHA-2) computation. #[cfg(sha512)] pub struct SHA512 { wc_sha512: sys::wc_Sha512, } #[cfg(sha512)] impl SHA512 { /// SHA-512 digest size in bytes. pub const DIGEST_SIZE: usize = sys::WC_SHA512_DIGEST_SIZE as usize; /// Build a new SHA512 instance. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA512 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA512; /// let sha = SHA512::new().expect("Error with new()"); /// ``` pub fn new() -> Result { Self::new_ex(None, None) } /// Build a new SHA512 instance with optional heap and device ID. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA512 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA512; /// let sha = SHA512::new_ex(None, None).expect("Error with new_ex()"); /// ``` pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_sha512: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha512_ex(wc_sha512.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_sha512 = unsafe { wc_sha512.assume_init() }; let sha512 = SHA512 { wc_sha512 }; Ok(sha512) } /// Reinitialize a SHA512 instance for a new hash calculation. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA512; /// let mut sha = SHA512::new().expect("Error with new()"); /// sha.init().expect("Error with init()"); /// ``` pub fn init(&mut self) -> Result<(), i32> { self.init_ex(None, None) } /// Reinitialize a SHA512 instance for a new hash calculation with optional /// heap and device ID. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA512; /// let mut sha = SHA512::new().expect("Error with new()"); /// sha.init_ex(None, None).expect("Error with init_ex()"); /// ``` pub fn init_ex(&mut self, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result<(), i32> { let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha512_ex(&mut self.wc_sha512, heap, dev_id) }; if rc != 0 { return Err(rc); } Ok(()) } /// Update the SHA-512 calculation by feeding in more input data. /// /// # Parameters /// /// * `data`: Input data. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA512; /// let mut sha = SHA512::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// ``` pub fn update(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_Sha512Update(&mut self.wc_sha512, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Finalize the SHA-512 calculation and retrieve the calculated hash. /// /// # Parameters /// /// * `hash`: Buffer in which to store the calculated hash. The length /// should be SHA512::DIGEST_SIZE. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA512; /// let mut sha = SHA512::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// let mut hash = [0u8; SHA512::DIGEST_SIZE]; /// sha.finalize(&mut hash).expect("Error with finalize()"); /// ``` pub fn finalize(&mut self, hash: &mut [u8]) -> Result<(), i32> { if hash.len() != Self::DIGEST_SIZE { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); } let rc = unsafe { sys::wc_Sha512Final(&mut self.wc_sha512, hash.as_mut_ptr()) }; if rc != 0 { return Err(rc); } Ok(()) } } #[cfg(sha512)] impl SHA512 { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_sha512); } } } #[cfg(sha512)] impl Drop for SHA512 { /// Safely free the underlying wolfSSL SHA512 context. /// /// This calls the `wc_Sha512Free` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the /// SHA512 struct goes out of scope, automatically cleaning up resources /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha512Free(&mut self.wc_sha512); } self.zeroize(); } } /// Context for SHA3-224 computation. #[cfg(sha3)] pub struct SHA3_224 { wc_sha3: sys::wc_Sha3, } #[cfg(sha3)] impl SHA3_224 { /// SHA3-224 digest size in bytes. pub const DIGEST_SIZE: usize = sys::WC_SHA3_224_DIGEST_SIZE as usize; /// Build a new SHA3_224 instance. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA3_224 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_224; /// let sha = SHA3_224::new().expect("Error with new()"); /// ``` pub fn new() -> Result { Self::new_ex(None, None) } /// Build a new SHA3_224 instance with optional heap and device ID. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA3_224 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_224; /// let sha = SHA3_224::new_ex(None, None).expect("Error with new_ex()"); /// ``` pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_sha3: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha3_224(wc_sha3.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_sha3 = unsafe { wc_sha3.assume_init() }; let sha3_224 = SHA3_224 { wc_sha3 }; Ok(sha3_224) } /// Reinitialize a SHA3_224 instance for a new hash calculation. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_224; /// let mut sha = SHA3_224::new().expect("Error with new()"); /// sha.init().expect("Error with init()"); /// ``` pub fn init(&mut self) -> Result<(), i32> { self.init_ex(None, None) } /// Reinitialize a SHA3_224 instance for a new hash calculation with /// optional heap and device ID. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_224; /// let mut sha = SHA3_224::new().expect("Error with new()"); /// sha.init_ex(None, None).expect("Error with init_ex()"); /// ``` pub fn init_ex(&mut self, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result<(), i32> { let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha3_224(&mut self.wc_sha3, heap, dev_id) }; if rc != 0 { return Err(rc); } Ok(()) } /// Update the SHA3-224 calculation by feeding in more input data. /// /// # Parameters /// /// * `data`: Input data. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_224; /// let mut sha = SHA3_224::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// ``` pub fn update(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_Sha3_224_Update(&mut self.wc_sha3, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Finalize the SHA3-224 calculation and retrieve the calculated hash. /// /// # Parameters /// /// * `hash`: Buffer in which to store the calculated hash. The length /// should be SHA3_224::DIGEST_SIZE. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_224; /// let mut sha = SHA3_224::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// let mut hash = [0u8; SHA3_224::DIGEST_SIZE]; /// sha.finalize(&mut hash).expect("Error with finalize()"); /// ``` pub fn finalize(&mut self, hash: &mut [u8]) -> Result<(), i32> { if hash.len() != Self::DIGEST_SIZE { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); } let rc = unsafe { sys::wc_Sha3_224_Final(&mut self.wc_sha3, hash.as_mut_ptr()) }; if rc != 0 { return Err(rc); } Ok(()) } } #[cfg(sha3)] impl SHA3_224 { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_sha3); } } } #[cfg(sha3)] impl Drop for SHA3_224 { /// Safely free the underlying wolfSSL SHA3_224 context. /// /// This calls the `wc_Sha3_224_Free` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the /// SHA3_224 struct goes out of scope, automatically cleaning up resources /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha3_224_Free(&mut self.wc_sha3); } self.zeroize(); } } /// Context for SHA3-256 computation. #[cfg(sha3)] pub struct SHA3_256 { wc_sha3: sys::wc_Sha3, } #[cfg(sha3)] impl SHA3_256 { /// SHA3-256 digest size in bytes. pub const DIGEST_SIZE: usize = sys::WC_SHA3_256_DIGEST_SIZE as usize; /// Build a new SHA3_256 instance. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA3_256 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_256; /// let sha = SHA3_256::new().expect("Error with new()"); /// ``` pub fn new() -> Result { Self::new_ex(None, None) } /// Build a new SHA3_256 instance with optional heap and device ID. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA3_256 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_256; /// let sha = SHA3_256::new_ex(None, None).expect("Error with new_ex()"); /// ``` pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_sha3: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha3_256(wc_sha3.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_sha3 = unsafe { wc_sha3.assume_init() }; let sha3_256 = SHA3_256 { wc_sha3 }; Ok(sha3_256) } /// Reinitialize a SHA3_256 instance for a new hash calculation. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_256; /// let mut sha = SHA3_256::new().expect("Error with new()"); /// sha.init().expect("Error with init()"); /// ``` pub fn init(&mut self) -> Result<(), i32> { self.init_ex(None, None) } /// Reinitialize a SHA3_256 instance for a new hash calculation with /// optional heap and device ID. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_256; /// let mut sha = SHA3_256::new().expect("Error with new()"); /// sha.init_ex(None, None).expect("Error with init_ex()"); /// ``` pub fn init_ex(&mut self, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result<(), i32> { let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha3_256(&mut self.wc_sha3, heap, dev_id) }; if rc != 0 { return Err(rc); } Ok(()) } /// Update the SHA3-256 calculation by feeding in more input data. /// /// # Parameters /// /// * `data`: Input data. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_256; /// let mut sha = SHA3_256::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// ``` pub fn update(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_Sha3_256_Update(&mut self.wc_sha3, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Finalize the SHA3-256 calculation and retrieve the calculated hash. /// /// # Parameters /// /// * `hash`: Buffer in which to store the calculated hash. The length /// should be SHA3_256::DIGEST_SIZE. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_256; /// let mut sha = SHA3_256::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// let mut hash = [0u8; SHA3_256::DIGEST_SIZE]; /// sha.finalize(&mut hash).expect("Error with finalize()"); /// ``` pub fn finalize(&mut self, hash: &mut [u8]) -> Result<(), i32> { if hash.len() != Self::DIGEST_SIZE { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); } let rc = unsafe { sys::wc_Sha3_256_Final(&mut self.wc_sha3, hash.as_mut_ptr()) }; if rc != 0 { return Err(rc); } Ok(()) } } #[cfg(sha3)] impl SHA3_256 { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_sha3); } } } #[cfg(sha3)] impl Drop for SHA3_256 { /// Safely free the underlying wolfSSL SHA3_256 context. /// /// This calls the `wc_Sha3_256_Free` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the /// SHA3_256 struct goes out of scope, automatically cleaning up resources /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha3_256_Free(&mut self.wc_sha3); } self.zeroize(); } } /// Context for SHA3-384 computation. #[cfg(sha3)] pub struct SHA3_384 { wc_sha3: sys::wc_Sha3, } #[cfg(sha3)] impl SHA3_384 { /// SHA3-384 digest size in bytes. pub const DIGEST_SIZE: usize = sys::WC_SHA3_384_DIGEST_SIZE as usize; /// Build a new SHA3_384 instance. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA3_384 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_384; /// let sha = SHA3_384::new().expect("Error with new()"); /// ``` pub fn new() -> Result { Self::new_ex(None, None) } /// Build a new SHA3_384 instance with optional heap and device ID. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA3_384 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_384; /// let sha = SHA3_384::new_ex(None, None).expect("Error with new_ex()"); /// ``` pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_sha3: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha3_384(wc_sha3.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_sha3 = unsafe { wc_sha3.assume_init() }; let sha3_384 = SHA3_384 { wc_sha3 }; Ok(sha3_384) } /// Reinitialize a SHA3_384 instance for a new hash calculation. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_384; /// let mut sha = SHA3_384::new().expect("Error with new()"); /// sha.init().expect("Error with init()"); /// ``` pub fn init(&mut self) -> Result<(), i32> { self.init_ex(None, None) } /// Reinitialize a SHA3_384 instance for a new hash calculation with /// optional heap and device ID. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_384; /// let mut sha = SHA3_384::new().expect("Error with new()"); /// sha.init_ex(None, None).expect("Error with init_ex()"); /// ``` pub fn init_ex(&mut self, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result<(), i32> { let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha3_384(&mut self.wc_sha3, heap, dev_id) }; if rc != 0 { return Err(rc); } Ok(()) } /// Update the SHA3-384 calculation by feeding in more input data. /// /// # Parameters /// /// * `data`: Input data. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_384; /// let mut sha = SHA3_384::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// ``` pub fn update(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_Sha3_384_Update(&mut self.wc_sha3, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Finalize the SHA3-384 calculation and retrieve the calculated hash. /// /// # Parameters /// /// * `hash`: Buffer in which to store the calculated hash. The length /// should be SHA3_384::DIGEST_SIZE. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_384; /// let mut sha = SHA3_384::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// let mut hash = [0u8; SHA3_384::DIGEST_SIZE]; /// sha.finalize(&mut hash).expect("Error with finalize()"); /// ``` pub fn finalize(&mut self, hash: &mut [u8]) -> Result<(), i32> { if hash.len() != Self::DIGEST_SIZE { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); } let rc = unsafe { sys::wc_Sha3_384_Final(&mut self.wc_sha3, hash.as_mut_ptr()) }; if rc != 0 { return Err(rc); } Ok(()) } } #[cfg(sha3)] impl SHA3_384 { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_sha3); } } } #[cfg(sha3)] impl Drop for SHA3_384 { /// Safely free the underlying wolfSSL SHA3_384 context. /// /// This calls the `wc_Sha3_384_Free` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the /// SHA3_384 struct goes out of scope, automatically cleaning up resources /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha3_384_Free(&mut self.wc_sha3); } self.zeroize(); } } /// Context for SHA3-512 computation. #[cfg(sha3)] pub struct SHA3_512 { wc_sha3: sys::wc_Sha3, } #[cfg(sha3)] impl SHA3_512 { /// SHA3-512 digest size in bytes. pub const DIGEST_SIZE: usize = sys::WC_SHA3_512_DIGEST_SIZE as usize; /// Build a new SHA3_512 instance. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA3_512 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_512; /// let sha = SHA3_512::new().expect("Error with new()"); /// ``` pub fn new() -> Result { Self::new_ex(None, None) } /// Build a new SHA3_512 instance with optional heap and device ID. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(sha) containing the SHA3_512 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_512; /// let sha = SHA3_512::new_ex(None, None).expect("Error with new_ex()"); /// ``` pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_sha3: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha3_512(wc_sha3.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_sha3 = unsafe { wc_sha3.assume_init() }; let sha3_512 = SHA3_512 { wc_sha3 }; Ok(sha3_512) } /// Reinitialize a SHA3_512 instance for a new hash calculation. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_512; /// let mut sha = SHA3_512::new().expect("Error with new()"); /// sha.init().expect("Error with init()"); /// ``` pub fn init(&mut self) -> Result<(), i32> { self.init_ex(None, None) } /// Reinitialize a SHA3_512 instance for a new hash calculation with /// optional heap and device ID. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_512; /// let mut sha = SHA3_512::new().expect("Error with new()"); /// sha.init_ex(None, None).expect("Error with init_ex()"); /// ``` pub fn init_ex(&mut self, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result<(), i32> { let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitSha3_512(&mut self.wc_sha3, heap, dev_id) }; if rc != 0 { return Err(rc); } Ok(()) } /// Update the SHA3-512 calculation by feeding in more input data. /// /// # Parameters /// /// * `data`: Input data. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_512; /// let mut sha = SHA3_512::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// ``` pub fn update(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_Sha3_512_Update(&mut self.wc_sha3, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Finalize the SHA3-512 calculation and retrieve the calculated hash. /// /// # Parameters /// /// * `hash`: Buffer in which to store the calculated hash. The length /// should be SHA3_512::DIGEST_SIZE. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHA3_512; /// let mut sha = SHA3_512::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// let mut hash = [0u8; SHA3_512::DIGEST_SIZE]; /// sha.finalize(&mut hash).expect("Error with finalize()"); /// ``` pub fn finalize(&mut self, hash: &mut [u8]) -> Result<(), i32> { if hash.len() != Self::DIGEST_SIZE { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); } let rc = unsafe { sys::wc_Sha3_512_Final(&mut self.wc_sha3, hash.as_mut_ptr()) }; if rc != 0 { return Err(rc); } Ok(()) } } #[cfg(sha3)] impl SHA3_512 { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_sha3); } } } #[cfg(sha3)] impl Drop for SHA3_512 { /// Safely free the underlying wolfSSL SHA3_512 context. /// /// This calls the `wc_Sha3_512_Free` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the /// SHA3_512 struct goes out of scope, automatically cleaning up resources /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha3_512_Free(&mut self.wc_sha3); } self.zeroize(); } } /// Context for SHAKE128 (SHA-3) computation. #[cfg(shake128)] pub struct SHAKE128 { wc_shake: sys::wc_Shake, } #[cfg(shake128)] impl SHAKE128 { /// Squeeze block size. pub const SQUEEZE_BLOCK_SIZE: usize = sys::WC_SHA3_128_BLOCK_SIZE as usize; /// Build a new SHAKE128 instance. /// /// # Returns /// /// Returns either Ok(sha) containing the SHAKE128 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE128; /// let sha = SHAKE128::new().expect("Error with new()"); /// ``` pub fn new() -> Result { Self::new_ex(None, None) } /// Build a new SHAKE128 instance with optional heap and device ID. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(sha) containing the SHAKE128 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE128; /// let sha = SHAKE128::new_ex(None, None).expect("Error with new_ex()"); /// ``` pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_shake: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitShake128(wc_shake.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_shake = unsafe { wc_shake.assume_init() }; let shake128 = SHAKE128 { wc_shake }; Ok(shake128) } /// Reinitialize a SHAKE128 instance for a new hash calculation. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE128; /// let mut sha = SHAKE128::new().expect("Error with new()"); /// sha.init().expect("Error with init()"); /// ``` pub fn init(&mut self) -> Result<(), i32> { self.init_ex(None, None) } /// Reinitialize a SHAKE128 instance for a new hash calculation with /// optional heap and device ID. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE128; /// let mut sha = SHAKE128::new().expect("Error with new()"); /// sha.init_ex(None, None).expect("Error with init_ex()"); /// ``` pub fn init_ex(&mut self, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result<(), i32> { let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitShake128(&mut self.wc_shake, heap, dev_id) }; if rc != 0 { return Err(rc); } Ok(()) } /// Update the SHAKE128 calculation by feeding in more input data. /// /// # Parameters /// /// * `data`: Input data. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE128; /// let mut sha = SHAKE128::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// ``` pub fn update(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_Shake128_Update(&mut self.wc_shake, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Finalize the SHAKE128 calculation and retrieve the calculated hash. /// /// # Parameters /// /// * `hash`: Buffer in which to store the calculated hash. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE128; /// let mut sha = SHAKE128::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// let mut hash = [0u8; 32]; /// sha.finalize(&mut hash).expect("Error with finalize()"); /// ``` pub fn finalize(&mut self, hash: &mut [u8]) -> Result<(), i32> { let hash_size = crate::buffer_len_to_u32(hash.len())?; let rc = unsafe { sys::wc_Shake128_Final(&mut self.wc_shake, hash.as_mut_ptr(), hash_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Absorb the provided byte array. Cannot be called incrementally. /// /// # Parameters /// /// * `data`: Data buffer to absorb. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE128; /// let mut sha = SHAKE128::new().expect("Error with new()"); /// sha.absorb(b"input").expect("Error with absorb()"); /// ``` pub fn absorb(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_Shake128_Absorb(&mut self.wc_shake, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Squeeze out more blocks of data. /// /// This function can be called inrementally. /// /// # Parameters /// /// * `dout`: Output buffer. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE128; /// let mut sha = SHAKE128::new().expect("Error with new()"); /// sha.absorb(b"input").expect("Error with absorb()"); /// let mut buffer = [0u8; 2 * SHAKE128::SQUEEZE_BLOCK_SIZE]; /// sha.squeeze_blocks(&mut buffer).expect("Error with squeeze_blocks()"); /// ``` pub fn squeeze_blocks(&mut self, dout: &mut [u8]) -> Result<(), i32> { let dout_size = crate::buffer_len_to_u32(dout.len())?; if dout_size % (Self::SQUEEZE_BLOCK_SIZE as u32) != 0 { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); } let n_blocks = dout_size / (Self::SQUEEZE_BLOCK_SIZE as u32); let rc = unsafe { sys::wc_Shake128_SqueezeBlocks(&mut self.wc_shake, dout.as_mut_ptr(), n_blocks) }; if rc != 0 { return Err(rc); } Ok(()) } } #[cfg(shake128)] impl SHAKE128 { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_shake); } } } #[cfg(shake128)] impl Drop for SHAKE128 { /// Safely free the underlying wolfSSL SHAKE128 context. /// /// This calls the `wc_Shake128_Free` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the /// SHAKE128 struct goes out of scope, automatically cleaning up resources /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Shake128_Free(&mut self.wc_shake); } self.zeroize(); } } /// Context for SHAKE256 (SHA-3) computation. #[cfg(shake256)] pub struct SHAKE256 { wc_shake: sys::wc_Shake, } #[cfg(shake256)] impl SHAKE256 { /// Squeeze block size. pub const SQUEEZE_BLOCK_SIZE: usize = sys::WC_SHA3_256_BLOCK_SIZE as usize; /// Build a new SHAKE256 instance. /// /// # Returns /// /// Returns either Ok(sha) containing the SHAKE256 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE256; /// let sha = SHAKE256::new().expect("Error with new()"); /// ``` pub fn new() -> Result { Self::new_ex(None, None) } /// Build a new SHAKE256 instance with optional heap and device ID. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(sha) containing the SHAKE256 struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE256; /// let sha = SHAKE256::new_ex(None, None).expect("Error with new_ex()"); /// ``` pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_shake: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitShake256(wc_shake.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_shake = unsafe { wc_shake.assume_init() }; let shake256 = SHAKE256 { wc_shake }; Ok(shake256) } /// Reinitialize a SHAKE256 instance for a new hash calculation. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE256; /// let mut sha = SHAKE256::new().expect("Error with new()"); /// sha.init().expect("Error with init()"); /// ``` pub fn init(&mut self) -> Result<(), i32> { self.init_ex(None, None) } /// Reinitialize a SHAKE256 instance for a new hash calculation with /// optional heap and device ID. /// /// This does not need to be called after `new()`, but should be called /// after a hash calculation to prepare for a new calculation. /// /// # Parameters /// /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE256; /// let mut sha = SHAKE256::new().expect("Error with new()"); /// sha.init_ex(None, None).expect("Error with init_ex()"); /// ``` pub fn init_ex(&mut self, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result<(), i32> { let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitShake256(&mut self.wc_shake, heap, dev_id) }; if rc != 0 { return Err(rc); } Ok(()) } /// Update the SHAKE256 calculation by feeding in more input data. /// /// # Parameters /// /// * `data`: Input data. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE256; /// let mut sha = SHAKE256::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// ``` pub fn update(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_Shake256_Update(&mut self.wc_shake, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Finalize the SHAKE256 calculation and retrieve the calculated hash. /// /// # Parameters /// /// * `hash`: Buffer in which to store the calculated hash. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE256; /// let mut sha = SHAKE256::new().expect("Error with new()"); /// sha.update(b"input").expect("Error with update()"); /// let mut hash = [0u8; 32]; /// sha.finalize(&mut hash).expect("Error with finalize()"); /// ``` pub fn finalize(&mut self, hash: &mut [u8]) -> Result<(), i32> { let hash_size = crate::buffer_len_to_u32(hash.len())?; let rc = unsafe { sys::wc_Shake256_Final(&mut self.wc_shake, hash.as_mut_ptr(), hash_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Absorb the provided byte array. Cannot be called incrementally. /// /// # Parameters /// /// * `data`: Data buffer to absorb. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE256; /// let mut sha = SHAKE256::new().expect("Error with new()"); /// sha.absorb(b"input").expect("Error with absorb()"); /// ``` pub fn absorb(&mut self, data: &[u8]) -> Result<(), i32> { let data_size = crate::buffer_len_to_u32(data.len())?; let rc = unsafe { sys::wc_Shake256_Absorb(&mut self.wc_shake, data.as_ptr(), data_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Squeeze out more blocks of data. /// /// This function can be called inrementally. /// /// # Parameters /// /// * `dout`: Output buffer. /// /// # Returns /// /// Returns either Ok(()) on success or Err(e) containing the wolfSSL /// library error code value. /// /// # Example /// /// ```rust /// use wolfssl_wolfcrypt::sha::SHAKE256; /// let mut sha = SHAKE256::new().expect("Error with new()"); /// sha.absorb(b"input").expect("Error with absorb()"); /// let mut buffer = [0u8; 2 * SHAKE256::SQUEEZE_BLOCK_SIZE]; /// sha.squeeze_blocks(&mut buffer).expect("Error with squeeze_blocks()"); /// ``` pub fn squeeze_blocks(&mut self, dout: &mut [u8]) -> Result<(), i32> { let dout_size = crate::buffer_len_to_u32(dout.len())?; if dout_size % (Self::SQUEEZE_BLOCK_SIZE as u32) != 0 { return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E); } let n_blocks = dout_size / (Self::SQUEEZE_BLOCK_SIZE as u32); let rc = unsafe { sys::wc_Shake256_SqueezeBlocks(&mut self.wc_shake, dout.as_mut_ptr(), n_blocks) }; if rc != 0 { return Err(rc); } Ok(()) } } #[cfg(shake256)] impl SHAKE256 { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_shake); } } } #[cfg(shake256)] impl Drop for SHAKE256 { /// Safely free the underlying wolfSSL SHAKE256 context. /// /// This calls the `wc_Shake256_Free` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the /// SHAKE256 struct goes out of scope, automatically cleaning up resources /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Shake256_Free(&mut self.wc_shake); } self.zeroize(); } }