Skip to main content

openssl/
cipher_ctx.rs

1//! The symmetric encryption context.
2//!
3//! # Examples
4//!
5//! Encrypt data with AES128 CBC
6//!
7//! ```
8//! use openssl::cipher::Cipher;
9//! use openssl::cipher_ctx::CipherCtx;
10//!
11//! let cipher = Cipher::aes_128_cbc();
12//! let data = b"Some Crypto Text";
13//! let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
14//! let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
15//!
16//! let mut ctx = CipherCtx::new().unwrap();
17//! ctx.encrypt_init(Some(cipher), Some(key), Some(iv)).unwrap();
18//!
19//! let mut ciphertext = vec![];
20//! ctx.cipher_update_vec(data, &mut ciphertext).unwrap();
21//! ctx.cipher_final_vec(&mut ciphertext).unwrap();
22//!
23//! assert_eq!(
24//!     b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\x87\x4D\
25//!       \xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1",
26//!     &ciphertext[..],
27//! );
28//! ```
29//!
30//! Decrypt data with AES128 CBC
31//!
32//! ```
33//! use openssl::cipher::Cipher;
34//! use openssl::cipher_ctx::CipherCtx;
35//!
36//! let cipher = Cipher::aes_128_cbc();
37//! let data = b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\
38//!              \x87\x4D\xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1";
39//! let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
40//! let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
41//!
42//! let mut ctx = CipherCtx::new().unwrap();
43//! ctx.decrypt_init(Some(cipher), Some(key), Some(iv)).unwrap();
44//!
45//! let mut plaintext = vec![];
46//! ctx.cipher_update_vec(data, &mut plaintext).unwrap();
47//! ctx.cipher_final_vec(&mut plaintext).unwrap();
48//!
49//! assert_eq!(b"Some Crypto Text", &plaintext[..]);
50//! ```
51#![warn(missing_docs)]
52
53use crate::cipher::CipherRef;
54use crate::error::ErrorStack;
55#[cfg(not(any(boringssl, awslc)))]
56use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef};
57use crate::{cvt, cvt_p};
58#[cfg(ossl110)]
59use bitflags::bitflags;
60use cfg_if::cfg_if;
61use foreign_types::{ForeignType, ForeignTypeRef};
62use libc::{c_int, c_uchar};
63use openssl_macros::corresponds;
64use std::convert::{TryFrom, TryInto};
65use std::ptr;
66
67cfg_if! {
68    if #[cfg(ossl300)] {
69        use ffi::EVP_CIPHER_CTX_get0_cipher;
70    } else {
71        use ffi::EVP_CIPHER_CTX_cipher as EVP_CIPHER_CTX_get0_cipher;
72    }
73}
74
75foreign_type_and_impl_send_sync! {
76    type CType = ffi::EVP_CIPHER_CTX;
77    fn drop = ffi::EVP_CIPHER_CTX_free;
78
79    /// A context object used to perform symmetric encryption operations.
80    pub struct CipherCtx;
81    /// A reference to a [`CipherCtx`].
82    pub struct CipherCtxRef;
83}
84
85#[cfg(ossl110)]
86bitflags! {
87    /// Flags for `EVP_CIPHER_CTX`.
88    pub struct CipherCtxFlags : c_int {
89        /// The flag used to opt into AES key wrap ciphers.
90        const FLAG_WRAP_ALLOW = ffi::EVP_CIPHER_CTX_FLAG_WRAP_ALLOW;
91    }
92}
93
94impl CipherCtx {
95    /// Creates a new context.
96    #[corresponds(EVP_CIPHER_CTX_new)]
97    pub fn new() -> Result<Self, ErrorStack> {
98        ffi::init();
99
100        unsafe {
101            let ptr = cvt_p(ffi::EVP_CIPHER_CTX_new())?;
102            Ok(CipherCtx::from_ptr(ptr))
103        }
104    }
105}
106
107impl CipherCtxRef {
108    #[corresponds(EVP_CIPHER_CTX_copy)]
109    pub fn copy(&mut self, src: &CipherCtxRef) -> Result<(), ErrorStack> {
110        unsafe {
111            cvt(ffi::EVP_CIPHER_CTX_copy(self.as_ptr(), src.as_ptr()))?;
112            Ok(())
113        }
114    }
115
116    /// Initializes the context for encryption.
117    ///
118    /// Normally this is called once to set all of the cipher, key, and IV. However, this process can be split up
119    /// by first setting the cipher with no key or IV and then setting the key and IV with no cipher. This can be used
120    /// to, for example, use a nonstandard IV size.
121    ///
122    /// # Panics
123    ///
124    /// Panics if the key buffer is smaller than the key size of the cipher, the IV buffer is smaller than the IV size
125    /// of the cipher, or if a key or IV is provided before a cipher.
126    #[corresponds(EVP_EncryptInit_ex)]
127    pub fn encrypt_init(
128        &mut self,
129        type_: Option<&CipherRef>,
130        key: Option<&[u8]>,
131        iv: Option<&[u8]>,
132    ) -> Result<(), ErrorStack> {
133        self.cipher_init(type_, key, iv, ffi::EVP_EncryptInit_ex)
134    }
135
136    /// Initializes the context for decryption.
137    ///
138    /// Normally this is called once to set all of the cipher, key, and IV. However, this process can be split up
139    /// by first setting the cipher with no key or IV and then setting the key and IV with no cipher. This can be used
140    /// to, for example, use a nonstandard IV size.
141    ///
142    /// # Panics
143    ///
144    /// Panics if the key buffer is smaller than the key size of the cipher, the IV buffer is smaller than the IV size
145    /// of the cipher, or if a key or IV is provided before a cipher.
146    #[corresponds(EVP_DecryptInit_ex)]
147    pub fn decrypt_init(
148        &mut self,
149        type_: Option<&CipherRef>,
150        key: Option<&[u8]>,
151        iv: Option<&[u8]>,
152    ) -> Result<(), ErrorStack> {
153        self.cipher_init(type_, key, iv, ffi::EVP_DecryptInit_ex)
154    }
155
156    fn cipher_init(
157        &mut self,
158        type_: Option<&CipherRef>,
159        key: Option<&[u8]>,
160        iv: Option<&[u8]>,
161        f: unsafe extern "C" fn(
162            *mut ffi::EVP_CIPHER_CTX,
163            *const ffi::EVP_CIPHER,
164            *mut ffi::ENGINE,
165            *const c_uchar,
166            *const c_uchar,
167        ) -> c_int,
168    ) -> Result<(), ErrorStack> {
169        if let Some(key) = key {
170            let key_len = type_.map_or_else(|| self.key_length(), |c| c.key_length());
171            assert!(key_len <= key.len());
172        }
173
174        if let Some(iv) = iv {
175            let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
176            assert!(iv_len <= iv.len());
177        }
178
179        unsafe {
180            cvt(f(
181                self.as_ptr(),
182                type_.map_or(ptr::null(), |p| p.as_ptr()),
183                ptr::null_mut(),
184                key.map_or(ptr::null(), |k| k.as_ptr()),
185                iv.map_or(ptr::null(), |iv| iv.as_ptr()),
186            ))?;
187        }
188
189        Ok(())
190    }
191
192    /// Initializes the context to perform envelope encryption.
193    ///
194    /// Normally this is called once to set both the cipher and public keys. However, this process may be split up by
195    /// first providing the cipher with no public keys and then setting the public keys with no cipher.
196    ///
197    /// `encrypted_keys` will contain the generated symmetric key encrypted with each corresponding asymmetric private
198    /// key. The generated IV will be written to `iv`.
199    ///
200    /// # Panics
201    ///
202    /// Panics if `pub_keys` is not the same size as `encrypted_keys`, the IV buffer is smaller than the cipher's IV
203    /// size, or if an IV is provided before the cipher.
204    #[corresponds(EVP_SealInit)]
205    #[cfg(not(any(boringssl, awslc)))]
206    pub fn seal_init<T>(
207        &mut self,
208        type_: Option<&CipherRef>,
209        pub_keys: &[PKey<T>],
210        encrypted_keys: &mut [Vec<u8>],
211        iv: Option<&mut [u8]>,
212    ) -> Result<(), ErrorStack>
213    where
214        T: HasPublic,
215    {
216        assert_eq!(pub_keys.len(), encrypted_keys.len());
217        if !pub_keys.is_empty() {
218            let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
219            assert!(iv.as_ref().map_or(0, |b| b.len()) >= iv_len);
220        }
221
222        for (pub_key, buf) in pub_keys.iter().zip(&mut *encrypted_keys) {
223            buf.resize(pub_key.size(), 0);
224        }
225
226        let mut keys = encrypted_keys
227            .iter_mut()
228            .map(|b| b.as_mut_ptr())
229            .collect::<Vec<_>>();
230        let mut key_lengths = vec![0; pub_keys.len()];
231        let pub_keys_len = i32::try_from(pub_keys.len()).unwrap();
232
233        unsafe {
234            cvt(ffi::EVP_SealInit(
235                self.as_ptr(),
236                type_.map_or(ptr::null(), |p| p.as_ptr()),
237                keys.as_mut_ptr(),
238                key_lengths.as_mut_ptr(),
239                iv.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
240                pub_keys.as_ptr() as *mut _,
241                pub_keys_len,
242            ))?;
243        }
244
245        for (buf, len) in encrypted_keys.iter_mut().zip(key_lengths) {
246            buf.truncate(len as usize);
247        }
248
249        Ok(())
250    }
251
252    /// Initializes the context to perform envelope decryption.
253    ///
254    /// Normally this is called once with all of the arguments present. However, this process may be split up by first
255    /// providing the cipher alone and then after providing the rest of the arguments in a second call.
256    ///
257    /// # Panics
258    ///
259    /// Panics if the IV buffer is smaller than the cipher's required IV size or if the IV is provided before the
260    /// cipher.
261    #[corresponds(EVP_OpenInit)]
262    #[cfg(not(any(boringssl, awslc)))]
263    pub fn open_init<T>(
264        &mut self,
265        type_: Option<&CipherRef>,
266        encrypted_key: &[u8],
267        iv: Option<&[u8]>,
268        priv_key: Option<&PKeyRef<T>>,
269    ) -> Result<(), ErrorStack>
270    where
271        T: HasPrivate,
272    {
273        if priv_key.is_some() {
274            let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
275            assert!(iv.map_or(0, |b| b.len()) >= iv_len);
276        }
277
278        let len = c_int::try_from(encrypted_key.len()).unwrap();
279        unsafe {
280            cvt(ffi::EVP_OpenInit(
281                self.as_ptr(),
282                type_.map_or(ptr::null(), |p| p.as_ptr()),
283                encrypted_key.as_ptr(),
284                len,
285                iv.map_or(ptr::null(), |b| b.as_ptr()),
286                priv_key.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
287            ))?;
288        }
289
290        Ok(())
291    }
292
293    fn assert_cipher(&self) {
294        unsafe {
295            assert!(!EVP_CIPHER_CTX_get0_cipher(self.as_ptr()).is_null());
296        }
297    }
298
299    #[cfg(not(any(boringssl, awslc)))]
300    fn is_wrap_mode(&self) -> bool {
301        unsafe {
302            let cipher = EVP_CIPHER_CTX_get0_cipher(self.as_ptr());
303            if cipher.is_null() {
304                return false;
305            }
306            ffi::EVP_CIPHER_flags(cipher) & ffi::EVP_CIPH_MODE == ffi::EVP_CIPH_WRAP_MODE
307        }
308    }
309
310    #[cfg(any(boringssl, awslc))]
311    fn is_wrap_mode(&self) -> bool {
312        false
313    }
314
315    fn cipher_update_output_size(&self, input_len: usize) -> usize {
316        // Wrap-mode ciphers have EVP_CIPH_FLAG_CUSTOM_CIPHER set and emit their
317        // entire output (plaintext rounded up to 8 bytes + 8-byte IV) in a
318        // single update call, so the usual `inlen + block_size` bound is too
319        // small for key-wrap-with-padding inputs that aren't already a
320        // multiple of 8.
321        if self.is_wrap_mode() {
322            return input_len.saturating_add(7) / 8 * 8 + 8;
323        }
324        let mut block_size = self.block_size();
325        if block_size == 1 {
326            block_size = 0;
327        }
328        input_len + block_size
329    }
330
331    /// Returns the block size of the context's cipher.
332    ///
333    /// Stream ciphers will report a block size of 1.
334    ///
335    /// # Panics
336    ///
337    /// Panics if the context has not been initialized with a cipher.
338    #[corresponds(EVP_CIPHER_CTX_block_size)]
339    pub fn block_size(&self) -> usize {
340        self.assert_cipher();
341
342        unsafe { ffi::EVP_CIPHER_CTX_block_size(self.as_ptr()) as usize }
343    }
344
345    /// Returns the key length of the context's cipher.
346    ///
347    /// # Panics
348    ///
349    /// Panics if the context has not been initialized with a cipher.
350    #[corresponds(EVP_CIPHER_CTX_key_length)]
351    pub fn key_length(&self) -> usize {
352        self.assert_cipher();
353
354        unsafe { ffi::EVP_CIPHER_CTX_key_length(self.as_ptr()) as usize }
355    }
356
357    /// Generates a random key based on the configured cipher.
358    ///
359    /// # Panics
360    ///
361    /// Panics if the context has not been initialized with a cipher or if the buffer is smaller than the cipher's key
362    /// length.
363    #[corresponds(EVP_CIPHER_CTX_rand_key)]
364    #[cfg(not(any(boringssl, awslc)))]
365    pub fn rand_key(&self, buf: &mut [u8]) -> Result<(), ErrorStack> {
366        assert!(buf.len() >= self.key_length());
367
368        unsafe {
369            cvt(ffi::EVP_CIPHER_CTX_rand_key(
370                self.as_ptr(),
371                buf.as_mut_ptr(),
372            ))?;
373        }
374
375        Ok(())
376    }
377
378    /// Sets the length of the key expected by the context.
379    ///
380    /// Only some ciphers support configurable key lengths.
381    ///
382    /// # Panics
383    ///
384    /// Panics if the context has not been initialized with a cipher.
385    #[corresponds(EVP_CIPHER_CTX_set_key_length)]
386    pub fn set_key_length(&mut self, len: usize) -> Result<(), ErrorStack> {
387        self.assert_cipher();
388
389        unsafe {
390            cvt(ffi::EVP_CIPHER_CTX_set_key_length(
391                self.as_ptr(),
392                len.try_into().unwrap(),
393            ))?;
394        }
395
396        Ok(())
397    }
398
399    /// Returns the length of the IV expected by this context.
400    ///
401    /// Returns 0 if the cipher does not use an IV.
402    ///
403    /// # Panics
404    ///
405    /// Panics if the context has not been initialized with a cipher.
406    #[corresponds(EVP_CIPHER_CTX_iv_length)]
407    pub fn iv_length(&self) -> usize {
408        self.assert_cipher();
409
410        unsafe { ffi::EVP_CIPHER_CTX_iv_length(self.as_ptr()) as usize }
411    }
412
413    /// Returns the `num` parameter of the cipher.
414    ///
415    /// Built-in ciphers typically use this to track how much of the
416    /// current underlying block has been "used" already.
417    ///
418    /// # Panics
419    ///
420    /// Panics if the context has not been initialized with a cipher.
421    #[corresponds(EVP_CIPHER_CTX_num)]
422    #[cfg(ossl110)]
423    pub fn num(&self) -> usize {
424        self.assert_cipher();
425
426        unsafe { ffi::EVP_CIPHER_CTX_num(self.as_ptr()) as usize }
427    }
428
429    /// Sets the length of the IV expected by this context.
430    ///
431    /// Only some ciphers support configurable IV lengths.
432    ///
433    /// # Panics
434    ///
435    /// Panics if the context has not been initialized with a cipher.
436    #[corresponds(EVP_CIPHER_CTX_ctrl)]
437    pub fn set_iv_length(&mut self, len: usize) -> Result<(), ErrorStack> {
438        self.assert_cipher();
439
440        let len = c_int::try_from(len).unwrap();
441
442        unsafe {
443            cvt(ffi::EVP_CIPHER_CTX_ctrl(
444                self.as_ptr(),
445                ffi::EVP_CTRL_GCM_SET_IVLEN,
446                len,
447                ptr::null_mut(),
448            ))?;
449        }
450
451        Ok(())
452    }
453
454    /// Returns the length of the authentication tag expected by this context.
455    ///
456    /// Returns 0 if the cipher is not authenticated.
457    ///
458    /// # Panics
459    ///
460    /// Panics if the context has not been initialized with a cipher.
461    ///
462    /// Requires OpenSSL 3.0.0 or newer.
463    #[corresponds(EVP_CIPHER_CTX_get_tag_length)]
464    #[cfg(ossl300)]
465    pub fn tag_length(&self) -> usize {
466        self.assert_cipher();
467
468        unsafe { ffi::EVP_CIPHER_CTX_get_tag_length(self.as_ptr()) as usize }
469    }
470
471    /// Retrieves the calculated authentication tag from the context.
472    ///
473    /// This should be called after [`Self::cipher_final`], and is only supported by authenticated ciphers.
474    ///
475    /// The size of the buffer indicates the size of the tag. While some ciphers support a range of tag sizes, it is
476    /// recommended to pick the maximum size.
477    #[corresponds(EVP_CIPHER_CTX_ctrl)]
478    pub fn tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> {
479        let len = c_int::try_from(tag.len()).unwrap();
480
481        unsafe {
482            cvt(ffi::EVP_CIPHER_CTX_ctrl(
483                self.as_ptr(),
484                ffi::EVP_CTRL_GCM_GET_TAG,
485                len,
486                tag.as_mut_ptr() as *mut _,
487            ))?;
488        }
489
490        Ok(())
491    }
492
493    /// Sets the length of the generated authentication tag.
494    ///
495    /// This must be called when encrypting with a cipher in CCM mode to use a tag size other than the default.
496    #[corresponds(EVP_CIPHER_CTX_ctrl)]
497    pub fn set_tag_length(&mut self, len: usize) -> Result<(), ErrorStack> {
498        let len = c_int::try_from(len).unwrap();
499
500        unsafe {
501            cvt(ffi::EVP_CIPHER_CTX_ctrl(
502                self.as_ptr(),
503                ffi::EVP_CTRL_GCM_SET_TAG,
504                len,
505                ptr::null_mut(),
506            ))?;
507        }
508
509        Ok(())
510    }
511
512    /// Sets the authentication tag for verification during decryption.
513    #[corresponds(EVP_CIPHER_CTX_ctrl)]
514    pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> {
515        let len = c_int::try_from(tag.len()).unwrap();
516
517        unsafe {
518            cvt(ffi::EVP_CIPHER_CTX_ctrl(
519                self.as_ptr(),
520                ffi::EVP_CTRL_GCM_SET_TAG,
521                len,
522                tag.as_ptr() as *mut _,
523            ))?;
524        }
525
526        Ok(())
527    }
528
529    /// Enables or disables padding.
530    ///
531    /// If padding is disabled, the plaintext must be an exact multiple of the cipher's block size.
532    #[corresponds(EVP_CIPHER_CTX_set_padding)]
533    pub fn set_padding(&mut self, padding: bool) {
534        unsafe {
535            ffi::EVP_CIPHER_CTX_set_padding(self.as_ptr(), padding as c_int);
536        }
537    }
538
539    /// Sets the total length of plaintext data.
540    ///
541    /// This is required for ciphers operating in CCM mode.
542    #[corresponds(EVP_CipherUpdate)]
543    pub fn set_data_len(&mut self, len: usize) -> Result<(), ErrorStack> {
544        let len = c_int::try_from(len).unwrap();
545
546        unsafe {
547            cvt(ffi::EVP_CipherUpdate(
548                self.as_ptr(),
549                ptr::null_mut(),
550                &mut 0,
551                ptr::null(),
552                len,
553            ))?;
554        }
555
556        Ok(())
557    }
558
559    /// Set ctx flags.
560    ///
561    /// This function is currently used to enable AES key wrap feature supported by OpenSSL 1.1.0 or newer.
562    #[corresponds(EVP_CIPHER_CTX_set_flags)]
563    #[cfg(ossl110)]
564    pub fn set_flags(&mut self, flags: CipherCtxFlags) {
565        unsafe {
566            ffi::EVP_CIPHER_CTX_set_flags(self.as_ptr(), flags.bits());
567        }
568    }
569
570    /// Writes data into the context.
571    ///
572    /// Providing no output buffer will cause the input to be considered additional authenticated data (AAD).
573    ///
574    /// Returns the number of bytes written to `output`.
575    ///
576    /// # Panics
577    ///
578    /// Panics if `output` doesn't contain enough space for data to be
579    /// written.
580    #[corresponds(EVP_CipherUpdate)]
581    pub fn cipher_update(
582        &mut self,
583        input: &[u8],
584        output: Option<&mut [u8]>,
585    ) -> Result<usize, ErrorStack> {
586        if let Some(output) = &output {
587            let min_output_size = self.cipher_update_output_size(input.len());
588            assert!(
589                output.len() >= min_output_size,
590                "Output buffer size should be at least {} bytes.",
591                min_output_size
592            );
593        }
594
595        unsafe { self.cipher_update_unchecked(input, output) }
596    }
597
598    /// Writes data into the context.
599    ///
600    /// Providing no output buffer will cause the input to be considered additional authenticated data (AAD).
601    ///
602    /// Returns the number of bytes written to `output`.
603    ///
604    /// This function is the same as [`Self::cipher_update`] but with the
605    /// output size check removed. It can be used when the exact
606    /// buffer size control is maintained by the caller.
607    ///
608    /// # Safety
609    ///
610    /// The caller is expected to provide `output` buffer
611    /// large enough to contain correct number of bytes. For streaming
612    /// ciphers the output buffer size should be at least as big as
613    /// the input buffer. For block ciphers the size of the output
614    /// buffer depends on the state of partially updated blocks.
615    #[corresponds(EVP_CipherUpdate)]
616    pub unsafe fn cipher_update_unchecked(
617        &mut self,
618        input: &[u8],
619        output: Option<&mut [u8]>,
620    ) -> Result<usize, ErrorStack> {
621        let inlen = c_int::try_from(input.len()).unwrap();
622
623        let mut outlen = 0;
624
625        cvt(ffi::EVP_CipherUpdate(
626            self.as_ptr(),
627            output.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
628            &mut outlen,
629            input.as_ptr(),
630            inlen,
631        ))?;
632
633        Ok(outlen as usize)
634    }
635
636    /// Like [`Self::cipher_update`] except that it appends output to a [`Vec`].
637    pub fn cipher_update_vec(
638        &mut self,
639        input: &[u8],
640        output: &mut Vec<u8>,
641    ) -> Result<usize, ErrorStack> {
642        let base = output.len();
643        output.resize(base + self.cipher_update_output_size(input.len()), 0);
644        let len = self.cipher_update(input, Some(&mut output[base..]))?;
645        output.truncate(base + len);
646
647        Ok(len)
648    }
649
650    /// Like [`Self::cipher_update`] except that it writes output into the
651    /// `data` buffer. The `inlen` parameter specifies the number of bytes in
652    /// `data` that are considered the input. For streaming ciphers, the size of
653    /// `data` must be at least the input size. Otherwise, it must be at least
654    /// an additional block size larger.
655    ///
656    /// Note: Use [`Self::cipher_update`] with no output argument to write AAD.
657    ///
658    /// # Panics
659    ///
660    /// This function panics if the input size cannot be represented as `int` or
661    /// exceeds the buffer size, or if the output buffer does not contain enough
662    /// additional space.
663    #[corresponds(EVP_CipherUpdate)]
664    pub fn cipher_update_inplace(
665        &mut self,
666        data: &mut [u8],
667        inlen: usize,
668    ) -> Result<usize, ErrorStack> {
669        assert!(inlen <= data.len(), "Input size may not exceed buffer size");
670        let block_size = self.block_size();
671        if block_size != 1 {
672            assert!(
673                data.len() >= inlen + block_size,
674                "Output buffer size must be at least {} bytes.",
675                inlen + block_size
676            );
677        }
678
679        let inlen = c_int::try_from(inlen).unwrap();
680        let mut outlen = 0;
681        unsafe {
682            cvt(ffi::EVP_CipherUpdate(
683                self.as_ptr(),
684                data.as_mut_ptr(),
685                &mut outlen,
686                data.as_ptr(),
687                inlen,
688            ))
689        }?;
690
691        Ok(outlen as usize)
692    }
693
694    /// Finalizes the encryption or decryption process.
695    ///
696    /// Any remaining data will be written to the output buffer.
697    ///
698    /// Returns the number of bytes written to `output`.
699    ///
700    /// # Panics
701    ///
702    /// Panics if `output` is smaller than the cipher's block size.
703    #[corresponds(EVP_CipherFinal)]
704    pub fn cipher_final(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
705        let block_size = self.block_size();
706        if block_size > 1 {
707            assert!(output.len() >= block_size);
708        }
709
710        unsafe { self.cipher_final_unchecked(output) }
711    }
712
713    /// Finalizes the encryption or decryption process.
714    ///
715    /// Any remaining data will be written to the output buffer.
716    ///
717    /// Returns the number of bytes written to `output`.
718    ///
719    /// This function is the same as [`Self::cipher_final`] but with
720    /// the output buffer size check removed.
721    ///
722    /// # Safety
723    ///
724    /// The caller is expected to provide `output` buffer
725    /// large enough to contain correct number of bytes. For streaming
726    /// ciphers the output buffer can be empty, for block ciphers the
727    /// output buffer should be at least as big as the block.
728    #[corresponds(EVP_CipherFinal)]
729    pub unsafe fn cipher_final_unchecked(
730        &mut self,
731        output: &mut [u8],
732    ) -> Result<usize, ErrorStack> {
733        let mut outl = 0;
734
735        cvt(ffi::EVP_CipherFinal(
736            self.as_ptr(),
737            output.as_mut_ptr(),
738            &mut outl,
739        ))?;
740
741        Ok(outl as usize)
742    }
743
744    /// Like [`Self::cipher_final`] except that it appends output to a [`Vec`].
745    pub fn cipher_final_vec(&mut self, output: &mut Vec<u8>) -> Result<usize, ErrorStack> {
746        let base = output.len();
747        output.resize(base + self.block_size(), 0);
748        let len = self.cipher_final(&mut output[base..])?;
749        output.truncate(base + len);
750
751        Ok(len)
752    }
753}
754
755#[cfg(test)]
756mod test {
757    use super::*;
758    use crate::{cipher::Cipher, rand::rand_bytes};
759    #[cfg(not(any(boringssl, awslc)))]
760    use std::slice;
761
762    #[test]
763    #[cfg(not(any(boringssl, awslc)))]
764    fn seal_open() {
765        let private_pem = include_bytes!("../test/rsa.pem");
766        let public_pem = include_bytes!("../test/rsa.pem.pub");
767        let private_key = PKey::private_key_from_pem(private_pem).unwrap();
768        let public_key = PKey::public_key_from_pem(public_pem).unwrap();
769        let cipher = Cipher::aes_256_cbc();
770        let secret = b"My secret message";
771
772        let mut ctx = CipherCtx::new().unwrap();
773        let mut encrypted_key = vec![];
774        let mut iv = vec![0; cipher.iv_length()];
775        let mut encrypted = vec![];
776        ctx.seal_init(
777            Some(cipher),
778            &[public_key],
779            slice::from_mut(&mut encrypted_key),
780            Some(&mut iv),
781        )
782        .unwrap();
783        ctx.cipher_update_vec(secret, &mut encrypted).unwrap();
784        ctx.cipher_final_vec(&mut encrypted).unwrap();
785
786        let mut decrypted = vec![];
787        ctx.open_init(Some(cipher), &encrypted_key, Some(&iv), Some(&private_key))
788            .unwrap();
789        ctx.cipher_update_vec(&encrypted, &mut decrypted).unwrap();
790        ctx.cipher_final_vec(&mut decrypted).unwrap();
791
792        assert_eq!(secret, &decrypted[..]);
793    }
794
795    fn aes_128_cbc(cipher: &CipherRef) {
796        // from https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf
797        let key = hex::decode("2b7e151628aed2a6abf7158809cf4f3c").unwrap();
798        let iv = hex::decode("000102030405060708090a0b0c0d0e0f").unwrap();
799        let pt = hex::decode("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51")
800            .unwrap();
801        let ct = hex::decode("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2")
802            .unwrap();
803
804        let mut ctx = CipherCtx::new().unwrap();
805
806        ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
807            .unwrap();
808        ctx.set_padding(false);
809
810        let mut buf = vec![];
811        ctx.cipher_update_vec(&pt, &mut buf).unwrap();
812        ctx.cipher_final_vec(&mut buf).unwrap();
813
814        assert_eq!(buf, ct);
815
816        ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv))
817            .unwrap();
818        ctx.set_padding(false);
819
820        let mut buf = vec![];
821        ctx.cipher_update_vec(&ct, &mut buf).unwrap();
822        ctx.cipher_final_vec(&mut buf).unwrap();
823
824        assert_eq!(buf, pt);
825    }
826
827    #[test]
828    #[cfg(ossl300)]
829    fn fetched_aes_128_cbc() {
830        let cipher = Cipher::fetch(None, "AES-128-CBC", None).unwrap();
831        aes_128_cbc(&cipher);
832    }
833
834    #[test]
835    fn default_aes_128_cbc() {
836        let cipher = Cipher::aes_128_cbc();
837        aes_128_cbc(cipher);
838    }
839
840    #[cfg(not(boringssl))]
841    #[test]
842    fn default_aes_128_ccm() {
843        // from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/ccmtestvectors.zip
844        let cipher = Cipher::aes_128_ccm();
845        aes_ccm(
846            cipher,
847            "26511fb51fcfa75cb4b44da75a6e5a0e",
848            "ea98ec44f5a86715014783172e",
849            "4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10",
850            "e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810",
851            "1bf0ba0ebb20d8edba59f29a9371750c9c714078f73c335d",
852            "2f1322ac69b848b001476323aed84c47",
853        );
854    }
855
856    #[cfg(not(boringssl))]
857    #[test]
858    fn default_aes_192_ccm() {
859        // from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/ccmtestvectors.zip
860        let cipher = Cipher::aes_192_ccm();
861        aes_ccm(
862            cipher,
863            "26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886",
864            "ea98ec44f5a86715014783172e",
865            "4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10",
866            "e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810",
867            "30c154c616946eccc2e241d336ad33720953e449a0e6b0f0",
868            "dbf8e9464909bdf337e48093c082a10b",
869        );
870    }
871
872    #[cfg(not(boringssl))]
873    #[test]
874    fn default_aes_256_ccm() {
875        // from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/ccmtestvectors.zip
876        let cipher = Cipher::aes_256_ccm();
877        aes_ccm(
878            cipher,
879            "314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e",
880            "3542fbe0f59a6d5f3abf619b7d",
881            "c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed",
882            "dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8",
883            "39c2e8f6edfe663b90963b98eb79e2d4f7f28a5053ae8881",
884            "567a6b4426f1667136bed4a5e32a2bc1",
885        );
886    }
887
888    #[cfg(not(boringssl))]
889    fn aes_ccm(
890        cipher: &CipherRef,
891        key: &'static str,
892        iv: &'static str,
893        pt: &'static str,
894        aad: &'static str,
895        ct: &'static str,
896        tag: &'static str,
897    ) {
898        let key = hex::decode(key).unwrap();
899        let iv = hex::decode(iv).unwrap();
900        let pt = hex::decode(pt).unwrap();
901        let ct = hex::decode(ct).unwrap();
902        let aad = hex::decode(aad).unwrap();
903        let tag = hex::decode(tag).unwrap();
904
905        let mut ctx = CipherCtx::new().unwrap();
906
907        ctx.encrypt_init(Some(cipher), None, None).unwrap();
908        ctx.set_iv_length(iv.len()).unwrap();
909        ctx.set_tag_length(tag.len()).unwrap();
910        ctx.encrypt_init(None, Some(&key), Some(&iv)).unwrap();
911        ctx.set_data_len(pt.len()).unwrap();
912
913        let mut buf = vec![];
914        ctx.cipher_update(&aad, None).unwrap();
915        ctx.cipher_update_vec(&pt, &mut buf).unwrap();
916        ctx.cipher_final_vec(&mut buf).unwrap();
917        assert_eq!(buf, ct);
918
919        let mut out_tag = vec![0u8; tag.len()];
920        ctx.tag(&mut out_tag).unwrap();
921        assert_eq!(tag, out_tag);
922
923        ctx.decrypt_init(Some(cipher), None, None).unwrap();
924        ctx.set_iv_length(iv.len()).unwrap();
925        ctx.set_tag(&tag).unwrap();
926        ctx.decrypt_init(None, Some(&key), Some(&iv)).unwrap();
927        ctx.set_data_len(pt.len()).unwrap();
928
929        let mut buf = vec![];
930        ctx.cipher_update(&aad, None).unwrap();
931        ctx.cipher_update_vec(&ct, &mut buf).unwrap();
932        // Some older libraries don't support calling EVP_CipherFinal/EVP_DecryptFinal for CCM
933        // https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption#Authenticated_Decryption_using_CCM_mode
934        #[cfg(any(ossl111, awslc, boringssl))]
935        ctx.cipher_final_vec(&mut buf).unwrap();
936
937        assert_eq!(buf, pt);
938    }
939
940    #[cfg(not(any(boringssl, awslc)))]
941    #[test]
942    fn default_aes_128_xts() {
943        // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/XTSTestVectors.zip
944        let cipher = Cipher::aes_128_xts();
945        aes_xts(
946            cipher,
947            "a1b90cba3f06ac353b2c343876081762090923026e91771815f29dab01932f2f",
948            "4faef7117cda59c66e4b92013e768ad5",
949            "ebabce95b14d3c8d6fb350390790311c",
950            "778ae8b43cb98d5a825081d5be471c63",
951        );
952    }
953
954    #[cfg(not(boringssl))]
955    #[test]
956    fn default_aes_256_xts() {
957        // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/XTSTestVectors.zip
958        let cipher = Cipher::aes_256_xts();
959        aes_xts(cipher, "1ea661c58d943a0e4801e42f4b0947149e7f9f8e3e68d0c7505210bd311a0e7cd6e13ffdf2418d8d1911c004cda58da3d619b7e2b9141e58318eea392cf41b08", "adf8d92627464ad2f0428e84a9f87564", "2eedea52cd8215e1acc647e810bbc3642e87287f8d2e57e36c0a24fbc12a202e", "cbaad0e2f6cea3f50b37f934d46a9b130b9d54f07e34f36af793e86f73c6d7db");
960    }
961
962    #[cfg(not(boringssl))]
963    fn aes_xts(
964        cipher: &CipherRef,
965        key: &'static str,
966        i: &'static str,
967        pt: &'static str,
968        ct: &'static str,
969    ) {
970        let key = hex::decode(key).unwrap();
971        let i = hex::decode(i).unwrap();
972        let pt = hex::decode(pt).unwrap();
973        let ct = hex::decode(ct).unwrap();
974
975        let mut ctx = CipherCtx::new().unwrap();
976        ctx.encrypt_init(Some(cipher), Some(&key), Some(&i))
977            .unwrap();
978        let mut buf = vec![];
979        ctx.cipher_update_vec(&pt, &mut buf).unwrap();
980        ctx.cipher_final_vec(&mut buf).unwrap();
981
982        assert_eq!(ct, buf);
983
984        ctx.decrypt_init(Some(cipher), Some(&key), Some(&i))
985            .unwrap();
986        let mut buf = vec![];
987        ctx.cipher_update_vec(&ct, &mut buf).unwrap();
988        ctx.cipher_final_vec(&mut buf).unwrap();
989
990        assert_eq!(pt, buf);
991    }
992
993    #[test]
994    fn test_stream_ciphers() {
995        #[cfg(not(boringssl))]
996        {
997            test_stream_cipher(Cipher::aes_128_cfb1());
998            test_stream_cipher(Cipher::aes_128_cfb8());
999            test_stream_cipher(Cipher::aes_128_cfb128());
1000            test_stream_cipher(Cipher::aes_192_cfb1());
1001            test_stream_cipher(Cipher::aes_192_cfb8());
1002            test_stream_cipher(Cipher::aes_192_cfb128());
1003            test_stream_cipher(Cipher::aes_256_cfb1());
1004            test_stream_cipher(Cipher::aes_256_cfb8());
1005            test_stream_cipher(Cipher::aes_256_cfb128());
1006        }
1007        test_stream_cipher(Cipher::aes_192_ctr());
1008        test_stream_cipher(Cipher::aes_256_ctr());
1009    }
1010
1011    fn test_stream_cipher(cipher: &'static CipherRef) {
1012        let mut key = vec![0; cipher.key_length()];
1013        rand_bytes(&mut key).unwrap();
1014        let mut iv = vec![0; cipher.iv_length()];
1015        rand_bytes(&mut iv).unwrap();
1016
1017        let mut ctx = CipherCtx::new().unwrap();
1018
1019        ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
1020            .unwrap();
1021        ctx.set_padding(false);
1022
1023        assert_eq!(
1024            1,
1025            cipher.block_size(),
1026            "Need a stream cipher, not a block cipher"
1027        );
1028
1029        // update cipher with non-full block
1030        // this is a streaming cipher so the number of output bytes
1031        // will be the same as the number of input bytes
1032        let mut output = vec![0; 32];
1033        let outlen = ctx
1034            .cipher_update(&[1; 15], Some(&mut output[0..15]))
1035            .unwrap();
1036        assert_eq!(15, outlen);
1037
1038        // update cipher with missing bytes from the previous block
1039        // as previously it will output the same number of bytes as
1040        // the input
1041        let outlen = ctx
1042            .cipher_update(&[1; 17], Some(&mut output[15..]))
1043            .unwrap();
1044        assert_eq!(17, outlen);
1045
1046        ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
1047
1048        // encrypt again, but use in-place encryption this time
1049        // First reset the IV
1050        ctx.encrypt_init(None, None, Some(&iv)).unwrap();
1051        ctx.set_padding(false);
1052        let mut data_inplace: [u8; 32] = [1; 32];
1053        let outlen = ctx
1054            .cipher_update_inplace(&mut data_inplace[0..15], 15)
1055            .unwrap();
1056        assert_eq!(15, outlen);
1057
1058        let outlen = ctx
1059            .cipher_update_inplace(&mut data_inplace[15..32], 17)
1060            .unwrap();
1061        assert_eq!(17, outlen);
1062
1063        ctx.cipher_final(&mut [0u8; 0]).unwrap();
1064
1065        // Check that the resulting data is encrypted in the same manner
1066        assert_eq!(data_inplace.as_slice(), output.as_slice());
1067
1068        // try to decrypt
1069        ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv))
1070            .unwrap();
1071        ctx.set_padding(false);
1072
1073        // update cipher with non-full block
1074        // expect that the output for stream cipher will contain
1075        // the same number of bytes as the input
1076        let mut output_decrypted = vec![0; 32];
1077        let outlen = ctx
1078            .cipher_update(&output[0..15], Some(&mut output_decrypted[0..15]))
1079            .unwrap();
1080        assert_eq!(15, outlen);
1081
1082        let outlen = ctx
1083            .cipher_update(&output[15..], Some(&mut output_decrypted[15..]))
1084            .unwrap();
1085        assert_eq!(17, outlen);
1086
1087        ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
1088        // check if the decrypted blocks are the same as input (all ones)
1089        assert_eq!(output_decrypted, vec![1; 32]);
1090
1091        // decrypt again, but now the output in-place
1092        ctx.decrypt_init(None, None, Some(&iv)).unwrap();
1093        ctx.set_padding(false);
1094
1095        let outlen = ctx.cipher_update_inplace(&mut output[0..15], 15).unwrap();
1096        assert_eq!(15, outlen);
1097
1098        let outlen = ctx.cipher_update_inplace(&mut output[15..], 17).unwrap();
1099        assert_eq!(17, outlen);
1100
1101        ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
1102        assert_eq!(output_decrypted, output);
1103    }
1104
1105    #[test]
1106    #[should_panic(expected = "Output buffer size should be at least 33 bytes.")]
1107    fn full_block_updates_aes_128() {
1108        output_buffer_too_small(Cipher::aes_128_cbc());
1109    }
1110
1111    #[test]
1112    #[should_panic(expected = "Output buffer size should be at least 33 bytes.")]
1113    fn full_block_updates_aes_256() {
1114        output_buffer_too_small(Cipher::aes_256_cbc());
1115    }
1116
1117    #[test]
1118    #[should_panic(expected = "Output buffer size should be at least 17 bytes.")]
1119    fn full_block_updates_3des() {
1120        output_buffer_too_small(Cipher::des_ede3_cbc());
1121    }
1122
1123    fn output_buffer_too_small(cipher: &'static CipherRef) {
1124        let mut key = vec![0; cipher.key_length()];
1125        rand_bytes(&mut key).unwrap();
1126        let mut iv = vec![0; cipher.iv_length()];
1127        rand_bytes(&mut iv).unwrap();
1128
1129        let mut ctx = CipherCtx::new().unwrap();
1130
1131        ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
1132            .unwrap();
1133        ctx.set_padding(false);
1134
1135        let block_size = cipher.block_size();
1136        assert!(block_size > 1, "Need a block cipher, not a stream cipher");
1137
1138        ctx.cipher_update(&vec![0; block_size + 1], Some(&mut vec![0; block_size - 1]))
1139            .unwrap();
1140    }
1141
1142    #[cfg(ossl110)]
1143    fn cipher_wrap_test(cipher: &CipherRef, pt: &str, ct: &str, key: &str, iv: Option<&str>) {
1144        let pt = hex::decode(pt).unwrap();
1145        let key = hex::decode(key).unwrap();
1146        let expected = hex::decode(ct).unwrap();
1147        let iv = iv.map(|v| hex::decode(v).unwrap());
1148        let padding = 8 - pt.len() % 8;
1149        let mut computed = vec![0; pt.len() + padding + cipher.block_size() * 2];
1150        let mut ctx = CipherCtx::new().unwrap();
1151
1152        ctx.set_flags(CipherCtxFlags::FLAG_WRAP_ALLOW);
1153        ctx.encrypt_init(Some(cipher), Some(&key), iv.as_deref())
1154            .unwrap();
1155
1156        let count = ctx.cipher_update(&pt, Some(&mut computed)).unwrap();
1157        let rest = ctx.cipher_final(&mut computed[count..]).unwrap();
1158        computed.truncate(count + rest);
1159
1160        if computed != expected {
1161            println!("Computed: {}", hex::encode(&computed));
1162            println!("Expected: {}", hex::encode(&expected));
1163            if computed.len() != expected.len() {
1164                println!(
1165                    "Lengths differ: {} in computed vs {} expected",
1166                    computed.len(),
1167                    expected.len()
1168                );
1169            }
1170            panic!("test failure");
1171        }
1172    }
1173
1174    #[test]
1175    #[cfg(ossl110)]
1176    fn test_aes128_wrap() {
1177        let pt = "00112233445566778899aabbccddeeff";
1178        let ct = "7940ff694448b5bb5139c959a4896832e55d69aa04daa27e";
1179        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1180        let iv = "0001020304050607";
1181
1182        cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, Some(iv));
1183    }
1184
1185    #[test]
1186    #[cfg(ossl110)]
1187    fn test_aes128_wrap_default_iv() {
1188        let pt = "00112233445566778899aabbccddeeff";
1189        let ct = "38f1215f0212526f8a70b51955b9fbdc9fe3041d9832306e";
1190        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1191
1192        cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, None);
1193    }
1194
1195    #[test]
1196    #[cfg(ossl110)]
1197    fn test_aes128_wrap_pad() {
1198        let pt = "00112233445566778899aabbccddee";
1199        let ct = "f13998f5ab32ef82a1bdbcbe585e1d837385b529572a1e1b";
1200        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1201        let iv = "00010203";
1202
1203        cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, Some(iv));
1204    }
1205
1206    #[test]
1207    #[cfg(ossl110)]
1208    fn test_aes128_wrap_pad_default_iv() {
1209        let pt = "00112233445566778899aabbccddee";
1210        let ct = "3a501085fb8cf66f4186b7df851914d471ed823411598add";
1211        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1212
1213        cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, None);
1214    }
1215
1216    #[test]
1217    #[cfg(ossl110)]
1218    fn test_aes192_wrap() {
1219        let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b";
1220        let ct = "83b89142dfeeb4871e078bfb81134d33e23fedc19b03a1cf689973d3831b6813";
1221        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1222        let iv = "0001020304050607";
1223
1224        cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, Some(iv));
1225    }
1226
1227    #[test]
1228    #[cfg(ossl110)]
1229    fn test_aes192_wrap_default_iv() {
1230        let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b";
1231        let ct = "c02c2cf11505d3e4851030d5534cbf5a1d7eca7ba8839adbf239756daf1b43e6";
1232        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1233
1234        cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, None);
1235    }
1236
1237    #[test]
1238    #[cfg(ossl110)]
1239    fn test_aes192_wrap_pad() {
1240        let pt = "00112233445566778899aabbccddee";
1241        let ct = "b4f6bb167ef7caf061a74da82b36ad038ca057ab51e98d3a";
1242        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1243        let iv = "00010203";
1244
1245        cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, Some(iv));
1246    }
1247
1248    #[test]
1249    #[cfg(ossl110)]
1250    fn test_aes192_wrap_pad_default_iv() {
1251        let pt = "00112233445566778899aabbccddee";
1252        let ct = "b2c37a28cc602753a7c944a4c2555a2df9c98b2eded5312e";
1253        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1254
1255        cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, None);
1256    }
1257
1258    #[test]
1259    #[cfg(ossl110)]
1260    fn test_aes256_wrap() {
1261        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51";
1262        let ct = "cc05da2a7f56f7dd0c144231f90bce58648fa20a8278f5a6b7d13bba6aa57a33229d4333866b7fd6";
1263        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1264        let iv = "0001020304050607";
1265
1266        cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, Some(iv));
1267    }
1268
1269    #[test]
1270    #[cfg(ossl110)]
1271    fn test_aes256_wrap_default_iv() {
1272        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51";
1273        let ct = "0b24f068b50e52bc6987868411c36e1b03900866ed12af81eb87cef70a8d1911731c1d7abf789d88";
1274        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1275
1276        cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, None);
1277    }
1278
1279    #[test]
1280    #[cfg(ossl110)]
1281    fn test_aes256_wrap_pad() {
1282        let pt = "00112233445566778899aabbccddee";
1283        let ct = "91594e044ccc06130d60e6c84a996aa4f96a9faff8c5f6e7";
1284        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1285        let iv = "00010203";
1286
1287        cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, Some(iv));
1288    }
1289
1290    #[test]
1291    #[cfg(ossl110)]
1292    fn test_aes256_wrap_pad_default_iv() {
1293        let pt = "00112233445566778899aabbccddee";
1294        let ct = "dc3c166a854afd68aea624a4272693554bf2e4fcbae602cd";
1295        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1296
1297        cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, None);
1298    }
1299
1300    #[test]
1301    #[cfg(ossl110)]
1302    fn test_aes_wrap_pad_cipher_update_vec_buffer_size() {
1303        let cipher = Cipher::aes_256_wrap_pad();
1304        let key = [0u8; 32];
1305        let iv = [0u8; 4];
1306        let pt = [0u8; 9];
1307
1308        let mut ctx = CipherCtx::new().unwrap();
1309        ctx.set_flags(CipherCtxFlags::FLAG_WRAP_ALLOW);
1310        ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
1311            .unwrap();
1312
1313        let mut out = vec![];
1314        let len = ctx.cipher_update_vec(&pt, &mut out).unwrap();
1315        // The vec must be large enough to fit the amount of data we wrote.
1316        assert!(out.capacity() >= len);
1317        assert_eq!(len, 24);
1318    }
1319}