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(boringssl))]
56use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef};
57use crate::{cvt, cvt_p};
58#[cfg(ossl102)]
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(ossl102)]
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    /// Initializes the context for encryption.
109    ///
110    /// Normally this is called once to set all of the cipher, key, and IV. However, this process can be split up
111    /// by first setting the cipher with no key or IV and then setting the key and IV with no cipher. This can be used
112    /// to, for example, use a nonstandard IV size.
113    ///
114    /// # Panics
115    ///
116    /// Panics if the key buffer is smaller than the key size of the cipher, the IV buffer is smaller than the IV size
117    /// of the cipher, or if a key or IV is provided before a cipher.
118    #[corresponds(EVP_EncryptInit_ex)]
119    pub fn encrypt_init(
120        &mut self,
121        type_: Option<&CipherRef>,
122        key: Option<&[u8]>,
123        iv: Option<&[u8]>,
124    ) -> Result<(), ErrorStack> {
125        self.cipher_init(type_, key, iv, ffi::EVP_EncryptInit_ex)
126    }
127
128    /// Initializes the context for decryption.
129    ///
130    /// Normally this is called once to set all of the cipher, key, and IV. However, this process can be split up
131    /// by first setting the cipher with no key or IV and then setting the key and IV with no cipher. This can be used
132    /// to, for example, use a nonstandard IV size.
133    ///
134    /// # Panics
135    ///
136    /// Panics if the key buffer is smaller than the key size of the cipher, the IV buffer is smaller than the IV size
137    /// of the cipher, or if a key or IV is provided before a cipher.
138    #[corresponds(EVP_DecryptInit_ex)]
139    pub fn decrypt_init(
140        &mut self,
141        type_: Option<&CipherRef>,
142        key: Option<&[u8]>,
143        iv: Option<&[u8]>,
144    ) -> Result<(), ErrorStack> {
145        self.cipher_init(type_, key, iv, ffi::EVP_DecryptInit_ex)
146    }
147
148    fn cipher_init(
149        &mut self,
150        type_: Option<&CipherRef>,
151        key: Option<&[u8]>,
152        iv: Option<&[u8]>,
153        f: unsafe extern "C" fn(
154            *mut ffi::EVP_CIPHER_CTX,
155            *const ffi::EVP_CIPHER,
156            *mut ffi::ENGINE,
157            *const c_uchar,
158            *const c_uchar,
159        ) -> c_int,
160    ) -> Result<(), ErrorStack> {
161        if let Some(key) = key {
162            let key_len = type_.map_or_else(|| self.key_length(), |c| c.key_length());
163            assert!(key_len <= key.len());
164        }
165
166        if let Some(iv) = iv {
167            let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
168            assert!(iv_len <= iv.len());
169        }
170
171        unsafe {
172            cvt(f(
173                self.as_ptr(),
174                type_.map_or(ptr::null(), |p| p.as_ptr()),
175                ptr::null_mut(),
176                key.map_or(ptr::null(), |k| k.as_ptr()),
177                iv.map_or(ptr::null(), |iv| iv.as_ptr()),
178            ))?;
179        }
180
181        Ok(())
182    }
183
184    /// Initializes the context to perform envelope encryption.
185    ///
186    /// Normally this is called once to set both the cipher and public keys. However, this process may be split up by
187    /// first providing the cipher with no public keys and then setting the public keys with no cipher.
188    ///
189    /// `encrypted_keys` will contain the generated symmetric key encrypted with each corresponding asymmetric private
190    /// key. The generated IV will be written to `iv`.
191    ///
192    /// # Panics
193    ///
194    /// Panics if `pub_keys` is not the same size as `encrypted_keys`, the IV buffer is smaller than the cipher's IV
195    /// size, or if an IV is provided before the cipher.
196    #[corresponds(EVP_SealInit)]
197    #[cfg(not(boringssl))]
198    pub fn seal_init<T>(
199        &mut self,
200        type_: Option<&CipherRef>,
201        pub_keys: &[PKey<T>],
202        encrypted_keys: &mut [Vec<u8>],
203        iv: Option<&mut [u8]>,
204    ) -> Result<(), ErrorStack>
205    where
206        T: HasPublic,
207    {
208        assert_eq!(pub_keys.len(), encrypted_keys.len());
209        if !pub_keys.is_empty() {
210            let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
211            assert!(iv.as_ref().map_or(0, |b| b.len()) >= iv_len);
212        }
213
214        for (pub_key, buf) in pub_keys.iter().zip(&mut *encrypted_keys) {
215            buf.resize(pub_key.size(), 0);
216        }
217
218        let mut keys = encrypted_keys
219            .iter_mut()
220            .map(|b| b.as_mut_ptr())
221            .collect::<Vec<_>>();
222        let mut key_lengths = vec![0; pub_keys.len()];
223        let pub_keys_len = i32::try_from(pub_keys.len()).unwrap();
224
225        unsafe {
226            cvt(ffi::EVP_SealInit(
227                self.as_ptr(),
228                type_.map_or(ptr::null(), |p| p.as_ptr()),
229                keys.as_mut_ptr(),
230                key_lengths.as_mut_ptr(),
231                iv.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
232                pub_keys.as_ptr() as *mut _,
233                pub_keys_len,
234            ))?;
235        }
236
237        for (buf, len) in encrypted_keys.iter_mut().zip(key_lengths) {
238            buf.truncate(len as usize);
239        }
240
241        Ok(())
242    }
243
244    /// Initializes the context to perform envelope decryption.
245    ///
246    /// Normally this is called once with all of the arguments present. However, this process may be split up by first
247    /// providing the cipher alone and then after providing the rest of the arguments in a second call.
248    ///
249    /// # Panics
250    ///
251    /// Panics if the IV buffer is smaller than the cipher's required IV size or if the IV is provided before the
252    /// cipher.
253    #[corresponds(EVP_OpenInit)]
254    #[cfg(not(boringssl))]
255    pub fn open_init<T>(
256        &mut self,
257        type_: Option<&CipherRef>,
258        encrypted_key: &[u8],
259        iv: Option<&[u8]>,
260        priv_key: Option<&PKeyRef<T>>,
261    ) -> Result<(), ErrorStack>
262    where
263        T: HasPrivate,
264    {
265        if priv_key.is_some() {
266            let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
267            assert!(iv.map_or(0, |b| b.len()) >= iv_len);
268        }
269
270        let len = c_int::try_from(encrypted_key.len()).unwrap();
271        unsafe {
272            cvt(ffi::EVP_OpenInit(
273                self.as_ptr(),
274                type_.map_or(ptr::null(), |p| p.as_ptr()),
275                encrypted_key.as_ptr(),
276                len,
277                iv.map_or(ptr::null(), |b| b.as_ptr()),
278                priv_key.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
279            ))?;
280        }
281
282        Ok(())
283    }
284
285    fn assert_cipher(&self) {
286        unsafe {
287            assert!(!EVP_CIPHER_CTX_get0_cipher(self.as_ptr()).is_null());
288        }
289    }
290
291    /// Returns the block size of the context's cipher.
292    ///
293    /// Stream ciphers will report a block size of 1.
294    ///
295    /// # Panics
296    ///
297    /// Panics if the context has not been initialized with a cipher.
298    #[corresponds(EVP_CIPHER_CTX_block_size)]
299    pub fn block_size(&self) -> usize {
300        self.assert_cipher();
301
302        unsafe { ffi::EVP_CIPHER_CTX_block_size(self.as_ptr()) as usize }
303    }
304
305    /// Returns the key length of the context's cipher.
306    ///
307    /// # Panics
308    ///
309    /// Panics if the context has not been initialized with a cipher.
310    #[corresponds(EVP_CIPHER_CTX_key_length)]
311    pub fn key_length(&self) -> usize {
312        self.assert_cipher();
313
314        unsafe { ffi::EVP_CIPHER_CTX_key_length(self.as_ptr()) as usize }
315    }
316
317    /// Generates a random key based on the configured cipher.
318    ///
319    /// # Panics
320    ///
321    /// Panics if the context has not been initialized with a cipher or if the buffer is smaller than the cipher's key
322    /// length.
323    ///
324    /// This corresponds to [`EVP_CIPHER_CTX_rand_key`].
325    ///
326    /// [`EVP_CIPHER_CTX_rand_key`]: https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_CTX_rand_key.html
327    #[corresponds(EVP_CIPHER_CTX_rand_key)]
328    #[cfg(not(boringssl))]
329    pub fn rand_key(&self, buf: &mut [u8]) -> Result<(), ErrorStack> {
330        assert!(buf.len() >= self.key_length());
331
332        unsafe {
333            cvt(ffi::EVP_CIPHER_CTX_rand_key(
334                self.as_ptr(),
335                buf.as_mut_ptr(),
336            ))?;
337        }
338
339        Ok(())
340    }
341
342    /// Sets the length of the key expected by the context.
343    ///
344    /// Only some ciphers support configurable key lengths.
345    ///
346    /// # Panics
347    ///
348    /// Panics if the context has not been initialized with a cipher.
349    #[corresponds(EVP_CIPHER_CTX_set_key_length)]
350    pub fn set_key_length(&mut self, len: usize) -> Result<(), ErrorStack> {
351        self.assert_cipher();
352
353        unsafe {
354            cvt(ffi::EVP_CIPHER_CTX_set_key_length(
355                self.as_ptr(),
356                len.try_into().unwrap(),
357            ))?;
358        }
359
360        Ok(())
361    }
362
363    /// Returns the length of the IV expected by this context.
364    ///
365    /// Returns 0 if the cipher does not use an IV.
366    ///
367    /// # Panics
368    ///
369    /// Panics if the context has not been initialized with a cipher.
370    #[corresponds(EVP_CIPHER_CTX_iv_length)]
371    pub fn iv_length(&self) -> usize {
372        self.assert_cipher();
373
374        unsafe { ffi::EVP_CIPHER_CTX_iv_length(self.as_ptr()) as usize }
375    }
376
377    /// Returns the `num` parameter of the cipher.
378    ///
379    /// Built-in ciphers typically use this to track how much of the
380    /// current underlying block has been "used" already.
381    ///
382    /// # Panics
383    ///
384    /// Panics if the context has not been initialized with a cipher.
385    #[corresponds(EVP_CIPHER_CTX_num)]
386    #[cfg(ossl110)]
387    pub fn num(&self) -> usize {
388        self.assert_cipher();
389
390        unsafe { ffi::EVP_CIPHER_CTX_num(self.as_ptr()) as usize }
391    }
392
393    /// Sets the length of the IV expected by this context.
394    ///
395    /// Only some ciphers support configurable IV lengths.
396    ///
397    /// # Panics
398    ///
399    /// Panics if the context has not been initialized with a cipher.
400    #[corresponds(EVP_CIPHER_CTX_ctrl)]
401    pub fn set_iv_length(&mut self, len: usize) -> Result<(), ErrorStack> {
402        self.assert_cipher();
403
404        let len = c_int::try_from(len).unwrap();
405
406        unsafe {
407            cvt(ffi::EVP_CIPHER_CTX_ctrl(
408                self.as_ptr(),
409                ffi::EVP_CTRL_GCM_SET_IVLEN,
410                len,
411                ptr::null_mut(),
412            ))?;
413        }
414
415        Ok(())
416    }
417
418    /// Returns the length of the authentication tag expected by this context.
419    ///
420    /// Returns 0 if the cipher is not authenticated.
421    ///
422    /// # Panics
423    ///
424    /// Panics if the context has not been initialized with a cipher.
425    ///
426    /// Requires OpenSSL 3.0.0 or newer.
427    #[corresponds(EVP_CIPHER_CTX_get_tag_length)]
428    #[cfg(ossl300)]
429    pub fn tag_length(&self) -> usize {
430        self.assert_cipher();
431
432        unsafe { ffi::EVP_CIPHER_CTX_get_tag_length(self.as_ptr()) as usize }
433    }
434
435    /// Retrieves the calculated authentication tag from the context.
436    ///
437    /// This should be called after [`Self::cipher_final`], and is only supported by authenticated ciphers.
438    ///
439    /// The size of the buffer indicates the size of the tag. While some ciphers support a range of tag sizes, it is
440    /// recommended to pick the maximum size.
441    #[corresponds(EVP_CIPHER_CTX_ctrl)]
442    pub fn tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> {
443        let len = c_int::try_from(tag.len()).unwrap();
444
445        unsafe {
446            cvt(ffi::EVP_CIPHER_CTX_ctrl(
447                self.as_ptr(),
448                ffi::EVP_CTRL_GCM_GET_TAG,
449                len,
450                tag.as_mut_ptr() as *mut _,
451            ))?;
452        }
453
454        Ok(())
455    }
456
457    /// Sets the length of the generated authentication tag.
458    ///
459    /// This must be called when encrypting with a cipher in CCM mode to use a tag size other than the default.
460    #[corresponds(EVP_CIPHER_CTX_ctrl)]
461    pub fn set_tag_length(&mut self, len: usize) -> Result<(), ErrorStack> {
462        let len = c_int::try_from(len).unwrap();
463
464        unsafe {
465            cvt(ffi::EVP_CIPHER_CTX_ctrl(
466                self.as_ptr(),
467                ffi::EVP_CTRL_GCM_SET_TAG,
468                len,
469                ptr::null_mut(),
470            ))?;
471        }
472
473        Ok(())
474    }
475
476    /// Sets the authentication tag for verification during decryption.
477    #[corresponds(EVP_CIPHER_CTX_ctrl)]
478    pub fn set_tag(&mut self, tag: &[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_SET_TAG,
485                len,
486                tag.as_ptr() as *mut _,
487            ))?;
488        }
489
490        Ok(())
491    }
492
493    /// Enables or disables padding.
494    ///
495    /// If padding is disabled, the plaintext must be an exact multiple of the cipher's block size.
496    #[corresponds(EVP_CIPHER_CTX_set_padding)]
497    pub fn set_padding(&mut self, padding: bool) {
498        unsafe {
499            ffi::EVP_CIPHER_CTX_set_padding(self.as_ptr(), padding as c_int);
500        }
501    }
502
503    /// Sets the total length of plaintext data.
504    ///
505    /// This is required for ciphers operating in CCM mode.
506    #[corresponds(EVP_CipherUpdate)]
507    pub fn set_data_len(&mut self, len: usize) -> Result<(), ErrorStack> {
508        let len = c_int::try_from(len).unwrap();
509
510        unsafe {
511            cvt(ffi::EVP_CipherUpdate(
512                self.as_ptr(),
513                ptr::null_mut(),
514                &mut 0,
515                ptr::null(),
516                len,
517            ))?;
518        }
519
520        Ok(())
521    }
522
523    /// Set ctx flags.
524    ///
525    /// This function is currently used to enable AES key wrap feature supported by OpenSSL 1.0.2 or newer.
526    #[corresponds(EVP_CIPHER_CTX_set_flags)]
527    #[cfg(ossl102)]
528    pub fn set_flags(&mut self, flags: CipherCtxFlags) {
529        unsafe {
530            ffi::EVP_CIPHER_CTX_set_flags(self.as_ptr(), flags.bits());
531        }
532    }
533
534    /// Writes data into the context.
535    ///
536    /// Providing no output buffer will cause the input to be considered additional authenticated data (AAD).
537    ///
538    /// Returns the number of bytes written to `output`.
539    ///
540    /// # Panics
541    ///
542    /// Panics if `output` doesn't contain enough space for data to be
543    /// written as specified by [`Self::minimal_output_size`].
544    #[corresponds(EVP_CipherUpdate)]
545    pub fn cipher_update(
546        &mut self,
547        input: &[u8],
548        output: Option<&mut [u8]>,
549    ) -> Result<usize, ErrorStack> {
550        if let Some(output) = &output {
551            let mut block_size = self.block_size();
552            if block_size == 1 {
553                block_size = 0;
554            }
555            let min_output_size = input.len() + block_size;
556            assert!(
557                output.len() >= min_output_size,
558                "Output buffer size should be at least {} bytes.",
559                min_output_size
560            );
561        }
562
563        unsafe { self.cipher_update_unchecked(input, output) }
564    }
565
566    /// Writes data into the context.
567    ///
568    /// Providing no output buffer will cause the input to be considered additional authenticated data (AAD).
569    ///
570    /// Returns the number of bytes written to `output`.
571    ///
572    /// This function is the same as [`Self::cipher_update`] but with the
573    /// output size check removed. It can be used when the exact
574    /// buffer size control is maintained by the caller.
575    ///
576    /// # Safety
577    /// The caller is expected to provide `output` buffer
578    /// large enough to contain correct number of bytes. For streaming
579    /// ciphers the output buffer size should be at least as big as
580    /// the input buffer. For block ciphers the size of the output
581    /// buffer depends on the state of partially updated blocks.
582    #[corresponds(EVP_CipherUpdate)]
583    pub unsafe fn cipher_update_unchecked(
584        &mut self,
585        input: &[u8],
586        output: Option<&mut [u8]>,
587    ) -> Result<usize, ErrorStack> {
588        let inlen = c_int::try_from(input.len()).unwrap();
589
590        let mut outlen = 0;
591
592        cvt(ffi::EVP_CipherUpdate(
593            self.as_ptr(),
594            output.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
595            &mut outlen,
596            input.as_ptr(),
597            inlen,
598        ))?;
599
600        Ok(outlen as usize)
601    }
602
603    /// Like [`Self::cipher_update`] except that it appends output to a [`Vec`].
604    pub fn cipher_update_vec(
605        &mut self,
606        input: &[u8],
607        output: &mut Vec<u8>,
608    ) -> Result<usize, ErrorStack> {
609        let base = output.len();
610        output.resize(base + input.len() + self.block_size(), 0);
611        let len = self.cipher_update(input, Some(&mut output[base..]))?;
612        output.truncate(base + len);
613
614        Ok(len)
615    }
616
617    /// Like [`Self::cipher_update`] except that it writes output into the
618    /// `data` buffer. The `inlen` parameter specifies the number of bytes in
619    /// `data` that are considered the input. For streaming ciphers, the size of
620    /// `data` must be at least the input size. Otherwise, it must be at least
621    /// an additional block size larger.
622    ///
623    /// Note: Use [`Self::cipher_update`] with no output argument to write AAD.
624    ///
625    /// # Panics
626    ///
627    /// This function panics if the input size cannot be represented as `int` or
628    /// exceeds the buffer size, or if the output buffer does not contain enough
629    /// additional space.
630    #[corresponds(EVP_CipherUpdate)]
631    pub fn cipher_update_inplace(
632        &mut self,
633        data: &mut [u8],
634        inlen: usize,
635    ) -> Result<usize, ErrorStack> {
636        assert!(inlen <= data.len(), "Input size may not exceed buffer size");
637        let block_size = self.block_size();
638        if block_size != 1 {
639            assert!(
640                data.len() >= inlen + block_size,
641                "Output buffer size must be at least {} bytes.",
642                inlen + block_size
643            );
644        }
645
646        let inlen = c_int::try_from(inlen).unwrap();
647        let mut outlen = 0;
648        unsafe {
649            cvt(ffi::EVP_CipherUpdate(
650                self.as_ptr(),
651                data.as_mut_ptr(),
652                &mut outlen,
653                data.as_ptr(),
654                inlen,
655            ))
656        }?;
657
658        Ok(outlen as usize)
659    }
660
661    /// Finalizes the encryption or decryption process.
662    ///
663    /// Any remaining data will be written to the output buffer.
664    ///
665    /// Returns the number of bytes written to `output`.
666    ///
667    /// # Panics
668    ///
669    /// Panics if `output` is smaller than the cipher's block size.
670    #[corresponds(EVP_CipherFinal)]
671    pub fn cipher_final(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
672        let block_size = self.block_size();
673        if block_size > 1 {
674            assert!(output.len() >= block_size);
675        }
676
677        unsafe { self.cipher_final_unchecked(output) }
678    }
679
680    /// Finalizes the encryption or decryption process.
681    ///
682    /// Any remaining data will be written to the output buffer.
683    ///
684    /// Returns the number of bytes written to `output`.
685    ///
686    /// This function is the same as [`Self::cipher_final`] but with
687    /// the output buffer size check removed.
688    ///
689    /// # Safety
690    /// The caller is expected to provide `output` buffer
691    /// large enough to contain correct number of bytes. For streaming
692    /// ciphers the output buffer can be empty, for block ciphers the
693    /// output buffer should be at least as big as the block.
694    #[corresponds(EVP_CipherFinal)]
695    pub unsafe fn cipher_final_unchecked(
696        &mut self,
697        output: &mut [u8],
698    ) -> Result<usize, ErrorStack> {
699        let mut outl = 0;
700
701        cvt(ffi::EVP_CipherFinal(
702            self.as_ptr(),
703            output.as_mut_ptr(),
704            &mut outl,
705        ))?;
706
707        Ok(outl as usize)
708    }
709
710    /// Like [`Self::cipher_final`] except that it appends output to a [`Vec`].
711    pub fn cipher_final_vec(&mut self, output: &mut Vec<u8>) -> Result<usize, ErrorStack> {
712        let base = output.len();
713        output.resize(base + self.block_size(), 0);
714        let len = self.cipher_final(&mut output[base..])?;
715        output.truncate(base + len);
716
717        Ok(len)
718    }
719}
720
721#[cfg(test)]
722mod test {
723    use super::*;
724    use crate::{cipher::Cipher, rand::rand_bytes};
725    #[cfg(not(boringssl))]
726    use std::slice;
727
728    #[test]
729    #[cfg(not(boringssl))]
730    fn seal_open() {
731        let private_pem = include_bytes!("../test/rsa.pem");
732        let public_pem = include_bytes!("../test/rsa.pem.pub");
733        let private_key = PKey::private_key_from_pem(private_pem).unwrap();
734        let public_key = PKey::public_key_from_pem(public_pem).unwrap();
735        let cipher = Cipher::aes_256_cbc();
736        let secret = b"My secret message";
737
738        let mut ctx = CipherCtx::new().unwrap();
739        let mut encrypted_key = vec![];
740        let mut iv = vec![0; cipher.iv_length()];
741        let mut encrypted = vec![];
742        ctx.seal_init(
743            Some(cipher),
744            &[public_key],
745            slice::from_mut(&mut encrypted_key),
746            Some(&mut iv),
747        )
748        .unwrap();
749        ctx.cipher_update_vec(secret, &mut encrypted).unwrap();
750        ctx.cipher_final_vec(&mut encrypted).unwrap();
751
752        let mut decrypted = vec![];
753        ctx.open_init(Some(cipher), &encrypted_key, Some(&iv), Some(&private_key))
754            .unwrap();
755        ctx.cipher_update_vec(&encrypted, &mut decrypted).unwrap();
756        ctx.cipher_final_vec(&mut decrypted).unwrap();
757
758        assert_eq!(secret, &decrypted[..]);
759    }
760
761    fn aes_128_cbc(cipher: &CipherRef) {
762        // from https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf
763        let key = hex::decode("2b7e151628aed2a6abf7158809cf4f3c").unwrap();
764        let iv = hex::decode("000102030405060708090a0b0c0d0e0f").unwrap();
765        let pt = hex::decode("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51")
766            .unwrap();
767        let ct = hex::decode("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2")
768            .unwrap();
769
770        let mut ctx = CipherCtx::new().unwrap();
771
772        ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
773            .unwrap();
774        ctx.set_padding(false);
775
776        let mut buf = vec![];
777        ctx.cipher_update_vec(&pt, &mut buf).unwrap();
778        ctx.cipher_final_vec(&mut buf).unwrap();
779
780        assert_eq!(buf, ct);
781
782        ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv))
783            .unwrap();
784        ctx.set_padding(false);
785
786        let mut buf = vec![];
787        ctx.cipher_update_vec(&ct, &mut buf).unwrap();
788        ctx.cipher_final_vec(&mut buf).unwrap();
789
790        assert_eq!(buf, pt);
791    }
792
793    #[test]
794    #[cfg(ossl300)]
795    fn fetched_aes_128_cbc() {
796        let cipher = Cipher::fetch(None, "AES-128-CBC", None).unwrap();
797        aes_128_cbc(&cipher);
798    }
799
800    #[test]
801    fn default_aes_128_cbc() {
802        let cipher = Cipher::aes_128_cbc();
803        aes_128_cbc(cipher);
804    }
805
806    #[test]
807    fn test_stream_ciphers() {
808        test_stream_cipher(Cipher::aes_192_ctr());
809        test_stream_cipher(Cipher::aes_256_ctr());
810    }
811
812    fn test_stream_cipher(cipher: &'static CipherRef) {
813        let mut key = vec![0; cipher.key_length()];
814        rand_bytes(&mut key).unwrap();
815        let mut iv = vec![0; cipher.iv_length()];
816        rand_bytes(&mut iv).unwrap();
817
818        let mut ctx = CipherCtx::new().unwrap();
819
820        ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
821            .unwrap();
822        ctx.set_padding(false);
823
824        assert_eq!(
825            1,
826            cipher.block_size(),
827            "Need a stream cipher, not a block cipher"
828        );
829
830        // update cipher with non-full block
831        // this is a streaming cipher so the number of output bytes
832        // will be the same as the number of input bytes
833        let mut output = vec![0; 32];
834        let outlen = ctx
835            .cipher_update(&[1; 15], Some(&mut output[0..15]))
836            .unwrap();
837        assert_eq!(15, outlen);
838
839        // update cipher with missing bytes from the previous block
840        // as previously it will output the same number of bytes as
841        // the input
842        let outlen = ctx
843            .cipher_update(&[1; 17], Some(&mut output[15..]))
844            .unwrap();
845        assert_eq!(17, outlen);
846
847        ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
848
849        // encrypt again, but use in-place encryption this time
850        // First reset the IV
851        ctx.encrypt_init(None, None, Some(&iv)).unwrap();
852        ctx.set_padding(false);
853        let mut data_inplace: [u8; 32] = [1; 32];
854        let outlen = ctx
855            .cipher_update_inplace(&mut data_inplace[0..15], 15)
856            .unwrap();
857        assert_eq!(15, outlen);
858
859        let outlen = ctx
860            .cipher_update_inplace(&mut data_inplace[15..32], 17)
861            .unwrap();
862        assert_eq!(17, outlen);
863
864        ctx.cipher_final(&mut [0u8; 0]).unwrap();
865
866        // Check that the resulting data is encrypted in the same manner
867        assert_eq!(data_inplace.as_slice(), output.as_slice());
868
869        // try to decrypt
870        ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv))
871            .unwrap();
872        ctx.set_padding(false);
873
874        // update cipher with non-full block
875        // expect that the output for stream cipher will contain
876        // the same number of bytes as the input
877        let mut output_decrypted = vec![0; 32];
878        let outlen = ctx
879            .cipher_update(&output[0..15], Some(&mut output_decrypted[0..15]))
880            .unwrap();
881        assert_eq!(15, outlen);
882
883        let outlen = ctx
884            .cipher_update(&output[15..], Some(&mut output_decrypted[15..]))
885            .unwrap();
886        assert_eq!(17, outlen);
887
888        ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
889        // check if the decrypted blocks are the same as input (all ones)
890        assert_eq!(output_decrypted, vec![1; 32]);
891
892        // decrypt again, but now the output in-place
893        ctx.decrypt_init(None, None, Some(&iv)).unwrap();
894        ctx.set_padding(false);
895
896        let outlen = ctx.cipher_update_inplace(&mut output[0..15], 15).unwrap();
897        assert_eq!(15, outlen);
898
899        let outlen = ctx.cipher_update_inplace(&mut output[15..], 17).unwrap();
900        assert_eq!(17, outlen);
901
902        ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
903        assert_eq!(output_decrypted, output);
904    }
905
906    #[test]
907    #[should_panic(expected = "Output buffer size should be at least 33 bytes.")]
908    fn full_block_updates_aes_128() {
909        output_buffer_too_small(Cipher::aes_128_cbc());
910    }
911
912    #[test]
913    #[should_panic(expected = "Output buffer size should be at least 33 bytes.")]
914    fn full_block_updates_aes_256() {
915        output_buffer_too_small(Cipher::aes_256_cbc());
916    }
917
918    #[test]
919    #[should_panic(expected = "Output buffer size should be at least 17 bytes.")]
920    fn full_block_updates_3des() {
921        output_buffer_too_small(Cipher::des_ede3_cbc());
922    }
923
924    fn output_buffer_too_small(cipher: &'static CipherRef) {
925        let mut key = vec![0; cipher.key_length()];
926        rand_bytes(&mut key).unwrap();
927        let mut iv = vec![0; cipher.iv_length()];
928        rand_bytes(&mut iv).unwrap();
929
930        let mut ctx = CipherCtx::new().unwrap();
931
932        ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
933            .unwrap();
934        ctx.set_padding(false);
935
936        let block_size = cipher.block_size();
937        assert!(block_size > 1, "Need a block cipher, not a stream cipher");
938
939        ctx.cipher_update(&vec![0; block_size + 1], Some(&mut vec![0; block_size - 1]))
940            .unwrap();
941    }
942
943    #[cfg(ossl102)]
944    fn cipher_wrap_test(cipher: &CipherRef, pt: &str, ct: &str, key: &str, iv: Option<&str>) {
945        let pt = hex::decode(pt).unwrap();
946        let key = hex::decode(key).unwrap();
947        let expected = hex::decode(ct).unwrap();
948        let iv = iv.map(|v| hex::decode(v).unwrap());
949        let padding = 8 - pt.len() % 8;
950        let mut computed = vec![0; pt.len() + padding + cipher.block_size() * 2];
951        let mut ctx = CipherCtx::new().unwrap();
952
953        ctx.set_flags(CipherCtxFlags::FLAG_WRAP_ALLOW);
954        ctx.encrypt_init(Some(cipher), Some(&key), iv.as_deref())
955            .unwrap();
956
957        let count = ctx.cipher_update(&pt, Some(&mut computed)).unwrap();
958        let rest = ctx.cipher_final(&mut computed[count..]).unwrap();
959        computed.truncate(count + rest);
960
961        if computed != expected {
962            println!("Computed: {}", hex::encode(&computed));
963            println!("Expected: {}", hex::encode(&expected));
964            if computed.len() != expected.len() {
965                println!(
966                    "Lengths differ: {} in computed vs {} expected",
967                    computed.len(),
968                    expected.len()
969                );
970            }
971            panic!("test failure");
972        }
973    }
974
975    #[test]
976    #[cfg(ossl102)]
977    fn test_aes128_wrap() {
978        let pt = "00112233445566778899aabbccddeeff";
979        let ct = "7940ff694448b5bb5139c959a4896832e55d69aa04daa27e";
980        let key = "2b7e151628aed2a6abf7158809cf4f3c";
981        let iv = "0001020304050607";
982
983        cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, Some(iv));
984    }
985
986    #[test]
987    #[cfg(ossl102)]
988    fn test_aes128_wrap_default_iv() {
989        let pt = "00112233445566778899aabbccddeeff";
990        let ct = "38f1215f0212526f8a70b51955b9fbdc9fe3041d9832306e";
991        let key = "2b7e151628aed2a6abf7158809cf4f3c";
992
993        cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, None);
994    }
995
996    #[test]
997    #[cfg(ossl110)]
998    fn test_aes128_wrap_pad() {
999        let pt = "00112233445566778899aabbccddee";
1000        let ct = "f13998f5ab32ef82a1bdbcbe585e1d837385b529572a1e1b";
1001        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1002        let iv = "00010203";
1003
1004        cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, Some(iv));
1005    }
1006
1007    #[test]
1008    #[cfg(ossl110)]
1009    fn test_aes128_wrap_pad_default_iv() {
1010        let pt = "00112233445566778899aabbccddee";
1011        let ct = "3a501085fb8cf66f4186b7df851914d471ed823411598add";
1012        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1013
1014        cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, None);
1015    }
1016
1017    #[test]
1018    #[cfg(ossl102)]
1019    fn test_aes192_wrap() {
1020        let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b";
1021        let ct = "83b89142dfeeb4871e078bfb81134d33e23fedc19b03a1cf689973d3831b6813";
1022        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1023        let iv = "0001020304050607";
1024
1025        cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, Some(iv));
1026    }
1027
1028    #[test]
1029    #[cfg(ossl102)]
1030    fn test_aes192_wrap_default_iv() {
1031        let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b";
1032        let ct = "c02c2cf11505d3e4851030d5534cbf5a1d7eca7ba8839adbf239756daf1b43e6";
1033        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1034
1035        cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, None);
1036    }
1037
1038    #[test]
1039    #[cfg(ossl110)]
1040    fn test_aes192_wrap_pad() {
1041        let pt = "00112233445566778899aabbccddee";
1042        let ct = "b4f6bb167ef7caf061a74da82b36ad038ca057ab51e98d3a";
1043        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1044        let iv = "00010203";
1045
1046        cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, Some(iv));
1047    }
1048
1049    #[test]
1050    #[cfg(ossl110)]
1051    fn test_aes192_wrap_pad_default_iv() {
1052        let pt = "00112233445566778899aabbccddee";
1053        let ct = "b2c37a28cc602753a7c944a4c2555a2df9c98b2eded5312e";
1054        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1055
1056        cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, None);
1057    }
1058
1059    #[test]
1060    #[cfg(ossl102)]
1061    fn test_aes256_wrap() {
1062        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51";
1063        let ct = "cc05da2a7f56f7dd0c144231f90bce58648fa20a8278f5a6b7d13bba6aa57a33229d4333866b7fd6";
1064        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1065        let iv = "0001020304050607";
1066
1067        cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, Some(iv));
1068    }
1069
1070    #[test]
1071    #[cfg(ossl102)]
1072    fn test_aes256_wrap_default_iv() {
1073        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51";
1074        let ct = "0b24f068b50e52bc6987868411c36e1b03900866ed12af81eb87cef70a8d1911731c1d7abf789d88";
1075        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1076
1077        cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, None);
1078    }
1079
1080    #[test]
1081    #[cfg(ossl110)]
1082    fn test_aes256_wrap_pad() {
1083        let pt = "00112233445566778899aabbccddee";
1084        let ct = "91594e044ccc06130d60e6c84a996aa4f96a9faff8c5f6e7";
1085        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1086        let iv = "00010203";
1087
1088        cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, Some(iv));
1089    }
1090
1091    #[test]
1092    #[cfg(ossl110)]
1093    fn test_aes256_wrap_pad_default_iv() {
1094        let pt = "00112233445566778899aabbccddee";
1095        let ct = "dc3c166a854afd68aea624a4272693554bf2e4fcbae602cd";
1096        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1097
1098        cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, None);
1099    }
1100}
1101