Files
wolfssl/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs
T
2026-04-14 20:50:08 -04:00

3927 lines
129 KiB
Rust

/*
* 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 Advanced
Encryption Standard (AES) functionality.
*/
#![cfg(aes)]
use crate::sys;
use core::mem::{size_of_val, MaybeUninit};
#[cfg(feature = "aead")]
use aead::{AeadCore, AeadInPlace, KeyInit, KeySizeUser};
#[cfg(feature = "aead")]
use aead::generic_array::typenum::{U0, U12, U16, U32};
#[cfg(all(feature = "cipher", not(feature = "aead")))]
use cipher::typenum::consts::{U16, U32};
#[cfg(feature = "cipher")]
use cipher::typenum::consts::U24;
#[cfg(feature = "cipher")]
use cipher::{
BlockModeDecBackend, BlockModeDecClosure, BlockModeDecrypt,
BlockModeEncBackend, BlockModeEncClosure, BlockModeEncrypt,
IvSizeUser, KeyIvInit, ParBlocksSizeUser, StreamCipher, StreamCipherError,
};
#[cfg(aes_wc_block_size)]
pub const AES_BLOCK_SIZE: usize = sys::WC_AES_BLOCK_SIZE as usize;
#[cfg(not(aes_wc_block_size))]
pub const AES_BLOCK_SIZE: usize = sys::AES_BLOCK_SIZE as usize;
/// AES Cipher Block Chaining (CBC) mode.
///
/// # Example
/// ```rust
/// #[cfg(aes_cbc)]
/// {
/// use wolfssl_wolfcrypt::aes::CBC;
/// let mut cbc = CBC::new().expect("Failed to create CBC");
/// let key: &[u8; 16] = b"0123456789abcdef";
/// let iv: &[u8; 16] = b"1234567890abcdef";
/// let msg: [u8; 16] = [
/// 0x6e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
/// 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
/// ];
/// let expected_cipher: [u8; 16] = [
/// 0x95, 0x94, 0x92, 0x57, 0x5f, 0x42, 0x81, 0x53,
/// 0x2c, 0xcc, 0x9d, 0x46, 0x77, 0xa2, 0x33, 0xcb
/// ];
/// cbc.init_encrypt(key, iv).expect("Error with init_encrypt()");
/// let mut cipher: [u8; 16] = [0; 16];
/// cbc.encrypt(&msg, &mut cipher).expect("Error with encrypt()");
/// assert_eq!(&cipher, &expected_cipher);
/// let mut plain_out = [0; 16];
/// cbc.init_decrypt(key, iv).expect("Error with init_decrypt()");
/// cbc.decrypt(&cipher, &mut plain_out).expect("Error with decrypt()");
/// assert_eq!(&plain_out, &msg);
/// }
/// ```
#[cfg(aes_cbc)]
pub struct CBC {
ws_aes: sys::Aes,
}
#[cfg(aes_cbc)]
impl CBC {
/// Create a new `CBC` instance.
///
/// # Returns
///
/// A Result which is Ok(CBC) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new() -> Result<Self, i32> {
Self::new_ex(None, None)
}
/// Create a new `CBC` 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
///
/// A Result which is Ok(CBC) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let ws_aes = new_ws_aes(heap, dev_id)?;
let cbc = CBC {ws_aes};
Ok(cbc)
}
fn init(&mut self, key: &[u8], iv: &[u8], dir: i32) -> Result<(), i32> {
let key_size = key.len() as u32;
if iv.len() != AES_BLOCK_SIZE {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesSetKey(&mut self.ws_aes, key.as_ptr(), key_size,
iv.as_ptr(), dir)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Initialize a CBC instance for encryption.
///
/// This method must be called before calling `encrypt()`.
///
/// # Parameters
///
/// * `key`: A slice containing the encryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
/// * `iv`: A slice containing the initialization vector (IV) to use. The
/// IV must be 16 bytes in length.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init_encrypt(&mut self, key: &[u8], iv: &[u8]) -> Result<(), i32> {
self.init(key, iv, sys::AES_ENCRYPTION as i32)
}
/// Initialize a CBC instance for decryption.
///
/// This method must be called before calling `decrypt()`.
///
/// # Parameters
///
/// * `key`: A slice containing the decryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
/// * `iv`: A slice containing the initialization vector (IV) to use. The
/// IV must be 16 bytes in length.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init_decrypt(&mut self, key: &[u8], iv: &[u8]) -> Result<(), i32> {
self.init(key, iv, sys::AES_DECRYPTION as i32)
}
/// Encrypt data.
///
/// The `init_encrypt()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to encrypt. The size of the data must be a multiple of
/// 16 bytes.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesCbcEncrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt data.
///
/// The `init_decrypt()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to decrypt. The size of the data must be a multiple of
/// 16 bytes.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the data must match that of the `din` slice.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesCbcDecrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
}
#[cfg(aes_cbc)]
impl Drop for CBC {
/// Safely free the wolfSSL resources.
fn drop(&mut self) {
unsafe { sys::wc_AesFree(&mut self.ws_aes); }
}
}
/// AES Counter with CBC-MAC (CCM) mode.
///
/// # Example
/// ```rust
/// #[cfg(aes_ccm)]
/// {
/// use wolfssl_wolfcrypt::aes::CCM;
/// let key: [u8; 16] = [
/// 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
/// 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
/// ];
/// let nonce: [u8; 13] = [
/// 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xa0,
/// 0xa1, 0xa2, 0xa3, 0xa4, 0xa5 ];
/// let plaintext: [u8; 23] = [
/// 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
/// 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
/// 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e
/// ];
/// let auth_data: [u8; 8] = [
/// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
/// ];
/// let expected_ciphertext: [u8; 23] = [
/// 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
/// 0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
/// 0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84
/// ];
/// let expected_auth_tag: [u8; 8] = [
/// 0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0
/// ];
///
/// let mut ccm = CCM::new().expect("Failed to create CCM");
/// ccm.init(&key).expect("Error with init()");
/// let mut auth_tag_out: [u8; 8] = [0; 8];
/// let mut cipher_out: [u8; 23] = [0; 23];
/// ccm.encrypt(&plaintext, &mut cipher_out,
/// &nonce, &auth_data, &mut auth_tag_out).expect("Error with encrypt()");
/// assert_eq!(cipher_out, expected_ciphertext);
/// assert_eq!(auth_tag_out, expected_auth_tag);
/// ccm.init(&key).expect("Error with init()");
/// let mut plain_out: [u8; 23] = [0; 23];
/// ccm.decrypt(&cipher_out, &mut plain_out,
/// &nonce, &auth_data, &auth_tag_out).expect("Error with decrypt()");
/// assert_eq!(plain_out, plaintext);
/// }
/// ```
#[cfg(aes_ccm)]
pub struct CCM {
ws_aes: sys::Aes,
}
#[cfg(aes_ccm)]
impl CCM {
/// Create a new `CCM` instance.
///
/// # Returns
///
/// A Result which is Ok(CCM) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new() -> Result<Self, i32> {
Self::new_ex(None, None)
}
/// Create a new `CCM` 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
///
/// A Result which is Ok(CCM) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let ws_aes = new_ws_aes(heap, dev_id)?;
let ccm = CCM {ws_aes};
Ok(ccm)
}
/// Initialize a CCM instance for encryption or decryption.
///
/// This method must be called before calling `encrypt()` or `decrypt()`.
///
/// # Parameters
///
/// * `key`: A slice containing the encryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init(&mut self, key: &[u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
let rc = unsafe {
sys::wc_AesCcmSetKey(&mut self.ws_aes, key.as_ptr(), key_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Encrypt data.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `nonce`: Nonce (number used once).
/// * `auth`: Authentication data input.
/// * `auth_tag`: Buffer in which to store the authentication tag.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt<I,O,N,A>(&mut self, din: &[I], dout: &mut [O], nonce: &[N], auth: &[A], auth_tag: &mut [A]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
let nonce_ptr = nonce.as_ptr() as *const u8;
let nonce_size = size_of_val(nonce) as u32;
let auth_ptr = auth.as_ptr() as *const u8;
let auth_size = size_of_val(auth) as u32;
let auth_tag_ptr = auth_tag.as_mut_ptr() as *mut u8;
let auth_tag_size = size_of_val(auth_tag) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesCcmEncrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size,
nonce_ptr, nonce_size, auth_tag_ptr, auth_tag_size,
auth_ptr, auth_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt data.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to decrypt.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `nonce`: Nonce (number used once).
/// * `auth`: Authentication data input.
/// * `auth_tag`: Authentication tag input to verify.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt<I,O,N,A>(&mut self, din: &[I], dout: &mut [O], nonce: &[N], auth: &[A], auth_tag: &[A]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
let nonce_ptr = nonce.as_ptr() as *const u8;
let nonce_size = size_of_val(nonce) as u32;
let auth_ptr = auth.as_ptr() as *const u8;
let auth_size = size_of_val(auth) as u32;
let auth_tag_ptr = auth_tag.as_ptr() as *const u8;
let auth_tag_size = size_of_val(auth_tag) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesCcmDecrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size,
nonce_ptr, nonce_size, auth_tag_ptr, auth_tag_size,
auth_ptr, auth_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
}
#[cfg(aes_ccm)]
impl Drop for CCM {
/// Safely free the wolfSSL resources.
fn drop(&mut self) {
unsafe { sys::wc_AesFree(&mut self.ws_aes); }
}
}
// ---------------------------------------------------------------------------
// AES-CCM aead trait implementations
// ---------------------------------------------------------------------------
/// Encrypt `buffer` in-place using AES-CCM (12-byte nonce, 16-byte tag).
#[cfg(all(aes_ccm, feature = "aead"))]
fn ccm_encrypt_in_place(
key: &[u8],
nonce: &[u8],
aad: &[u8],
buffer: &mut [u8],
tag: &mut [u8],
) -> Result<(), aead::Error> {
let mut ccm = CCM::new().map_err(|_| aead::Error)?;
ccm.init(key).map_err(|_| aead::Error)?;
// wolfCrypt CCM supports in-place operation (out == in).
let buf_ptr = buffer.as_mut_ptr();
let in_ptr = buf_ptr as *const u8;
let rc = unsafe {
sys::wc_AesCcmEncrypt(
&mut ccm.ws_aes,
buf_ptr, in_ptr, buffer.len() as u32,
nonce.as_ptr(), nonce.len() as u32,
tag.as_mut_ptr(), tag.len() as u32,
aad.as_ptr(), aad.len() as u32,
)
};
if rc != 0 {
return Err(aead::Error);
}
Ok(())
}
/// Decrypt `buffer` in-place using AES-CCM and verify `tag`.
#[cfg(all(aes_ccm, feature = "aead"))]
fn ccm_decrypt_in_place(
key: &[u8],
nonce: &[u8],
aad: &[u8],
buffer: &mut [u8],
tag: &[u8],
) -> Result<(), aead::Error> {
let mut ccm = CCM::new().map_err(|_| aead::Error)?;
ccm.init(key).map_err(|_| aead::Error)?;
let buf_ptr = buffer.as_mut_ptr();
let in_ptr = buf_ptr as *const u8;
let rc = unsafe {
sys::wc_AesCcmDecrypt(
&mut ccm.ws_aes,
buf_ptr, in_ptr, buffer.len() as u32,
nonce.as_ptr(), nonce.len() as u32,
tag.as_ptr(), tag.len() as u32,
aad.as_ptr(), aad.len() as u32,
)
};
if rc != 0 {
return Err(aead::Error);
}
Ok(())
}
/// AES-128-CCM authenticated encryption (12-byte nonce, 16-byte tag).
#[cfg(all(aes_ccm, feature = "aead"))]
pub struct Aes128Ccm {
key: [u8; 16],
}
#[cfg(all(aes_ccm, feature = "aead"))]
impl KeySizeUser for Aes128Ccm {
type KeySize = U16;
}
#[cfg(all(aes_ccm, feature = "aead"))]
impl AeadCore for Aes128Ccm {
type NonceSize = U12;
type TagSize = U16;
type CiphertextOverhead = U0;
}
#[cfg(all(aes_ccm, feature = "aead"))]
impl KeyInit for Aes128Ccm {
fn new(key: &aead::Key<Self>) -> Self {
let mut k = [0u8; 16];
k.copy_from_slice(key.as_ref());
Aes128Ccm { key: k }
}
}
#[cfg(all(aes_ccm, feature = "aead"))]
impl AeadInPlace for Aes128Ccm {
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"))]
pub struct Aes256Ccm {
key: [u8; 32],
}
#[cfg(all(aes_ccm, feature = "aead"))]
impl KeySizeUser for Aes256Ccm {
type KeySize = U32;
}
#[cfg(all(aes_ccm, feature = "aead"))]
impl AeadCore for Aes256Ccm {
type NonceSize = U12;
type TagSize = U16;
type CiphertextOverhead = U0;
}
#[cfg(all(aes_ccm, feature = "aead"))]
impl KeyInit for Aes256Ccm {
fn new(key: &aead::Key<Self>) -> Self {
let mut k = [0u8; 32];
k.copy_from_slice(key.as_ref());
Aes256Ccm { key: k }
}
}
#[cfg(all(aes_ccm, feature = "aead"))]
impl AeadInPlace for Aes256Ccm {
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 Cipher FeedBack (CFB) mode.
///
/// # Example
/// ```rust
/// #[cfg(aes_cfb)]
/// {
/// use wolfssl_wolfcrypt::aes::CFB;
/// let mut cfb = CFB::new().expect("Failed to create CFB");
/// let key: [u8; 16] = [
/// 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,
/// 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c
/// ];
/// let iv: [u8; 16] = [
/// 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
/// 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
/// ];
/// let msg: [u8; 48] = [
/// 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,
/// 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,
/// 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,
/// 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51,
/// 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,
/// 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef
/// ];
/// let cipher: [u8; 48] = [
/// 0x3b,0x3f,0xd9,0x2e,0xb7,0x2d,0xad,0x20,
/// 0x33,0x34,0x49,0xf8,0xe8,0x3c,0xfb,0x4a,
/// 0xc8,0xa6,0x45,0x37,0xa0,0xb3,0xa9,0x3f,
/// 0xcd,0xe3,0xcd,0xad,0x9f,0x1c,0xe5,0x8b,
/// 0x26,0x75,0x1f,0x67,0xa3,0xcb,0xb1,0x40,
/// 0xb1,0x80,0x8c,0xf1,0x87,0xa4,0xf4,0xdf
/// ];
/// cfb.init(&key, &iv).expect("Error with init()");
/// let mut outbuf: [u8; 48] = [0; 48];
/// cfb.encrypt(&msg[0..32], &mut outbuf[0..32]).expect("Error with encrypt()");
/// cfb.encrypt(&msg[32..48], &mut outbuf[32..48]).expect("Error with encrypt()");
/// assert_eq!(outbuf, cipher);
/// cfb.init(&key, &iv).expect("Error with init()");
/// let mut plain: [u8; 48] = [0; 48];
/// #[cfg(aes_decrypt)]
/// {
/// cfb.decrypt(&outbuf, &mut plain).expect("Error with decrypt()");
/// assert_eq!(plain, msg);
/// }
/// }
/// ```
#[cfg(aes_cfb)]
pub struct CFB {
ws_aes: sys::Aes,
}
#[cfg(aes_cfb)]
impl CFB {
/// Create a new `CFB` instance.
///
/// # Returns
///
/// A Result which is Ok(CFB) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new() -> Result<Self, i32> {
Self::new_ex(None, None)
}
/// Create a new `CFB` 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
///
/// A Result which is Ok(CFB) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let ws_aes = new_ws_aes(heap, dev_id)?;
let cfb = CFB {ws_aes};
Ok(cfb)
}
/// Initialize a CFB instance for encryption or decryption.
///
/// This method must be called before calling `encrypt()`, `encrypt1()`,
/// `encrypt8()`, `decrypt()`, `decrypt1()`, or `decrypt8()`.
///
/// # Parameters
///
/// * `key`: A slice containing the encryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
/// * `iv`: A slice containing the initialization vector (IV) to use. The
/// IV must be 16 bytes in length.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init(&mut self, key: &[u8], iv: &[u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
if iv.len() != AES_BLOCK_SIZE {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesSetKey(&mut self.ws_aes, key.as_ptr(), key_size,
iv.as_ptr(), sys::AES_ENCRYPTION as i32)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Encrypt data in full-block CFB mode.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesCfbEncrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Encrypt data in 1-bit CFB mode.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt1<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesCfb1Encrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Encrypt data in 8-bit CFB mode.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt8<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesCfb8Encrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt data in full-block CFB mode.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to decrypt.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
#[cfg(aes_decrypt)]
pub fn decrypt<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesCfbDecrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt data in 1-bit CFB mode.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to decrypt.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
#[cfg(aes_decrypt)]
pub fn decrypt1<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesCfb1Decrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt data in 8-bit CFB mode.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to decrypt.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
#[cfg(aes_decrypt)]
pub fn decrypt8<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesCfb8Decrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
}
#[cfg(aes_cfb)]
impl Drop for CFB {
/// Safely free the wolfSSL resources.
fn drop(&mut self) {
unsafe { sys::wc_AesFree(&mut self.ws_aes); }
}
}
/// AES Counter (CTR) mode.
///
/// # Example
/// ```rust
/// #[cfg(aes_ctr)]
/// {
/// use wolfssl_wolfcrypt::aes::CTR;
/// let iv: [u8; 16] = [
/// 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
/// 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
/// ];
/// let msg: [u8; 64] = [
/// 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,
/// 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,
/// 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,
/// 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51,
/// 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,
/// 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef,
/// 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17,
/// 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10
/// ];
/// let key: [u8; 16] = [
/// 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,
/// 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c
/// ];
/// let cipher: [u8; 64] = [
/// 0x87,0x4d,0x61,0x91,0xb6,0x20,0xe3,0x26,
/// 0x1b,0xef,0x68,0x64,0x99,0x0d,0xb6,0xce,
/// 0x98,0x06,0xf6,0x6b,0x79,0x70,0xfd,0xff,
/// 0x86,0x17,0x18,0x7b,0xb9,0xff,0xfd,0xff,
/// 0x5a,0xe4,0xdf,0x3e,0xdb,0xd5,0xd3,0x5e,
/// 0x5b,0x4f,0x09,0x02,0x0d,0xb0,0x3e,0xab,
/// 0x1e,0x03,0x1d,0xda,0x2f,0xbe,0x03,0xd1,
/// 0x79,0x21,0x70,0xa0,0xf3,0x00,0x9c,0xee
/// ];
/// let mut ctr = CTR::new().expect("Failed to create CTR");
/// ctr.init(&key, &iv).expect("Error with init()");
/// let mut outbuf: [u8; 64] = [0; 64];
/// ctr.encrypt(&msg, &mut outbuf).expect("Error with encrypt()");
/// assert_eq!(outbuf, cipher);
/// ctr.init(&key, &iv).expect("Error with init()");
/// let mut plain: [u8; 64] = [0; 64];
/// ctr.decrypt(&outbuf, &mut plain).expect("Error with decrypt()");
/// assert_eq!(plain, msg);
/// }
/// ```
#[cfg(aes_ctr)]
pub struct CTR {
ws_aes: sys::Aes,
}
#[cfg(aes_ctr)]
impl CTR {
/// Create a new `CTR` instance.
///
/// # Returns
///
/// A Result which is Ok(CTR) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new() -> Result<Self, i32> {
Self::new_ex(None, None)
}
/// Create a new `CTR` 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
///
/// A Result which is Ok(CTR) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let ws_aes = new_ws_aes(heap, dev_id)?;
let ctr = CTR {ws_aes};
Ok(ctr)
}
/// Initialize a CTR instance for encryption or decryption.
///
/// This method must be called before calling `encrypt()` or `decrypt()`.
///
/// # Parameters
///
/// * `key`: A slice containing the encryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
/// * `iv`: A slice containing the initialization vector (IV) to use. The
/// IV must be 16 bytes in length.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init(&mut self, key: &[u8], iv: &[u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
if iv.len() != AES_BLOCK_SIZE {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesSetKeyDirect(&mut self.ws_aes, key.as_ptr(), key_size,
iv.as_ptr(), sys::AES_ENCRYPTION as i32)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
fn encrypt_decrypt<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesCtrEncrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Encrypt data.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
self.encrypt_decrypt(din, dout)
}
/// Decrypt data.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to decrypt.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
self.encrypt_decrypt(din, dout)
}
}
#[cfg(aes_ctr)]
impl Drop for CTR {
/// Safely free the wolfSSL resources.
fn drop(&mut self) {
unsafe { sys::wc_AesFree(&mut self.ws_aes); }
}
}
/// AES Encrypt-Then-Authenticate-Then-Translate (EAX) mode.
///
/// # Example
/// ```rust
/// #[cfg(aes_eax)]
/// {
/// use wolfssl_wolfcrypt::aes::EAX;
/// let key: [u8; 16] = [
/// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
/// 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
/// ];
/// let nonce: [u8; 16] = [
/// 0x3c, 0x8c, 0xc2, 0x97, 0x0a, 0x00, 0x8f, 0x75,
/// 0xcc, 0x5b, 0xea, 0xe2, 0x84, 0x72, 0x58, 0xc2
/// ];
/// let auth: &[u8] = &[];
/// let msg: [u8; 32] = [
/// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/// 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
/// 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
/// ];
/// let expected_cipher: [u8; 32] = [
/// 0x3c, 0x44, 0x1f, 0x32, 0xce, 0x07, 0x82, 0x23,
/// 0x64, 0xd7, 0xa2, 0x99, 0x0e, 0x50, 0xbb, 0x13,
/// 0xd7, 0xb0, 0x2a, 0x26, 0x96, 0x9e, 0x4a, 0x93,
/// 0x7e, 0x5e, 0x90, 0x73, 0xb0, 0xd9, 0xc9, 0x68
/// ];
/// let expected_auth_tag: [u8; 16] = [
/// 0xdb, 0x90, 0xbd, 0xb3, 0xda, 0x3d, 0x00, 0xaf,
/// 0xd0, 0xfc, 0x6a, 0x83, 0x55, 0x1d, 0xa9, 0x5e
/// ];
/// let mut cipher: [u8; 32] = [0; 32];
/// let mut auth_tag: [u8; 16] = [0; 16];
/// EAX::encrypt(&msg, &mut cipher, &key, &nonce, auth, &mut auth_tag).expect("Error with encrypt()");
/// assert_eq!(cipher, expected_cipher);
/// assert_eq!(auth_tag, expected_auth_tag);
/// let mut plain: [u8; 32] = [0; 32];
/// EAX::decrypt(&cipher, &mut plain, &key, &nonce, auth, &auth_tag).expect("Error with decrypt()");
/// assert_eq!(plain, msg);
/// }
/// ```
#[cfg(aes_eax)]
pub struct EAX {
}
#[cfg(aes_eax)]
impl EAX {
/// Encrypt data.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `key`: Encryption key to use. The key size must be 16, 24, or 32
/// bytes.
/// * `nonce`: Nonce (number used once).
/// * `auth`: Authentication data input.
/// * `auth_tag`: Buffer in which to store the authentication tag.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt<I,O>(din: &[I], dout: &mut [O], key: &[u8], nonce: &[u8],
auth: &[u8], auth_tag: &mut [u8]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
let key_size = key.len() as u32;
let nonce_size = nonce.len() as u32;
let auth_size = auth.len() as u32;
let auth_tag_size = auth_tag.len() as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesEaxEncryptAuth(key.as_ptr(), key_size, out_ptr,
in_ptr, in_size, nonce.as_ptr(), nonce_size,
auth_tag.as_mut_ptr(), auth_tag_size, auth.as_ptr(), auth_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt data.
///
/// # Parameters
///
/// * `din`: Data to decrypt.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `key`: Decryption key to use. The key size must be 16, 24, or 32
/// bytes.
/// * `nonce`: Nonce (number used once).
/// * `auth`: Authentication data input.
/// * `auth_tag`: Authentication tag input to verify.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt<I,O>(din: &[I], dout: &mut [O], key: &[u8], nonce: &[u8],
auth: &[u8], auth_tag: &[u8]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
let key_size = key.len() as u32;
let nonce_size = nonce.len() as u32;
let auth_size = auth.len() as u32;
let auth_tag_size = auth_tag.len() as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesEaxDecryptAuth(key.as_ptr(), key_size, out_ptr,
in_ptr, in_size, nonce.as_ptr(), nonce_size,
auth_tag.as_ptr(), auth_tag_size, auth.as_ptr(), auth_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
}
/// AES Electronic CodeBook (ECB) mode.
///
/// # Example
/// ```rust
/// #[cfg(aes_ecb)]
/// {
/// use wolfssl_wolfcrypt::aes::ECB;
/// let mut ecb = ECB::new().expect("Failed to create ECB");
/// let key_128: &[u8; 16] = b"0123456789abcdef";
/// let msg: [u8; 16] = [
/// 0x6e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
/// 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20
/// ];
/// let verify_ecb_128: [u8; 16] = [
/// 0xd0, 0xc9, 0xd9, 0xc9, 0x40, 0xe8, 0x97, 0xb6,
/// 0xc8, 0x8c, 0x33, 0x3b, 0xb5, 0x8f, 0x85, 0xd1
/// ];
/// ecb.init_encrypt(key_128).expect("Error with init_encrypt()");
/// let mut outbuf: [u8; 16] = [0; 16];
/// ecb.encrypt(&msg, &mut outbuf).expect("Error with encrypt()");
/// assert_eq!(&outbuf, &verify_ecb_128);
/// outbuf = [0; 16];
/// ecb.init_decrypt(key_128).expect("Error with init_decrypt()");
/// ecb.decrypt(&verify_ecb_128, &mut outbuf).expect("Error with decrypt()");
/// assert_eq!(&outbuf, &msg);
/// }
/// ```
#[cfg(aes_ecb)]
pub struct ECB {
ws_aes: sys::Aes,
}
#[cfg(aes_ecb)]
impl ECB {
/// Create a new `ECB` instance.
///
/// # Returns
///
/// A Result which is Ok(ECB) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new() -> Result<Self, i32> {
Self::new_ex(None, None)
}
/// Create a new `ECB` 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
///
/// A Result which is Ok(ECB) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let ws_aes = new_ws_aes(heap, dev_id)?;
let ecb = ECB {ws_aes};
Ok(ecb)
}
fn init(&mut self, key: &[u8], dir: i32) -> Result<(), i32> {
let key_size = key.len() as u32;
let rc = unsafe {
sys::wc_AesSetKey(&mut self.ws_aes, key.as_ptr(), key_size,
core::ptr::null(), dir)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Initialize a ECB instance for encryption.
///
/// This method must be called before calling `encrypt()`.
///
/// # Parameters
///
/// * `key`: A slice containing the encryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init_encrypt(&mut self, key: &[u8]) -> Result<(), i32> {
self.init(key, sys::AES_ENCRYPTION as i32)
}
/// Initialize a ECB instance for decryption.
///
/// This method must be called before calling `decrypt()`.
///
/// # Parameters
///
/// * `key`: A slice containing the decryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init_decrypt(&mut self, key: &[u8]) -> Result<(), i32> {
self.init(key, sys::AES_DECRYPTION as i32)
}
/// Encrypt data.
///
/// The `init_encrypt()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to encrypt. The size of the data must be a multiple of
/// 16 bytes.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesEcbEncrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt data.
///
/// The `init_decrypt()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to decrypt. The size of the data must be a multiple of
/// 16 bytes.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesEcbDecrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
}
#[cfg(aes_ecb)]
impl Drop for ECB {
/// Safely free the wolfSSL resources.
fn drop(&mut self) {
unsafe { sys::wc_AesFree(&mut self.ws_aes); }
}
}
/// AES Galois/Counter Mode (GCM) mode (one shot functionality).
///
/// This struct provides one-shot encryption and decryption functionality.
/// For streaming/chunking functionality, see the `GCMStream` struct instead.
///
/// # Example
/// ```rust
/// #[cfg(aes_gcm)]
/// {
/// use wolfssl_wolfcrypt::aes::GCM;
/// let key: [u8; 16] = [
/// 0x29, 0x8e, 0xfa, 0x1c, 0xcf, 0x29, 0xcf, 0x62,
/// 0xae, 0x68, 0x24, 0xbf, 0xc1, 0x95, 0x57, 0xfc
/// ];
/// let iv: [u8; 12] = [
/// 0x6f, 0x58, 0xa9, 0x3f, 0xe1, 0xd2, 0x07, 0xfa,
/// 0xe4, 0xed, 0x2f, 0x6d
/// ];
/// let plain: [u8; 32] = [
/// 0xcc, 0x38, 0xbc, 0xcd, 0x6b, 0xc5, 0x36, 0xad,
/// 0x91, 0x9b, 0x13, 0x95, 0xf5, 0xd6, 0x38, 0x01,
/// 0xf9, 0x9f, 0x80, 0x68, 0xd6, 0x5c, 0xa5, 0xac,
/// 0x63, 0x87, 0x2d, 0xaf, 0x16, 0xb9, 0x39, 0x01
/// ];
/// let auth: [u8; 16] = [
/// 0x02, 0x1f, 0xaf, 0xd2, 0x38, 0x46, 0x39, 0x73,
/// 0xff, 0xe8, 0x02, 0x56, 0xe5, 0xb1, 0xc6, 0xb1
/// ];
/// let expected_cipher: [u8; 32] = [
/// 0xdf, 0xce, 0x4e, 0x9c, 0xd2, 0x91, 0x10, 0x3d,
/// 0x7f, 0xe4, 0xe6, 0x33, 0x51, 0xd9, 0xe7, 0x9d,
/// 0x3d, 0xfd, 0x39, 0x1e, 0x32, 0x67, 0x10, 0x46,
/// 0x58, 0x21, 0x2d, 0xa9, 0x65, 0x21, 0xb7, 0xdb
/// ];
/// let expected_auth_tag: [u8; 16] = [
/// 0x54, 0x24, 0x65, 0xef, 0x59, 0x93, 0x16, 0xf7,
/// 0x3a, 0x7a, 0x56, 0x05, 0x09, 0xa2, 0xd9, 0xf2
/// ];
/// let mut gcm = GCM::new().expect("Failed to create GCM");
/// gcm.init(&key).expect("Error with init()");
/// let mut cipher: [u8; 32] = [0; 32];
/// let mut auth_tag: [u8; 16] = [0; 16];
/// gcm.encrypt(&plain, &mut cipher, &iv, &auth, &mut auth_tag).expect("Error with encrypt()");
/// assert_eq!(cipher, expected_cipher);
/// assert_eq!(auth_tag, expected_auth_tag);
/// let mut plain_out: [u8; 32] = [0; 32];
/// gcm.decrypt(&cipher, &mut plain_out, &iv, &auth, &auth_tag).expect("Error with decrypt()");
/// assert_eq!(plain_out, plain);
/// }
/// ```
#[cfg(aes_gcm)]
pub struct GCM {
ws_aes: sys::Aes,
}
#[cfg(aes_gcm)]
impl GCM {
/// Create a new `GCM` instance.
///
/// # Returns
///
/// A Result which is Ok(GCM) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new() -> Result<Self, i32> {
Self::new_ex(None, None)
}
/// Create a new `GCM` 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
///
/// A Result which is Ok(GCM) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let ws_aes = new_ws_aes(heap, dev_id)?;
let gcm = GCM {ws_aes};
Ok(gcm)
}
/// Initialize a GCM instance for encryption or decryption.
///
/// This method must be called before calling `encrypt()` or `decrypt()`.
///
/// # Parameters
///
/// * `key`: A slice containing the encryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init(&mut self, key: &[u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
let rc = unsafe {
sys::wc_AesGcmSetKey(&mut self.ws_aes, key.as_ptr(), key_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Encrypt data.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `iv`: Initialization vector to use for the encryption operation.
/// * `auth`: Authentication data input.
/// * `auth_tag`: Buffer in which to store the authentication tag.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt<I,O>(&mut self, din: &[I], dout: &mut [O], iv: &[u8],
auth: &[u8], auth_tag: &mut [u8]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
let iv_size = iv.len() as u32;
let auth_size = auth.len() as u32;
let auth_tag_size = auth_tag.len() as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesGcmEncrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size,
iv.as_ptr(), iv_size, auth_tag.as_mut_ptr(), auth_tag_size,
auth.as_ptr(), auth_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt data.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to decrypt.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `iv`: Initialization vector to use for the decryption operation.
/// * `auth`: Authentication data input.
/// * `auth_tag`: Authentication tag input to verify.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt<I,O>(&mut self, din: &[I], dout: &mut [O], iv: &[u8],
auth: &[u8], auth_tag: &[u8]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
let iv_size = iv.len() as u32;
let auth_size = auth.len() as u32;
let auth_tag_size = auth_tag.len() as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesGcmDecrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size,
iv.as_ptr(), iv_size, auth_tag.as_ptr(), auth_tag_size,
auth.as_ptr(), auth_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
}
#[cfg(aes_gcm)]
impl Drop for GCM {
/// Safely free the wolfSSL resources.
fn drop(&mut self) {
unsafe { sys::wc_AesFree(&mut self.ws_aes); }
}
}
// ---------------------------------------------------------------------------
// AES-GCM aead trait implementations
// ---------------------------------------------------------------------------
/// Encrypt `buffer` in-place using AES-GCM (12-byte nonce, 16-byte tag).
///
/// wolfCrypt's `wc_AesGcmEncrypt` supports in-place operation (out == in).
#[cfg(all(aes_gcm, feature = "aead"))]
fn gcm_encrypt_in_place(
key: &[u8],
nonce: &[u8],
aad: &[u8],
buffer: &mut [u8],
tag: &mut [u8],
) -> Result<(), aead::Error> {
let mut gcm = GCM::new().map_err(|_| aead::Error)?;
gcm.init(key).map_err(|_| aead::Error)?;
let buf_ptr = buffer.as_mut_ptr();
let in_ptr = buf_ptr as *const u8;
let rc = unsafe {
sys::wc_AesGcmEncrypt(
&mut gcm.ws_aes,
buf_ptr, in_ptr, buffer.len() as u32,
nonce.as_ptr(), nonce.len() as u32,
tag.as_mut_ptr(), tag.len() as u32,
aad.as_ptr(), aad.len() as u32,
)
};
if rc != 0 {
return Err(aead::Error);
}
Ok(())
}
/// Decrypt `buffer` in-place using AES-GCM and verify `tag`.
#[cfg(all(aes_gcm, feature = "aead"))]
fn gcm_decrypt_in_place(
key: &[u8],
nonce: &[u8],
aad: &[u8],
buffer: &mut [u8],
tag: &[u8],
) -> Result<(), aead::Error> {
let mut gcm = GCM::new().map_err(|_| aead::Error)?;
gcm.init(key).map_err(|_| aead::Error)?;
let buf_ptr = buffer.as_mut_ptr();
let in_ptr = buf_ptr as *const u8;
let rc = unsafe {
sys::wc_AesGcmDecrypt(
&mut gcm.ws_aes,
buf_ptr, in_ptr, buffer.len() as u32,
nonce.as_ptr(), nonce.len() as u32,
tag.as_ptr(), tag.len() as u32,
aad.as_ptr(), aad.len() as u32,
)
};
if rc != 0 {
return Err(aead::Error);
}
Ok(())
}
/// AES-128-GCM authenticated encryption (12-byte nonce, 16-byte tag).
#[cfg(all(aes_gcm, feature = "aead"))]
pub struct Aes128Gcm {
key: [u8; 16],
}
#[cfg(all(aes_gcm, feature = "aead"))]
impl KeySizeUser for Aes128Gcm {
type KeySize = U16;
}
#[cfg(all(aes_gcm, feature = "aead"))]
impl AeadCore for Aes128Gcm {
type NonceSize = U12;
type TagSize = U16;
type CiphertextOverhead = U0;
}
#[cfg(all(aes_gcm, feature = "aead"))]
impl KeyInit for Aes128Gcm {
fn new(key: &aead::Key<Self>) -> Self {
let mut k = [0u8; 16];
k.copy_from_slice(key.as_ref());
Aes128Gcm { key: k }
}
}
#[cfg(all(aes_gcm, feature = "aead"))]
impl AeadInPlace for Aes128Gcm {
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"))]
pub struct Aes256Gcm {
key: [u8; 32],
}
#[cfg(all(aes_gcm, feature = "aead"))]
impl KeySizeUser for Aes256Gcm {
type KeySize = U32;
}
#[cfg(all(aes_gcm, feature = "aead"))]
impl AeadCore for Aes256Gcm {
type NonceSize = U12;
type TagSize = U16;
type CiphertextOverhead = U0;
}
#[cfg(all(aes_gcm, feature = "aead"))]
impl KeyInit for Aes256Gcm {
fn new(key: &aead::Key<Self>) -> Self {
let mut k = [0u8; 32];
k.copy_from_slice(key.as_ref());
Aes256Gcm { key: k }
}
}
#[cfg(all(aes_gcm, feature = "aead"))]
impl AeadInPlace for Aes256Gcm {
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 Galois/Counter Mode (GCM) mode (streaming functionality).
///
/// This struct provides streaming/chunking encryption and decryption
/// functionality. For one-shot functionality, see the `GCM` struct instead.
///
/// # Example
/// ```rust
/// #[cfg(aes_gcm_stream)]
/// {
/// use wolfssl_wolfcrypt::aes::GCMStream;
/// let plain: [u8; 60] = [
/// 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
/// 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
/// 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
/// 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
/// 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
/// 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
/// 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
/// 0xba, 0x63, 0x7b, 0x39
/// ];
/// let auth: [u8; 20] = [
/// 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
/// 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
/// 0xab, 0xad, 0xda, 0xd2
/// ];
/// let key: [u8; 32] = [
/// 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
/// 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
/// 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
/// 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
/// ];
/// let iv: [u8; 12] = [
/// 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
/// 0xde, 0xca, 0xf8, 0x88
/// ];
/// let expected_cipher: [u8; 60] = [
/// 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
/// 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
/// 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
/// 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
/// 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
/// 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
/// 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
/// 0xbc, 0xc9, 0xf6, 0x62
/// ];
/// let expected_auth_tag: [u8; 16] = [
/// 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
/// 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b
/// ];
/// let mut gcmstream = GCMStream::new().expect("Failed to create GCMStream");
/// for chunk_size in 1..=auth.len() {
/// gcmstream.init(&key, &iv).expect("Error with init()");
/// let mut cipher: [u8; 60] = [0; 60];
/// let mut i = 0;
/// while i < auth.len() {
/// let mut end = i + chunk_size;
/// if end > auth.len() {
/// end = auth.len()
/// }
/// gcmstream.encrypt_update(&plain[0..0], &mut cipher[0..0], &auth[i..end]).expect("Error with encrypt_update()");
/// i += chunk_size;
/// }
/// i = 0;
/// while i < plain.len() {
/// let mut end = i + chunk_size;
/// if end > plain.len() {
/// end = plain.len()
/// }
/// gcmstream.encrypt_update(&plain[i..end], &mut cipher[i..end], &auth[0..0]).expect("Error with encrypt_update()");
/// i += chunk_size;
/// }
/// let mut auth_tag: [u8; 16] = [0; 16];
/// gcmstream.encrypt_final(&mut auth_tag).expect("Error with encrypt_final()");
/// assert_eq!(cipher, expected_cipher);
/// assert_eq!(auth_tag, expected_auth_tag);
/// }
/// }
/// ```
#[cfg(aes_gcm_stream)]
pub struct GCMStream {
ws_aes: sys::Aes,
}
#[cfg(aes_gcm_stream)]
impl GCMStream {
/// Create a new `GCMStream` instance.
///
/// # Returns
///
/// A Result which is Ok(GCMStream) on success or an Err containing the
/// wolfSSL library return code on failure.
pub fn new() -> Result<Self, i32> {
Self::new_ex(None, None)
}
/// Create a new `GCMStream` instance with heap and device ID.
///
/// # Parameters
///
/// * `heap`: Optional heap hint.
/// * `dev_id` Optional device ID to use with crypto callbacks or async hardware.
///
/// # Returns
///
/// A Result which is Ok(GCMStream) on success or an Err containing the
/// wolfSSL library return code on failure.
pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let ws_aes = new_ws_aes(heap, dev_id)?;
let gcmstream = GCMStream {ws_aes};
Ok(gcmstream)
}
/// Initialize a GCMStream instance for encryption or decryption.
///
/// This method must be called before calling `encrypt_update()`,
/// `encrypt_final()`, `decrypt_update()`, or `decrypt_final()`.
///
/// # Parameters
///
/// * `key`: A slice containing the encryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
/// * `iv`: A slice containing the initialization vector (IV) to use.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init(&mut self, key: &[u8], iv: &[u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
let iv_size = iv.len() as u32;
let rc = unsafe {
sys::wc_AesGcmInit(&mut self.ws_aes, key.as_ptr(), key_size,
iv.as_ptr(), iv_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Add a chunk of data to encrypt or authentication data.
///
/// All authentication data must be passed in to update before the
/// plaintext to encrypt. The last part of the authentication data can be
/// passed in with the same call as the first part of the plaintext data.
///
/// The `init()` method must be called before calling this method.
/// The `encrypt_final()` method must be called to finalize the encryption
/// operation and retrieve the calculated authentication tag.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `auth`: Authentication data input.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt_update<I,O>(&mut self, din: &[I], dout: &mut [O],
auth: &[u8]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
let auth_size = auth.len() as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesGcmEncryptUpdate(&mut self.ws_aes, out_ptr,
in_ptr, in_size, auth.as_ptr(), auth_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Finalize encryption.
///
/// The `init()` method must be called before calling this method.
/// The `encrypt_update()` method must be called one or more times before
/// calling this method to supply authentication data and plaintext input
/// for encryption.
///
/// # Parameters
///
/// * `auth_tag`: Buffer in which to store the authentication tag.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt_final(&mut self, auth_tag: &mut [u8]) -> Result<(), i32> {
let auth_tag_size = auth_tag.len() as u32;
let rc = unsafe {
sys::wc_AesGcmEncryptFinal(&mut self.ws_aes,
auth_tag.as_mut_ptr(), auth_tag_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Add a chunk of data to decrypt or authentication data.
///
/// All authentication data must be passed in to update before the
/// ciphertext to decrypt. The last part of the authentication data can be
/// passed in with the same call as the first part of the ciphertext data.
///
/// The `init()` method must be called before calling this method.
/// The `decrypt_final()` method must be called to finalize the decryption
/// operation and verify the authentication tag.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `auth`: Authentication data input.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt_update<I,O>(&mut self, din: &[I], dout: &mut [O],
auth: &[u8]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
let auth_size = auth.len() as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesGcmDecryptUpdate(&mut self.ws_aes, out_ptr,
in_ptr, in_size, auth.as_ptr(), auth_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Finalize decryption.
///
/// The `init()` method must be called before calling this method.
/// The `decrypt_update()` method must be called one or more times before
/// calling this method to supply authentication data and ciphertext input
/// for decryption.
///
/// # Parameters
///
/// * `auth_tag`: Authentication tag input to verify.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt_final(&mut self, auth_tag: &[u8]) -> Result<(), i32> {
let auth_tag_size = auth_tag.len() as u32;
let rc = unsafe {
sys::wc_AesGcmDecryptFinal(&mut self.ws_aes,
auth_tag.as_ptr(), auth_tag_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
}
#[cfg(aes_gcm_stream)]
impl Drop for GCMStream {
/// Safely free the wolfSSL resources.
fn drop(&mut self) {
unsafe { sys::wc_AesFree(&mut self.ws_aes); }
}
}
/// AES Output FeedBack (OFB) mode.
///
/// # Example
/// ```rust
/// #[cfg(aes_ofb)]
/// {
/// use wolfssl_wolfcrypt::aes::OFB;
/// let key: [u8; 32] = [
/// 0xc4,0xc7,0xfa,0xd6,0x53,0x5c,0xb8,0x71,
/// 0x4a,0x5c,0x40,0x77,0x9a,0x8b,0xa1,0xd2,
/// 0x53,0x3e,0x23,0xb4,0xb2,0x58,0x73,0x2a,
/// 0x5b,0x78,0x01,0xf4,0xe3,0x71,0xa7,0x94
/// ];
/// let iv: [u8; 16] = [
/// 0x5e,0xb9,0x33,0x13,0xb8,0x71,0xff,0x16,
/// 0xb9,0x8a,0x9b,0xcb,0x43,0x33,0x0d,0x6f
/// ];
/// let plain: [u8; 48] = [
/// 0x6d,0x0b,0xb0,0x79,0x63,0x84,0x71,0xe9,
/// 0x39,0xd4,0x53,0x14,0x86,0xc1,0x4c,0x25,
/// 0x9a,0xee,0xc6,0xf3,0xc0,0x0d,0xfd,0xd6,
/// 0xc0,0x50,0xa8,0xba,0xa8,0x20,0xdb,0x71,
/// 0xcc,0x12,0x2c,0x4e,0x0c,0x17,0x15,0xef,
/// 0x55,0xf3,0x99,0x5a,0x6b,0xf0,0x2a,0x4c
/// ];
/// let expected_cipher: [u8; 48] = [
/// 0x0f,0x54,0x61,0x71,0x59,0xd0,0x3f,0xfc,
/// 0x1b,0xfa,0xfb,0x60,0x29,0x30,0xd7,0x00,
/// 0xf4,0xa4,0xa8,0xe6,0xdd,0x93,0x94,0x46,
/// 0x64,0xd2,0x19,0xc4,0xc5,0x4d,0xde,0x1b,
/// 0x04,0x53,0xe1,0x73,0xf5,0x18,0x74,0xae,
/// 0xfd,0x64,0xa2,0xe1,0xe2,0x76,0x13,0xb0
/// ];
/// let mut ofb = OFB::new().expect("Failed to create OFB");
/// ofb.init(&key, &iv).expect("Error with init()");
/// let mut cipher: [u8; 48] = [0; 48];
/// ofb.encrypt(&plain, &mut cipher).expect("Error with encrypt()");
/// assert_eq!(cipher, expected_cipher);
/// ofb.init(&key, &iv).expect("Error with init()");
/// let mut plain_out: [u8; 48] = [0; 48];
/// #[cfg(aes_decrypt)]
/// {
/// ofb.decrypt(&cipher, &mut plain_out).expect("Error with decrypt()");
/// assert_eq!(plain_out, plain);
/// }
/// }
/// ```
#[cfg(aes_ofb)]
pub struct OFB {
ws_aes: sys::Aes,
}
#[cfg(aes_ofb)]
impl OFB {
/// Create a new `OFB` instance.
///
/// # Returns
///
/// A Result which is Ok(OFB) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new() -> Result<Self, i32> {
Self::new_ex(None, None)
}
/// Create a new `OFB` 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
///
/// A Result which is Ok(OFB) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let ws_aes = new_ws_aes(heap, dev_id)?;
let ofb = OFB {ws_aes};
Ok(ofb)
}
/// Initialize a OFB instance for encryption or decryption.
///
/// This method must be called before calling `encrypt()` or `decrypt()`.
///
/// # Parameters
///
/// * `key`: A slice containing the encryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
/// * `iv`: A slice containing the initialization vector (IV) to use. The
/// IV must be 16 bytes in length.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init(&mut self, key: &[u8], iv: &[u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
if iv.len() != AES_BLOCK_SIZE {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesSetKey(&mut self.ws_aes, key.as_ptr(),
key_size, iv.as_ptr(), sys::AES_ENCRYPTION as i32)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Encrypt data.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesOfbEncrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt data.
///
/// The `init()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to decrypt.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
#[cfg(aes_decrypt)]
pub fn decrypt<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesOfbDecrypt(&mut self.ws_aes, out_ptr, in_ptr, in_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
}
#[cfg(aes_ofb)]
impl Drop for OFB {
/// Safely free the wolfSSL resources.
fn drop(&mut self) {
unsafe { sys::wc_AesFree(&mut self.ws_aes); }
}
}
/// AES XEX-based Tweaked-Codebook Mode With Ciphertext Stealing (XTS) support
/// (one shot functionality).
///
/// This struct provides one-shot encryption and decryption functionality.
/// For streaming/chunking functionality, see the `XTSStream` struct instead.
///
/// # Example
/// ```rust
/// #[cfg(aes_xts)]
/// {
/// use wolfssl_wolfcrypt::aes::XTS;
/// let key: [u8; 32] = [
/// 0xa1, 0xb9, 0x0c, 0xba, 0x3f, 0x06, 0xac, 0x35,
/// 0x3b, 0x2c, 0x34, 0x38, 0x76, 0x08, 0x17, 0x62,
/// 0x09, 0x09, 0x23, 0x02, 0x6e, 0x91, 0x77, 0x18,
/// 0x15, 0xf2, 0x9d, 0xab, 0x01, 0x93, 0x2f, 0x2f
/// ];
/// let tweak: [u8; 16] = [
/// 0x4f, 0xae, 0xf7, 0x11, 0x7c, 0xda, 0x59, 0xc6,
/// 0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5
/// ];
/// let plain: [u8; 16] = [
/// 0xeb, 0xab, 0xce, 0x95, 0xb1, 0x4d, 0x3c, 0x8d,
/// 0x6f, 0xb3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1c
/// ];
/// let expected_cipher: [u8; 16] = [
/// 0x77, 0x8a, 0xe8, 0xb4, 0x3c, 0xb9, 0x8d, 0x5a,
/// 0x82, 0x50, 0x81, 0xd5, 0xbe, 0x47, 0x1c, 0x63
/// ];
/// let partial: [u8; 24] = [
/// 0xeb, 0xab, 0xce, 0x95, 0xb1, 0x4d, 0x3c, 0x8d,
/// 0x6f, 0xb3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1c,
/// 0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5
/// ];
/// let expected_partial_cipher: [u8; 24] = [
/// 0x2b, 0xf7, 0x2c, 0xf3, 0xeb, 0x85, 0xef, 0x7b,
/// 0x0b, 0x76, 0xa0, 0xaa, 0xf3, 0x3f, 0x25, 0x8b,
/// 0x77, 0x8a, 0xe8, 0xb4, 0x3c, 0xb9, 0x8d, 0x5a
/// ];
///
/// let mut xts = XTS::new().expect("Failed to create XTS");
/// xts.init_encrypt(&key).expect("Error with init_encrypt()");
/// let mut cipher: [u8; 16] = [0; 16];
/// xts.encrypt(&plain, &mut cipher, &tweak).expect("Error with encrypt()");
/// assert_eq!(cipher, expected_cipher);
/// xts.init_decrypt(&key).expect("Error with init_decrypt()");
/// let mut plain_out: [u8; 16] = [0; 16];
/// xts.decrypt(&cipher, &mut plain_out, &tweak).expect("Error with decrypt()");
/// assert_eq!(plain_out, plain);
///
/// xts.init_encrypt(&key).expect("Error with init_encrypt()");
/// let mut partial_cipher: [u8; 24] = [0; 24];
/// xts.encrypt(&partial, &mut partial_cipher, &tweak).expect("Error with encrypt()");
/// assert_eq!(partial_cipher, expected_partial_cipher);
/// xts.init_decrypt(&key).expect("Error with init_decrypt()");
/// let mut partial_out: [u8; 24] = [0; 24];
/// xts.decrypt(&partial_cipher, &mut partial_out, &tweak).expect("Error with decrypt()");
/// assert_eq!(partial_out, partial);
/// }
/// ```
#[cfg(aes_xts)]
pub struct XTS {
ws_xtsaes: sys::XtsAes,
}
#[cfg(aes_xts)]
impl XTS {
/// Create a new `XTS` instance.
///
/// # Returns
///
/// A Result which is Ok(XTS) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new() -> Result<Self, i32> {
Self::new_ex(None, None)
}
/// Create a new `XTS` 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
///
/// A Result which is Ok(XTS) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let ws_xtsaes = new_ws_xtsaes(heap, dev_id)?;
let xts = XTS {ws_xtsaes};
Ok(xts)
}
fn init(&mut self, key: &[u8], dir: i32) -> Result<(), i32> {
let key_size = key.len() as u32;
let rc = unsafe {
sys::wc_AesXtsSetKeyNoInit(&mut self.ws_xtsaes,
key.as_ptr(), key_size, dir)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Initialize a XTS instance for encryption.
///
/// This method must be called before calling any encryption methods.
///
/// # Parameters
///
/// * `key`: A slice containing the encryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init_encrypt(&mut self, key: &[u8]) -> Result<(), i32> {
self.init(key, sys::AES_ENCRYPTION as i32)
}
/// Initialize a XTS instance for decryption.
///
/// This method must be called before calling any decryption methods.
///
/// # Parameters
///
/// * `key`: A slice containing the decryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init_decrypt(&mut self, key: &[u8]) -> Result<(), i32> {
self.init(key, sys::AES_DECRYPTION as i32)
}
/// Encrypt data.
///
/// The `init_encrypt()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `tweak`: Tweak value to use for the encryption operation.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt<I,O>(&mut self, din: &[I], dout: &mut [O], tweak: &[u8]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
let tweak_size = tweak.len() as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesXtsEncrypt(&mut self.ws_xtsaes, out_ptr,
in_ptr, in_size, tweak.as_ptr(), tweak_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Encrypt a sector of data.
///
/// The `init_encrypt()` method must be called before calling this method.
///
/// This method is the same as `encrypt()` except that a sector number is
/// taken instead of a tweak buffer. Internally the sector number is
/// expanded into the tweak value to use.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `sector`: Sector number to use for encryption operation. This value
/// is expanded into a tweak value.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt_sector<I,O>(&mut self, din: &[I], dout: &mut [O], sector: u64) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesXtsEncryptSector(&mut self.ws_xtsaes, out_ptr,
in_ptr, in_size, sector)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Encrypt consecutive sectors of data.
///
/// The `init_encrypt()` method must be called before calling this method.
///
/// This method is the same as `encrypt_sector()` except that the sector
/// number is automatically incremented every `sector_size` bytes.
///
/// # Parameters
///
/// * `din`: Data to encrypt.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `sector`: Sector number to use for encryption operation. This value
/// is expanded into a tweak value.
/// * `sector_size`: Sector size. The `sector` value is internally
/// incremented every `sector_size` bytes.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt_consecutive_sectors<I,O>(&mut self, din: &[I], dout: &mut [O],
sector: u64, sector_size: u32) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesXtsEncryptConsecutiveSectors(&mut self.ws_xtsaes,
out_ptr, in_ptr, in_size, sector, sector_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt data.
///
/// The `init_decrypt()` method must be called before calling this method.
///
/// # Parameters
///
/// * `din`: Data to decrypt.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `tweak`: Tweak value to use for the decryption operation.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt<I,O>(&mut self, din: &[I], dout: &mut [O], tweak: &[u8]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
let tweak_size = tweak.len() as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesXtsDecrypt(&mut self.ws_xtsaes, out_ptr,
in_ptr, in_size, tweak.as_ptr(), tweak_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt a sector of data.
///
/// The `init_decrypt()` method must be called before calling this method.
///
/// This method is the same as `decrypt()` except that a sector number is
/// taken instead of a tweak buffer. Internally the sector number is
/// expanded into the tweak value to use.
///
/// # Parameters
///
/// * `din`: Data to decrypt.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `sector`: Sector number to use for decryption operation. This value
/// is expanded into a tweak value.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt_sector<I,O>(&mut self, din: &[I], dout: &mut [O], sector: u64) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesXtsDecryptSector(&mut self.ws_xtsaes, out_ptr,
in_ptr, in_size, sector)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt consecutive sectors of data.
///
/// The `init_decrypt()` method must be called before calling this method.
///
/// This method is the same as `decrypt_sector()` except that the sector
/// number is automatically incremented every `sector_size` bytes.
///
/// # Parameters
///
/// * `din`: Data to decrypt.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
/// * `sector`: Sector number to use for decryption operation. This value
/// is expanded into a tweak value.
/// * `sector_size`: Sector size. The `sector` value is internally
/// incremented every `sector_size` bytes.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt_consecutive_sectors<I,O>(&mut self, din: &[I], dout: &mut [O],
sector: u64, sector_size: u32) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_mut_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesXtsDecryptConsecutiveSectors(&mut self.ws_xtsaes,
out_ptr, in_ptr, in_size, sector, sector_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
}
#[cfg(aes_xts)]
impl Drop for XTS {
/// Safely free the wolfSSL resources.
fn drop(&mut self) {
unsafe { sys::wc_AesXtsFree(&mut self.ws_xtsaes); }
}
}
/// AES XEX-based Tweaked-Codebook Mode With Ciphertext Stealing (XTS) support
/// (streaming functionality).
///
/// This struct provides streaming/chunking encryption and decryption
/// functionality. For one-shot functionality, see the `XTS` struct instead.
///
/// # Example
/// ```rust
/// #[cfg(aes_xts_stream)]
/// {
/// use wolfssl_wolfcrypt::aes::XTSStream;
/// let keys: [u8; 32] = [
/// 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
/// 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
/// 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
/// 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
/// ];
/// let tweak: [u8; 16] = [
/// 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
/// 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
/// ];
/// let plain: [u8; 40] = [
/// 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
/// 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
/// 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
/// 0x20, 0xff, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
/// 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
/// ];
/// let expected_cipher: [u8; 40] = [
/// 0xA2, 0x07, 0x47, 0x76, 0x3F, 0xEC, 0x0C, 0x23,
/// 0x1B, 0xD0, 0xBD, 0x46, 0x9A, 0x27, 0x38, 0x12,
/// 0x95, 0x02, 0x3D, 0x5D, 0xC6, 0x94, 0x51, 0x36,
/// 0xA0, 0x85, 0xD2, 0x69, 0x6E, 0x87, 0x0A, 0xBF,
/// 0xB5, 0x5A, 0xDD, 0xCB, 0x80, 0xE0, 0xFC, 0xCD
/// ];
///
/// let mut xtsstream = XTSStream::new().expect("Failed to create XTSStream");
/// xtsstream.init_encrypt(&keys, &tweak).expect("Error with init_encrypt()");
/// let mut cipher: [u8; 40] = [0; 40];
/// xtsstream.encrypt_update(&plain[0..16], &mut cipher[0..16]).expect("Error with encrypt_update()");
/// xtsstream.encrypt_final(&plain[16..40], &mut cipher[16..40]).expect("Error with encrypt_final()");
/// assert_eq!(cipher, expected_cipher);
///
/// xtsstream.init_decrypt(&keys, &tweak).expect("Error with init_decrypt()");
/// let mut plain_out: [u8; 40] = [0; 40];
/// xtsstream.decrypt_update(&cipher[0..16], &mut plain_out[0..16]).expect("Error with decrypt_update()");
/// xtsstream.decrypt_final(&cipher[16..40], &mut plain_out[16..40]).expect("Error with decrypt_final()");
/// assert_eq!(plain_out, plain);
/// }
/// ```
#[cfg(aes_xts_stream)]
pub struct XTSStream {
ws_xtsaes: sys::XtsAes,
ws_xtsaesstreamdata: sys::XtsAesStreamData,
}
#[cfg(aes_xts_stream)]
impl XTSStream {
/// Create a new `XTSStream` instance.
///
/// # Returns
///
/// A Result which is Ok(XTSStream) on success or an Err containing the
/// wolfSSL library return code on failure.
pub fn new() -> Result<Self, i32> {
Self::new_ex(None, None)
}
/// Create a new `XTSStream` 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
///
/// A Result which is Ok(XTSStream) on success or an Err containing the
/// wolfSSL library return code on failure.
pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let ws_xtsaes = new_ws_xtsaes(heap, dev_id)?;
let ws_xtsaesstreamdata: MaybeUninit<sys::XtsAesStreamData> = MaybeUninit::zeroed();
let ws_xtsaesstreamdata = unsafe { ws_xtsaesstreamdata.assume_init() };
let xtsstream = XTSStream {ws_xtsaes, ws_xtsaesstreamdata};
Ok(xtsstream)
}
/// Initialize a XTSStream instance for encryption.
///
/// This method must be called before calling `encrypt_update()`.
///
/// # Parameters
///
/// * `key`: A slice containing the encryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
/// * `tweak`: Tweak value to use for the encryption operation.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init_encrypt(&mut self, key: &[u8], tweak: &[u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
let rc = unsafe {
sys::wc_AesXtsSetKeyNoInit(&mut self.ws_xtsaes,
key.as_ptr(), key_size, sys::AES_ENCRYPTION as i32)
};
if rc != 0 {
return Err(rc);
}
let tweak_size = tweak.len() as u32;
let rc = unsafe {
sys::wc_AesXtsEncryptInit(&mut self.ws_xtsaes,
tweak.as_ptr(), tweak_size, &mut self.ws_xtsaesstreamdata)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Initialize a XTSStream instance for decryption.
///
/// This method must be called before calling `decrypt_update()`.
///
/// # Parameters
///
/// * `key`: A slice containing the decryption key to use. The key must be
/// 16, 24, or 32 bytes in length.
/// * `tweak`: Tweak value to use for the decryption operation.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn init_decrypt(&mut self, key: &[u8], tweak: &[u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
let rc = unsafe {
sys::wc_AesXtsSetKeyNoInit(&mut self.ws_xtsaes,
key.as_ptr(), key_size, sys::AES_DECRYPTION as i32)
};
if rc != 0 {
return Err(rc);
}
let tweak_size = tweak.len() as u32;
let rc = unsafe {
sys::wc_AesXtsDecryptInit(&mut self.ws_xtsaes,
tweak.as_ptr(), tweak_size, &mut self.ws_xtsaesstreamdata)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Add a chunk of data to encrypt.
///
/// The `init_encrypt()` method must be called before calling this method.
/// The `encrypt_final()` method must be called to finalize the encryption
/// operation.
///
/// # Parameters
///
/// * `din`: Data to encrypt. The size of the data must be a multiple of
/// 16 bytes. A final chunk of data that is not a multiple of 16 bytes
/// can be passed in to `encrypt_final()`.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt_update<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesXtsEncryptUpdate(&mut self.ws_xtsaes, out_ptr,
in_ptr, in_size, &mut self.ws_xtsaesstreamdata)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Encrypt the final chunk of data.
///
/// The `init_encrypt()` method must be called before calling this method.
/// The `encrypt_update()` method may be called prior to this to encrypt
/// blocks of data in chunks.
///
/// # Parameters
///
/// * `din`: Data to encrypt. The size of the data must be 0 or at least
/// 16 bytes. It does not need to be a multiple of 16 bytes.
/// * `dout`: Buffer in which to store the encrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn encrypt_final<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesXtsEncryptFinal(&mut self.ws_xtsaes, out_ptr,
in_ptr, in_size, &mut self.ws_xtsaesstreamdata)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Add a chunk of data to decrypt.
///
/// The `init_decrypt()` method must be called before calling this method.
/// The `decrypt_final()` method must be called to finalize the decryption
/// operation.
///
/// # Parameters
///
/// * `din`: Data to decrypt. The size of the data must be a multiple of
/// 16 bytes. A final chunk of data that is not a multiple of 16 bytes
/// can be passed in to `decrypt_final()`.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt_update<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesXtsDecryptUpdate(&mut self.ws_xtsaes, out_ptr,
in_ptr, in_size, &mut self.ws_xtsaesstreamdata)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Decrypt the final chunk of data.
///
/// The `init_decrypt()` method must be called before calling this method.
/// The `decrypt_update()` method may be called prior to this to decrypt
/// blocks of data in chunks.
///
/// # Parameters
///
/// * `din`: Data to decrypt. The size of the data must be 0 or at least
/// 16 bytes. It does not need to be a multiple of 16 bytes.
/// * `dout`: Buffer in which to store the decrypted data. The size of
/// the buffer must match that of the `din` buffer.
///
/// # Returns
///
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn decrypt_final<I,O>(&mut self, din: &[I], dout: &mut [O]) -> Result<(), i32> {
let in_ptr = din.as_ptr() as *const u8;
let in_size = size_of_val(din) as u32;
let out_ptr = dout.as_ptr() as *mut u8;
let out_size = size_of_val(dout) as u32;
if in_size != out_size {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let rc = unsafe {
sys::wc_AesXtsDecryptFinal(&mut self.ws_xtsaes, out_ptr,
in_ptr, in_size, &mut self.ws_xtsaesstreamdata)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
}
#[cfg(aes_xts_stream)]
impl Drop for XTSStream {
/// Safely free the wolfSSL resources.
fn drop(&mut self) {
unsafe { sys::wc_AesXtsFree(&mut self.ws_xtsaes); }
}
}
// ---------------------------------------------------------------------------
// AES-ECB cipher trait implementations
// ---------------------------------------------------------------------------
/// AES-128 ECB block cipher (encryption) implementing [`cipher::BlockModeEncrypt`].
///
/// The key schedule is computed once during construction via
/// [`cipher::KeyInit::new`] or [`cipher::KeyInit::new_from_slice`].
#[cfg(all(aes_ecb, feature = "cipher"))]
pub struct Aes128EcbEnc {
inner: ECB,
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::KeySizeUser for Aes128EcbEnc {
type KeySize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes128EcbEnc {
type BlockSize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::KeyInit for Aes128EcbEnc {
fn new(key: &cipher::Key<Self>) -> Self {
let mut ecb = ECB::new().expect("wc_AesInit failed");
ecb.init_encrypt(key.as_ref()).expect("wc_AesSetKey failed");
Self { inner: ecb }
}
}
#[cfg(all(aes_ecb, feature = "cipher"))]
struct Aes128EcbEncBackend<'a>(&'a mut Aes128EcbEnc);
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes128EcbEncBackend<'_> {
type BlockSize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl ParBlocksSizeUser for Aes128EcbEncBackend<'_> {
type ParBlocksSize = cipher::typenum::consts::U1;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl BlockModeEncBackend for Aes128EcbEncBackend<'_> {
fn encrypt_block(&mut self, mut block: cipher::InOut<'_, '_, cipher::Block<Self>>) {
let in_block = *block.get_in();
let out = block.get_out();
self.0.inner.encrypt(in_block.as_ref(), out.as_mut()).expect("wc_AesEcbEncrypt failed");
}
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl BlockModeEncrypt for Aes128EcbEnc {
fn encrypt_with_backend(&mut self, f: impl BlockModeEncClosure<BlockSize = Self::BlockSize>) {
f.call(&mut Aes128EcbEncBackend(self));
}
}
/// AES-192 ECB block cipher (encryption) implementing [`cipher::BlockModeEncrypt`].
#[cfg(all(aes_ecb, feature = "cipher"))]
pub struct Aes192EcbEnc {
inner: ECB,
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::KeySizeUser for Aes192EcbEnc {
type KeySize = U24;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes192EcbEnc {
type BlockSize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::KeyInit for Aes192EcbEnc {
fn new(key: &cipher::Key<Self>) -> Self {
let mut ecb = ECB::new().expect("wc_AesInit failed");
ecb.init_encrypt(key.as_ref()).expect("wc_AesSetKey failed");
Self { inner: ecb }
}
}
#[cfg(all(aes_ecb, feature = "cipher"))]
struct Aes192EcbEncBackend<'a>(&'a mut Aes192EcbEnc);
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes192EcbEncBackend<'_> {
type BlockSize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl ParBlocksSizeUser for Aes192EcbEncBackend<'_> {
type ParBlocksSize = cipher::typenum::consts::U1;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl BlockModeEncBackend for Aes192EcbEncBackend<'_> {
fn encrypt_block(&mut self, mut block: cipher::InOut<'_, '_, cipher::Block<Self>>) {
let in_block = *block.get_in();
let out = block.get_out();
self.0.inner.encrypt(in_block.as_ref(), out.as_mut()).expect("wc_AesEcbEncrypt failed");
}
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl BlockModeEncrypt for Aes192EcbEnc {
fn encrypt_with_backend(&mut self, f: impl BlockModeEncClosure<BlockSize = Self::BlockSize>) {
f.call(&mut Aes192EcbEncBackend(self));
}
}
/// AES-256 ECB block cipher (encryption) implementing [`cipher::BlockModeEncrypt`].
#[cfg(all(aes_ecb, feature = "cipher"))]
pub struct Aes256EcbEnc {
inner: ECB,
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::KeySizeUser for Aes256EcbEnc {
type KeySize = U32;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes256EcbEnc {
type BlockSize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::KeyInit for Aes256EcbEnc {
fn new(key: &cipher::Key<Self>) -> Self {
let mut ecb = ECB::new().expect("wc_AesInit failed");
ecb.init_encrypt(key.as_ref()).expect("wc_AesSetKey failed");
Self { inner: ecb }
}
}
#[cfg(all(aes_ecb, feature = "cipher"))]
struct Aes256EcbEncBackend<'a>(&'a mut Aes256EcbEnc);
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes256EcbEncBackend<'_> {
type BlockSize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl ParBlocksSizeUser for Aes256EcbEncBackend<'_> {
type ParBlocksSize = cipher::typenum::consts::U1;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl BlockModeEncBackend for Aes256EcbEncBackend<'_> {
fn encrypt_block(&mut self, mut block: cipher::InOut<'_, '_, cipher::Block<Self>>) {
let in_block = *block.get_in();
let out = block.get_out();
self.0.inner.encrypt(in_block.as_ref(), out.as_mut()).expect("wc_AesEcbEncrypt failed");
}
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl BlockModeEncrypt for Aes256EcbEnc {
fn encrypt_with_backend(&mut self, f: impl BlockModeEncClosure<BlockSize = Self::BlockSize>) {
f.call(&mut Aes256EcbEncBackend(self));
}
}
/// AES-128 ECB block cipher (decryption) implementing [`cipher::BlockModeDecrypt`].
///
/// The key schedule is computed once during construction via
/// [`cipher::KeyInit::new`] or [`cipher::KeyInit::new_from_slice`].
#[cfg(all(aes_ecb, feature = "cipher"))]
pub struct Aes128EcbDec {
inner: ECB,
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::KeySizeUser for Aes128EcbDec {
type KeySize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes128EcbDec {
type BlockSize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::KeyInit for Aes128EcbDec {
fn new(key: &cipher::Key<Self>) -> Self {
let mut ecb = ECB::new().expect("wc_AesInit failed");
ecb.init_decrypt(key.as_ref()).expect("wc_AesSetKey failed");
Self { inner: ecb }
}
}
#[cfg(all(aes_ecb, feature = "cipher"))]
struct Aes128EcbDecBackend<'a>(&'a mut Aes128EcbDec);
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes128EcbDecBackend<'_> {
type BlockSize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl ParBlocksSizeUser for Aes128EcbDecBackend<'_> {
type ParBlocksSize = cipher::typenum::consts::U1;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl BlockModeDecBackend for Aes128EcbDecBackend<'_> {
fn decrypt_block(&mut self, mut block: cipher::InOut<'_, '_, cipher::Block<Self>>) {
let in_block = *block.get_in();
let out = block.get_out();
self.0.inner.decrypt(in_block.as_ref(), out.as_mut()).expect("wc_AesEcbDecrypt failed");
}
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl BlockModeDecrypt for Aes128EcbDec {
fn decrypt_with_backend(&mut self, f: impl BlockModeDecClosure<BlockSize = Self::BlockSize>) {
f.call(&mut Aes128EcbDecBackend(self));
}
}
/// AES-192 ECB block cipher (decryption) implementing [`cipher::BlockModeDecrypt`].
#[cfg(all(aes_ecb, feature = "cipher"))]
pub struct Aes192EcbDec {
inner: ECB,
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::KeySizeUser for Aes192EcbDec {
type KeySize = U24;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes192EcbDec {
type BlockSize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::KeyInit for Aes192EcbDec {
fn new(key: &cipher::Key<Self>) -> Self {
let mut ecb = ECB::new().expect("wc_AesInit failed");
ecb.init_decrypt(key.as_ref()).expect("wc_AesSetKey failed");
Self { inner: ecb }
}
}
#[cfg(all(aes_ecb, feature = "cipher"))]
struct Aes192EcbDecBackend<'a>(&'a mut Aes192EcbDec);
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes192EcbDecBackend<'_> {
type BlockSize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl ParBlocksSizeUser for Aes192EcbDecBackend<'_> {
type ParBlocksSize = cipher::typenum::consts::U1;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl BlockModeDecBackend for Aes192EcbDecBackend<'_> {
fn decrypt_block(&mut self, mut block: cipher::InOut<'_, '_, cipher::Block<Self>>) {
let in_block = *block.get_in();
let out = block.get_out();
self.0.inner.decrypt(in_block.as_ref(), out.as_mut()).expect("wc_AesEcbDecrypt failed");
}
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl BlockModeDecrypt for Aes192EcbDec {
fn decrypt_with_backend(&mut self, f: impl BlockModeDecClosure<BlockSize = Self::BlockSize>) {
f.call(&mut Aes192EcbDecBackend(self));
}
}
/// AES-256 ECB block cipher (decryption) implementing [`cipher::BlockModeDecrypt`].
#[cfg(all(aes_ecb, feature = "cipher"))]
pub struct Aes256EcbDec {
inner: ECB,
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::KeySizeUser for Aes256EcbDec {
type KeySize = U32;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes256EcbDec {
type BlockSize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::KeyInit for Aes256EcbDec {
fn new(key: &cipher::Key<Self>) -> Self {
let mut ecb = ECB::new().expect("wc_AesInit failed");
ecb.init_decrypt(key.as_ref()).expect("wc_AesSetKey failed");
Self { inner: ecb }
}
}
#[cfg(all(aes_ecb, feature = "cipher"))]
struct Aes256EcbDecBackend<'a>(&'a mut Aes256EcbDec);
#[cfg(all(aes_ecb, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes256EcbDecBackend<'_> {
type BlockSize = U16;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl ParBlocksSizeUser for Aes256EcbDecBackend<'_> {
type ParBlocksSize = cipher::typenum::consts::U1;
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl BlockModeDecBackend for Aes256EcbDecBackend<'_> {
fn decrypt_block(&mut self, mut block: cipher::InOut<'_, '_, cipher::Block<Self>>) {
let in_block = *block.get_in();
let out = block.get_out();
self.0.inner.decrypt(in_block.as_ref(), out.as_mut()).expect("wc_AesEcbDecrypt failed");
}
}
#[cfg(all(aes_ecb, feature = "cipher"))]
impl BlockModeDecrypt for Aes256EcbDec {
fn decrypt_with_backend(&mut self, f: impl BlockModeDecClosure<BlockSize = Self::BlockSize>) {
f.call(&mut Aes256EcbDecBackend(self));
}
}
// ---------------------------------------------------------------------------
// AES-CTR cipher trait implementations
// ---------------------------------------------------------------------------
/// AES-128 CTR stream cipher implementing [`cipher::StreamCipher`].
///
/// wolfCrypt AES-CTR supports in-place operation, so the in/out pointers from
/// the [`cipher::inout::InOutBuf`] are passed directly to `wc_AesCtrEncrypt`.
#[cfg(all(aes_ctr, feature = "cipher"))]
pub struct Aes128Ctr {
inner: CTR,
}
#[cfg(all(aes_ctr, feature = "cipher"))]
impl cipher::KeySizeUser for Aes128Ctr {
type KeySize = U16;
}
#[cfg(all(aes_ctr, feature = "cipher"))]
impl IvSizeUser for Aes128Ctr {
type IvSize = U16;
}
#[cfg(all(aes_ctr, feature = "cipher"))]
impl KeyIvInit for Aes128Ctr {
fn new(key: &cipher::Key<Self>, iv: &cipher::Iv<Self>) -> Self {
let mut ctr = CTR::new().expect("wc_AesInit failed");
ctr.init(key.as_ref(), iv.as_ref()).expect("wc_AesSetKeyDirect failed");
Self { inner: ctr }
}
}
#[cfg(all(aes_ctr, feature = "cipher"))]
impl StreamCipher for Aes128Ctr {
fn check_remaining(&self, _data_len: usize) -> Result<(), StreamCipherError> {
Ok(())
}
fn unchecked_apply_keystream_inout(&mut self, mut buf: cipher::InOutBuf<'_, '_, u8>) {
let len = buf.len();
if len == 0 { return; }
// wolfCrypt AES-CTR supports in-place operation (out == in).
let in_ptr = buf.get_in().as_ptr();
let out_ptr = buf.get_out().as_mut_ptr();
// SAFETY: CTR in-place is valid; C function called directly to avoid
// creating aliasing slices.
let rc = unsafe { sys::wc_AesCtrEncrypt(&mut self.inner.ws_aes, out_ptr, in_ptr, len as u32) };
assert_eq!(rc, 0, "wc_AesCtrEncrypt failed");
}
fn unchecked_write_keystream(&mut self, buf: &mut [u8]) {
buf.fill(0);
self.unchecked_apply_keystream_inout(buf.into());
}
}
/// AES-192 CTR stream cipher implementing [`cipher::StreamCipher`].
#[cfg(all(aes_ctr, feature = "cipher"))]
pub struct Aes192Ctr {
inner: CTR,
}
#[cfg(all(aes_ctr, feature = "cipher"))]
impl cipher::KeySizeUser for Aes192Ctr {
type KeySize = U24;
}
#[cfg(all(aes_ctr, feature = "cipher"))]
impl IvSizeUser for Aes192Ctr {
type IvSize = U16;
}
#[cfg(all(aes_ctr, feature = "cipher"))]
impl KeyIvInit for Aes192Ctr {
fn new(key: &cipher::Key<Self>, iv: &cipher::Iv<Self>) -> Self {
let mut ctr = CTR::new().expect("wc_AesInit failed");
ctr.init(key.as_ref(), iv.as_ref()).expect("wc_AesSetKeyDirect failed");
Self { inner: ctr }
}
}
#[cfg(all(aes_ctr, feature = "cipher"))]
impl StreamCipher for Aes192Ctr {
fn check_remaining(&self, _data_len: usize) -> Result<(), StreamCipherError> {
Ok(())
}
fn unchecked_apply_keystream_inout(&mut self, mut buf: cipher::InOutBuf<'_, '_, u8>) {
let len = buf.len();
if len == 0 { return; }
let in_ptr = buf.get_in().as_ptr();
let out_ptr = buf.get_out().as_mut_ptr();
// SAFETY: CTR in-place is valid; C function called directly to avoid
// creating aliasing slices.
let rc = unsafe { sys::wc_AesCtrEncrypt(&mut self.inner.ws_aes, out_ptr, in_ptr, len as u32) };
assert_eq!(rc, 0, "wc_AesCtrEncrypt failed");
}
fn unchecked_write_keystream(&mut self, buf: &mut [u8]) {
buf.fill(0);
self.unchecked_apply_keystream_inout(buf.into());
}
}
/// AES-256 CTR stream cipher implementing [`cipher::StreamCipher`].
#[cfg(all(aes_ctr, feature = "cipher"))]
pub struct Aes256Ctr {
inner: CTR,
}
#[cfg(all(aes_ctr, feature = "cipher"))]
impl cipher::KeySizeUser for Aes256Ctr {
type KeySize = U32;
}
#[cfg(all(aes_ctr, feature = "cipher"))]
impl IvSizeUser for Aes256Ctr {
type IvSize = U16;
}
#[cfg(all(aes_ctr, feature = "cipher"))]
impl KeyIvInit for Aes256Ctr {
fn new(key: &cipher::Key<Self>, iv: &cipher::Iv<Self>) -> Self {
let mut ctr = CTR::new().expect("wc_AesInit failed");
ctr.init(key.as_ref(), iv.as_ref()).expect("wc_AesSetKeyDirect failed");
Self { inner: ctr }
}
}
#[cfg(all(aes_ctr, feature = "cipher"))]
impl StreamCipher for Aes256Ctr {
fn check_remaining(&self, _data_len: usize) -> Result<(), StreamCipherError> {
Ok(())
}
fn unchecked_apply_keystream_inout(&mut self, mut buf: cipher::InOutBuf<'_, '_, u8>) {
let len = buf.len();
if len == 0 { return; }
let in_ptr = buf.get_in().as_ptr();
let out_ptr = buf.get_out().as_mut_ptr();
// SAFETY: CTR in-place is valid; C function called directly to avoid
// creating aliasing slices.
let rc = unsafe { sys::wc_AesCtrEncrypt(&mut self.inner.ws_aes, out_ptr, in_ptr, len as u32) };
assert_eq!(rc, 0, "wc_AesCtrEncrypt failed");
}
fn unchecked_write_keystream(&mut self, buf: &mut [u8]) {
buf.fill(0);
self.unchecked_apply_keystream_inout(buf.into());
}
}
// ---------------------------------------------------------------------------
// AES-OFB cipher trait implementations
// ---------------------------------------------------------------------------
/// AES-128 OFB stream cipher implementing [`cipher::StreamCipher`].
///
/// OFB (Output FeedBack) generates a keystream independent of the data, so
/// [`StreamCipher::apply_keystream`] is self-inverse and wolfCrypt supports
/// in-place operation.
#[cfg(all(aes_ofb, feature = "cipher"))]
pub struct Aes128Ofb {
inner: OFB,
}
#[cfg(all(aes_ofb, feature = "cipher"))]
impl cipher::KeySizeUser for Aes128Ofb {
type KeySize = U16;
}
#[cfg(all(aes_ofb, feature = "cipher"))]
impl IvSizeUser for Aes128Ofb {
type IvSize = U16;
}
#[cfg(all(aes_ofb, feature = "cipher"))]
impl KeyIvInit for Aes128Ofb {
fn new(key: &cipher::Key<Self>, iv: &cipher::Iv<Self>) -> Self {
let mut ofb = OFB::new().expect("wc_AesInit failed");
ofb.init(key.as_ref(), iv.as_ref()).expect("wc_AesSetKey failed");
Self { inner: ofb }
}
}
#[cfg(all(aes_ofb, feature = "cipher"))]
impl StreamCipher for Aes128Ofb {
fn check_remaining(&self, _data_len: usize) -> Result<(), StreamCipherError> {
Ok(())
}
fn unchecked_apply_keystream_inout(&mut self, mut buf: cipher::InOutBuf<'_, '_, u8>) {
let len = buf.len();
if len == 0 { return; }
// wolfCrypt AES-OFB supports in-place operation (out == in).
let in_ptr = buf.get_in().as_ptr();
let out_ptr = buf.get_out().as_mut_ptr();
// SAFETY: OFB in-place is valid; C function called directly to avoid
// creating aliasing slices.
let rc = unsafe { sys::wc_AesOfbEncrypt(&mut self.inner.ws_aes, out_ptr, in_ptr, len as u32) };
assert_eq!(rc, 0, "wc_AesOfbEncrypt failed");
}
fn unchecked_write_keystream(&mut self, buf: &mut [u8]) {
buf.fill(0);
self.unchecked_apply_keystream_inout(buf.into());
}
}
/// AES-192 OFB stream cipher implementing [`cipher::StreamCipher`].
#[cfg(all(aes_ofb, feature = "cipher"))]
pub struct Aes192Ofb {
inner: OFB,
}
#[cfg(all(aes_ofb, feature = "cipher"))]
impl cipher::KeySizeUser for Aes192Ofb {
type KeySize = U24;
}
#[cfg(all(aes_ofb, feature = "cipher"))]
impl IvSizeUser for Aes192Ofb {
type IvSize = U16;
}
#[cfg(all(aes_ofb, feature = "cipher"))]
impl KeyIvInit for Aes192Ofb {
fn new(key: &cipher::Key<Self>, iv: &cipher::Iv<Self>) -> Self {
let mut ofb = OFB::new().expect("wc_AesInit failed");
ofb.init(key.as_ref(), iv.as_ref()).expect("wc_AesSetKey failed");
Self { inner: ofb }
}
}
#[cfg(all(aes_ofb, feature = "cipher"))]
impl StreamCipher for Aes192Ofb {
fn check_remaining(&self, _data_len: usize) -> Result<(), StreamCipherError> {
Ok(())
}
fn unchecked_apply_keystream_inout(&mut self, mut buf: cipher::InOutBuf<'_, '_, u8>) {
let len = buf.len();
if len == 0 { return; }
let in_ptr = buf.get_in().as_ptr();
let out_ptr = buf.get_out().as_mut_ptr();
// SAFETY: OFB in-place is valid; C function called directly to avoid
// creating aliasing slices.
let rc = unsafe { sys::wc_AesOfbEncrypt(&mut self.inner.ws_aes, out_ptr, in_ptr, len as u32) };
assert_eq!(rc, 0, "wc_AesOfbEncrypt failed");
}
fn unchecked_write_keystream(&mut self, buf: &mut [u8]) {
buf.fill(0);
self.unchecked_apply_keystream_inout(buf.into());
}
}
/// AES-256 OFB stream cipher implementing [`cipher::StreamCipher`].
#[cfg(all(aes_ofb, feature = "cipher"))]
pub struct Aes256Ofb {
inner: OFB,
}
#[cfg(all(aes_ofb, feature = "cipher"))]
impl cipher::KeySizeUser for Aes256Ofb {
type KeySize = U32;
}
#[cfg(all(aes_ofb, feature = "cipher"))]
impl IvSizeUser for Aes256Ofb {
type IvSize = U16;
}
#[cfg(all(aes_ofb, feature = "cipher"))]
impl KeyIvInit for Aes256Ofb {
fn new(key: &cipher::Key<Self>, iv: &cipher::Iv<Self>) -> Self {
let mut ofb = OFB::new().expect("wc_AesInit failed");
ofb.init(key.as_ref(), iv.as_ref()).expect("wc_AesSetKey failed");
Self { inner: ofb }
}
}
#[cfg(all(aes_ofb, feature = "cipher"))]
impl StreamCipher for Aes256Ofb {
fn check_remaining(&self, _data_len: usize) -> Result<(), StreamCipherError> {
Ok(())
}
fn unchecked_apply_keystream_inout(&mut self, mut buf: cipher::InOutBuf<'_, '_, u8>) {
let len = buf.len();
if len == 0 { return; }
let in_ptr = buf.get_in().as_ptr();
let out_ptr = buf.get_out().as_mut_ptr();
// SAFETY: OFB in-place is valid; C function called directly to avoid
// creating aliasing slices.
let rc = unsafe { sys::wc_AesOfbEncrypt(&mut self.inner.ws_aes, out_ptr, in_ptr, len as u32) };
assert_eq!(rc, 0, "wc_AesOfbEncrypt failed");
}
fn unchecked_write_keystream(&mut self, buf: &mut [u8]) {
buf.fill(0);
self.unchecked_apply_keystream_inout(buf.into());
}
}
// ---------------------------------------------------------------------------
// AES-CBC block mode trait implementations
// ---------------------------------------------------------------------------
/// AES-128 CBC block cipher (encryption) implementing [`cipher::BlockModeEncrypt`].
///
/// CBC chains ciphertext blocks: each plaintext block is XORed with the
/// previous ciphertext block (or the IV for the first block) before
/// encryption. wolfCrypt maintains the IV state internally between calls,
/// so blocks can be encrypted one at a time and the chaining is preserved.
#[cfg(all(aes_cbc, feature = "cipher"))]
pub struct Aes128CbcEnc {
inner: CBC,
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::KeySizeUser for Aes128CbcEnc {
type KeySize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes128CbcEnc {
type BlockSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl IvSizeUser for Aes128CbcEnc {
type IvSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl KeyIvInit for Aes128CbcEnc {
fn new(key: &cipher::Key<Self>, iv: &cipher::Iv<Self>) -> Self {
let mut cbc = CBC::new().expect("wc_AesInit failed");
cbc.init_encrypt(key.as_ref(), iv.as_ref()).expect("wc_AesSetKey failed");
Self { inner: cbc }
}
}
#[cfg(all(aes_cbc, feature = "cipher"))]
struct Aes128CbcEncBackend<'a>(&'a mut Aes128CbcEnc);
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes128CbcEncBackend<'_> {
type BlockSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl ParBlocksSizeUser for Aes128CbcEncBackend<'_> {
type ParBlocksSize = cipher::typenum::consts::U1;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl BlockModeEncBackend for Aes128CbcEncBackend<'_> {
fn encrypt_block(&mut self, mut block: cipher::InOut<'_, '_, cipher::Block<Self>>) {
let in_block = *block.get_in();
let out = block.get_out();
self.0.inner.encrypt(in_block.as_ref(), out.as_mut()).expect("wc_AesCbcEncrypt failed");
}
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl BlockModeEncrypt for Aes128CbcEnc {
fn encrypt_with_backend(&mut self, f: impl BlockModeEncClosure<BlockSize = Self::BlockSize>) {
f.call(&mut Aes128CbcEncBackend(self));
}
}
/// AES-192 CBC block cipher (encryption) implementing [`cipher::BlockModeEncrypt`].
#[cfg(all(aes_cbc, feature = "cipher"))]
pub struct Aes192CbcEnc {
inner: CBC,
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::KeySizeUser for Aes192CbcEnc {
type KeySize = U24;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes192CbcEnc {
type BlockSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl IvSizeUser for Aes192CbcEnc {
type IvSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl KeyIvInit for Aes192CbcEnc {
fn new(key: &cipher::Key<Self>, iv: &cipher::Iv<Self>) -> Self {
let mut cbc = CBC::new().expect("wc_AesInit failed");
cbc.init_encrypt(key.as_ref(), iv.as_ref()).expect("wc_AesSetKey failed");
Self { inner: cbc }
}
}
#[cfg(all(aes_cbc, feature = "cipher"))]
struct Aes192CbcEncBackend<'a>(&'a mut Aes192CbcEnc);
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes192CbcEncBackend<'_> {
type BlockSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl ParBlocksSizeUser for Aes192CbcEncBackend<'_> {
type ParBlocksSize = cipher::typenum::consts::U1;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl BlockModeEncBackend for Aes192CbcEncBackend<'_> {
fn encrypt_block(&mut self, mut block: cipher::InOut<'_, '_, cipher::Block<Self>>) {
let in_block = *block.get_in();
let out = block.get_out();
self.0.inner.encrypt(in_block.as_ref(), out.as_mut()).expect("wc_AesCbcEncrypt failed");
}
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl BlockModeEncrypt for Aes192CbcEnc {
fn encrypt_with_backend(&mut self, f: impl BlockModeEncClosure<BlockSize = Self::BlockSize>) {
f.call(&mut Aes192CbcEncBackend(self));
}
}
/// AES-256 CBC block cipher (encryption) implementing [`cipher::BlockModeEncrypt`].
#[cfg(all(aes_cbc, feature = "cipher"))]
pub struct Aes256CbcEnc {
inner: CBC,
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::KeySizeUser for Aes256CbcEnc {
type KeySize = U32;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes256CbcEnc {
type BlockSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl IvSizeUser for Aes256CbcEnc {
type IvSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl KeyIvInit for Aes256CbcEnc {
fn new(key: &cipher::Key<Self>, iv: &cipher::Iv<Self>) -> Self {
let mut cbc = CBC::new().expect("wc_AesInit failed");
cbc.init_encrypt(key.as_ref(), iv.as_ref()).expect("wc_AesSetKey failed");
Self { inner: cbc }
}
}
#[cfg(all(aes_cbc, feature = "cipher"))]
struct Aes256CbcEncBackend<'a>(&'a mut Aes256CbcEnc);
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes256CbcEncBackend<'_> {
type BlockSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl ParBlocksSizeUser for Aes256CbcEncBackend<'_> {
type ParBlocksSize = cipher::typenum::consts::U1;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl BlockModeEncBackend for Aes256CbcEncBackend<'_> {
fn encrypt_block(&mut self, mut block: cipher::InOut<'_, '_, cipher::Block<Self>>) {
let in_block = *block.get_in();
let out = block.get_out();
self.0.inner.encrypt(in_block.as_ref(), out.as_mut()).expect("wc_AesCbcEncrypt failed");
}
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl BlockModeEncrypt for Aes256CbcEnc {
fn encrypt_with_backend(&mut self, f: impl BlockModeEncClosure<BlockSize = Self::BlockSize>) {
f.call(&mut Aes256CbcEncBackend(self));
}
}
/// AES-128 CBC block cipher (decryption) implementing [`cipher::BlockModeDecrypt`].
///
/// wolfCrypt maintains the IV state (last ciphertext block) internally, so
/// blocks can be decrypted one at a time and the chaining is preserved.
#[cfg(all(aes_cbc, feature = "cipher"))]
pub struct Aes128CbcDec {
inner: CBC,
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::KeySizeUser for Aes128CbcDec {
type KeySize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes128CbcDec {
type BlockSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl IvSizeUser for Aes128CbcDec {
type IvSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl KeyIvInit for Aes128CbcDec {
fn new(key: &cipher::Key<Self>, iv: &cipher::Iv<Self>) -> Self {
let mut cbc = CBC::new().expect("wc_AesInit failed");
cbc.init_decrypt(key.as_ref(), iv.as_ref()).expect("wc_AesSetKey failed");
Self { inner: cbc }
}
}
#[cfg(all(aes_cbc, feature = "cipher"))]
struct Aes128CbcDecBackend<'a>(&'a mut Aes128CbcDec);
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes128CbcDecBackend<'_> {
type BlockSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl ParBlocksSizeUser for Aes128CbcDecBackend<'_> {
type ParBlocksSize = cipher::typenum::consts::U1;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl BlockModeDecBackend for Aes128CbcDecBackend<'_> {
fn decrypt_block(&mut self, mut block: cipher::InOut<'_, '_, cipher::Block<Self>>) {
let in_block = *block.get_in();
let out = block.get_out();
self.0.inner.decrypt(in_block.as_ref(), out.as_mut()).expect("wc_AesCbcDecrypt failed");
}
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl BlockModeDecrypt for Aes128CbcDec {
fn decrypt_with_backend(&mut self, f: impl BlockModeDecClosure<BlockSize = Self::BlockSize>) {
f.call(&mut Aes128CbcDecBackend(self));
}
}
/// AES-192 CBC block cipher (decryption) implementing [`cipher::BlockModeDecrypt`].
#[cfg(all(aes_cbc, feature = "cipher"))]
pub struct Aes192CbcDec {
inner: CBC,
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::KeySizeUser for Aes192CbcDec {
type KeySize = U24;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes192CbcDec {
type BlockSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl IvSizeUser for Aes192CbcDec {
type IvSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl KeyIvInit for Aes192CbcDec {
fn new(key: &cipher::Key<Self>, iv: &cipher::Iv<Self>) -> Self {
let mut cbc = CBC::new().expect("wc_AesInit failed");
cbc.init_decrypt(key.as_ref(), iv.as_ref()).expect("wc_AesSetKey failed");
Self { inner: cbc }
}
}
#[cfg(all(aes_cbc, feature = "cipher"))]
struct Aes192CbcDecBackend<'a>(&'a mut Aes192CbcDec);
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes192CbcDecBackend<'_> {
type BlockSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl ParBlocksSizeUser for Aes192CbcDecBackend<'_> {
type ParBlocksSize = cipher::typenum::consts::U1;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl BlockModeDecBackend for Aes192CbcDecBackend<'_> {
fn decrypt_block(&mut self, mut block: cipher::InOut<'_, '_, cipher::Block<Self>>) {
let in_block = *block.get_in();
let out = block.get_out();
self.0.inner.decrypt(in_block.as_ref(), out.as_mut()).expect("wc_AesCbcDecrypt failed");
}
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl BlockModeDecrypt for Aes192CbcDec {
fn decrypt_with_backend(&mut self, f: impl BlockModeDecClosure<BlockSize = Self::BlockSize>) {
f.call(&mut Aes192CbcDecBackend(self));
}
}
/// AES-256 CBC block cipher (decryption) implementing [`cipher::BlockModeDecrypt`].
#[cfg(all(aes_cbc, feature = "cipher"))]
pub struct Aes256CbcDec {
inner: CBC,
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::KeySizeUser for Aes256CbcDec {
type KeySize = U32;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes256CbcDec {
type BlockSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl IvSizeUser for Aes256CbcDec {
type IvSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl KeyIvInit for Aes256CbcDec {
fn new(key: &cipher::Key<Self>, iv: &cipher::Iv<Self>) -> Self {
let mut cbc = CBC::new().expect("wc_AesInit failed");
cbc.init_decrypt(key.as_ref(), iv.as_ref()).expect("wc_AesSetKey failed");
Self { inner: cbc }
}
}
#[cfg(all(aes_cbc, feature = "cipher"))]
struct Aes256CbcDecBackend<'a>(&'a mut Aes256CbcDec);
#[cfg(all(aes_cbc, feature = "cipher"))]
impl cipher::BlockSizeUser for Aes256CbcDecBackend<'_> {
type BlockSize = U16;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl ParBlocksSizeUser for Aes256CbcDecBackend<'_> {
type ParBlocksSize = cipher::typenum::consts::U1;
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl BlockModeDecBackend for Aes256CbcDecBackend<'_> {
fn decrypt_block(&mut self, mut block: cipher::InOut<'_, '_, cipher::Block<Self>>) {
let in_block = *block.get_in();
let out = block.get_out();
self.0.inner.decrypt(in_block.as_ref(), out.as_mut()).expect("wc_AesCbcDecrypt failed");
}
}
#[cfg(all(aes_cbc, feature = "cipher"))]
impl BlockModeDecrypt for Aes256CbcDec {
fn decrypt_with_backend(&mut self, f: impl BlockModeDecClosure<BlockSize = Self::BlockSize>) {
f.call(&mut Aes256CbcDecBackend(self));
}
}
fn new_ws_aes(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<sys::Aes, 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 mut ws_aes: MaybeUninit<sys::Aes> = MaybeUninit::uninit();
let rc = unsafe {
sys::wc_AesInit(ws_aes.as_mut_ptr(), heap, dev_id)
};
if rc != 0 {
return Err(rc);
}
let ws_aes = unsafe { ws_aes.assume_init() };
Ok(ws_aes)
}
#[cfg(any(aes_xts, aes_xts_stream))]
fn new_ws_xtsaes(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<sys::XtsAes, 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 mut ws_xtsaes: MaybeUninit<sys::XtsAes> = MaybeUninit::uninit();
let rc = unsafe {
sys::wc_AesXtsInit(ws_xtsaes.as_mut_ptr(), heap, dev_id)
};
if rc != 0 {
return Err(rc);
}
let ws_xtsaes = unsafe { ws_xtsaes.assume_init() };
Ok(ws_xtsaes)
}