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]
1023 #[cfg_attr(ossl300, ignore)]
test_rc4()1024 fn test_rc4() {
1025 let pt = "0000000000000000000000000000000000000000000000000000000000000000000000000000";
1026 let ct = "A68686B04D686AA107BD8D4CAB191A3EEC0A6294BC78B60F65C25CB47BD7BB3A48EFC4D26BE4";
1027 let key = "97CD440324DA5FD1F7955C1C13B6B466";
1028 let iv = "";
1029
1030 cipher_test(super::Cipher::rc4(), pt, ct, key, iv);
1031 }
1032
1033 #[test]
test_aes256_xts()1034 fn test_aes256_xts() {
1035 // Test case 174 from
1036 // http://csrc.nist.gov/groups/STM/cavp/documents/aes/XTSTestVectors.zip
1037 let pt = "77f4ef63d734ebd028508da66c22cdebdd52ecd6ee2ab0a50bc8ad0cfd692ca5fcd4e6dedc45df7f\
1038 6503f462611dc542";
1039 let ct = "ce7d905a7776ac72f240d22aafed5e4eb7566cdc7211220e970da634ce015f131a5ecb8d400bc9e8\
1040 4f0b81d8725dbbc7";
1041 let key = "b6bfef891f83b5ff073f2231267be51eb084b791fa19a154399c0684c8b2dfcb37de77d28bbda3b\
1042 4180026ad640b74243b3133e7b9fae629403f6733423dae28";
1043 let iv = "db200efb7eaaa737dbdf40babb68953f";
1044
1045 cipher_test(super::Cipher::aes_256_xts(), pt, ct, key, iv);
1046 }
1047
1048 #[test]
test_aes128_ctr()1049 fn test_aes128_ctr() {
1050 let pt = "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411\
1051 E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710";
1052 let ct = "874D6191B620E3261BEF6864990DB6CE9806F66B7970FDFF8617187BB9FFFDFF5AE4DF3EDBD5D35E\
1053 5B4F09020DB03EAB1E031DDA2FBE03D1792170A0F3009CEE";
1054 let key = "2B7E151628AED2A6ABF7158809CF4F3C";
1055 let iv = "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF";
1056
1057 cipher_test(super::Cipher::aes_128_ctr(), pt, ct, key, iv);
1058 }
1059
1060 #[test]
test_aes128_cfb1()1061 fn test_aes128_cfb1() {
1062 // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1063
1064 let pt = "6bc1";
1065 let ct = "68b3";
1066 let key = "2b7e151628aed2a6abf7158809cf4f3c";
1067 let iv = "000102030405060708090a0b0c0d0e0f";
1068
1069 cipher_test(super::Cipher::aes_128_cfb1(), pt, ct, key, iv);
1070 }
1071
1072 #[test]
test_aes128_cfb128()1073 fn test_aes128_cfb128() {
1074 let pt = "6bc1bee22e409f96e93d7e117393172a";
1075 let ct = "3b3fd92eb72dad20333449f8e83cfb4a";
1076 let key = "2b7e151628aed2a6abf7158809cf4f3c";
1077 let iv = "000102030405060708090a0b0c0d0e0f";
1078
1079 cipher_test(super::Cipher::aes_128_cfb128(), pt, ct, key, iv);
1080 }
1081
1082 #[test]
test_aes128_cfb8()1083 fn test_aes128_cfb8() {
1084 let pt = "6bc1bee22e409f96e93d7e117393172aae2d";
1085 let ct = "3b79424c9c0dd436bace9e0ed4586a4f32b9";
1086 let key = "2b7e151628aed2a6abf7158809cf4f3c";
1087 let iv = "000102030405060708090a0b0c0d0e0f";
1088
1089 cipher_test(super::Cipher::aes_128_cfb8(), pt, ct, key, iv);
1090 }
1091
1092 #[test]
test_aes128_ofb()1093 fn test_aes128_ofb() {
1094 // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1095
1096 let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1097 let ct = "3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e";
1098 let key = "2b7e151628aed2a6abf7158809cf4f3c";
1099 let iv = "000102030405060708090a0b0c0d0e0f";
1100
1101 cipher_test(super::Cipher::aes_128_ofb(), pt, ct, key, iv);
1102 }
1103
1104 #[test]
test_aes192_ctr()1105 fn test_aes192_ctr() {
1106 // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1107
1108 let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1109 let ct = "1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e941e36b26bd1ebc670d1bd1d665620abf74f78a7f6d29809585a97daec58c6b050";
1110 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1111 let iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
1112
1113 cipher_test(super::Cipher::aes_192_ctr(), pt, ct, key, iv);
1114 }
1115
1116 #[test]
test_aes192_cfb1()1117 fn test_aes192_cfb1() {
1118 // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1119
1120 let pt = "6bc1";
1121 let ct = "9359";
1122 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1123 let iv = "000102030405060708090a0b0c0d0e0f";
1124
1125 cipher_test(super::Cipher::aes_192_cfb1(), pt, ct, key, iv);
1126 }
1127
1128 #[test]
test_aes192_cfb128()1129 fn test_aes192_cfb128() {
1130 // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1131
1132 let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1133 let ct = "cdc80d6fddf18cab34c25909c99a417467ce7f7f81173621961a2b70171d3d7a2e1e8a1dd59b88b1c8e60fed1efac4c9c05f9f9ca9834fa042ae8fba584b09ff";
1134 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1135 let iv = "000102030405060708090a0b0c0d0e0f";
1136
1137 cipher_test(super::Cipher::aes_192_cfb128(), pt, ct, key, iv);
1138 }
1139
1140 #[test]
test_aes192_cfb8()1141 fn test_aes192_cfb8() {
1142 // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1143
1144 let pt = "6bc1bee22e409f96e93d7e117393172aae2d";
1145 let ct = "cda2521ef0a905ca44cd057cbf0d47a0678a";
1146 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1147 let iv = "000102030405060708090a0b0c0d0e0f";
1148
1149 cipher_test(super::Cipher::aes_192_cfb8(), pt, ct, key, iv);
1150 }
1151
1152 #[test]
test_aes192_ofb()1153 fn test_aes192_ofb() {
1154 // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1155
1156 let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1157 let ct = "cdc80d6fddf18cab34c25909c99a4174fcc28b8d4c63837c09e81700c11004018d9a9aeac0f6596f559c6d4daf59a5f26d9f200857ca6c3e9cac524bd9acc92a";
1158 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1159 let iv = "000102030405060708090a0b0c0d0e0f";
1160
1161 cipher_test(super::Cipher::aes_192_ofb(), pt, ct, key, iv);
1162 }
1163
1164 #[test]
test_aes256_cfb1()1165 fn test_aes256_cfb1() {
1166 let pt = "6bc1";
1167 let ct = "9029";
1168 let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1169 let iv = "000102030405060708090a0b0c0d0e0f";
1170
1171 cipher_test(super::Cipher::aes_256_cfb1(), pt, ct, key, iv);
1172 }
1173
1174 #[test]
test_aes256_cfb128()1175 fn test_aes256_cfb128() {
1176 let pt = "6bc1bee22e409f96e93d7e117393172a";
1177 let ct = "dc7e84bfda79164b7ecd8486985d3860";
1178 let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1179 let iv = "000102030405060708090a0b0c0d0e0f";
1180
1181 cipher_test(super::Cipher::aes_256_cfb128(), pt, ct, key, iv);
1182 }
1183
1184 #[test]
test_aes256_cfb8()1185 fn test_aes256_cfb8() {
1186 let pt = "6bc1bee22e409f96e93d7e117393172aae2d";
1187 let ct = "dc1f1a8520a64db55fcc8ac554844e889700";
1188 let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1189 let iv = "000102030405060708090a0b0c0d0e0f";
1190
1191 cipher_test(super::Cipher::aes_256_cfb8(), pt, ct, key, iv);
1192 }
1193
1194 #[test]
test_aes256_ofb()1195 fn test_aes256_ofb() {
1196 // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
1197
1198 let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
1199 let ct = "dc7e84bfda79164b7ecd8486985d38604febdc6740d20b3ac88f6ad82a4fb08d71ab47a086e86eedf39d1c5bba97c4080126141d67f37be8538f5a8be740e484";
1200 let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1201 let iv = "000102030405060708090a0b0c0d0e0f";
1202
1203 cipher_test(super::Cipher::aes_256_ofb(), pt, ct, key, iv);
1204 }
1205
1206 #[test]
1207 #[cfg_attr(ossl300, ignore)]
test_bf_cbc()1208 fn test_bf_cbc() {
1209 // https://www.schneier.com/code/vectors.txt
1210
1211 let pt = "37363534333231204E6F77206973207468652074696D6520666F722000000000";
1212 let ct = "6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC";
1213 let key = "0123456789ABCDEFF0E1D2C3B4A59687";
1214 let iv = "FEDCBA9876543210";
1215
1216 cipher_test_nopad(super::Cipher::bf_cbc(), pt, ct, key, iv);
1217 }
1218
1219 #[test]
1220 #[cfg_attr(ossl300, ignore)]
test_bf_ecb()1221 fn test_bf_ecb() {
1222 let pt = "5CD54CA83DEF57DA";
1223 let ct = "B1B8CC0B250F09A0";
1224 let key = "0131D9619DC1376E";
1225 let iv = "0000000000000000";
1226
1227 cipher_test_nopad(super::Cipher::bf_ecb(), pt, ct, key, iv);
1228 }
1229
1230 #[test]
1231 #[cfg_attr(ossl300, ignore)]
test_bf_cfb64()1232 fn test_bf_cfb64() {
1233 let pt = "37363534333231204E6F77206973207468652074696D6520666F722000";
1234 let ct = "E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3";
1235 let key = "0123456789ABCDEFF0E1D2C3B4A59687";
1236 let iv = "FEDCBA9876543210";
1237
1238 cipher_test_nopad(super::Cipher::bf_cfb64(), pt, ct, key, iv);
1239 }
1240
1241 #[test]
1242 #[cfg_attr(ossl300, ignore)]
test_bf_ofb()1243 fn test_bf_ofb() {
1244 let pt = "37363534333231204E6F77206973207468652074696D6520666F722000";
1245 let ct = "E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA";
1246 let key = "0123456789ABCDEFF0E1D2C3B4A59687";
1247 let iv = "FEDCBA9876543210";
1248
1249 cipher_test_nopad(super::Cipher::bf_ofb(), pt, ct, key, iv);
1250 }
1251
1252 #[test]
1253 #[cfg_attr(ossl300, ignore)]
test_des_cbc()1254 fn test_des_cbc() {
1255 let pt = "54686973206973206120746573742e";
1256 let ct = "6f2867cfefda048a4046ef7e556c7132";
1257 let key = "7cb66337f3d3c0fe";
1258 let iv = "0001020304050607";
1259
1260 cipher_test(super::Cipher::des_cbc(), pt, ct, key, iv);
1261 }
1262
1263 #[test]
1264 #[cfg_attr(ossl300, ignore)]
test_des_ecb()1265 fn test_des_ecb() {
1266 let pt = "54686973206973206120746573742e";
1267 let ct = "0050ab8aecec758843fe157b4dde938c";
1268 let key = "7cb66337f3d3c0fe";
1269 let iv = "0001020304050607";
1270
1271 cipher_test(super::Cipher::des_ecb(), pt, ct, key, iv);
1272 }
1273
1274 #[test]
test_des_ede3()1275 fn test_des_ede3() {
1276 let pt = "9994f4c69d40ae4f34ff403b5cf39d4c8207ea5d3e19a5fd";
1277 let ct = "9e5c4297d60582f81071ac8ab7d0698d4c79de8b94c519858207ea5d3e19a5fd";
1278 let key = "010203040506070801020304050607080102030405060708";
1279 let iv = "5cc118306dc702e4";
1280
1281 cipher_test(super::Cipher::des_ede3(), pt, ct, key, iv);
1282 }
1283
1284 #[test]
test_des_ede3_cbc()1285 fn test_des_ede3_cbc() {
1286 let pt = "54686973206973206120746573742e";
1287 let ct = "6f2867cfefda048a4046ef7e556c7132";
1288 let key = "7cb66337f3d3c0fe7cb66337f3d3c0fe7cb66337f3d3c0fe";
1289 let iv = "0001020304050607";
1290
1291 cipher_test(super::Cipher::des_ede3_cbc(), pt, ct, key, iv);
1292 }
1293
1294 #[test]
test_des_ede3_cfb64()1295 fn test_des_ede3_cfb64() {
1296 let pt = "2b1773784b5889dc788477367daa98ad";
1297 let ct = "6f2867cfefda048a4046ef7e556c7132";
1298 let key = "7cb66337f3d3c0fe7cb66337f3d3c0fe7cb66337f3d3c0fe";
1299 let iv = "0001020304050607";
1300
1301 cipher_test(super::Cipher::des_ede3_cfb64(), pt, ct, key, iv);
1302 }
1303
1304 #[test]
test_aes128_gcm()1305 fn test_aes128_gcm() {
1306 let key = "23dc8d23d95b6fd1251741a64f7d4f41";
1307 let iv = "f416f48ad44d9efa1179e167";
1308 let pt = "6cb9b71dd0ccd42cdf87e8e396fc581fd8e0d700e360f590593b748e105390de";
1309 let aad = "45074844c97d515c65bbe37c210a5a4b08c21c588efe5c5f73c4d9c17d34dacddc0bb6a8a53f7bf477b9780c1c2a928660df87016b2873fe876b2b887fb5886bfd63216b7eaecc046372a82c047eb043f0b063226ee52a12c69b";
1310 let ct = "8ad20486778e87387efb3f2574e509951c0626816722018129e578b2787969d3";
1311 let tag = "91e1bc09";
1312
1313 // this tag is smaller than you'd normally want, but I pulled this test from the part of
1314 // the NIST test vectors that cover 4 byte tags.
1315 let mut actual_tag = [0; 4];
1316 let out = encrypt_aead(
1317 Cipher::aes_128_gcm(),
1318 &Vec::from_hex(key).unwrap(),
1319 Some(&Vec::from_hex(iv).unwrap()),
1320 &Vec::from_hex(aad).unwrap(),
1321 &Vec::from_hex(pt).unwrap(),
1322 &mut actual_tag,
1323 )
1324 .unwrap();
1325 assert_eq!(ct, hex::encode(out));
1326 assert_eq!(tag, hex::encode(actual_tag));
1327
1328 let out = decrypt_aead(
1329 Cipher::aes_128_gcm(),
1330 &Vec::from_hex(key).unwrap(),
1331 Some(&Vec::from_hex(iv).unwrap()),
1332 &Vec::from_hex(aad).unwrap(),
1333 &Vec::from_hex(ct).unwrap(),
1334 &Vec::from_hex(tag).unwrap(),
1335 )
1336 .unwrap();
1337 assert_eq!(pt, hex::encode(out));
1338 }
1339
1340 #[test]
test_aes128_ccm()1341 fn test_aes128_ccm() {
1342 let key = "3ee186594f110fb788a8bf8aa8be5d4a";
1343 let nonce = "44f705d52acf27b7f17196aa9b";
1344 let aad = "2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57";
1345
1346 let pt = "d71864877f2578db092daba2d6a1f9f4698a9c356c7830a1";
1347 let ct = "b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0";
1348 let tag = "d6965f5aa6e31302a9cc2b36";
1349
1350 let mut actual_tag = [0; 12];
1351 let out = encrypt_aead(
1352 Cipher::aes_128_ccm(),
1353 &Vec::from_hex(key).unwrap(),
1354 Some(&Vec::from_hex(nonce).unwrap()),
1355 &Vec::from_hex(aad).unwrap(),
1356 &Vec::from_hex(pt).unwrap(),
1357 &mut actual_tag,
1358 )
1359 .unwrap();
1360
1361 assert_eq!(ct, hex::encode(out));
1362 assert_eq!(tag, hex::encode(actual_tag));
1363
1364 let out = decrypt_aead(
1365 Cipher::aes_128_ccm(),
1366 &Vec::from_hex(key).unwrap(),
1367 Some(&Vec::from_hex(nonce).unwrap()),
1368 &Vec::from_hex(aad).unwrap(),
1369 &Vec::from_hex(ct).unwrap(),
1370 &Vec::from_hex(tag).unwrap(),
1371 )
1372 .unwrap();
1373 assert_eq!(pt, hex::encode(out));
1374 }
1375
1376 #[test]
test_aes128_ccm_verify_fail()1377 fn test_aes128_ccm_verify_fail() {
1378 let key = "3ee186594f110fb788a8bf8aa8be5d4a";
1379 let nonce = "44f705d52acf27b7f17196aa9b";
1380 let aad = "2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57";
1381
1382 let ct = "b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0";
1383 let tag = "00005f5aa6e31302a9cc2b36";
1384
1385 let out = decrypt_aead(
1386 Cipher::aes_128_ccm(),
1387 &Vec::from_hex(key).unwrap(),
1388 Some(&Vec::from_hex(nonce).unwrap()),
1389 &Vec::from_hex(aad).unwrap(),
1390 &Vec::from_hex(ct).unwrap(),
1391 &Vec::from_hex(tag).unwrap(),
1392 );
1393 assert!(out.is_err());
1394 }
1395
1396 #[test]
test_aes256_ccm()1397 fn test_aes256_ccm() {
1398 let key = "7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d";
1399 let nonce = "dde2a362ce81b2b6913abc3095";
1400 let aad = "404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695";
1401
1402 let pt = "7ebef26bf4ecf6f0ebb2eb860edbf900f27b75b4a6340fdb";
1403 let ct = "353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd";
1404 let tag = "2927a053c9244d3217a7ad05";
1405
1406 let mut actual_tag = [0; 12];
1407 let out = encrypt_aead(
1408 Cipher::aes_256_ccm(),
1409 &Vec::from_hex(key).unwrap(),
1410 Some(&Vec::from_hex(nonce).unwrap()),
1411 &Vec::from_hex(aad).unwrap(),
1412 &Vec::from_hex(pt).unwrap(),
1413 &mut actual_tag,
1414 )
1415 .unwrap();
1416
1417 assert_eq!(ct, hex::encode(out));
1418 assert_eq!(tag, hex::encode(actual_tag));
1419
1420 let out = decrypt_aead(
1421 Cipher::aes_256_ccm(),
1422 &Vec::from_hex(key).unwrap(),
1423 Some(&Vec::from_hex(nonce).unwrap()),
1424 &Vec::from_hex(aad).unwrap(),
1425 &Vec::from_hex(ct).unwrap(),
1426 &Vec::from_hex(tag).unwrap(),
1427 )
1428 .unwrap();
1429 assert_eq!(pt, hex::encode(out));
1430 }
1431
1432 #[test]
test_aes256_ccm_verify_fail()1433 fn test_aes256_ccm_verify_fail() {
1434 let key = "7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d";
1435 let nonce = "dde2a362ce81b2b6913abc3095";
1436 let aad = "404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695";
1437
1438 let ct = "353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd";
1439 let tag = "0000a053c9244d3217a7ad05";
1440
1441 let out = decrypt_aead(
1442 Cipher::aes_256_ccm(),
1443 &Vec::from_hex(key).unwrap(),
1444 Some(&Vec::from_hex(nonce).unwrap()),
1445 &Vec::from_hex(aad).unwrap(),
1446 &Vec::from_hex(ct).unwrap(),
1447 &Vec::from_hex(tag).unwrap(),
1448 );
1449 assert!(out.is_err());
1450 }
1451
1452 #[test]
1453 #[cfg(ossl110)]
test_aes_128_ocb()1454 fn test_aes_128_ocb() {
1455 let key = "000102030405060708090a0b0c0d0e0f";
1456 let aad = "0001020304050607";
1457 let tag = "16dc76a46d47e1ead537209e8a96d14e";
1458 let iv = "000102030405060708090a0b";
1459 let pt = "0001020304050607";
1460 let ct = "92b657130a74b85a";
1461
1462 let mut actual_tag = [0; 16];
1463 let out = encrypt_aead(
1464 Cipher::aes_128_ocb(),
1465 &Vec::from_hex(key).unwrap(),
1466 Some(&Vec::from_hex(iv).unwrap()),
1467 &Vec::from_hex(aad).unwrap(),
1468 &Vec::from_hex(pt).unwrap(),
1469 &mut actual_tag,
1470 )
1471 .unwrap();
1472
1473 assert_eq!(ct, hex::encode(out));
1474 assert_eq!(tag, hex::encode(actual_tag));
1475
1476 let out = decrypt_aead(
1477 Cipher::aes_128_ocb(),
1478 &Vec::from_hex(key).unwrap(),
1479 Some(&Vec::from_hex(iv).unwrap()),
1480 &Vec::from_hex(aad).unwrap(),
1481 &Vec::from_hex(ct).unwrap(),
1482 &Vec::from_hex(tag).unwrap(),
1483 )
1484 .unwrap();
1485 assert_eq!(pt, hex::encode(out));
1486 }
1487
1488 #[test]
1489 #[cfg(ossl110)]
test_aes_128_ocb_fail()1490 fn test_aes_128_ocb_fail() {
1491 let key = "000102030405060708090a0b0c0d0e0f";
1492 let aad = "0001020304050607";
1493 let tag = "16dc76a46d47e1ead537209e8a96d14e";
1494 let iv = "000000000405060708090a0b";
1495 let ct = "92b657130a74b85a";
1496
1497 let out = decrypt_aead(
1498 Cipher::aes_128_ocb(),
1499 &Vec::from_hex(key).unwrap(),
1500 Some(&Vec::from_hex(iv).unwrap()),
1501 &Vec::from_hex(aad).unwrap(),
1502 &Vec::from_hex(ct).unwrap(),
1503 &Vec::from_hex(tag).unwrap(),
1504 );
1505 assert!(out.is_err());
1506 }
1507
1508 #[test]
1509 #[cfg(any(ossl110))]
test_chacha20()1510 fn test_chacha20() {
1511 let key = "0000000000000000000000000000000000000000000000000000000000000000";
1512 let iv = "00000000000000000000000000000000";
1513 let pt =
1514 "000000000000000000000000000000000000000000000000000000000000000000000000000000000\
1515 00000000000000000000000000000000000000000000000";
1516 let ct =
1517 "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7\
1518 724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586";
1519
1520 cipher_test(Cipher::chacha20(), pt, ct, key, iv);
1521 }
1522
1523 #[test]
1524 #[cfg(any(ossl110))]
test_chacha20_poly1305()1525 fn test_chacha20_poly1305() {
1526 let key = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f";
1527 let iv = "070000004041424344454647";
1528 let aad = "50515253c0c1c2c3c4c5c6c7";
1529 let pt =
1530 "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393\
1531 a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f722074\
1532 6865206675747572652c2073756e73637265656e20776f756c642062652069742e";
1533 let ct =
1534 "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca967128\
1535 2fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fa\
1536 b324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116";
1537 let tag = "1ae10b594f09e26a7e902ecbd0600691";
1538
1539 let mut actual_tag = [0; 16];
1540 let out = encrypt_aead(
1541 Cipher::chacha20_poly1305(),
1542 &Vec::from_hex(key).unwrap(),
1543 Some(&Vec::from_hex(iv).unwrap()),
1544 &Vec::from_hex(aad).unwrap(),
1545 &Vec::from_hex(pt).unwrap(),
1546 &mut actual_tag,
1547 )
1548 .unwrap();
1549 assert_eq!(ct, hex::encode(out));
1550 assert_eq!(tag, hex::encode(actual_tag));
1551
1552 let out = decrypt_aead(
1553 Cipher::chacha20_poly1305(),
1554 &Vec::from_hex(key).unwrap(),
1555 Some(&Vec::from_hex(iv).unwrap()),
1556 &Vec::from_hex(aad).unwrap(),
1557 &Vec::from_hex(ct).unwrap(),
1558 &Vec::from_hex(tag).unwrap(),
1559 )
1560 .unwrap();
1561 assert_eq!(pt, hex::encode(out));
1562 }
1563 }
1564