Skip to main content

openssl/
symm.rs

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//! ```
54use crate::cipher::CipherRef;
55use crate::cipher_ctx::{CipherCtx, CipherCtxRef};
56use crate::error::ErrorStack;
57use crate::nid::Nid;
58use foreign_types::ForeignTypeRef;
59use openssl_macros::corresponds;
60
61#[derive(Copy, Clone)]
62pub enum Mode {
63    Encrypt,
64    Decrypt,
65}
66
67/// Represents a particular cipher algorithm.
68///
69/// See OpenSSL doc at [`EVP_EncryptInit`] for more information on each algorithms.
70///
71/// [`EVP_EncryptInit`]: https://docs.openssl.org/master/man3/EVP_EncryptInit/
72#[derive(Copy, Clone, PartialEq, Eq)]
73pub struct Cipher(*const ffi::EVP_CIPHER);
74
75impl Cipher {
76    /// Looks up the cipher for a certain nid.
77    #[corresponds(EVP_get_cipherbynid)]
78    pub fn from_nid(nid: Nid) -> Option<Cipher> {
79        let ptr = unsafe { ffi::EVP_get_cipherbyname(ffi::OBJ_nid2sn(nid.as_raw())) };
80        if ptr.is_null() {
81            None
82        } else {
83            Some(Cipher(ptr))
84        }
85    }
86
87    /// Returns the cipher's Nid.
88    #[corresponds(EVP_CIPHER_nid)]
89    pub fn nid(&self) -> Nid {
90        let nid = unsafe { ffi::EVP_CIPHER_nid(self.0) };
91        Nid::from_raw(nid)
92    }
93
94    pub fn aes_128_ecb() -> Cipher {
95        unsafe { Cipher(ffi::EVP_aes_128_ecb()) }
96    }
97
98    pub fn aes_128_cbc() -> Cipher {
99        unsafe { Cipher(ffi::EVP_aes_128_cbc()) }
100    }
101
102    #[cfg(not(any(boringssl, awslc)))]
103    pub fn aes_128_xts() -> Cipher {
104        unsafe { Cipher(ffi::EVP_aes_128_xts()) }
105    }
106
107    pub fn aes_128_ctr() -> Cipher {
108        unsafe { Cipher(ffi::EVP_aes_128_ctr()) }
109    }
110
111    #[cfg(not(boringssl))]
112    pub fn aes_128_cfb1() -> Cipher {
113        unsafe { Cipher(ffi::EVP_aes_128_cfb1()) }
114    }
115
116    #[cfg(not(boringssl))]
117    pub fn aes_128_cfb128() -> Cipher {
118        unsafe { Cipher(ffi::EVP_aes_128_cfb128()) }
119    }
120
121    #[cfg(not(boringssl))]
122    pub fn aes_128_cfb8() -> Cipher {
123        unsafe { Cipher(ffi::EVP_aes_128_cfb8()) }
124    }
125
126    pub fn aes_128_gcm() -> Cipher {
127        unsafe { Cipher(ffi::EVP_aes_128_gcm()) }
128    }
129
130    #[cfg(not(boringssl))]
131    pub fn aes_128_ccm() -> Cipher {
132        unsafe { Cipher(ffi::EVP_aes_128_ccm()) }
133    }
134
135    pub fn aes_128_ofb() -> Cipher {
136        unsafe { Cipher(ffi::EVP_aes_128_ofb()) }
137    }
138
139    /// Requires OpenSSL 1.1.0 or newer.
140    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
141    pub fn aes_128_ocb() -> Cipher {
142        unsafe { Cipher(ffi::EVP_aes_128_ocb()) }
143    }
144
145    pub fn aes_192_ecb() -> Cipher {
146        unsafe { Cipher(ffi::EVP_aes_192_ecb()) }
147    }
148
149    pub fn aes_192_cbc() -> Cipher {
150        unsafe { Cipher(ffi::EVP_aes_192_cbc()) }
151    }
152
153    pub fn aes_192_ctr() -> Cipher {
154        unsafe { Cipher(ffi::EVP_aes_192_ctr()) }
155    }
156
157    #[cfg(not(boringssl))]
158    pub fn aes_192_cfb1() -> Cipher {
159        unsafe { Cipher(ffi::EVP_aes_192_cfb1()) }
160    }
161
162    #[cfg(not(boringssl))]
163    pub fn aes_192_cfb128() -> Cipher {
164        unsafe { Cipher(ffi::EVP_aes_192_cfb128()) }
165    }
166
167    #[cfg(not(boringssl))]
168    pub fn aes_192_cfb8() -> Cipher {
169        unsafe { Cipher(ffi::EVP_aes_192_cfb8()) }
170    }
171
172    pub fn aes_192_gcm() -> Cipher {
173        unsafe { Cipher(ffi::EVP_aes_192_gcm()) }
174    }
175
176    #[cfg(not(any(boringssl, awslc)))]
177    pub fn aes_192_ccm() -> Cipher {
178        unsafe { Cipher(ffi::EVP_aes_192_ccm()) }
179    }
180
181    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(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
187    pub fn aes_192_ocb() -> Cipher {
188        unsafe { Cipher(ffi::EVP_aes_192_ocb()) }
189    }
190
191    pub fn aes_256_ecb() -> Cipher {
192        unsafe { Cipher(ffi::EVP_aes_256_ecb()) }
193    }
194
195    pub fn aes_256_cbc() -> Cipher {
196        unsafe { Cipher(ffi::EVP_aes_256_cbc()) }
197    }
198
199    #[cfg(not(boringssl))]
200    pub fn aes_256_xts() -> Cipher {
201        unsafe { Cipher(ffi::EVP_aes_256_xts()) }
202    }
203
204    pub fn aes_256_ctr() -> Cipher {
205        unsafe { Cipher(ffi::EVP_aes_256_ctr()) }
206    }
207
208    #[cfg(not(boringssl))]
209    pub fn aes_256_cfb1() -> Cipher {
210        unsafe { Cipher(ffi::EVP_aes_256_cfb1()) }
211    }
212
213    #[cfg(not(boringssl))]
214    pub fn aes_256_cfb128() -> Cipher {
215        unsafe { Cipher(ffi::EVP_aes_256_cfb128()) }
216    }
217
218    #[cfg(not(boringssl))]
219    pub fn aes_256_cfb8() -> Cipher {
220        unsafe { Cipher(ffi::EVP_aes_256_cfb8()) }
221    }
222
223    pub fn aes_256_gcm() -> Cipher {
224        unsafe { Cipher(ffi::EVP_aes_256_gcm()) }
225    }
226
227    #[cfg(not(boringssl))]
228    pub fn aes_256_ccm() -> Cipher {
229        unsafe { Cipher(ffi::EVP_aes_256_ccm()) }
230    }
231
232    pub fn aes_256_ofb() -> Cipher {
233        unsafe { Cipher(ffi::EVP_aes_256_ofb()) }
234    }
235
236    /// Requires OpenSSL 1.1.0 or newer.
237    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
238    pub fn aes_256_ocb() -> Cipher {
239        unsafe { Cipher(ffi::EVP_aes_256_ocb()) }
240    }
241
242    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
243    pub fn bf_cbc() -> Cipher {
244        unsafe { Cipher(ffi::EVP_bf_cbc()) }
245    }
246
247    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
248    pub fn bf_ecb() -> Cipher {
249        unsafe { Cipher(ffi::EVP_bf_ecb()) }
250    }
251
252    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
253    pub fn bf_cfb64() -> Cipher {
254        unsafe { Cipher(ffi::EVP_bf_cfb64()) }
255    }
256
257    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
258    pub fn bf_ofb() -> Cipher {
259        unsafe { Cipher(ffi::EVP_bf_ofb()) }
260    }
261
262    pub fn des_cbc() -> Cipher {
263        unsafe { Cipher(ffi::EVP_des_cbc()) }
264    }
265
266    pub fn des_ecb() -> Cipher {
267        unsafe { Cipher(ffi::EVP_des_ecb()) }
268    }
269
270    pub fn des_ede3() -> Cipher {
271        unsafe { Cipher(ffi::EVP_des_ede3()) }
272    }
273
274    pub fn des_ede3_cbc() -> Cipher {
275        unsafe { Cipher(ffi::EVP_des_ede3_cbc()) }
276    }
277
278    pub fn des_ede3_ecb() -> Cipher {
279        unsafe { Cipher(ffi::EVP_des_ede3_ecb()) }
280    }
281
282    #[cfg(not(any(boringssl, awslc)))]
283    pub fn des_ede3_cfb64() -> Cipher {
284        unsafe { Cipher(ffi::EVP_des_ede3_cfb64()) }
285    }
286
287    #[cfg(not(any(boringssl, awslc)))]
288    pub fn des_ede3_cfb8() -> Cipher {
289        unsafe { Cipher(ffi::EVP_des_ede3_cfb8()) }
290    }
291
292    #[cfg(not(any(boringssl, awslc)))]
293    pub fn des_ede3_ofb() -> Cipher {
294        unsafe { Cipher(ffi::EVP_des_ede3_ofb()) }
295    }
296
297    #[cfg(not(osslconf = "OPENSSL_NO_RC4"))]
298    pub fn rc4() -> Cipher {
299        unsafe { Cipher(ffi::EVP_rc4()) }
300    }
301
302    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
303    pub fn camellia_128_cbc() -> Cipher {
304        unsafe { Cipher(ffi::EVP_camellia_128_cbc()) }
305    }
306
307    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
308    pub fn camellia_128_ecb() -> Cipher {
309        unsafe { Cipher(ffi::EVP_camellia_128_ecb()) }
310    }
311
312    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
313    pub fn camellia_128_ofb() -> Cipher {
314        unsafe { Cipher(ffi::EVP_camellia_128_ofb()) }
315    }
316
317    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
318    pub fn camellia_128_cfb128() -> Cipher {
319        unsafe { Cipher(ffi::EVP_camellia_128_cfb128()) }
320    }
321
322    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
323    pub fn camellia_192_cbc() -> Cipher {
324        unsafe { Cipher(ffi::EVP_camellia_192_cbc()) }
325    }
326
327    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
328    pub fn camellia_192_ecb() -> Cipher {
329        unsafe { Cipher(ffi::EVP_camellia_192_ecb()) }
330    }
331
332    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
333    pub fn camellia_192_ofb() -> Cipher {
334        unsafe { Cipher(ffi::EVP_camellia_192_ofb()) }
335    }
336
337    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
338    pub fn camellia_192_cfb128() -> Cipher {
339        unsafe { Cipher(ffi::EVP_camellia_192_cfb128()) }
340    }
341
342    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
343    pub fn camellia_256_cbc() -> Cipher {
344        unsafe { Cipher(ffi::EVP_camellia_256_cbc()) }
345    }
346
347    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
348    pub fn camellia_256_ecb() -> Cipher {
349        unsafe { Cipher(ffi::EVP_camellia_256_ecb()) }
350    }
351
352    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
353    pub fn camellia_256_ofb() -> Cipher {
354        unsafe { Cipher(ffi::EVP_camellia_256_ofb()) }
355    }
356
357    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
358    pub fn camellia_256_cfb128() -> Cipher {
359        unsafe { Cipher(ffi::EVP_camellia_256_cfb128()) }
360    }
361
362    #[cfg(not(osslconf = "OPENSSL_NO_CAST"))]
363    pub fn cast5_cbc() -> Cipher {
364        unsafe { Cipher(ffi::EVP_cast5_cbc()) }
365    }
366
367    #[cfg(not(osslconf = "OPENSSL_NO_CAST"))]
368    pub fn cast5_ecb() -> Cipher {
369        unsafe { Cipher(ffi::EVP_cast5_ecb()) }
370    }
371
372    #[cfg(not(osslconf = "OPENSSL_NO_CAST"))]
373    pub fn cast5_ofb() -> Cipher {
374        unsafe { Cipher(ffi::EVP_cast5_ofb()) }
375    }
376
377    #[cfg(not(osslconf = "OPENSSL_NO_CAST"))]
378    pub fn cast5_cfb64() -> Cipher {
379        unsafe { Cipher(ffi::EVP_cast5_cfb64()) }
380    }
381
382    /// Requires OpenSSL 1.1.0 or newer.
383    #[cfg(all(any(ossl110, libressl), not(osslconf = "OPENSSL_NO_CHACHA")))]
384    pub fn chacha20() -> Cipher {
385        unsafe { Cipher(ffi::EVP_chacha20()) }
386    }
387
388    /// Requires OpenSSL 1.1.0 or newer.
389    #[cfg(all(any(ossl110, libressl360, awslc), not(osslconf = "OPENSSL_NO_CHACHA")))]
390    pub fn chacha20_poly1305() -> Cipher {
391        unsafe { Cipher(ffi::EVP_chacha20_poly1305()) }
392    }
393
394    #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))]
395    pub fn idea_cbc() -> Cipher {
396        unsafe { Cipher(ffi::EVP_idea_cbc()) }
397    }
398
399    #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))]
400    pub fn idea_ecb() -> Cipher {
401        unsafe { Cipher(ffi::EVP_idea_ecb()) }
402    }
403
404    #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))]
405    pub fn idea_ofb() -> Cipher {
406        unsafe { Cipher(ffi::EVP_idea_ofb()) }
407    }
408
409    #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))]
410    pub fn idea_cfb64() -> Cipher {
411        unsafe { Cipher(ffi::EVP_idea_cfb64()) }
412    }
413
414    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
415    pub fn seed_cbc() -> Cipher {
416        unsafe { Cipher(ffi::EVP_seed_cbc()) }
417    }
418
419    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
420    pub fn seed_cfb128() -> Cipher {
421        unsafe { Cipher(ffi::EVP_seed_cfb128()) }
422    }
423
424    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
425    pub fn seed_ecb() -> Cipher {
426        unsafe { Cipher(ffi::EVP_seed_ecb()) }
427    }
428
429    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
430    pub fn seed_ofb() -> Cipher {
431        unsafe { Cipher(ffi::EVP_seed_ofb()) }
432    }
433
434    #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))]
435    pub fn sm4_ecb() -> Cipher {
436        unsafe { Cipher(ffi::EVP_sm4_ecb()) }
437    }
438
439    #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))]
440    pub fn sm4_cbc() -> Cipher {
441        unsafe { Cipher(ffi::EVP_sm4_cbc()) }
442    }
443
444    #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))]
445    pub fn sm4_ctr() -> Cipher {
446        unsafe { Cipher(ffi::EVP_sm4_ctr()) }
447    }
448
449    #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))]
450    pub fn sm4_cfb128() -> Cipher {
451        unsafe { Cipher(ffi::EVP_sm4_cfb128()) }
452    }
453
454    #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))]
455    pub fn sm4_ofb() -> Cipher {
456        unsafe { Cipher(ffi::EVP_sm4_ofb()) }
457    }
458
459    #[cfg(not(osslconf = "OPENSSL_NO_RC2"))]
460    pub fn rc2_cbc() -> Cipher {
461        unsafe { Cipher(ffi::EVP_rc2_cbc()) }
462    }
463
464    #[cfg(not(osslconf = "OPENSSL_NO_RC2"))]
465    pub fn rc2_40_cbc() -> Cipher {
466        unsafe { Cipher(ffi::EVP_rc2_40_cbc()) }
467    }
468
469    /// Creates a `Cipher` from a raw pointer to its OpenSSL type.
470    ///
471    /// # Safety
472    ///
473    /// The caller must ensure the pointer is valid for the `'static` lifetime.
474    pub unsafe fn from_ptr(ptr: *const ffi::EVP_CIPHER) -> Cipher {
475        Cipher(ptr)
476    }
477
478    #[allow(clippy::trivially_copy_pass_by_ref)]
479    pub fn as_ptr(&self) -> *const ffi::EVP_CIPHER {
480        self.0
481    }
482
483    /// Returns the length of keys used with this cipher.
484    #[allow(clippy::trivially_copy_pass_by_ref)]
485    pub fn key_len(&self) -> usize {
486        unsafe { EVP_CIPHER_key_length(self.0) as usize }
487    }
488
489    /// Returns the length of the IV used with this cipher, or `None` if the
490    /// cipher does not use an IV.
491    #[allow(clippy::trivially_copy_pass_by_ref)]
492    pub fn iv_len(&self) -> Option<usize> {
493        unsafe {
494            let len = EVP_CIPHER_iv_length(self.0) as usize;
495            if len == 0 {
496                None
497            } else {
498                Some(len)
499            }
500        }
501    }
502
503    /// Returns the block size of the cipher.
504    ///
505    /// # Note
506    ///
507    /// Stream ciphers such as RC4 have a block size of 1.
508    #[allow(clippy::trivially_copy_pass_by_ref)]
509    pub fn block_size(&self) -> usize {
510        unsafe { EVP_CIPHER_block_size(self.0) as usize }
511    }
512
513    /// Determines whether the cipher is using CCM mode
514    #[cfg(not(any(boringssl, awslc)))]
515    fn is_ccm(self) -> bool {
516        matches!(
517            self.nid(),
518            Nid::AES_128_CCM | Nid::AES_192_CCM | Nid::AES_256_CCM
519        )
520    }
521
522    #[cfg(any(boringssl, awslc))]
523    fn is_ccm(self) -> bool {
524        false
525    }
526
527    /// Determines whether the cipher is using OCB mode
528    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
529    fn is_ocb(self) -> bool {
530        matches!(
531            self.nid(),
532            Nid::AES_128_OCB | Nid::AES_192_OCB | Nid::AES_256_OCB
533        )
534    }
535
536    #[cfg(any(not(ossl110), osslconf = "OPENSSL_NO_OCB"))]
537    const fn is_ocb(self) -> bool {
538        false
539    }
540}
541
542unsafe impl Sync for Cipher {}
543unsafe impl Send for Cipher {}
544
545/// Represents a symmetric cipher context.
546///
547/// Padding is enabled by default.
548///
549/// # Examples
550///
551/// Encrypt some plaintext in chunks, then decrypt the ciphertext back into plaintext, in AES 128
552/// CBC mode.
553///
554/// ```
555/// use openssl::symm::{Cipher, Mode, Crypter};
556///
557/// let plaintexts: [&[u8]; 2] = [b"Some Stream of", b" Crypto Text"];
558/// let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
559/// let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
560/// let data_len = plaintexts.iter().fold(0, |sum, x| sum + x.len());
561///
562/// // Create a cipher context for encryption.
563/// let mut encrypter = Crypter::new(
564///     Cipher::aes_128_cbc(),
565///     Mode::Encrypt,
566///     key,
567///     Some(iv)).unwrap();
568///
569/// let block_size = Cipher::aes_128_cbc().block_size();
570/// let mut ciphertext = vec![0; data_len + block_size];
571///
572/// // Encrypt 2 chunks of plaintexts successively.
573/// let mut count = encrypter.update(plaintexts[0], &mut ciphertext).unwrap();
574/// count += encrypter.update(plaintexts[1], &mut ciphertext[count..]).unwrap();
575/// count += encrypter.finalize(&mut ciphertext[count..]).unwrap();
576/// ciphertext.truncate(count);
577///
578/// assert_eq!(
579///     b"\x0F\x21\x83\x7E\xB2\x88\x04\xAF\xD9\xCC\xE2\x03\x49\xB4\x88\xF6\xC4\x61\x0E\x32\x1C\xF9\
580///       \x0D\x66\xB1\xE6\x2C\x77\x76\x18\x8D\x99",
581///     &ciphertext[..]
582/// );
583///
584///
585/// // Let's pretend we don't know the plaintext, and now decrypt the ciphertext.
586/// let data_len = ciphertext.len();
587/// let ciphertexts = [&ciphertext[..9], &ciphertext[9..]];
588///
589/// // Create a cipher context for decryption.
590/// let mut decrypter = Crypter::new(
591///     Cipher::aes_128_cbc(),
592///     Mode::Decrypt,
593///     key,
594///     Some(iv)).unwrap();
595/// let mut plaintext = vec![0; data_len + block_size];
596///
597/// // Decrypt 2 chunks of ciphertexts successively.
598/// let mut count = decrypter.update(ciphertexts[0], &mut plaintext).unwrap();
599/// count += decrypter.update(ciphertexts[1], &mut plaintext[count..]).unwrap();
600/// count += decrypter.finalize(&mut plaintext[count..]).unwrap();
601/// plaintext.truncate(count);
602///
603/// assert_eq!(b"Some Stream of Crypto Text", &plaintext[..]);
604/// ```
605pub struct Crypter {
606    ctx: CipherCtx,
607}
608
609impl Crypter {
610    /// Creates a new `Crypter`.  The initialisation vector, `iv`, is not necessary for certain
611    /// types of `Cipher`.
612    ///
613    /// # Panics
614    ///
615    /// Panics if an IV is required by the cipher but not provided.  Also make sure that the key
616    /// and IV size are appropriate for your cipher.
617    pub fn new(
618        t: Cipher,
619        mode: Mode,
620        key: &[u8],
621        iv: Option<&[u8]>,
622    ) -> Result<Crypter, ErrorStack> {
623        assert!(
624            iv.is_some() || t.iv_len().is_none(),
625            "an IV is required for this cipher"
626        );
627        let mut ctx = CipherCtx::new()?;
628
629        let f = match mode {
630            Mode::Encrypt => CipherCtxRef::encrypt_init,
631            Mode::Decrypt => CipherCtxRef::decrypt_init,
632        };
633
634        f(
635            &mut ctx,
636            Some(unsafe { CipherRef::from_ptr(t.as_ptr() as *mut _) }),
637            None,
638            None,
639        )?;
640
641        ctx.set_key_length(key.len())?;
642
643        if let (Some(iv), Some(iv_len)) = (iv, t.iv_len()) {
644            if iv.len() != iv_len {
645                ctx.set_iv_length(iv.len())?;
646            }
647        }
648
649        f(&mut ctx, None, Some(key), iv)?;
650
651        Ok(Crypter { ctx })
652    }
653
654    /// Enables or disables padding.
655    ///
656    /// If padding is disabled, total amount of data encrypted/decrypted must
657    /// be a multiple of the cipher's block size.
658    pub fn pad(&mut self, padding: bool) {
659        self.ctx.set_padding(padding)
660    }
661
662    /// Sets the tag used to authenticate ciphertext in AEAD ciphers such as AES GCM.
663    ///
664    /// When decrypting cipher text using an AEAD cipher, this must be called before `finalize`.
665    pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> {
666        self.ctx.set_tag(tag)
667    }
668
669    /// Sets the length of the authentication tag to generate in AES CCM.
670    ///
671    /// When encrypting with AES CCM, the tag length needs to be explicitly set in order
672    /// to use a value different than the default 12 bytes.
673    pub fn set_tag_len(&mut self, tag_len: usize) -> Result<(), ErrorStack> {
674        self.ctx.set_tag_length(tag_len)
675    }
676
677    /// Feeds total plaintext length to the cipher.
678    ///
679    /// The total plaintext or ciphertext length MUST be passed to the cipher when it operates in
680    /// CCM mode.
681    pub fn set_data_len(&mut self, data_len: usize) -> Result<(), ErrorStack> {
682        self.ctx.set_data_len(data_len)
683    }
684
685    /// Feeds Additional Authenticated Data (AAD) through the cipher.
686    ///
687    /// This can only be used with AEAD ciphers such as AES GCM. Data fed in is not encrypted, but
688    /// is factored into the authentication tag. It must be called before the first call to
689    /// `update`.
690    pub fn aad_update(&mut self, input: &[u8]) -> Result<(), ErrorStack> {
691        self.ctx.cipher_update(input, None)?;
692        Ok(())
693    }
694
695    /// Feeds data from `input` through the cipher, writing encrypted/decrypted
696    /// bytes into `output`.
697    ///
698    /// The number of bytes written to `output` is returned. Note that this may
699    /// not be equal to the length of `input`.
700    ///
701    /// # Panics
702    ///
703    /// Panics for stream ciphers if `output.len() < input.len()`.
704    ///
705    /// Panics for block ciphers if `output.len() < input.len() + block_size`,
706    /// where `block_size` is the block size of the cipher (see `Cipher::block_size`).
707    ///
708    /// Panics if `output.len() > c_int::MAX`.
709    pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result<usize, ErrorStack> {
710        self.ctx.cipher_update(input, Some(output))
711    }
712
713    /// Feeds data from `input` through the cipher, writing encrypted/decrypted
714    /// bytes into `output`.
715    ///
716    /// The number of bytes written to `output` is returned. Note that this may
717    /// not be equal to the length of `input`.
718    ///
719    /// # Safety
720    ///
721    /// The caller must provide an `output` buffer large enough to contain
722    /// correct number of bytes. For streaming ciphers the output buffer size
723    /// should be at least as big as the input buffer. For block ciphers the
724    /// size of the output buffer depends on the state of partially updated
725    /// blocks.
726    pub unsafe fn update_unchecked(
727        &mut self,
728        input: &[u8],
729        output: &mut [u8],
730    ) -> Result<usize, ErrorStack> {
731        self.ctx.cipher_update_unchecked(input, Some(output))
732    }
733
734    /// Finishes the encryption/decryption process, writing any remaining data
735    /// to `output`.
736    ///
737    /// The number of bytes written to `output` is returned.
738    ///
739    /// `update` should not be called after this method.
740    ///
741    /// # Panics
742    ///
743    /// Panics for block ciphers if `output.len() < block_size`,
744    /// where `block_size` is the block size of the cipher (see `Cipher::block_size`).
745    pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
746        self.ctx.cipher_final(output)
747    }
748
749    /// Retrieves the authentication tag used to authenticate ciphertext in AEAD ciphers such
750    /// as AES GCM.
751    ///
752    /// When encrypting data with an AEAD cipher, this must be called after `finalize`.
753    ///
754    /// The size of the buffer indicates the required size of the tag. While some ciphers support a
755    /// range of tag sizes, it is recommended to pick the maximum size. For AES GCM, this is 16
756    /// bytes, for example.
757    pub fn get_tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> {
758        self.ctx.tag(tag)
759    }
760}
761
762/// Encrypts data in one go, and returns the encrypted data.
763///
764/// Data is encrypted using the specified cipher type `t` in encrypt mode with the specified `key`
765/// and initialization vector `iv`. Padding is enabled.
766///
767/// This is a convenient interface to `Crypter` to encrypt all data in one go.  To encrypt a stream
768/// of data incrementally , use `Crypter` instead.
769///
770/// # Examples
771///
772/// Encrypt data in AES128 CBC mode
773///
774/// ```
775/// use openssl::symm::{encrypt, Cipher};
776///
777/// let cipher = Cipher::aes_128_cbc();
778/// let data = b"Some Crypto Text";
779/// let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
780/// let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
781/// let ciphertext = encrypt(
782///     cipher,
783///     key,
784///     Some(iv),
785///     data).unwrap();
786///
787/// assert_eq!(
788///     b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\x87\x4D\
789///       \xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1",
790///     &ciphertext[..]);
791/// ```
792pub fn encrypt(
793    t: Cipher,
794    key: &[u8],
795    iv: Option<&[u8]>,
796    data: &[u8],
797) -> Result<Vec<u8>, ErrorStack> {
798    cipher(t, Mode::Encrypt, key, iv, data)
799}
800
801/// Decrypts data in one go, and returns the decrypted data.
802///
803/// Data is decrypted using the specified cipher type `t` in decrypt mode with the specified `key`
804/// and initialization vector `iv`. Padding is enabled.
805///
806/// This is a convenient interface to `Crypter` to decrypt all data in one go.  To decrypt a  stream
807/// of data incrementally , use `Crypter` instead.
808///
809/// # Examples
810///
811/// Decrypt data in AES128 CBC mode
812///
813/// ```
814/// use openssl::symm::{decrypt, Cipher};
815///
816/// let cipher = Cipher::aes_128_cbc();
817/// let data = b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\
818///              \x87\x4D\xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1";
819/// let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
820/// let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
821/// let ciphertext = decrypt(
822///     cipher,
823///     key,
824///     Some(iv),
825///     data).unwrap();
826///
827/// assert_eq!(
828///     b"Some Crypto Text",
829///     &ciphertext[..]);
830/// ```
831pub fn decrypt(
832    t: Cipher,
833    key: &[u8],
834    iv: Option<&[u8]>,
835    data: &[u8],
836) -> Result<Vec<u8>, ErrorStack> {
837    cipher(t, Mode::Decrypt, key, iv, data)
838}
839
840fn cipher(
841    t: Cipher,
842    mode: Mode,
843    key: &[u8],
844    iv: Option<&[u8]>,
845    data: &[u8],
846) -> Result<Vec<u8>, ErrorStack> {
847    let mut c = Crypter::new(t, mode, key, iv)?;
848    let mut out = vec![0; data.len() + t.block_size()];
849    let count = c.update(data, &mut out)?;
850    let rest = c.finalize(&mut out[count..])?;
851    out.truncate(count + rest);
852    Ok(out)
853}
854
855/// Like `encrypt`, but for AEAD ciphers such as AES GCM.
856///
857/// Additional Authenticated Data can be provided in the `aad` field, and the authentication tag
858/// will be copied into the `tag` field.
859///
860/// The size of the `tag` buffer indicates the required size of the tag. While some ciphers support
861/// a range of tag sizes, it is recommended to pick the maximum size. For AES GCM, this is 16 bytes,
862/// for example.
863pub fn encrypt_aead(
864    t: Cipher,
865    key: &[u8],
866    iv: Option<&[u8]>,
867    aad: &[u8],
868    data: &[u8],
869    tag: &mut [u8],
870) -> Result<Vec<u8>, ErrorStack> {
871    let mut c = Crypter::new(t, Mode::Encrypt, key, iv)?;
872    let mut out = vec![0; data.len() + t.block_size()];
873
874    let is_ccm = t.is_ccm();
875    if is_ccm || t.is_ocb() {
876        c.set_tag_len(tag.len())?;
877        if is_ccm {
878            c.set_data_len(data.len())?;
879        }
880    }
881
882    c.aad_update(aad)?;
883    let count = c.update(data, &mut out)?;
884    let rest = c.finalize(&mut out[count..])?;
885    c.get_tag(tag)?;
886    out.truncate(count + rest);
887    Ok(out)
888}
889
890/// Like `decrypt`, but for AEAD ciphers such as AES GCM.
891///
892/// Additional Authenticated Data can be provided in the `aad` field, and the authentication tag
893/// should be provided in the `tag` field.
894pub fn decrypt_aead(
895    t: Cipher,
896    key: &[u8],
897    iv: Option<&[u8]>,
898    aad: &[u8],
899    data: &[u8],
900    tag: &[u8],
901) -> Result<Vec<u8>, ErrorStack> {
902    let mut c = Crypter::new(t, Mode::Decrypt, key, iv)?;
903    let mut out = vec![0; data.len() + t.block_size()];
904
905    let is_ccm = t.is_ccm();
906    if is_ccm || t.is_ocb() {
907        c.set_tag(tag)?;
908        if is_ccm {
909            c.set_data_len(data.len())?;
910        }
911    }
912
913    c.aad_update(aad)?;
914    let count = c.update(data, &mut out)?;
915
916    let rest = if t.is_ccm() {
917        0
918    } else {
919        c.set_tag(tag)?;
920        c.finalize(&mut out[count..])?
921    };
922
923    out.truncate(count + rest);
924    Ok(out)
925}
926
927use ffi::{EVP_CIPHER_block_size, EVP_CIPHER_iv_length, EVP_CIPHER_key_length};
928
929#[cfg(test)]
930mod tests {
931    use super::*;
932    use hex::{self, FromHex};
933
934    #[test]
935    fn test_stream_cipher_output() {
936        let key = [0u8; 16];
937        let iv = [0u8; 16];
938        let mut c = super::Crypter::new(
939            super::Cipher::aes_128_ctr(),
940            super::Mode::Encrypt,
941            &key,
942            Some(&iv),
943        )
944        .unwrap();
945
946        assert_eq!(c.update(&[0u8; 15], &mut [0u8; 15]).unwrap(), 15);
947        assert_eq!(c.update(&[0u8; 1], &mut [0u8; 1]).unwrap(), 1);
948        assert_eq!(c.finalize(&mut [0u8; 0]).unwrap(), 0);
949    }
950
951    // Test vectors from FIPS-197:
952    // http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
953    #[test]
954    fn test_aes_256_ecb() {
955        let k0 = [
956            0x00u8, 0x01u8, 0x02u8, 0x03u8, 0x04u8, 0x05u8, 0x06u8, 0x07u8, 0x08u8, 0x09u8, 0x0au8,
957            0x0bu8, 0x0cu8, 0x0du8, 0x0eu8, 0x0fu8, 0x10u8, 0x11u8, 0x12u8, 0x13u8, 0x14u8, 0x15u8,
958            0x16u8, 0x17u8, 0x18u8, 0x19u8, 0x1au8, 0x1bu8, 0x1cu8, 0x1du8, 0x1eu8, 0x1fu8,
959        ];
960        let p0 = [
961            0x00u8, 0x11u8, 0x22u8, 0x33u8, 0x44u8, 0x55u8, 0x66u8, 0x77u8, 0x88u8, 0x99u8, 0xaau8,
962            0xbbu8, 0xccu8, 0xddu8, 0xeeu8, 0xffu8,
963        ];
964        let c0 = [
965            0x8eu8, 0xa2u8, 0xb7u8, 0xcau8, 0x51u8, 0x67u8, 0x45u8, 0xbfu8, 0xeau8, 0xfcu8, 0x49u8,
966            0x90u8, 0x4bu8, 0x49u8, 0x60u8, 0x89u8,
967        ];
968        let mut c = super::Crypter::new(
969            super::Cipher::aes_256_ecb(),
970            super::Mode::Encrypt,
971            &k0,
972            None,
973        )
974        .unwrap();
975        c.pad(false);
976        let mut r0 = vec![0; c0.len() + super::Cipher::aes_256_ecb().block_size()];
977        let count = c.update(&p0, &mut r0).unwrap();
978        let rest = c.finalize(&mut r0[count..]).unwrap();
979        r0.truncate(count + rest);
980        assert_eq!(hex::encode(&r0), hex::encode(c0));
981
982        let mut c = super::Crypter::new(
983            super::Cipher::aes_256_ecb(),
984            super::Mode::Decrypt,
985            &k0,
986            None,
987        )
988        .unwrap();
989        c.pad(false);
990        let mut p1 = vec![0; r0.len() + super::Cipher::aes_256_ecb().block_size()];
991        let count = c.update(&r0, &mut p1).unwrap();
992        let rest = c.finalize(&mut p1[count..]).unwrap();
993        p1.truncate(count + rest);
994        assert_eq!(hex::encode(p1), hex::encode(p0));
995    }
996
997    #[test]
998    fn test_aes_256_cbc_decrypt() {
999        let iv = [
1000            4_u8, 223_u8, 153_u8, 219_u8, 28_u8, 142_u8, 234_u8, 68_u8, 227_u8, 69_u8, 98_u8,
1001            107_u8, 208_u8, 14_u8, 236_u8, 60_u8,
1002        ];
1003        let data = [
1004            143_u8, 210_u8, 75_u8, 63_u8, 214_u8, 179_u8, 155_u8, 241_u8, 242_u8, 31_u8, 154_u8,
1005            56_u8, 198_u8, 145_u8, 192_u8, 64_u8, 2_u8, 245_u8, 167_u8, 220_u8, 55_u8, 119_u8,
1006            233_u8, 136_u8, 139_u8, 27_u8, 71_u8, 242_u8, 119_u8, 175_u8, 65_u8, 207_u8,
1007        ];
1008        let ciphered_data = [
1009            0x4a_u8, 0x2e_u8, 0xe5_u8, 0x6_u8, 0xbf_u8, 0xcf_u8, 0xf2_u8, 0xd7_u8, 0xea_u8,
1010            0x2d_u8, 0xb1_u8, 0x85_u8, 0x6c_u8, 0x93_u8, 0x65_u8, 0x6f_u8,
1011        ];
1012        let mut cr = super::Crypter::new(
1013            super::Cipher::aes_256_cbc(),
1014            super::Mode::Decrypt,
1015            &data,
1016            Some(&iv),
1017        )
1018        .unwrap();
1019        cr.pad(false);
1020        let mut unciphered_data = vec![0; data.len() + super::Cipher::aes_256_cbc().block_size()];
1021        let count = cr.update(&ciphered_data, &mut unciphered_data).unwrap();
1022        let rest = cr.finalize(&mut unciphered_data[count..]).unwrap();
1023        unciphered_data.truncate(count + rest);
1024
1025        let expected_unciphered_data = b"I love turtles.\x01";
1026
1027        assert_eq!(&unciphered_data, expected_unciphered_data);
1028    }
1029
1030    fn cipher_test(ciphertype: super::Cipher, pt: &str, ct: &str, key: &str, iv: &str) {
1031        let pt = Vec::from_hex(pt).unwrap();
1032        let ct = Vec::from_hex(ct).unwrap();
1033        let key = Vec::from_hex(key).unwrap();
1034        let iv = Vec::from_hex(iv).unwrap();
1035
1036        let computed = super::decrypt(ciphertype, &key, Some(&iv), &ct).unwrap();
1037        let expected = pt;
1038
1039        if computed != expected {
1040            println!("Computed: {}", hex::encode(&computed));
1041            println!("Expected: {}", hex::encode(&expected));
1042            if computed.len() != expected.len() {
1043                println!(
1044                    "Lengths differ: {} in computed vs {} expected",
1045                    computed.len(),
1046                    expected.len()
1047                );
1048            }
1049            panic!("test failure");
1050        }
1051    }
1052
1053    #[cfg(not(any(boringssl, awslc)))]
1054    fn cipher_test_nopad(ciphertype: super::Cipher, pt: &str, ct: &str, key: &str, iv: &str) {
1055        let pt = Vec::from_hex(pt).unwrap();
1056        let ct = Vec::from_hex(ct).unwrap();
1057        let key = Vec::from_hex(key).unwrap();
1058        let iv = Vec::from_hex(iv).unwrap();
1059
1060        let computed = {
1061            let mut c = Crypter::new(ciphertype, Mode::Decrypt, &key, Some(&iv)).unwrap();
1062            c.pad(false);
1063            let mut out = vec![0; ct.len() + ciphertype.block_size()];
1064            let count = c.update(&ct, &mut out).unwrap();
1065            let rest = c.finalize(&mut out[count..]).unwrap();
1066            out.truncate(count + rest);
1067            out
1068        };
1069        let expected = pt;
1070
1071        if computed != expected {
1072            println!("Computed: {}", hex::encode(&computed));
1073            println!("Expected: {}", hex::encode(&expected));
1074            if computed.len() != expected.len() {
1075                println!(
1076                    "Lengths differ: {} in computed vs {} expected",
1077                    computed.len(),
1078                    expected.len()
1079                );
1080            }
1081            panic!("test failure");
1082        }
1083    }
1084
1085    #[test]
1086    fn test_rc4() {
1087        #[cfg(ossl300)]
1088        let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
1089
1090        let pt = "0000000000000000000000000000000000000000000000000000000000000000000000000000";
1091        let ct = "A68686B04D686AA107BD8D4CAB191A3EEC0A6294BC78B60F65C25CB47BD7BB3A48EFC4D26BE4";
1092        let key = "97CD440324DA5FD1F7955C1C13B6B466";
1093        let iv = "";
1094
1095        cipher_test(super::Cipher::rc4(), pt, ct, key, iv);
1096    }
1097
1098    #[test]
1099    #[cfg(not(any(boringssl, awslc)))]
1100    fn test_aes256_xts() {
1101        // Test case 174 from
1102        // http://csrc.nist.gov/groups/STM/cavp/documents/aes/XTSTestVectors.zip
1103        let pt = "77f4ef63d734ebd028508da66c22cdebdd52ecd6ee2ab0a50bc8ad0cfd692ca5fcd4e6dedc45df7f\
1104                  6503f462611dc542";
1105        let ct = "ce7d905a7776ac72f240d22aafed5e4eb7566cdc7211220e970da634ce015f131a5ecb8d400bc9e8\
1106                  4f0b81d8725dbbc7";
1107        let key = "b6bfef891f83b5ff073f2231267be51eb084b791fa19a154399c0684c8b2dfcb37de77d28bbda3b\
1108                   4180026ad640b74243b3133e7b9fae629403f6733423dae28";
1109        let iv = "db200efb7eaaa737dbdf40babb68953f";
1110
1111        cipher_test(super::Cipher::aes_256_xts(), pt, ct, key, iv);
1112    }
1113
1114    #[test]
1115    fn test_aes128_ctr() {
1116        let pt = "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411\
1117                  E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710";
1118        let ct = "874D6191B620E3261BEF6864990DB6CE9806F66B7970FDFF8617187BB9FFFDFF5AE4DF3EDBD5D35E\
1119                  5B4F09020DB03EAB1E031DDA2FBE03D1792170A0F3009CEE";
1120        let key = "2B7E151628AED2A6ABF7158809CF4F3C";
1121        let iv = "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF";
1122
1123        cipher_test(super::Cipher::aes_128_ctr(), pt, ct, key, iv);
1124    }
1125
1126    #[test]
1127    #[cfg(not(any(boringssl, awslc)))]
1128    fn test_aes128_cfb1() {
1129        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1130
1131        let pt = "6bc1";
1132        let ct = "68b3";
1133        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1134        let iv = "000102030405060708090a0b0c0d0e0f";
1135
1136        cipher_test(super::Cipher::aes_128_cfb1(), pt, ct, key, iv);
1137    }
1138
1139    #[test]
1140    #[cfg(not(any(boringssl, awslc)))]
1141    fn test_aes128_cfb128() {
1142        let pt = "6bc1bee22e409f96e93d7e117393172a";
1143        let ct = "3b3fd92eb72dad20333449f8e83cfb4a";
1144        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1145        let iv = "000102030405060708090a0b0c0d0e0f";
1146
1147        cipher_test(super::Cipher::aes_128_cfb128(), pt, ct, key, iv);
1148    }
1149
1150    #[test]
1151    #[cfg(not(any(boringssl, awslc)))]
1152    fn test_aes128_cfb8() {
1153        let pt = "6bc1bee22e409f96e93d7e117393172aae2d";
1154        let ct = "3b79424c9c0dd436bace9e0ed4586a4f32b9";
1155        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1156        let iv = "000102030405060708090a0b0c0d0e0f";
1157
1158        cipher_test(super::Cipher::aes_128_cfb8(), pt, ct, key, iv);
1159    }
1160
1161    #[test]
1162    fn test_aes128_ofb() {
1163        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1164
1165        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1166        let ct = "3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e";
1167        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1168        let iv = "000102030405060708090a0b0c0d0e0f";
1169
1170        cipher_test(super::Cipher::aes_128_ofb(), pt, ct, key, iv);
1171    }
1172
1173    #[test]
1174    fn test_aes192_ctr() {
1175        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1176
1177        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1178        let ct = "1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e941e36b26bd1ebc670d1bd1d665620abf74f78a7f6d29809585a97daec58c6b050";
1179        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1180        let iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
1181
1182        cipher_test(super::Cipher::aes_192_ctr(), pt, ct, key, iv);
1183    }
1184
1185    #[test]
1186    #[cfg(not(any(boringssl, awslc)))]
1187    fn test_aes192_cfb1() {
1188        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1189
1190        let pt = "6bc1";
1191        let ct = "9359";
1192        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1193        let iv = "000102030405060708090a0b0c0d0e0f";
1194
1195        cipher_test(super::Cipher::aes_192_cfb1(), pt, ct, key, iv);
1196    }
1197
1198    #[test]
1199    #[cfg(not(any(boringssl, awslc)))]
1200    fn test_aes192_cfb128() {
1201        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1202
1203        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1204        let ct = "cdc80d6fddf18cab34c25909c99a417467ce7f7f81173621961a2b70171d3d7a2e1e8a1dd59b88b1c8e60fed1efac4c9c05f9f9ca9834fa042ae8fba584b09ff";
1205        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1206        let iv = "000102030405060708090a0b0c0d0e0f";
1207
1208        cipher_test(super::Cipher::aes_192_cfb128(), pt, ct, key, iv);
1209    }
1210
1211    #[test]
1212    #[cfg(not(any(boringssl, awslc)))]
1213    fn test_aes192_cfb8() {
1214        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1215
1216        let pt = "6bc1bee22e409f96e93d7e117393172aae2d";
1217        let ct = "cda2521ef0a905ca44cd057cbf0d47a0678a";
1218        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1219        let iv = "000102030405060708090a0b0c0d0e0f";
1220
1221        cipher_test(super::Cipher::aes_192_cfb8(), pt, ct, key, iv);
1222    }
1223
1224    #[test]
1225    fn test_aes192_ofb() {
1226        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1227
1228        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1229        let ct = "cdc80d6fddf18cab34c25909c99a4174fcc28b8d4c63837c09e81700c11004018d9a9aeac0f6596f559c6d4daf59a5f26d9f200857ca6c3e9cac524bd9acc92a";
1230        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1231        let iv = "000102030405060708090a0b0c0d0e0f";
1232
1233        cipher_test(super::Cipher::aes_192_ofb(), pt, ct, key, iv);
1234    }
1235
1236    #[test]
1237    #[cfg(not(any(boringssl, awslc)))]
1238    fn test_aes256_cfb1() {
1239        let pt = "6bc1";
1240        let ct = "9029";
1241        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1242        let iv = "000102030405060708090a0b0c0d0e0f";
1243
1244        cipher_test(super::Cipher::aes_256_cfb1(), pt, ct, key, iv);
1245    }
1246
1247    #[test]
1248    #[cfg(not(any(boringssl, awslc)))]
1249    fn test_aes256_cfb128() {
1250        let pt = "6bc1bee22e409f96e93d7e117393172a";
1251        let ct = "dc7e84bfda79164b7ecd8486985d3860";
1252        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1253        let iv = "000102030405060708090a0b0c0d0e0f";
1254
1255        cipher_test(super::Cipher::aes_256_cfb128(), pt, ct, key, iv);
1256    }
1257
1258    #[test]
1259    #[cfg(not(any(boringssl, awslc)))]
1260    fn test_aes256_cfb8() {
1261        let pt = "6bc1bee22e409f96e93d7e117393172aae2d";
1262        let ct = "dc1f1a8520a64db55fcc8ac554844e889700";
1263        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1264        let iv = "000102030405060708090a0b0c0d0e0f";
1265
1266        cipher_test(super::Cipher::aes_256_cfb8(), pt, ct, key, iv);
1267    }
1268
1269    #[test]
1270    fn test_aes256_ofb() {
1271        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1272
1273        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1274        let ct = "dc7e84bfda79164b7ecd8486985d38604febdc6740d20b3ac88f6ad82a4fb08d71ab47a086e86eedf39d1c5bba97c4080126141d67f37be8538f5a8be740e484";
1275        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1276        let iv = "000102030405060708090a0b0c0d0e0f";
1277
1278        cipher_test(super::Cipher::aes_256_ofb(), pt, ct, key, iv);
1279    }
1280
1281    #[test]
1282    #[cfg_attr(ossl300, ignore)]
1283    #[cfg(not(any(boringssl, awslc)))]
1284    fn test_bf_cbc() {
1285        #[cfg(ossl300)]
1286        let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
1287
1288        // https://www.schneier.com/code/vectors.txt
1289
1290        let pt = "37363534333231204E6F77206973207468652074696D6520666F722000000000";
1291        let ct = "6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC";
1292        let key = "0123456789ABCDEFF0E1D2C3B4A59687";
1293        let iv = "FEDCBA9876543210";
1294
1295        cipher_test_nopad(super::Cipher::bf_cbc(), pt, ct, key, iv);
1296    }
1297
1298    #[test]
1299    #[cfg_attr(ossl300, ignore)]
1300    #[cfg(not(any(boringssl, awslc)))]
1301    fn test_bf_ecb() {
1302        #[cfg(ossl300)]
1303        let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
1304
1305        let pt = "5CD54CA83DEF57DA";
1306        let ct = "B1B8CC0B250F09A0";
1307        let key = "0131D9619DC1376E";
1308        let iv = "0000000000000000";
1309
1310        cipher_test_nopad(super::Cipher::bf_ecb(), pt, ct, key, iv);
1311    }
1312
1313    #[test]
1314    #[cfg_attr(ossl300, ignore)]
1315    #[cfg(not(any(boringssl, awslc)))]
1316    fn test_bf_cfb64() {
1317        #[cfg(ossl300)]
1318        let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
1319
1320        let pt = "37363534333231204E6F77206973207468652074696D6520666F722000";
1321        let ct = "E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3";
1322        let key = "0123456789ABCDEFF0E1D2C3B4A59687";
1323        let iv = "FEDCBA9876543210";
1324
1325        cipher_test_nopad(super::Cipher::bf_cfb64(), pt, ct, key, iv);
1326    }
1327
1328    #[test]
1329    #[cfg_attr(ossl300, ignore)]
1330    #[cfg(not(any(boringssl, awslc)))]
1331    fn test_bf_ofb() {
1332        #[cfg(ossl300)]
1333        let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
1334
1335        let pt = "37363534333231204E6F77206973207468652074696D6520666F722000";
1336        let ct = "E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA";
1337        let key = "0123456789ABCDEFF0E1D2C3B4A59687";
1338        let iv = "FEDCBA9876543210";
1339
1340        cipher_test_nopad(super::Cipher::bf_ofb(), pt, ct, key, iv);
1341    }
1342
1343    #[test]
1344    fn test_des_cbc() {
1345        #[cfg(ossl300)]
1346        let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
1347
1348        let pt = "54686973206973206120746573742e";
1349        let ct = "6f2867cfefda048a4046ef7e556c7132";
1350        let key = "7cb66337f3d3c0fe";
1351        let iv = "0001020304050607";
1352
1353        cipher_test(super::Cipher::des_cbc(), pt, ct, key, iv);
1354    }
1355
1356    #[test]
1357    fn test_des_ecb() {
1358        #[cfg(ossl300)]
1359        let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
1360
1361        let pt = "54686973206973206120746573742e";
1362        let ct = "0050ab8aecec758843fe157b4dde938c";
1363        let key = "7cb66337f3d3c0fe";
1364        let iv = "0001020304050607";
1365
1366        cipher_test(super::Cipher::des_ecb(), pt, ct, key, iv);
1367    }
1368
1369    #[test]
1370    fn test_des_ede3() {
1371        let pt = "9994f4c69d40ae4f34ff403b5cf39d4c8207ea5d3e19a5fd";
1372        let ct = "9e5c4297d60582f81071ac8ab7d0698d4c79de8b94c519858207ea5d3e19a5fd";
1373        let key = "010203040506070801020304050607080102030405060708";
1374        let iv = "5cc118306dc702e4";
1375
1376        cipher_test(super::Cipher::des_ede3(), pt, ct, key, iv);
1377    }
1378
1379    #[test]
1380    fn test_des_ede3_cbc() {
1381        let pt = "54686973206973206120746573742e";
1382        let ct = "6f2867cfefda048a4046ef7e556c7132";
1383        let key = "7cb66337f3d3c0fe7cb66337f3d3c0fe7cb66337f3d3c0fe";
1384        let iv = "0001020304050607";
1385
1386        cipher_test(super::Cipher::des_ede3_cbc(), pt, ct, key, iv);
1387    }
1388
1389    #[test]
1390    #[cfg(not(any(boringssl, awslc)))]
1391    fn test_des_ede3_cfb64() {
1392        let pt = "2b1773784b5889dc788477367daa98ad";
1393        let ct = "6f2867cfefda048a4046ef7e556c7132";
1394        let key = "7cb66337f3d3c0fe7cb66337f3d3c0fe7cb66337f3d3c0fe";
1395        let iv = "0001020304050607";
1396
1397        cipher_test(super::Cipher::des_ede3_cfb64(), pt, ct, key, iv);
1398    }
1399
1400    #[test]
1401    fn test_aes128_gcm() {
1402        let key = "23dc8d23d95b6fd1251741a64f7d4f41";
1403        let iv = "f416f48ad44d9efa1179e167";
1404        let pt = "6cb9b71dd0ccd42cdf87e8e396fc581fd8e0d700e360f590593b748e105390de";
1405        let aad = "45074844c97d515c65bbe37c210a5a4b08c21c588efe5c5f73c4d9c17d34dacddc0bb6a8a53f7bf477b9780c1c2a928660df87016b2873fe876b2b887fb5886bfd63216b7eaecc046372a82c047eb043f0b063226ee52a12c69b";
1406        let ct = "8ad20486778e87387efb3f2574e509951c0626816722018129e578b2787969d3";
1407        let tag = "91e1bc09";
1408
1409        // this tag is smaller than you'd normally want, but I pulled this test from the part of
1410        // the NIST test vectors that cover 4 byte tags.
1411        let mut actual_tag = [0; 4];
1412        let out = encrypt_aead(
1413            Cipher::aes_128_gcm(),
1414            &Vec::from_hex(key).unwrap(),
1415            Some(&Vec::from_hex(iv).unwrap()),
1416            &Vec::from_hex(aad).unwrap(),
1417            &Vec::from_hex(pt).unwrap(),
1418            &mut actual_tag,
1419        )
1420        .unwrap();
1421        assert_eq!(ct, hex::encode(out));
1422        assert_eq!(tag, hex::encode(actual_tag));
1423
1424        let out = decrypt_aead(
1425            Cipher::aes_128_gcm(),
1426            &Vec::from_hex(key).unwrap(),
1427            Some(&Vec::from_hex(iv).unwrap()),
1428            &Vec::from_hex(aad).unwrap(),
1429            &Vec::from_hex(ct).unwrap(),
1430            &Vec::from_hex(tag).unwrap(),
1431        )
1432        .unwrap();
1433        assert_eq!(pt, hex::encode(out));
1434    }
1435
1436    #[test]
1437    #[cfg(not(any(boringssl, awslc)))]
1438    fn test_aes128_ccm() {
1439        let key = "3ee186594f110fb788a8bf8aa8be5d4a";
1440        let nonce = "44f705d52acf27b7f17196aa9b";
1441        let aad = "2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57";
1442
1443        let pt = "d71864877f2578db092daba2d6a1f9f4698a9c356c7830a1";
1444        let ct = "b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0";
1445        let tag = "d6965f5aa6e31302a9cc2b36";
1446
1447        let mut actual_tag = [0; 12];
1448        let out = encrypt_aead(
1449            Cipher::aes_128_ccm(),
1450            &Vec::from_hex(key).unwrap(),
1451            Some(&Vec::from_hex(nonce).unwrap()),
1452            &Vec::from_hex(aad).unwrap(),
1453            &Vec::from_hex(pt).unwrap(),
1454            &mut actual_tag,
1455        )
1456        .unwrap();
1457
1458        assert_eq!(ct, hex::encode(out));
1459        assert_eq!(tag, hex::encode(actual_tag));
1460
1461        let out = decrypt_aead(
1462            Cipher::aes_128_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        .unwrap();
1470        assert_eq!(pt, hex::encode(out));
1471    }
1472
1473    #[test]
1474    #[cfg(not(any(boringssl, awslc)))]
1475    fn test_aes128_ccm_verify_fail() {
1476        let key = "3ee186594f110fb788a8bf8aa8be5d4a";
1477        let nonce = "44f705d52acf27b7f17196aa9b";
1478        let aad = "2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57";
1479
1480        let ct = "b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0";
1481        let tag = "00005f5aa6e31302a9cc2b36";
1482
1483        let out = decrypt_aead(
1484            Cipher::aes_128_ccm(),
1485            &Vec::from_hex(key).unwrap(),
1486            Some(&Vec::from_hex(nonce).unwrap()),
1487            &Vec::from_hex(aad).unwrap(),
1488            &Vec::from_hex(ct).unwrap(),
1489            &Vec::from_hex(tag).unwrap(),
1490        );
1491        assert!(out.is_err());
1492    }
1493
1494    #[test]
1495    #[cfg(not(any(boringssl, awslc)))]
1496    fn test_aes256_ccm() {
1497        let key = "7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d";
1498        let nonce = "dde2a362ce81b2b6913abc3095";
1499        let aad = "404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695";
1500
1501        let pt = "7ebef26bf4ecf6f0ebb2eb860edbf900f27b75b4a6340fdb";
1502        let ct = "353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd";
1503        let tag = "2927a053c9244d3217a7ad05";
1504
1505        let mut actual_tag = [0; 12];
1506        let out = encrypt_aead(
1507            Cipher::aes_256_ccm(),
1508            &Vec::from_hex(key).unwrap(),
1509            Some(&Vec::from_hex(nonce).unwrap()),
1510            &Vec::from_hex(aad).unwrap(),
1511            &Vec::from_hex(pt).unwrap(),
1512            &mut actual_tag,
1513        )
1514        .unwrap();
1515
1516        assert_eq!(ct, hex::encode(out));
1517        assert_eq!(tag, hex::encode(actual_tag));
1518
1519        let out = decrypt_aead(
1520            Cipher::aes_256_ccm(),
1521            &Vec::from_hex(key).unwrap(),
1522            Some(&Vec::from_hex(nonce).unwrap()),
1523            &Vec::from_hex(aad).unwrap(),
1524            &Vec::from_hex(ct).unwrap(),
1525            &Vec::from_hex(tag).unwrap(),
1526        )
1527        .unwrap();
1528        assert_eq!(pt, hex::encode(out));
1529    }
1530
1531    #[test]
1532    #[cfg(not(any(boringssl, awslc)))]
1533    fn test_aes256_ccm_verify_fail() {
1534        let key = "7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d";
1535        let nonce = "dde2a362ce81b2b6913abc3095";
1536        let aad = "404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695";
1537
1538        let ct = "353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd";
1539        let tag = "0000a053c9244d3217a7ad05";
1540
1541        let out = decrypt_aead(
1542            Cipher::aes_256_ccm(),
1543            &Vec::from_hex(key).unwrap(),
1544            Some(&Vec::from_hex(nonce).unwrap()),
1545            &Vec::from_hex(aad).unwrap(),
1546            &Vec::from_hex(ct).unwrap(),
1547            &Vec::from_hex(tag).unwrap(),
1548        );
1549        assert!(out.is_err());
1550    }
1551
1552    #[test]
1553    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
1554    fn test_aes_128_ocb() {
1555        let key = "000102030405060708090a0b0c0d0e0f";
1556        let aad = "0001020304050607";
1557        let tag = "16dc76a46d47e1ead537209e8a96d14e";
1558        let iv = "000102030405060708090a0b";
1559        let pt = "0001020304050607";
1560        let ct = "92b657130a74b85a";
1561
1562        let mut actual_tag = [0; 16];
1563        let out = encrypt_aead(
1564            Cipher::aes_128_ocb(),
1565            &Vec::from_hex(key).unwrap(),
1566            Some(&Vec::from_hex(iv).unwrap()),
1567            &Vec::from_hex(aad).unwrap(),
1568            &Vec::from_hex(pt).unwrap(),
1569            &mut actual_tag,
1570        )
1571        .unwrap();
1572
1573        assert_eq!(ct, hex::encode(out));
1574        assert_eq!(tag, hex::encode(actual_tag));
1575
1576        let out = decrypt_aead(
1577            Cipher::aes_128_ocb(),
1578            &Vec::from_hex(key).unwrap(),
1579            Some(&Vec::from_hex(iv).unwrap()),
1580            &Vec::from_hex(aad).unwrap(),
1581            &Vec::from_hex(ct).unwrap(),
1582            &Vec::from_hex(tag).unwrap(),
1583        )
1584        .unwrap();
1585        assert_eq!(pt, hex::encode(out));
1586    }
1587
1588    #[test]
1589    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
1590    fn test_aes_128_ocb_fail() {
1591        let key = "000102030405060708090a0b0c0d0e0f";
1592        let aad = "0001020304050607";
1593        let tag = "16dc76a46d47e1ead537209e8a96d14e";
1594        let iv = "000000000405060708090a0b";
1595        let ct = "92b657130a74b85a";
1596
1597        let out = decrypt_aead(
1598            Cipher::aes_128_ocb(),
1599            &Vec::from_hex(key).unwrap(),
1600            Some(&Vec::from_hex(iv).unwrap()),
1601            &Vec::from_hex(aad).unwrap(),
1602            &Vec::from_hex(ct).unwrap(),
1603            &Vec::from_hex(tag).unwrap(),
1604        );
1605        assert!(out.is_err());
1606    }
1607
1608    #[test]
1609    #[cfg(any(ossl110, libressl))]
1610    fn test_chacha20() {
1611        let key = "0000000000000000000000000000000000000000000000000000000000000000";
1612        let iv = "00000000000000000000000000000000";
1613        let pt =
1614            "000000000000000000000000000000000000000000000000000000000000000000000000000000000\
1615             00000000000000000000000000000000000000000000000";
1616        let ct =
1617            "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7\
1618             724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586";
1619
1620        cipher_test(Cipher::chacha20(), pt, ct, key, iv);
1621    }
1622
1623    #[test]
1624    #[cfg(any(ossl110, libressl360, awslc))]
1625    fn test_chacha20_poly1305() {
1626        let key = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f";
1627        let iv = "070000004041424344454647";
1628        let aad = "50515253c0c1c2c3c4c5c6c7";
1629        let pt =
1630            "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393\
1631             a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f722074\
1632             6865206675747572652c2073756e73637265656e20776f756c642062652069742e";
1633        let ct =
1634            "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca967128\
1635             2fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fa\
1636             b324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116";
1637        let tag = "1ae10b594f09e26a7e902ecbd0600691";
1638
1639        let mut actual_tag = [0; 16];
1640        let out = encrypt_aead(
1641            Cipher::chacha20_poly1305(),
1642            &Vec::from_hex(key).unwrap(),
1643            Some(&Vec::from_hex(iv).unwrap()),
1644            &Vec::from_hex(aad).unwrap(),
1645            &Vec::from_hex(pt).unwrap(),
1646            &mut actual_tag,
1647        )
1648        .unwrap();
1649        assert_eq!(ct, hex::encode(out));
1650        assert_eq!(tag, hex::encode(actual_tag));
1651
1652        let out = decrypt_aead(
1653            Cipher::chacha20_poly1305(),
1654            &Vec::from_hex(key).unwrap(),
1655            Some(&Vec::from_hex(iv).unwrap()),
1656            &Vec::from_hex(aad).unwrap(),
1657            &Vec::from_hex(ct).unwrap(),
1658            &Vec::from_hex(tag).unwrap(),
1659        )
1660        .unwrap();
1661        assert_eq!(pt, hex::encode(out));
1662    }
1663
1664    #[test]
1665    #[cfg(not(any(osslconf = "OPENSSL_NO_SEED", ossl300)))]
1666    fn test_seed_cbc() {
1667        #[cfg(ossl300)]
1668        let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
1669
1670        let pt = "5363686f6b6f6c6164656e6b756368656e0a";
1671        let ct = "c2edf0fb2eb11bf7b2f39417a8528896d34b24b6fd79e5923b116dfcd2aba5a4";
1672        let key = "41414141414141414141414141414141";
1673        let iv = "41414141414141414141414141414141";
1674
1675        cipher_test(super::Cipher::seed_cbc(), pt, ct, key, iv);
1676    }
1677
1678    #[test]
1679    #[cfg(not(any(osslconf = "OPENSSL_NO_SEED", ossl300)))]
1680    fn test_seed_cfb128() {
1681        #[cfg(ossl300)]
1682        let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
1683
1684        let pt = "5363686f6b6f6c6164656e6b756368656e0a";
1685        let ct = "71d4d25fc1750cb7789259e7f34061939a41";
1686        let key = "41414141414141414141414141414141";
1687        let iv = "41414141414141414141414141414141";
1688
1689        cipher_test(super::Cipher::seed_cfb128(), pt, ct, key, iv);
1690    }
1691
1692    #[test]
1693    #[cfg(not(any(osslconf = "OPENSSL_NO_SEED", ossl300)))]
1694    fn test_seed_ecb() {
1695        #[cfg(ossl300)]
1696        let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
1697
1698        let pt = "5363686f6b6f6c6164656e6b756368656e0a";
1699        let ct = "0263a9cd498cf0edb0ef72a3231761d00ce601f7d08ad19ad74f0815f2c77f7e";
1700        let key = "41414141414141414141414141414141";
1701        let iv = "41414141414141414141414141414141";
1702
1703        cipher_test(super::Cipher::seed_ecb(), pt, ct, key, iv);
1704    }
1705
1706    #[test]
1707    #[cfg(not(any(osslconf = "OPENSSL_NO_SEED", ossl300)))]
1708    fn test_seed_ofb() {
1709        #[cfg(ossl300)]
1710        let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
1711
1712        let pt = "5363686f6b6f6c6164656e6b756368656e0a";
1713        let ct = "71d4d25fc1750cb7789259e7f34061930afd";
1714        let key = "41414141414141414141414141414141";
1715        let iv = "41414141414141414141414141414141";
1716
1717        cipher_test(super::Cipher::seed_ofb(), pt, ct, key, iv);
1718    }
1719
1720    // GB/T 32907-2016
1721    // http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=7803DE42D3BC5E80B0C3E5D8E873D56A
1722    #[test]
1723    #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))]
1724    fn test_sm4_ecb() {
1725        use std::mem;
1726
1727        let key = vec![
1728            0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,
1729            0x32, 0x10,
1730        ];
1731        let pt = vec![
1732            0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,
1733            0x32, 0x10,
1734        ];
1735        let ct = vec![
1736            0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e,
1737            0x42, 0x46,
1738        ];
1739        let ct1 = vec![
1740            0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d,
1741            0x3f, 0x66,
1742        ];
1743
1744        let block_size = Cipher::sm4_ecb().block_size();
1745        let mut c = Crypter::new(Cipher::sm4_ecb(), Mode::Encrypt, &key, None).unwrap();
1746        c.pad(false);
1747
1748        // 1 round
1749        let mut r = vec![0; pt.len() + Cipher::sm4_ecb().block_size()];
1750        let count = c.update(&pt, &mut r).unwrap();
1751        assert_eq!(ct, &r[..count]);
1752
1753        // 1000000 rounds
1754        let mut r1 = vec![0; pt.len() + Cipher::sm4_ecb().block_size()];
1755        for _ in 0..999999 {
1756            c.update(&r[..block_size], &mut r1).unwrap();
1757            mem::swap(&mut r, &mut r1);
1758        }
1759        assert_eq!(ct1, &r[..count]);
1760    }
1761
1762    #[test]
1763    #[should_panic(expected = "an IV is required for this cipher")]
1764    fn test_crypter_panics_for_missing_iv_cbc() {
1765        let key = [0u8; 16];
1766        let _ = Crypter::new(
1767            super::Cipher::aes_128_cbc(),
1768            super::Mode::Encrypt,
1769            &key,
1770            None,
1771        );
1772    }
1773
1774    #[test]
1775    #[should_panic(expected = "an IV is required for this cipher")]
1776    fn test_crypter_panics_for_missing_iv_gcm() {
1777        let key = [0u8; 16];
1778        let _ = Crypter::new(
1779            super::Cipher::aes_128_gcm(),
1780            super::Mode::Encrypt,
1781            &key,
1782            None,
1783        );
1784    }
1785}