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