use std::sync::Arc; use std::io::Write; use anyhow::Error; use pbs_tools::crypt_config::CryptConfig; pub struct CryptWriter { writer: W, block_size: usize, encr_buf: Box<[u8; 64*1024]>, iv: [u8; 16], crypter: openssl::symm::Crypter, } impl CryptWriter { pub fn new(writer: W, config: Arc) -> Result { let mut iv = [0u8; 16]; proxmox::sys::linux::fill_with_random_data(&mut iv)?; let block_size = config.cipher().block_size(); let crypter = config.data_crypter(&iv, openssl::symm::Mode::Encrypt)?; Ok(Self { writer, iv, crypter, block_size, encr_buf: Box::new([0u8; 64*1024]) }) } pub fn finish(mut self) -> Result<(W, [u8; 16], [u8; 16]), Error> { let rest = self.crypter.finalize(self.encr_buf.as_mut())?; if rest > 0 { self.writer.write_all(&self.encr_buf[..rest])?; } self.writer.flush()?; let mut tag = [0u8; 16]; self.crypter.get_tag(&mut tag)?; Ok((self.writer, self.iv, tag)) } } impl Write for CryptWriter { fn write(&mut self, buf: &[u8]) -> Result { let mut write_size = buf.len(); if write_size > (self.encr_buf.len() - self.block_size) { write_size = self.encr_buf.len() - self.block_size; } let count = self.crypter.update(&buf[..write_size], self.encr_buf.as_mut()) .map_err(|err| { std::io::Error::new( std::io::ErrorKind::Other, format!("crypter update failed - {}", err)) })?; self.writer.write_all(&self.encr_buf[..count])?; Ok(write_size) } fn flush(&mut self) -> Result<(), std::io::Error> { Ok(()) } }