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