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