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: *mut EVP_CIPHER_CTX = 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 ///
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))]
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)]
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)]
379 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)]
395 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)]
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)]
437 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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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`].
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)]
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)]
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)]
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`].
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)]
732mod 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))]
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
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)]
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]
811 fn default_aes_128_cbc() {
812 let cipher = Cipher::aes_128_cbc();
813 aes_128_cbc(cipher);
814 }
815
816 #[test]
817 fn test_stream_ciphers() {
818 test_stream_cipher(Cipher::aes_192_ctr());
819 test_stream_cipher(Cipher::aes_256_ctr());
820 }
821
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.")]
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.")]
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.")]
930 fn full_block_updates_3des() {
931 output_buffer_too_small(Cipher::des_ede3_cbc());
932 }
933
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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