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