192f3ab15Sopenharmony_ci//! The symmetric encryption context. 292f3ab15Sopenharmony_ci//! 392f3ab15Sopenharmony_ci//! # Examples 492f3ab15Sopenharmony_ci//! 592f3ab15Sopenharmony_ci//! Encrypt data with AES128 CBC 692f3ab15Sopenharmony_ci//! 792f3ab15Sopenharmony_ci//! ``` 892f3ab15Sopenharmony_ci//! use openssl::cipher::Cipher; 992f3ab15Sopenharmony_ci//! use openssl::cipher_ctx::CipherCtx; 1092f3ab15Sopenharmony_ci//! 1192f3ab15Sopenharmony_ci//! let cipher = Cipher::aes_128_cbc(); 1292f3ab15Sopenharmony_ci//! let data = b"Some Crypto Text"; 1392f3ab15Sopenharmony_ci//! let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; 1492f3ab15Sopenharmony_ci//! let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07"; 1592f3ab15Sopenharmony_ci//! 1692f3ab15Sopenharmony_ci//! let mut ctx = CipherCtx::new().unwrap(); 1792f3ab15Sopenharmony_ci//! ctx.encrypt_init(Some(cipher), Some(key), Some(iv)).unwrap(); 1892f3ab15Sopenharmony_ci//! 1992f3ab15Sopenharmony_ci//! let mut ciphertext = vec![]; 2092f3ab15Sopenharmony_ci//! ctx.cipher_update_vec(data, &mut ciphertext).unwrap(); 2192f3ab15Sopenharmony_ci//! ctx.cipher_final_vec(&mut ciphertext).unwrap(); 2292f3ab15Sopenharmony_ci//! 2392f3ab15Sopenharmony_ci//! assert_eq!( 2492f3ab15Sopenharmony_ci//! b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\x87\x4D\ 2592f3ab15Sopenharmony_ci//! \xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1", 2692f3ab15Sopenharmony_ci//! &ciphertext[..], 2792f3ab15Sopenharmony_ci//! ); 2892f3ab15Sopenharmony_ci//! ``` 2992f3ab15Sopenharmony_ci//! 3092f3ab15Sopenharmony_ci//! Decrypt data with AES128 CBC 3192f3ab15Sopenharmony_ci//! 3292f3ab15Sopenharmony_ci//! ``` 3392f3ab15Sopenharmony_ci//! use openssl::cipher::Cipher; 3492f3ab15Sopenharmony_ci//! use openssl::cipher_ctx::CipherCtx; 3592f3ab15Sopenharmony_ci//! 3692f3ab15Sopenharmony_ci//! let cipher = Cipher::aes_128_cbc(); 3792f3ab15Sopenharmony_ci//! let data = b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\ 3892f3ab15Sopenharmony_ci//! \x87\x4D\xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1"; 3992f3ab15Sopenharmony_ci//! let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; 4092f3ab15Sopenharmony_ci//! let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07"; 4192f3ab15Sopenharmony_ci//! 4292f3ab15Sopenharmony_ci//! let mut ctx = CipherCtx::new().unwrap(); 4392f3ab15Sopenharmony_ci//! ctx.decrypt_init(Some(cipher), Some(key), Some(iv)).unwrap(); 4492f3ab15Sopenharmony_ci//! 4592f3ab15Sopenharmony_ci//! let mut plaintext = vec![]; 4692f3ab15Sopenharmony_ci//! ctx.cipher_update_vec(data, &mut plaintext).unwrap(); 4792f3ab15Sopenharmony_ci//! ctx.cipher_final_vec(&mut plaintext).unwrap(); 4892f3ab15Sopenharmony_ci//! 4992f3ab15Sopenharmony_ci//! assert_eq!(b"Some Crypto Text", &plaintext[..]); 5092f3ab15Sopenharmony_ci//! ``` 5192f3ab15Sopenharmony_ci#![warn(missing_docs)] 5292f3ab15Sopenharmony_ci 5392f3ab15Sopenharmony_ciuse crate::cipher::CipherRef; 5492f3ab15Sopenharmony_ciuse crate::error::ErrorStack; 5592f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 5692f3ab15Sopenharmony_ciuse crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef}; 5792f3ab15Sopenharmony_ciuse crate::{cvt, cvt_p}; 5892f3ab15Sopenharmony_ci#[cfg(ossl102)] 5992f3ab15Sopenharmony_ciuse bitflags::bitflags; 6092f3ab15Sopenharmony_ciuse cfg_if::cfg_if; 6192f3ab15Sopenharmony_ciuse foreign_types::{ForeignType, ForeignTypeRef}; 6292f3ab15Sopenharmony_ciuse libc::{c_int, c_uchar}; 6392f3ab15Sopenharmony_ciuse openssl_macros::corresponds; 6492f3ab15Sopenharmony_ciuse std::convert::{TryFrom, TryInto}; 6592f3ab15Sopenharmony_ciuse std::ptr; 6692f3ab15Sopenharmony_ci 6792f3ab15Sopenharmony_cicfg_if! { 6892f3ab15Sopenharmony_ci if #[cfg(ossl300)] { 6992f3ab15Sopenharmony_ci use ffi::EVP_CIPHER_CTX_get0_cipher; 7092f3ab15Sopenharmony_ci } else { 7192f3ab15Sopenharmony_ci use ffi::EVP_CIPHER_CTX_cipher as EVP_CIPHER_CTX_get0_cipher; 7292f3ab15Sopenharmony_ci } 7392f3ab15Sopenharmony_ci} 7492f3ab15Sopenharmony_ci 7592f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 7692f3ab15Sopenharmony_ci type CType = ffi::EVP_CIPHER_CTX; 7792f3ab15Sopenharmony_ci fn drop = ffi::EVP_CIPHER_CTX_free; 7892f3ab15Sopenharmony_ci 7992f3ab15Sopenharmony_ci /// A context object used to perform symmetric encryption operations. 8092f3ab15Sopenharmony_ci pub struct CipherCtx; 8192f3ab15Sopenharmony_ci /// A reference to a [`CipherCtx`]. 8292f3ab15Sopenharmony_ci pub struct CipherCtxRef; 8392f3ab15Sopenharmony_ci} 8492f3ab15Sopenharmony_ci 8592f3ab15Sopenharmony_ci#[cfg(ossl102)] 8692f3ab15Sopenharmony_cibitflags! { 8792f3ab15Sopenharmony_ci /// Flags for `EVP_CIPHER_CTX`. 8892f3ab15Sopenharmony_ci pub struct CipherCtxFlags : c_int { 8992f3ab15Sopenharmony_ci /// The flag used to opt into AES key wrap ciphers. 9092f3ab15Sopenharmony_ci const FLAG_WRAP_ALLOW = ffi::EVP_CIPHER_CTX_FLAG_WRAP_ALLOW; 9192f3ab15Sopenharmony_ci } 9292f3ab15Sopenharmony_ci} 9392f3ab15Sopenharmony_ci 9492f3ab15Sopenharmony_ciimpl CipherCtx { 9592f3ab15Sopenharmony_ci /// Creates a new context. 9692f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_new)] 9792f3ab15Sopenharmony_ci pub fn new() -> Result<Self, ErrorStack> { 9892f3ab15Sopenharmony_ci ffi::init(); 9992f3ab15Sopenharmony_ci 10092f3ab15Sopenharmony_ci unsafe { 10192f3ab15Sopenharmony_ci let ptr = cvt_p(ffi::EVP_CIPHER_CTX_new())?; 10292f3ab15Sopenharmony_ci Ok(CipherCtx::from_ptr(ptr)) 10392f3ab15Sopenharmony_ci } 10492f3ab15Sopenharmony_ci } 10592f3ab15Sopenharmony_ci} 10692f3ab15Sopenharmony_ci 10792f3ab15Sopenharmony_ciimpl CipherCtxRef { 10892f3ab15Sopenharmony_ci /// Initializes the context for encryption. 10992f3ab15Sopenharmony_ci /// 11092f3ab15Sopenharmony_ci /// Normally this is called once to set all of the cipher, key, and IV. However, this process can be split up 11192f3ab15Sopenharmony_ci /// by first setting the cipher with no key or IV and then setting the key and IV with no cipher. This can be used 11292f3ab15Sopenharmony_ci /// to, for example, use a nonstandard IV size. 11392f3ab15Sopenharmony_ci /// 11492f3ab15Sopenharmony_ci /// # Panics 11592f3ab15Sopenharmony_ci /// 11692f3ab15Sopenharmony_ci /// Panics if the key buffer is smaller than the key size of the cipher, the IV buffer is smaller than the IV size 11792f3ab15Sopenharmony_ci /// of the cipher, or if a key or IV is provided before a cipher. 11892f3ab15Sopenharmony_ci #[corresponds(EVP_EncryptInit_ex)] 11992f3ab15Sopenharmony_ci pub fn encrypt_init( 12092f3ab15Sopenharmony_ci &mut self, 12192f3ab15Sopenharmony_ci type_: Option<&CipherRef>, 12292f3ab15Sopenharmony_ci key: Option<&[u8]>, 12392f3ab15Sopenharmony_ci iv: Option<&[u8]>, 12492f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> { 12592f3ab15Sopenharmony_ci self.cipher_init(type_, key, iv, ffi::EVP_EncryptInit_ex) 12692f3ab15Sopenharmony_ci } 12792f3ab15Sopenharmony_ci 12892f3ab15Sopenharmony_ci /// Initializes the context for decryption. 12992f3ab15Sopenharmony_ci /// 13092f3ab15Sopenharmony_ci /// Normally this is called once to set all of the cipher, key, and IV. However, this process can be split up 13192f3ab15Sopenharmony_ci /// by first setting the cipher with no key or IV and then setting the key and IV with no cipher. This can be used 13292f3ab15Sopenharmony_ci /// to, for example, use a nonstandard IV size. 13392f3ab15Sopenharmony_ci /// 13492f3ab15Sopenharmony_ci /// # Panics 13592f3ab15Sopenharmony_ci /// 13692f3ab15Sopenharmony_ci /// Panics if the key buffer is smaller than the key size of the cipher, the IV buffer is smaller than the IV size 13792f3ab15Sopenharmony_ci /// of the cipher, or if a key or IV is provided before a cipher. 13892f3ab15Sopenharmony_ci #[corresponds(EVP_DecryptInit_ex)] 13992f3ab15Sopenharmony_ci pub fn decrypt_init( 14092f3ab15Sopenharmony_ci &mut self, 14192f3ab15Sopenharmony_ci type_: Option<&CipherRef>, 14292f3ab15Sopenharmony_ci key: Option<&[u8]>, 14392f3ab15Sopenharmony_ci iv: Option<&[u8]>, 14492f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> { 14592f3ab15Sopenharmony_ci self.cipher_init(type_, key, iv, ffi::EVP_DecryptInit_ex) 14692f3ab15Sopenharmony_ci } 14792f3ab15Sopenharmony_ci 14892f3ab15Sopenharmony_ci fn cipher_init( 14992f3ab15Sopenharmony_ci &mut self, 15092f3ab15Sopenharmony_ci type_: Option<&CipherRef>, 15192f3ab15Sopenharmony_ci key: Option<&[u8]>, 15292f3ab15Sopenharmony_ci iv: Option<&[u8]>, 15392f3ab15Sopenharmony_ci f: unsafe extern "C" fn( 15492f3ab15Sopenharmony_ci *mut ffi::EVP_CIPHER_CTX, 15592f3ab15Sopenharmony_ci *const ffi::EVP_CIPHER, 15692f3ab15Sopenharmony_ci *mut ffi::ENGINE, 15792f3ab15Sopenharmony_ci *const c_uchar, 15892f3ab15Sopenharmony_ci *const c_uchar, 15992f3ab15Sopenharmony_ci ) -> c_int, 16092f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> { 16192f3ab15Sopenharmony_ci if let Some(key) = key { 16292f3ab15Sopenharmony_ci let key_len = type_.map_or_else(|| self.key_length(), |c| c.key_length()); 16392f3ab15Sopenharmony_ci assert!(key_len <= key.len()); 16492f3ab15Sopenharmony_ci } 16592f3ab15Sopenharmony_ci 16692f3ab15Sopenharmony_ci if let Some(iv) = iv { 16792f3ab15Sopenharmony_ci let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length()); 16892f3ab15Sopenharmony_ci assert!(iv_len <= iv.len()); 16992f3ab15Sopenharmony_ci } 17092f3ab15Sopenharmony_ci 17192f3ab15Sopenharmony_ci unsafe { 17292f3ab15Sopenharmony_ci cvt(f( 17392f3ab15Sopenharmony_ci self.as_ptr(), 17492f3ab15Sopenharmony_ci type_.map_or(ptr::null(), |p| p.as_ptr()), 17592f3ab15Sopenharmony_ci ptr::null_mut(), 17692f3ab15Sopenharmony_ci key.map_or(ptr::null(), |k| k.as_ptr()), 17792f3ab15Sopenharmony_ci iv.map_or(ptr::null(), |iv| iv.as_ptr()), 17892f3ab15Sopenharmony_ci ))?; 17992f3ab15Sopenharmony_ci } 18092f3ab15Sopenharmony_ci 18192f3ab15Sopenharmony_ci Ok(()) 18292f3ab15Sopenharmony_ci } 18392f3ab15Sopenharmony_ci 18492f3ab15Sopenharmony_ci /// Initializes the context to perform envelope encryption. 18592f3ab15Sopenharmony_ci /// 18692f3ab15Sopenharmony_ci /// Normally this is called once to set both the cipher and public keys. However, this process may be split up by 18792f3ab15Sopenharmony_ci /// first providing the cipher with no public keys and then setting the public keys with no cipher. 18892f3ab15Sopenharmony_ci /// 18992f3ab15Sopenharmony_ci /// `encrypted_keys` will contain the generated symmetric key encrypted with each corresponding asymmetric private 19092f3ab15Sopenharmony_ci /// key. The generated IV will be written to `iv`. 19192f3ab15Sopenharmony_ci /// 19292f3ab15Sopenharmony_ci /// # Panics 19392f3ab15Sopenharmony_ci /// 19492f3ab15Sopenharmony_ci /// Panics if `pub_keys` is not the same size as `encrypted_keys`, the IV buffer is smaller than the cipher's IV 19592f3ab15Sopenharmony_ci /// size, or if an IV is provided before the cipher. 19692f3ab15Sopenharmony_ci #[corresponds(EVP_SealInit)] 19792f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 19892f3ab15Sopenharmony_ci pub fn seal_init<T>( 19992f3ab15Sopenharmony_ci &mut self, 20092f3ab15Sopenharmony_ci type_: Option<&CipherRef>, 20192f3ab15Sopenharmony_ci pub_keys: &[PKey<T>], 20292f3ab15Sopenharmony_ci encrypted_keys: &mut [Vec<u8>], 20392f3ab15Sopenharmony_ci iv: Option<&mut [u8]>, 20492f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> 20592f3ab15Sopenharmony_ci where 20692f3ab15Sopenharmony_ci T: HasPublic, 20792f3ab15Sopenharmony_ci { 20892f3ab15Sopenharmony_ci assert_eq!(pub_keys.len(), encrypted_keys.len()); 20992f3ab15Sopenharmony_ci if !pub_keys.is_empty() { 21092f3ab15Sopenharmony_ci let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length()); 21192f3ab15Sopenharmony_ci assert!(iv.as_ref().map_or(0, |b| b.len()) >= iv_len); 21292f3ab15Sopenharmony_ci } 21392f3ab15Sopenharmony_ci 21492f3ab15Sopenharmony_ci for (pub_key, buf) in pub_keys.iter().zip(&mut *encrypted_keys) { 21592f3ab15Sopenharmony_ci buf.resize(pub_key.size(), 0); 21692f3ab15Sopenharmony_ci } 21792f3ab15Sopenharmony_ci 21892f3ab15Sopenharmony_ci let mut keys = encrypted_keys 21992f3ab15Sopenharmony_ci .iter_mut() 22092f3ab15Sopenharmony_ci .map(|b| b.as_mut_ptr()) 22192f3ab15Sopenharmony_ci .collect::<Vec<_>>(); 22292f3ab15Sopenharmony_ci let mut key_lengths = vec![0; pub_keys.len()]; 22392f3ab15Sopenharmony_ci let pub_keys_len = i32::try_from(pub_keys.len()).unwrap(); 22492f3ab15Sopenharmony_ci 22592f3ab15Sopenharmony_ci unsafe { 22692f3ab15Sopenharmony_ci cvt(ffi::EVP_SealInit( 22792f3ab15Sopenharmony_ci self.as_ptr(), 22892f3ab15Sopenharmony_ci type_.map_or(ptr::null(), |p| p.as_ptr()), 22992f3ab15Sopenharmony_ci keys.as_mut_ptr(), 23092f3ab15Sopenharmony_ci key_lengths.as_mut_ptr(), 23192f3ab15Sopenharmony_ci iv.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 23292f3ab15Sopenharmony_ci pub_keys.as_ptr() as *mut _, 23392f3ab15Sopenharmony_ci pub_keys_len, 23492f3ab15Sopenharmony_ci ))?; 23592f3ab15Sopenharmony_ci } 23692f3ab15Sopenharmony_ci 23792f3ab15Sopenharmony_ci for (buf, len) in encrypted_keys.iter_mut().zip(key_lengths) { 23892f3ab15Sopenharmony_ci buf.truncate(len as usize); 23992f3ab15Sopenharmony_ci } 24092f3ab15Sopenharmony_ci 24192f3ab15Sopenharmony_ci Ok(()) 24292f3ab15Sopenharmony_ci } 24392f3ab15Sopenharmony_ci 24492f3ab15Sopenharmony_ci /// Initializes the context to perform envelope decryption. 24592f3ab15Sopenharmony_ci /// 24692f3ab15Sopenharmony_ci /// Normally this is called once with all of the arguments present. However, this process may be split up by first 24792f3ab15Sopenharmony_ci /// providing the cipher alone and then after providing the rest of the arguments in a second call. 24892f3ab15Sopenharmony_ci /// 24992f3ab15Sopenharmony_ci /// # Panics 25092f3ab15Sopenharmony_ci /// 25192f3ab15Sopenharmony_ci /// Panics if the IV buffer is smaller than the cipher's required IV size or if the IV is provided before the 25292f3ab15Sopenharmony_ci /// cipher. 25392f3ab15Sopenharmony_ci #[corresponds(EVP_OpenInit)] 25492f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 25592f3ab15Sopenharmony_ci pub fn open_init<T>( 25692f3ab15Sopenharmony_ci &mut self, 25792f3ab15Sopenharmony_ci type_: Option<&CipherRef>, 25892f3ab15Sopenharmony_ci encrypted_key: &[u8], 25992f3ab15Sopenharmony_ci iv: Option<&[u8]>, 26092f3ab15Sopenharmony_ci priv_key: Option<&PKeyRef<T>>, 26192f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> 26292f3ab15Sopenharmony_ci where 26392f3ab15Sopenharmony_ci T: HasPrivate, 26492f3ab15Sopenharmony_ci { 26592f3ab15Sopenharmony_ci if priv_key.is_some() { 26692f3ab15Sopenharmony_ci let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length()); 26792f3ab15Sopenharmony_ci assert!(iv.map_or(0, |b| b.len()) >= iv_len); 26892f3ab15Sopenharmony_ci } 26992f3ab15Sopenharmony_ci 27092f3ab15Sopenharmony_ci let len = c_int::try_from(encrypted_key.len()).unwrap(); 27192f3ab15Sopenharmony_ci unsafe { 27292f3ab15Sopenharmony_ci cvt(ffi::EVP_OpenInit( 27392f3ab15Sopenharmony_ci self.as_ptr(), 27492f3ab15Sopenharmony_ci type_.map_or(ptr::null(), |p| p.as_ptr()), 27592f3ab15Sopenharmony_ci encrypted_key.as_ptr(), 27692f3ab15Sopenharmony_ci len, 27792f3ab15Sopenharmony_ci iv.map_or(ptr::null(), |b| b.as_ptr()), 27892f3ab15Sopenharmony_ci priv_key.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr), 27992f3ab15Sopenharmony_ci ))?; 28092f3ab15Sopenharmony_ci } 28192f3ab15Sopenharmony_ci 28292f3ab15Sopenharmony_ci Ok(()) 28392f3ab15Sopenharmony_ci } 28492f3ab15Sopenharmony_ci 28592f3ab15Sopenharmony_ci fn assert_cipher(&self) { 28692f3ab15Sopenharmony_ci unsafe { 28792f3ab15Sopenharmony_ci assert!(!EVP_CIPHER_CTX_get0_cipher(self.as_ptr()).is_null()); 28892f3ab15Sopenharmony_ci } 28992f3ab15Sopenharmony_ci } 29092f3ab15Sopenharmony_ci 29192f3ab15Sopenharmony_ci /// Returns the block size of the context's cipher. 29292f3ab15Sopenharmony_ci /// 29392f3ab15Sopenharmony_ci /// Stream ciphers will report a block size of 1. 29492f3ab15Sopenharmony_ci /// 29592f3ab15Sopenharmony_ci /// # Panics 29692f3ab15Sopenharmony_ci /// 29792f3ab15Sopenharmony_ci /// Panics if the context has not been initialized with a cipher. 29892f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_block_size)] 29992f3ab15Sopenharmony_ci pub fn block_size(&self) -> usize { 30092f3ab15Sopenharmony_ci self.assert_cipher(); 30192f3ab15Sopenharmony_ci 30292f3ab15Sopenharmony_ci unsafe { ffi::EVP_CIPHER_CTX_block_size(self.as_ptr()) as usize } 30392f3ab15Sopenharmony_ci } 30492f3ab15Sopenharmony_ci 30592f3ab15Sopenharmony_ci /// Returns the key length of the context's cipher. 30692f3ab15Sopenharmony_ci /// 30792f3ab15Sopenharmony_ci /// # Panics 30892f3ab15Sopenharmony_ci /// 30992f3ab15Sopenharmony_ci /// Panics if the context has not been initialized with a cipher. 31092f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_key_length)] 31192f3ab15Sopenharmony_ci pub fn key_length(&self) -> usize { 31292f3ab15Sopenharmony_ci self.assert_cipher(); 31392f3ab15Sopenharmony_ci 31492f3ab15Sopenharmony_ci unsafe { ffi::EVP_CIPHER_CTX_key_length(self.as_ptr()) as usize } 31592f3ab15Sopenharmony_ci } 31692f3ab15Sopenharmony_ci 31792f3ab15Sopenharmony_ci /// Generates a random key based on the configured cipher. 31892f3ab15Sopenharmony_ci /// 31992f3ab15Sopenharmony_ci /// # Panics 32092f3ab15Sopenharmony_ci /// 32192f3ab15Sopenharmony_ci /// Panics if the context has not been initialized with a cipher or if the buffer is smaller than the cipher's key 32292f3ab15Sopenharmony_ci /// length. 32392f3ab15Sopenharmony_ci /// 32492f3ab15Sopenharmony_ci /// This corresponds to [`EVP_CIPHER_CTX_rand_key`]. 32592f3ab15Sopenharmony_ci /// 32692f3ab15Sopenharmony_ci /// [`EVP_CIPHER_CTX_rand_key`]: https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_CTX_rand_key.html 32792f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_rand_key)] 32892f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 32992f3ab15Sopenharmony_ci pub fn rand_key(&self, buf: &mut [u8]) -> Result<(), ErrorStack> { 33092f3ab15Sopenharmony_ci assert!(buf.len() >= self.key_length()); 33192f3ab15Sopenharmony_ci 33292f3ab15Sopenharmony_ci unsafe { 33392f3ab15Sopenharmony_ci cvt(ffi::EVP_CIPHER_CTX_rand_key( 33492f3ab15Sopenharmony_ci self.as_ptr(), 33592f3ab15Sopenharmony_ci buf.as_mut_ptr(), 33692f3ab15Sopenharmony_ci ))?; 33792f3ab15Sopenharmony_ci } 33892f3ab15Sopenharmony_ci 33992f3ab15Sopenharmony_ci Ok(()) 34092f3ab15Sopenharmony_ci } 34192f3ab15Sopenharmony_ci 34292f3ab15Sopenharmony_ci /// Sets the length of the key expected by the context. 34392f3ab15Sopenharmony_ci /// 34492f3ab15Sopenharmony_ci /// Only some ciphers support configurable key lengths. 34592f3ab15Sopenharmony_ci /// 34692f3ab15Sopenharmony_ci /// # Panics 34792f3ab15Sopenharmony_ci /// 34892f3ab15Sopenharmony_ci /// Panics if the context has not been initialized with a cipher. 34992f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_set_key_length)] 35092f3ab15Sopenharmony_ci pub fn set_key_length(&mut self, len: usize) -> Result<(), ErrorStack> { 35192f3ab15Sopenharmony_ci self.assert_cipher(); 35292f3ab15Sopenharmony_ci 35392f3ab15Sopenharmony_ci unsafe { 35492f3ab15Sopenharmony_ci cvt(ffi::EVP_CIPHER_CTX_set_key_length( 35592f3ab15Sopenharmony_ci self.as_ptr(), 35692f3ab15Sopenharmony_ci len.try_into().unwrap(), 35792f3ab15Sopenharmony_ci ))?; 35892f3ab15Sopenharmony_ci } 35992f3ab15Sopenharmony_ci 36092f3ab15Sopenharmony_ci Ok(()) 36192f3ab15Sopenharmony_ci } 36292f3ab15Sopenharmony_ci 36392f3ab15Sopenharmony_ci /// Returns the length of the IV expected by this context. 36492f3ab15Sopenharmony_ci /// 36592f3ab15Sopenharmony_ci /// Returns 0 if the cipher does not use an IV. 36692f3ab15Sopenharmony_ci /// 36792f3ab15Sopenharmony_ci /// # Panics 36892f3ab15Sopenharmony_ci /// 36992f3ab15Sopenharmony_ci /// Panics if the context has not been initialized with a cipher. 37092f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_iv_length)] 37192f3ab15Sopenharmony_ci pub fn iv_length(&self) -> usize { 37292f3ab15Sopenharmony_ci self.assert_cipher(); 37392f3ab15Sopenharmony_ci 37492f3ab15Sopenharmony_ci unsafe { ffi::EVP_CIPHER_CTX_iv_length(self.as_ptr()) as usize } 37592f3ab15Sopenharmony_ci } 37692f3ab15Sopenharmony_ci 37792f3ab15Sopenharmony_ci /// Returns the `num` parameter of the cipher. 37892f3ab15Sopenharmony_ci /// 37992f3ab15Sopenharmony_ci /// Built-in ciphers typically use this to track how much of the 38092f3ab15Sopenharmony_ci /// current underlying block has been "used" already. 38192f3ab15Sopenharmony_ci /// 38292f3ab15Sopenharmony_ci /// # Panics 38392f3ab15Sopenharmony_ci /// 38492f3ab15Sopenharmony_ci /// Panics if the context has not been initialized with a cipher. 38592f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_num)] 38692f3ab15Sopenharmony_ci #[cfg(ossl110)] 38792f3ab15Sopenharmony_ci pub fn num(&self) -> usize { 38892f3ab15Sopenharmony_ci self.assert_cipher(); 38992f3ab15Sopenharmony_ci 39092f3ab15Sopenharmony_ci unsafe { ffi::EVP_CIPHER_CTX_num(self.as_ptr()) as usize } 39192f3ab15Sopenharmony_ci } 39292f3ab15Sopenharmony_ci 39392f3ab15Sopenharmony_ci /// Sets the length of the IV expected by this context. 39492f3ab15Sopenharmony_ci /// 39592f3ab15Sopenharmony_ci /// Only some ciphers support configurable IV lengths. 39692f3ab15Sopenharmony_ci /// 39792f3ab15Sopenharmony_ci /// # Panics 39892f3ab15Sopenharmony_ci /// 39992f3ab15Sopenharmony_ci /// Panics if the context has not been initialized with a cipher. 40092f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_ctrl)] 40192f3ab15Sopenharmony_ci pub fn set_iv_length(&mut self, len: usize) -> Result<(), ErrorStack> { 40292f3ab15Sopenharmony_ci self.assert_cipher(); 40392f3ab15Sopenharmony_ci 40492f3ab15Sopenharmony_ci let len = c_int::try_from(len).unwrap(); 40592f3ab15Sopenharmony_ci 40692f3ab15Sopenharmony_ci unsafe { 40792f3ab15Sopenharmony_ci cvt(ffi::EVP_CIPHER_CTX_ctrl( 40892f3ab15Sopenharmony_ci self.as_ptr(), 40992f3ab15Sopenharmony_ci ffi::EVP_CTRL_GCM_SET_IVLEN, 41092f3ab15Sopenharmony_ci len, 41192f3ab15Sopenharmony_ci ptr::null_mut(), 41292f3ab15Sopenharmony_ci ))?; 41392f3ab15Sopenharmony_ci } 41492f3ab15Sopenharmony_ci 41592f3ab15Sopenharmony_ci Ok(()) 41692f3ab15Sopenharmony_ci } 41792f3ab15Sopenharmony_ci 41892f3ab15Sopenharmony_ci /// Returns the length of the authentication tag expected by this context. 41992f3ab15Sopenharmony_ci /// 42092f3ab15Sopenharmony_ci /// Returns 0 if the cipher is not authenticated. 42192f3ab15Sopenharmony_ci /// 42292f3ab15Sopenharmony_ci /// # Panics 42392f3ab15Sopenharmony_ci /// 42492f3ab15Sopenharmony_ci /// Panics if the context has not been initialized with a cipher. 42592f3ab15Sopenharmony_ci /// 42692f3ab15Sopenharmony_ci /// Requires OpenSSL 3.0.0 or newer. 42792f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_get_tag_length)] 42892f3ab15Sopenharmony_ci #[cfg(ossl300)] 42992f3ab15Sopenharmony_ci pub fn tag_length(&self) -> usize { 43092f3ab15Sopenharmony_ci self.assert_cipher(); 43192f3ab15Sopenharmony_ci 43292f3ab15Sopenharmony_ci unsafe { ffi::EVP_CIPHER_CTX_get_tag_length(self.as_ptr()) as usize } 43392f3ab15Sopenharmony_ci } 43492f3ab15Sopenharmony_ci 43592f3ab15Sopenharmony_ci /// Retrieves the calculated authentication tag from the context. 43692f3ab15Sopenharmony_ci /// 43792f3ab15Sopenharmony_ci /// This should be called after [`Self::cipher_final`], and is only supported by authenticated ciphers. 43892f3ab15Sopenharmony_ci /// 43992f3ab15Sopenharmony_ci /// The size of the buffer indicates the size of the tag. While some ciphers support a range of tag sizes, it is 44092f3ab15Sopenharmony_ci /// recommended to pick the maximum size. 44192f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_ctrl)] 44292f3ab15Sopenharmony_ci pub fn tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> { 44392f3ab15Sopenharmony_ci let len = c_int::try_from(tag.len()).unwrap(); 44492f3ab15Sopenharmony_ci 44592f3ab15Sopenharmony_ci unsafe { 44692f3ab15Sopenharmony_ci cvt(ffi::EVP_CIPHER_CTX_ctrl( 44792f3ab15Sopenharmony_ci self.as_ptr(), 44892f3ab15Sopenharmony_ci ffi::EVP_CTRL_GCM_GET_TAG, 44992f3ab15Sopenharmony_ci len, 45092f3ab15Sopenharmony_ci tag.as_mut_ptr() as *mut _, 45192f3ab15Sopenharmony_ci ))?; 45292f3ab15Sopenharmony_ci } 45392f3ab15Sopenharmony_ci 45492f3ab15Sopenharmony_ci Ok(()) 45592f3ab15Sopenharmony_ci } 45692f3ab15Sopenharmony_ci 45792f3ab15Sopenharmony_ci /// Sets the length of the generated authentication tag. 45892f3ab15Sopenharmony_ci /// 45992f3ab15Sopenharmony_ci /// This must be called when encrypting with a cipher in CCM mode to use a tag size other than the default. 46092f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_ctrl)] 46192f3ab15Sopenharmony_ci pub fn set_tag_length(&mut self, len: usize) -> Result<(), ErrorStack> { 46292f3ab15Sopenharmony_ci let len = c_int::try_from(len).unwrap(); 46392f3ab15Sopenharmony_ci 46492f3ab15Sopenharmony_ci unsafe { 46592f3ab15Sopenharmony_ci cvt(ffi::EVP_CIPHER_CTX_ctrl( 46692f3ab15Sopenharmony_ci self.as_ptr(), 46792f3ab15Sopenharmony_ci ffi::EVP_CTRL_GCM_SET_TAG, 46892f3ab15Sopenharmony_ci len, 46992f3ab15Sopenharmony_ci ptr::null_mut(), 47092f3ab15Sopenharmony_ci ))?; 47192f3ab15Sopenharmony_ci } 47292f3ab15Sopenharmony_ci 47392f3ab15Sopenharmony_ci Ok(()) 47492f3ab15Sopenharmony_ci } 47592f3ab15Sopenharmony_ci 47692f3ab15Sopenharmony_ci /// Sets the authentication tag for verification during decryption. 47792f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_ctrl)] 47892f3ab15Sopenharmony_ci pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> { 47992f3ab15Sopenharmony_ci let len = c_int::try_from(tag.len()).unwrap(); 48092f3ab15Sopenharmony_ci 48192f3ab15Sopenharmony_ci unsafe { 48292f3ab15Sopenharmony_ci cvt(ffi::EVP_CIPHER_CTX_ctrl( 48392f3ab15Sopenharmony_ci self.as_ptr(), 48492f3ab15Sopenharmony_ci ffi::EVP_CTRL_GCM_SET_TAG, 48592f3ab15Sopenharmony_ci len, 48692f3ab15Sopenharmony_ci tag.as_ptr() as *mut _, 48792f3ab15Sopenharmony_ci ))?; 48892f3ab15Sopenharmony_ci } 48992f3ab15Sopenharmony_ci 49092f3ab15Sopenharmony_ci Ok(()) 49192f3ab15Sopenharmony_ci } 49292f3ab15Sopenharmony_ci 49392f3ab15Sopenharmony_ci /// Enables or disables padding. 49492f3ab15Sopenharmony_ci /// 49592f3ab15Sopenharmony_ci /// If padding is disabled, the plaintext must be an exact multiple of the cipher's block size. 49692f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_set_padding)] 49792f3ab15Sopenharmony_ci pub fn set_padding(&mut self, padding: bool) { 49892f3ab15Sopenharmony_ci unsafe { 49992f3ab15Sopenharmony_ci ffi::EVP_CIPHER_CTX_set_padding(self.as_ptr(), padding as c_int); 50092f3ab15Sopenharmony_ci } 50192f3ab15Sopenharmony_ci } 50292f3ab15Sopenharmony_ci 50392f3ab15Sopenharmony_ci /// Sets the total length of plaintext data. 50492f3ab15Sopenharmony_ci /// 50592f3ab15Sopenharmony_ci /// This is required for ciphers operating in CCM mode. 50692f3ab15Sopenharmony_ci #[corresponds(EVP_CipherUpdate)] 50792f3ab15Sopenharmony_ci pub fn set_data_len(&mut self, len: usize) -> Result<(), ErrorStack> { 50892f3ab15Sopenharmony_ci let len = c_int::try_from(len).unwrap(); 50992f3ab15Sopenharmony_ci 51092f3ab15Sopenharmony_ci unsafe { 51192f3ab15Sopenharmony_ci cvt(ffi::EVP_CipherUpdate( 51292f3ab15Sopenharmony_ci self.as_ptr(), 51392f3ab15Sopenharmony_ci ptr::null_mut(), 51492f3ab15Sopenharmony_ci &mut 0, 51592f3ab15Sopenharmony_ci ptr::null(), 51692f3ab15Sopenharmony_ci len, 51792f3ab15Sopenharmony_ci ))?; 51892f3ab15Sopenharmony_ci } 51992f3ab15Sopenharmony_ci 52092f3ab15Sopenharmony_ci Ok(()) 52192f3ab15Sopenharmony_ci } 52292f3ab15Sopenharmony_ci 52392f3ab15Sopenharmony_ci /// Set ctx flags. 52492f3ab15Sopenharmony_ci /// 52592f3ab15Sopenharmony_ci /// This function is currently used to enable AES key wrap feature supported by OpenSSL 1.0.2 or newer. 52692f3ab15Sopenharmony_ci #[corresponds(EVP_CIPHER_CTX_set_flags)] 52792f3ab15Sopenharmony_ci #[cfg(ossl102)] 52892f3ab15Sopenharmony_ci pub fn set_flags(&mut self, flags: CipherCtxFlags) { 52992f3ab15Sopenharmony_ci unsafe { 53092f3ab15Sopenharmony_ci ffi::EVP_CIPHER_CTX_set_flags(self.as_ptr(), flags.bits()); 53192f3ab15Sopenharmony_ci } 53292f3ab15Sopenharmony_ci } 53392f3ab15Sopenharmony_ci 53492f3ab15Sopenharmony_ci /// Writes data into the context. 53592f3ab15Sopenharmony_ci /// 53692f3ab15Sopenharmony_ci /// Providing no output buffer will cause the input to be considered additional authenticated data (AAD). 53792f3ab15Sopenharmony_ci /// 53892f3ab15Sopenharmony_ci /// Returns the number of bytes written to `output`. 53992f3ab15Sopenharmony_ci /// 54092f3ab15Sopenharmony_ci /// # Panics 54192f3ab15Sopenharmony_ci /// 54292f3ab15Sopenharmony_ci /// Panics if `output` doesn't contain enough space for data to be 54392f3ab15Sopenharmony_ci /// written as specified by [`Self::minimal_output_size`]. 54492f3ab15Sopenharmony_ci #[corresponds(EVP_CipherUpdate)] 54592f3ab15Sopenharmony_ci pub fn cipher_update( 54692f3ab15Sopenharmony_ci &mut self, 54792f3ab15Sopenharmony_ci input: &[u8], 54892f3ab15Sopenharmony_ci output: Option<&mut [u8]>, 54992f3ab15Sopenharmony_ci ) -> Result<usize, ErrorStack> { 55092f3ab15Sopenharmony_ci if let Some(output) = &output { 55192f3ab15Sopenharmony_ci let mut block_size = self.block_size(); 55292f3ab15Sopenharmony_ci if block_size == 1 { 55392f3ab15Sopenharmony_ci block_size = 0; 55492f3ab15Sopenharmony_ci } 55592f3ab15Sopenharmony_ci let min_output_size = input.len() + block_size; 55692f3ab15Sopenharmony_ci assert!( 55792f3ab15Sopenharmony_ci output.len() >= min_output_size, 55892f3ab15Sopenharmony_ci "Output buffer size should be at least {} bytes.", 55992f3ab15Sopenharmony_ci min_output_size 56092f3ab15Sopenharmony_ci ); 56192f3ab15Sopenharmony_ci } 56292f3ab15Sopenharmony_ci 56392f3ab15Sopenharmony_ci unsafe { self.cipher_update_unchecked(input, output) } 56492f3ab15Sopenharmony_ci } 56592f3ab15Sopenharmony_ci 56692f3ab15Sopenharmony_ci /// Writes data into the context. 56792f3ab15Sopenharmony_ci /// 56892f3ab15Sopenharmony_ci /// Providing no output buffer will cause the input to be considered additional authenticated data (AAD). 56992f3ab15Sopenharmony_ci /// 57092f3ab15Sopenharmony_ci /// Returns the number of bytes written to `output`. 57192f3ab15Sopenharmony_ci /// 57292f3ab15Sopenharmony_ci /// This function is the same as [`Self::cipher_update`] but with the 57392f3ab15Sopenharmony_ci /// output size check removed. It can be used when the exact 57492f3ab15Sopenharmony_ci /// buffer size control is maintained by the caller. 57592f3ab15Sopenharmony_ci /// 57692f3ab15Sopenharmony_ci /// # Safety 57792f3ab15Sopenharmony_ci /// The caller is expected to provide `output` buffer 57892f3ab15Sopenharmony_ci /// large enough to contain correct number of bytes. For streaming 57992f3ab15Sopenharmony_ci /// ciphers the output buffer size should be at least as big as 58092f3ab15Sopenharmony_ci /// the input buffer. For block ciphers the size of the output 58192f3ab15Sopenharmony_ci /// buffer depends on the state of partially updated blocks. 58292f3ab15Sopenharmony_ci #[corresponds(EVP_CipherUpdate)] 58392f3ab15Sopenharmony_ci pub unsafe fn cipher_update_unchecked( 58492f3ab15Sopenharmony_ci &mut self, 58592f3ab15Sopenharmony_ci input: &[u8], 58692f3ab15Sopenharmony_ci output: Option<&mut [u8]>, 58792f3ab15Sopenharmony_ci ) -> Result<usize, ErrorStack> { 58892f3ab15Sopenharmony_ci let inlen = c_int::try_from(input.len()).unwrap(); 58992f3ab15Sopenharmony_ci 59092f3ab15Sopenharmony_ci let mut outlen = 0; 59192f3ab15Sopenharmony_ci 59292f3ab15Sopenharmony_ci cvt(ffi::EVP_CipherUpdate( 59392f3ab15Sopenharmony_ci self.as_ptr(), 59492f3ab15Sopenharmony_ci output.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 59592f3ab15Sopenharmony_ci &mut outlen, 59692f3ab15Sopenharmony_ci input.as_ptr(), 59792f3ab15Sopenharmony_ci inlen, 59892f3ab15Sopenharmony_ci ))?; 59992f3ab15Sopenharmony_ci 60092f3ab15Sopenharmony_ci Ok(outlen as usize) 60192f3ab15Sopenharmony_ci } 60292f3ab15Sopenharmony_ci 60392f3ab15Sopenharmony_ci /// Like [`Self::cipher_update`] except that it appends output to a [`Vec`]. 60492f3ab15Sopenharmony_ci pub fn cipher_update_vec( 60592f3ab15Sopenharmony_ci &mut self, 60692f3ab15Sopenharmony_ci input: &[u8], 60792f3ab15Sopenharmony_ci output: &mut Vec<u8>, 60892f3ab15Sopenharmony_ci ) -> Result<usize, ErrorStack> { 60992f3ab15Sopenharmony_ci let base = output.len(); 61092f3ab15Sopenharmony_ci output.resize(base + input.len() + self.block_size(), 0); 61192f3ab15Sopenharmony_ci let len = self.cipher_update(input, Some(&mut output[base..]))?; 61292f3ab15Sopenharmony_ci output.truncate(base + len); 61392f3ab15Sopenharmony_ci 61492f3ab15Sopenharmony_ci Ok(len) 61592f3ab15Sopenharmony_ci } 61692f3ab15Sopenharmony_ci 61792f3ab15Sopenharmony_ci /// Like [`Self::cipher_update`] except that it writes output into the 61892f3ab15Sopenharmony_ci /// `data` buffer. The `inlen` parameter specifies the number of bytes in 61992f3ab15Sopenharmony_ci /// `data` that are considered the input. For streaming ciphers, the size of 62092f3ab15Sopenharmony_ci /// `data` must be at least the input size. Otherwise, it must be at least 62192f3ab15Sopenharmony_ci /// an additional block size larger. 62292f3ab15Sopenharmony_ci /// 62392f3ab15Sopenharmony_ci /// Note: Use [`Self::cipher_update`] with no output argument to write AAD. 62492f3ab15Sopenharmony_ci /// 62592f3ab15Sopenharmony_ci /// # Panics 62692f3ab15Sopenharmony_ci /// 62792f3ab15Sopenharmony_ci /// This function panics if the input size cannot be represented as `int` or 62892f3ab15Sopenharmony_ci /// exceeds the buffer size, or if the output buffer does not contain enough 62992f3ab15Sopenharmony_ci /// additional space. 63092f3ab15Sopenharmony_ci #[corresponds(EVP_CipherUpdate)] 63192f3ab15Sopenharmony_ci pub fn cipher_update_inplace( 63292f3ab15Sopenharmony_ci &mut self, 63392f3ab15Sopenharmony_ci data: &mut [u8], 63492f3ab15Sopenharmony_ci inlen: usize, 63592f3ab15Sopenharmony_ci ) -> Result<usize, ErrorStack> { 63692f3ab15Sopenharmony_ci assert!(inlen <= data.len(), "Input size may not exceed buffer size"); 63792f3ab15Sopenharmony_ci let block_size = self.block_size(); 63892f3ab15Sopenharmony_ci if block_size != 1 { 63992f3ab15Sopenharmony_ci assert!( 64092f3ab15Sopenharmony_ci data.len() >= inlen + block_size, 64192f3ab15Sopenharmony_ci "Output buffer size must be at least {} bytes.", 64292f3ab15Sopenharmony_ci inlen + block_size 64392f3ab15Sopenharmony_ci ); 64492f3ab15Sopenharmony_ci } 64592f3ab15Sopenharmony_ci 64692f3ab15Sopenharmony_ci let inlen = c_int::try_from(inlen).unwrap(); 64792f3ab15Sopenharmony_ci let mut outlen = 0; 64892f3ab15Sopenharmony_ci unsafe { 64992f3ab15Sopenharmony_ci cvt(ffi::EVP_CipherUpdate( 65092f3ab15Sopenharmony_ci self.as_ptr(), 65192f3ab15Sopenharmony_ci data.as_mut_ptr(), 65292f3ab15Sopenharmony_ci &mut outlen, 65392f3ab15Sopenharmony_ci data.as_ptr(), 65492f3ab15Sopenharmony_ci inlen, 65592f3ab15Sopenharmony_ci )) 65692f3ab15Sopenharmony_ci }?; 65792f3ab15Sopenharmony_ci 65892f3ab15Sopenharmony_ci Ok(outlen as usize) 65992f3ab15Sopenharmony_ci } 66092f3ab15Sopenharmony_ci 66192f3ab15Sopenharmony_ci /// Finalizes the encryption or decryption process. 66292f3ab15Sopenharmony_ci /// 66392f3ab15Sopenharmony_ci /// Any remaining data will be written to the output buffer. 66492f3ab15Sopenharmony_ci /// 66592f3ab15Sopenharmony_ci /// Returns the number of bytes written to `output`. 66692f3ab15Sopenharmony_ci /// 66792f3ab15Sopenharmony_ci /// # Panics 66892f3ab15Sopenharmony_ci /// 66992f3ab15Sopenharmony_ci /// Panics if `output` is smaller than the cipher's block size. 67092f3ab15Sopenharmony_ci #[corresponds(EVP_CipherFinal)] 67192f3ab15Sopenharmony_ci pub fn cipher_final(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> { 67292f3ab15Sopenharmony_ci let block_size = self.block_size(); 67392f3ab15Sopenharmony_ci if block_size > 1 { 67492f3ab15Sopenharmony_ci assert!(output.len() >= block_size); 67592f3ab15Sopenharmony_ci } 67692f3ab15Sopenharmony_ci 67792f3ab15Sopenharmony_ci unsafe { self.cipher_final_unchecked(output) } 67892f3ab15Sopenharmony_ci } 67992f3ab15Sopenharmony_ci 68092f3ab15Sopenharmony_ci /// Finalizes the encryption or decryption process. 68192f3ab15Sopenharmony_ci /// 68292f3ab15Sopenharmony_ci /// Any remaining data will be written to the output buffer. 68392f3ab15Sopenharmony_ci /// 68492f3ab15Sopenharmony_ci /// Returns the number of bytes written to `output`. 68592f3ab15Sopenharmony_ci /// 68692f3ab15Sopenharmony_ci /// This function is the same as [`Self::cipher_final`] but with 68792f3ab15Sopenharmony_ci /// the output buffer size check removed. 68892f3ab15Sopenharmony_ci /// 68992f3ab15Sopenharmony_ci /// # Safety 69092f3ab15Sopenharmony_ci /// The caller is expected to provide `output` buffer 69192f3ab15Sopenharmony_ci /// large enough to contain correct number of bytes. For streaming 69292f3ab15Sopenharmony_ci /// ciphers the output buffer can be empty, for block ciphers the 69392f3ab15Sopenharmony_ci /// output buffer should be at least as big as the block. 69492f3ab15Sopenharmony_ci #[corresponds(EVP_CipherFinal)] 69592f3ab15Sopenharmony_ci pub unsafe fn cipher_final_unchecked( 69692f3ab15Sopenharmony_ci &mut self, 69792f3ab15Sopenharmony_ci output: &mut [u8], 69892f3ab15Sopenharmony_ci ) -> Result<usize, ErrorStack> { 69992f3ab15Sopenharmony_ci let mut outl = 0; 70092f3ab15Sopenharmony_ci 70192f3ab15Sopenharmony_ci cvt(ffi::EVP_CipherFinal( 70292f3ab15Sopenharmony_ci self.as_ptr(), 70392f3ab15Sopenharmony_ci output.as_mut_ptr(), 70492f3ab15Sopenharmony_ci &mut outl, 70592f3ab15Sopenharmony_ci ))?; 70692f3ab15Sopenharmony_ci 70792f3ab15Sopenharmony_ci Ok(outl as usize) 70892f3ab15Sopenharmony_ci } 70992f3ab15Sopenharmony_ci 71092f3ab15Sopenharmony_ci /// Like [`Self::cipher_final`] except that it appends output to a [`Vec`]. 71192f3ab15Sopenharmony_ci pub fn cipher_final_vec(&mut self, output: &mut Vec<u8>) -> Result<usize, ErrorStack> { 71292f3ab15Sopenharmony_ci let base = output.len(); 71392f3ab15Sopenharmony_ci output.resize(base + self.block_size(), 0); 71492f3ab15Sopenharmony_ci let len = self.cipher_final(&mut output[base..])?; 71592f3ab15Sopenharmony_ci output.truncate(base + len); 71692f3ab15Sopenharmony_ci 71792f3ab15Sopenharmony_ci Ok(len) 71892f3ab15Sopenharmony_ci } 71992f3ab15Sopenharmony_ci} 72092f3ab15Sopenharmony_ci 72192f3ab15Sopenharmony_ci#[cfg(test)] 72292f3ab15Sopenharmony_cimod test { 72392f3ab15Sopenharmony_ci use super::*; 72492f3ab15Sopenharmony_ci use crate::{cipher::Cipher, rand::rand_bytes}; 72592f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 72692f3ab15Sopenharmony_ci use std::slice; 72792f3ab15Sopenharmony_ci 72892f3ab15Sopenharmony_ci #[test] 72992f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 73092f3ab15Sopenharmony_ci fn seal_open() { 73192f3ab15Sopenharmony_ci let private_pem = include_bytes!("../test/rsa.pem"); 73292f3ab15Sopenharmony_ci let public_pem = include_bytes!("../test/rsa.pem.pub"); 73392f3ab15Sopenharmony_ci let private_key = PKey::private_key_from_pem(private_pem).unwrap(); 73492f3ab15Sopenharmony_ci let public_key = PKey::public_key_from_pem(public_pem).unwrap(); 73592f3ab15Sopenharmony_ci let cipher = Cipher::aes_256_cbc(); 73692f3ab15Sopenharmony_ci let secret = b"My secret message"; 73792f3ab15Sopenharmony_ci 73892f3ab15Sopenharmony_ci let mut ctx = CipherCtx::new().unwrap(); 73992f3ab15Sopenharmony_ci let mut encrypted_key = vec![]; 74092f3ab15Sopenharmony_ci let mut iv = vec![0; cipher.iv_length()]; 74192f3ab15Sopenharmony_ci let mut encrypted = vec![]; 74292f3ab15Sopenharmony_ci ctx.seal_init( 74392f3ab15Sopenharmony_ci Some(cipher), 74492f3ab15Sopenharmony_ci &[public_key], 74592f3ab15Sopenharmony_ci slice::from_mut(&mut encrypted_key), 74692f3ab15Sopenharmony_ci Some(&mut iv), 74792f3ab15Sopenharmony_ci ) 74892f3ab15Sopenharmony_ci .unwrap(); 74992f3ab15Sopenharmony_ci ctx.cipher_update_vec(secret, &mut encrypted).unwrap(); 75092f3ab15Sopenharmony_ci ctx.cipher_final_vec(&mut encrypted).unwrap(); 75192f3ab15Sopenharmony_ci 75292f3ab15Sopenharmony_ci let mut decrypted = vec![]; 75392f3ab15Sopenharmony_ci ctx.open_init(Some(cipher), &encrypted_key, Some(&iv), Some(&private_key)) 75492f3ab15Sopenharmony_ci .unwrap(); 75592f3ab15Sopenharmony_ci ctx.cipher_update_vec(&encrypted, &mut decrypted).unwrap(); 75692f3ab15Sopenharmony_ci ctx.cipher_final_vec(&mut decrypted).unwrap(); 75792f3ab15Sopenharmony_ci 75892f3ab15Sopenharmony_ci assert_eq!(secret, &decrypted[..]); 75992f3ab15Sopenharmony_ci } 76092f3ab15Sopenharmony_ci 76192f3ab15Sopenharmony_ci fn aes_128_cbc(cipher: &CipherRef) { 76292f3ab15Sopenharmony_ci // from https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf 76392f3ab15Sopenharmony_ci let key = hex::decode("2b7e151628aed2a6abf7158809cf4f3c").unwrap(); 76492f3ab15Sopenharmony_ci let iv = hex::decode("000102030405060708090a0b0c0d0e0f").unwrap(); 76592f3ab15Sopenharmony_ci let pt = hex::decode("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51") 76692f3ab15Sopenharmony_ci .unwrap(); 76792f3ab15Sopenharmony_ci let ct = hex::decode("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2") 76892f3ab15Sopenharmony_ci .unwrap(); 76992f3ab15Sopenharmony_ci 77092f3ab15Sopenharmony_ci let mut ctx = CipherCtx::new().unwrap(); 77192f3ab15Sopenharmony_ci 77292f3ab15Sopenharmony_ci ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv)) 77392f3ab15Sopenharmony_ci .unwrap(); 77492f3ab15Sopenharmony_ci ctx.set_padding(false); 77592f3ab15Sopenharmony_ci 77692f3ab15Sopenharmony_ci let mut buf = vec![]; 77792f3ab15Sopenharmony_ci ctx.cipher_update_vec(&pt, &mut buf).unwrap(); 77892f3ab15Sopenharmony_ci ctx.cipher_final_vec(&mut buf).unwrap(); 77992f3ab15Sopenharmony_ci 78092f3ab15Sopenharmony_ci assert_eq!(buf, ct); 78192f3ab15Sopenharmony_ci 78292f3ab15Sopenharmony_ci ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv)) 78392f3ab15Sopenharmony_ci .unwrap(); 78492f3ab15Sopenharmony_ci ctx.set_padding(false); 78592f3ab15Sopenharmony_ci 78692f3ab15Sopenharmony_ci let mut buf = vec![]; 78792f3ab15Sopenharmony_ci ctx.cipher_update_vec(&ct, &mut buf).unwrap(); 78892f3ab15Sopenharmony_ci ctx.cipher_final_vec(&mut buf).unwrap(); 78992f3ab15Sopenharmony_ci 79092f3ab15Sopenharmony_ci assert_eq!(buf, pt); 79192f3ab15Sopenharmony_ci } 79292f3ab15Sopenharmony_ci 79392f3ab15Sopenharmony_ci #[test] 79492f3ab15Sopenharmony_ci #[cfg(ossl300)] 79592f3ab15Sopenharmony_ci fn fetched_aes_128_cbc() { 79692f3ab15Sopenharmony_ci let cipher = Cipher::fetch(None, "AES-128-CBC", None).unwrap(); 79792f3ab15Sopenharmony_ci aes_128_cbc(&cipher); 79892f3ab15Sopenharmony_ci } 79992f3ab15Sopenharmony_ci 80092f3ab15Sopenharmony_ci #[test] 80192f3ab15Sopenharmony_ci fn default_aes_128_cbc() { 80292f3ab15Sopenharmony_ci let cipher = Cipher::aes_128_cbc(); 80392f3ab15Sopenharmony_ci aes_128_cbc(cipher); 80492f3ab15Sopenharmony_ci } 80592f3ab15Sopenharmony_ci 80692f3ab15Sopenharmony_ci #[test] 80792f3ab15Sopenharmony_ci fn test_stream_ciphers() { 80892f3ab15Sopenharmony_ci test_stream_cipher(Cipher::aes_192_ctr()); 80992f3ab15Sopenharmony_ci test_stream_cipher(Cipher::aes_256_ctr()); 81092f3ab15Sopenharmony_ci } 81192f3ab15Sopenharmony_ci 81292f3ab15Sopenharmony_ci fn test_stream_cipher(cipher: &'static CipherRef) { 81392f3ab15Sopenharmony_ci let mut key = vec![0; cipher.key_length()]; 81492f3ab15Sopenharmony_ci rand_bytes(&mut key).unwrap(); 81592f3ab15Sopenharmony_ci let mut iv = vec![0; cipher.iv_length()]; 81692f3ab15Sopenharmony_ci rand_bytes(&mut iv).unwrap(); 81792f3ab15Sopenharmony_ci 81892f3ab15Sopenharmony_ci let mut ctx = CipherCtx::new().unwrap(); 81992f3ab15Sopenharmony_ci 82092f3ab15Sopenharmony_ci ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv)) 82192f3ab15Sopenharmony_ci .unwrap(); 82292f3ab15Sopenharmony_ci ctx.set_padding(false); 82392f3ab15Sopenharmony_ci 82492f3ab15Sopenharmony_ci assert_eq!( 82592f3ab15Sopenharmony_ci 1, 82692f3ab15Sopenharmony_ci cipher.block_size(), 82792f3ab15Sopenharmony_ci "Need a stream cipher, not a block cipher" 82892f3ab15Sopenharmony_ci ); 82992f3ab15Sopenharmony_ci 83092f3ab15Sopenharmony_ci // update cipher with non-full block 83192f3ab15Sopenharmony_ci // this is a streaming cipher so the number of output bytes 83292f3ab15Sopenharmony_ci // will be the same as the number of input bytes 83392f3ab15Sopenharmony_ci let mut output = vec![0; 32]; 83492f3ab15Sopenharmony_ci let outlen = ctx 83592f3ab15Sopenharmony_ci .cipher_update(&[1; 15], Some(&mut output[0..15])) 83692f3ab15Sopenharmony_ci .unwrap(); 83792f3ab15Sopenharmony_ci assert_eq!(15, outlen); 83892f3ab15Sopenharmony_ci 83992f3ab15Sopenharmony_ci // update cipher with missing bytes from the previous block 84092f3ab15Sopenharmony_ci // as previously it will output the same number of bytes as 84192f3ab15Sopenharmony_ci // the input 84292f3ab15Sopenharmony_ci let outlen = ctx 84392f3ab15Sopenharmony_ci .cipher_update(&[1; 17], Some(&mut output[15..])) 84492f3ab15Sopenharmony_ci .unwrap(); 84592f3ab15Sopenharmony_ci assert_eq!(17, outlen); 84692f3ab15Sopenharmony_ci 84792f3ab15Sopenharmony_ci ctx.cipher_final_vec(&mut vec![0; 0]).unwrap(); 84892f3ab15Sopenharmony_ci 84992f3ab15Sopenharmony_ci // encrypt again, but use in-place encryption this time 85092f3ab15Sopenharmony_ci // First reset the IV 85192f3ab15Sopenharmony_ci ctx.encrypt_init(None, None, Some(&iv)).unwrap(); 85292f3ab15Sopenharmony_ci ctx.set_padding(false); 85392f3ab15Sopenharmony_ci let mut data_inplace: [u8; 32] = [1; 32]; 85492f3ab15Sopenharmony_ci let outlen = ctx 85592f3ab15Sopenharmony_ci .cipher_update_inplace(&mut data_inplace[0..15], 15) 85692f3ab15Sopenharmony_ci .unwrap(); 85792f3ab15Sopenharmony_ci assert_eq!(15, outlen); 85892f3ab15Sopenharmony_ci 85992f3ab15Sopenharmony_ci let outlen = ctx 86092f3ab15Sopenharmony_ci .cipher_update_inplace(&mut data_inplace[15..32], 17) 86192f3ab15Sopenharmony_ci .unwrap(); 86292f3ab15Sopenharmony_ci assert_eq!(17, outlen); 86392f3ab15Sopenharmony_ci 86492f3ab15Sopenharmony_ci ctx.cipher_final(&mut [0u8; 0]).unwrap(); 86592f3ab15Sopenharmony_ci 86692f3ab15Sopenharmony_ci // Check that the resulting data is encrypted in the same manner 86792f3ab15Sopenharmony_ci assert_eq!(data_inplace.as_slice(), output.as_slice()); 86892f3ab15Sopenharmony_ci 86992f3ab15Sopenharmony_ci // try to decrypt 87092f3ab15Sopenharmony_ci ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv)) 87192f3ab15Sopenharmony_ci .unwrap(); 87292f3ab15Sopenharmony_ci ctx.set_padding(false); 87392f3ab15Sopenharmony_ci 87492f3ab15Sopenharmony_ci // update cipher with non-full block 87592f3ab15Sopenharmony_ci // expect that the output for stream cipher will contain 87692f3ab15Sopenharmony_ci // the same number of bytes as the input 87792f3ab15Sopenharmony_ci let mut output_decrypted = vec![0; 32]; 87892f3ab15Sopenharmony_ci let outlen = ctx 87992f3ab15Sopenharmony_ci .cipher_update(&output[0..15], Some(&mut output_decrypted[0..15])) 88092f3ab15Sopenharmony_ci .unwrap(); 88192f3ab15Sopenharmony_ci assert_eq!(15, outlen); 88292f3ab15Sopenharmony_ci 88392f3ab15Sopenharmony_ci let outlen = ctx 88492f3ab15Sopenharmony_ci .cipher_update(&output[15..], Some(&mut output_decrypted[15..])) 88592f3ab15Sopenharmony_ci .unwrap(); 88692f3ab15Sopenharmony_ci assert_eq!(17, outlen); 88792f3ab15Sopenharmony_ci 88892f3ab15Sopenharmony_ci ctx.cipher_final_vec(&mut vec![0; 0]).unwrap(); 88992f3ab15Sopenharmony_ci // check if the decrypted blocks are the same as input (all ones) 89092f3ab15Sopenharmony_ci assert_eq!(output_decrypted, vec![1; 32]); 89192f3ab15Sopenharmony_ci 89292f3ab15Sopenharmony_ci // decrypt again, but now the output in-place 89392f3ab15Sopenharmony_ci ctx.decrypt_init(None, None, Some(&iv)).unwrap(); 89492f3ab15Sopenharmony_ci ctx.set_padding(false); 89592f3ab15Sopenharmony_ci 89692f3ab15Sopenharmony_ci let outlen = ctx.cipher_update_inplace(&mut output[0..15], 15).unwrap(); 89792f3ab15Sopenharmony_ci assert_eq!(15, outlen); 89892f3ab15Sopenharmony_ci 89992f3ab15Sopenharmony_ci let outlen = ctx.cipher_update_inplace(&mut output[15..], 17).unwrap(); 90092f3ab15Sopenharmony_ci assert_eq!(17, outlen); 90192f3ab15Sopenharmony_ci 90292f3ab15Sopenharmony_ci ctx.cipher_final_vec(&mut vec![0; 0]).unwrap(); 90392f3ab15Sopenharmony_ci assert_eq!(output_decrypted, output); 90492f3ab15Sopenharmony_ci } 90592f3ab15Sopenharmony_ci 90692f3ab15Sopenharmony_ci #[test] 90792f3ab15Sopenharmony_ci #[should_panic(expected = "Output buffer size should be at least 33 bytes.")] 90892f3ab15Sopenharmony_ci fn full_block_updates_aes_128() { 90992f3ab15Sopenharmony_ci output_buffer_too_small(Cipher::aes_128_cbc()); 91092f3ab15Sopenharmony_ci } 91192f3ab15Sopenharmony_ci 91292f3ab15Sopenharmony_ci #[test] 91392f3ab15Sopenharmony_ci #[should_panic(expected = "Output buffer size should be at least 33 bytes.")] 91492f3ab15Sopenharmony_ci fn full_block_updates_aes_256() { 91592f3ab15Sopenharmony_ci output_buffer_too_small(Cipher::aes_256_cbc()); 91692f3ab15Sopenharmony_ci } 91792f3ab15Sopenharmony_ci 91892f3ab15Sopenharmony_ci #[test] 91992f3ab15Sopenharmony_ci #[should_panic(expected = "Output buffer size should be at least 17 bytes.")] 92092f3ab15Sopenharmony_ci fn full_block_updates_3des() { 92192f3ab15Sopenharmony_ci output_buffer_too_small(Cipher::des_ede3_cbc()); 92292f3ab15Sopenharmony_ci } 92392f3ab15Sopenharmony_ci 92492f3ab15Sopenharmony_ci fn output_buffer_too_small(cipher: &'static CipherRef) { 92592f3ab15Sopenharmony_ci let mut key = vec![0; cipher.key_length()]; 92692f3ab15Sopenharmony_ci rand_bytes(&mut key).unwrap(); 92792f3ab15Sopenharmony_ci let mut iv = vec![0; cipher.iv_length()]; 92892f3ab15Sopenharmony_ci rand_bytes(&mut iv).unwrap(); 92992f3ab15Sopenharmony_ci 93092f3ab15Sopenharmony_ci let mut ctx = CipherCtx::new().unwrap(); 93192f3ab15Sopenharmony_ci 93292f3ab15Sopenharmony_ci ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv)) 93392f3ab15Sopenharmony_ci .unwrap(); 93492f3ab15Sopenharmony_ci ctx.set_padding(false); 93592f3ab15Sopenharmony_ci 93692f3ab15Sopenharmony_ci let block_size = cipher.block_size(); 93792f3ab15Sopenharmony_ci assert!(block_size > 1, "Need a block cipher, not a stream cipher"); 93892f3ab15Sopenharmony_ci 93992f3ab15Sopenharmony_ci ctx.cipher_update(&vec![0; block_size + 1], Some(&mut vec![0; block_size - 1])) 94092f3ab15Sopenharmony_ci .unwrap(); 94192f3ab15Sopenharmony_ci } 94292f3ab15Sopenharmony_ci 94392f3ab15Sopenharmony_ci #[cfg(ossl102)] 94492f3ab15Sopenharmony_ci fn cipher_wrap_test(cipher: &CipherRef, pt: &str, ct: &str, key: &str, iv: Option<&str>) { 94592f3ab15Sopenharmony_ci let pt = hex::decode(pt).unwrap(); 94692f3ab15Sopenharmony_ci let key = hex::decode(key).unwrap(); 94792f3ab15Sopenharmony_ci let expected = hex::decode(ct).unwrap(); 94892f3ab15Sopenharmony_ci let iv = iv.map(|v| hex::decode(v).unwrap()); 94992f3ab15Sopenharmony_ci let padding = 8 - pt.len() % 8; 95092f3ab15Sopenharmony_ci let mut computed = vec![0; pt.len() + padding + cipher.block_size() * 2]; 95192f3ab15Sopenharmony_ci let mut ctx = CipherCtx::new().unwrap(); 95292f3ab15Sopenharmony_ci 95392f3ab15Sopenharmony_ci ctx.set_flags(CipherCtxFlags::FLAG_WRAP_ALLOW); 95492f3ab15Sopenharmony_ci ctx.encrypt_init(Some(cipher), Some(&key), iv.as_deref()) 95592f3ab15Sopenharmony_ci .unwrap(); 95692f3ab15Sopenharmony_ci 95792f3ab15Sopenharmony_ci let count = ctx.cipher_update(&pt, Some(&mut computed)).unwrap(); 95892f3ab15Sopenharmony_ci let rest = ctx.cipher_final(&mut computed[count..]).unwrap(); 95992f3ab15Sopenharmony_ci computed.truncate(count + rest); 96092f3ab15Sopenharmony_ci 96192f3ab15Sopenharmony_ci if computed != expected { 96292f3ab15Sopenharmony_ci println!("Computed: {}", hex::encode(&computed)); 96392f3ab15Sopenharmony_ci println!("Expected: {}", hex::encode(&expected)); 96492f3ab15Sopenharmony_ci if computed.len() != expected.len() { 96592f3ab15Sopenharmony_ci println!( 96692f3ab15Sopenharmony_ci "Lengths differ: {} in computed vs {} expected", 96792f3ab15Sopenharmony_ci computed.len(), 96892f3ab15Sopenharmony_ci expected.len() 96992f3ab15Sopenharmony_ci ); 97092f3ab15Sopenharmony_ci } 97192f3ab15Sopenharmony_ci panic!("test failure"); 97292f3ab15Sopenharmony_ci } 97392f3ab15Sopenharmony_ci } 97492f3ab15Sopenharmony_ci 97592f3ab15Sopenharmony_ci #[test] 97692f3ab15Sopenharmony_ci #[cfg(ossl102)] 97792f3ab15Sopenharmony_ci fn test_aes128_wrap() { 97892f3ab15Sopenharmony_ci let pt = "00112233445566778899aabbccddeeff"; 97992f3ab15Sopenharmony_ci let ct = "7940ff694448b5bb5139c959a4896832e55d69aa04daa27e"; 98092f3ab15Sopenharmony_ci let key = "2b7e151628aed2a6abf7158809cf4f3c"; 98192f3ab15Sopenharmony_ci let iv = "0001020304050607"; 98292f3ab15Sopenharmony_ci 98392f3ab15Sopenharmony_ci cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, Some(iv)); 98492f3ab15Sopenharmony_ci } 98592f3ab15Sopenharmony_ci 98692f3ab15Sopenharmony_ci #[test] 98792f3ab15Sopenharmony_ci #[cfg(ossl102)] 98892f3ab15Sopenharmony_ci fn test_aes128_wrap_default_iv() { 98992f3ab15Sopenharmony_ci let pt = "00112233445566778899aabbccddeeff"; 99092f3ab15Sopenharmony_ci let ct = "38f1215f0212526f8a70b51955b9fbdc9fe3041d9832306e"; 99192f3ab15Sopenharmony_ci let key = "2b7e151628aed2a6abf7158809cf4f3c"; 99292f3ab15Sopenharmony_ci 99392f3ab15Sopenharmony_ci cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, None); 99492f3ab15Sopenharmony_ci } 99592f3ab15Sopenharmony_ci 99692f3ab15Sopenharmony_ci #[test] 99792f3ab15Sopenharmony_ci #[cfg(ossl110)] 99892f3ab15Sopenharmony_ci fn test_aes128_wrap_pad() { 99992f3ab15Sopenharmony_ci let pt = "00112233445566778899aabbccddee"; 100092f3ab15Sopenharmony_ci let ct = "f13998f5ab32ef82a1bdbcbe585e1d837385b529572a1e1b"; 100192f3ab15Sopenharmony_ci let key = "2b7e151628aed2a6abf7158809cf4f3c"; 100292f3ab15Sopenharmony_ci let iv = "00010203"; 100392f3ab15Sopenharmony_ci 100492f3ab15Sopenharmony_ci cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, Some(iv)); 100592f3ab15Sopenharmony_ci } 100692f3ab15Sopenharmony_ci 100792f3ab15Sopenharmony_ci #[test] 100892f3ab15Sopenharmony_ci #[cfg(ossl110)] 100992f3ab15Sopenharmony_ci fn test_aes128_wrap_pad_default_iv() { 101092f3ab15Sopenharmony_ci let pt = "00112233445566778899aabbccddee"; 101192f3ab15Sopenharmony_ci let ct = "3a501085fb8cf66f4186b7df851914d471ed823411598add"; 101292f3ab15Sopenharmony_ci let key = "2b7e151628aed2a6abf7158809cf4f3c"; 101392f3ab15Sopenharmony_ci 101492f3ab15Sopenharmony_ci cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, None); 101592f3ab15Sopenharmony_ci } 101692f3ab15Sopenharmony_ci 101792f3ab15Sopenharmony_ci #[test] 101892f3ab15Sopenharmony_ci #[cfg(ossl102)] 101992f3ab15Sopenharmony_ci fn test_aes192_wrap() { 102092f3ab15Sopenharmony_ci let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b"; 102192f3ab15Sopenharmony_ci let ct = "83b89142dfeeb4871e078bfb81134d33e23fedc19b03a1cf689973d3831b6813"; 102292f3ab15Sopenharmony_ci let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; 102392f3ab15Sopenharmony_ci let iv = "0001020304050607"; 102492f3ab15Sopenharmony_ci 102592f3ab15Sopenharmony_ci cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, Some(iv)); 102692f3ab15Sopenharmony_ci } 102792f3ab15Sopenharmony_ci 102892f3ab15Sopenharmony_ci #[test] 102992f3ab15Sopenharmony_ci #[cfg(ossl102)] 103092f3ab15Sopenharmony_ci fn test_aes192_wrap_default_iv() { 103192f3ab15Sopenharmony_ci let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b"; 103292f3ab15Sopenharmony_ci let ct = "c02c2cf11505d3e4851030d5534cbf5a1d7eca7ba8839adbf239756daf1b43e6"; 103392f3ab15Sopenharmony_ci let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; 103492f3ab15Sopenharmony_ci 103592f3ab15Sopenharmony_ci cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, None); 103692f3ab15Sopenharmony_ci } 103792f3ab15Sopenharmony_ci 103892f3ab15Sopenharmony_ci #[test] 103992f3ab15Sopenharmony_ci #[cfg(ossl110)] 104092f3ab15Sopenharmony_ci fn test_aes192_wrap_pad() { 104192f3ab15Sopenharmony_ci let pt = "00112233445566778899aabbccddee"; 104292f3ab15Sopenharmony_ci let ct = "b4f6bb167ef7caf061a74da82b36ad038ca057ab51e98d3a"; 104392f3ab15Sopenharmony_ci let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; 104492f3ab15Sopenharmony_ci let iv = "00010203"; 104592f3ab15Sopenharmony_ci 104692f3ab15Sopenharmony_ci cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, Some(iv)); 104792f3ab15Sopenharmony_ci } 104892f3ab15Sopenharmony_ci 104992f3ab15Sopenharmony_ci #[test] 105092f3ab15Sopenharmony_ci #[cfg(ossl110)] 105192f3ab15Sopenharmony_ci fn test_aes192_wrap_pad_default_iv() { 105292f3ab15Sopenharmony_ci let pt = "00112233445566778899aabbccddee"; 105392f3ab15Sopenharmony_ci let ct = "b2c37a28cc602753a7c944a4c2555a2df9c98b2eded5312e"; 105492f3ab15Sopenharmony_ci let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; 105592f3ab15Sopenharmony_ci 105692f3ab15Sopenharmony_ci cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, None); 105792f3ab15Sopenharmony_ci } 105892f3ab15Sopenharmony_ci 105992f3ab15Sopenharmony_ci #[test] 106092f3ab15Sopenharmony_ci #[cfg(ossl102)] 106192f3ab15Sopenharmony_ci fn test_aes256_wrap() { 106292f3ab15Sopenharmony_ci let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"; 106392f3ab15Sopenharmony_ci let ct = "cc05da2a7f56f7dd0c144231f90bce58648fa20a8278f5a6b7d13bba6aa57a33229d4333866b7fd6"; 106492f3ab15Sopenharmony_ci let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; 106592f3ab15Sopenharmony_ci let iv = "0001020304050607"; 106692f3ab15Sopenharmony_ci 106792f3ab15Sopenharmony_ci cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, Some(iv)); 106892f3ab15Sopenharmony_ci } 106992f3ab15Sopenharmony_ci 107092f3ab15Sopenharmony_ci #[test] 107192f3ab15Sopenharmony_ci #[cfg(ossl102)] 107292f3ab15Sopenharmony_ci fn test_aes256_wrap_default_iv() { 107392f3ab15Sopenharmony_ci let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"; 107492f3ab15Sopenharmony_ci let ct = "0b24f068b50e52bc6987868411c36e1b03900866ed12af81eb87cef70a8d1911731c1d7abf789d88"; 107592f3ab15Sopenharmony_ci let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; 107692f3ab15Sopenharmony_ci 107792f3ab15Sopenharmony_ci cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, None); 107892f3ab15Sopenharmony_ci } 107992f3ab15Sopenharmony_ci 108092f3ab15Sopenharmony_ci #[test] 108192f3ab15Sopenharmony_ci #[cfg(ossl110)] 108292f3ab15Sopenharmony_ci fn test_aes256_wrap_pad() { 108392f3ab15Sopenharmony_ci let pt = "00112233445566778899aabbccddee"; 108492f3ab15Sopenharmony_ci let ct = "91594e044ccc06130d60e6c84a996aa4f96a9faff8c5f6e7"; 108592f3ab15Sopenharmony_ci let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; 108692f3ab15Sopenharmony_ci let iv = "00010203"; 108792f3ab15Sopenharmony_ci 108892f3ab15Sopenharmony_ci cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, Some(iv)); 108992f3ab15Sopenharmony_ci } 109092f3ab15Sopenharmony_ci 109192f3ab15Sopenharmony_ci #[test] 109292f3ab15Sopenharmony_ci #[cfg(ossl110)] 109392f3ab15Sopenharmony_ci fn test_aes256_wrap_pad_default_iv() { 109492f3ab15Sopenharmony_ci let pt = "00112233445566778899aabbccddee"; 109592f3ab15Sopenharmony_ci let ct = "dc3c166a854afd68aea624a4272693554bf2e4fcbae602cd"; 109692f3ab15Sopenharmony_ci let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; 109792f3ab15Sopenharmony_ci 109892f3ab15Sopenharmony_ci cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, None); 109992f3ab15Sopenharmony_ci } 110092f3ab15Sopenharmony_ci} 1101