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