]>
Commit | Line | Data |
---|---|---|
018d11bb | 1 | use failure::*; |
9025312a | 2 | use std::sync::Arc; |
71d08e00 | 3 | use std::io::{Read, BufReader}; |
018d11bb DM |
4 | use proxmox::tools::io::ReadExt; |
5 | ||
6 | use super::*; | |
7 | ||
9025312a WB |
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>>>>> }, | |
018d11bb DM |
15 | } |
16 | ||
17 | /// Read data blobs | |
9025312a WB |
18 | pub struct DataBlobReader<R: Read> { |
19 | state: BlobReaderState<R>, | |
018d11bb DM |
20 | } |
21 | ||
9025312a | 22 | impl <R: Read> DataBlobReader<R> { |
018d11bb | 23 | |
9025312a | 24 | pub fn new(mut reader: R, config: Option<Arc<CryptConfig>>) -> Result<Self, Error> { |
018d11bb DM |
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)?; | |
9025312a | 44 | let csum_reader = ChecksumReader::new(reader, config); |
018d11bb DM |
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)?; | |
9025312a | 51 | let csum_reader = ChecksumReader::new(reader, config); |
018d11bb DM |
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 | ||
9025312a | 144 | impl <R: Read> Read for DataBlobReader<R> { |
018d11bb DM |
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 | } |