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