src/backup/data_blob.rs - DataBlobReader: implement reader for encrtypted blobs
This commit is contained in:
parent
d03d3fa04e
commit
2aa0bfff59
|
@ -51,6 +51,11 @@ impl CryptConfig {
|
||||||
Ok(Self { id_key, id_pkey, enc_key, cipher: Cipher::aes_256_gcm() })
|
Ok(Self { id_key, id_pkey, enc_key, cipher: Cipher::aes_256_gcm() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expose Cipher
|
||||||
|
pub fn cipher(&self) -> &Cipher {
|
||||||
|
&self.cipher
|
||||||
|
}
|
||||||
|
|
||||||
/// Compute a chunk digest using a secret name space.
|
/// Compute a chunk digest using a secret name space.
|
||||||
///
|
///
|
||||||
/// Computes an SHA256 checksum over some secret data (derived
|
/// Computes an SHA256 checksum over some secret data (derived
|
||||||
|
|
|
@ -309,6 +309,58 @@ impl DataBlob {
|
||||||
|
|
||||||
use std::io::{Read, BufRead, BufReader, Write, Seek, SeekFrom};
|
use std::io::{Read, BufRead, BufReader, Write, Seek, SeekFrom};
|
||||||
|
|
||||||
|
struct CryptReader<R> {
|
||||||
|
reader: R,
|
||||||
|
block_size: usize,
|
||||||
|
crypter: openssl::symm::Crypter,
|
||||||
|
finalized: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <R: BufRead> CryptReader<R> {
|
||||||
|
|
||||||
|
fn new(reader: R, iv: [u8; 16], tag: [u8; 16], config: &CryptConfig) -> Result<Self, Error> {
|
||||||
|
let block_size = config.cipher().block_size();
|
||||||
|
if block_size.count_ones() != 1 || block_size > 1024 {
|
||||||
|
bail!("unexpected Cipher block size {}", block_size);
|
||||||
|
}
|
||||||
|
let mut crypter = config.data_crypter(&iv, openssl::symm::Mode::Decrypt)?;
|
||||||
|
crypter.set_tag(&tag)?;
|
||||||
|
Ok(Self { reader, crypter, block_size, finalized: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(self) -> Result<R, Error> {
|
||||||
|
if !self.finalized {
|
||||||
|
bail!("CryptReader not successfully finalized.");
|
||||||
|
}
|
||||||
|
Ok(self.reader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <R: BufRead> Read for CryptReader<R> {
|
||||||
|
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
|
||||||
|
if buf.len() <= 2*self.block_size {
|
||||||
|
panic!("CryptReader read buffer too small!");
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = self.reader.fill_buf()?;
|
||||||
|
|
||||||
|
if data.len() == 0 { // EOF
|
||||||
|
let rest = self.crypter.finalize(buf)?;
|
||||||
|
self.finalized = true;
|
||||||
|
Ok(rest)
|
||||||
|
} else {
|
||||||
|
let mut read_size = buf.len() - self.block_size;
|
||||||
|
if read_size > data.len() {
|
||||||
|
read_size = data.len();
|
||||||
|
}
|
||||||
|
let count = self.crypter.update(&data[..read_size], buf)?;
|
||||||
|
self.reader.consume(read_size);
|
||||||
|
Ok(count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct CryptWriter<W> {
|
struct CryptWriter<W> {
|
||||||
writer: W,
|
writer: W,
|
||||||
encr_buf: [u8; 64*1024],
|
encr_buf: [u8; 64*1024],
|
||||||
|
@ -697,6 +749,7 @@ enum BlobReaderState<'a, R: Read> {
|
||||||
Compressed { expected_crc: u32, decompr: zstd::stream::read::Decoder<BufReader<ChecksumReader<'a, R>>> },
|
Compressed { expected_crc: u32, decompr: zstd::stream::read::Decoder<BufReader<ChecksumReader<'a, R>>> },
|
||||||
Signed { expected_crc: u32, expected_hmac: [u8; 32], csum_reader: ChecksumReader<'a, R> },
|
Signed { expected_crc: u32, expected_hmac: [u8; 32], csum_reader: ChecksumReader<'a, R> },
|
||||||
SignedCompressed { expected_crc: u32, expected_hmac: [u8; 32], decompr: zstd::stream::read::Decoder<BufReader<ChecksumReader<'a, R>>> },
|
SignedCompressed { expected_crc: u32, expected_hmac: [u8; 32], decompr: zstd::stream::read::Decoder<BufReader<ChecksumReader<'a, R>>> },
|
||||||
|
Encrypted { expected_crc: u32, decrypt_reader: CryptReader<BufReader<ChecksumReader<'a, R>>> },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read data blobs
|
/// Read data blobs
|
||||||
|
@ -740,6 +793,16 @@ impl <'a, R: Read> DataBlobReader<'a, R> {
|
||||||
let decompr = zstd::stream::read::Decoder::new(csum_reader)?;
|
let decompr = zstd::stream::read::Decoder::new(csum_reader)?;
|
||||||
Ok(Self { state: BlobReaderState::SignedCompressed { expected_crc, expected_hmac, decompr }})
|
Ok(Self { state: BlobReaderState::SignedCompressed { expected_crc, expected_hmac, decompr }})
|
||||||
}
|
}
|
||||||
|
ENCRYPTED_BLOB_MAGIC_1_0 => {
|
||||||
|
let expected_crc = u32::from_le_bytes(head.crc);
|
||||||
|
let mut iv = [0u8; 16];
|
||||||
|
let mut expected_tag = [0u8; 16];
|
||||||
|
reader.read_exact(&mut iv)?;
|
||||||
|
reader.read_exact(&mut expected_tag)?;
|
||||||
|
let csum_reader = ChecksumReader::new(reader, None);
|
||||||
|
let decrypt_reader = CryptReader::new(BufReader::with_capacity(64*1024,csum_reader), iv, expected_tag, config.unwrap())?;
|
||||||
|
Ok(Self { state: BlobReaderState::Encrypted { expected_crc, decrypt_reader }})
|
||||||
|
}
|
||||||
_ => bail!("got wrong magic number {:?}", head.magic)
|
_ => bail!("got wrong magic number {:?}", head.magic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -786,6 +849,14 @@ impl <'a, R: Read> DataBlobReader<'a, R> {
|
||||||
}
|
}
|
||||||
Ok(reader)
|
Ok(reader)
|
||||||
}
|
}
|
||||||
|
BlobReaderState::Encrypted { expected_crc, decrypt_reader } => {
|
||||||
|
let csum_reader = decrypt_reader.finish()?.into_inner();
|
||||||
|
let (reader, crc, _) = csum_reader.finish()?;
|
||||||
|
if crc != expected_crc {
|
||||||
|
bail!("blob crc check failed");
|
||||||
|
}
|
||||||
|
Ok(reader)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -806,6 +877,9 @@ impl <'a, R: BufRead> Read for DataBlobReader<'a, R> {
|
||||||
BlobReaderState::SignedCompressed { decompr, .. } => {
|
BlobReaderState::SignedCompressed { decompr, .. } => {
|
||||||
decompr.read(buf)
|
decompr.read(buf)
|
||||||
}
|
}
|
||||||
|
BlobReaderState::Encrypted { decrypt_reader, .. } => {
|
||||||
|
decrypt_reader.read(buf)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue