2019-08-16 07:19:01 +00:00
|
|
|
use std::sync::Arc;
|
2019-08-14 11:05:11 +00:00
|
|
|
use std::io::Write;
|
|
|
|
|
2020-04-17 12:11:25 +00:00
|
|
|
use anyhow::{Error};
|
2019-08-16 07:19:01 +00:00
|
|
|
|
2021-07-06 11:26:35 +00:00
|
|
|
use pbs_tools::borrow::Tied;
|
|
|
|
|
2019-08-16 07:19:01 +00:00
|
|
|
use super::CryptConfig;
|
|
|
|
|
|
|
|
pub struct ChecksumWriter<W> {
|
2019-08-14 11:05:11 +00:00
|
|
|
writer: W,
|
|
|
|
hasher: crc32fast::Hasher,
|
2019-08-16 07:19:01 +00:00
|
|
|
signer: Option<Tied<Arc<CryptConfig>, openssl::sign::Signer<'static>>>,
|
2019-08-14 11:05:11 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 07:19:01 +00:00
|
|
|
impl <W: Write> ChecksumWriter<W> {
|
2019-08-14 11:05:11 +00:00
|
|
|
|
2019-08-16 07:19:01 +00:00
|
|
|
pub fn new(writer: W, config: Option<Arc<CryptConfig>>) -> Self {
|
2019-08-14 11:05:11 +00:00
|
|
|
let hasher = crc32fast::Hasher::new();
|
2019-08-16 07:19:01 +00:00
|
|
|
let signer = match config {
|
|
|
|
Some(config) => {
|
2021-01-15 13:38:27 +00:00
|
|
|
let tied_signer = Tied::new(config, |config| {
|
2019-08-16 07:19:01 +00:00
|
|
|
Box::new(unsafe { (*config).data_signer() })
|
|
|
|
});
|
|
|
|
Some(tied_signer)
|
|
|
|
}
|
|
|
|
None => None,
|
|
|
|
};
|
2019-08-14 11:05:11 +00:00
|
|
|
Self { writer, hasher, signer }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn finish(mut self) -> Result<(W, u32, Option<[u8; 32]>), Error> {
|
|
|
|
let crc = self.hasher.finalize();
|
|
|
|
|
|
|
|
if let Some(ref mut signer) = self.signer {
|
|
|
|
let mut tag = [0u8; 32];
|
|
|
|
signer.sign(&mut tag)?;
|
|
|
|
Ok((self.writer, crc, Some(tag)))
|
|
|
|
} else {
|
|
|
|
Ok((self.writer, crc, None))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-16 07:19:01 +00:00
|
|
|
impl <W: Write> Write for ChecksumWriter<W> {
|
2019-08-14 11:05:11 +00:00
|
|
|
|
|
|
|
fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
|
|
|
|
self.hasher.update(buf);
|
|
|
|
if let Some(ref mut signer) = self.signer {
|
|
|
|
signer.update(buf)
|
|
|
|
.map_err(|err| {
|
|
|
|
std::io::Error::new(
|
|
|
|
std::io::ErrorKind::Other,
|
|
|
|
format!("hmac update failed - {}", err))
|
|
|
|
})?;
|
|
|
|
}
|
|
|
|
self.writer.write(buf)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn flush(&mut self) -> Result<(), std::io::Error> {
|
|
|
|
self.writer.flush()
|
|
|
|
}
|
|
|
|
}
|