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