src/backup/data_blob.rs - DataBlobWriter: impl. encrypted blobs
This commit is contained in:
parent
c57ec43a53
commit
f4942e9ffd
@ -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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user