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