1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
use super::{Mac, PACKET_MIN_SIZE};
#[cfg(doc)]
use super::Packet;
const MIN_PAD_SIZE: usize = 4;
const MIN_ALIGN: usize = 8;
/// A trait with common methods and associated types involved
/// in the manipulation of [`OpeningCipher`] and [`SealingCipher`].
pub trait CipherCore {
    /// The associated error type returned by the `open` method.
    type Err: From<binrw::Error> + From<std::io::Error>;
    /// The _Message Authentication Code_ associated to the cipher.
    type Mac: Mac;
    /// Gets a reference to the _Message Authentication Code_ for this [`CipherCore`].
    fn mac(&self) -> &Self::Mac;
    /// The size of a [`CipherCore`]'s block.
    fn block_size(&self) -> usize;
    /// Calculate the necessary padding size for the provided payload `size`.
    fn padding(&self, payload: usize) -> u8 {
        let align = self.block_size().max(MIN_ALIGN);
        let size = if self.mac().etm() {
            std::mem::size_of::<u8>() + payload
        } else {
            std::mem::size_of::<u32>() + std::mem::size_of::<u8>() + payload
        };
        let padding = align - size % align;
        let padding = if padding < MIN_PAD_SIZE {
            padding + align
        } else {
            padding
        };
        if size + padding < self.block_size().max(PACKET_MIN_SIZE) {
            (padding + align) as u8
        } else {
            padding as u8
        }
    }
}
/// A cipher able to `open` a [`Packet`] and retrieve it's payload.
pub trait OpeningCipher: CipherCore {
    /// Decrypt the received `buf` using the [`OpeningCipher`].
    fn decrypt<B: AsMut<[u8]>>(&mut self, buf: B) -> Result<(), Self::Err>;
    /// Compare the received `buf` against the received _Message Authentication Code_.
    fn open<B: AsRef<[u8]>>(&mut self, buf: B, mac: Vec<u8>, seq: u32) -> Result<(), Self::Err>;
    /// Decompress the received `buf` using the [`OpeningCipher`].
    fn decompress(&mut self, buf: Vec<u8>) -> Result<Vec<u8>, Self::Err>;
}
/// A cipher able to `seal` a payload to create a [`Packet`].
pub trait SealingCipher: CipherCore {
    /// Decompress the `buf` using the [`SealingCipher`].
    fn compress<B: AsRef<[u8]>>(&mut self, buf: B) -> Result<Vec<u8>, Self::Err>;
    /// Pad the `buf` to match [`SealingCipher`]'s block size with random data,
    /// by increasing it by `padding` bytes and prefixing the `buf` it with it's len.
    fn pad(&mut self, buf: Vec<u8>, padding: u8) -> Result<Vec<u8>, Self::Err>;
    /// Encrypt the `buf` using using the [`SealingCipher`].
    fn encrypt<B: AsMut<[u8]>>(&mut self, buf: B) -> Result<(), Self::Err>;
    /// Generate a seal from the HMAC algorithm to produce a _Message Authentication Code_.
    fn seal<B: AsRef<[u8]>>(&mut self, buf: B, seq: u32) -> Result<Vec<u8>, Self::Err>;
}