From 1d2553f76b5b57c0604da18029877caf1a6377a0 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 8 Nov 2025 09:10:47 -0700 Subject: [PATCH] Revert "ssh-cipher: allows to decrypt a payload without altering state" This reverts commit ab1f2784d9cfb88e0c7ba9f870575d18450e50cb (#266). The latest versions of `cbc` and `ctr` no longer impl `Clone` deliberately, so this can no longer be implemented in this manner: RustCrypto/block-modes#91 The cipher needs to be fully reinitialized from the original key instead. --- ssh-cipher/src/decryptor.rs | 54 +++++++++++++------------------------ 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/ssh-cipher/src/decryptor.rs b/ssh-cipher/src/decryptor.rs index d1ecca7..b1423eb 100644 --- a/ssh-cipher/src/decryptor.rs +++ b/ssh-cipher/src/decryptor.rs @@ -28,7 +28,6 @@ pub struct Decryptor { } /// Inner decryptor enum which is deliberately kept out of the public API. -#[derive(Clone)] enum Inner { #[cfg(feature = "aes-cbc")] Aes128Cbc(cbc::Decryptor), @@ -46,31 +45,6 @@ enum Inner { TDesCbc(cbc::Decryptor), } -impl Inner { - fn decrypt(&mut self, buffer: &mut [u8]) -> Result<()> { - #[cfg(any(feature = "aes-cbc", feature = "aes-ctr", feature = "tdes"))] - match self { - #[cfg(feature = "aes-cbc")] - Self::Aes128Cbc(cipher) => cbc_decrypt(cipher, buffer), - #[cfg(feature = "aes-cbc")] - Self::Aes192Cbc(cipher) => cbc_decrypt(cipher, buffer), - #[cfg(feature = "aes-cbc")] - Self::Aes256Cbc(cipher) => cbc_decrypt(cipher, buffer), - #[cfg(feature = "aes-ctr")] - Self::Aes128Ctr(cipher) => ctr_decrypt(cipher, buffer), - #[cfg(feature = "aes-ctr")] - Self::Aes192Ctr(cipher) => ctr_decrypt(cipher, buffer), - #[cfg(feature = "aes-ctr")] - Self::Aes256Ctr(cipher) => ctr_decrypt(cipher, buffer), - #[cfg(feature = "tdes")] - Self::TDesCbc(cipher) => cbc_decrypt(cipher, buffer), - } - .map_err(|_| Error::Length)?; - - Ok(()) - } -} - impl Decryptor { /// Create a new decryptor object with the given [`Cipher`], key, and IV. pub fn new(cipher: Cipher, key: &[u8], iv: &[u8]) -> Result { @@ -123,16 +97,26 @@ impl Decryptor { /// Returns [`Error::Length`] in the event that `buffer` is not a multiple of the cipher's /// block size. pub fn decrypt(&mut self, buffer: &mut [u8]) -> Result<()> { - self.inner.decrypt(buffer) - } + #[cfg(any(feature = "aes-cbc", feature = "aes-ctr", feature = "tdes"))] + match &mut self.inner { + #[cfg(feature = "aes-cbc")] + Inner::Aes128Cbc(cipher) => cbc_decrypt(cipher, buffer), + #[cfg(feature = "aes-cbc")] + Inner::Aes192Cbc(cipher) => cbc_decrypt(cipher, buffer), + #[cfg(feature = "aes-cbc")] + Inner::Aes256Cbc(cipher) => cbc_decrypt(cipher, buffer), + #[cfg(feature = "aes-ctr")] + Inner::Aes128Ctr(cipher) => ctr_decrypt(cipher, buffer), + #[cfg(feature = "aes-ctr")] + Inner::Aes192Ctr(cipher) => ctr_decrypt(cipher, buffer), + #[cfg(feature = "aes-ctr")] + Inner::Aes256Ctr(cipher) => ctr_decrypt(cipher, buffer), + #[cfg(feature = "tdes")] + Inner::TDesCbc(cipher) => cbc_decrypt(cipher, buffer), + } + .map_err(|_| Error::Length)?; - /// Decrypt the given buffer in place without altering the internal state - /// - /// Returns [`Error::Length`] in the event that `buffer` is not a multiple of the cipher's - /// block size. - pub fn peek_decrypt(&self, buffer: &mut [u8]) -> Result<()> { - let mut inner = self.inner.clone(); - inner.decrypt(buffer) + Ok(()) } }