ssh_cipher/block_cipher/
decryptor.rs1use super::{BlockMode, State, sealed::BlockCipher};
4use crate::{Cipher, Error, Result};
5use ::cipher::{
6 Block, BlockModeDecClosure, BlockModeDecrypt,
7 common::{BlockSizeUser, InnerUser},
8};
9use core::fmt::{self, Debug};
10
11pub struct Decryptor<C: BlockCipher> {
17 cipher: C,
19
20 state: State<C::BlockSize>,
22}
23
24impl<C: BlockCipher> Decryptor<C> {
25 pub fn new(cipher: Cipher, key: &[u8], iv: &[u8]) -> Result<Self> {
34 if !C::is_supported(cipher) {
35 return Err(Error::UnsupportedCipher(cipher));
36 }
37
38 let mode = cipher.block_mode().ok_or(Error::Crypto)?;
39 let cipher = C::new_from_slice(key)?;
40 let state = State::new_from_slice(mode, iv)?;
41 Ok(Self { cipher, state })
42 }
43
44 pub fn peek<T, F>(&mut self, mut f: F) -> T
47 where
48 F: FnMut(&mut Self) -> T,
49 {
50 let state = self.state.clone();
51 let ret = f(self);
52 self.state = state;
53 ret
54 }
55}
56
57impl<C: BlockCipher> BlockModeDecrypt for Decryptor<C> {
58 fn decrypt_with_backend(&mut self, _f: impl BlockModeDecClosure<BlockSize = Self::BlockSize>) {
59 unimplemented!("CTR mode support is incompatible with BlockModeDecrypt")
60 }
61
62 fn decrypt_block(&mut self, block: &mut Block<Self>) {
63 match self.state.mode() {
64 BlockMode::Cbc => {
65 let pad = self.state.clone();
66 self.state.as_mut().copy_from_slice(block);
67 self.cipher.decrypt_block(block);
68 pad.xor_into(block);
69 }
70 BlockMode::Ctr => {
71 let mut pad = self.state.clone();
72 self.cipher.encrypt_block(pad.as_mut());
73 pad.xor_into(block);
74 self.state.increment_counter();
75 }
76 }
77 }
78
79 fn decrypt_blocks(&mut self, blocks: &mut [Block<Self>]) {
80 for block in blocks {
82 self.decrypt_block(block);
83 }
84 }
85}
86impl<C: BlockCipher> BlockSizeUser for Decryptor<C> {
87 type BlockSize = C::BlockSize;
88}
89
90impl<C: BlockCipher> Debug for Decryptor<C> {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 f.debug_struct("Decryptor").finish_non_exhaustive()
93 }
94}
95
96impl<C: BlockCipher> InnerUser for Decryptor<C> {
97 type Inner = C;
98}