1#![warn(missing_docs)]
52
53use crate::cipher::CipherRef;
54use crate::error::ErrorStack;
55#[cfg(not(boringssl))]
56use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef};
57use crate::{cvt, cvt_p};
58#[cfg(ossl102)]
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(ossl102)]
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_copy)]
109 pub fn copy(&mut self, src: &CipherCtxRef) -> Result<(), ErrorStack> {
110 unsafe {
111 cvt(ffi::EVP_CIPHER_CTX_copy(self.as_ptr(), src.as_ptr()))?;
112 Ok(())
113 }
114 }
115
116 #[corresponds(EVP_EncryptInit_ex)]
127 pub fn encrypt_init(
128 &mut self,
129 type_: Option<&CipherRef>,
130 key: Option<&[u8]>,
131 iv: Option<&[u8]>,
132 ) -> Result<(), ErrorStack> {
133 self.cipher_init(type_, key, iv, ffi::EVP_EncryptInit_ex)
134 }
135
136 #[corresponds(EVP_DecryptInit_ex)]
147 pub fn decrypt_init(
148 &mut self,
149 type_: Option<&CipherRef>,
150 key: Option<&[u8]>,
151 iv: Option<&[u8]>,
152 ) -> Result<(), ErrorStack> {
153 self.cipher_init(type_, key, iv, ffi::EVP_DecryptInit_ex)
154 }
155
156 fn cipher_init(
157 &mut self,
158 type_: Option<&CipherRef>,
159 key: Option<&[u8]>,
160 iv: Option<&[u8]>,
161 f: unsafe extern "C" fn(
162 *mut ffi::EVP_CIPHER_CTX,
163 *const ffi::EVP_CIPHER,
164 *mut ffi::ENGINE,
165 *const c_uchar,
166 *const c_uchar,
167 ) -> c_int,
168 ) -> Result<(), ErrorStack> {
169 if let Some(key) = key {
170 let key_len = type_.map_or_else(|| self.key_length(), |c| c.key_length());
171 assert!(key_len <= key.len());
172 }
173
174 if let Some(iv) = iv {
175 let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
176 assert!(iv_len <= iv.len());
177 }
178
179 unsafe {
180 cvt(f(
181 self.as_ptr(),
182 type_.map_or(ptr::null(), |p| p.as_ptr()),
183 ptr::null_mut(),
184 key.map_or(ptr::null(), |k| k.as_ptr()),
185 iv.map_or(ptr::null(), |iv| iv.as_ptr()),
186 ))?;
187 }
188
189 Ok(())
190 }
191
192 #[corresponds(EVP_SealInit)]
205 #[cfg(not(boringssl))]
206 pub fn seal_init<T>(
207 &mut self,
208 type_: Option<&CipherRef>,
209 pub_keys: &[PKey<T>],
210 encrypted_keys: &mut [Vec<u8>],
211 iv: Option<&mut [u8]>,
212 ) -> Result<(), ErrorStack>
213 where
214 T: HasPublic,
215 {
216 assert_eq!(pub_keys.len(), encrypted_keys.len());
217 if !pub_keys.is_empty() {
218 let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
219 assert!(iv.as_ref().map_or(0, |b| b.len()) >= iv_len);
220 }
221
222 for (pub_key, buf) in pub_keys.iter().zip(&mut *encrypted_keys) {
223 buf.resize(pub_key.size(), 0);
224 }
225
226 let mut keys = encrypted_keys
227 .iter_mut()
228 .map(|b| b.as_mut_ptr())
229 .collect::<Vec<_>>();
230 let mut key_lengths = vec![0; pub_keys.len()];
231 let pub_keys_len = i32::try_from(pub_keys.len()).unwrap();
232
233 unsafe {
234 cvt(ffi::EVP_SealInit(
235 self.as_ptr(),
236 type_.map_or(ptr::null(), |p| p.as_ptr()),
237 keys.as_mut_ptr(),
238 key_lengths.as_mut_ptr(),
239 iv.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
240 pub_keys.as_ptr() as *mut _,
241 pub_keys_len,
242 ))?;
243 }
244
245 for (buf, len) in encrypted_keys.iter_mut().zip(key_lengths) {
246 buf.truncate(len as usize);
247 }
248
249 Ok(())
250 }
251
252 #[corresponds(EVP_OpenInit)]
262 #[cfg(not(boringssl))]
263 pub fn open_init<T>(
264 &mut self,
265 type_: Option<&CipherRef>,
266 encrypted_key: &[u8],
267 iv: Option<&[u8]>,
268 priv_key: Option<&PKeyRef<T>>,
269 ) -> Result<(), ErrorStack>
270 where
271 T: HasPrivate,
272 {
273 if priv_key.is_some() {
274 let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
275 assert!(iv.map_or(0, |b| b.len()) >= iv_len);
276 }
277
278 let len = c_int::try_from(encrypted_key.len()).unwrap();
279 unsafe {
280 cvt(ffi::EVP_OpenInit(
281 self.as_ptr(),
282 type_.map_or(ptr::null(), |p| p.as_ptr()),
283 encrypted_key.as_ptr(),
284 len,
285 iv.map_or(ptr::null(), |b| b.as_ptr()),
286 priv_key.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
287 ))?;
288 }
289
290 Ok(())
291 }
292
293 fn assert_cipher(&self) {
294 unsafe {
295 assert!(!EVP_CIPHER_CTX_get0_cipher(self.as_ptr()).is_null());
296 }
297 }
298
299 #[corresponds(EVP_CIPHER_CTX_block_size)]
307 pub fn block_size(&self) -> usize {
308 self.assert_cipher();
309
310 unsafe { ffi::EVP_CIPHER_CTX_block_size(self.as_ptr()) as usize }
311 }
312
313 #[corresponds(EVP_CIPHER_CTX_key_length)]
319 pub fn key_length(&self) -> usize {
320 self.assert_cipher();
321
322 unsafe { ffi::EVP_CIPHER_CTX_key_length(self.as_ptr()) as usize }
323 }
324
325 #[corresponds(EVP_CIPHER_CTX_rand_key)]
332 #[cfg(not(boringssl))]
333 pub fn rand_key(&self, buf: &mut [u8]) -> Result<(), ErrorStack> {
334 assert!(buf.len() >= self.key_length());
335
336 unsafe {
337 cvt(ffi::EVP_CIPHER_CTX_rand_key(
338 self.as_ptr(),
339 buf.as_mut_ptr(),
340 ))?;
341 }
342
343 Ok(())
344 }
345
346 #[corresponds(EVP_CIPHER_CTX_set_key_length)]
354 pub fn set_key_length(&mut self, len: usize) -> Result<(), ErrorStack> {
355 self.assert_cipher();
356
357 unsafe {
358 cvt(ffi::EVP_CIPHER_CTX_set_key_length(
359 self.as_ptr(),
360 len.try_into().unwrap(),
361 ))?;
362 }
363
364 Ok(())
365 }
366
367 #[corresponds(EVP_CIPHER_CTX_iv_length)]
375 pub fn iv_length(&self) -> usize {
376 self.assert_cipher();
377
378 unsafe { ffi::EVP_CIPHER_CTX_iv_length(self.as_ptr()) as usize }
379 }
380
381 #[corresponds(EVP_CIPHER_CTX_num)]
390 #[cfg(ossl110)]
391 pub fn num(&self) -> usize {
392 self.assert_cipher();
393
394 unsafe { ffi::EVP_CIPHER_CTX_num(self.as_ptr()) as usize }
395 }
396
397 #[corresponds(EVP_CIPHER_CTX_ctrl)]
405 pub fn set_iv_length(&mut self, len: usize) -> Result<(), ErrorStack> {
406 self.assert_cipher();
407
408 let len = c_int::try_from(len).unwrap();
409
410 unsafe {
411 cvt(ffi::EVP_CIPHER_CTX_ctrl(
412 self.as_ptr(),
413 ffi::EVP_CTRL_GCM_SET_IVLEN,
414 len,
415 ptr::null_mut(),
416 ))?;
417 }
418
419 Ok(())
420 }
421
422 #[corresponds(EVP_CIPHER_CTX_get_tag_length)]
432 #[cfg(ossl300)]
433 pub fn tag_length(&self) -> usize {
434 self.assert_cipher();
435
436 unsafe { ffi::EVP_CIPHER_CTX_get_tag_length(self.as_ptr()) as usize }
437 }
438
439 #[corresponds(EVP_CIPHER_CTX_ctrl)]
446 pub fn tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> {
447 let len = c_int::try_from(tag.len()).unwrap();
448
449 unsafe {
450 cvt(ffi::EVP_CIPHER_CTX_ctrl(
451 self.as_ptr(),
452 ffi::EVP_CTRL_GCM_GET_TAG,
453 len,
454 tag.as_mut_ptr() as *mut _,
455 ))?;
456 }
457
458 Ok(())
459 }
460
461 #[corresponds(EVP_CIPHER_CTX_ctrl)]
465 pub fn set_tag_length(&mut self, len: usize) -> Result<(), ErrorStack> {
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_TAG,
472 len,
473 ptr::null_mut(),
474 ))?;
475 }
476
477 Ok(())
478 }
479
480 #[corresponds(EVP_CIPHER_CTX_ctrl)]
482 pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> {
483 let len = c_int::try_from(tag.len()).unwrap();
484
485 unsafe {
486 cvt(ffi::EVP_CIPHER_CTX_ctrl(
487 self.as_ptr(),
488 ffi::EVP_CTRL_GCM_SET_TAG,
489 len,
490 tag.as_ptr() as *mut _,
491 ))?;
492 }
493
494 Ok(())
495 }
496
497 #[corresponds(EVP_CIPHER_CTX_set_padding)]
501 pub fn set_padding(&mut self, padding: bool) {
502 unsafe {
503 ffi::EVP_CIPHER_CTX_set_padding(self.as_ptr(), padding as c_int);
504 }
505 }
506
507 #[corresponds(EVP_CipherUpdate)]
511 pub fn set_data_len(&mut self, len: usize) -> Result<(), ErrorStack> {
512 let len = c_int::try_from(len).unwrap();
513
514 unsafe {
515 cvt(ffi::EVP_CipherUpdate(
516 self.as_ptr(),
517 ptr::null_mut(),
518 &mut 0,
519 ptr::null(),
520 len,
521 ))?;
522 }
523
524 Ok(())
525 }
526
527 #[corresponds(EVP_CIPHER_CTX_set_flags)]
531 #[cfg(ossl102)]
532 pub fn set_flags(&mut self, flags: CipherCtxFlags) {
533 unsafe {
534 ffi::EVP_CIPHER_CTX_set_flags(self.as_ptr(), flags.bits());
535 }
536 }
537
538 #[corresponds(EVP_CipherUpdate)]
549 pub fn cipher_update(
550 &mut self,
551 input: &[u8],
552 output: Option<&mut [u8]>,
553 ) -> Result<usize, ErrorStack> {
554 if let Some(output) = &output {
555 let mut block_size = self.block_size();
556 if block_size == 1 {
557 block_size = 0;
558 }
559 let min_output_size = input.len() + block_size;
560 assert!(
561 output.len() >= min_output_size,
562 "Output buffer size should be at least {} bytes.",
563 min_output_size
564 );
565 }
566
567 unsafe { self.cipher_update_unchecked(input, output) }
568 }
569
570 #[corresponds(EVP_CipherUpdate)]
588 pub unsafe fn cipher_update_unchecked(
589 &mut self,
590 input: &[u8],
591 output: Option<&mut [u8]>,
592 ) -> Result<usize, ErrorStack> {
593 let inlen = c_int::try_from(input.len()).unwrap();
594
595 let mut outlen = 0;
596
597 cvt(ffi::EVP_CipherUpdate(
598 self.as_ptr(),
599 output.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
600 &mut outlen,
601 input.as_ptr(),
602 inlen,
603 ))?;
604
605 Ok(outlen as usize)
606 }
607
608 pub fn cipher_update_vec(
610 &mut self,
611 input: &[u8],
612 output: &mut Vec<u8>,
613 ) -> Result<usize, ErrorStack> {
614 let base = output.len();
615 output.resize(base + input.len() + self.block_size(), 0);
616 let len = self.cipher_update(input, Some(&mut output[base..]))?;
617 output.truncate(base + len);
618
619 Ok(len)
620 }
621
622 #[corresponds(EVP_CipherUpdate)]
636 pub fn cipher_update_inplace(
637 &mut self,
638 data: &mut [u8],
639 inlen: usize,
640 ) -> Result<usize, ErrorStack> {
641 assert!(inlen <= data.len(), "Input size may not exceed buffer size");
642 let block_size = self.block_size();
643 if block_size != 1 {
644 assert!(
645 data.len() >= inlen + block_size,
646 "Output buffer size must be at least {} bytes.",
647 inlen + block_size
648 );
649 }
650
651 let inlen = c_int::try_from(inlen).unwrap();
652 let mut outlen = 0;
653 unsafe {
654 cvt(ffi::EVP_CipherUpdate(
655 self.as_ptr(),
656 data.as_mut_ptr(),
657 &mut outlen,
658 data.as_ptr(),
659 inlen,
660 ))
661 }?;
662
663 Ok(outlen as usize)
664 }
665
666 #[corresponds(EVP_CipherFinal)]
676 pub fn cipher_final(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
677 let block_size = self.block_size();
678 if block_size > 1 {
679 assert!(output.len() >= block_size);
680 }
681
682 unsafe { self.cipher_final_unchecked(output) }
683 }
684
685 #[corresponds(EVP_CipherFinal)]
701 pub unsafe fn cipher_final_unchecked(
702 &mut self,
703 output: &mut [u8],
704 ) -> Result<usize, ErrorStack> {
705 let mut outl = 0;
706
707 cvt(ffi::EVP_CipherFinal(
708 self.as_ptr(),
709 output.as_mut_ptr(),
710 &mut outl,
711 ))?;
712
713 Ok(outl as usize)
714 }
715
716 pub fn cipher_final_vec(&mut self, output: &mut Vec<u8>) -> Result<usize, ErrorStack> {
718 let base = output.len();
719 output.resize(base + self.block_size(), 0);
720 let len = self.cipher_final(&mut output[base..])?;
721 output.truncate(base + len);
722
723 Ok(len)
724 }
725}
726
727#[cfg(test)]
728mod test {
729 use super::*;
730 use crate::{cipher::Cipher, rand::rand_bytes};
731 #[cfg(not(boringssl))]
732 use std::slice;
733
734 #[test]
735 #[cfg(not(boringssl))]
736 fn seal_open() {
737 let private_pem = include_bytes!("../test/rsa.pem");
738 let public_pem = include_bytes!("../test/rsa.pem.pub");
739 let private_key = PKey::private_key_from_pem(private_pem).unwrap();
740 let public_key = PKey::public_key_from_pem(public_pem).unwrap();
741 let cipher = Cipher::aes_256_cbc();
742 let secret = b"My secret message";
743
744 let mut ctx = CipherCtx::new().unwrap();
745 let mut encrypted_key = vec![];
746 let mut iv = vec![0; cipher.iv_length()];
747 let mut encrypted = vec![];
748 ctx.seal_init(
749 Some(cipher),
750 &[public_key],
751 slice::from_mut(&mut encrypted_key),
752 Some(&mut iv),
753 )
754 .unwrap();
755 ctx.cipher_update_vec(secret, &mut encrypted).unwrap();
756 ctx.cipher_final_vec(&mut encrypted).unwrap();
757
758 let mut decrypted = vec![];
759 ctx.open_init(Some(cipher), &encrypted_key, Some(&iv), Some(&private_key))
760 .unwrap();
761 ctx.cipher_update_vec(&encrypted, &mut decrypted).unwrap();
762 ctx.cipher_final_vec(&mut decrypted).unwrap();
763
764 assert_eq!(secret, &decrypted[..]);
765 }
766
767 fn aes_128_cbc(cipher: &CipherRef) {
768 let key = hex::decode("2b7e151628aed2a6abf7158809cf4f3c").unwrap();
770 let iv = hex::decode("000102030405060708090a0b0c0d0e0f").unwrap();
771 let pt = hex::decode("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51")
772 .unwrap();
773 let ct = hex::decode("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2")
774 .unwrap();
775
776 let mut ctx = CipherCtx::new().unwrap();
777
778 ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
779 .unwrap();
780 ctx.set_padding(false);
781
782 let mut buf = vec![];
783 ctx.cipher_update_vec(&pt, &mut buf).unwrap();
784 ctx.cipher_final_vec(&mut buf).unwrap();
785
786 assert_eq!(buf, ct);
787
788 ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv))
789 .unwrap();
790 ctx.set_padding(false);
791
792 let mut buf = vec![];
793 ctx.cipher_update_vec(&ct, &mut buf).unwrap();
794 ctx.cipher_final_vec(&mut buf).unwrap();
795
796 assert_eq!(buf, pt);
797 }
798
799 #[test]
800 #[cfg(ossl300)]
801 fn fetched_aes_128_cbc() {
802 let cipher = Cipher::fetch(None, "AES-128-CBC", None).unwrap();
803 aes_128_cbc(&cipher);
804 }
805
806 #[test]
807 fn default_aes_128_cbc() {
808 let cipher = Cipher::aes_128_cbc();
809 aes_128_cbc(cipher);
810 }
811
812 #[test]
813 fn test_stream_ciphers() {
814 test_stream_cipher(Cipher::aes_192_ctr());
815 test_stream_cipher(Cipher::aes_256_ctr());
816 }
817
818 fn test_stream_cipher(cipher: &'static CipherRef) {
819 let mut key = vec![0; cipher.key_length()];
820 rand_bytes(&mut key).unwrap();
821 let mut iv = vec![0; cipher.iv_length()];
822 rand_bytes(&mut iv).unwrap();
823
824 let mut ctx = CipherCtx::new().unwrap();
825
826 ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
827 .unwrap();
828 ctx.set_padding(false);
829
830 assert_eq!(
831 1,
832 cipher.block_size(),
833 "Need a stream cipher, not a block cipher"
834 );
835
836 let mut output = vec![0; 32];
840 let outlen = ctx
841 .cipher_update(&[1; 15], Some(&mut output[0..15]))
842 .unwrap();
843 assert_eq!(15, outlen);
844
845 let outlen = ctx
849 .cipher_update(&[1; 17], Some(&mut output[15..]))
850 .unwrap();
851 assert_eq!(17, outlen);
852
853 ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
854
855 ctx.encrypt_init(None, None, Some(&iv)).unwrap();
858 ctx.set_padding(false);
859 let mut data_inplace: [u8; 32] = [1; 32];
860 let outlen = ctx
861 .cipher_update_inplace(&mut data_inplace[0..15], 15)
862 .unwrap();
863 assert_eq!(15, outlen);
864
865 let outlen = ctx
866 .cipher_update_inplace(&mut data_inplace[15..32], 17)
867 .unwrap();
868 assert_eq!(17, outlen);
869
870 ctx.cipher_final(&mut [0u8; 0]).unwrap();
871
872 assert_eq!(data_inplace.as_slice(), output.as_slice());
874
875 ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv))
877 .unwrap();
878 ctx.set_padding(false);
879
880 let mut output_decrypted = vec![0; 32];
884 let outlen = ctx
885 .cipher_update(&output[0..15], Some(&mut output_decrypted[0..15]))
886 .unwrap();
887 assert_eq!(15, outlen);
888
889 let outlen = ctx
890 .cipher_update(&output[15..], Some(&mut output_decrypted[15..]))
891 .unwrap();
892 assert_eq!(17, outlen);
893
894 ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
895 assert_eq!(output_decrypted, vec![1; 32]);
897
898 ctx.decrypt_init(None, None, Some(&iv)).unwrap();
900 ctx.set_padding(false);
901
902 let outlen = ctx.cipher_update_inplace(&mut output[0..15], 15).unwrap();
903 assert_eq!(15, outlen);
904
905 let outlen = ctx.cipher_update_inplace(&mut output[15..], 17).unwrap();
906 assert_eq!(17, outlen);
907
908 ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
909 assert_eq!(output_decrypted, output);
910 }
911
912 #[test]
913 #[should_panic(expected = "Output buffer size should be at least 33 bytes.")]
914 fn full_block_updates_aes_128() {
915 output_buffer_too_small(Cipher::aes_128_cbc());
916 }
917
918 #[test]
919 #[should_panic(expected = "Output buffer size should be at least 33 bytes.")]
920 fn full_block_updates_aes_256() {
921 output_buffer_too_small(Cipher::aes_256_cbc());
922 }
923
924 #[test]
925 #[should_panic(expected = "Output buffer size should be at least 17 bytes.")]
926 fn full_block_updates_3des() {
927 output_buffer_too_small(Cipher::des_ede3_cbc());
928 }
929
930 fn output_buffer_too_small(cipher: &'static CipherRef) {
931 let mut key = vec![0; cipher.key_length()];
932 rand_bytes(&mut key).unwrap();
933 let mut iv = vec![0; cipher.iv_length()];
934 rand_bytes(&mut iv).unwrap();
935
936 let mut ctx = CipherCtx::new().unwrap();
937
938 ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
939 .unwrap();
940 ctx.set_padding(false);
941
942 let block_size = cipher.block_size();
943 assert!(block_size > 1, "Need a block cipher, not a stream cipher");
944
945 ctx.cipher_update(&vec![0; block_size + 1], Some(&mut vec![0; block_size - 1]))
946 .unwrap();
947 }
948
949 #[cfg(ossl102)]
950 fn cipher_wrap_test(cipher: &CipherRef, pt: &str, ct: &str, key: &str, iv: Option<&str>) {
951 let pt = hex::decode(pt).unwrap();
952 let key = hex::decode(key).unwrap();
953 let expected = hex::decode(ct).unwrap();
954 let iv = iv.map(|v| hex::decode(v).unwrap());
955 let padding = 8 - pt.len() % 8;
956 let mut computed = vec![0; pt.len() + padding + cipher.block_size() * 2];
957 let mut ctx = CipherCtx::new().unwrap();
958
959 ctx.set_flags(CipherCtxFlags::FLAG_WRAP_ALLOW);
960 ctx.encrypt_init(Some(cipher), Some(&key), iv.as_deref())
961 .unwrap();
962
963 let count = ctx.cipher_update(&pt, Some(&mut computed)).unwrap();
964 let rest = ctx.cipher_final(&mut computed[count..]).unwrap();
965 computed.truncate(count + rest);
966
967 if computed != expected {
968 println!("Computed: {}", hex::encode(&computed));
969 println!("Expected: {}", hex::encode(&expected));
970 if computed.len() != expected.len() {
971 println!(
972 "Lengths differ: {} in computed vs {} expected",
973 computed.len(),
974 expected.len()
975 );
976 }
977 panic!("test failure");
978 }
979 }
980
981 #[test]
982 #[cfg(ossl102)]
983 fn test_aes128_wrap() {
984 let pt = "00112233445566778899aabbccddeeff";
985 let ct = "7940ff694448b5bb5139c959a4896832e55d69aa04daa27e";
986 let key = "2b7e151628aed2a6abf7158809cf4f3c";
987 let iv = "0001020304050607";
988
989 cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, Some(iv));
990 }
991
992 #[test]
993 #[cfg(ossl102)]
994 fn test_aes128_wrap_default_iv() {
995 let pt = "00112233445566778899aabbccddeeff";
996 let ct = "38f1215f0212526f8a70b51955b9fbdc9fe3041d9832306e";
997 let key = "2b7e151628aed2a6abf7158809cf4f3c";
998
999 cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, None);
1000 }
1001
1002 #[test]
1003 #[cfg(ossl110)]
1004 fn test_aes128_wrap_pad() {
1005 let pt = "00112233445566778899aabbccddee";
1006 let ct = "f13998f5ab32ef82a1bdbcbe585e1d837385b529572a1e1b";
1007 let key = "2b7e151628aed2a6abf7158809cf4f3c";
1008 let iv = "00010203";
1009
1010 cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, Some(iv));
1011 }
1012
1013 #[test]
1014 #[cfg(ossl110)]
1015 fn test_aes128_wrap_pad_default_iv() {
1016 let pt = "00112233445566778899aabbccddee";
1017 let ct = "3a501085fb8cf66f4186b7df851914d471ed823411598add";
1018 let key = "2b7e151628aed2a6abf7158809cf4f3c";
1019
1020 cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, None);
1021 }
1022
1023 #[test]
1024 #[cfg(ossl102)]
1025 fn test_aes192_wrap() {
1026 let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b";
1027 let ct = "83b89142dfeeb4871e078bfb81134d33e23fedc19b03a1cf689973d3831b6813";
1028 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1029 let iv = "0001020304050607";
1030
1031 cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, Some(iv));
1032 }
1033
1034 #[test]
1035 #[cfg(ossl102)]
1036 fn test_aes192_wrap_default_iv() {
1037 let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b";
1038 let ct = "c02c2cf11505d3e4851030d5534cbf5a1d7eca7ba8839adbf239756daf1b43e6";
1039 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1040
1041 cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, None);
1042 }
1043
1044 #[test]
1045 #[cfg(ossl110)]
1046 fn test_aes192_wrap_pad() {
1047 let pt = "00112233445566778899aabbccddee";
1048 let ct = "b4f6bb167ef7caf061a74da82b36ad038ca057ab51e98d3a";
1049 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1050 let iv = "00010203";
1051
1052 cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, Some(iv));
1053 }
1054
1055 #[test]
1056 #[cfg(ossl110)]
1057 fn test_aes192_wrap_pad_default_iv() {
1058 let pt = "00112233445566778899aabbccddee";
1059 let ct = "b2c37a28cc602753a7c944a4c2555a2df9c98b2eded5312e";
1060 let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1061
1062 cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, None);
1063 }
1064
1065 #[test]
1066 #[cfg(ossl102)]
1067 fn test_aes256_wrap() {
1068 let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51";
1069 let ct = "cc05da2a7f56f7dd0c144231f90bce58648fa20a8278f5a6b7d13bba6aa57a33229d4333866b7fd6";
1070 let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1071 let iv = "0001020304050607";
1072
1073 cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, Some(iv));
1074 }
1075
1076 #[test]
1077 #[cfg(ossl102)]
1078 fn test_aes256_wrap_default_iv() {
1079 let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51";
1080 let ct = "0b24f068b50e52bc6987868411c36e1b03900866ed12af81eb87cef70a8d1911731c1d7abf789d88";
1081 let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1082
1083 cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, None);
1084 }
1085
1086 #[test]
1087 #[cfg(ossl110)]
1088 fn test_aes256_wrap_pad() {
1089 let pt = "00112233445566778899aabbccddee";
1090 let ct = "91594e044ccc06130d60e6c84a996aa4f96a9faff8c5f6e7";
1091 let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1092 let iv = "00010203";
1093
1094 cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, Some(iv));
1095 }
1096
1097 #[test]
1098 #[cfg(ossl110)]
1099 fn test_aes256_wrap_pad_default_iv() {
1100 let pt = "00112233445566778899aabbccddee";
1101 let ct = "dc3c166a854afd68aea624a4272693554bf2e4fcbae602cd";
1102 let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1103
1104 cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, None);
1105 }
1106}