use cipher_trait::generic_array::GenericArray;
use cipher_trait::inout::InOut;
use cipher_trait::{
Block, BlockBackend, BlockClosure, BlockDecryptMut, BlockEncryptMut,
BlockSizeUser, IvSizeUser, KeyIvInit, KeySizeUser, ParBlocksSizeUser,
};
use core::ffi::c_int;
use typenum::{U1, U8, U24};
pub use cipher_trait;
pub struct DesEde3CbcEnc {
ctx: *mut wolfcrypt_rs::EVP_CIPHER_CTX,
}
unsafe impl Send for DesEde3CbcEnc {}
impl Drop for DesEde3CbcEnc {
fn drop(&mut self) {
if !self.ctx.is_null() {
unsafe { wolfcrypt_rs::EVP_CIPHER_CTX_free(self.ctx) };
}
}
}
impl KeySizeUser for DesEde3CbcEnc {
type KeySize = U24; }
impl IvSizeUser for DesEde3CbcEnc {
type IvSize = U8; }
impl BlockSizeUser for DesEde3CbcEnc {
type BlockSize = U8; }
impl KeyIvInit for DesEde3CbcEnc {
fn new(key: &GenericArray<u8, U24>, iv: &GenericArray<u8, U8>) -> Self {
let ctx = unsafe { wolfcrypt_rs::EVP_CIPHER_CTX_new() };
assert!(!ctx.is_null(), "EVP_CIPHER_CTX_new returned null");
let rc = unsafe {
wolfcrypt_rs::EVP_EncryptInit_ex(
ctx,
wolfcrypt_rs::EVP_des_ede3_cbc(),
core::ptr::null_mut(),
key.as_ptr(),
iv.as_ptr(),
)
};
assert_eq!(rc, 1, "EVP_EncryptInit_ex failed (OOM or invalid cipher)");
let rc = unsafe { wolfcrypt_rs::EVP_CIPHER_CTX_set_padding(ctx, 0) };
assert_eq!(rc, 1, "EVP_CIPHER_CTX_set_padding failed (context not initialized)");
Self { ctx }
}
}
struct DesEde3CbcEncBackend(*mut wolfcrypt_rs::EVP_CIPHER_CTX);
impl BlockSizeUser for DesEde3CbcEncBackend {
type BlockSize = U8;
}
impl ParBlocksSizeUser for DesEde3CbcEncBackend {
type ParBlocksSize = U1;
}
impl BlockBackend for DesEde3CbcEncBackend {
#[inline]
fn proc_block(&mut self, mut block: InOut<'_, '_, Block<Self>>) {
let mut tmp = [0u8; 8];
let mut outl: c_int = 0;
let rc = unsafe {
wolfcrypt_rs::EVP_EncryptUpdate(
self.0,
tmp.as_mut_ptr(),
&mut outl,
block.get_in().as_ptr(),
8,
)
};
assert_eq!(rc, 1, "EVP_EncryptUpdate failed (context not initialized)");
block.get_out().copy_from_slice(&tmp);
}
}
impl BlockEncryptMut for DesEde3CbcEnc {
fn encrypt_with_backend_mut(
&mut self,
f: impl BlockClosure<BlockSize = Self::BlockSize>,
) {
f.call(&mut DesEde3CbcEncBackend(self.ctx));
}
}
pub struct DesEde3CbcDec {
ctx: *mut wolfcrypt_rs::EVP_CIPHER_CTX,
}
unsafe impl Send for DesEde3CbcDec {}
impl Drop for DesEde3CbcDec {
fn drop(&mut self) {
if !self.ctx.is_null() {
unsafe { wolfcrypt_rs::EVP_CIPHER_CTX_free(self.ctx) };
}
}
}
impl KeySizeUser for DesEde3CbcDec {
type KeySize = U24; }
impl IvSizeUser for DesEde3CbcDec {
type IvSize = U8; }
impl BlockSizeUser for DesEde3CbcDec {
type BlockSize = U8; }
impl KeyIvInit for DesEde3CbcDec {
fn new(key: &GenericArray<u8, U24>, iv: &GenericArray<u8, U8>) -> Self {
let ctx = unsafe { wolfcrypt_rs::EVP_CIPHER_CTX_new() };
assert!(!ctx.is_null(), "EVP_CIPHER_CTX_new returned null");
let rc = unsafe {
wolfcrypt_rs::EVP_DecryptInit_ex(
ctx,
wolfcrypt_rs::EVP_des_ede3_cbc(),
core::ptr::null_mut(),
key.as_ptr(),
iv.as_ptr(),
)
};
assert_eq!(rc, 1, "EVP_DecryptInit_ex failed (OOM or invalid cipher)");
let rc = unsafe { wolfcrypt_rs::EVP_CIPHER_CTX_set_padding(ctx, 0) };
assert_eq!(rc, 1, "EVP_CIPHER_CTX_set_padding failed (context not initialized)");
Self { ctx }
}
}
struct DesEde3CbcDecBackend(*mut wolfcrypt_rs::EVP_CIPHER_CTX);
impl BlockSizeUser for DesEde3CbcDecBackend {
type BlockSize = U8;
}
impl ParBlocksSizeUser for DesEde3CbcDecBackend {
type ParBlocksSize = U1;
}
impl BlockBackend for DesEde3CbcDecBackend {
#[inline]
fn proc_block(&mut self, mut block: InOut<'_, '_, Block<Self>>) {
let mut tmp = [0u8; 8];
let mut outl: c_int = 0;
let rc = unsafe {
wolfcrypt_rs::EVP_DecryptUpdate(
self.0,
tmp.as_mut_ptr(),
&mut outl,
block.get_in().as_ptr(),
8,
)
};
assert_eq!(rc, 1, "EVP_DecryptUpdate failed (context not initialized)");
block.get_out().copy_from_slice(&tmp);
}
}
impl BlockDecryptMut for DesEde3CbcDec {
fn decrypt_with_backend_mut(
&mut self,
f: impl BlockClosure<BlockSize = Self::BlockSize>,
) {
f.call(&mut DesEde3CbcDecBackend(self.ctx));
}
}