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