use crate::aliases::{Block16, Trailer32};
use crate::decryption::stream::context::DecryptionContext;
use crate::error::AescryptError;
use secure_gate::{ConstantTimeEq, RevealSecret, RevealSecretMut};
use std::io::Write;
#[inline(always)]
pub fn extract_hmac_simple(ctx: &DecryptionContext) -> Trailer32 {
let mut expected = Trailer32::new([0u8; 32]);
ctx.ring_buffer.with_secret(|ring| {
expected.with_secret_mut(|e| {
for (i, byte) in e.iter_mut().enumerate() {
*byte = ring[(ctx.tail_index + i) % 64];
}
});
});
expected
}
#[inline(always)]
pub fn extract_hmac_scattered(ctx: &DecryptionContext) -> (Trailer32, u8) {
let mut expected = Trailer32::new([0u8; 32]);
let modulo_byte = ctx.ring_buffer.with_secret(|ring| {
expected.with_secret_mut(|e| {
for (i, byte) in e.iter_mut().enumerate() {
*byte = ring[(ctx.tail_index + 1 + i) % 64];
}
});
ring[ctx.tail_index]
});
(expected, modulo_byte)
}
#[inline(always)]
pub fn write_final_modulo<W: Write>(
ctx: &DecryptionContext,
output: &mut W,
modulo: u8,
) -> Result<(), AescryptError> {
if ctx.need_write_plaintext {
let len = if (modulo & 0x0F) == 0 {
16
} else {
(modulo & 0x0F) as usize
};
ctx.plaintext_block
.with_secret(|pb| output.write_all(&pb[..len]))?;
}
Ok(())
}
#[inline(always)]
pub fn write_final_pkcs7<W: Write>(
ctx: &DecryptionContext,
output: &mut W,
) -> Result<(), AescryptError> {
if !ctx.need_write_plaintext {
return Err(AescryptError::Header(
"v3: missing final plaintext block".into(),
));
}
let padding = ctx.plaintext_block.with_secret(|block| block[15]);
if padding == 0 || padding > 16 {
return Err(AescryptError::Header("v3: invalid PKCS#7 padding".into()));
}
let padding_start = 16 - padding as usize;
let mut expected_block = [0u8; 16];
ctx.plaintext_block.with_secret(|block| {
expected_block[..padding_start].copy_from_slice(&block[..padding_start]);
});
expected_block[padding_start..].fill(padding);
let expected_fixed = Block16::from(expected_block);
let padding_valid = ctx.plaintext_block.ct_eq(&expected_fixed);
if !padding_valid {
return Err(AescryptError::Header("v3: invalid PKCS#7 padding".into()));
}
ctx.plaintext_block
.with_secret(|block| output.write_all(&block[..16 - padding as usize]))?;
Ok(())
}