1 //! High level interface to certain symmetric ciphers.
2 //!
3 //! # Examples
4 //!
5 //! Encrypt data in AES128 CBC mode
6 //!
7 //! ```
8 //! use openssl::symm::{encrypt, Cipher};
9 //!
10 //! let cipher = Cipher::aes_128_cbc();
11 //! let data = b"Some Crypto Text";
12 //! let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
13 //! let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
14 //! let ciphertext = encrypt(
15 //!     cipher,
16 //!     key,
17 //!     Some(iv),
18 //!     data).unwrap();
19 //!
20 //! assert_eq!(
21 //!     b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\x87\x4D\
22 //!       \xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1",
23 //!     &ciphertext[..]);
24 //! ```
25 //!
26 //! Encrypting an asymmetric key with a symmetric cipher
27 //!
28 //! ```
29 //! use openssl::rsa::{Padding, Rsa};
30 //! use openssl::symm::Cipher;
31 //!
32 //! // Generate keypair and encrypt private key:
33 //! let keypair = Rsa::generate(2048).unwrap();
34 //! let cipher = Cipher::aes_256_cbc();
35 //! let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
36 //! let privkey_pem = keypair.private_key_to_pem_passphrase(cipher, b"Rust").unwrap();
37 //! // pubkey_pem and privkey_pem could be written to file here.
38 //!
39 //! // Load private and public key from string:
40 //! let pubkey = Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
41 //! let privkey = Rsa::private_key_from_pem_passphrase(&privkey_pem, b"Rust").unwrap();
42 //!
43 //! // Use the asymmetric keys to encrypt and decrypt a short message:
44 //! let msg = b"Foo bar";
45 //! let mut encrypted = vec![0; pubkey.size() as usize];
46 //! let mut decrypted = vec![0; privkey.size() as usize];
47 //! let len = pubkey.public_encrypt(msg, &mut encrypted, Padding::PKCS1).unwrap();
48 //! assert!(len > msg.len());
49 //! let len = privkey.private_decrypt(&encrypted, &mut decrypted, Padding::PKCS1).unwrap();
50 //! let output_string = String::from_utf8(decrypted[..len].to_vec()).unwrap();
51 //! assert_eq!("Foo bar", output_string);
52 //! println!("Decrypted: '{}'", output_string);
53 //! ```
54 
55 use ffi;
56 use libc::c_int;
57 use std::cmp;
58 use std::ptr;
59 
60 use error::ErrorStack;
61 use nid::Nid;
62 use {cvt, cvt_p};
63 
64 #[derive(Copy, Clone)]
65 pub enum Mode {
66     Encrypt,
67     Decrypt,
68 }
69 
70 /// Represents a particular cipher algorithm.
71 ///
72 /// See OpenSSL doc at [`EVP_EncryptInit`] for more information on each algorithms.
73 ///
74 /// [`EVP_EncryptInit`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_EncryptInit.html
75 #[derive(Copy, Clone, PartialEq, Eq)]
76 pub struct Cipher(*const ffi::EVP_CIPHER);
77 
78 impl Cipher {
79     /// Looks up the cipher for a certain nid.
80     ///
81     /// This corresponds to [`EVP_get_cipherbynid`]
82     ///
83     /// [`EVP_get_cipherbynid`]: https://www.openssl.org/docs/man1.0.2/crypto/EVP_get_cipherbyname.html
from_nid(nid: Nid) -> Option<Cipher>84     pub fn from_nid(nid: Nid) -> Option<Cipher> {
85         let ptr = unsafe { ffi::EVP_get_cipherbyname(ffi::OBJ_nid2sn(nid.as_raw())) };
86         if ptr.is_null() {
87             None
88         } else {
89             Some(Cipher(ptr))
90         }
91     }
92 
aes_128_ecb() -> Cipher93     pub fn aes_128_ecb() -> Cipher {
94         unsafe { Cipher(ffi::EVP_aes_128_ecb()) }
95     }
96 
aes_128_cbc() -> Cipher97     pub fn aes_128_cbc() -> Cipher {
98         unsafe { Cipher(ffi::EVP_aes_128_cbc()) }
99     }
100 
aes_128_xts() -> Cipher101     pub fn aes_128_xts() -> Cipher {
102         unsafe { Cipher(ffi::EVP_aes_128_xts()) }
103     }
104 
aes_128_ctr() -> Cipher105     pub fn aes_128_ctr() -> Cipher {
106         unsafe { Cipher(ffi::EVP_aes_128_ctr()) }
107     }
108 
aes_128_cfb1() -> Cipher109     pub fn aes_128_cfb1() -> Cipher {
110         unsafe { Cipher(ffi::EVP_aes_128_cfb1()) }
111     }
112 
aes_128_cfb128() -> Cipher113     pub fn aes_128_cfb128() -> Cipher {
114         unsafe { Cipher(ffi::EVP_aes_128_cfb128()) }
115     }
116 
aes_128_cfb8() -> Cipher117     pub fn aes_128_cfb8() -> Cipher {
118         unsafe { Cipher(ffi::EVP_aes_128_cfb8()) }
119     }
120 
aes_128_gcm() -> Cipher121     pub fn aes_128_gcm() -> Cipher {
122         unsafe { Cipher(ffi::EVP_aes_128_gcm()) }
123     }
124 
aes_128_ccm() -> Cipher125     pub fn aes_128_ccm() -> Cipher {
126         unsafe { Cipher(ffi::EVP_aes_128_ccm()) }
127     }
128 
aes_128_ofb() -> Cipher129     pub fn aes_128_ofb() -> Cipher {
130         unsafe { Cipher(ffi::EVP_aes_128_ofb()) }
131     }
132 
133     /// Requires OpenSSL 1.1.0 or newer.
134     #[cfg(ossl110)]
aes_128_ocb() -> Cipher135     pub fn aes_128_ocb() -> Cipher {
136         unsafe { Cipher(ffi::EVP_aes_128_ocb()) }
137     }
138 
aes_192_ecb() -> Cipher139     pub fn aes_192_ecb() -> Cipher {
140         unsafe { Cipher(ffi::EVP_aes_192_ecb()) }
141     }
142 
aes_192_cbc() -> Cipher143     pub fn aes_192_cbc() -> Cipher {
144         unsafe { Cipher(ffi::EVP_aes_192_cbc()) }
145     }
146 
aes_192_ctr() -> Cipher147     pub fn aes_192_ctr() -> Cipher {
148         unsafe { Cipher(ffi::EVP_aes_192_ctr()) }
149     }
150 
aes_192_cfb1() -> Cipher151     pub fn aes_192_cfb1() -> Cipher {
152         unsafe { Cipher(ffi::EVP_aes_192_cfb1()) }
153     }
154 
aes_192_cfb128() -> Cipher155     pub fn aes_192_cfb128() -> Cipher {
156         unsafe { Cipher(ffi::EVP_aes_192_cfb128()) }
157     }
158 
aes_192_cfb8() -> Cipher159     pub fn aes_192_cfb8() -> Cipher {
160         unsafe { Cipher(ffi::EVP_aes_192_cfb8()) }
161     }
162 
aes_192_gcm() -> Cipher163     pub fn aes_192_gcm() -> Cipher {
164         unsafe { Cipher(ffi::EVP_aes_192_gcm()) }
165     }
166 
aes_192_ccm() -> Cipher167     pub fn aes_192_ccm() -> Cipher {
168         unsafe { Cipher(ffi::EVP_aes_192_ccm()) }
169     }
170 
aes_192_ofb() -> Cipher171     pub fn aes_192_ofb() -> Cipher {
172         unsafe { Cipher(ffi::EVP_aes_192_ofb()) }
173     }
174 
175     /// Requires OpenSSL 1.1.0 or newer.
176     #[cfg(ossl110)]
aes_192_ocb() -> Cipher177     pub fn aes_192_ocb() -> Cipher {
178         unsafe { Cipher(ffi::EVP_aes_192_ocb()) }
179     }
180 
aes_256_ecb() -> Cipher181     pub fn aes_256_ecb() -> Cipher {
182         unsafe { Cipher(ffi::EVP_aes_256_ecb()) }
183     }
184 
aes_256_cbc() -> Cipher185     pub fn aes_256_cbc() -> Cipher {
186         unsafe { Cipher(ffi::EVP_aes_256_cbc()) }
187     }
188 
aes_256_xts() -> Cipher189     pub fn aes_256_xts() -> Cipher {
190         unsafe { Cipher(ffi::EVP_aes_256_xts()) }
191     }
192 
aes_256_ctr() -> Cipher193     pub fn aes_256_ctr() -> Cipher {
194         unsafe { Cipher(ffi::EVP_aes_256_ctr()) }
195     }
196 
aes_256_cfb1() -> Cipher197     pub fn aes_256_cfb1() -> Cipher {
198         unsafe { Cipher(ffi::EVP_aes_256_cfb1()) }
199     }
200 
aes_256_cfb128() -> Cipher201     pub fn aes_256_cfb128() -> Cipher {
202         unsafe { Cipher(ffi::EVP_aes_256_cfb128()) }
203     }
204 
aes_256_cfb8() -> Cipher205     pub fn aes_256_cfb8() -> Cipher {
206         unsafe { Cipher(ffi::EVP_aes_256_cfb8()) }
207     }
208 
aes_256_gcm() -> Cipher209     pub fn aes_256_gcm() -> Cipher {
210         unsafe { Cipher(ffi::EVP_aes_256_gcm()) }
211     }
212 
aes_256_ccm() -> Cipher213     pub fn aes_256_ccm() -> Cipher {
214         unsafe { Cipher(ffi::EVP_aes_256_ccm()) }
215     }
216 
aes_256_ofb() -> Cipher217     pub fn aes_256_ofb() -> Cipher {
218         unsafe { Cipher(ffi::EVP_aes_256_ofb()) }
219     }
220 
221     /// Requires OpenSSL 1.1.0 or newer.
222     #[cfg(ossl110)]
aes_256_ocb() -> Cipher223     pub fn aes_256_ocb() -> Cipher {
224         unsafe { Cipher(ffi::EVP_aes_256_ocb()) }
225     }
226 
bf_cbc() -> Cipher227     pub fn bf_cbc() -> Cipher {
228         unsafe { Cipher(ffi::EVP_bf_cbc()) }
229     }
230 
bf_ecb() -> Cipher231     pub fn bf_ecb() -> Cipher {
232         unsafe { Cipher(ffi::EVP_bf_ecb()) }
233     }
234 
bf_cfb64() -> Cipher235     pub fn bf_cfb64() -> Cipher {
236         unsafe { Cipher(ffi::EVP_bf_cfb64()) }
237     }
238 
bf_ofb() -> Cipher239     pub fn bf_ofb() -> Cipher {
240         unsafe { Cipher(ffi::EVP_bf_ofb()) }
241     }
242 
des_cbc() -> Cipher243     pub fn des_cbc() -> Cipher {
244         unsafe { Cipher(ffi::EVP_des_cbc()) }
245     }
246 
des_ecb() -> Cipher247     pub fn des_ecb() -> Cipher {
248         unsafe { Cipher(ffi::EVP_des_ecb()) }
249     }
250 
des_ede3() -> Cipher251     pub fn des_ede3() -> Cipher {
252         unsafe { Cipher(ffi::EVP_des_ede3()) }
253     }
254 
des_ede3_cbc() -> Cipher255     pub fn des_ede3_cbc() -> Cipher {
256         unsafe { Cipher(ffi::EVP_des_ede3_cbc()) }
257     }
258 
des_ede3_cfb64() -> Cipher259     pub fn des_ede3_cfb64() -> Cipher {
260         unsafe { Cipher(ffi::EVP_des_ede3_cfb64()) }
261     }
262 
rc4() -> Cipher263     pub fn rc4() -> Cipher {
264         unsafe { Cipher(ffi::EVP_rc4()) }
265     }
266 
267     /// Requires OpenSSL 1.1.0 or newer.
268     #[cfg(any(ossl110))]
chacha20() -> Cipher269     pub fn chacha20() -> Cipher {
270         unsafe { Cipher(ffi::EVP_chacha20()) }
271     }
272 
273     /// Requires OpenSSL 1.1.0 or newer.
274     #[cfg(any(ossl110))]
chacha20_poly1305() -> Cipher275     pub fn chacha20_poly1305() -> Cipher {
276         unsafe { Cipher(ffi::EVP_chacha20_poly1305()) }
277     }
278 
279     /// Creates a `Cipher` from a raw pointer to its OpenSSL type.
280     ///
281     /// # Safety
282     ///
283     /// The caller must ensure the pointer is valid for the `'static` lifetime.
from_ptr(ptr: *const ffi::EVP_CIPHER) -> Cipher284     pub unsafe fn from_ptr(ptr: *const ffi::EVP_CIPHER) -> Cipher {
285         Cipher(ptr)
286     }
287 
288     #[allow(clippy::trivially_copy_pass_by_ref)]
as_ptr(&self) -> *const ffi::EVP_CIPHER289     pub fn as_ptr(&self) -> *const ffi::EVP_CIPHER {
290         self.0
291     }
292 
293     /// Returns the length of keys used with this cipher.
294     #[allow(clippy::trivially_copy_pass_by_ref)]
key_len(&self) -> usize295     pub fn key_len(&self) -> usize {
296         unsafe { EVP_CIPHER_key_length(self.0) as usize }
297     }
298 
299     /// Returns the length of the IV used with this cipher, or `None` if the
300     /// cipher does not use an IV.
301     #[allow(clippy::trivially_copy_pass_by_ref)]
iv_len(&self) -> Option<usize>302     pub fn iv_len(&self) -> Option<usize> {
303         unsafe {
304             let len = EVP_CIPHER_iv_length(self.0) as usize;
305             if len == 0 {
306                 None
307             } else {
308                 Some(len)
309             }
310         }
311     }
312 
313     /// Returns the block size of the cipher.
314     ///
315     /// # Note
316     ///
317     /// Stream ciphers such as RC4 have a block size of 1.
318     #[allow(clippy::trivially_copy_pass_by_ref)]
block_size(&self) -> usize319     pub fn block_size(&self) -> usize {
320         unsafe { EVP_CIPHER_block_size(self.0) as usize }
321     }
322 
323     /// Determines whether the cipher is using CCM mode
is_ccm(self) -> bool324     fn is_ccm(self) -> bool {
325         // NOTE: OpenSSL returns pointers to static structs, which makes this work as expected
326         self == Cipher::aes_128_ccm() || self == Cipher::aes_256_ccm()
327     }
328 
329     /// Determines whether the cipher is using OCB mode
330     #[cfg(ossl110)]
is_ocb(self) -> bool331     fn is_ocb(self) -> bool {
332         self == Cipher::aes_128_ocb()
333             || self == Cipher::aes_192_ocb()
334             || self == Cipher::aes_256_ocb()
335     }
336 
337     #[cfg(not(ossl110))]
is_ocb(self) -> bool338     const fn is_ocb(self) -> bool {
339         false
340     }
341 }
342 
343 unsafe impl Sync for Cipher {}
344 unsafe impl Send for Cipher {}
345 
346 /// Represents a symmetric cipher context.
347 ///
348 /// Padding is enabled by default.
349 ///
350 /// # Examples
351 ///
352 /// Encrypt some plaintext in chunks, then decrypt the ciphertext back into plaintext, in AES 128
353 /// CBC mode.
354 ///
355 /// ```
356 /// use openssl::symm::{Cipher, Mode, Crypter};
357 ///
358 /// let plaintexts: [&[u8]; 2] = [b"Some Stream of", b" Crypto Text"];
359 /// let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
360 /// let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
361 /// let data_len = plaintexts.iter().fold(0, |sum, x| sum + x.len());
362 ///
363 /// // Create a cipher context for encryption.
364 /// let mut encrypter = Crypter::new(
365 ///     Cipher::aes_128_cbc(),
366 ///     Mode::Encrypt,
367 ///     key,
368 ///     Some(iv)).unwrap();
369 ///
370 /// let block_size = Cipher::aes_128_cbc().block_size();
371 /// let mut ciphertext = vec![0; data_len + block_size];
372 ///
373 /// // Encrypt 2 chunks of plaintexts successively.
374 /// let mut count = encrypter.update(plaintexts[0], &mut ciphertext).unwrap();
375 /// count += encrypter.update(plaintexts[1], &mut ciphertext[count..]).unwrap();
376 /// count += encrypter.finalize(&mut ciphertext[count..]).unwrap();
377 /// ciphertext.truncate(count);
378 ///
379 /// assert_eq!(
380 ///     b"\x0F\x21\x83\x7E\xB2\x88\x04\xAF\xD9\xCC\xE2\x03\x49\xB4\x88\xF6\xC4\x61\x0E\x32\x1C\xF9\
381 ///       \x0D\x66\xB1\xE6\x2C\x77\x76\x18\x8D\x99",
382 ///     &ciphertext[..]
383 /// );
384 ///
385 ///
386 /// // Let's pretend we don't know the plaintext, and now decrypt the ciphertext.
387 /// let data_len = ciphertext.len();
388 /// let ciphertexts = [&ciphertext[..9], &ciphertext[9..]];
389 ///
390 /// // Create a cipher context for decryption.
391 /// let mut decrypter = Crypter::new(
392 ///     Cipher::aes_128_cbc(),
393 ///     Mode::Decrypt,
394 ///     key,
395 ///     Some(iv)).unwrap();
396 /// let mut plaintext = vec![0; data_len + block_size];
397 ///
398 /// // Decrypt 2 chunks of ciphertexts successively.
399 /// let mut count = decrypter.update(ciphertexts[0], &mut plaintext).unwrap();
400 /// count += decrypter.update(ciphertexts[1], &mut plaintext[count..]).unwrap();
401 /// count += decrypter.finalize(&mut plaintext[count..]).unwrap();
402 /// plaintext.truncate(count);
403 ///
404 /// assert_eq!(b"Some Stream of Crypto Text", &plaintext[..]);
405 /// ```
406 pub struct Crypter {
407     ctx: *mut ffi::EVP_CIPHER_CTX,
408     block_size: usize,
409 }
410 
411 unsafe impl Sync for Crypter {}
412 unsafe impl Send for Crypter {}
413 
414 impl Crypter {
415     /// Creates a new `Crypter`.  The initialisation vector, `iv`, is not necesarry for certain
416     /// types of `Cipher`.
417     ///
418     /// # Panics
419     ///
420     /// Panics if an IV is required by the cipher but not provided.  Also make sure that the key
421     /// and IV size are appropriate for your cipher.
new( t: Cipher, mode: Mode, key: &[u8], iv: Option<&[u8]>, ) -> Result<Crypter, ErrorStack>422     pub fn new(
423         t: Cipher,
424         mode: Mode,
425         key: &[u8],
426         iv: Option<&[u8]>,
427     ) -> Result<Crypter, ErrorStack> {
428         ffi::init();
429 
430         unsafe {
431             let ctx = cvt_p(ffi::EVP_CIPHER_CTX_new())?;
432             let crypter = Crypter {
433                 ctx,
434                 block_size: t.block_size(),
435             };
436 
437             let mode = match mode {
438                 Mode::Encrypt => 1,
439                 Mode::Decrypt => 0,
440             };
441 
442             cvt(ffi::EVP_CipherInit_ex(
443                 crypter.ctx,
444                 t.as_ptr(),
445                 ptr::null_mut(),
446                 ptr::null_mut(),
447                 ptr::null_mut(),
448                 mode,
449             ))?;
450 
451             assert!(key.len() <= c_int::max_value() as usize);
452             cvt(ffi::EVP_CIPHER_CTX_set_key_length(
453                 crypter.ctx,
454                 key.len() as c_int,
455             ))?;
456 
457             let key = key.as_ptr() as *mut _;
458             let iv = match (iv, t.iv_len()) {
459                 (Some(iv), Some(len)) => {
460                     if iv.len() != len {
461                         assert!(iv.len() <= c_int::max_value() as usize);
462                         cvt(ffi::EVP_CIPHER_CTX_ctrl(
463                             crypter.ctx,
464                             ffi::EVP_CTRL_GCM_SET_IVLEN,
465                             iv.len() as c_int,
466                             ptr::null_mut(),
467                         ))?;
468                     }
469                     iv.as_ptr() as *mut _
470                 }
471                 (Some(_), None) | (None, None) => ptr::null_mut(),
472                 (None, Some(_)) => panic!("an IV is required for this cipher"),
473             };
474             cvt(ffi::EVP_CipherInit_ex(
475                 crypter.ctx,
476                 ptr::null(),
477                 ptr::null_mut(),
478                 key,
479                 iv,
480                 mode,
481             ))?;
482 
483             Ok(crypter)
484         }
485     }
486 
487     /// Enables or disables padding.
488     ///
489     /// If padding is disabled, total amount of data encrypted/decrypted must
490     /// be a multiple of the cipher's block size.
pad(&mut self, padding: bool)491     pub fn pad(&mut self, padding: bool) {
492         unsafe {
493             ffi::EVP_CIPHER_CTX_set_padding(self.ctx, padding as c_int);
494         }
495     }
496 
497     /// Sets the tag used to authenticate ciphertext in AEAD ciphers such as AES GCM.
498     ///
499     /// When decrypting cipher text using an AEAD cipher, this must be called before `finalize`.
set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack>500     pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> {
501         unsafe {
502             assert!(tag.len() <= c_int::max_value() as usize);
503             // NB: this constant is actually more general than just GCM.
504             cvt(ffi::EVP_CIPHER_CTX_ctrl(
505                 self.ctx,
506                 ffi::EVP_CTRL_GCM_SET_TAG,
507                 tag.len() as c_int,
508                 tag.as_ptr() as *mut _,
509             ))
510             .map(|_| ())
511         }
512     }
513 
514     /// Sets the length of the authentication tag to generate in AES CCM.
515     ///
516     /// When encrypting with AES CCM, the tag length needs to be explicitly set in order
517     /// to use a value different than the default 12 bytes.
set_tag_len(&mut self, tag_len: usize) -> Result<(), ErrorStack>518     pub fn set_tag_len(&mut self, tag_len: usize) -> Result<(), ErrorStack> {
519         unsafe {
520             assert!(tag_len <= c_int::max_value() as usize);
521             // NB: this constant is actually more general than just GCM.
522             cvt(ffi::EVP_CIPHER_CTX_ctrl(
523                 self.ctx,
524                 ffi::EVP_CTRL_GCM_SET_TAG,
525                 tag_len as c_int,
526                 ptr::null_mut(),
527             ))
528             .map(|_| ())
529         }
530     }
531 
532     /// Feeds total plaintext length to the cipher.
533     ///
534     /// The total plaintext or ciphertext length MUST be passed to the cipher when it operates in
535     /// CCM mode.
set_data_len(&mut self, data_len: usize) -> Result<(), ErrorStack>536     pub fn set_data_len(&mut self, data_len: usize) -> Result<(), ErrorStack> {
537         unsafe {
538             assert!(data_len <= c_int::max_value() as usize);
539             let mut len = 0;
540             cvt(ffi::EVP_CipherUpdate(
541                 self.ctx,
542                 ptr::null_mut(),
543                 &mut len,
544                 ptr::null_mut(),
545                 data_len as c_int,
546             ))
547             .map(|_| ())
548         }
549     }
550 
551     /// Feeds Additional Authenticated Data (AAD) through the cipher.
552     ///
553     /// This can only be used with AEAD ciphers such as AES GCM. Data fed in is not encrypted, but
554     /// is factored into the authentication tag. It must be called before the first call to
555     /// `update`.
aad_update(&mut self, input: &[u8]) -> Result<(), ErrorStack>556     pub fn aad_update(&mut self, input: &[u8]) -> Result<(), ErrorStack> {
557         unsafe {
558             assert!(input.len() <= c_int::max_value() as usize);
559             let mut len = 0;
560             cvt(ffi::EVP_CipherUpdate(
561                 self.ctx,
562                 ptr::null_mut(),
563                 &mut len,
564                 input.as_ptr(),
565                 input.len() as c_int,
566             ))
567             .map(|_| ())
568         }
569     }
570 
571     /// Feeds data from `input` through the cipher, writing encrypted/decrypted
572     /// bytes into `output`.
573     ///
574     /// The number of bytes written to `output` is returned. Note that this may
575     /// not be equal to the length of `input`.
576     ///
577     /// # Panics
578     ///
579     /// Panics for stream ciphers if `output.len() < input.len()`.
580     ///
581     /// Panics for block ciphers if `output.len() < input.len() + block_size`,
582     /// where `block_size` is the block size of the cipher (see `Cipher::block_size`).
583     ///
584     /// Panics if `output.len() > c_int::max_value()`.
update(&mut self, input: &[u8], output: &mut [u8]) -> Result<usize, ErrorStack>585     pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result<usize, ErrorStack> {
586         unsafe {
587             let block_size = if self.block_size > 1 {
588                 self.block_size
589             } else {
590                 0
591             };
592             assert!(output.len() >= input.len() + block_size);
593             assert!(output.len() <= c_int::max_value() as usize);
594             let mut outl = output.len() as c_int;
595             let inl = input.len() as c_int;
596 
597             cvt(ffi::EVP_CipherUpdate(
598                 self.ctx,
599                 output.as_mut_ptr(),
600                 &mut outl,
601                 input.as_ptr(),
602                 inl,
603             ))?;
604 
605             Ok(outl as usize)
606         }
607     }
608 
609     /// Finishes the encryption/decryption process, writing any remaining data
610     /// to `output`.
611     ///
612     /// The number of bytes written to `output` is returned.
613     ///
614     /// `update` should not be called after this method.
615     ///
616     /// # Panics
617     ///
618     /// Panics for block ciphers if `output.len() < block_size`,
619     /// where `block_size` is the block size of the cipher (see `Cipher::block_size`).
finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack>620     pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
621         unsafe {
622             if self.block_size > 1 {
623                 assert!(output.len() >= self.block_size);
624             }
625             let mut outl = cmp::min(output.len(), c_int::max_value() as usize) as c_int;
626 
627             cvt(ffi::EVP_CipherFinal(
628                 self.ctx,
629                 output.as_mut_ptr(),
630                 &mut outl,
631             ))?;
632 
633             Ok(outl as usize)
634         }
635     }
636 
637     /// Retrieves the authentication tag used to authenticate ciphertext in AEAD ciphers such
638     /// as AES GCM.
639     ///
640     /// When encrypting data with an AEAD cipher, this must be called after `finalize`.
641     ///
642     /// The size of the buffer indicates the required size of the tag. While some ciphers support a
643     /// range of tag sizes, it is recommended to pick the maximum size. For AES GCM, this is 16
644     /// bytes, for example.
get_tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack>645     pub fn get_tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> {
646         unsafe {
647             assert!(tag.len() <= c_int::max_value() as usize);
648             cvt(ffi::EVP_CIPHER_CTX_ctrl(
649                 self.ctx,
650                 ffi::EVP_CTRL_GCM_GET_TAG,
651                 tag.len() as c_int,
652                 tag.as_mut_ptr() as *mut _,
653             ))
654             .map(|_| ())
655         }
656     }
657 }
658 
659 impl Drop for Crypter {
drop(&mut self)660     fn drop(&mut self) {
661         unsafe {
662             ffi::EVP_CIPHER_CTX_free(self.ctx);
663         }
664     }
665 }
666 
667 /// Encrypts data in one go, and returns the encrypted data.
668 ///
669 /// Data is encrypted using the specified cipher type `t` in encrypt mode with the specified `key`
670 /// and initailization vector `iv`. Padding is enabled.
671 ///
672 /// This is a convenient interface to `Crypter` to encrypt all data in one go.  To encrypt a stream
673 /// of data increamentally , use `Crypter` instead.
674 ///
675 /// # Examples
676 ///
677 /// Encrypt data in AES128 CBC mode
678 ///
679 /// ```
680 /// use openssl::symm::{encrypt, Cipher};
681 ///
682 /// let cipher = Cipher::aes_128_cbc();
683 /// let data = b"Some Crypto Text";
684 /// let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
685 /// let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
686 /// let ciphertext = encrypt(
687 ///     cipher,
688 ///     key,
689 ///     Some(iv),
690 ///     data).unwrap();
691 ///
692 /// assert_eq!(
693 ///     b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\x87\x4D\
694 ///       \xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1",
695 ///     &ciphertext[..]);
696 /// ```
encrypt( t: Cipher, key: &[u8], iv: Option<&[u8]>, data: &[u8], ) -> Result<Vec<u8>, ErrorStack>697 pub fn encrypt(
698     t: Cipher,
699     key: &[u8],
700     iv: Option<&[u8]>,
701     data: &[u8],
702 ) -> Result<Vec<u8>, ErrorStack> {
703     cipher(t, Mode::Encrypt, key, iv, data)
704 }
705 
706 /// Decrypts data in one go, and returns the decrypted data.
707 ///
708 /// Data is decrypted using the specified cipher type `t` in decrypt mode with the specified `key`
709 /// and initailization vector `iv`. Padding is enabled.
710 ///
711 /// This is a convenient interface to `Crypter` to decrypt all data in one go.  To decrypt a  stream
712 /// of data increamentally , use `Crypter` instead.
713 ///
714 /// # Examples
715 ///
716 /// Decrypt data in AES128 CBC mode
717 ///
718 /// ```
719 /// use openssl::symm::{decrypt, Cipher};
720 ///
721 /// let cipher = Cipher::aes_128_cbc();
722 /// let data = b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\
723 ///              \x87\x4D\xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1";
724 /// let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
725 /// let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
726 /// let ciphertext = decrypt(
727 ///     cipher,
728 ///     key,
729 ///     Some(iv),
730 ///     data).unwrap();
731 ///
732 /// assert_eq!(
733 ///     b"Some Crypto Text",
734 ///     &ciphertext[..]);
735 /// ```
decrypt( t: Cipher, key: &[u8], iv: Option<&[u8]>, data: &[u8], ) -> Result<Vec<u8>, ErrorStack>736 pub fn decrypt(
737     t: Cipher,
738     key: &[u8],
739     iv: Option<&[u8]>,
740     data: &[u8],
741 ) -> Result<Vec<u8>, ErrorStack> {
742     cipher(t, Mode::Decrypt, key, iv, data)
743 }
744 
cipher( t: Cipher, mode: Mode, key: &[u8], iv: Option<&[u8]>, data: &[u8], ) -> Result<Vec<u8>, ErrorStack>745 fn cipher(
746     t: Cipher,
747     mode: Mode,
748     key: &[u8],
749     iv: Option<&[u8]>,
750     data: &[u8],
751 ) -> Result<Vec<u8>, ErrorStack> {
752     let mut c = Crypter::new(t, mode, key, iv)?;
753     let mut out = vec![0; data.len() + t.block_size()];
754     let count = c.update(data, &mut out)?;
755     let rest = c.finalize(&mut out[count..])?;
756     out.truncate(count + rest);
757     Ok(out)
758 }
759 
760 /// Like `encrypt`, but for AEAD ciphers such as AES GCM.
761 ///
762 /// Additional Authenticated Data can be provided in the `aad` field, and the authentication tag
763 /// will be copied into the `tag` field.
764 ///
765 /// The size of the `tag` buffer indicates the required size of the tag. While some ciphers support
766 /// a range of tag sizes, it is recommended to pick the maximum size. For AES GCM, this is 16 bytes,
767 /// for example.
encrypt_aead( t: Cipher, key: &[u8], iv: Option<&[u8]>, aad: &[u8], data: &[u8], tag: &mut [u8], ) -> Result<Vec<u8>, ErrorStack>768 pub fn encrypt_aead(
769     t: Cipher,
770     key: &[u8],
771     iv: Option<&[u8]>,
772     aad: &[u8],
773     data: &[u8],
774     tag: &mut [u8],
775 ) -> Result<Vec<u8>, ErrorStack> {
776     let mut c = Crypter::new(t, Mode::Encrypt, key, iv)?;
777     let mut out = vec![0; data.len() + t.block_size()];
778 
779     let is_ccm = t.is_ccm();
780     if is_ccm || t.is_ocb() {
781         c.set_tag_len(tag.len())?;
782         if is_ccm {
783             c.set_data_len(data.len())?;
784         }
785     }
786 
787     c.aad_update(aad)?;
788     let count = c.update(data, &mut out)?;
789     let rest = c.finalize(&mut out[count..])?;
790     c.get_tag(tag)?;
791     out.truncate(count + rest);
792     Ok(out)
793 }
794 
795 /// Like `decrypt`, but for AEAD ciphers such as AES GCM.
796 ///
797 /// Additional Authenticated Data can be provided in the `aad` field, and the authentication tag
798 /// should be provided in the `tag` field.
decrypt_aead( t: Cipher, key: &[u8], iv: Option<&[u8]>, aad: &[u8], data: &[u8], tag: &[u8], ) -> Result<Vec<u8>, ErrorStack>799 pub fn decrypt_aead(
800     t: Cipher,
801     key: &[u8],
802     iv: Option<&[u8]>,
803     aad: &[u8],
804     data: &[u8],
805     tag: &[u8],
806 ) -> Result<Vec<u8>, ErrorStack> {
807     let mut c = Crypter::new(t, Mode::Decrypt, key, iv)?;
808     let mut out = vec![0; data.len() + t.block_size()];
809 
810     let is_ccm = t.is_ccm();
811     if is_ccm || t.is_ocb() {
812         c.set_tag(tag)?;
813         if is_ccm {
814             c.set_data_len(data.len())?;
815         }
816     }
817 
818     c.aad_update(aad)?;
819     let count = c.update(data, &mut out)?;
820 
821     let rest = if t.is_ccm() {
822         0
823     } else {
824         c.set_tag(tag)?;
825         c.finalize(&mut out[count..])?
826     };
827 
828     out.truncate(count + rest);
829     Ok(out)
830 }
831 
832 cfg_if! {
833     if #[cfg(any(ossl110, libressl273))] {
834         use ffi::{EVP_CIPHER_block_size, EVP_CIPHER_iv_length, EVP_CIPHER_key_length};
835     } else {
836         #[allow(bad_style)]
837         pub unsafe fn EVP_CIPHER_iv_length(ptr: *const ffi::EVP_CIPHER) -> c_int {
838             (*ptr).iv_len
839         }
840 
841         #[allow(bad_style)]
842         pub unsafe fn EVP_CIPHER_block_size(ptr: *const ffi::EVP_CIPHER) -> c_int {
843             (*ptr).block_size
844         }
845 
846         #[allow(bad_style)]
847         pub unsafe fn EVP_CIPHER_key_length(ptr: *const ffi::EVP_CIPHER) -> c_int {
848             (*ptr).key_len
849         }
850     }
851 }
852 
853 #[cfg(test)]
854 mod tests {
855     use super::*;
856     use hex::{self, FromHex};
857 
858     #[test]
test_stream_cipher_output()859     fn test_stream_cipher_output() {
860         let key = [0u8; 16];
861         let iv = [0u8; 16];
862         let mut c = super::Crypter::new(
863             super::Cipher::aes_128_ctr(),
864             super::Mode::Encrypt,
865             &key,
866             Some(&iv),
867         )
868         .unwrap();
869 
870         assert_eq!(c.update(&[0u8; 15], &mut [0u8; 15]).unwrap(), 15);
871         assert_eq!(c.update(&[0u8; 1], &mut [0u8; 1]).unwrap(), 1);
872         assert_eq!(c.finalize(&mut [0u8; 0]).unwrap(), 0);
873     }
874 
875     // Test vectors from FIPS-197:
876     // http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
877     #[test]
test_aes_256_ecb()878     fn test_aes_256_ecb() {
879         let k0 = [
880             0x00u8, 0x01u8, 0x02u8, 0x03u8, 0x04u8, 0x05u8, 0x06u8, 0x07u8, 0x08u8, 0x09u8, 0x0au8,
881             0x0bu8, 0x0cu8, 0x0du8, 0x0eu8, 0x0fu8, 0x10u8, 0x11u8, 0x12u8, 0x13u8, 0x14u8, 0x15u8,
882             0x16u8, 0x17u8, 0x18u8, 0x19u8, 0x1au8, 0x1bu8, 0x1cu8, 0x1du8, 0x1eu8, 0x1fu8,
883         ];
884         let p0 = [
885             0x00u8, 0x11u8, 0x22u8, 0x33u8, 0x44u8, 0x55u8, 0x66u8, 0x77u8, 0x88u8, 0x99u8, 0xaau8,
886             0xbbu8, 0xccu8, 0xddu8, 0xeeu8, 0xffu8,
887         ];
888         let c0 = [
889             0x8eu8, 0xa2u8, 0xb7u8, 0xcau8, 0x51u8, 0x67u8, 0x45u8, 0xbfu8, 0xeau8, 0xfcu8, 0x49u8,
890             0x90u8, 0x4bu8, 0x49u8, 0x60u8, 0x89u8,
891         ];
892         let mut c = super::Crypter::new(
893             super::Cipher::aes_256_ecb(),
894             super::Mode::Encrypt,
895             &k0,
896             None,
897         )
898         .unwrap();
899         c.pad(false);
900         let mut r0 = vec![0; c0.len() + super::Cipher::aes_256_ecb().block_size()];
901         let count = c.update(&p0, &mut r0).unwrap();
902         let rest = c.finalize(&mut r0[count..]).unwrap();
903         r0.truncate(count + rest);
904         assert_eq!(hex::encode(&r0), hex::encode(c0));
905 
906         let mut c = super::Crypter::new(
907             super::Cipher::aes_256_ecb(),
908             super::Mode::Decrypt,
909             &k0,
910             None,
911         )
912         .unwrap();
913         c.pad(false);
914         let mut p1 = vec![0; r0.len() + super::Cipher::aes_256_ecb().block_size()];
915         let count = c.update(&r0, &mut p1).unwrap();
916         let rest = c.finalize(&mut p1[count..]).unwrap();
917         p1.truncate(count + rest);
918         assert_eq!(hex::encode(p1), hex::encode(p0));
919     }
920 
921     #[test]
test_aes_256_cbc_decrypt()922     fn test_aes_256_cbc_decrypt() {
923         let iv = [
924             4_u8, 223_u8, 153_u8, 219_u8, 28_u8, 142_u8, 234_u8, 68_u8, 227_u8, 69_u8, 98_u8,
925             107_u8, 208_u8, 14_u8, 236_u8, 60_u8,
926         ];
927         let data = [
928             143_u8, 210_u8, 75_u8, 63_u8, 214_u8, 179_u8, 155_u8, 241_u8, 242_u8, 31_u8, 154_u8,
929             56_u8, 198_u8, 145_u8, 192_u8, 64_u8, 2_u8, 245_u8, 167_u8, 220_u8, 55_u8, 119_u8,
930             233_u8, 136_u8, 139_u8, 27_u8, 71_u8, 242_u8, 119_u8, 175_u8, 65_u8, 207_u8,
931         ];
932         let ciphered_data = [
933             0x4a_u8, 0x2e_u8, 0xe5_u8, 0x6_u8, 0xbf_u8, 0xcf_u8, 0xf2_u8, 0xd7_u8, 0xea_u8,
934             0x2d_u8, 0xb1_u8, 0x85_u8, 0x6c_u8, 0x93_u8, 0x65_u8, 0x6f_u8,
935         ];
936         let mut cr = super::Crypter::new(
937             super::Cipher::aes_256_cbc(),
938             super::Mode::Decrypt,
939             &data,
940             Some(&iv),
941         )
942         .unwrap();
943         cr.pad(false);
944         let mut unciphered_data = vec![0; data.len() + super::Cipher::aes_256_cbc().block_size()];
945         let count = cr.update(&ciphered_data, &mut unciphered_data).unwrap();
946         let rest = cr.finalize(&mut unciphered_data[count..]).unwrap();
947         unciphered_data.truncate(count + rest);
948 
949         let expected_unciphered_data = b"I love turtles.\x01";
950 
951         assert_eq!(&unciphered_data, expected_unciphered_data);
952     }
953 
cipher_test(ciphertype: super::Cipher, pt: &str, ct: &str, key: &str, iv: &str)954     fn cipher_test(ciphertype: super::Cipher, pt: &str, ct: &str, key: &str, iv: &str) {
955         let pt = Vec::from_hex(pt).unwrap();
956         let ct = Vec::from_hex(ct).unwrap();
957         let key = Vec::from_hex(key).unwrap();
958         let iv = Vec::from_hex(iv).unwrap();
959 
960         let computed = super::decrypt(ciphertype, &key, Some(&iv), &ct).unwrap();
961         let expected = pt;
962 
963         if computed != expected {
964             println!("Computed: {}", hex::encode(&computed));
965             println!("Expected: {}", hex::encode(&expected));
966             if computed.len() != expected.len() {
967                 println!(
968                     "Lengths differ: {} in computed vs {} expected",
969                     computed.len(),
970                     expected.len()
971                 );
972             }
973             panic!("test failure");
974         }
975     }
976 
cipher_test_nopad(ciphertype: super::Cipher, pt: &str, ct: &str, key: &str, iv: &str)977     fn cipher_test_nopad(ciphertype: super::Cipher, pt: &str, ct: &str, key: &str, iv: &str) {
978         let pt = Vec::from_hex(pt).unwrap();
979         let ct = Vec::from_hex(ct).unwrap();
980         let key = Vec::from_hex(key).unwrap();
981         let iv = Vec::from_hex(iv).unwrap();
982 
983         let computed = {
984             let mut c = Crypter::new(ciphertype, Mode::Decrypt, &key, Some(&iv)).unwrap();
985             c.pad(false);
986             let mut out = vec![0; ct.len() + ciphertype.block_size()];
987             let count = c.update(&ct, &mut out).unwrap();
988             let rest = c.finalize(&mut out[count..]).unwrap();
989             out.truncate(count + rest);
990             out
991         };
992         let expected = pt;
993 
994         if computed != expected {
995             println!("Computed: {}", hex::encode(&computed));
996             println!("Expected: {}", hex::encode(&expected));
997             if computed.len() != expected.len() {
998                 println!(
999                     "Lengths differ: {} in computed vs {} expected",
1000                     computed.len(),
1001                     expected.len()
1002                 );
1003             }
1004             panic!("test failure");
1005         }
1006     }
1007 
1008     #[test]
test_rc4()1009     fn test_rc4() {
1010         let pt = "0000000000000000000000000000000000000000000000000000000000000000000000000000";
1011         let ct = "A68686B04D686AA107BD8D4CAB191A3EEC0A6294BC78B60F65C25CB47BD7BB3A48EFC4D26BE4";
1012         let key = "97CD440324DA5FD1F7955C1C13B6B466";
1013         let iv = "";
1014 
1015         cipher_test(super::Cipher::rc4(), pt, ct, key, iv);
1016     }
1017 
1018     #[test]
test_aes256_xts()1019     fn test_aes256_xts() {
1020         // Test case 174 from
1021         // http://csrc.nist.gov/groups/STM/cavp/documents/aes/XTSTestVectors.zip
1022         let pt = "77f4ef63d734ebd028508da66c22cdebdd52ecd6ee2ab0a50bc8ad0cfd692ca5fcd4e6dedc45df7f\
1023                   6503f462611dc542";
1024         let ct = "ce7d905a7776ac72f240d22aafed5e4eb7566cdc7211220e970da634ce015f131a5ecb8d400bc9e8\
1025                   4f0b81d8725dbbc7";
1026         let key = "b6bfef891f83b5ff073f2231267be51eb084b791fa19a154399c0684c8b2dfcb37de77d28bbda3b\
1027                    4180026ad640b74243b3133e7b9fae629403f6733423dae28";
1028         let iv = "db200efb7eaaa737dbdf40babb68953f";
1029 
1030         cipher_test(super::Cipher::aes_256_xts(), pt, ct, key, iv);
1031     }
1032 
1033     #[test]
test_aes128_ctr()1034     fn test_aes128_ctr() {
1035         let pt = "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411\
1036                   E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710";
1037         let ct = "874D6191B620E3261BEF6864990DB6CE9806F66B7970FDFF8617187BB9FFFDFF5AE4DF3EDBD5D35E\
1038                   5B4F09020DB03EAB1E031DDA2FBE03D1792170A0F3009CEE";
1039         let key = "2B7E151628AED2A6ABF7158809CF4F3C";
1040         let iv = "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF";
1041 
1042         cipher_test(super::Cipher::aes_128_ctr(), pt, ct, key, iv);
1043     }
1044 
1045     #[test]
test_aes128_cfb1()1046     fn test_aes128_cfb1() {
1047         // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1048 
1049         let pt = "6bc1";
1050         let ct = "68b3";
1051         let key = "2b7e151628aed2a6abf7158809cf4f3c";
1052         let iv = "000102030405060708090a0b0c0d0e0f";
1053 
1054         cipher_test(super::Cipher::aes_128_cfb1(), pt, ct, key, iv);
1055     }
1056 
1057     #[test]
test_aes128_cfb128()1058     fn test_aes128_cfb128() {
1059         let pt = "6bc1bee22e409f96e93d7e117393172a";
1060         let ct = "3b3fd92eb72dad20333449f8e83cfb4a";
1061         let key = "2b7e151628aed2a6abf7158809cf4f3c";
1062         let iv = "000102030405060708090a0b0c0d0e0f";
1063 
1064         cipher_test(super::Cipher::aes_128_cfb128(), pt, ct, key, iv);
1065     }
1066 
1067     #[test]
test_aes128_cfb8()1068     fn test_aes128_cfb8() {
1069         let pt = "6bc1bee22e409f96e93d7e117393172aae2d";
1070         let ct = "3b79424c9c0dd436bace9e0ed4586a4f32b9";
1071         let key = "2b7e151628aed2a6abf7158809cf4f3c";
1072         let iv = "000102030405060708090a0b0c0d0e0f";
1073 
1074         cipher_test(super::Cipher::aes_128_cfb8(), pt, ct, key, iv);
1075     }
1076 
1077     #[test]
test_aes128_ofb()1078     fn test_aes128_ofb() {
1079         // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1080 
1081         let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1082         let ct = "3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e";
1083         let key = "2b7e151628aed2a6abf7158809cf4f3c";
1084         let iv = "000102030405060708090a0b0c0d0e0f";
1085 
1086         cipher_test(super::Cipher::aes_128_ofb(), pt, ct, key, iv);
1087     }
1088 
1089     #[test]
test_aes192_ctr()1090     fn test_aes192_ctr() {
1091         // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1092 
1093         let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1094         let ct = "1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e941e36b26bd1ebc670d1bd1d665620abf74f78a7f6d29809585a97daec58c6b050";
1095         let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1096         let iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
1097 
1098         cipher_test(super::Cipher::aes_192_ctr(), pt, ct, key, iv);
1099     }
1100 
1101     #[test]
test_aes192_cfb1()1102     fn test_aes192_cfb1() {
1103         // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1104 
1105         let pt = "6bc1";
1106         let ct = "9359";
1107         let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1108         let iv = "000102030405060708090a0b0c0d0e0f";
1109 
1110         cipher_test(super::Cipher::aes_192_cfb1(), pt, ct, key, iv);
1111     }
1112 
1113     #[test]
test_aes192_cfb128()1114     fn test_aes192_cfb128() {
1115         // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1116 
1117         let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1118         let ct = "cdc80d6fddf18cab34c25909c99a417467ce7f7f81173621961a2b70171d3d7a2e1e8a1dd59b88b1c8e60fed1efac4c9c05f9f9ca9834fa042ae8fba584b09ff";
1119         let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1120         let iv = "000102030405060708090a0b0c0d0e0f";
1121 
1122         cipher_test(super::Cipher::aes_192_cfb128(), pt, ct, key, iv);
1123     }
1124 
1125     #[test]
test_aes192_cfb8()1126     fn test_aes192_cfb8() {
1127         // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1128 
1129         let pt = "6bc1bee22e409f96e93d7e117393172aae2d";
1130         let ct = "cda2521ef0a905ca44cd057cbf0d47a0678a";
1131         let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1132         let iv = "000102030405060708090a0b0c0d0e0f";
1133 
1134         cipher_test(super::Cipher::aes_192_cfb8(), pt, ct, key, iv);
1135     }
1136 
1137     #[test]
test_aes192_ofb()1138     fn test_aes192_ofb() {
1139         // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1140 
1141         let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1142         let ct = "cdc80d6fddf18cab34c25909c99a4174fcc28b8d4c63837c09e81700c11004018d9a9aeac0f6596f559c6d4daf59a5f26d9f200857ca6c3e9cac524bd9acc92a";
1143         let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1144         let iv = "000102030405060708090a0b0c0d0e0f";
1145 
1146         cipher_test(super::Cipher::aes_192_ofb(), pt, ct, key, iv);
1147     }
1148 
1149     #[test]
test_aes256_cfb1()1150     fn test_aes256_cfb1() {
1151         let pt = "6bc1";
1152         let ct = "9029";
1153         let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1154         let iv = "000102030405060708090a0b0c0d0e0f";
1155 
1156         cipher_test(super::Cipher::aes_256_cfb1(), pt, ct, key, iv);
1157     }
1158 
1159     #[test]
test_aes256_cfb128()1160     fn test_aes256_cfb128() {
1161         let pt = "6bc1bee22e409f96e93d7e117393172a";
1162         let ct = "dc7e84bfda79164b7ecd8486985d3860";
1163         let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1164         let iv = "000102030405060708090a0b0c0d0e0f";
1165 
1166         cipher_test(super::Cipher::aes_256_cfb128(), pt, ct, key, iv);
1167     }
1168 
1169     #[test]
test_aes256_cfb8()1170     fn test_aes256_cfb8() {
1171         let pt = "6bc1bee22e409f96e93d7e117393172aae2d";
1172         let ct = "dc1f1a8520a64db55fcc8ac554844e889700";
1173         let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1174         let iv = "000102030405060708090a0b0c0d0e0f";
1175 
1176         cipher_test(super::Cipher::aes_256_cfb8(), pt, ct, key, iv);
1177     }
1178 
1179     #[test]
test_aes256_ofb()1180     fn test_aes256_ofb() {
1181         // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1182 
1183         let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1184         let ct = "dc7e84bfda79164b7ecd8486985d38604febdc6740d20b3ac88f6ad82a4fb08d71ab47a086e86eedf39d1c5bba97c4080126141d67f37be8538f5a8be740e484";
1185         let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1186         let iv = "000102030405060708090a0b0c0d0e0f";
1187 
1188         cipher_test(super::Cipher::aes_256_ofb(), pt, ct, key, iv);
1189     }
1190 
1191     #[test]
test_bf_cbc()1192     fn test_bf_cbc() {
1193         // https://www.schneier.com/code/vectors.txt
1194 
1195         let pt = "37363534333231204E6F77206973207468652074696D6520666F722000000000";
1196         let ct = "6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC";
1197         let key = "0123456789ABCDEFF0E1D2C3B4A59687";
1198         let iv = "FEDCBA9876543210";
1199 
1200         cipher_test_nopad(super::Cipher::bf_cbc(), pt, ct, key, iv);
1201     }
1202 
1203     #[test]
test_bf_ecb()1204     fn test_bf_ecb() {
1205         let pt = "5CD54CA83DEF57DA";
1206         let ct = "B1B8CC0B250F09A0";
1207         let key = "0131D9619DC1376E";
1208         let iv = "0000000000000000";
1209 
1210         cipher_test_nopad(super::Cipher::bf_ecb(), pt, ct, key, iv);
1211     }
1212 
1213     #[test]
test_bf_cfb64()1214     fn test_bf_cfb64() {
1215         let pt = "37363534333231204E6F77206973207468652074696D6520666F722000";
1216         let ct = "E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3";
1217         let key = "0123456789ABCDEFF0E1D2C3B4A59687";
1218         let iv = "FEDCBA9876543210";
1219 
1220         cipher_test_nopad(super::Cipher::bf_cfb64(), pt, ct, key, iv);
1221     }
1222 
1223     #[test]
test_bf_ofb()1224     fn test_bf_ofb() {
1225         let pt = "37363534333231204E6F77206973207468652074696D6520666F722000";
1226         let ct = "E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA";
1227         let key = "0123456789ABCDEFF0E1D2C3B4A59687";
1228         let iv = "FEDCBA9876543210";
1229 
1230         cipher_test_nopad(super::Cipher::bf_ofb(), pt, ct, key, iv);
1231     }
1232 
1233     #[test]
test_des_cbc()1234     fn test_des_cbc() {
1235         let pt = "54686973206973206120746573742e";
1236         let ct = "6f2867cfefda048a4046ef7e556c7132";
1237         let key = "7cb66337f3d3c0fe";
1238         let iv = "0001020304050607";
1239 
1240         cipher_test(super::Cipher::des_cbc(), pt, ct, key, iv);
1241     }
1242 
1243     #[test]
test_des_ecb()1244     fn test_des_ecb() {
1245         let pt = "54686973206973206120746573742e";
1246         let ct = "0050ab8aecec758843fe157b4dde938c";
1247         let key = "7cb66337f3d3c0fe";
1248         let iv = "0001020304050607";
1249 
1250         cipher_test(super::Cipher::des_ecb(), pt, ct, key, iv);
1251     }
1252 
1253     #[test]
test_des_ede3()1254     fn test_des_ede3() {
1255         let pt = "9994f4c69d40ae4f34ff403b5cf39d4c8207ea5d3e19a5fd";
1256         let ct = "9e5c4297d60582f81071ac8ab7d0698d4c79de8b94c519858207ea5d3e19a5fd";
1257         let key = "010203040506070801020304050607080102030405060708";
1258         let iv = "5cc118306dc702e4";
1259 
1260         cipher_test(super::Cipher::des_ede3(), pt, ct, key, iv);
1261     }
1262 
1263     #[test]
test_des_ede3_cbc()1264     fn test_des_ede3_cbc() {
1265         let pt = "54686973206973206120746573742e";
1266         let ct = "6f2867cfefda048a4046ef7e556c7132";
1267         let key = "7cb66337f3d3c0fe7cb66337f3d3c0fe7cb66337f3d3c0fe";
1268         let iv = "0001020304050607";
1269 
1270         cipher_test(super::Cipher::des_ede3_cbc(), pt, ct, key, iv);
1271     }
1272 
1273     #[test]
test_des_ede3_cfb64()1274     fn test_des_ede3_cfb64() {
1275         let pt = "2b1773784b5889dc788477367daa98ad";
1276         let ct = "6f2867cfefda048a4046ef7e556c7132";
1277         let key = "7cb66337f3d3c0fe7cb66337f3d3c0fe7cb66337f3d3c0fe";
1278         let iv = "0001020304050607";
1279 
1280         cipher_test(super::Cipher::des_ede3_cfb64(), pt, ct, key, iv);
1281     }
1282 
1283     #[test]
test_aes128_gcm()1284     fn test_aes128_gcm() {
1285         let key = "0e00c76561d2bd9b40c3c15427e2b08f";
1286         let iv = "492cadaccd3ca3fbc9cf9f06eb3325c4e159850b0dbe98199b89b7af528806610b6f63998e1eae80c348e7\
1287              4cbb921d8326631631fc6a5d304f39166daf7ea15fa1977f101819adb510b50fe9932e12c5a85aa3fd1e73\
1288              d8d760af218be829903a77c63359d75edd91b4f6ed5465a72662f5055999e059e7654a8edc921aa0d496";
1289         let pt = "fef03c2d7fb15bf0d2df18007d99f967c878ad59359034f7bb2c19af120685d78e32f6b8b83b032019956c\
1290              a9c0195721476b85";
1291         let aad = "d8f1163d8c840292a2b2dacf4ac7c36aff8733f18fabb4fa5594544125e03d1e6e5d6d0fd61656c8d8f327\
1292              c92839ae5539bb469c9257f109ebff85aad7bd220fdaa95c022dbd0c7bb2d878ad504122c943045d3c5eba\
1293              8f1f56c0";
1294         let ct = "4f6cf471be7cbd2575cd5a1747aea8fe9dea83e51936beac3e68f66206922060c697ffa7af80ad6bb68f2c\
1295              f4fc97416ee52abe";
1296         let tag = "e20b6655";
1297 
1298         // this tag is smaller than you'd normally want, but I pulled this test from the part of
1299         // the NIST test vectors that cover 4 byte tags.
1300         let mut actual_tag = [0; 4];
1301         let out = encrypt_aead(
1302             Cipher::aes_128_gcm(),
1303             &Vec::from_hex(key).unwrap(),
1304             Some(&Vec::from_hex(iv).unwrap()),
1305             &Vec::from_hex(aad).unwrap(),
1306             &Vec::from_hex(pt).unwrap(),
1307             &mut actual_tag,
1308         )
1309         .unwrap();
1310         assert_eq!(ct, hex::encode(out));
1311         assert_eq!(tag, hex::encode(actual_tag));
1312 
1313         let out = decrypt_aead(
1314             Cipher::aes_128_gcm(),
1315             &Vec::from_hex(key).unwrap(),
1316             Some(&Vec::from_hex(iv).unwrap()),
1317             &Vec::from_hex(aad).unwrap(),
1318             &Vec::from_hex(ct).unwrap(),
1319             &Vec::from_hex(tag).unwrap(),
1320         )
1321         .unwrap();
1322         assert_eq!(pt, hex::encode(out));
1323     }
1324 
1325     #[test]
test_aes128_ccm()1326     fn test_aes128_ccm() {
1327         let key = "3ee186594f110fb788a8bf8aa8be5d4a";
1328         let nonce = "44f705d52acf27b7f17196aa9b";
1329         let aad = "2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57";
1330 
1331         let pt = "d71864877f2578db092daba2d6a1f9f4698a9c356c7830a1";
1332         let ct = "b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0";
1333         let tag = "d6965f5aa6e31302a9cc2b36";
1334 
1335         let mut actual_tag = [0; 12];
1336         let out = encrypt_aead(
1337             Cipher::aes_128_ccm(),
1338             &Vec::from_hex(key).unwrap(),
1339             Some(&Vec::from_hex(nonce).unwrap()),
1340             &Vec::from_hex(aad).unwrap(),
1341             &Vec::from_hex(pt).unwrap(),
1342             &mut actual_tag,
1343         )
1344         .unwrap();
1345 
1346         assert_eq!(ct, hex::encode(out));
1347         assert_eq!(tag, hex::encode(actual_tag));
1348 
1349         let out = decrypt_aead(
1350             Cipher::aes_128_ccm(),
1351             &Vec::from_hex(key).unwrap(),
1352             Some(&Vec::from_hex(nonce).unwrap()),
1353             &Vec::from_hex(aad).unwrap(),
1354             &Vec::from_hex(ct).unwrap(),
1355             &Vec::from_hex(tag).unwrap(),
1356         )
1357         .unwrap();
1358         assert_eq!(pt, hex::encode(out));
1359     }
1360 
1361     #[test]
test_aes128_ccm_verify_fail()1362     fn test_aes128_ccm_verify_fail() {
1363         let key = "3ee186594f110fb788a8bf8aa8be5d4a";
1364         let nonce = "44f705d52acf27b7f17196aa9b";
1365         let aad = "2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57";
1366 
1367         let ct = "b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0";
1368         let tag = "00005f5aa6e31302a9cc2b36";
1369 
1370         let out = decrypt_aead(
1371             Cipher::aes_128_ccm(),
1372             &Vec::from_hex(key).unwrap(),
1373             Some(&Vec::from_hex(nonce).unwrap()),
1374             &Vec::from_hex(aad).unwrap(),
1375             &Vec::from_hex(ct).unwrap(),
1376             &Vec::from_hex(tag).unwrap(),
1377         );
1378         assert!(out.is_err());
1379     }
1380 
1381     #[test]
test_aes256_ccm()1382     fn test_aes256_ccm() {
1383         let key = "7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d";
1384         let nonce = "dde2a362ce81b2b6913abc3095";
1385         let aad = "404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695";
1386 
1387         let pt = "7ebef26bf4ecf6f0ebb2eb860edbf900f27b75b4a6340fdb";
1388         let ct = "353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd";
1389         let tag = "2927a053c9244d3217a7ad05";
1390 
1391         let mut actual_tag = [0; 12];
1392         let out = encrypt_aead(
1393             Cipher::aes_256_ccm(),
1394             &Vec::from_hex(key).unwrap(),
1395             Some(&Vec::from_hex(nonce).unwrap()),
1396             &Vec::from_hex(aad).unwrap(),
1397             &Vec::from_hex(pt).unwrap(),
1398             &mut actual_tag,
1399         )
1400         .unwrap();
1401 
1402         assert_eq!(ct, hex::encode(out));
1403         assert_eq!(tag, hex::encode(actual_tag));
1404 
1405         let out = decrypt_aead(
1406             Cipher::aes_256_ccm(),
1407             &Vec::from_hex(key).unwrap(),
1408             Some(&Vec::from_hex(nonce).unwrap()),
1409             &Vec::from_hex(aad).unwrap(),
1410             &Vec::from_hex(ct).unwrap(),
1411             &Vec::from_hex(tag).unwrap(),
1412         )
1413         .unwrap();
1414         assert_eq!(pt, hex::encode(out));
1415     }
1416 
1417     #[test]
test_aes256_ccm_verify_fail()1418     fn test_aes256_ccm_verify_fail() {
1419         let key = "7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d";
1420         let nonce = "dde2a362ce81b2b6913abc3095";
1421         let aad = "404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695";
1422 
1423         let ct = "353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd";
1424         let tag = "0000a053c9244d3217a7ad05";
1425 
1426         let out = decrypt_aead(
1427             Cipher::aes_256_ccm(),
1428             &Vec::from_hex(key).unwrap(),
1429             Some(&Vec::from_hex(nonce).unwrap()),
1430             &Vec::from_hex(aad).unwrap(),
1431             &Vec::from_hex(ct).unwrap(),
1432             &Vec::from_hex(tag).unwrap(),
1433         );
1434         assert!(out.is_err());
1435     }
1436 
1437     #[test]
1438     #[cfg(ossl110)]
test_aes_128_ocb()1439     fn test_aes_128_ocb() {
1440         let key = "000102030405060708090a0b0c0d0e0f";
1441         let aad = "0001020304050607";
1442         let tag = "16dc76a46d47e1ead537209e8a96d14e";
1443         let iv = "000102030405060708090a0b";
1444         let pt = "0001020304050607";
1445         let ct = "92b657130a74b85a";
1446 
1447         let mut actual_tag = [0; 16];
1448         let out = encrypt_aead(
1449             Cipher::aes_128_ocb(),
1450             &Vec::from_hex(key).unwrap(),
1451             Some(&Vec::from_hex(iv).unwrap()),
1452             &Vec::from_hex(aad).unwrap(),
1453             &Vec::from_hex(pt).unwrap(),
1454             &mut actual_tag,
1455         )
1456         .unwrap();
1457 
1458         assert_eq!(ct, hex::encode(out));
1459         assert_eq!(tag, hex::encode(actual_tag));
1460 
1461         let out = decrypt_aead(
1462             Cipher::aes_128_ocb(),
1463             &Vec::from_hex(key).unwrap(),
1464             Some(&Vec::from_hex(iv).unwrap()),
1465             &Vec::from_hex(aad).unwrap(),
1466             &Vec::from_hex(ct).unwrap(),
1467             &Vec::from_hex(tag).unwrap(),
1468         )
1469         .unwrap();
1470         assert_eq!(pt, hex::encode(out));
1471     }
1472 
1473     #[test]
1474     #[cfg(ossl110)]
test_aes_128_ocb_fail()1475     fn test_aes_128_ocb_fail() {
1476         let key = "000102030405060708090a0b0c0d0e0f";
1477         let aad = "0001020304050607";
1478         let tag = "16dc76a46d47e1ead537209e8a96d14e";
1479         let iv = "000000000405060708090a0b";
1480         let ct = "92b657130a74b85a";
1481 
1482         let out = decrypt_aead(
1483             Cipher::aes_128_ocb(),
1484             &Vec::from_hex(key).unwrap(),
1485             Some(&Vec::from_hex(iv).unwrap()),
1486             &Vec::from_hex(aad).unwrap(),
1487             &Vec::from_hex(ct).unwrap(),
1488             &Vec::from_hex(tag).unwrap(),
1489         );
1490         assert!(out.is_err());
1491     }
1492 
1493     #[test]
1494     #[cfg(any(ossl110))]
test_chacha20()1495     fn test_chacha20() {
1496         let key = "0000000000000000000000000000000000000000000000000000000000000000";
1497         let iv = "00000000000000000000000000000000";
1498         let pt =
1499             "000000000000000000000000000000000000000000000000000000000000000000000000000000000\
1500              00000000000000000000000000000000000000000000000";
1501         let ct =
1502             "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7\
1503              724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586";
1504 
1505         cipher_test(Cipher::chacha20(), pt, ct, key, iv);
1506     }
1507 
1508     #[test]
1509     #[cfg(any(ossl110))]
test_chacha20_poly1305()1510     fn test_chacha20_poly1305() {
1511         let key = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f";
1512         let iv = "070000004041424344454647";
1513         let aad = "50515253c0c1c2c3c4c5c6c7";
1514         let pt =
1515             "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393\
1516              a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f722074\
1517              6865206675747572652c2073756e73637265656e20776f756c642062652069742e";
1518         let ct =
1519             "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca967128\
1520              2fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fa\
1521              b324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116";
1522         let tag = "1ae10b594f09e26a7e902ecbd0600691";
1523 
1524         let mut actual_tag = [0; 16];
1525         let out = encrypt_aead(
1526             Cipher::chacha20_poly1305(),
1527             &Vec::from_hex(key).unwrap(),
1528             Some(&Vec::from_hex(iv).unwrap()),
1529             &Vec::from_hex(aad).unwrap(),
1530             &Vec::from_hex(pt).unwrap(),
1531             &mut actual_tag,
1532         )
1533         .unwrap();
1534         assert_eq!(ct, hex::encode(out));
1535         assert_eq!(tag, hex::encode(actual_tag));
1536 
1537         let out = decrypt_aead(
1538             Cipher::chacha20_poly1305(),
1539             &Vec::from_hex(key).unwrap(),
1540             Some(&Vec::from_hex(iv).unwrap()),
1541             &Vec::from_hex(aad).unwrap(),
1542             &Vec::from_hex(ct).unwrap(),
1543             &Vec::from_hex(tag).unwrap(),
1544         )
1545         .unwrap();
1546         assert_eq!(pt, hex::encode(out));
1547     }
1548 }
1549