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