]> git.proxmox.com Git - proxmox-backup.git/blob - src/backup/data_blob_reader.rs
9ae112ad51e9df19a6fc845698734bea465cf664
[proxmox-backup.git] / src / backup / data_blob_reader.rs
1 use failure::*;
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 Signed { expected_crc: u32, expected_hmac: [u8; 32], csum_reader: ChecksumReader<R> },
12 SignedCompressed { expected_crc: u32, expected_hmac: [u8; 32], decompr: zstd::stream::read::Decoder<BufReader<ChecksumReader<R>>> },
13 Encrypted { expected_crc: u32, decrypt_reader: CryptReader<BufReader<ChecksumReader<R>>> },
14 EncryptedCompressed { expected_crc: u32, decompr: zstd::stream::read::Decoder<BufReader<CryptReader<BufReader<ChecksumReader<R>>>>> },
15 }
16
17 /// Read data blobs
18 pub struct DataBlobReader<R: Read> {
19 state: BlobReaderState<R>,
20 }
21
22 impl <R: Read> DataBlobReader<R> {
23
24 pub fn new(mut reader: R, config: Option<Arc<CryptConfig>>) -> Result<Self, Error> {
25
26 let head: DataBlobHeader = unsafe { reader.read_le_value()? };
27 match head.magic {
28 UNCOMPRESSED_BLOB_MAGIC_1_0 => {
29 let expected_crc = u32::from_le_bytes(head.crc);
30 let csum_reader = ChecksumReader::new(reader, None);
31 Ok(Self { state: BlobReaderState::Uncompressed { expected_crc, csum_reader }})
32 }
33 COMPRESSED_BLOB_MAGIC_1_0 => {
34 let expected_crc = u32::from_le_bytes(head.crc);
35 let csum_reader = ChecksumReader::new(reader, None);
36
37 let decompr = zstd::stream::read::Decoder::new(csum_reader)?;
38 Ok(Self { state: BlobReaderState::Compressed { expected_crc, decompr }})
39 }
40 AUTHENTICATED_BLOB_MAGIC_1_0 => {
41 let expected_crc = u32::from_le_bytes(head.crc);
42 let mut expected_hmac = [0u8; 32];
43 reader.read_exact(&mut expected_hmac)?;
44 let csum_reader = ChecksumReader::new(reader, config);
45 Ok(Self { state: BlobReaderState::Signed { expected_crc, expected_hmac, csum_reader }})
46 }
47 AUTH_COMPR_BLOB_MAGIC_1_0 => {
48 let expected_crc = u32::from_le_bytes(head.crc);
49 let mut expected_hmac = [0u8; 32];
50 reader.read_exact(&mut expected_hmac)?;
51 let csum_reader = ChecksumReader::new(reader, config);
52
53 let decompr = zstd::stream::read::Decoder::new(csum_reader)?;
54 Ok(Self { state: BlobReaderState::SignedCompressed { expected_crc, expected_hmac, decompr }})
55 }
56 ENCRYPTED_BLOB_MAGIC_1_0 => {
57 let expected_crc = u32::from_le_bytes(head.crc);
58 let mut iv = [0u8; 16];
59 let mut expected_tag = [0u8; 16];
60 reader.read_exact(&mut iv)?;
61 reader.read_exact(&mut expected_tag)?;
62 let csum_reader = ChecksumReader::new(reader, None);
63 let decrypt_reader = CryptReader::new(BufReader::with_capacity(64*1024, csum_reader), iv, expected_tag, config.unwrap())?;
64 Ok(Self { state: BlobReaderState::Encrypted { expected_crc, decrypt_reader }})
65 }
66 ENCR_COMPR_BLOB_MAGIC_1_0 => {
67 let expected_crc = u32::from_le_bytes(head.crc);
68 let mut iv = [0u8; 16];
69 let mut expected_tag = [0u8; 16];
70 reader.read_exact(&mut iv)?;
71 reader.read_exact(&mut expected_tag)?;
72 let csum_reader = ChecksumReader::new(reader, None);
73 let decrypt_reader = CryptReader::new(BufReader::with_capacity(64*1024, csum_reader), iv, expected_tag, config.unwrap())?;
74 let decompr = zstd::stream::read::Decoder::new(decrypt_reader)?;
75 Ok(Self { state: BlobReaderState::EncryptedCompressed { expected_crc, decompr }})
76 }
77 _ => bail!("got wrong magic number {:?}", head.magic)
78 }
79 }
80
81 pub fn finish(self) -> Result<R, Error> {
82 match self.state {
83 BlobReaderState::Uncompressed { csum_reader, expected_crc } => {
84 let (reader, crc, _) = csum_reader.finish()?;
85 if crc != expected_crc {
86 bail!("blob crc check failed");
87 }
88 Ok(reader)
89 }
90 BlobReaderState::Compressed { expected_crc, decompr } => {
91 let csum_reader = decompr.finish().into_inner();
92 let (reader, crc, _) = csum_reader.finish()?;
93 if crc != expected_crc {
94 bail!("blob crc check failed");
95 }
96 Ok(reader)
97 }
98 BlobReaderState::Signed { csum_reader, expected_crc, expected_hmac } => {
99 let (reader, crc, hmac) = csum_reader.finish()?;
100 if crc != expected_crc {
101 bail!("blob crc check failed");
102 }
103 if let Some(hmac) = hmac {
104 if hmac != expected_hmac {
105 bail!("blob signature check failed");
106 }
107 }
108 Ok(reader)
109 }
110 BlobReaderState::SignedCompressed { expected_crc, expected_hmac, decompr } => {
111 let csum_reader = decompr.finish().into_inner();
112 let (reader, crc, hmac) = csum_reader.finish()?;
113 if crc != expected_crc {
114 bail!("blob crc check failed");
115 }
116 if let Some(hmac) = hmac {
117 if hmac != expected_hmac {
118 bail!("blob signature check failed");
119 }
120 }
121 Ok(reader)
122 }
123 BlobReaderState::Encrypted { expected_crc, decrypt_reader } => {
124 let csum_reader = decrypt_reader.finish()?.into_inner();
125 let (reader, crc, _) = csum_reader.finish()?;
126 if crc != expected_crc {
127 bail!("blob crc check failed");
128 }
129 Ok(reader)
130 }
131 BlobReaderState::EncryptedCompressed { expected_crc, decompr } => {
132 let decrypt_reader = decompr.finish().into_inner();
133 let csum_reader = decrypt_reader.finish()?.into_inner();
134 let (reader, crc, _) = csum_reader.finish()?;
135 if crc != expected_crc {
136 bail!("blob crc check failed");
137 }
138 Ok(reader)
139 }
140 }
141 }
142 }
143
144 impl <R: Read> Read for DataBlobReader<R> {
145
146 fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
147 match &mut self.state {
148 BlobReaderState::Uncompressed { csum_reader, .. } => {
149 csum_reader.read(buf)
150 }
151 BlobReaderState::Compressed { decompr, .. } => {
152 decompr.read(buf)
153 }
154 BlobReaderState::Signed { csum_reader, .. } => {
155 csum_reader.read(buf)
156 }
157 BlobReaderState::SignedCompressed { decompr, .. } => {
158 decompr.read(buf)
159 }
160 BlobReaderState::Encrypted { decrypt_reader, .. } => {
161 decrypt_reader.read(buf)
162 }
163 BlobReaderState::EncryptedCompressed { decompr, .. } => {
164 decompr.read(buf)
165 }
166 }
167 }
168 }