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