src/backup/data_blob.rs - DataBlobWriter: impl. encrypted blobs

This commit is contained in:
Dietmar Maurer 2019-08-12 10:08:00 +02:00
parent c57ec43a53
commit f4942e9ffd

View File

@ -294,6 +294,59 @@ impl DataBlob {
use std::io::{Read, BufRead, Write, Seek, SeekFrom}; use std::io::{Read, BufRead, Write, Seek, SeekFrom};
struct CryptWriter<W> {
writer: W,
encr_buf: [u8; 64*1024],
iv: [u8; 16],
crypter: openssl::symm::Crypter,
}
impl <W: Write> CryptWriter<W> {
fn new(writer: W, config: &CryptConfig) -> Result<Self, Error> {
let mut iv = [0u8; 16];
proxmox::sys::linux::fill_with_random_data(&mut iv)?;
let crypter = config.data_crypter(&iv)?;
Ok(Self { writer, iv, crypter, encr_buf: [0u8; 64*1024] })
}
fn finish(mut self) -> Result<(W, [u8; 16], [u8; 16]), Error> {
let rest = self.crypter.finalize(&mut self.encr_buf)?;
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 <W: Write> Write for CryptWriter<W> {
fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
let count = self.crypter.update(buf, &mut self.encr_buf)
.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(count)
}
fn flush(&mut self) -> Result<(), std::io::Error> {
Ok(())
}
}
struct ChecksumWriter<'a, W> { struct ChecksumWriter<'a, W> {
writer: W, writer: W,
hasher: crc32fast::Hasher, hasher: crc32fast::Hasher,
@ -325,8 +378,8 @@ impl <'a, W: Write> Write for ChecksumWriter<'a, W> {
fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> { fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
self.hasher.update(buf); self.hasher.update(buf);
if let Some(ref mut signer) = self.signer { if let Some(ref mut signer) = self.signer {
signer.update(buf). signer.update(buf)
map_err(|err| { .map_err(|err| {
std::io::Error::new( std::io::Error::new(
std::io::ErrorKind::Other, std::io::ErrorKind::Other,
format!("hmac update failed - {}", err)) format!("hmac update failed - {}", err))
@ -345,6 +398,7 @@ enum BlobWriterState<'a, W: Write> {
Compressed { compr: zstd::stream::write::Encoder<ChecksumWriter<'a, W>> }, Compressed { compr: zstd::stream::write::Encoder<ChecksumWriter<'a, W>> },
Signed { csum_writer: ChecksumWriter<'a, W> }, Signed { csum_writer: ChecksumWriter<'a, W> },
SignedCompressed { compr: zstd::stream::write::Encoder<ChecksumWriter<'a, W>> }, SignedCompressed { compr: zstd::stream::write::Encoder<ChecksumWriter<'a, W>> },
Encrypted { crypt_writer: CryptWriter<ChecksumWriter<'a, W>> },
} }
/// Write compressed data blobs /// Write compressed data blobs
@ -404,6 +458,22 @@ impl <'a, W: Write + Seek> DataBlobWriter<'a, W> {
Ok(Self { state: BlobWriterState::SignedCompressed { compr }}) Ok(Self { state: BlobWriterState::SignedCompressed { compr }})
} }
pub fn new_encrypted(mut writer: W, config: &'a CryptConfig) -> Result<Self, Error> {
writer.seek(SeekFrom::Start(0))?;
let head = EncryptedDataBlobHeader {
head: DataBlobHeader { magic: ENCRYPTED_BLOB_MAGIC_1_0, crc: [0; 4] },
iv: [0u8; 16],
tag: [0u8; 16],
};
unsafe {
writer.write_le_value(head)?;
}
let csum_writer = ChecksumWriter::new(writer, None);
let crypt_writer = CryptWriter::new(csum_writer, config)?;
Ok(Self { state: BlobWriterState::Encrypted { crypt_writer }})
}
pub fn finish(self) -> Result<W, Error> { pub fn finish(self) -> Result<W, Error> {
match self.state { match self.state {
BlobWriterState::Uncompressed { csum_writer } => { BlobWriterState::Uncompressed { csum_writer } => {
@ -462,6 +532,19 @@ impl <'a, W: Write + Seek> DataBlobWriter<'a, W> {
return Ok(writer) return Ok(writer)
} }
BlobWriterState::Encrypted { crypt_writer } => {
let (csum_writer, iv, tag) = crypt_writer.finish()?;
let (mut writer, crc, _) = csum_writer.finish()?;
let head = EncryptedDataBlobHeader {
head: DataBlobHeader { magic: ENCRYPTED_BLOB_MAGIC_1_0, crc: crc.to_le_bytes() },
iv, tag,
};
unsafe {
writer.write_le_value(head)?;
}
return Ok(writer)
}
} }
} }
} }
@ -482,6 +565,9 @@ impl <'a, W: Write + Seek> Write for DataBlobWriter<'a, W> {
BlobWriterState::SignedCompressed { ref mut compr } => { BlobWriterState::SignedCompressed { ref mut compr } => {
compr.write(buf) compr.write(buf)
} }
BlobWriterState::Encrypted { ref mut crypt_writer } => {
crypt_writer.write(buf)
}
} }
} }
@ -499,6 +585,9 @@ impl <'a, W: Write + Seek> Write for DataBlobWriter<'a, W> {
BlobWriterState::SignedCompressed { ref mut compr } => { BlobWriterState::SignedCompressed { ref mut compr } => {
compr.flush() compr.flush()
} }
BlobWriterState::Encrypted { ref mut crypt_writer } => {
crypt_writer.flush()
}
} }
} }
} }