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