]> git.proxmox.com Git - proxmox-backup.git/blob - src/backup/data_blob_reader.rs
src/backup/file_formats.rs: remove signed chunks
[proxmox-backup.git] / src / backup / data_blob_reader.rs
1 use anyhow::{bail, Error};
2 use std::sync::Arc;
3 use std::io::{Read, BufReader};
4 use proxmox::tools::io::ReadExt;
5
6 use super::*;
7
8 enum BlobReaderState<R: Read> {
9 Uncompressed { expected_crc: u32, csum_reader: ChecksumReader<R> },
10 Compressed { expected_crc: u32, decompr: zstd::stream::read::Decoder<BufReader<ChecksumReader<R>>> },
11 Encrypted { expected_crc: u32, decrypt_reader: CryptReader<BufReader<ChecksumReader<R>>> },
12 EncryptedCompressed { expected_crc: u32, decompr: zstd::stream::read::Decoder<BufReader<CryptReader<BufReader<ChecksumReader<R>>>>> },
13 }
14
15 /// Read data blobs
16 pub struct DataBlobReader<R: Read> {
17 state: BlobReaderState<R>,
18 }
19
20 // zstd_safe::DCtx is not sync but we are, since
21 // the only public interface is on mutable reference
22 unsafe impl<R: Read> Sync for DataBlobReader<R> {}
23
24 impl <R: Read> DataBlobReader<R> {
25
26 pub fn new(mut reader: R, config: Option<Arc<CryptConfig>>) -> Result<Self, Error> {
27
28 let head: DataBlobHeader = unsafe { reader.read_le_value()? };
29 match head.magic {
30 UNCOMPRESSED_BLOB_MAGIC_1_0 => {
31 let expected_crc = u32::from_le_bytes(head.crc);
32 let csum_reader = ChecksumReader::new(reader, None);
33 Ok(Self { state: BlobReaderState::Uncompressed { expected_crc, csum_reader }})
34 }
35 COMPRESSED_BLOB_MAGIC_1_0 => {
36 let expected_crc = u32::from_le_bytes(head.crc);
37 let csum_reader = ChecksumReader::new(reader, None);
38
39 let decompr = zstd::stream::read::Decoder::new(csum_reader)?;
40 Ok(Self { state: BlobReaderState::Compressed { expected_crc, decompr }})
41 }
42 ENCRYPTED_BLOB_MAGIC_1_0 => {
43 let expected_crc = u32::from_le_bytes(head.crc);
44 let mut iv = [0u8; 16];
45 let mut expected_tag = [0u8; 16];
46 reader.read_exact(&mut iv)?;
47 reader.read_exact(&mut expected_tag)?;
48 let csum_reader = ChecksumReader::new(reader, None);
49 let decrypt_reader = CryptReader::new(BufReader::with_capacity(64*1024, csum_reader), iv, expected_tag, config.unwrap())?;
50 Ok(Self { state: BlobReaderState::Encrypted { expected_crc, decrypt_reader }})
51 }
52 ENCR_COMPR_BLOB_MAGIC_1_0 => {
53 let expected_crc = u32::from_le_bytes(head.crc);
54 let mut iv = [0u8; 16];
55 let mut expected_tag = [0u8; 16];
56 reader.read_exact(&mut iv)?;
57 reader.read_exact(&mut expected_tag)?;
58 let csum_reader = ChecksumReader::new(reader, None);
59 let decrypt_reader = CryptReader::new(BufReader::with_capacity(64*1024, csum_reader), iv, expected_tag, config.unwrap())?;
60 let decompr = zstd::stream::read::Decoder::new(decrypt_reader)?;
61 Ok(Self { state: BlobReaderState::EncryptedCompressed { expected_crc, decompr }})
62 }
63 _ => bail!("got wrong magic number {:?}", head.magic)
64 }
65 }
66
67 pub fn finish(self) -> Result<R, Error> {
68 match self.state {
69 BlobReaderState::Uncompressed { csum_reader, expected_crc } => {
70 let (reader, crc, _) = csum_reader.finish()?;
71 if crc != expected_crc {
72 bail!("blob crc check failed");
73 }
74 Ok(reader)
75 }
76 BlobReaderState::Compressed { expected_crc, decompr } => {
77 let csum_reader = decompr.finish().into_inner();
78 let (reader, crc, _) = csum_reader.finish()?;
79 if crc != expected_crc {
80 bail!("blob crc check failed");
81 }
82 Ok(reader)
83 }
84 BlobReaderState::Encrypted { expected_crc, decrypt_reader } => {
85 let csum_reader = decrypt_reader.finish()?.into_inner();
86 let (reader, crc, _) = csum_reader.finish()?;
87 if crc != expected_crc {
88 bail!("blob crc check failed");
89 }
90 Ok(reader)
91 }
92 BlobReaderState::EncryptedCompressed { expected_crc, decompr } => {
93 let decrypt_reader = decompr.finish().into_inner();
94 let csum_reader = decrypt_reader.finish()?.into_inner();
95 let (reader, crc, _) = csum_reader.finish()?;
96 if crc != expected_crc {
97 bail!("blob crc check failed");
98 }
99 Ok(reader)
100 }
101 }
102 }
103 }
104
105 impl <R: Read> Read for DataBlobReader<R> {
106
107 fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
108 match &mut self.state {
109 BlobReaderState::Uncompressed { csum_reader, .. } => {
110 csum_reader.read(buf)
111 }
112 BlobReaderState::Compressed { decompr, .. } => {
113 decompr.read(buf)
114 }
115 BlobReaderState::Encrypted { decrypt_reader, .. } => {
116 decrypt_reader.read(buf)
117 }
118 BlobReaderState::EncryptedCompressed { decompr, .. } => {
119 decompr.read(buf)
120 }
121 }
122 }
123 }