1#![allow(clippy::module_name_repetitions)]
230
231pub(crate) mod aes;
232pub(crate) mod block;
233pub(crate) mod chacha;
234#[cfg(feature = "legacy-des")]
235pub(crate) mod des;
236pub(crate) mod key;
237mod padded;
238mod streaming;
239
240pub use padded::{PaddedBlockDecryptingKey, PaddedBlockEncryptingKey};
241pub use streaming::{BufferUpdate, StreamingDecryptingKey, StreamingEncryptingKey};
242
243use crate::aws_lc::{
244 EVP_aes_128_cbc, EVP_aes_128_cfb128, EVP_aes_128_ctr, EVP_aes_128_ecb, EVP_aes_192_cbc,
245 EVP_aes_192_cfb128, EVP_aes_192_ctr, EVP_aes_192_ecb, EVP_aes_256_cbc, EVP_aes_256_cfb128,
246 EVP_aes_256_ctr, EVP_aes_256_ecb, EVP_CIPHER,
247};
248#[cfg(feature = "legacy-des")]
249use crate::aws_lc::{
250 EVP_des_cbc, EVP_des_ecb, EVP_des_ede, EVP_des_ede3_cbc, EVP_des_ede3_ecb, EVP_des_ede_cbc,
251};
252use crate::buffer::Buffer;
253use crate::error::{KeyRejected, Unspecified};
254use crate::hkdf;
255use crate::hkdf::KeyType;
256#[cfg(feature = "legacy-des")]
257use crate::iv::IV_LEN_64_BIT;
258use crate::iv::{FixedLength, IV_LEN_128_BIT};
259use crate::ptr::ConstPointer;
260use core::fmt::Debug;
261use key::SymmetricCipherKey;
262
263pub use crate::cipher::aes::AES_128_KEY_LEN;
265
266pub use crate::cipher::aes::AES_192_KEY_LEN;
268
269pub use crate::cipher::aes::AES_256_KEY_LEN;
271
272#[cfg(feature = "legacy-des")]
277#[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "legacy-des")))]
278#[deprecated(
279 note = "Single DES is a legacy algorithm retained for interoperability only. Prefer an AES-based algorithm."
280)]
281pub use crate::cipher::des::DES_KEY_LEN;
282
283#[cfg(feature = "legacy-des")]
288#[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "legacy-des")))]
289#[deprecated(
290 note = "2-key Triple DES is a legacy algorithm retained for interoperability only; NIST SP 800-131A Rev. 2 disallows its use for encryption. Prefer an AES-based algorithm."
291)]
292pub use crate::cipher::des::DES_EDE_KEY_LEN;
293
294#[cfg(feature = "legacy-des")]
299#[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "legacy-des")))]
300#[deprecated(
301 note = "3DES is a legacy algorithm retained for interoperability only; NIST SP 800-131A Rev. 2 disallows its use for encryption. Prefer an AES-based algorithm."
302)]
303pub use crate::cipher::des::DES_EDE3_KEY_LEN;
304
305const MAX_CIPHER_KEY_LEN: usize = AES_256_KEY_LEN;
306
307pub use crate::cipher::aes::AES_CBC_IV_LEN;
309
310pub use crate::cipher::aes::AES_CTR_IV_LEN;
312
313pub use crate::cipher::aes::AES_CFB_IV_LEN;
315
316#[cfg(feature = "legacy-des")]
321#[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "legacy-des")))]
322#[deprecated(
323 note = "DES/3DES are legacy algorithms retained for interoperability only; NIST SP 800-131A Rev. 2 disallows their use for encryption. Prefer an AES-based algorithm."
324)]
325pub use crate::cipher::des::DES_CBC_IV_LEN;
326
327use crate::cipher::aes::AES_BLOCK_LEN;
328#[cfg(feature = "legacy-des")]
329use crate::cipher::des::DES_BLOCK_LEN;
330
331const MAX_CIPHER_BLOCK_LEN: usize = AES_BLOCK_LEN;
332
333#[non_exhaustive]
335#[derive(Debug, PartialEq, Eq, Clone, Copy)]
336pub enum OperatingMode {
337 CBC,
339
340 CTR,
342
343 CFB128,
345
346 ECB,
348}
349
350impl OperatingMode {
351 fn evp_cipher(&self, algorithm: &Algorithm) -> ConstPointer<'_, EVP_CIPHER> {
352 let alg = match (self, algorithm.id) {
353 (OperatingMode::CBC, AlgorithmId::Aes128) => unsafe { EVP_aes_128_cbc() },
354 (OperatingMode::CTR, AlgorithmId::Aes128) => unsafe { EVP_aes_128_ctr() },
355 (OperatingMode::CFB128, AlgorithmId::Aes128) => unsafe { EVP_aes_128_cfb128() },
356 (OperatingMode::ECB, AlgorithmId::Aes128) => unsafe { EVP_aes_128_ecb() },
357 (OperatingMode::CBC, AlgorithmId::Aes192) => unsafe { EVP_aes_192_cbc() },
358 (OperatingMode::CTR, AlgorithmId::Aes192) => unsafe { EVP_aes_192_ctr() },
359 (OperatingMode::CFB128, AlgorithmId::Aes192) => unsafe { EVP_aes_192_cfb128() },
360 (OperatingMode::ECB, AlgorithmId::Aes192) => unsafe { EVP_aes_192_ecb() },
361 (OperatingMode::CBC, AlgorithmId::Aes256) => unsafe { EVP_aes_256_cbc() },
362 (OperatingMode::CTR, AlgorithmId::Aes256) => unsafe { EVP_aes_256_ctr() },
363 (OperatingMode::CFB128, AlgorithmId::Aes256) => unsafe { EVP_aes_256_cfb128() },
364 (OperatingMode::ECB, AlgorithmId::Aes256) => unsafe { EVP_aes_256_ecb() },
365 #[cfg(feature = "legacy-des")]
366 #[allow(deprecated)]
367 (OperatingMode::CBC, AlgorithmId::DesForLegacyUseOnly) => unsafe { EVP_des_cbc() },
368 #[cfg(feature = "legacy-des")]
369 #[allow(deprecated)]
370 (OperatingMode::ECB, AlgorithmId::DesForLegacyUseOnly) => unsafe { EVP_des_ecb() },
371 #[cfg(feature = "legacy-des")]
372 #[allow(deprecated)]
373 (OperatingMode::CBC, AlgorithmId::DesEdeForLegacyUseOnly) => unsafe {
374 EVP_des_ede_cbc()
375 },
376 #[cfg(feature = "legacy-des")]
377 #[allow(deprecated)]
378 (OperatingMode::ECB, AlgorithmId::DesEdeForLegacyUseOnly) => unsafe { EVP_des_ede() },
379 #[cfg(feature = "legacy-des")]
380 #[allow(deprecated)]
381 (OperatingMode::CBC, AlgorithmId::DesEde3ForLegacyUseOnly) => unsafe {
382 EVP_des_ede3_cbc()
383 },
384 #[cfg(feature = "legacy-des")]
385 #[allow(deprecated)]
386 (OperatingMode::ECB, AlgorithmId::DesEde3ForLegacyUseOnly) => unsafe {
387 EVP_des_ede3_ecb()
388 },
389 #[cfg(feature = "legacy-des")]
390 #[allow(deprecated)]
391 (OperatingMode::CTR, AlgorithmId::DesForLegacyUseOnly)
392 | (OperatingMode::CTR, AlgorithmId::DesEdeForLegacyUseOnly)
393 | (OperatingMode::CTR, AlgorithmId::DesEde3ForLegacyUseOnly)
394 | (OperatingMode::CFB128, AlgorithmId::DesForLegacyUseOnly)
395 | (OperatingMode::CFB128, AlgorithmId::DesEdeForLegacyUseOnly)
396 | (OperatingMode::CFB128, AlgorithmId::DesEde3ForLegacyUseOnly) => {
397 unreachable!("DES does not support CTR or CFB128 modes")
400 }
401 };
402 unsafe { ConstPointer::new_static(alg).unwrap() }
403 }
404}
405
406macro_rules! define_cipher_context {
407 ($name:ident, $other:ident) => {
408 #[non_exhaustive]
410 pub enum $name {
411 Iv128(FixedLength<IV_LEN_128_BIT>),
413
414 #[cfg(feature = "legacy-des")]
420 #[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "legacy-des")))]
421 Iv64(FixedLength<IV_LEN_64_BIT>),
422
423 None,
425 }
426
427 impl<'a> TryFrom<&'a $name> for &'a [u8] {
428 type Error = Unspecified;
429
430 fn try_from(value: &'a $name) -> Result<Self, Unspecified> {
431 match value {
432 $name::Iv128(iv) => Ok(iv.as_ref()),
433 #[cfg(feature = "legacy-des")]
434 $name::Iv64(iv) => Ok(iv.as_ref()),
435 _ => Err(Unspecified),
436 }
437 }
438 }
439
440 impl Debug for $name {
441 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
442 match self {
443 Self::Iv128(_) => write!(f, "Iv128"),
444 #[cfg(feature = "legacy-des")]
445 Self::Iv64(_) => write!(f, "Iv64"),
446 Self::None => write!(f, "None"),
447 }
448 }
449 }
450
451 impl From<$other> for $name {
452 fn from(value: $other) -> Self {
453 match value {
454 $other::Iv128(iv) => $name::Iv128(iv),
455 #[cfg(feature = "legacy-des")]
456 $other::Iv64(iv) => $name::Iv64(iv),
457 $other::None => $name::None,
458 }
459 }
460 }
461 };
462}
463
464define_cipher_context!(EncryptionContext, DecryptionContext);
465define_cipher_context!(DecryptionContext, EncryptionContext);
466
467#[non_exhaustive]
468#[derive(Debug, PartialEq, Eq, Clone, Copy)]
469pub enum AlgorithmId {
471 Aes128,
473
474 Aes256,
476
477 Aes192,
479
480 #[cfg(feature = "legacy-des")]
485 #[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "legacy-des")))]
486 #[deprecated(
487 note = "Single DES is a legacy algorithm retained for interoperability only. Prefer an AES-based algorithm."
488 )]
489 DesForLegacyUseOnly,
490
491 #[cfg(feature = "legacy-des")]
496 #[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "legacy-des")))]
497 #[deprecated(
498 note = "2-key Triple DES is a legacy algorithm retained for interoperability only; NIST SP 800-131A Rev. 2 disallows its use for encryption. Prefer an AES-based algorithm."
499 )]
500 DesEdeForLegacyUseOnly,
501
502 #[cfg(feature = "legacy-des")]
507 #[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "legacy-des")))]
508 #[deprecated(
509 note = "3DES is a legacy algorithm retained for interoperability only; NIST SP 800-131A Rev. 2 disallows its use for encryption. Prefer an AES-based algorithm."
510 )]
511 DesEde3ForLegacyUseOnly,
512}
513
514#[derive(Debug, PartialEq, Eq)]
516pub struct Algorithm {
517 id: AlgorithmId,
518 key_len: usize,
519 block_len: usize,
520}
521
522pub const AES_128: Algorithm = Algorithm {
524 id: AlgorithmId::Aes128,
525 key_len: AES_128_KEY_LEN,
526 block_len: AES_BLOCK_LEN,
527};
528
529pub const AES_192: Algorithm = Algorithm {
531 id: AlgorithmId::Aes192,
532 key_len: AES_192_KEY_LEN,
533 block_len: AES_BLOCK_LEN,
534};
535
536pub const AES_256: Algorithm = Algorithm {
538 id: AlgorithmId::Aes256,
539 key_len: AES_256_KEY_LEN,
540 block_len: AES_BLOCK_LEN,
541};
542
543#[cfg(feature = "legacy-des")]
553#[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "legacy-des")))]
554#[allow(deprecated)]
555#[deprecated(
556 note = "Single DES is a legacy algorithm retained for interoperability only. Prefer an AES-based algorithm."
557)]
558pub const DES_FOR_LEGACY_USE_ONLY: Algorithm = Algorithm {
559 id: AlgorithmId::DesForLegacyUseOnly,
560 key_len: DES_KEY_LEN,
561 block_len: DES_BLOCK_LEN,
562};
563
564#[cfg(feature = "legacy-des")]
580#[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "legacy-des")))]
581#[allow(deprecated)]
582#[deprecated(
583 note = "2-key Triple DES is a legacy algorithm retained for interoperability only; NIST SP 800-131A Rev. 2 disallows its use for encryption. Prefer an AES-based algorithm."
584)]
585pub const DES_EDE_FOR_LEGACY_USE_ONLY: Algorithm = Algorithm {
586 id: AlgorithmId::DesEdeForLegacyUseOnly,
587 key_len: DES_EDE_KEY_LEN,
588 block_len: DES_BLOCK_LEN,
589};
590
591#[cfg(feature = "legacy-des")]
642#[cfg_attr(aws_lc_rs_docsrs, doc(cfg(feature = "legacy-des")))]
643#[allow(deprecated)]
644#[deprecated(
645 note = "3DES is a legacy algorithm retained for interoperability only; NIST SP 800-131A Rev. 2 disallows its use for encryption. Prefer an AES-based algorithm."
646)]
647pub const DES_EDE3_FOR_LEGACY_USE_ONLY: Algorithm = Algorithm {
648 id: AlgorithmId::DesEde3ForLegacyUseOnly,
649 key_len: DES_EDE3_KEY_LEN,
650 block_len: DES_BLOCK_LEN,
651};
652
653impl Algorithm {
654 fn id(&self) -> &AlgorithmId {
655 &self.id
656 }
657
658 #[must_use]
660 pub const fn block_len(&self) -> usize {
661 self.block_len
662 }
663
664 fn new_encryption_context(
665 &self,
666 mode: OperatingMode,
667 ) -> Result<EncryptionContext, Unspecified> {
668 match self.id {
669 AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => match mode {
671 OperatingMode::CBC | OperatingMode::CTR | OperatingMode::CFB128 => {
672 Ok(EncryptionContext::Iv128(FixedLength::new()?))
673 }
674 OperatingMode::ECB => Ok(EncryptionContext::None),
675 },
676 #[cfg(feature = "legacy-des")]
677 #[allow(deprecated)]
678 AlgorithmId::DesForLegacyUseOnly
679 | AlgorithmId::DesEdeForLegacyUseOnly
680 | AlgorithmId::DesEde3ForLegacyUseOnly => match mode {
681 OperatingMode::CBC => Ok(EncryptionContext::Iv64(FixedLength::new()?)),
682 OperatingMode::ECB => Ok(EncryptionContext::None),
683 _ => Err(Unspecified),
684 },
685 }
686 }
687
688 fn is_valid_encryption_context(&self, mode: OperatingMode, input: &EncryptionContext) -> bool {
689 match self.id {
690 AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => match mode {
692 OperatingMode::CBC | OperatingMode::CTR | OperatingMode::CFB128 => {
693 matches!(input, EncryptionContext::Iv128(_))
694 }
695 OperatingMode::ECB => {
696 matches!(input, EncryptionContext::None)
697 }
698 },
699 #[cfg(feature = "legacy-des")]
700 #[allow(deprecated)]
701 AlgorithmId::DesForLegacyUseOnly
702 | AlgorithmId::DesEdeForLegacyUseOnly
703 | AlgorithmId::DesEde3ForLegacyUseOnly => match mode {
704 OperatingMode::CBC => matches!(input, EncryptionContext::Iv64(_)),
705 OperatingMode::ECB => matches!(input, EncryptionContext::None),
706 _ => false,
707 },
708 }
709 }
710
711 fn is_valid_decryption_context(&self, mode: OperatingMode, input: &DecryptionContext) -> bool {
712 match self.id {
714 AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => match mode {
715 OperatingMode::CBC | OperatingMode::CTR | OperatingMode::CFB128 => {
716 matches!(input, DecryptionContext::Iv128(_))
717 }
718 OperatingMode::ECB => {
719 matches!(input, DecryptionContext::None)
720 }
721 },
722 #[cfg(feature = "legacy-des")]
723 #[allow(deprecated)]
724 AlgorithmId::DesForLegacyUseOnly
725 | AlgorithmId::DesEdeForLegacyUseOnly
726 | AlgorithmId::DesEde3ForLegacyUseOnly => match mode {
727 OperatingMode::CBC => matches!(input, DecryptionContext::Iv64(_)),
728 OperatingMode::ECB => matches!(input, DecryptionContext::None),
729 _ => false,
730 },
731 }
732 }
733
734 fn supports_mode(&self, mode: OperatingMode) -> bool {
740 match self.id {
741 AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => matches!(
742 mode,
743 OperatingMode::CBC
744 | OperatingMode::CTR
745 | OperatingMode::CFB128
746 | OperatingMode::ECB
747 ),
748 #[cfg(feature = "legacy-des")]
749 #[allow(deprecated)]
750 AlgorithmId::DesForLegacyUseOnly
751 | AlgorithmId::DesEdeForLegacyUseOnly
752 | AlgorithmId::DesEde3ForLegacyUseOnly => {
753 matches!(mode, OperatingMode::CBC | OperatingMode::ECB)
754 }
755 }
756 }
757}
758
759#[allow(clippy::missing_fields_in_debug)]
760impl Debug for UnboundCipherKey {
761 fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
762 f.debug_struct("UnboundCipherKey")
763 .field("algorithm", &self.algorithm)
764 .finish()
765 }
766}
767
768impl From<hkdf::Okm<'_, &'static Algorithm>> for UnboundCipherKey {
769 fn from(okm: hkdf::Okm<&'static Algorithm>) -> Self {
770 let mut key_bytes = [0; MAX_CIPHER_KEY_LEN];
771 let key_bytes = &mut key_bytes[..okm.len().key_len];
772 let algorithm = *okm.len();
773 okm.fill(key_bytes).unwrap();
774 Self::new(algorithm, key_bytes).unwrap()
775 }
776}
777
778impl KeyType for &'static Algorithm {
779 fn len(&self) -> usize {
780 self.key_len
781 }
782}
783
784pub struct UnboundCipherKey {
786 algorithm: &'static Algorithm,
787 key_bytes: Buffer<'static, &'static [u8]>,
788}
789
790impl UnboundCipherKey {
791 pub fn new(algorithm: &'static Algorithm, key_bytes: &[u8]) -> Result<Self, Unspecified> {
797 if key_bytes.len() != algorithm.key_len {
798 return Err(Unspecified);
799 }
800 let key_bytes = Buffer::new(key_bytes.to_vec());
801 Ok(UnboundCipherKey {
802 algorithm,
803 key_bytes,
804 })
805 }
806
807 #[inline]
808 #[must_use]
809 pub fn algorithm(&self) -> &'static Algorithm {
811 self.algorithm
812 }
813
814 #[allow(clippy::unused_self)]
827 #[allow(clippy::unnecessary_wraps)]
828 fn validate_key_material(&self) -> Result<(), KeyRejected> {
829 #[cfg(feature = "legacy-des")]
830 #[allow(deprecated)]
831 match self.algorithm.id() {
832 AlgorithmId::DesForLegacyUseOnly => {
833 let _ = SymmetricCipherKey::prepare_des(self.key_bytes.as_ref())?;
834 }
835 AlgorithmId::DesEdeForLegacyUseOnly => {
836 let _ = SymmetricCipherKey::prepare_des_ede(self.key_bytes.as_ref())?;
837 }
838 AlgorithmId::DesEde3ForLegacyUseOnly => {
839 let _ = SymmetricCipherKey::prepare_des_ede3(self.key_bytes.as_ref())?;
840 }
841 _ => {}
842 }
843 Ok(())
844 }
845}
846
847impl TryInto<SymmetricCipherKey> for UnboundCipherKey {
848 type Error = KeyRejected;
849
850 fn try_into(self) -> Result<SymmetricCipherKey, Self::Error> {
851 match self.algorithm.id() {
852 AlgorithmId::Aes128 => SymmetricCipherKey::aes128(self.key_bytes.as_ref()),
853 AlgorithmId::Aes192 => SymmetricCipherKey::aes192(self.key_bytes.as_ref()),
854 AlgorithmId::Aes256 => SymmetricCipherKey::aes256(self.key_bytes.as_ref()),
855 #[cfg(feature = "legacy-des")]
856 #[allow(deprecated)]
857 AlgorithmId::DesForLegacyUseOnly => SymmetricCipherKey::des(self.key_bytes.as_ref()),
858 #[cfg(feature = "legacy-des")]
859 #[allow(deprecated)]
860 AlgorithmId::DesEdeForLegacyUseOnly => {
861 SymmetricCipherKey::des_ede(self.key_bytes.as_ref())
862 }
863 #[cfg(feature = "legacy-des")]
864 #[allow(deprecated)]
865 AlgorithmId::DesEde3ForLegacyUseOnly => {
866 SymmetricCipherKey::des_ede3(self.key_bytes.as_ref())
867 }
868 }
869 }
870}
871
872pub struct EncryptingKey {
874 algorithm: &'static Algorithm,
875 key: SymmetricCipherKey,
876 mode: OperatingMode,
877}
878
879impl EncryptingKey {
880 pub fn ctr(key: UnboundCipherKey) -> Result<Self, Unspecified> {
893 Self::new(key, OperatingMode::CTR)
894 }
895
896 pub fn cfb128(key: UnboundCipherKey) -> Result<Self, Unspecified> {
909 Self::new(key, OperatingMode::CFB128)
910 }
911
912 pub fn cbc(key: UnboundCipherKey) -> Result<Self, Unspecified> {
935 Self::new(key, OperatingMode::CBC)
936 }
937
938 pub fn ecb(key: UnboundCipherKey) -> Result<Self, Unspecified> {
961 Self::new(key, OperatingMode::ECB)
962 }
963
964 #[allow(clippy::unnecessary_wraps)]
965 fn new(key: UnboundCipherKey, mode: OperatingMode) -> Result<Self, Unspecified> {
966 let algorithm = key.algorithm();
967 if !algorithm.supports_mode(mode) {
968 return Err(Unspecified);
969 }
970 let key = key.try_into()?;
971 Ok(Self {
972 algorithm,
973 key,
974 mode,
975 })
976 }
977
978 #[must_use]
980 pub fn algorithm(&self) -> &Algorithm {
981 self.algorithm
982 }
983
984 #[must_use]
986 pub fn mode(&self) -> OperatingMode {
987 self.mode
988 }
989
990 pub fn encrypt(&self, in_out: &mut [u8]) -> Result<DecryptionContext, Unspecified> {
1001 let context = self.algorithm.new_encryption_context(self.mode)?;
1002 self.less_safe_encrypt(in_out, context)
1003 }
1004
1005 pub fn less_safe_encrypt(
1017 &self,
1018 in_out: &mut [u8],
1019 context: EncryptionContext,
1020 ) -> Result<DecryptionContext, Unspecified> {
1021 if !self
1022 .algorithm()
1023 .is_valid_encryption_context(self.mode, &context)
1024 {
1025 return Err(Unspecified);
1026 }
1027 encrypt(self.algorithm(), &self.key, self.mode, in_out, context)
1028 }
1029}
1030
1031impl Debug for EncryptingKey {
1032 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1033 f.debug_struct("EncryptingKey")
1034 .field("algorithm", self.algorithm)
1035 .field("mode", &self.mode)
1036 .finish_non_exhaustive()
1037 }
1038}
1039
1040pub struct DecryptingKey {
1042 algorithm: &'static Algorithm,
1043 key: SymmetricCipherKey,
1044 mode: OperatingMode,
1045}
1046
1047impl DecryptingKey {
1048 pub fn ctr(key: UnboundCipherKey) -> Result<DecryptingKey, Unspecified> {
1061 Self::new(key, OperatingMode::CTR)
1062 }
1063
1064 pub fn cfb128(key: UnboundCipherKey) -> Result<Self, Unspecified> {
1077 Self::new(key, OperatingMode::CFB128)
1078 }
1079
1080 pub fn cbc(key: UnboundCipherKey) -> Result<DecryptingKey, Unspecified> {
1103 Self::new(key, OperatingMode::CBC)
1104 }
1105
1106 pub fn ecb(key: UnboundCipherKey) -> Result<Self, Unspecified> {
1129 Self::new(key, OperatingMode::ECB)
1130 }
1131
1132 #[allow(clippy::unnecessary_wraps)]
1133 fn new(key: UnboundCipherKey, mode: OperatingMode) -> Result<Self, Unspecified> {
1134 let algorithm = key.algorithm();
1135 if !algorithm.supports_mode(mode) {
1136 return Err(Unspecified);
1137 }
1138 let key = key.try_into()?;
1139 Ok(Self {
1140 algorithm,
1141 key,
1142 mode,
1143 })
1144 }
1145
1146 #[must_use]
1148 pub fn algorithm(&self) -> &Algorithm {
1149 self.algorithm
1150 }
1151
1152 #[must_use]
1154 pub fn mode(&self) -> OperatingMode {
1155 self.mode
1156 }
1157
1158 pub fn decrypt<'in_out>(
1168 &self,
1169 in_out: &'in_out mut [u8],
1170 context: DecryptionContext,
1171 ) -> Result<&'in_out mut [u8], Unspecified> {
1172 decrypt(self.algorithm, &self.key, self.mode, in_out, context)
1173 }
1174}
1175
1176impl Debug for DecryptingKey {
1177 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1178 f.debug_struct("DecryptingKey")
1179 .field("algorithm", &self.algorithm)
1180 .field("mode", &self.mode)
1181 .finish_non_exhaustive()
1182 }
1183}
1184
1185fn encrypt(
1186 algorithm: &Algorithm,
1187 key: &SymmetricCipherKey,
1188 mode: OperatingMode,
1189 in_out: &mut [u8],
1190 context: EncryptionContext,
1191) -> Result<DecryptionContext, Unspecified> {
1192 let block_len = algorithm.block_len();
1193
1194 match mode {
1195 OperatingMode::CBC | OperatingMode::ECB if in_out.len() % block_len != 0 => {
1196 return Err(Unspecified);
1197 }
1198 _ => {}
1199 }
1200
1201 match mode {
1202 OperatingMode::CBC => match algorithm.id() {
1203 AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
1204 aes::encrypt_cbc_mode(key, context, in_out)
1205 }
1206 #[cfg(feature = "legacy-des")]
1207 #[allow(deprecated)]
1208 AlgorithmId::DesForLegacyUseOnly
1209 | AlgorithmId::DesEdeForLegacyUseOnly
1210 | AlgorithmId::DesEde3ForLegacyUseOnly => des::encrypt_cbc_mode(key, context, in_out),
1211 },
1212 OperatingMode::CTR => match algorithm.id() {
1213 AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
1214 aes::encrypt_ctr_mode(key, context, in_out)
1215 }
1216 #[cfg(feature = "legacy-des")]
1217 #[allow(deprecated)]
1218 AlgorithmId::DesForLegacyUseOnly
1219 | AlgorithmId::DesEdeForLegacyUseOnly
1220 | AlgorithmId::DesEde3ForLegacyUseOnly => {
1221 unreachable!("DES does not support CTR mode.")
1222 }
1223 },
1224 OperatingMode::CFB128 => match algorithm.id() {
1226 AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
1227 aes::encrypt_cfb_mode(key, mode, context, in_out)
1228 }
1229 #[cfg(feature = "legacy-des")]
1230 #[allow(deprecated)]
1231 AlgorithmId::DesForLegacyUseOnly
1232 | AlgorithmId::DesEdeForLegacyUseOnly
1233 | AlgorithmId::DesEde3ForLegacyUseOnly => {
1234 unreachable!("DES does not support CFB128 mode.")
1235 }
1236 },
1237 OperatingMode::ECB => match algorithm.id() {
1238 AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
1239 aes::encrypt_ecb_mode(key, context, in_out)
1240 }
1241 #[cfg(feature = "legacy-des")]
1242 #[allow(deprecated)]
1243 AlgorithmId::DesForLegacyUseOnly
1244 | AlgorithmId::DesEdeForLegacyUseOnly
1245 | AlgorithmId::DesEde3ForLegacyUseOnly => des::encrypt_ecb_mode(key, context, in_out),
1246 },
1247 }
1248}
1249
1250fn decrypt<'in_out>(
1251 algorithm: &'static Algorithm,
1252 key: &SymmetricCipherKey,
1253 mode: OperatingMode,
1254 in_out: &'in_out mut [u8],
1255 context: DecryptionContext,
1256) -> Result<&'in_out mut [u8], Unspecified> {
1257 let block_len = algorithm.block_len();
1258
1259 match mode {
1260 OperatingMode::CBC | OperatingMode::ECB if in_out.len() % block_len != 0 => {
1261 return Err(Unspecified);
1262 }
1263 _ => {}
1264 }
1265
1266 match mode {
1267 OperatingMode::CBC => match algorithm.id() {
1268 AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
1269 aes::decrypt_cbc_mode(key, context, in_out)
1270 }
1271 #[cfg(feature = "legacy-des")]
1272 #[allow(deprecated)]
1273 AlgorithmId::DesForLegacyUseOnly
1274 | AlgorithmId::DesEdeForLegacyUseOnly
1275 | AlgorithmId::DesEde3ForLegacyUseOnly => des::decrypt_cbc_mode(key, context, in_out),
1276 },
1277 OperatingMode::CTR => match algorithm.id() {
1278 AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
1279 aes::decrypt_ctr_mode(key, context, in_out)
1280 }
1281 #[cfg(feature = "legacy-des")]
1282 #[allow(deprecated)]
1283 AlgorithmId::DesForLegacyUseOnly
1284 | AlgorithmId::DesEdeForLegacyUseOnly
1285 | AlgorithmId::DesEde3ForLegacyUseOnly => {
1286 unreachable!("DES does not support CTR mode.")
1287 }
1288 },
1289 OperatingMode::CFB128 => match algorithm.id() {
1291 AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
1292 aes::decrypt_cfb_mode(key, mode, context, in_out)
1293 }
1294 #[cfg(feature = "legacy-des")]
1295 #[allow(deprecated)]
1296 AlgorithmId::DesForLegacyUseOnly
1297 | AlgorithmId::DesEdeForLegacyUseOnly
1298 | AlgorithmId::DesEde3ForLegacyUseOnly => {
1299 unreachable!("DES does not support CFB128 mode.")
1300 }
1301 },
1302 OperatingMode::ECB => match algorithm.id() {
1303 AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
1304 aes::decrypt_ecb_mode(key, context, in_out)
1305 }
1306 #[cfg(feature = "legacy-des")]
1307 #[allow(deprecated)]
1308 AlgorithmId::DesForLegacyUseOnly
1309 | AlgorithmId::DesEdeForLegacyUseOnly
1310 | AlgorithmId::DesEde3ForLegacyUseOnly => des::decrypt_ecb_mode(key, context, in_out),
1311 },
1312 }
1313}
1314
1315#[cfg(test)]
1316mod tests {
1317 use super::*;
1318 use crate::test::from_hex;
1319
1320 #[cfg(feature = "fips")]
1321 mod fips;
1322
1323 #[test]
1324 fn test_debug() {
1325 {
1326 let aes_128_key_bytes = from_hex("000102030405060708090a0b0c0d0e0f").unwrap();
1327 let cipher_key = UnboundCipherKey::new(&AES_128, aes_128_key_bytes.as_slice()).unwrap();
1328 assert_eq!("UnboundCipherKey { algorithm: Algorithm { id: Aes128, key_len: 16, block_len: 16 } }", format!("{cipher_key:?}"));
1329 }
1330
1331 {
1332 let aes_256_key_bytes =
1333 from_hex("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f")
1334 .unwrap();
1335 let cipher_key = UnboundCipherKey::new(&AES_256, aes_256_key_bytes.as_slice()).unwrap();
1336 assert_eq!("UnboundCipherKey { algorithm: Algorithm { id: Aes256, key_len: 32, block_len: 16 } }", format!("{cipher_key:?}"));
1337 }
1338
1339 {
1340 let key_bytes = &[0u8; 16];
1341 let key = PaddedBlockEncryptingKey::cbc_pkcs7(
1342 UnboundCipherKey::new(&AES_128, key_bytes).unwrap(),
1343 )
1344 .unwrap();
1345 assert_eq!("PaddedBlockEncryptingKey { algorithm: Algorithm { id: Aes128, key_len: 16, block_len: 16 }, mode: CBC, padding: PKCS7, .. }", format!("{key:?}"));
1346 let mut data = vec![0u8; 16];
1347 let context = key.encrypt(&mut data).unwrap();
1348 assert_eq!("Iv128", format!("{context:?}"));
1349 let key = PaddedBlockDecryptingKey::cbc_pkcs7(
1350 UnboundCipherKey::new(&AES_128, key_bytes).unwrap(),
1351 )
1352 .unwrap();
1353 assert_eq!("PaddedBlockDecryptingKey { algorithm: Algorithm { id: Aes128, key_len: 16, block_len: 16 }, mode: CBC, padding: PKCS7, .. }", format!("{key:?}"));
1354 }
1355
1356 {
1357 let key_bytes = &[0u8; 16];
1358 let key =
1359 EncryptingKey::ctr(UnboundCipherKey::new(&AES_128, key_bytes).unwrap()).unwrap();
1360 assert_eq!("EncryptingKey { algorithm: Algorithm { id: Aes128, key_len: 16, block_len: 16 }, mode: CTR, .. }", format!("{key:?}"));
1361 let mut data = vec![0u8; 16];
1362 let context = key.encrypt(&mut data).unwrap();
1363 assert_eq!("Iv128", format!("{context:?}"));
1364 let key =
1365 DecryptingKey::ctr(UnboundCipherKey::new(&AES_128, key_bytes).unwrap()).unwrap();
1366 assert_eq!("DecryptingKey { algorithm: Algorithm { id: Aes128, key_len: 16, block_len: 16 }, mode: CTR, .. }", format!("{key:?}"));
1367 }
1368 }
1369
1370 fn helper_test_cipher_n_bytes(
1371 key: &[u8],
1372 alg: &'static Algorithm,
1373 mode: OperatingMode,
1374 n: usize,
1375 ) {
1376 let mut input: Vec<u8> = Vec::with_capacity(n);
1377 for i in 0..n {
1378 let byte: u8 = i.try_into().unwrap();
1379 input.push(byte);
1380 }
1381
1382 let cipher_key = UnboundCipherKey::new(alg, key).unwrap();
1383 let encrypting_key = EncryptingKey::new(cipher_key, mode).unwrap();
1384
1385 let mut in_out = input.clone();
1386 let decrypt_iv = encrypting_key.encrypt(&mut in_out).unwrap();
1387
1388 if n > 5 {
1389 assert_ne!(input.as_slice(), in_out);
1391 }
1392
1393 let cipher_key2 = UnboundCipherKey::new(alg, key).unwrap();
1394 let decrypting_key = DecryptingKey::new(cipher_key2, mode).unwrap();
1395
1396 let plaintext = decrypting_key.decrypt(&mut in_out, decrypt_iv).unwrap();
1397 assert_eq!(input.as_slice(), plaintext);
1398 }
1399
1400 #[test]
1401 fn test_aes_128_ctr() {
1402 let key = from_hex("000102030405060708090a0b0c0d0e0f").unwrap();
1403 for i in 0..=50 {
1404 helper_test_cipher_n_bytes(key.as_slice(), &AES_128, OperatingMode::CTR, i);
1405 }
1406 }
1407
1408 #[test]
1409 fn test_aes_128_cfb128() {
1410 let key = from_hex("000102030405060708090a0b0c0d0e0f").unwrap();
1411 for i in 0..=50 {
1412 helper_test_cipher_n_bytes(key.as_slice(), &AES_128, OperatingMode::CFB128, i);
1413 }
1414 }
1415
1416 #[test]
1417 fn test_aes_256_cfb128() {
1418 let key =
1419 from_hex("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f").unwrap();
1420 for i in 0..=50 {
1421 helper_test_cipher_n_bytes(key.as_slice(), &AES_256, OperatingMode::CFB128, i);
1422 }
1423 }
1424
1425 #[test]
1426 fn test_aes_256_ctr() {
1427 let key =
1428 from_hex("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f").unwrap();
1429 for i in 0..=50 {
1430 helper_test_cipher_n_bytes(key.as_slice(), &AES_256, OperatingMode::CTR, i);
1431 }
1432 }
1433
1434 #[test]
1435 fn test_aes_128_cbc() {
1436 let key = from_hex("000102030405060708090a0b0c0d0e0f").unwrap();
1437 for i in 0..=3 {
1439 let size = i * 16; helper_test_cipher_n_bytes(key.as_slice(), &AES_128, OperatingMode::CBC, size);
1441 }
1442 }
1443
1444 #[test]
1445 fn test_aes_256_cbc() {
1446 let key =
1447 from_hex("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f").unwrap();
1448 for i in 0..=3 {
1450 let size = i * 16; helper_test_cipher_n_bytes(key.as_slice(), &AES_256, OperatingMode::CBC, size);
1452 }
1453 }
1454
1455 #[test]
1456 fn test_aes_128_ecb() {
1457 let key = from_hex("000102030405060708090a0b0c0d0e0f").unwrap();
1458 _ = key;
1459 }
1460
1461 macro_rules! cipher_kat {
1462 ($name:ident, $alg:expr, $mode:expr, $key:literal, $iv: literal, $plaintext:literal, $ciphertext:literal) => {
1463 #[test]
1464 fn $name() {
1465 let key = from_hex($key).unwrap();
1466 let input = from_hex($plaintext).unwrap();
1467 let expected_ciphertext = from_hex($ciphertext).unwrap();
1468 let mut iv = from_hex($iv).unwrap();
1469 let iv = {
1470 let slice = iv.as_mut_slice();
1471 let mut iv = [0u8; $iv.len() / 2];
1472 {
1473 let x = iv.as_mut_slice();
1474 x.copy_from_slice(slice);
1475 }
1476 iv
1477 };
1478
1479 let ec = EncryptionContext::Iv128(FixedLength::from(iv));
1480
1481 let alg = $alg;
1482
1483 let unbound_key = UnboundCipherKey::new(alg, &key).unwrap();
1484
1485 let encrypting_key = EncryptingKey::new(unbound_key, $mode).unwrap();
1486
1487 let mut in_out = input.clone();
1488
1489 let context = encrypting_key.less_safe_encrypt(&mut in_out, ec).unwrap();
1490
1491 assert_eq!(expected_ciphertext, in_out);
1492
1493 let unbound_key2 = UnboundCipherKey::new(alg, &key).unwrap();
1494 let decrypting_key = DecryptingKey::new(unbound_key2, $mode).unwrap();
1495
1496 let plaintext = decrypting_key.decrypt(&mut in_out, context).unwrap();
1497 assert_eq!(input.as_slice(), plaintext);
1498 }
1499 };
1500 ($name:ident, $alg:expr, $mode:expr, $key:literal, $plaintext:literal, $ciphertext:literal) => {
1501 #[test]
1502 fn $name() {
1503 let key = from_hex($key).unwrap();
1504 let input = from_hex($plaintext).unwrap();
1505 let expected_ciphertext = from_hex($ciphertext).unwrap();
1506
1507 let alg = $alg;
1508
1509 let unbound_key = UnboundCipherKey::new(alg, &key).unwrap();
1510
1511 let encrypting_key = EncryptingKey::new(unbound_key, $mode).unwrap();
1512
1513 let mut in_out = input.clone();
1514
1515 let context = encrypting_key
1516 .less_safe_encrypt(&mut in_out, EncryptionContext::None)
1517 .unwrap();
1518
1519 assert_eq!(expected_ciphertext, in_out);
1520
1521 let unbound_key2 = UnboundCipherKey::new(alg, &key).unwrap();
1522 let decrypting_key = DecryptingKey::new(unbound_key2, $mode).unwrap();
1523
1524 let plaintext = decrypting_key.decrypt(&mut in_out, context).unwrap();
1525 assert_eq!(input.as_slice(), plaintext);
1526 }
1527 };
1528 }
1529
1530 cipher_kat!(
1531 test_iv_aes_128_ctr_16_bytes,
1532 &AES_128,
1533 OperatingMode::CTR,
1534 "000102030405060708090a0b0c0d0e0f",
1535 "00000000000000000000000000000000",
1536 "00112233445566778899aabbccddeeff",
1537 "c6b01904c3da3df5e7d62bd96d153686"
1538 );
1539
1540 cipher_kat!(
1541 test_iv_aes_256_ctr_15_bytes,
1542 &AES_256,
1543 OperatingMode::CTR,
1544 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
1545 "00000000000000000000000000000000",
1546 "00112233445566778899aabbccddee",
1547 "f28122856e1cf9a7216a30d111f399"
1548 );
1549
1550 cipher_kat!(
1551 test_openssl_aes_128_ctr_15_bytes,
1552 &AES_128,
1553 OperatingMode::CTR,
1554 "244828580821c1652582c76e34d299f5",
1555 "093145d5af233f46072a5eb5adc11aa1",
1556 "3ee38cec171e6cf466bf0df98aa0e1",
1557 "bd7d928f60e3422d96b3f8cd614eb2"
1558 );
1559
1560 cipher_kat!(
1561 test_openssl_aes_256_ctr_15_bytes,
1562 &AES_256,
1563 OperatingMode::CTR,
1564 "0857db8240ea459bdf660b4cced66d1f2d3734ff2de7b81e92740e65e7cc6a1d",
1565 "f028ecb053f801102d11fccc9d303a27",
1566 "eca7285d19f3c20e295378460e8729",
1567 "b5098e5e788de6ac2f2098eb2fc6f8"
1568 );
1569
1570 cipher_kat!(
1571 test_sp800_38a_cfb128_aes128,
1572 &AES_128,
1573 OperatingMode::CFB128,
1574 "2b7e151628aed2a6abf7158809cf4f3c",
1575 "000102030405060708090a0b0c0d0e0f",
1576 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
1577 "3b3fd92eb72dad20333449f8e83cfb4ac8a64537a0b3a93fcde3cdad9f1ce58b26751f67a3cbb140b1808cf187a4f4dfc04b05357c5d1c0eeac4c66f9ff7f2e6"
1578 );
1579
1580 cipher_kat!(
1581 test_sp800_38a_cfb128_aes256,
1582 &AES_256,
1583 OperatingMode::CFB128,
1584 "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
1585 "000102030405060708090a0b0c0d0e0f",
1586 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
1587 "dc7e84bfda79164b7ecd8486985d386039ffed143b28b1c832113c6331e5407bdf10132415e54b92a13ed0a8267ae2f975a385741ab9cef82031623d55b1e471"
1588 );
1589
1590 cipher_kat!(
1591 test_sp800_38a_ecb_aes128,
1592 &AES_128,
1593 OperatingMode::ECB,
1594 "2b7e151628aed2a6abf7158809cf4f3c",
1595 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
1596 "3ad77bb40d7a3660a89ecaf32466ef97f5d3d58503b9699de785895a96fdbaaf43b1cd7f598ece23881b00e3ed0306887b0c785e27e8ad3f8223207104725dd4"
1597 );
1598
1599 cipher_kat!(
1600 test_sp800_38a_ecb_aes256,
1601 &AES_256,
1602 OperatingMode::ECB,
1603 "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
1604 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
1605 "f3eed1bdb5d2a03c064b5a7e3db181f8591ccb10d410ed26dc5ba74a31362870b6ed21b99ca6f4f9f153e7b1beafed1d23304b7a39f9f3ff067d8d8f9e24ecc7"
1606 );
1607
1608 cipher_kat!(
1609 test_sp800_38a_cbc_aes128,
1610 &AES_128,
1611 OperatingMode::CBC,
1612 "2b7e151628aed2a6abf7158809cf4f3c",
1613 "000102030405060708090a0b0c0d0e0f",
1614 "6bc1bee22e409f96e93d7e117393172a",
1615 "7649abac8119b246cee98e9b12e9197d"
1616 );
1617
1618 cipher_kat!(
1619 test_sp800_38a_cbc_aes256,
1620 &AES_256,
1621 OperatingMode::CBC,
1622 "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
1623 "000102030405060708090a0b0c0d0e0f",
1624 "6bc1bee22e409f96e93d7e117393172a",
1625 "f58c4c04d6e5f1ba779eabfb5f7bfbd6"
1626 );
1627
1628 cipher_kat!(
1629 test_sp800_38a_cbc_aes128_multi_block,
1630 &AES_128,
1631 OperatingMode::CBC,
1632 "2b7e151628aed2a6abf7158809cf4f3c",
1633 "000102030405060708090a0b0c0d0e0f",
1634 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
1635 "7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e222295163ff1caa1681fac09120eca307586e1a7"
1636 );
1637
1638 cipher_kat!(
1639 test_sp800_38a_cbc_aes256_multi_block,
1640 &AES_256,
1641 OperatingMode::CBC,
1642 "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
1643 "000102030405060708090a0b0c0d0e0f",
1644 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
1645 "f58c4c04d6e5f1ba779eabfb5f7bfbd69cfc4e967edb808d679f777bc6702c7d39f23369a9d9bacfa530e26304231461b2eb05e2c39be9fcda6c19078c6a9d1b"
1646 );
1647
1648 #[cfg(feature = "legacy-des")]
1649 #[test]
1650 #[allow(deprecated)]
1651 fn test_des_rejects_weak_key() {
1652 let weak_keys: [&str; 4] = [
1653 "0101010101010101",
1654 "fefefefefefefefe",
1655 "e0e0e0e0f1f1f1f1",
1656 "1f1f1f1f0e0e0e0e",
1657 ];
1658 for weak in &weak_keys {
1659 let key = from_hex(weak).unwrap();
1660 assert!(
1661 UnboundCipherKey::new(&DES_FOR_LEGACY_USE_ONLY, &key)
1662 .and_then(EncryptingKey::cbc)
1663 .is_err(),
1664 "expected weak DES key {weak} to be rejected"
1665 );
1666 }
1667 }
1668
1669 #[cfg(feature = "legacy-des")]
1670 #[test]
1671 #[allow(deprecated)]
1672 fn test_des_rejects_semi_weak_key() {
1673 let semi_weak_keys: [&str; 12] = [
1674 "01fe01fe01fe01fe",
1675 "fe01fe01fe01fe01",
1676 "1fe01fe00ef10ef1",
1677 "e01fe01ff10ef10e",
1678 "01e001e001f101f1",
1679 "e001e001f101f101",
1680 "1ffe1ffe0efe0efe",
1681 "fe1ffe1ffe0efe0e",
1682 "011f011f010e010e",
1683 "1f011f010e010e01",
1684 "e0fee0fef1fef1fe",
1685 "fee0fee0fef1fef1",
1686 ];
1687 for semi_weak in &semi_weak_keys {
1688 let key = from_hex(semi_weak).unwrap();
1689 assert!(
1690 UnboundCipherKey::new(&DES_FOR_LEGACY_USE_ONLY, &key)
1691 .and_then(EncryptingKey::cbc)
1692 .is_err(),
1693 "expected semi-weak DES key {semi_weak} to be rejected"
1694 );
1695 }
1696 }
1697
1698 #[cfg(feature = "legacy-des")]
1699 #[test]
1700 #[allow(deprecated)]
1701 fn test_des_ede_rejects_k1_equal_k2() {
1702 let weak_key = from_hex("0123456789abcdef0123456789abcdef").unwrap();
1705 let result = UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &weak_key)
1706 .and_then(EncryptingKey::cbc);
1707 assert!(result.is_err(), "expected K1 == K2 to be rejected");
1708
1709 let good_key = from_hex("0123456789abcdef23456789abcdef01").unwrap();
1711 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &good_key)
1712 .and_then(EncryptingKey::cbc)
1713 .expect("valid 2TDEA key should be accepted");
1714 }
1715
1716 #[cfg(feature = "legacy-des")]
1717 #[test]
1718 #[allow(deprecated)]
1719 fn test_des_ede_rejects_weak_subkey() {
1720 let weak_keys: [&str; 4] = [
1725 "0101010101010101",
1726 "fefefefefefefefe",
1727 "e0e0e0e0f1f1f1f1",
1728 "1f1f1f1f0e0e0e0e",
1729 ];
1730 let distinct = "23456789abcdef01";
1731 for weak in &weak_keys {
1732 let key = from_hex(&format!("{}{}", weak, distinct)).unwrap();
1734 assert!(
1735 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &key)
1736 .and_then(EncryptingKey::cbc)
1737 .is_err(),
1738 "expected weak DES K1 = {weak} to be rejected in 2TDEA"
1739 );
1740 let key = from_hex(&format!("{}{}", distinct, weak)).unwrap();
1742 assert!(
1743 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &key)
1744 .and_then(EncryptingKey::cbc)
1745 .is_err(),
1746 "expected weak DES K2 = {weak} to be rejected in 2TDEA"
1747 );
1748 }
1749 }
1750
1751 #[cfg(feature = "legacy-des")]
1752 #[test]
1753 #[allow(deprecated)]
1754 fn test_des_ede3_rejects_degenerate_keys() {
1755 let k1_eq_k2 = from_hex("0123456789abcdef0123456789abcdef456789abcdef0123").unwrap();
1760 assert!(
1761 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &k1_eq_k2)
1762 .and_then(EncryptingKey::cbc)
1763 .is_err(),
1764 "expected K1 == K2 to be rejected for 3TDEA"
1765 );
1766
1767 let k2_eq_k3 = from_hex("0123456789abcdef23456789abcdef0123456789abcdef01").unwrap();
1768 assert!(
1769 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &k2_eq_k3)
1770 .and_then(EncryptingKey::cbc)
1771 .is_err(),
1772 "expected K2 == K3 to be rejected for 3TDEA"
1773 );
1774
1775 let k1_eq_k3 = from_hex("0123456789abcdef23456789abcdef010123456789abcdef").unwrap();
1776 assert!(
1777 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &k1_eq_k3)
1778 .and_then(EncryptingKey::cbc)
1779 .is_err(),
1780 "expected K1 == K3 (2TDEA-in-3TDEA form) to be rejected for 3TDEA"
1781 );
1782
1783 let good_key = from_hex("0123456789abcdef23456789abcdef01456789abcdef0123").unwrap();
1785 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &good_key)
1786 .and_then(EncryptingKey::cbc)
1787 .expect("valid 3TDEA key should be accepted");
1788 }
1789
1790 #[cfg(feature = "legacy-des")]
1791 #[test]
1792 #[allow(deprecated)]
1793 fn test_des_ede3_rejects_weak_subkey() {
1794 let weak_keys: [&str; 4] = [
1799 "0101010101010101",
1800 "fefefefefefefefe",
1801 "e0e0e0e0f1f1f1f1",
1802 "1f1f1f1f0e0e0e0e",
1803 ];
1804 let fillers = ["23456789abcdef01", "456789abcdef0123"];
1805
1806 for weak in &weak_keys {
1807 for position in 0..3 {
1808 let mut parts = [""; 3];
1813 parts[position] = *weak;
1814 parts[(position + 1) % 3] = fillers[0];
1815 parts[(position + 2) % 3] = fillers[1];
1816 let key = from_hex(&format!("{}{}{}", parts[0], parts[1], parts[2])).unwrap();
1817 assert!(
1818 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &key)
1819 .and_then(EncryptingKey::cbc)
1820 .is_err(),
1821 "expected weak DES subkey {weak} at position {position} to be rejected"
1822 );
1823 }
1824 }
1825 }
1826
1827 #[cfg(feature = "legacy-des")]
1828 #[test]
1829 #[allow(deprecated)]
1830 fn test_des_ede_rejects_semi_weak_subkey() {
1831 let semi_weak_keys: [&str; 12] = [
1842 "01fe01fe01fe01fe",
1843 "fe01fe01fe01fe01",
1844 "1fe01fe00ef10ef1",
1845 "e01fe01ff10ef10e",
1846 "01e001e001f101f1",
1847 "e001e001f101f101",
1848 "1ffe1ffe0efe0efe",
1849 "fe1ffe1ffe0efe0e",
1850 "011f011f010e010e",
1851 "1f011f010e010e01",
1852 "e0fee0fef1fef1fe",
1853 "fee0fee0fef1fef1",
1854 ];
1855 let distinct = "0123456789abcdef";
1856 for semi_weak in &semi_weak_keys {
1857 let key = from_hex(&format!("{}{}", semi_weak, distinct)).unwrap();
1858 assert!(
1859 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &key)
1860 .and_then(EncryptingKey::cbc)
1861 .is_err(),
1862 "expected semi-weak DES K1 = {semi_weak} to be rejected in 2TDEA"
1863 );
1864 let key = from_hex(&format!("{}{}", distinct, semi_weak)).unwrap();
1865 assert!(
1866 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &key)
1867 .and_then(EncryptingKey::cbc)
1868 .is_err(),
1869 "expected semi-weak DES K2 = {semi_weak} to be rejected in 2TDEA"
1870 );
1871 }
1872 }
1873
1874 #[cfg(feature = "legacy-des")]
1875 #[test]
1876 #[allow(deprecated)]
1877 fn test_des_ede3_rejects_semi_weak_subkey() {
1878 let semi_weak_keys: [&str; 12] = [
1881 "01fe01fe01fe01fe",
1882 "fe01fe01fe01fe01",
1883 "1fe01fe00ef10ef1",
1884 "e01fe01ff10ef10e",
1885 "01e001e001f101f1",
1886 "e001e001f101f101",
1887 "1ffe1ffe0efe0efe",
1888 "fe1ffe1ffe0efe0e",
1889 "011f011f010e010e",
1890 "1f011f010e010e01",
1891 "e0fee0fef1fef1fe",
1892 "fee0fee0fef1fef1",
1893 ];
1894 let fillers = ["0123456789abcdef", "23456789abcdef01"];
1895
1896 for semi_weak in &semi_weak_keys {
1897 for position in 0..3 {
1898 let mut parts = [""; 3];
1899 parts[position] = *semi_weak;
1900 parts[(position + 1) % 3] = fillers[0];
1901 parts[(position + 2) % 3] = fillers[1];
1902 let key = from_hex(&format!("{}{}{}", parts[0], parts[1], parts[2])).unwrap();
1903 assert!(
1904 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &key)
1905 .and_then(EncryptingKey::cbc)
1906 .is_err(),
1907 "expected semi-weak DES subkey {semi_weak} at position {position} to be rejected in 3TDEA"
1908 );
1909 }
1910 }
1911 }
1912
1913 #[cfg(feature = "legacy-des")]
1914 #[test]
1915 #[allow(deprecated)]
1916 fn test_des_rejects_unsupported_modes() {
1917 let key1 = from_hex("0123456789abcdef").unwrap();
1920 assert!(
1921 UnboundCipherKey::new(&DES_FOR_LEGACY_USE_ONLY, &key1)
1922 .and_then(EncryptingKey::ctr)
1923 .is_err(),
1924 "DES + CTR (encrypt) should be rejected"
1925 );
1926 assert!(
1927 UnboundCipherKey::new(&DES_FOR_LEGACY_USE_ONLY, &key1)
1928 .and_then(EncryptingKey::cfb128)
1929 .is_err(),
1930 "DES + CFB128 (encrypt) should be rejected"
1931 );
1932 assert!(
1933 UnboundCipherKey::new(&DES_FOR_LEGACY_USE_ONLY, &key1)
1934 .and_then(DecryptingKey::ctr)
1935 .is_err(),
1936 "DES + CTR (decrypt) should be rejected"
1937 );
1938 assert!(
1939 UnboundCipherKey::new(&DES_FOR_LEGACY_USE_ONLY, &key1)
1940 .and_then(DecryptingKey::cfb128)
1941 .is_err(),
1942 "DES + CFB128 (decrypt) should be rejected"
1943 );
1944
1945 let key2 = from_hex("0123456789abcdef23456789abcdef01").unwrap();
1946 assert!(
1947 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &key2)
1948 .and_then(EncryptingKey::ctr)
1949 .is_err(),
1950 "2TDEA + CTR (encrypt) should be rejected"
1951 );
1952 assert!(
1953 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &key2)
1954 .and_then(EncryptingKey::cfb128)
1955 .is_err(),
1956 "2TDEA + CFB128 (encrypt) should be rejected"
1957 );
1958 assert!(
1959 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &key2)
1960 .and_then(DecryptingKey::ctr)
1961 .is_err(),
1962 "2TDEA + CTR (decrypt) should be rejected"
1963 );
1964 assert!(
1965 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &key2)
1966 .and_then(DecryptingKey::cfb128)
1967 .is_err(),
1968 "2TDEA + CFB128 (decrypt) should be rejected"
1969 );
1970
1971 let key3 = from_hex("0123456789abcdef23456789abcdef01456789abcdef0123").unwrap();
1972 assert!(
1973 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &key3)
1974 .and_then(EncryptingKey::ctr)
1975 .is_err(),
1976 "3TDEA + CTR (encrypt) should be rejected"
1977 );
1978 assert!(
1979 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &key3)
1980 .and_then(EncryptingKey::cfb128)
1981 .is_err(),
1982 "3TDEA + CFB128 (encrypt) should be rejected"
1983 );
1984 assert!(
1985 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &key3)
1986 .and_then(DecryptingKey::ctr)
1987 .is_err(),
1988 "3TDEA + CTR (decrypt) should be rejected"
1989 );
1990 assert!(
1991 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &key3)
1992 .and_then(DecryptingKey::cfb128)
1993 .is_err(),
1994 "3TDEA + CFB128 (decrypt) should be rejected"
1995 );
1996
1997 assert!(
1999 UnboundCipherKey::new(&DES_FOR_LEGACY_USE_ONLY, &key1)
2000 .and_then(StreamingEncryptingKey::ctr)
2001 .is_err(),
2002 "DES + CTR (streaming encrypt) should be rejected"
2003 );
2004 assert!(
2005 UnboundCipherKey::new(&DES_FOR_LEGACY_USE_ONLY, &key1)
2006 .and_then(StreamingEncryptingKey::cfb128)
2007 .is_err(),
2008 "DES + CFB128 (streaming encrypt) should be rejected"
2009 );
2010 assert!(
2011 UnboundCipherKey::new(&DES_FOR_LEGACY_USE_ONLY, &key1)
2012 .and_then(|k| StreamingDecryptingKey::ctr(k, DecryptionContext::None))
2013 .is_err(),
2014 "DES + CTR (streaming decrypt) should be rejected"
2015 );
2016 assert!(
2017 UnboundCipherKey::new(&DES_FOR_LEGACY_USE_ONLY, &key1)
2018 .and_then(|k| StreamingDecryptingKey::cfb128(k, DecryptionContext::None))
2019 .is_err(),
2020 "DES + CFB128 (streaming decrypt) should be rejected"
2021 );
2022
2023 assert!(
2024 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &key2)
2025 .and_then(StreamingEncryptingKey::ctr)
2026 .is_err(),
2027 "2TDEA + CTR (streaming encrypt) should be rejected"
2028 );
2029 assert!(
2030 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &key2)
2031 .and_then(StreamingEncryptingKey::cfb128)
2032 .is_err(),
2033 "2TDEA + CFB128 (streaming encrypt) should be rejected"
2034 );
2035 assert!(
2036 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &key2)
2037 .and_then(|k| StreamingDecryptingKey::ctr(k, DecryptionContext::None))
2038 .is_err(),
2039 "2TDEA + CTR (streaming decrypt) should be rejected"
2040 );
2041 assert!(
2042 UnboundCipherKey::new(&DES_EDE_FOR_LEGACY_USE_ONLY, &key2)
2043 .and_then(|k| StreamingDecryptingKey::cfb128(k, DecryptionContext::None))
2044 .is_err(),
2045 "2TDEA + CFB128 (streaming decrypt) should be rejected"
2046 );
2047
2048 assert!(
2049 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &key3)
2050 .and_then(StreamingEncryptingKey::ctr)
2051 .is_err(),
2052 "3TDEA + CTR (streaming encrypt) should be rejected"
2053 );
2054 assert!(
2055 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &key3)
2056 .and_then(StreamingEncryptingKey::cfb128)
2057 .is_err(),
2058 "3TDEA + CFB128 (streaming encrypt) should be rejected"
2059 );
2060 assert!(
2061 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &key3)
2062 .and_then(|k| StreamingDecryptingKey::ctr(k, DecryptionContext::None))
2063 .is_err(),
2064 "3TDEA + CTR (streaming decrypt) should be rejected"
2065 );
2066 assert!(
2067 UnboundCipherKey::new(&DES_EDE3_FOR_LEGACY_USE_ONLY, &key3)
2068 .and_then(|k| StreamingDecryptingKey::cfb128(k, DecryptionContext::None))
2069 .is_err(),
2070 "3TDEA + CFB128 (streaming decrypt) should be rejected"
2071 );
2072 }
2073
2074 #[cfg(feature = "legacy-des")]
2075 #[test]
2076 #[allow(deprecated)]
2077 fn test_des_cbc() {
2078 let key = from_hex("0123456789abcdef").unwrap();
2079 for i in 0..=3 {
2080 let size = i * 8;
2081 helper_test_cipher_n_bytes(
2082 key.as_slice(),
2083 &DES_FOR_LEGACY_USE_ONLY,
2084 OperatingMode::CBC,
2085 size,
2086 );
2087 }
2088 }
2089
2090 #[cfg(feature = "legacy-des")]
2091 #[test]
2092 #[allow(deprecated)]
2093 fn test_des_ecb() {
2094 let key = from_hex("0123456789abcdef").unwrap();
2095 for i in 0..=3 {
2096 let size = i * 8;
2097 helper_test_cipher_n_bytes(
2098 key.as_slice(),
2099 &DES_FOR_LEGACY_USE_ONLY,
2100 OperatingMode::ECB,
2101 size,
2102 );
2103 }
2104 }
2105
2106 #[cfg(feature = "legacy-des")]
2107 #[test]
2108 #[allow(deprecated)]
2109 fn test_des_ede_cbc() {
2110 let key = from_hex("0123456789abcdef23456789abcdef01").unwrap();
2111 for i in 0..=3 {
2112 let size = i * 8;
2113 helper_test_cipher_n_bytes(
2114 key.as_slice(),
2115 &DES_EDE_FOR_LEGACY_USE_ONLY,
2116 OperatingMode::CBC,
2117 size,
2118 );
2119 }
2120 }
2121
2122 #[cfg(feature = "legacy-des")]
2123 #[test]
2124 #[allow(deprecated)]
2125 fn test_des_ede_ecb() {
2126 let key = from_hex("0123456789abcdef23456789abcdef01").unwrap();
2127 for i in 0..=3 {
2128 let size = i * 8;
2129 helper_test_cipher_n_bytes(
2130 key.as_slice(),
2131 &DES_EDE_FOR_LEGACY_USE_ONLY,
2132 OperatingMode::ECB,
2133 size,
2134 );
2135 }
2136 }
2137
2138 #[cfg(feature = "legacy-des")]
2139 #[test]
2140 #[allow(deprecated)]
2141 fn test_des_ede3_cbc() {
2142 let key = from_hex("0123456789abcdef23456789abcdef01456789abcdef0123").unwrap();
2143 for i in 0..=3 {
2144 let size = i * 8;
2145 helper_test_cipher_n_bytes(
2146 key.as_slice(),
2147 &DES_EDE3_FOR_LEGACY_USE_ONLY,
2148 OperatingMode::CBC,
2149 size,
2150 );
2151 }
2152 }
2153
2154 #[cfg(feature = "legacy-des")]
2155 #[test]
2156 #[allow(deprecated)]
2157 fn test_des_ede3_ecb() {
2158 let key = from_hex("0123456789abcdef23456789abcdef01456789abcdef0123").unwrap();
2159 for i in 0..=3 {
2160 let size = i * 8;
2161 helper_test_cipher_n_bytes(
2162 key.as_slice(),
2163 &DES_EDE3_FOR_LEGACY_USE_ONLY,
2164 OperatingMode::ECB,
2165 size,
2166 );
2167 }
2168 }
2169
2170 #[cfg(feature = "legacy-des")]
2171 macro_rules! des_cipher_kat {
2172 ($name:ident, $alg:expr, $mode:expr, $key:literal, $iv:literal, $plaintext:literal, $ciphertext:literal) => {
2173 #[test]
2174 #[allow(deprecated)]
2175 fn $name() {
2176 let key = from_hex($key).unwrap();
2177 let input = from_hex($plaintext).unwrap();
2178 let expected_ciphertext = from_hex($ciphertext).unwrap();
2179
2180 let ec = if $iv.len() == 0 {
2181 EncryptionContext::None
2182 } else {
2183 let iv_arr: [u8; 8] = from_hex($iv).unwrap().try_into().unwrap();
2184 EncryptionContext::Iv64(FixedLength::from(iv_arr))
2185 };
2186
2187 let unbound_key = UnboundCipherKey::new($alg, &key).unwrap();
2188 let encrypting_key = EncryptingKey::new(unbound_key, $mode).unwrap();
2189 let mut in_out = input.clone();
2190 let context = encrypting_key.less_safe_encrypt(&mut in_out, ec).unwrap();
2191 assert_eq!(expected_ciphertext, in_out);
2192
2193 let unbound_key2 = UnboundCipherKey::new($alg, &key).unwrap();
2194 let decrypting_key = DecryptingKey::new(unbound_key2, $mode).unwrap();
2195 let plaintext = decrypting_key.decrypt(&mut in_out, context).unwrap();
2196 assert_eq!(input.as_slice(), plaintext);
2197 }
2198 };
2199 }
2200
2201 #[cfg(feature = "legacy-des")]
2202 des_cipher_kat!(
2203 test_des_cbc_kat,
2204 &DES_FOR_LEGACY_USE_ONLY,
2205 OperatingMode::CBC,
2206 "0123456789abcdef",
2207 "f69f2445df4f9b17",
2208 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
2209 "2d121f90fcf68631ed788fcfe31a62dffa784891fa512ef928ea856d934257c6"
2210 );
2211
2212 #[cfg(feature = "legacy-des")]
2213 des_cipher_kat!(
2214 test_des_ecb_kat,
2215 &DES_FOR_LEGACY_USE_ONLY,
2216 OperatingMode::ECB,
2217 "0123456789abcdef",
2218 "",
2219 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
2220 "7277a00dc1c1c36b2256338b7a9f36ef6e511022cfebec489a4a53a1c7d22e5b"
2221 );
2222
2223 #[cfg(feature = "legacy-des")]
2224 des_cipher_kat!(
2225 test_sp800_67_des_ede_cbc,
2226 &DES_EDE_FOR_LEGACY_USE_ONLY,
2227 OperatingMode::CBC,
2228 "0123456789abcdef23456789abcdef01",
2229 "f69f2445df4f9b17",
2230 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
2231 "7401CE1EAB6D003CAFF84BF47B36CC2154F0238F9FFECD8F6ACF118392B45581"
2232 );
2233
2234 #[cfg(feature = "legacy-des")]
2235 des_cipher_kat!(
2236 test_sp800_67_des_ede_ecb,
2237 &DES_EDE_FOR_LEGACY_USE_ONLY,
2238 OperatingMode::ECB,
2239 "0123456789abcdef23456789abcdef01",
2240 "",
2241 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
2242 "06EDE3D82884090AFF322C19F0518486730576972A666E58B6C88CF107340D3D"
2243 );
2244
2245 #[cfg(feature = "legacy-des")]
2246 des_cipher_kat!(
2247 test_sp800_67_des_ede3_cbc,
2248 &DES_EDE3_FOR_LEGACY_USE_ONLY,
2249 OperatingMode::CBC,
2250 "0123456789abcdef23456789abcdef01456789abcdef0123",
2251 "f69f2445df4f9b17",
2252 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
2253 "2079c3d53aa763e193b79e2569ab5262516570481f25b50f73c0bda85c8e0da7"
2254 );
2255
2256 #[cfg(feature = "legacy-des")]
2257 des_cipher_kat!(
2258 test_sp800_67_des_ede3_ecb,
2259 &DES_EDE3_FOR_LEGACY_USE_ONLY,
2260 OperatingMode::ECB,
2261 "0123456789abcdef23456789abcdef01456789abcdef0123",
2262 "",
2263 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
2264 "714772f339841d34267fcc4bd2949cc3ee11c22a576a303876183f99c0b6de87"
2265 );
2266}