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