navajo 0.0.4

cryptographic APIs
Documentation
use rust_crypto_aead::KeyInit;

use crate::{
    buffer::RcBuffer,
    error::{DecryptDeterministicallyError, EncryptDeterministicallyError, KeyError},
    Aad, Buffer,
};

use alloc::string::ToString;

use super::Algorithm;
use aes_siv::siv::Aes256Siv;

const AES_BLOCK_SIZE: usize = 16;

pub(super) struct Cipher(Aes256Siv);

impl Cipher {
    pub(super) fn new(algorithm: Algorithm, key: &[u8]) -> Result<Self, KeyError> {
        if key.len() != algorithm.key_len() {
            return Err(KeyError("invalid key length".to_string()));
        }

        let cipher = aes_siv::siv::Aes256Siv::new_from_slice(key)
            .map_err(|err| KeyError(err.to_string()))?;
        Ok(Self(cipher))
    }

    pub(super) fn encrypt_in_place<A, B>(
        &mut self,
        aad: Aad<A>,
        plaintext: &mut B,
    ) -> Result<(), EncryptDeterministicallyError>
    where
        A: AsRef<[u8]>,
        B: Buffer,
    {
        if plaintext.len() > (isize::MAX as usize) - AES_BLOCK_SIZE {
            return Err(EncryptDeterministicallyError::PlaintextTooLong);
        }
        let mut buf = RcBuffer(plaintext);
        self.0
            .encrypt_in_place([aad], &mut buf)
            .map_err(|_| EncryptDeterministicallyError::Unspecified)?;
        Ok(())
    }

    pub(super) fn decrypt_in_place<A, B>(
        &mut self,
        aad: Aad<A>,
        ciphertext: &mut B,
    ) -> Result<(), DecryptDeterministicallyError>
    where
        A: AsRef<[u8]>,
        B: Buffer,
    {
        if ciphertext.len() < aes_siv::siv::IV_SIZE {
            return Err(DecryptDeterministicallyError::CiphertextTooShort);
        }

        let mut buf = RcBuffer(ciphertext);
        self.0
            .decrypt_in_place([aad], &mut buf)
            .map_err(|_| DecryptDeterministicallyError::Unspecified)
    }
}