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