Skip to main content

ssh_cipher/
block_cipher.rs

1//! Low-level block cipher interface.
2//!
3//! This module provides APIs which enable streaming and "peeking" when using unauthenticated block
4//! cipher modes such as CBC and CTR.
5
6#[cfg(feature = "aes")]
7mod aes;
8mod decryptor;
9mod encryptor;
10mod state;
11
12pub use self::{decryptor::Decryptor, encryptor::Encryptor};
13pub use ::cipher::{
14    Block, BlockModeDecrypt, BlockModeEncrypt, common::BlockSizeUser, common::InvalidLength,
15};
16
17#[cfg(feature = "aes")]
18pub use self::aes::Aes;
19#[cfg(feature = "tdes")]
20pub use ::des::TdesEde3 as Tdes;
21
22use self::state::State;
23
24#[cfg(feature = "tdes")]
25use {crate::Cipher, ::cipher::common::KeyInit};
26
27/// Seal the `BlockCipher` trait so others cannot implement it.
28pub(crate) mod sealed {
29    use crate::Cipher;
30    use ::cipher::{BlockCipherDecrypt, BlockCipherEncrypt, common::InvalidLength};
31
32    /// Trait for block ciphers supported by this crate.
33    ///
34    /// This trait is deliberately sealed so it cannot be implemented by downstream crates.
35    /// Notably new ciphers added to SSH should be authenticated, and we shouldn't support a
36    /// proliferation of unauthenticated ciphers.
37    pub trait BlockCipher: BlockCipherDecrypt + BlockCipherEncrypt {
38        /// Initialize cipher from a byte slice.
39        ///
40        /// This is defined separate from the [`KeyInit`] trait so it can support variable-sized keys.
41        ///
42        /// # Errors
43        /// Returns [`InvalidLength`] if `slice` is not equal in length to the key size.
44        fn new_from_slice(slice: &[u8]) -> Result<Self, InvalidLength>;
45
46        /// Is this the correct block cipher implementation for the given cipher?
47        fn is_supported(cipher: Cipher) -> bool;
48    }
49}
50
51/// Supported block cipher modes of operation.
52#[derive(Copy, Clone, Debug, Eq, PartialEq)]
53pub(crate) enum BlockMode {
54    /// Cipher block chaining.
55    Cbc,
56
57    /// Counter mode.
58    Ctr,
59}
60
61/// Encryptor for the Advanced Encryption Standard (AES).
62#[cfg(feature = "aes")]
63pub type AesEncryptor = Encryptor<Aes>;
64/// Decryptor for the Advanced Encryption Standard (AES).
65#[cfg(feature = "aes")]
66pub type AesDecryptor = Decryptor<Aes>;
67
68/// Encryptor for 3DES.
69#[cfg(feature = "tdes")]
70pub type TdesEncryptor = Encryptor<Tdes>;
71/// Decryptor for 3DES.
72#[cfg(feature = "tdes")]
73pub type TdesDecryptor = Decryptor<Tdes>;
74
75#[cfg(feature = "tdes")]
76impl sealed::BlockCipher for Tdes {
77    fn new_from_slice(slice: &[u8]) -> Result<Self, InvalidLength> {
78        KeyInit::new_from_slice(slice)
79    }
80
81    fn is_supported(cipher: Cipher) -> bool {
82        cipher == Cipher::TdesCbc
83    }
84}