fixed aes so it resets instead of reallocating

This commit is contained in:
mamoniot 2022-12-14 18:14:44 -05:00
parent 56b7074ed3
commit d3e0de0ad8

View file

@ -298,6 +298,9 @@ mod fruit_flavored {
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
mod openssl_aes { mod openssl_aes {
use crate::secret::Secret; use crate::secret::Secret;
use foreign_types::ForeignTypeRef;
use openssl::cipher::CipherRef;
use openssl::cipher_ctx::{CipherCtx, CipherCtxRef};
use openssl::symm::{Cipher, Crypter, Mode}; use openssl::symm::{Cipher, Crypter, Mode};
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
@ -385,7 +388,7 @@ mod openssl_aes {
unsafe impl Send for Aes {} unsafe impl Send for Aes {}
unsafe impl Sync for Aes {} unsafe impl Sync for Aes {}
pub struct AesGcm(Secret<32>, usize, Option<Crypter>, bool); pub struct AesGcm(Secret<32>, usize, CipherCtx, bool);
impl AesGcm { impl AesGcm {
/// Construct a new AES-GCM cipher. /// Construct a new AES-GCM cipher.
@ -395,7 +398,7 @@ mod openssl_aes {
match k.len() { match k.len() {
16 | 24 | 32 => { 16 | 24 | 32 => {
s.0[..k.len()].copy_from_slice(k); s.0[..k.len()].copy_from_slice(k);
Self(s, k.len(), None, encrypt) Self(s, k.len(), CipherCtx::new().unwrap(), encrypt)
} }
_ => { _ => {
panic!("AES supports 128, 192, or 256 bits keys"); panic!("AES supports 128, 192, or 256 bits keys");
@ -408,58 +411,64 @@ mod openssl_aes {
#[inline] #[inline]
pub fn reset_init_gcm(&mut self, iv: &[u8]) { pub fn reset_init_gcm(&mut self, iv: &[u8]) {
assert_eq!(iv.len(), 12); assert_eq!(iv.len(), 12);
let mut c = Crypter::new( let t = aes_gcm_by_key_size(self.1);
aes_gcm_by_key_size(self.1), let key = &self.0 .0[..self.1];
if self.3 { {
Mode::Encrypt let f = match self.3 {
} else { true => CipherCtxRef::encrypt_init,
Mode::Decrypt false => CipherCtxRef::decrypt_init,
}, };
&self.0 .0[..self.1],
Some(iv), f(
) &mut self.2,
.unwrap(); Some(unsafe { CipherRef::from_ptr(t.as_ptr() as *mut _) }),
c.pad(false); None,
//let _ = c.set_tag_len(16); None,
let _ = self.2.replace(c); ).unwrap();
self.2.set_key_length(key.len()).unwrap();
if let Some(iv_len) = t.iv_len() {
if iv.len() != iv_len {
self.2.set_iv_length(iv.len()).unwrap();
}
}
f(&mut self.2, None, Some(key), Some(iv)).unwrap();
}
self.2.set_padding(false);
} }
#[inline(always)] #[inline(always)]
pub fn aad(&mut self, aad: &[u8]) { pub fn aad(&mut self, aad: &[u8]) {
assert!(self.2.as_mut().unwrap().aad_update(aad).is_ok()); self.2.cipher_update(aad, None).unwrap();
} }
/// Encrypt or decrypt (same operation with CTR mode) /// Encrypt or decrypt (same operation with CTR mode)
#[inline(always)] #[inline(always)]
pub fn crypt(&mut self, input: &[u8], output: &mut [u8]) { pub fn crypt(&mut self, input: &[u8], output: &mut [u8]) {
assert!(self.2.as_mut().unwrap().update(input, output).is_ok()); self.2.cipher_update(input, Some(output)).unwrap();
} }
/// Encrypt or decrypt in place (same operation with CTR mode) /// Encrypt or decrypt in place (same operation with CTR mode)
#[inline(always)] #[inline(always)]
pub fn crypt_in_place(&mut self, data: &mut [u8]) { pub fn crypt_in_place(&mut self, data: &mut [u8]) {
assert!(self self.2.cipher_update(unsafe { &*std::slice::from_raw_parts(data.as_ptr(), data.len()) }, Some(data)).unwrap();
.2
.as_mut()
.unwrap()
.update(unsafe { &*std::slice::from_raw_parts(data.as_ptr(), data.len()) }, data)
.is_ok());
} }
#[inline(always)] #[inline(always)]
pub fn finish_encrypt(&mut self) -> [u8; 16] { pub fn finish_encrypt(&mut self) -> [u8; 16] {
let mut tag = [0_u8; 16]; let mut tag = [0_u8; 16];
let mut c = self.2.take().unwrap(); self.2.cipher_final(&mut tag).unwrap();
assert!(c.finalize(&mut tag).is_ok()); self.2.tag(&mut tag).unwrap();
assert!(c.get_tag(&mut tag).is_ok());
tag tag
} }
#[inline(always)] #[inline(always)]
pub fn finish_decrypt(&mut self, expected_tag: &[u8]) -> bool { pub fn finish_decrypt(&mut self, expected_tag: &[u8]) -> bool {
let mut c = self.2.take().unwrap(); if self.2.set_tag(expected_tag).is_ok() {
if c.set_tag(expected_tag).is_ok() { let result = self.2.cipher_final(&mut []).is_ok();
let result = c.finalize(&mut []).is_ok();
result result
} else { } else {
false false