1#![warn(missing_docs)]
52
53use crate::cipher::CipherRef;
54use crate::error::ErrorStack;
55#[cfg(not(any(boringssl, awslc)))]
56use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef};
57use crate::{cvt, cvt_p};
58#[cfg(ossl110)]
59use bitflags::bitflags;
60use cfg_if::cfg_if;
61use foreign_types::{ForeignType, ForeignTypeRef};
62use libc::{c_int, c_uchar};
63use openssl_macros::corresponds;
64use std::convert::{TryFrom, TryInto};
65use std::ptr;
66
67cfg_if! {
68 if #[cfg(ossl300)] {
69 use ffi::EVP_CIPHER_CTX_get0_cipher;
70 } else {
71 use ffi::EVP_CIPHER_CTX_cipher as EVP_CIPHER_CTX_get0_cipher;
72 }
73}
74
75foreign_type_and_impl_send_sync! {
76 type CType = ffi::EVP_CIPHER_CTX;
77 fn drop = ffi::EVP_CIPHER_CTX_free;
78
79 pub struct CipherCtx;
81 pub struct CipherCtxRef;
83}
84
85#[cfg(ossl110)]
86bitflags! {
87 pub struct CipherCtxFlags : c_int {
89 const FLAG_WRAP_ALLOW = ffi::EVP_CIPHER_CTX_FLAG_WRAP_ALLOW;
91 }
92}
93
94impl CipherCtx {
95 #[corresponds(EVP_CIPHER_CTX_new)]
97 pub fn new() -> Result<Self, ErrorStack> {
98 ffi::init();
99
100 unsafe {
101 let ptr = cvt_p(ffi::EVP_CIPHER_CTX_new())?;
102 Ok(CipherCtx::from_ptr(ptr))
103 }
104 }
105}
106
107impl CipherCtxRef {
108 #[corresponds(EVP_CIPHER_CTX_reset)]
112 #[cfg(any(ossl110, libressl350))]
113 #[inline]
114 pub fn reset(&mut self) -> Result<(), ErrorStack> {
115 unsafe {
116 let _ = cvt(ffi::EVP_CIPHER_CTX_reset(self.as_ptr()))?;
117 Ok(())
118 }
119 }
120
121 #[corresponds(EVP_CIPHER_CTX_reset)]
125 #[cfg(any(boringssl, awslc))]
126 #[inline]
127 pub fn reset(&mut self) -> Result<(), ErrorStack> {
128 unsafe {
129 ffi::EVP_CIPHER_CTX_reset(self.as_ptr());
130 Ok(())
131 }
132 }
133
134 #[corresponds(EVP_CIPHER_CTX_copy)]
135 pub fn copy(&mut self, src: &CipherCtxRef) -> Result<(), ErrorStack> {
136 unsafe {
137 cvt(ffi::EVP_CIPHER_CTX_copy(self.as_ptr(), src.as_ptr()))?;
138 Ok(())
139 }
140 }
141
142 #[corresponds(EVP_EncryptInit_ex)]
153 pub fn encrypt_init(
154 &mut self,
155 type_: Option<&CipherRef>,
156 key: Option<&[u8]>,
157 iv: Option<&[u8]>,
158 ) -> Result<(), ErrorStack> {
159 self.cipher_init(type_, key, iv, ffi::EVP_EncryptInit_ex)
160 }
161
162 #[corresponds(EVP_DecryptInit_ex)]
173 pub fn decrypt_init(
174 &mut self,
175 type_: Option<&CipherRef>,
176 key: Option<&[u8]>,
177 iv: Option<&[u8]>,
178 ) -> Result<(), ErrorStack> {
179 self.cipher_init(type_, key, iv, ffi::EVP_DecryptInit_ex)
180 }
181
182 fn cipher_init(
183 &mut self,
184 type_: Option<&CipherRef>,
185 key: Option<&[u8]>,
186 iv: Option<&[u8]>,
187 f: unsafe extern "C" fn(
188 *mut ffi::EVP_CIPHER_CTX,
189 *const ffi::EVP_CIPHER,
190 *mut ffi::ENGINE,
191 *const c_uchar,
192 *const c_uchar,
193 ) -> c_int,
194 ) -> Result<(), ErrorStack> {
195 if let Some(key) = key {
196 let key_len = type_.map_or_else(|| self.key_length(), |c| c.key_length());
197 assert!(key_len <= key.len());
198 }
199
200 if let Some(iv) = iv {
201 let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
202 assert!(iv_len <= iv.len());
203 }
204
205 unsafe {
206 cvt(f(
207 self.as_ptr(),
208 type_.map_or(ptr::null(), |p| p.as_ptr()),
209 ptr::null_mut(),
210 key.map_or(ptr::null(), |k| k.as_ptr()),
211 iv.map_or(ptr::null(), |iv| iv.as_ptr()),
212 ))?;
213 }
214
215 Ok(())
216 }
217
218 #[corresponds(EVP_SealInit)]
231 #[cfg(not(any(boringssl, awslc)))]
232 pub fn seal_init<T>(
233 &mut self,
234 type_: Option<&CipherRef>,
235 pub_keys: &[PKey<T>],
236 encrypted_keys: &mut [Vec<u8>],
237 iv: Option<&mut [u8]>,
238 ) -> Result<(), ErrorStack>
239 where
240 T: HasPublic,
241 {
242 assert_eq!(pub_keys.len(), encrypted_keys.len());
243 if !pub_keys.is_empty() {
244 let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
245 assert!(iv.as_ref().map_or(0, |b| b.len()) >= iv_len);
246 }
247
248 for (pub_key, buf) in pub_keys.iter().zip(&mut *encrypted_keys) {
249 buf.resize(pub_key.size(), 0);
250 }
251
252 let mut keys = encrypted_keys
253 .iter_mut()
254 .map(|b| b.as_mut_ptr())
255 .collect::<Vec<_>>();
256 let mut key_lengths = vec![0; pub_keys.len()];
257 let pub_keys_len = i32::try_from(pub_keys.len()).unwrap();
258
259 unsafe {
260 cvt(ffi::EVP_SealInit(
261 self.as_ptr(),
262 type_.map_or(ptr::null(), |p| p.as_ptr()),
263 keys.as_mut_ptr(),
264 key_lengths.as_mut_ptr(),
265 iv.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
266 pub_keys.as_ptr() as *mut _,
267 pub_keys_len,
268 ))?;
269 }
270
271 for (buf, len) in encrypted_keys.iter_mut().zip(key_lengths) {
272 buf.truncate(len as usize);
273 }
274
275 Ok(())
276 }
277
278 #[corresponds(EVP_OpenInit)]
288 #[cfg(not(any(boringssl, awslc)))]
289 pub fn open_init<T>(
290 &mut self,
291 type_: Option<&CipherRef>,
292 encrypted_key: &[u8],
293 iv: Option<&[u8]>,
294 priv_key: Option<&PKeyRef<T>>,
295 ) -> Result<(), ErrorStack>
296 where
297 T: HasPrivate,
298 {
299 if priv_key.is_some() {
300 let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
301 assert!(iv.map_or(0, |b| b.len()) >= iv_len);
302 }
303
304 let len = c_int::try_from(encrypted_key.len()).unwrap();
305 unsafe {
306 cvt(ffi::EVP_OpenInit(
307 self.as_ptr(),
308 type_.map_or(ptr::null(), |p| p.as_ptr()),
309 encrypted_key.as_ptr(),
310 len,
311 iv.map_or(ptr::null(), |b| b.as_ptr()),
312 priv_key.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
313 ))?;
314 }
315
316 Ok(())
317 }
318
319 fn assert_cipher(&self) {
320 unsafe {
321 assert!(!EVP_CIPHER_CTX_get0_cipher(self.as_ptr()).is_null());
322 }
323 }
324
325 #[cfg(not(any(boringssl, awslc)))]
326 fn is_wrap_mode(&self) -> bool {
327 unsafe {
328 let cipher = EVP_CIPHER_CTX_get0_cipher(self.as_ptr());
329 if cipher.is_null() {
330 return false;
331 }
332 ffi::EVP_CIPHER_flags(cipher) & ffi::EVP_CIPH_MODE == ffi::EVP_CIPH_WRAP_MODE
333 }
334 }
335
336 #[cfg(any(boringssl, awslc))]
337 fn is_wrap_mode(&self) -> bool {
338 false
339 }
340
341 fn cipher_update_output_size(&self, input_len: usize) -> usize {
342 if self.is_wrap_mode() {
348 return input_len.saturating_add(7) / 8 * 8 + 8;
349 }
350 let mut block_size = self.block_size();
351 if block_size == 1 {
352 block_size = 0;
353 }
354 input_len + block_size
355 }
356
357 #[corresponds(EVP_CIPHER_CTX_block_size)]
365 pub fn block_size(&self) -> usize {
366 self.assert_cipher();
367
368 unsafe { ffi::EVP_CIPHER_CTX_block_size(self.as_ptr()) as usize }
369 }
370
371 #[corresponds(EVP_CIPHER_CTX_key_length)]
377 pub fn key_length(&self) -> usize {
378 self.assert_cipher();
379
380 unsafe { ffi::EVP_CIPHER_CTX_key_length(self.as_ptr()) as usize }
381 }
382
383 #[corresponds(EVP_CIPHER_CTX_rand_key)]
390 #[cfg(not(any(boringssl, awslc)))]
391 pub fn rand_key(&self, buf: &mut [u8]) -> Result<(), ErrorStack> {
392 assert!(buf.len() >= self.key_length());
393
394 unsafe {
395 cvt(ffi::EVP_CIPHER_CTX_rand_key(
396 self.as_ptr(),
397 buf.as_mut_ptr(),
398 ))?;
399 }
400
401 Ok(())
402 }
403
404 #[corresponds(EVP_CIPHER_CTX_set_key_length)]
412 pub fn set_key_length(&mut self, len: usize) -> Result<(), ErrorStack> {
413 self.assert_cipher();
414
415 unsafe {
416 cvt(ffi::EVP_CIPHER_CTX_set_key_length(
417 self.as_ptr(),
418 len.try_into().unwrap(),
419 ))?;
420 }
421
422 Ok(())
423 }
424
425 #[corresponds(EVP_CIPHER_CTX_iv_length)]
433 pub fn iv_length(&self) -> usize {
434 self.assert_cipher();
435
436 unsafe { ffi::EVP_CIPHER_CTX_iv_length(self.as_ptr()) as usize }
437 }
438
439 #[corresponds(EVP_CIPHER_CTX_num)]
448 #[cfg(ossl110)]
449 pub fn num(&self) -> usize {
450 self.assert_cipher();
451
452 unsafe { ffi::EVP_CIPHER_CTX_num(self.as_ptr()) as usize }
453 }
454
455 #[corresponds(EVP_CIPHER_CTX_ctrl)]
463 pub fn set_iv_length(&mut self, len: usize) -> Result<(), ErrorStack> {
464 self.assert_cipher();
465
466 let len = c_int::try_from(len).unwrap();
467
468 unsafe {
469 cvt(ffi::EVP_CIPHER_CTX_ctrl(
470 self.as_ptr(),
471 ffi::EVP_CTRL_GCM_SET_IVLEN,
472 len,
473 ptr::null_mut(),
474 ))?;
475 }
476
477 Ok(())
478 }
479
480 #[corresponds(EVP_CIPHER_CTX_get_tag_length)]
490 #[cfg(ossl300)]
491 pub fn tag_length(&self) -> usize {
492 self.assert_cipher();
493
494 unsafe { ffi::EVP_CIPHER_CTX_get_tag_length(self.as_ptr()) as usize }
495 }
496
497 #[corresponds(EVP_CIPHER_CTX_ctrl)]
504 pub fn tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> {
505 let len = c_int::try_from(tag.len()).unwrap();
506
507 unsafe {
508 cvt(ffi::EVP_CIPHER_CTX_ctrl(
509 self.as_ptr(),
510 ffi::EVP_CTRL_GCM_GET_TAG,
511 len,
512 tag.as_mut_ptr() as *mut _,
513 ))?;
514 }
515
516 Ok(())
517 }
518
519 #[corresponds(EVP_CIPHER_CTX_ctrl)]
523 pub fn set_tag_length(&mut self, len: usize) -> Result<(), ErrorStack> {
524 let len = c_int::try_from(len).unwrap();
525
526 unsafe {
527 cvt(ffi::EVP_CIPHER_CTX_ctrl(
528 self.as_ptr(),
529 ffi::EVP_CTRL_GCM_SET_TAG,
530 len,
531 ptr::null_mut(),
532 ))?;
533 }
534
535 Ok(())
536 }
537
538 #[corresponds(EVP_CIPHER_CTX_ctrl)]
540 pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> {
541 let len = c_int::try_from(tag.len()).unwrap();
542
543 unsafe {
544 cvt(ffi::EVP_CIPHER_CTX_ctrl(
545 self.as_ptr(),
546 ffi::EVP_CTRL_GCM_SET_TAG,
547 len,
548 tag.as_ptr() as *mut _,
549 ))?;
550 }
551
552 Ok(())
553 }
554
555 #[corresponds(EVP_CIPHER_CTX_set_padding)]
559 pub fn set_padding(&mut self, padding: bool) {
560 unsafe {
561 ffi::EVP_CIPHER_CTX_set_padding(self.as_ptr(), padding as c_int);
562 }
563 }
564
565 #[corresponds(EVP_CipherUpdate)]
569 pub fn set_data_len(&mut self, len: usize) -> Result<(), ErrorStack> {
570 let len = c_int::try_from(len).unwrap();
571
572 unsafe {
573 cvt(ffi::EVP_CipherUpdate(
574 self.as_ptr(),
575 ptr::null_mut(),
576 &mut 0,
577 ptr::null(),
578 len,
579 ))?;
580 }
581
582 Ok(())
583 }
584
585 #[corresponds(EVP_CIPHER_CTX_set_flags)]
589 #[cfg(ossl110)]
590 pub fn set_flags(&mut self, flags: CipherCtxFlags) {
591 unsafe {
592 ffi::EVP_CIPHER_CTX_set_flags(self.as_ptr(), flags.bits());
593 }
594 }
595
596 #[corresponds(EVP_CipherUpdate)]
607 pub fn cipher_update(
608 &mut self,
609 input: &[u8],
610 output: Option<&mut [u8]>,
611 ) -> Result<usize, ErrorStack> {
612 if let Some(output) = &output {
613 let min_output_size = self.cipher_update_output_size(input.len());
614 assert!(
615 output.len() >= min_output_size,
616 "Output buffer size should be at least {} bytes.",
617 min_output_size
618 );
619 }
620
621 unsafe { self.cipher_update_unchecked(input, output) }
622 }
623
624 #[corresponds(EVP_CipherUpdate)]
642 pub unsafe fn cipher_update_unchecked(
643 &mut self,
644 input: &[u8],
645 output: Option<&mut [u8]>,
646 ) -> Result<usize, ErrorStack> {
647 let inlen = c_int::try_from(input.len()).unwrap();
648
649 let mut outlen = 0;
650
651 cvt(ffi::EVP_CipherUpdate(
652 self.as_ptr(),
653 output.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
654 &mut outlen,
655 input.as_ptr(),
656 inlen,
657 ))?;
658
659 Ok(outlen as usize)
660 }
661
662 pub fn cipher_update_vec(
664 &mut self,
665 input: &[u8],
666 output: &mut Vec<u8>,
667 ) -> Result<usize, ErrorStack> {
668 let base = output.len();
669 output.resize(base + self.cipher_update_output_size(input.len()), 0);
670 let len = self.cipher_update(input, Some(&mut output[base..]))?;
671 output.truncate(base + len);
672
673 Ok(len)
674 }
675
676 #[corresponds(EVP_CipherUpdate)]
690 pub fn cipher_update_inplace(
691 &mut self,
692 data: &mut [u8],
693 inlen: usize,
694 ) -> Result<usize, ErrorStack> {
695 assert!(inlen <= data.len(), "Input size may not exceed buffer size");
696 let min_output_size = self.cipher_update_output_size(inlen);
697 assert!(
698 data.len() >= min_output_size,
699 "Output buffer size must be at least {} bytes.",
700 min_output_size
701 );
702
703 let inlen = c_int::try_from(inlen).unwrap();
704 let mut outlen = 0;
705 unsafe {
706 cvt(ffi::EVP_CipherUpdate(
707 self.as_ptr(),
708 data.as_mut_ptr(),
709 &mut outlen,
710 data.as_ptr(),
711 inlen,
712 ))
713 }?;
714
715 Ok(outlen as usize)
716 }
717
718 #[corresponds(EVP_CipherFinal)]
728 pub fn cipher_final(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
729 let block_size = self.block_size();
730 if block_size > 1 {
731 assert!(output.len() >= block_size);
732 }
733
734 unsafe { self.cipher_final_unchecked(output) }
735 }
736
737 #[corresponds(EVP_CipherFinal)]
753 pub unsafe fn cipher_final_unchecked(
754 &mut self,
755 output: &mut [u8],
756 ) -> Result<usize, ErrorStack> {
757 let mut outl = 0;
758
759 cvt(ffi::EVP_CipherFinal(
760 self.as_ptr(),
761 output.as_mut_ptr(),
762 &mut outl,
763 ))?;
764
765 Ok(outl as usize)
766 }
767
768 pub fn cipher_final_vec(&mut self, output: &mut Vec<u8>) -> Result<usize, ErrorStack> {
770 let base = output.len();
771 output.resize(base + self.block_size(), 0);
772 let len = self.cipher_final(&mut output[base..])?;
773 output.truncate(base + len);
774
775 Ok(len)
776 }
777}
778
779#[cfg(test)]
780mod test {
781 use super::*;
782 use crate::{cipher::Cipher, rand::rand_bytes};
783 #[cfg(not(any(boringssl, awslc)))]
784 use std::slice;
785
786 #[test]
787 #[cfg(not(any(boringssl, awslc)))]
788 fn seal_open() {
789 let private_pem = include_bytes!("../test/rsa.pem");
790 let public_pem = include_bytes!("../test/rsa.pem.pub");
791 let private_key = PKey::private_key_from_pem(private_pem).unwrap();
792 let public_key = PKey::public_key_from_pem(public_pem).unwrap();
793 let cipher = Cipher::aes_256_cbc();
794 let secret = b"My secret message";
795
796 let mut ctx = CipherCtx::new().unwrap();
797 let mut encrypted_key = vec![];
798 let mut iv = vec![0; cipher.iv_length()];
799 let mut encrypted = vec![];
800 ctx.seal_init(
801 Some(cipher),
802 &[public_key],
803 slice::from_mut(&mut encrypted_key),
804 Some(&mut iv),
805 )
806 .unwrap();
807 ctx.cipher_update_vec(secret, &mut encrypted).unwrap();
808 ctx.cipher_final_vec(&mut encrypted).unwrap();
809
810 let mut decrypted = vec![];
811 ctx.open_init(Some(cipher), &encrypted_key, Some(&iv), Some(&private_key))
812 .unwrap();
813 ctx.cipher_update_vec(&encrypted, &mut decrypted).unwrap();
814 ctx.cipher_final_vec(&mut decrypted).unwrap();
815
816 assert_eq!(secret, &decrypted[..]);
817 }
818
819 fn aes_128_cbc(cipher: &CipherRef) {
820 let key = hex::decode("2b7e151628aed2a6abf7158809cf4f3c").unwrap();
822 let iv = hex::decode("000102030405060708090a0b0c0d0e0f").unwrap();
823 let pt = hex::decode("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51")
824 .unwrap();
825 let ct = hex::decode("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2")
826 .unwrap();
827
828 let mut ctx = CipherCtx::new().unwrap();
829
830 ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
831 .unwrap();
832 ctx.set_padding(false);
833
834 let mut buf = vec![];
835 ctx.cipher_update_vec(&pt, &mut buf).unwrap();
836 ctx.cipher_final_vec(&mut buf).unwrap();
837
838 assert_eq!(buf, ct);
839
840 ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv))
841 .unwrap();
842 ctx.set_padding(false);
843
844 let mut buf = vec![];
845 ctx.cipher_update_vec(&ct, &mut buf).unwrap();
846 ctx.cipher_final_vec(&mut buf).unwrap();
847
848 assert_eq!(buf, pt);
849 }
850
851 #[test]
852 #[cfg(ossl300)]
853 fn fetched_aes_128_cbc() {
854 let cipher = Cipher::fetch(None, "AES-128-CBC", None).unwrap();
855 aes_128_cbc(&cipher);
856 }
857
858 #[test]
859 fn default_aes_128_cbc() {
860 let cipher = Cipher::aes_128_cbc();
861 aes_128_cbc(cipher);
862 }
863
864 #[cfg(not(boringssl))]
865 #[test]
866 fn default_aes_128_ccm() {
867 let cipher = Cipher::aes_128_ccm();
869 aes_ccm(
870 cipher,
871 "26511fb51fcfa75cb4b44da75a6e5a0e",
872 "ea98ec44f5a86715014783172e",
873 "4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10",
874 "e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810",
875 "1bf0ba0ebb20d8edba59f29a9371750c9c714078f73c335d",
876 "2f1322ac69b848b001476323aed84c47",
877 );
878 }
879
880 #[cfg(not(boringssl))]
881 #[test]
882 fn default_aes_192_ccm() {
883 let cipher = Cipher::aes_192_ccm();
885 aes_ccm(
886 cipher,
887 "26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886",
888 "ea98ec44f5a86715014783172e",
889 "4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10",
890 "e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810",
891 "30c154c616946eccc2e241d336ad33720953e449a0e6b0f0",
892 "dbf8e9464909bdf337e48093c082a10b",
893 );
894 }
895
896 #[cfg(not(boringssl))]
897 #[test]
898 fn default_aes_256_ccm() {
899 let cipher = Cipher::aes_256_ccm();
901 aes_ccm(
902 cipher,
903 "314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e",
904 "3542fbe0f59a6d5f3abf619b7d",
905 "c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed",
906 "dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8",
907 "39c2e8f6edfe663b90963b98eb79e2d4f7f28a5053ae8881",
908 "567a6b4426f1667136bed4a5e32a2bc1",
909 );
910 }
911
912 #[cfg(not(boringssl))]
913 fn aes_ccm(
914 cipher: &CipherRef,
915 key: &'static str,
916 iv: &'static str,
917 pt: &'static str,
918 aad: &'static str,
919 ct: &'static str,
920 tag: &'static str,
921 ) {
922 let key = hex::decode(key).unwrap();
923 let iv = hex::decode(iv).unwrap();
924 let pt = hex::decode(pt).unwrap();
925 let ct = hex::decode(ct).unwrap();
926 let aad = hex::decode(aad).unwrap();
927 let tag = hex::decode(tag).unwrap();
928
929 let mut ctx = CipherCtx::new().unwrap();
930
931 ctx.encrypt_init(Some(cipher), None, None).unwrap();
932 ctx.set_iv_length(iv.len()).unwrap();
933 ctx.set_tag_length(tag.len()).unwrap();
934 ctx.encrypt_init(None, Some(&key), Some(&iv)).unwrap();
935 ctx.set_data_len(pt.len()).unwrap();
936
937 let mut buf = vec![];
938 ctx.cipher_update(&aad, None).unwrap();
939 ctx.cipher_update_vec(&pt, &mut buf).unwrap();
940 ctx.cipher_final_vec(&mut buf).unwrap();
941 assert_eq!(buf, ct);
942
943 let mut out_tag = vec![0u8; tag.len()];
944 ctx.tag(&mut out_tag).unwrap();
945 assert_eq!(tag, out_tag);
946
947 ctx.decrypt_init(Some(cipher), None, None).unwrap();
948 ctx.set_iv_length(iv.len()).unwrap();
949 ctx.set_tag(&tag).unwrap();
950 ctx.decrypt_init(None, Some(&key), Some(&iv)).unwrap();
951 ctx.set_data_len(pt.len()).unwrap();
952
953 let mut buf = vec![];
954 ctx.cipher_update(&aad, None).unwrap();
955 ctx.cipher_update_vec(&ct, &mut buf).unwrap();
956 #[cfg(any(ossl111, awslc, boringssl))]
959 ctx.cipher_final_vec(&mut buf).unwrap();
960
961 assert_eq!(buf, pt);
962 }
963
964 #[cfg(not(any(boringssl, awslc)))]
965 #[test]
966 fn default_aes_128_xts() {
967 let cipher = Cipher::aes_128_xts();
969 aes_xts(
970 cipher,
971 "a1b90cba3f06ac353b2c343876081762090923026e91771815f29dab01932f2f",
972 "4faef7117cda59c66e4b92013e768ad5",
973 "ebabce95b14d3c8d6fb350390790311c",
974 "778ae8b43cb98d5a825081d5be471c63",
975 );
976 }
977
978 #[cfg(not(boringssl))]
979 #[test]
980 fn default_aes_256_xts() {
981 let cipher = Cipher::aes_256_xts();
983 aes_xts(cipher, "1ea661c58d943a0e4801e42f4b0947149e7f9f8e3e68d0c7505210bd311a0e7cd6e13ffdf2418d8d1911c004cda58da3d619b7e2b9141e58318eea392cf41b08", "adf8d92627464ad2f0428e84a9f87564", "2eedea52cd8215e1acc647e810bbc3642e87287f8d2e57e36c0a24fbc12a202e", "cbaad0e2f6cea3f50b37f934d46a9b130b9d54f07e34f36af793e86f73c6d7db");
984 }
985
986 #[cfg(not(boringssl))]
987 fn aes_xts(
988 cipher: &CipherRef,
989 key: &'static str,
990 i: &'static str,
991 pt: &'static str,
992 ct: &'static str,
993 ) {
994 let key = hex::decode(key).unwrap();
995 let i = hex::decode(i).unwrap();
996 let pt = hex::decode(pt).unwrap();
997 let ct = hex::decode(ct).unwrap();
998
999 let mut ctx = CipherCtx::new().unwrap();
1000 ctx.encrypt_init(Some(cipher), Some(&key), Some(&i))
1001 .unwrap();
1002 let mut buf = vec![];
1003 ctx.cipher_update_vec(&pt, &mut buf).unwrap();
1004 ctx.cipher_final_vec(&mut buf).unwrap();
1005
1006 assert_eq!(ct, buf);
1007
1008 ctx.decrypt_init(Some(cipher), Some(&key), Some(&i))
1009 .unwrap();
1010 let mut buf = vec![];
1011 ctx.cipher_update_vec(&ct, &mut buf).unwrap();
1012 ctx.cipher_final_vec(&mut buf).unwrap();
1013
1014 assert_eq!(pt, buf);
1015 }
1016
1017 #[test]
1018 fn test_stream_ciphers() {
1019 #[cfg(not(boringssl))]
1020 {
1021 test_stream_cipher(Cipher::aes_128_cfb1());
1022 test_stream_cipher(Cipher::aes_128_cfb8());
1023 test_stream_cipher(Cipher::aes_128_cfb128());
1024 test_stream_cipher(Cipher::aes_192_cfb1());
1025 test_stream_cipher(Cipher::aes_192_cfb8());
1026 test_stream_cipher(Cipher::aes_192_cfb128());
1027 test_stream_cipher(Cipher::aes_256_cfb1());
1028 test_stream_cipher(Cipher::aes_256_cfb8());
1029 test_stream_cipher(Cipher::aes_256_cfb128());
1030 }
1031 test_stream_cipher(Cipher::aes_192_ctr());
1032 test_stream_cipher(Cipher::aes_256_ctr());
1033 }
1034
1035 fn test_stream_cipher(cipher: &'static CipherRef) {
1036 let mut key = vec![0; cipher.key_length()];
1037 rand_bytes(&mut key).unwrap();
1038 let mut iv = vec![0; cipher.iv_length()];
1039 rand_bytes(&mut iv).unwrap();
1040
1041 let mut ctx = CipherCtx::new().unwrap();
1042
1043 ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
1044 .unwrap();
1045 ctx.set_padding(false);
1046
1047 assert_eq!(
1048 1,
1049 cipher.block_size(),
1050 "Need a stream cipher, not a block cipher"
1051 );
1052
1053 let mut output = vec![0; 32];
1057 let outlen = ctx
1058 .cipher_update(&[1; 15], Some(&mut output[0..15]))
1059 .unwrap();
1060 assert_eq!(15, outlen);
1061
1062 let outlen = ctx
1066 .cipher_update(&[1; 17], Some(&mut output[15..]))
1067 .unwrap();
1068 assert_eq!(17, outlen);
1069
1070 ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
1071
1072 ctx.encrypt_init(None, None, Some(&iv)).unwrap();
1075 ctx.set_padding(false);
1076 let mut data_inplace: [u8; 32] = [1; 32];
1077 let outlen = ctx
1078 .cipher_update_inplace(&mut data_inplace[0..15], 15)
1079 .unwrap();
1080 assert_eq!(15, outlen);
1081
1082 let outlen = ctx
1083 .cipher_update_inplace(&mut data_inplace[15..32], 17)
1084 .unwrap();
1085 assert_eq!(17, outlen);
1086
1087 ctx.cipher_final(&mut [0u8; 0]).unwrap();
1088
1089 assert_eq!(data_inplace.as_slice(), output.as_slice());
1091
1092 ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv))
1094 .unwrap();
1095 ctx.set_padding(false);
1096
1097 let mut output_decrypted = vec![0; 32];
1101 let outlen = ctx
1102 .cipher_update(&output[0..15], Some(&mut output_decrypted[0..15]))
1103 .unwrap();
1104 assert_eq!(15, outlen);
1105
1106 let outlen = ctx
1107 .cipher_update(&output[15..], Some(&mut output_decrypted[15..]))
1108 .unwrap();
1109 assert_eq!(17, outlen);
1110
1111 ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
1112 assert_eq!(output_decrypted, vec![1; 32]);
1114
1115 ctx.decrypt_init(None, None, Some(&iv)).unwrap();
1117 ctx.set_padding(false);
1118
1119 let outlen = ctx.cipher_update_inplace(&mut output[0..15], 15).unwrap();
1120 assert_eq!(15, outlen);
1121
1122 let outlen = ctx.cipher_update_inplace(&mut output[15..], 17).unwrap();
1123 assert_eq!(17, outlen);
1124
1125 ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
1126 assert_eq!(output_decrypted, output);
1127 }
1128
1129 #[test]
1130 #[should_panic(expected = "Output buffer size should be at least 33 bytes.")]
1131 fn full_block_updates_aes_128() {
1132 output_buffer_too_small(Cipher::aes_128_cbc());
1133 }
1134
1135 #[test]
1136 #[should_panic(expected = "Output buffer size should be at least 33 bytes.")]
1137 fn full_block_updates_aes_256() {
1138 output_buffer_too_small(Cipher::aes_256_cbc());
1139 }
1140
1141 #[test]
1142 #[should_panic(expected = "Output buffer size should be at least 17 bytes.")]
1143 fn full_block_updates_3des() {
1144 output_buffer_too_small(Cipher::des_ede3_cbc());
1145 }
1146
1147 fn output_buffer_too_small(cipher: &'static CipherRef) {
1148 let mut key = vec![0; cipher.key_length()];
1149 rand_bytes(&mut key).unwrap();
1150 let mut iv = vec![0; cipher.iv_length()];
1151 rand_bytes(&mut iv).unwrap();
1152
1153 let mut ctx = CipherCtx::new().unwrap();
1154
1155 ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
1156 .unwrap();
1157 ctx.set_padding(false);
1158
1159 let block_size = cipher.block_size();
1160 assert!(block_size > 1, "Need a block cipher, not a stream cipher");
1161
1162 ctx.cipher_update(&vec![0; block_size + 1], Some(&mut vec![0; block_size - 1]))
1163 .unwrap();
1164 }
1165
1166 #[cfg(ossl110)]
1167 fn cipher_wrap_test(cipher: &CipherRef, pt: &str, ct: &str, key: &str, iv: Option<&str>) {
1168 let pt = hex::decode(pt).unwrap();
1169 let key = hex::decode(key).unwrap();
1170 let expected = hex::decode(ct).unwrap();
1171 let iv = iv.map(|v| hex::decode(v).unwrap());
1172 let padding = 8 - pt.len() % 8;
1173 let mut computed = vec![0; pt.len() + padding + cipher.block_size() * 2];
1174 let mut ctx = CipherCtx::new().unwrap();
1175
1176 ctx.set_flags(CipherCtxFlags::FLAG_WRAP_ALLOW);
1177 ctx.encrypt_init(Some(cipher), Some(&key), iv.as_deref())
1178 .unwrap();
1179
1180 let count = ctx.cipher_update(&pt, Some(&mut computed)).unwrap();
1181 let rest = ctx.cipher_final(&mut computed[count..]).unwrap();
1182 computed.truncate(count + rest);
1183
1184 if computed != expected {
1185 println!("Computed: {}", hex::encode(&computed));
1186 println!("Expected: {}", hex::encode(&expected));
1187 if computed.len() != expected.len() {
1188 println!(
1189 "Lengths differ: {} in computed vs {} expected",
1190 computed.len(),
1191 expected.len()
1192 );
1193 }
1194 panic!("test failure");
1195 }
1196 }
1197
1198 #[test]
1199 #[cfg(ossl110)]
1200 fn test_aes128_wrap() {
1201 let pt = "00112233445566778899aabbccddeeff";
1202 let ct = "7940ff694448b5bb5139c959a4896832e55d69aa04daa27e";
1203 let key = "2b7e151628aed2a6abf7158809cf4f3c";
1204 let iv = "0001020304050607";
1205
1206 cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, Some(iv));
1207 }
1208
1209 #[test]
1210 #[cfg(ossl110)]
1211 fn test_aes128_wrap_default_iv() {
1212 let pt = "00112233445566778899aabbccddeeff";
1213 let ct = "38f1215f0212526f8a70b51955b9fbdc9fe3041d9832306e";
1214 let key = "2b7e151628aed2a6abf7158809cf4f3c";
1215
1216 cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, None);
1217 }
1218
1219 #[test]
1220 #[cfg(ossl110)]
1221 fn test_aes128_wrap_pad() {
1222 let pt = "00112233445566778899aabbccddee";
1223 let ct = "f13998f5ab32ef82a1bdbcbe585e1d837385b529572a1e1b";
1224 let key = "2b7e151628aed2a6abf7158809cf4f3c";
1225 let iv = "00010203";
1226
1227 cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, Some(iv));
1228 }
1229
1230 #[test]
1231 #[cfg(ossl110)]
1232 fn test_aes128_wrap_pad_default_iv() {
1233 let pt = "00112233445566778899aabbccddee";
1234 let ct = "3a501085fb8cf66f4186b7df851914d471ed823411598add";
1235 let key = "2b7e151628aed2a6abf7158809cf4f3c";
1236
1237 cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, None);
1238 }
1239
1240 #[test]
1241 #[cfg(ossl110)]
1242 fn test_aes192_wrap() {
1243 let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b";
1244 let ct = "83b89142dfeeb4871e078bfb81134d33e23fedc19b03a1cf689973d3831b6813";
1245 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1246 let iv = "0001020304050607";
1247
1248 cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, Some(iv));
1249 }
1250
1251 #[test]
1252 #[cfg(ossl110)]
1253 fn test_aes192_wrap_default_iv() {
1254 let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b";
1255 let ct = "c02c2cf11505d3e4851030d5534cbf5a1d7eca7ba8839adbf239756daf1b43e6";
1256 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1257
1258 cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, None);
1259 }
1260
1261 #[test]
1262 #[cfg(ossl110)]
1263 fn test_aes192_wrap_pad() {
1264 let pt = "00112233445566778899aabbccddee";
1265 let ct = "b4f6bb167ef7caf061a74da82b36ad038ca057ab51e98d3a";
1266 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1267 let iv = "00010203";
1268
1269 cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, Some(iv));
1270 }
1271
1272 #[test]
1273 #[cfg(ossl110)]
1274 fn test_aes192_wrap_pad_default_iv() {
1275 let pt = "00112233445566778899aabbccddee";
1276 let ct = "b2c37a28cc602753a7c944a4c2555a2df9c98b2eded5312e";
1277 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1278
1279 cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, None);
1280 }
1281
1282 #[test]
1283 #[cfg(ossl110)]
1284 fn test_aes256_wrap() {
1285 let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51";
1286 let ct = "cc05da2a7f56f7dd0c144231f90bce58648fa20a8278f5a6b7d13bba6aa57a33229d4333866b7fd6";
1287 let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1288 let iv = "0001020304050607";
1289
1290 cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, Some(iv));
1291 }
1292
1293 #[test]
1294 #[cfg(ossl110)]
1295 fn test_aes256_wrap_default_iv() {
1296 let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51";
1297 let ct = "0b24f068b50e52bc6987868411c36e1b03900866ed12af81eb87cef70a8d1911731c1d7abf789d88";
1298 let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1299
1300 cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, None);
1301 }
1302
1303 #[test]
1304 #[cfg(ossl110)]
1305 fn test_aes256_wrap_pad() {
1306 let pt = "00112233445566778899aabbccddee";
1307 let ct = "91594e044ccc06130d60e6c84a996aa4f96a9faff8c5f6e7";
1308 let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1309 let iv = "00010203";
1310
1311 cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, Some(iv));
1312 }
1313
1314 #[test]
1315 #[cfg(ossl110)]
1316 fn test_aes256_wrap_pad_default_iv() {
1317 let pt = "00112233445566778899aabbccddee";
1318 let ct = "dc3c166a854afd68aea624a4272693554bf2e4fcbae602cd";
1319 let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1320
1321 cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, None);
1322 }
1323
1324 #[test]
1325 #[cfg(ossl110)]
1326 fn test_aes_wrap_pad_cipher_update_vec_buffer_size() {
1327 let cipher = Cipher::aes_256_wrap_pad();
1328 let key = [0u8; 32];
1329 let iv = [0u8; 4];
1330 let pt = [0u8; 9];
1331
1332 let mut ctx = CipherCtx::new().unwrap();
1333 ctx.set_flags(CipherCtxFlags::FLAG_WRAP_ALLOW);
1334 ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
1335 .unwrap();
1336
1337 let mut out = vec![];
1338 let len = ctx.cipher_update_vec(&pt, &mut out).unwrap();
1339 assert!(out.capacity() >= len);
1341 assert_eq!(len, 24);
1342 }
1343
1344 #[test]
1345 #[cfg(ossl110)]
1346 #[should_panic(expected = "Output buffer size must be at least 24 bytes.")]
1347 fn test_aes_wrap_pad_cipher_update_inplace_buffer_size() {
1348 let cipher = Cipher::aes_256_wrap_pad();
1349 let key = [0u8; 32];
1350 let iv = [0u8; 4];
1351
1352 let mut ctx = CipherCtx::new().unwrap();
1353 ctx.set_flags(CipherCtxFlags::FLAG_WRAP_ALLOW);
1354 ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
1355 .unwrap();
1356
1357 let mut buf = [0u8; 17];
1361 let _ = ctx.cipher_update_inplace(&mut buf, 9);
1362 }
1363}