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