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 use cfg_if::cfg_if; 59 use foreign_types::{ForeignType, ForeignTypeRef}; 60 use libc::{c_int, c_uchar}; 61 use openssl_macros::corresponds; 62 use std::convert::{TryFrom, TryInto}; 63 use std::ptr; 64 65 cfg_if! { 66 if #[cfg(ossl300)] { 67 use ffi::EVP_CIPHER_CTX_get0_cipher; 68 } else { 69 use ffi::EVP_CIPHER_CTX_cipher as EVP_CIPHER_CTX_get0_cipher; 70 } 71 } 72 73 foreign_type_and_impl_send_sync! { 74 type CType = ffi::EVP_CIPHER_CTX; 75 fn drop = ffi::EVP_CIPHER_CTX_free; 76 77 /// A context object used to perform symmetric encryption operations. 78 pub struct CipherCtx; 79 /// A reference to a [`CipherCtx`]. 80 pub struct CipherCtxRef; 81 } 82 83 impl CipherCtx { 84 /// Creates a new context. 85 #[corresponds(EVP_CIPHER_CTX_new)] new() -> Result<Self, ErrorStack>86 pub fn new() -> Result<Self, ErrorStack> { 87 ffi::init(); 88 89 unsafe { 90 let ptr = cvt_p(ffi::EVP_CIPHER_CTX_new())?; 91 Ok(CipherCtx::from_ptr(ptr)) 92 } 93 } 94 } 95 96 impl CipherCtxRef { 97 /// Initializes the context for encryption. 98 /// 99 /// Normally this is called once to set all of the cipher, key, and IV. However, this process can be split up 100 /// by first setting the cipher with no key or IV and then setting the key and IV with no cipher. This can be used 101 /// to, for example, use a nonstandard IV size. 102 /// 103 /// # Panics 104 /// 105 /// Panics if the key buffer is smaller than the key size of the cipher, the IV buffer is smaller than the IV size 106 /// of the cipher, or if a key or IV is provided before a cipher. 107 #[corresponds(EVP_EncryptInit_ex)] encrypt_init( &mut self, type_: Option<&CipherRef>, key: Option<&[u8]>, iv: Option<&[u8]>, ) -> Result<(), ErrorStack>108 pub fn encrypt_init( 109 &mut self, 110 type_: Option<&CipherRef>, 111 key: Option<&[u8]>, 112 iv: Option<&[u8]>, 113 ) -> Result<(), ErrorStack> { 114 self.cipher_init(type_, key, iv, ffi::EVP_EncryptInit_ex) 115 } 116 117 /// Initializes the context for decryption. 118 /// 119 /// Normally this is called once to set all of the cipher, key, and IV. However, this process can be split up 120 /// by first setting the cipher with no key or IV and then setting the key and IV with no cipher. This can be used 121 /// to, for example, use a nonstandard IV size. 122 /// 123 /// # Panics 124 /// 125 /// Panics if the key buffer is smaller than the key size of the cipher, the IV buffer is smaller than the IV size 126 /// of the cipher, or if a key or IV is provided before a cipher. 127 #[corresponds(EVP_DecryptInit_ex)] decrypt_init( &mut self, type_: Option<&CipherRef>, key: Option<&[u8]>, iv: Option<&[u8]>, ) -> Result<(), ErrorStack>128 pub fn decrypt_init( 129 &mut self, 130 type_: Option<&CipherRef>, 131 key: Option<&[u8]>, 132 iv: Option<&[u8]>, 133 ) -> Result<(), ErrorStack> { 134 self.cipher_init(type_, key, iv, ffi::EVP_DecryptInit_ex) 135 } 136 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>137 fn cipher_init( 138 &mut self, 139 type_: Option<&CipherRef>, 140 key: Option<&[u8]>, 141 iv: Option<&[u8]>, 142 f: unsafe extern "C" fn( 143 *mut ffi::EVP_CIPHER_CTX, 144 *const ffi::EVP_CIPHER, 145 *mut ffi::ENGINE, 146 *const c_uchar, 147 *const c_uchar, 148 ) -> c_int, 149 ) -> Result<(), ErrorStack> { 150 if let Some(key) = key { 151 let key_len = type_.map_or_else(|| self.key_length(), |c| c.key_length()); 152 assert!(key_len <= key.len()); 153 } 154 155 if let Some(iv) = iv { 156 let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length()); 157 assert!(iv_len <= iv.len()); 158 } 159 160 unsafe { 161 cvt(f( 162 self.as_ptr(), 163 type_.map_or(ptr::null(), |p| p.as_ptr()), 164 ptr::null_mut(), 165 key.map_or(ptr::null(), |k| k.as_ptr()), 166 iv.map_or(ptr::null(), |iv| iv.as_ptr()), 167 ))?; 168 } 169 170 Ok(()) 171 } 172 173 /// Initializes the context to perform envelope encryption. 174 /// 175 /// Normally this is called once to set both the cipher and public keys. However, this process may be split up by 176 /// first providing the cipher with no public keys and then setting the public keys with no cipher. 177 /// 178 /// `encrypted_keys` will contain the generated symmetric key encrypted with each corresponding asymmetric private 179 /// key. The generated IV will be written to `iv`. 180 /// 181 /// # Panics 182 /// 183 /// Panics if `pub_keys` is not the same size as `encrypted_keys`, the IV buffer is smaller than the cipher's IV 184 /// size, or if an IV is provided before the cipher. 185 #[corresponds(EVP_SealInit)] 186 #[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,187 pub fn seal_init<T>( 188 &mut self, 189 type_: Option<&CipherRef>, 190 pub_keys: &[PKey<T>], 191 encrypted_keys: &mut [Vec<u8>], 192 iv: Option<&mut [u8]>, 193 ) -> Result<(), ErrorStack> 194 where 195 T: HasPublic, 196 { 197 assert_eq!(pub_keys.len(), encrypted_keys.len()); 198 if !pub_keys.is_empty() { 199 let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length()); 200 assert!(iv.as_ref().map_or(0, |b| b.len()) >= iv_len); 201 } 202 203 for (pub_key, buf) in pub_keys.iter().zip(&mut *encrypted_keys) { 204 buf.resize(pub_key.size(), 0); 205 } 206 207 let mut keys = encrypted_keys 208 .iter_mut() 209 .map(|b| b.as_mut_ptr()) 210 .collect::<Vec<_>>(); 211 let mut key_lengths = vec![0; pub_keys.len()]; 212 let pub_keys_len = i32::try_from(pub_keys.len()).unwrap(); 213 214 unsafe { 215 cvt(ffi::EVP_SealInit( 216 self.as_ptr(), 217 type_.map_or(ptr::null(), |p| p.as_ptr()), 218 keys.as_mut_ptr(), 219 key_lengths.as_mut_ptr(), 220 iv.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 221 pub_keys.as_ptr() as *mut _, 222 pub_keys_len, 223 ))?; 224 } 225 226 for (buf, len) in encrypted_keys.iter_mut().zip(key_lengths) { 227 buf.truncate(len as usize); 228 } 229 230 Ok(()) 231 } 232 233 /// Initializes the context to perform envelope decryption. 234 /// 235 /// Normally this is called once with all of the arguments present. However, this process may be split up by first 236 /// providing the cipher alone and then after providing the rest of the arguments in a second call. 237 /// 238 /// # Panics 239 /// 240 /// Panics if the IV buffer is smaller than the cipher's required IV size or if the IV is provided before the 241 /// cipher. 242 #[corresponds(EVP_OpenInit)] 243 #[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,244 pub fn open_init<T>( 245 &mut self, 246 type_: Option<&CipherRef>, 247 encrypted_key: &[u8], 248 iv: Option<&[u8]>, 249 priv_key: Option<&PKeyRef<T>>, 250 ) -> Result<(), ErrorStack> 251 where 252 T: HasPrivate, 253 { 254 if priv_key.is_some() { 255 let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length()); 256 assert!(iv.map_or(0, |b| b.len()) >= iv_len); 257 } 258 259 let len = c_int::try_from(encrypted_key.len()).unwrap(); 260 unsafe { 261 cvt(ffi::EVP_OpenInit( 262 self.as_ptr(), 263 type_.map_or(ptr::null(), |p| p.as_ptr()), 264 encrypted_key.as_ptr(), 265 len, 266 iv.map_or(ptr::null(), |b| b.as_ptr()), 267 priv_key.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr), 268 ))?; 269 } 270 271 Ok(()) 272 } 273 assert_cipher(&self)274 fn assert_cipher(&self) { 275 unsafe { 276 assert!(!EVP_CIPHER_CTX_get0_cipher(self.as_ptr()).is_null()); 277 } 278 } 279 280 /// Returns the block size of the context's cipher. 281 /// 282 /// Stream ciphers will report a block size of 1. 283 /// 284 /// # Panics 285 /// 286 /// Panics if the context has not been initialized with a cipher. 287 #[corresponds(EVP_CIPHER_CTX_block_size)] block_size(&self) -> usize288 pub fn block_size(&self) -> usize { 289 self.assert_cipher(); 290 291 unsafe { ffi::EVP_CIPHER_CTX_block_size(self.as_ptr()) as usize } 292 } 293 294 /// Returns the key length of the context's cipher. 295 /// 296 /// # Panics 297 /// 298 /// Panics if the context has not been initialized with a cipher. 299 #[corresponds(EVP_CIPHER_CTX_key_length)] key_length(&self) -> usize300 pub fn key_length(&self) -> usize { 301 self.assert_cipher(); 302 303 unsafe { ffi::EVP_CIPHER_CTX_key_length(self.as_ptr()) as usize } 304 } 305 306 /// Generates a random key based on the configured cipher. 307 /// 308 /// # Panics 309 /// 310 /// Panics if the context has not been initialized with a cipher or if the buffer is smaller than the cipher's key 311 /// length. 312 /// 313 /// This corresponds to [`EVP_CIPHER_CTX_rand_key`]. 314 /// 315 /// [`EVP_CIPHER_CTX_rand_key`]: https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_CTX_rand_key.html 316 #[corresponds(EVP_CIPHER_CTX_rand_key)] 317 #[cfg(not(boringssl))] rand_key(&self, buf: &mut [u8]) -> Result<(), ErrorStack>318 pub fn rand_key(&self, buf: &mut [u8]) -> Result<(), ErrorStack> { 319 assert!(buf.len() >= self.key_length()); 320 321 unsafe { 322 cvt(ffi::EVP_CIPHER_CTX_rand_key( 323 self.as_ptr(), 324 buf.as_mut_ptr(), 325 ))?; 326 } 327 328 Ok(()) 329 } 330 331 /// Sets the length of the key expected by the context. 332 /// 333 /// Only some ciphers support configurable key lengths. 334 /// 335 /// # Panics 336 /// 337 /// Panics if the context has not been initialized with a cipher. 338 #[corresponds(EVP_CIPHER_CTX_set_key_length)] set_key_length(&mut self, len: usize) -> Result<(), ErrorStack>339 pub fn set_key_length(&mut self, len: usize) -> Result<(), ErrorStack> { 340 self.assert_cipher(); 341 342 unsafe { 343 cvt(ffi::EVP_CIPHER_CTX_set_key_length( 344 self.as_ptr(), 345 len.try_into().unwrap(), 346 ))?; 347 } 348 349 Ok(()) 350 } 351 352 /// Returns the length of the IV expected by this context. 353 /// 354 /// Returns 0 if the cipher does not use an IV. 355 /// 356 /// # Panics 357 /// 358 /// Panics if the context has not been initialized with a cipher. 359 #[corresponds(EVP_CIPHER_CTX_iv_length)] iv_length(&self) -> usize360 pub fn iv_length(&self) -> usize { 361 self.assert_cipher(); 362 363 unsafe { ffi::EVP_CIPHER_CTX_iv_length(self.as_ptr()) as usize } 364 } 365 366 /// Returns the `num` parameter of the cipher. 367 /// 368 /// Built-in ciphers typically use this to track how much of the 369 /// current underlying block has been "used" already. 370 /// 371 /// # Panics 372 /// 373 /// Panics if the context has not been initialized with a cipher. 374 #[corresponds(EVP_CIPHER_CTX_num)] 375 #[cfg(ossl110)] num(&self) -> usize376 pub fn num(&self) -> usize { 377 self.assert_cipher(); 378 379 unsafe { ffi::EVP_CIPHER_CTX_num(self.as_ptr()) as usize } 380 } 381 382 /// Sets the length of the IV expected by this context. 383 /// 384 /// Only some ciphers support configurable IV lengths. 385 /// 386 /// # Panics 387 /// 388 /// Panics if the context has not been initialized with a cipher. 389 #[corresponds(EVP_CIHPER_CTX_ctrl)] set_iv_length(&mut self, len: usize) -> Result<(), ErrorStack>390 pub fn set_iv_length(&mut self, len: usize) -> Result<(), ErrorStack> { 391 self.assert_cipher(); 392 393 let len = c_int::try_from(len).unwrap(); 394 395 unsafe { 396 cvt(ffi::EVP_CIPHER_CTX_ctrl( 397 self.as_ptr(), 398 ffi::EVP_CTRL_GCM_SET_IVLEN, 399 len, 400 ptr::null_mut(), 401 ))?; 402 } 403 404 Ok(()) 405 } 406 407 /// Returns the length of the authentication tag expected by this context. 408 /// 409 /// Returns 0 if the cipher is not authenticated. 410 /// 411 /// # Panics 412 /// 413 /// Panics if the context has not been initialized with a cipher. 414 /// 415 /// Requires OpenSSL 3.0.0 or newer. 416 #[corresponds(EVP_CIPHER_CTX_get_tag_length)] 417 #[cfg(ossl300)] tag_length(&self) -> usize418 pub fn tag_length(&self) -> usize { 419 self.assert_cipher(); 420 421 unsafe { ffi::EVP_CIPHER_CTX_get_tag_length(self.as_ptr()) as usize } 422 } 423 424 /// Retrieves the calculated authentication tag from the context. 425 /// 426 /// This should be called after [`Self::cipher_final`], and is only supported by authenticated ciphers. 427 /// 428 /// The size of the buffer indicates the size of the tag. While some ciphers support a range of tag sizes, it is 429 /// recommended to pick the maximum size. 430 #[corresponds(EVP_CIPHER_CTX_ctrl)] tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack>431 pub fn tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> { 432 let len = c_int::try_from(tag.len()).unwrap(); 433 434 unsafe { 435 cvt(ffi::EVP_CIPHER_CTX_ctrl( 436 self.as_ptr(), 437 ffi::EVP_CTRL_GCM_GET_TAG, 438 len, 439 tag.as_mut_ptr() as *mut _, 440 ))?; 441 } 442 443 Ok(()) 444 } 445 446 /// Sets the length of the generated authentication tag. 447 /// 448 /// This must be called when encrypting with a cipher in CCM mode to use a tag size other than the default. 449 #[corresponds(EVP_CIPHER_CTX_ctrl)] set_tag_length(&mut self, len: usize) -> Result<(), ErrorStack>450 pub fn set_tag_length(&mut self, len: usize) -> Result<(), ErrorStack> { 451 let len = c_int::try_from(len).unwrap(); 452 453 unsafe { 454 cvt(ffi::EVP_CIPHER_CTX_ctrl( 455 self.as_ptr(), 456 ffi::EVP_CTRL_GCM_SET_TAG, 457 len, 458 ptr::null_mut(), 459 ))?; 460 } 461 462 Ok(()) 463 } 464 465 /// Sets the authentication tag for verification during decryption. 466 #[corresponds(EVP_CIPHER_CTX_ctrl)] set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack>467 pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> { 468 let len = c_int::try_from(tag.len()).unwrap(); 469 470 unsafe { 471 cvt(ffi::EVP_CIPHER_CTX_ctrl( 472 self.as_ptr(), 473 ffi::EVP_CTRL_GCM_SET_TAG, 474 len, 475 tag.as_ptr() as *mut _, 476 ))?; 477 } 478 479 Ok(()) 480 } 481 482 /// Enables or disables padding. 483 /// 484 /// If padding is disabled, the plaintext must be an exact multiple of the cipher's block size. 485 #[corresponds(EVP_CIPHER_CTX_set_padding)] set_padding(&mut self, padding: bool)486 pub fn set_padding(&mut self, padding: bool) { 487 unsafe { 488 ffi::EVP_CIPHER_CTX_set_padding(self.as_ptr(), padding as c_int); 489 } 490 } 491 492 /// Sets the total length of plaintext data. 493 /// 494 /// This is required for ciphers operating in CCM mode. 495 #[corresponds(EVP_CipherUpdate)] set_data_len(&mut self, len: usize) -> Result<(), ErrorStack>496 pub fn set_data_len(&mut self, len: usize) -> Result<(), ErrorStack> { 497 let len = c_int::try_from(len).unwrap(); 498 499 unsafe { 500 cvt(ffi::EVP_CipherUpdate( 501 self.as_ptr(), 502 ptr::null_mut(), 503 &mut 0, 504 ptr::null(), 505 len, 506 ))?; 507 } 508 509 Ok(()) 510 } 511 512 /// Writes data into the context. 513 /// 514 /// Providing no output buffer will cause the input to be considered additional authenticated data (AAD). 515 /// 516 /// Returns the number of bytes written to `output`. 517 /// 518 /// # Panics 519 /// 520 /// Panics if `output` doesn't contain enough space for data to be 521 /// written as specified by [`Self::minimal_output_size`]. 522 #[corresponds(EVP_CipherUpdate)] cipher_update( &mut self, input: &[u8], output: Option<&mut [u8]>, ) -> Result<usize, ErrorStack>523 pub fn cipher_update( 524 &mut self, 525 input: &[u8], 526 output: Option<&mut [u8]>, 527 ) -> Result<usize, ErrorStack> { 528 if let Some(output) = &output { 529 let mut block_size = self.block_size(); 530 if block_size == 1 { 531 block_size = 0; 532 } 533 let min_output_size = input.len() + block_size; 534 assert!( 535 output.len() >= min_output_size, 536 "Output buffer size should be at least {} bytes.", 537 min_output_size 538 ); 539 } 540 541 unsafe { self.cipher_update_unchecked(input, output) } 542 } 543 544 /// Writes data into the context. 545 /// 546 /// Providing no output buffer will cause the input to be considered additional authenticated data (AAD). 547 /// 548 /// Returns the number of bytes written to `output`. 549 /// 550 /// This function is the same as [`Self::cipher_update`] but with the 551 /// output size check removed. It can be used when the exact 552 /// buffer size control is maintained by the caller. 553 /// 554 /// SAFETY: The caller is expected to provide `output` buffer 555 /// large enough to contain correct number of bytes. For streaming 556 /// ciphers the output buffer size should be at least as big as 557 /// the input buffer. For block ciphers the size of the output 558 /// buffer depends on the state of partially updated blocks. 559 #[corresponds(EVP_CipherUpdate)] cipher_update_unchecked( &mut self, input: &[u8], output: Option<&mut [u8]>, ) -> Result<usize, ErrorStack>560 pub unsafe fn cipher_update_unchecked( 561 &mut self, 562 input: &[u8], 563 output: Option<&mut [u8]>, 564 ) -> Result<usize, ErrorStack> { 565 let inlen = c_int::try_from(input.len()).unwrap(); 566 567 let mut outlen = 0; 568 569 cvt(ffi::EVP_CipherUpdate( 570 self.as_ptr(), 571 output.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 572 &mut outlen, 573 input.as_ptr(), 574 inlen, 575 ))?; 576 577 Ok(outlen as usize) 578 } 579 580 /// 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>581 pub fn cipher_update_vec( 582 &mut self, 583 input: &[u8], 584 output: &mut Vec<u8>, 585 ) -> Result<usize, ErrorStack> { 586 let base = output.len(); 587 output.resize(base + input.len() + self.block_size(), 0); 588 let len = self.cipher_update(input, Some(&mut output[base..]))?; 589 output.truncate(base + len); 590 591 Ok(len) 592 } 593 594 /// Finalizes the encryption or decryption process. 595 /// 596 /// Any remaining data will be written to the output buffer. 597 /// 598 /// Returns the number of bytes written to `output`. 599 /// 600 /// # Panics 601 /// 602 /// Panics if `output` is smaller than the cipher's block size. 603 #[corresponds(EVP_CipherFinal)] cipher_final(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack>604 pub fn cipher_final(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> { 605 let block_size = self.block_size(); 606 if block_size > 1 { 607 assert!(output.len() >= block_size); 608 } 609 610 unsafe { self.cipher_final_unchecked(output) } 611 } 612 613 /// Finalizes the encryption or decryption process. 614 /// 615 /// Any remaining data will be written to the output buffer. 616 /// 617 /// Returns the number of bytes written to `output`. 618 /// 619 /// This function is the same as [`Self::cipher_final`] but with 620 /// the output buffer size check removed. 621 /// 622 /// SAFETY: The caller is expected to provide `output` buffer 623 /// large enough to contain correct number of bytes. For streaming 624 /// ciphers the output buffer can be empty, for block ciphers the 625 /// output buffer should be at least as big as the block. 626 #[corresponds(EVP_CipherFinal)] cipher_final_unchecked( &mut self, output: &mut [u8], ) -> Result<usize, ErrorStack>627 pub unsafe fn cipher_final_unchecked( 628 &mut self, 629 output: &mut [u8], 630 ) -> Result<usize, ErrorStack> { 631 let mut outl = 0; 632 633 cvt(ffi::EVP_CipherFinal( 634 self.as_ptr(), 635 output.as_mut_ptr(), 636 &mut outl, 637 ))?; 638 639 Ok(outl as usize) 640 } 641 642 /// Like [`Self::cipher_final`] except that it appends output to a [`Vec`]. cipher_final_vec(&mut self, output: &mut Vec<u8>) -> Result<usize, ErrorStack>643 pub fn cipher_final_vec(&mut self, output: &mut Vec<u8>) -> Result<usize, ErrorStack> { 644 let base = output.len(); 645 output.resize(base + self.block_size(), 0); 646 let len = self.cipher_final(&mut output[base..])?; 647 output.truncate(base + len); 648 649 Ok(len) 650 } 651 } 652 653 #[cfg(test)] 654 mod test { 655 use super::*; 656 use crate::{cipher::Cipher, rand::rand_bytes}; 657 #[cfg(not(boringssl))] 658 use std::slice; 659 660 #[test] 661 #[cfg(not(boringssl))] seal_open()662 fn seal_open() { 663 let private_pem = include_bytes!("../test/rsa.pem"); 664 let public_pem = include_bytes!("../test/rsa.pem.pub"); 665 let private_key = PKey::private_key_from_pem(private_pem).unwrap(); 666 let public_key = PKey::public_key_from_pem(public_pem).unwrap(); 667 let cipher = Cipher::aes_256_cbc(); 668 let secret = b"My secret message"; 669 670 let mut ctx = CipherCtx::new().unwrap(); 671 let mut encrypted_key = vec![]; 672 let mut iv = vec![0; cipher.iv_length()]; 673 let mut encrypted = vec![]; 674 ctx.seal_init( 675 Some(cipher), 676 &[public_key], 677 slice::from_mut(&mut encrypted_key), 678 Some(&mut iv), 679 ) 680 .unwrap(); 681 ctx.cipher_update_vec(secret, &mut encrypted).unwrap(); 682 ctx.cipher_final_vec(&mut encrypted).unwrap(); 683 684 let mut decrypted = vec![]; 685 ctx.open_init(Some(cipher), &encrypted_key, Some(&iv), Some(&private_key)) 686 .unwrap(); 687 ctx.cipher_update_vec(&encrypted, &mut decrypted).unwrap(); 688 ctx.cipher_final_vec(&mut decrypted).unwrap(); 689 690 assert_eq!(secret, &decrypted[..]); 691 } 692 aes_128_cbc(cipher: &CipherRef)693 fn aes_128_cbc(cipher: &CipherRef) { 694 // from https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf 695 let key = hex::decode("2b7e151628aed2a6abf7158809cf4f3c").unwrap(); 696 let iv = hex::decode("000102030405060708090a0b0c0d0e0f").unwrap(); 697 let pt = hex::decode("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51") 698 .unwrap(); 699 let ct = hex::decode("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2") 700 .unwrap(); 701 702 let mut ctx = CipherCtx::new().unwrap(); 703 704 ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv)) 705 .unwrap(); 706 ctx.set_padding(false); 707 708 let mut buf = vec![]; 709 ctx.cipher_update_vec(&pt, &mut buf).unwrap(); 710 ctx.cipher_final_vec(&mut buf).unwrap(); 711 712 assert_eq!(buf, ct); 713 714 ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv)) 715 .unwrap(); 716 ctx.set_padding(false); 717 718 let mut buf = vec![]; 719 ctx.cipher_update_vec(&ct, &mut buf).unwrap(); 720 ctx.cipher_final_vec(&mut buf).unwrap(); 721 722 assert_eq!(buf, pt); 723 } 724 725 #[test] 726 #[cfg(ossl300)] fetched_aes_128_cbc()727 fn fetched_aes_128_cbc() { 728 let cipher = Cipher::fetch(None, "AES-128-CBC", None).unwrap(); 729 aes_128_cbc(&cipher); 730 } 731 732 #[test] default_aes_128_cbc()733 fn default_aes_128_cbc() { 734 let cipher = Cipher::aes_128_cbc(); 735 aes_128_cbc(cipher); 736 } 737 738 #[test] test_stream_ciphers()739 fn test_stream_ciphers() { 740 test_stream_cipher(Cipher::aes_192_ctr()); 741 test_stream_cipher(Cipher::aes_256_ctr()); 742 } 743 test_stream_cipher(cipher: &'static CipherRef)744 fn test_stream_cipher(cipher: &'static CipherRef) { 745 let mut key = vec![0; cipher.key_length()]; 746 rand_bytes(&mut key).unwrap(); 747 let mut iv = vec![0; cipher.iv_length()]; 748 rand_bytes(&mut iv).unwrap(); 749 750 let mut ctx = CipherCtx::new().unwrap(); 751 752 ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv)) 753 .unwrap(); 754 ctx.set_padding(false); 755 756 assert_eq!( 757 1, 758 cipher.block_size(), 759 "Need a stream cipher, not a block cipher" 760 ); 761 762 // update cipher with non-full block 763 // this is a streaming cipher so the number of output bytes 764 // will be the same as the number of input bytes 765 let mut output = vec![0; 32]; 766 let outlen = ctx 767 .cipher_update(&[1; 15], Some(&mut output[0..15])) 768 .unwrap(); 769 assert_eq!(15, outlen); 770 771 // update cipher with missing bytes from the previous block 772 // as previously it will output the same number of bytes as 773 // the input 774 let outlen = ctx 775 .cipher_update(&[1; 17], Some(&mut output[15..])) 776 .unwrap(); 777 assert_eq!(17, outlen); 778 779 ctx.cipher_final_vec(&mut vec![0; 0]).unwrap(); 780 781 // try to decrypt 782 ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv)) 783 .unwrap(); 784 ctx.set_padding(false); 785 786 // update cipher with non-full block 787 // expect that the output for stream cipher will contain 788 // the same number of bytes as the input 789 let mut output_decrypted = vec![0; 32]; 790 let outlen = ctx 791 .cipher_update(&output[0..15], Some(&mut output_decrypted[0..15])) 792 .unwrap(); 793 assert_eq!(15, outlen); 794 795 let outlen = ctx 796 .cipher_update(&output[15..], Some(&mut output_decrypted[15..])) 797 .unwrap(); 798 assert_eq!(17, outlen); 799 800 ctx.cipher_final_vec(&mut vec![0; 0]).unwrap(); 801 // check if the decrypted blocks are the same as input (all ones) 802 assert_eq!(output_decrypted, vec![1; 32]); 803 } 804 805 #[test] 806 #[should_panic(expected = "Output buffer size should be at least 33 bytes.")] full_block_updates_aes_128()807 fn full_block_updates_aes_128() { 808 output_buffer_too_small(Cipher::aes_128_cbc()); 809 } 810 811 #[test] 812 #[should_panic(expected = "Output buffer size should be at least 33 bytes.")] full_block_updates_aes_256()813 fn full_block_updates_aes_256() { 814 output_buffer_too_small(Cipher::aes_256_cbc()); 815 } 816 817 #[test] 818 #[should_panic(expected = "Output buffer size should be at least 17 bytes.")] full_block_updates_3des()819 fn full_block_updates_3des() { 820 output_buffer_too_small(Cipher::des_ede3_cbc()); 821 } 822 output_buffer_too_small(cipher: &'static CipherRef)823 fn output_buffer_too_small(cipher: &'static CipherRef) { 824 let mut key = vec![0; cipher.key_length()]; 825 rand_bytes(&mut key).unwrap(); 826 let mut iv = vec![0; cipher.iv_length()]; 827 rand_bytes(&mut iv).unwrap(); 828 829 let mut ctx = CipherCtx::new().unwrap(); 830 831 ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv)) 832 .unwrap(); 833 ctx.set_padding(false); 834 835 let block_size = cipher.block_size(); 836 assert!(block_size > 1, "Need a block cipher, not a stream cipher"); 837 838 ctx.cipher_update(&vec![0; block_size + 1], Some(&mut vec![0; block_size - 1])) 839 .unwrap(); 840 } 841 } 842