Skip to main content

variant_ssl/
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    #[test]
1054    #[cfg(not(any(boringssl, awslc)))]
1055    fn test_aes256_xts() {
1056        // Test case 174 from
1057        // http://csrc.nist.gov/groups/STM/cavp/documents/aes/XTSTestVectors.zip
1058        let pt = "77f4ef63d734ebd028508da66c22cdebdd52ecd6ee2ab0a50bc8ad0cfd692ca5fcd4e6dedc45df7f\
1059                  6503f462611dc542";
1060        let ct = "ce7d905a7776ac72f240d22aafed5e4eb7566cdc7211220e970da634ce015f131a5ecb8d400bc9e8\
1061                  4f0b81d8725dbbc7";
1062        let key = "b6bfef891f83b5ff073f2231267be51eb084b791fa19a154399c0684c8b2dfcb37de77d28bbda3b\
1063                   4180026ad640b74243b3133e7b9fae629403f6733423dae28";
1064        let iv = "db200efb7eaaa737dbdf40babb68953f";
1065
1066        cipher_test(super::Cipher::aes_256_xts(), pt, ct, key, iv);
1067    }
1068
1069    #[test]
1070    fn test_aes128_ctr() {
1071        let pt = "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411\
1072                  E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710";
1073        let ct = "874D6191B620E3261BEF6864990DB6CE9806F66B7970FDFF8617187BB9FFFDFF5AE4DF3EDBD5D35E\
1074                  5B4F09020DB03EAB1E031DDA2FBE03D1792170A0F3009CEE";
1075        let key = "2B7E151628AED2A6ABF7158809CF4F3C";
1076        let iv = "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF";
1077
1078        cipher_test(super::Cipher::aes_128_ctr(), pt, ct, key, iv);
1079    }
1080
1081    #[test]
1082    #[cfg(not(any(boringssl, awslc)))]
1083    fn test_aes128_cfb1() {
1084        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1085
1086        let pt = "6bc1";
1087        let ct = "68b3";
1088        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1089        let iv = "000102030405060708090a0b0c0d0e0f";
1090
1091        cipher_test(super::Cipher::aes_128_cfb1(), pt, ct, key, iv);
1092    }
1093
1094    #[test]
1095    #[cfg(not(any(boringssl, awslc)))]
1096    fn test_aes128_cfb128() {
1097        let pt = "6bc1bee22e409f96e93d7e117393172a";
1098        let ct = "3b3fd92eb72dad20333449f8e83cfb4a";
1099        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1100        let iv = "000102030405060708090a0b0c0d0e0f";
1101
1102        cipher_test(super::Cipher::aes_128_cfb128(), pt, ct, key, iv);
1103    }
1104
1105    #[test]
1106    #[cfg(not(any(boringssl, awslc)))]
1107    fn test_aes128_cfb8() {
1108        let pt = "6bc1bee22e409f96e93d7e117393172aae2d";
1109        let ct = "3b79424c9c0dd436bace9e0ed4586a4f32b9";
1110        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1111        let iv = "000102030405060708090a0b0c0d0e0f";
1112
1113        cipher_test(super::Cipher::aes_128_cfb8(), pt, ct, key, iv);
1114    }
1115
1116    #[test]
1117    fn test_aes128_ofb() {
1118        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1119
1120        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1121        let ct = "3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e";
1122        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1123        let iv = "000102030405060708090a0b0c0d0e0f";
1124
1125        cipher_test(super::Cipher::aes_128_ofb(), pt, ct, key, iv);
1126    }
1127
1128    #[test]
1129    fn test_aes192_ctr() {
1130        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1131
1132        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1133        let ct = "1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e941e36b26bd1ebc670d1bd1d665620abf74f78a7f6d29809585a97daec58c6b050";
1134        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1135        let iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
1136
1137        cipher_test(super::Cipher::aes_192_ctr(), pt, ct, key, iv);
1138    }
1139
1140    #[test]
1141    #[cfg(not(any(boringssl, awslc)))]
1142    fn test_aes192_cfb1() {
1143        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1144
1145        let pt = "6bc1";
1146        let ct = "9359";
1147        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1148        let iv = "000102030405060708090a0b0c0d0e0f";
1149
1150        cipher_test(super::Cipher::aes_192_cfb1(), pt, ct, key, iv);
1151    }
1152
1153    #[test]
1154    #[cfg(not(any(boringssl, awslc)))]
1155    fn test_aes192_cfb128() {
1156        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1157
1158        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1159        let ct = "cdc80d6fddf18cab34c25909c99a417467ce7f7f81173621961a2b70171d3d7a2e1e8a1dd59b88b1c8e60fed1efac4c9c05f9f9ca9834fa042ae8fba584b09ff";
1160        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1161        let iv = "000102030405060708090a0b0c0d0e0f";
1162
1163        cipher_test(super::Cipher::aes_192_cfb128(), pt, ct, key, iv);
1164    }
1165
1166    #[test]
1167    #[cfg(not(any(boringssl, awslc)))]
1168    fn test_aes192_cfb8() {
1169        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1170
1171        let pt = "6bc1bee22e409f96e93d7e117393172aae2d";
1172        let ct = "cda2521ef0a905ca44cd057cbf0d47a0678a";
1173        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1174        let iv = "000102030405060708090a0b0c0d0e0f";
1175
1176        cipher_test(super::Cipher::aes_192_cfb8(), pt, ct, key, iv);
1177    }
1178
1179    #[test]
1180    fn test_aes192_ofb() {
1181        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1182
1183        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1184        let ct = "cdc80d6fddf18cab34c25909c99a4174fcc28b8d4c63837c09e81700c11004018d9a9aeac0f6596f559c6d4daf59a5f26d9f200857ca6c3e9cac524bd9acc92a";
1185        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1186        let iv = "000102030405060708090a0b0c0d0e0f";
1187
1188        cipher_test(super::Cipher::aes_192_ofb(), pt, ct, key, iv);
1189    }
1190
1191    #[test]
1192    #[cfg(not(any(boringssl, awslc)))]
1193    fn test_aes256_cfb1() {
1194        let pt = "6bc1";
1195        let ct = "9029";
1196        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1197        let iv = "000102030405060708090a0b0c0d0e0f";
1198
1199        cipher_test(super::Cipher::aes_256_cfb1(), pt, ct, key, iv);
1200    }
1201
1202    #[test]
1203    #[cfg(not(any(boringssl, awslc)))]
1204    fn test_aes256_cfb128() {
1205        let pt = "6bc1bee22e409f96e93d7e117393172a";
1206        let ct = "dc7e84bfda79164b7ecd8486985d3860";
1207        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1208        let iv = "000102030405060708090a0b0c0d0e0f";
1209
1210        cipher_test(super::Cipher::aes_256_cfb128(), pt, ct, key, iv);
1211    }
1212
1213    #[test]
1214    #[cfg(not(any(boringssl, awslc)))]
1215    fn test_aes256_cfb8() {
1216        let pt = "6bc1bee22e409f96e93d7e117393172aae2d";
1217        let ct = "dc1f1a8520a64db55fcc8ac554844e889700";
1218        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1219        let iv = "000102030405060708090a0b0c0d0e0f";
1220
1221        cipher_test(super::Cipher::aes_256_cfb8(), pt, ct, key, iv);
1222    }
1223
1224    #[test]
1225    fn test_aes256_ofb() {
1226        // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1227
1228        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1229        let ct = "dc7e84bfda79164b7ecd8486985d38604febdc6740d20b3ac88f6ad82a4fb08d71ab47a086e86eedf39d1c5bba97c4080126141d67f37be8538f5a8be740e484";
1230        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1231        let iv = "000102030405060708090a0b0c0d0e0f";
1232
1233        cipher_test(super::Cipher::aes_256_ofb(), pt, ct, key, iv);
1234    }
1235
1236    #[test]
1237    fn test_des_ede3() {
1238        let pt = "9994f4c69d40ae4f34ff403b5cf39d4c8207ea5d3e19a5fd";
1239        let ct = "9e5c4297d60582f81071ac8ab7d0698d4c79de8b94c519858207ea5d3e19a5fd";
1240        let key = "010203040506070801020304050607080102030405060708";
1241        let iv = "5cc118306dc702e4";
1242
1243        cipher_test(super::Cipher::des_ede3(), pt, ct, key, iv);
1244    }
1245
1246    #[test]
1247    fn test_des_ede3_cbc() {
1248        let pt = "54686973206973206120746573742e";
1249        let ct = "6f2867cfefda048a4046ef7e556c7132";
1250        let key = "7cb66337f3d3c0fe7cb66337f3d3c0fe7cb66337f3d3c0fe";
1251        let iv = "0001020304050607";
1252
1253        cipher_test(super::Cipher::des_ede3_cbc(), pt, ct, key, iv);
1254    }
1255
1256    #[test]
1257    #[cfg(not(any(boringssl, awslc)))]
1258    fn test_des_ede3_cfb64() {
1259        let pt = "2b1773784b5889dc788477367daa98ad";
1260        let ct = "6f2867cfefda048a4046ef7e556c7132";
1261        let key = "7cb66337f3d3c0fe7cb66337f3d3c0fe7cb66337f3d3c0fe";
1262        let iv = "0001020304050607";
1263
1264        cipher_test(super::Cipher::des_ede3_cfb64(), pt, ct, key, iv);
1265    }
1266
1267    #[test]
1268    fn test_aes128_gcm() {
1269        let key = "23dc8d23d95b6fd1251741a64f7d4f41";
1270        let iv = "f416f48ad44d9efa1179e167";
1271        let pt = "6cb9b71dd0ccd42cdf87e8e396fc581fd8e0d700e360f590593b748e105390de";
1272        let aad = "45074844c97d515c65bbe37c210a5a4b08c21c588efe5c5f73c4d9c17d34dacddc0bb6a8a53f7bf477b9780c1c2a928660df87016b2873fe876b2b887fb5886bfd63216b7eaecc046372a82c047eb043f0b063226ee52a12c69b";
1273        let ct = "8ad20486778e87387efb3f2574e509951c0626816722018129e578b2787969d3";
1274        let tag = "91e1bc09";
1275
1276        // this tag is smaller than you'd normally want, but I pulled this test from the part of
1277        // the NIST test vectors that cover 4 byte tags.
1278        let mut actual_tag = [0; 4];
1279        let out = encrypt_aead(
1280            Cipher::aes_128_gcm(),
1281            &Vec::from_hex(key).unwrap(),
1282            Some(&Vec::from_hex(iv).unwrap()),
1283            &Vec::from_hex(aad).unwrap(),
1284            &Vec::from_hex(pt).unwrap(),
1285            &mut actual_tag,
1286        )
1287        .unwrap();
1288        assert_eq!(ct, hex::encode(out));
1289        assert_eq!(tag, hex::encode(actual_tag));
1290
1291        let out = decrypt_aead(
1292            Cipher::aes_128_gcm(),
1293            &Vec::from_hex(key).unwrap(),
1294            Some(&Vec::from_hex(iv).unwrap()),
1295            &Vec::from_hex(aad).unwrap(),
1296            &Vec::from_hex(ct).unwrap(),
1297            &Vec::from_hex(tag).unwrap(),
1298        )
1299        .unwrap();
1300        assert_eq!(pt, hex::encode(out));
1301    }
1302
1303    #[test]
1304    #[cfg(not(any(boringssl, awslc)))]
1305    fn test_aes128_ccm() {
1306        let key = "3ee186594f110fb788a8bf8aa8be5d4a";
1307        let nonce = "44f705d52acf27b7f17196aa9b";
1308        let aad = "2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57";
1309
1310        let pt = "d71864877f2578db092daba2d6a1f9f4698a9c356c7830a1";
1311        let ct = "b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0";
1312        let tag = "d6965f5aa6e31302a9cc2b36";
1313
1314        let mut actual_tag = [0; 12];
1315        let out = encrypt_aead(
1316            Cipher::aes_128_ccm(),
1317            &Vec::from_hex(key).unwrap(),
1318            Some(&Vec::from_hex(nonce).unwrap()),
1319            &Vec::from_hex(aad).unwrap(),
1320            &Vec::from_hex(pt).unwrap(),
1321            &mut actual_tag,
1322        )
1323        .unwrap();
1324
1325        assert_eq!(ct, hex::encode(out));
1326        assert_eq!(tag, hex::encode(actual_tag));
1327
1328        let out = decrypt_aead(
1329            Cipher::aes_128_ccm(),
1330            &Vec::from_hex(key).unwrap(),
1331            Some(&Vec::from_hex(nonce).unwrap()),
1332            &Vec::from_hex(aad).unwrap(),
1333            &Vec::from_hex(ct).unwrap(),
1334            &Vec::from_hex(tag).unwrap(),
1335        )
1336        .unwrap();
1337        assert_eq!(pt, hex::encode(out));
1338    }
1339
1340    #[test]
1341    #[cfg(not(any(boringssl, awslc)))]
1342    fn test_aes128_ccm_verify_fail() {
1343        let key = "3ee186594f110fb788a8bf8aa8be5d4a";
1344        let nonce = "44f705d52acf27b7f17196aa9b";
1345        let aad = "2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57";
1346
1347        let ct = "b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0";
1348        let tag = "00005f5aa6e31302a9cc2b36";
1349
1350        let out = decrypt_aead(
1351            Cipher::aes_128_ccm(),
1352            &Vec::from_hex(key).unwrap(),
1353            Some(&Vec::from_hex(nonce).unwrap()),
1354            &Vec::from_hex(aad).unwrap(),
1355            &Vec::from_hex(ct).unwrap(),
1356            &Vec::from_hex(tag).unwrap(),
1357        );
1358        assert!(out.is_err());
1359    }
1360
1361    #[test]
1362    #[cfg(not(any(boringssl, awslc)))]
1363    fn test_aes256_ccm() {
1364        let key = "7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d";
1365        let nonce = "dde2a362ce81b2b6913abc3095";
1366        let aad = "404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695";
1367
1368        let pt = "7ebef26bf4ecf6f0ebb2eb860edbf900f27b75b4a6340fdb";
1369        let ct = "353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd";
1370        let tag = "2927a053c9244d3217a7ad05";
1371
1372        let mut actual_tag = [0; 12];
1373        let out = encrypt_aead(
1374            Cipher::aes_256_ccm(),
1375            &Vec::from_hex(key).unwrap(),
1376            Some(&Vec::from_hex(nonce).unwrap()),
1377            &Vec::from_hex(aad).unwrap(),
1378            &Vec::from_hex(pt).unwrap(),
1379            &mut actual_tag,
1380        )
1381        .unwrap();
1382
1383        assert_eq!(ct, hex::encode(out));
1384        assert_eq!(tag, hex::encode(actual_tag));
1385
1386        let out = decrypt_aead(
1387            Cipher::aes_256_ccm(),
1388            &Vec::from_hex(key).unwrap(),
1389            Some(&Vec::from_hex(nonce).unwrap()),
1390            &Vec::from_hex(aad).unwrap(),
1391            &Vec::from_hex(ct).unwrap(),
1392            &Vec::from_hex(tag).unwrap(),
1393        )
1394        .unwrap();
1395        assert_eq!(pt, hex::encode(out));
1396    }
1397
1398    #[test]
1399    #[cfg(not(any(boringssl, awslc)))]
1400    fn test_aes256_ccm_verify_fail() {
1401        let key = "7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d";
1402        let nonce = "dde2a362ce81b2b6913abc3095";
1403        let aad = "404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695";
1404
1405        let ct = "353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd";
1406        let tag = "0000a053c9244d3217a7ad05";
1407
1408        let out = decrypt_aead(
1409            Cipher::aes_256_ccm(),
1410            &Vec::from_hex(key).unwrap(),
1411            Some(&Vec::from_hex(nonce).unwrap()),
1412            &Vec::from_hex(aad).unwrap(),
1413            &Vec::from_hex(ct).unwrap(),
1414            &Vec::from_hex(tag).unwrap(),
1415        );
1416        assert!(out.is_err());
1417    }
1418
1419    #[test]
1420    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
1421    fn test_aes_128_ocb() {
1422        let key = "000102030405060708090a0b0c0d0e0f";
1423        let aad = "0001020304050607";
1424        let tag = "16dc76a46d47e1ead537209e8a96d14e";
1425        let iv = "000102030405060708090a0b";
1426        let pt = "0001020304050607";
1427        let ct = "92b657130a74b85a";
1428
1429        let mut actual_tag = [0; 16];
1430        let out = encrypt_aead(
1431            Cipher::aes_128_ocb(),
1432            &Vec::from_hex(key).unwrap(),
1433            Some(&Vec::from_hex(iv).unwrap()),
1434            &Vec::from_hex(aad).unwrap(),
1435            &Vec::from_hex(pt).unwrap(),
1436            &mut actual_tag,
1437        )
1438        .unwrap();
1439
1440        assert_eq!(ct, hex::encode(out));
1441        assert_eq!(tag, hex::encode(actual_tag));
1442
1443        let out = decrypt_aead(
1444            Cipher::aes_128_ocb(),
1445            &Vec::from_hex(key).unwrap(),
1446            Some(&Vec::from_hex(iv).unwrap()),
1447            &Vec::from_hex(aad).unwrap(),
1448            &Vec::from_hex(ct).unwrap(),
1449            &Vec::from_hex(tag).unwrap(),
1450        )
1451        .unwrap();
1452        assert_eq!(pt, hex::encode(out));
1453    }
1454
1455    #[test]
1456    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
1457    fn test_aes_128_ocb_fail() {
1458        let key = "000102030405060708090a0b0c0d0e0f";
1459        let aad = "0001020304050607";
1460        let tag = "16dc76a46d47e1ead537209e8a96d14e";
1461        let iv = "000000000405060708090a0b";
1462        let ct = "92b657130a74b85a";
1463
1464        let out = decrypt_aead(
1465            Cipher::aes_128_ocb(),
1466            &Vec::from_hex(key).unwrap(),
1467            Some(&Vec::from_hex(iv).unwrap()),
1468            &Vec::from_hex(aad).unwrap(),
1469            &Vec::from_hex(ct).unwrap(),
1470            &Vec::from_hex(tag).unwrap(),
1471        );
1472        assert!(out.is_err());
1473    }
1474
1475    #[test]
1476    #[cfg(any(ossl110, libressl))]
1477    fn test_chacha20() {
1478        let key = "0000000000000000000000000000000000000000000000000000000000000000";
1479        let iv = "00000000000000000000000000000000";
1480        let pt =
1481            "000000000000000000000000000000000000000000000000000000000000000000000000000000000\
1482             00000000000000000000000000000000000000000000000";
1483        let ct =
1484            "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7\
1485             724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586";
1486
1487        cipher_test(Cipher::chacha20(), pt, ct, key, iv);
1488    }
1489
1490    #[test]
1491    #[cfg(any(ossl110, libressl360, awslc))]
1492    fn test_chacha20_poly1305() {
1493        let key = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f";
1494        let iv = "070000004041424344454647";
1495        let aad = "50515253c0c1c2c3c4c5c6c7";
1496        let pt =
1497            "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393\
1498             a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f722074\
1499             6865206675747572652c2073756e73637265656e20776f756c642062652069742e";
1500        let ct =
1501            "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca967128\
1502             2fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fa\
1503             b324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116";
1504        let tag = "1ae10b594f09e26a7e902ecbd0600691";
1505
1506        let mut actual_tag = [0; 16];
1507        let out = encrypt_aead(
1508            Cipher::chacha20_poly1305(),
1509            &Vec::from_hex(key).unwrap(),
1510            Some(&Vec::from_hex(iv).unwrap()),
1511            &Vec::from_hex(aad).unwrap(),
1512            &Vec::from_hex(pt).unwrap(),
1513            &mut actual_tag,
1514        )
1515        .unwrap();
1516        assert_eq!(ct, hex::encode(out));
1517        assert_eq!(tag, hex::encode(actual_tag));
1518
1519        let out = decrypt_aead(
1520            Cipher::chacha20_poly1305(),
1521            &Vec::from_hex(key).unwrap(),
1522            Some(&Vec::from_hex(iv).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    // GB/T 32907-2016
1532    // http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=7803DE42D3BC5E80B0C3E5D8E873D56A
1533    #[test]
1534    #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM4")))]
1535    fn test_sm4_ecb() {
1536        use std::mem;
1537
1538        let key = vec![
1539            0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,
1540            0x32, 0x10,
1541        ];
1542        let pt = vec![
1543            0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,
1544            0x32, 0x10,
1545        ];
1546        let ct = vec![
1547            0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e,
1548            0x42, 0x46,
1549        ];
1550        let ct1 = vec![
1551            0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d,
1552            0x3f, 0x66,
1553        ];
1554
1555        let block_size = Cipher::sm4_ecb().block_size();
1556        let mut c = Crypter::new(Cipher::sm4_ecb(), Mode::Encrypt, &key, None).unwrap();
1557        c.pad(false);
1558
1559        // 1 round
1560        let mut r = vec![0; pt.len() + Cipher::sm4_ecb().block_size()];
1561        let count = c.update(&pt, &mut r).unwrap();
1562        assert_eq!(ct, &r[..count]);
1563
1564        // 1000000 rounds
1565        let mut r1 = vec![0; pt.len() + Cipher::sm4_ecb().block_size()];
1566        for _ in 0..999999 {
1567            c.update(&r[..block_size], &mut r1).unwrap();
1568            mem::swap(&mut r, &mut r1);
1569        }
1570        assert_eq!(ct1, &r[..count]);
1571    }
1572
1573    #[test]
1574    #[should_panic(expected = "an IV is required for this cipher")]
1575    fn test_crypter_panics_for_missing_iv_cbc() {
1576        let key = [0u8; 16];
1577        let _ = Crypter::new(
1578            super::Cipher::aes_128_cbc(),
1579            super::Mode::Encrypt,
1580            &key,
1581            None,
1582        );
1583    }
1584
1585    #[test]
1586    #[should_panic(expected = "an IV is required for this cipher")]
1587    fn test_crypter_panics_for_missing_iv_gcm() {
1588        let key = [0u8; 16];
1589        let _ = Crypter::new(
1590            super::Cipher::aes_128_gcm(),
1591            super::Mode::Encrypt,
1592            &key,
1593            None,
1594        );
1595    }
1596}