Files
libsignal/rust/crypto/src/aes_ctr.rs
2025-09-03 14:22:08 -04:00

47 lines
1.4 KiB
Rust

//
// Copyright 2021 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
use aes::Aes256;
use aes::cipher::typenum::Unsigned;
use aes::cipher::{InnerIvInit, KeyInit, StreamCipher, StreamCipherSeek};
use crate::error::{Error, Result};
/// A wrapper around [`ctr::Ctr32BE`] that uses a smaller nonce and supports an initial counter.
pub struct Aes256Ctr32(ctr::Ctr32BE<Aes256>);
impl Aes256Ctr32 {
pub const NONCE_SIZE: usize = <Aes256 as aes::cipher::BlockSizeUser>::BlockSize::USIZE - 4;
pub fn new(aes256: Aes256, nonce: &[u8], init_ctr: u32) -> Result<Self> {
if nonce.len() != Self::NONCE_SIZE {
return Err(Error::InvalidNonceSize);
}
let mut nonce_block = [0u8; <Aes256 as aes::cipher::BlockSizeUser>::BlockSize::USIZE];
nonce_block[0..Self::NONCE_SIZE].copy_from_slice(nonce);
let mut ctr =
ctr::Ctr32BE::from_core(ctr::CtrCore::inner_iv_init(aes256, &nonce_block.into()));
ctr.seek(
(<Aes256 as aes::cipher::BlockSizeUser>::BlockSize::USIZE as u64) * (init_ctr as u64),
);
Ok(Self(ctr))
}
pub fn from_key(key: &[u8], nonce: &[u8], init_ctr: u32) -> Result<Self> {
Self::new(
Aes256::new_from_slice(key).map_err(|_| Error::InvalidKeySize)?,
nonce,
init_ctr,
)
}
pub fn process(&mut self, buf: &mut [u8]) {
self.0.apply_keystream(buf);
}
}