1 use std
::io
::{BufReader, Read}
;
4 use anyhow
::{bail, format_err, Error}
;
5 use proxmox
::tools
::io
::ReadExt
;
7 use crate::checksum_reader
::ChecksumReader
;
8 use crate::crypt_config
::CryptConfig
;
9 use crate::crypt_reader
::CryptReader
;
10 use crate::file_formats
::{self, DataBlobHeader}
;
12 enum BlobReaderState
<'reader
, R
: Read
> {
15 csum_reader
: ChecksumReader
<R
>,
19 decompr
: zstd
::stream
::read
::Decoder
<'reader
, BufReader
<ChecksumReader
<R
>>>,
23 decrypt_reader
: CryptReader
<BufReader
<ChecksumReader
<R
>>>,
27 decompr
: zstd
::stream
::read
::Decoder
<
29 BufReader
<CryptReader
<BufReader
<ChecksumReader
<R
>>>>,
35 pub struct DataBlobReader
<'reader
, R
: Read
> {
36 state
: BlobReaderState
<'reader
, R
>,
39 // zstd_safe::DCtx is not sync but we are, since
40 // the only public interface is on mutable reference
41 unsafe impl<R
: Read
> Sync
for DataBlobReader
<'_
, R
> {}
43 impl<R
: Read
> DataBlobReader
<'_
, R
> {
44 pub fn new(mut reader
: R
, config
: Option
<Arc
<CryptConfig
>>) -> Result
<Self, Error
> {
45 let head
: DataBlobHeader
= unsafe { reader.read_le_value()? }
;
47 file_formats
::UNCOMPRESSED_BLOB_MAGIC_1_0
=> {
48 let expected_crc
= u32::from_le_bytes(head
.crc
);
49 let csum_reader
= ChecksumReader
::new(reader
, None
);
51 state
: BlobReaderState
::Uncompressed
{
57 file_formats
::COMPRESSED_BLOB_MAGIC_1_0
=> {
58 let expected_crc
= u32::from_le_bytes(head
.crc
);
59 let csum_reader
= ChecksumReader
::new(reader
, None
);
61 let decompr
= zstd
::stream
::read
::Decoder
::new(csum_reader
)?
;
63 state
: BlobReaderState
::Compressed
{
69 file_formats
::ENCRYPTED_BLOB_MAGIC_1_0
=> {
71 .ok_or_else(|| format_err
!("unable to read encrypted blob without key"))?
;
72 let expected_crc
= u32::from_le_bytes(head
.crc
);
73 let mut iv
= [0u8; 16];
74 let mut expected_tag
= [0u8; 16];
75 reader
.read_exact(&mut iv
)?
;
76 reader
.read_exact(&mut expected_tag
)?
;
77 let csum_reader
= ChecksumReader
::new(reader
, None
);
78 let decrypt_reader
= CryptReader
::new(
79 BufReader
::with_capacity(64 * 1024, csum_reader
),
85 state
: BlobReaderState
::Encrypted
{
91 file_formats
::ENCR_COMPR_BLOB_MAGIC_1_0
=> {
93 .ok_or_else(|| format_err
!("unable to read encrypted blob without key"))?
;
94 let expected_crc
= u32::from_le_bytes(head
.crc
);
95 let mut iv
= [0u8; 16];
96 let mut expected_tag
= [0u8; 16];
97 reader
.read_exact(&mut iv
)?
;
98 reader
.read_exact(&mut expected_tag
)?
;
99 let csum_reader
= ChecksumReader
::new(reader
, None
);
100 let decrypt_reader
= CryptReader
::new(
101 BufReader
::with_capacity(64 * 1024, csum_reader
),
106 let decompr
= zstd
::stream
::read
::Decoder
::new(decrypt_reader
)?
;
108 state
: BlobReaderState
::EncryptedCompressed
{
114 _
=> bail
!("got wrong magic number {:?}", head
.magic
),
118 pub fn finish(self) -> Result
<R
, Error
> {
120 BlobReaderState
::Uncompressed
{
124 let (reader
, crc
, _
) = csum_reader
.finish()?
;
125 if crc
!= expected_crc
{
126 bail
!("blob crc check failed");
130 BlobReaderState
::Compressed
{
134 let csum_reader
= decompr
.finish().into_inner();
135 let (reader
, crc
, _
) = csum_reader
.finish()?
;
136 if crc
!= expected_crc
{
137 bail
!("blob crc check failed");
141 BlobReaderState
::Encrypted
{
145 let csum_reader
= decrypt_reader
.finish()?
.into_inner();
146 let (reader
, crc
, _
) = csum_reader
.finish()?
;
147 if crc
!= expected_crc
{
148 bail
!("blob crc check failed");
152 BlobReaderState
::EncryptedCompressed
{
156 let decrypt_reader
= decompr
.finish().into_inner();
157 let csum_reader
= decrypt_reader
.finish()?
.into_inner();
158 let (reader
, crc
, _
) = csum_reader
.finish()?
;
159 if crc
!= expected_crc
{
160 bail
!("blob crc check failed");
168 impl<R
: Read
> Read
for DataBlobReader
<'_
, R
> {
169 fn read(&mut self, buf
: &mut [u8]) -> Result
<usize, std
::io
::Error
> {
170 match &mut self.state
{
171 BlobReaderState
::Uncompressed { csum_reader, .. }
=> csum_reader
.read(buf
),
172 BlobReaderState
::Compressed { decompr, .. }
=> decompr
.read(buf
),
173 BlobReaderState
::Encrypted { decrypt_reader, .. }
=> decrypt_reader
.read(buf
),
174 BlobReaderState
::EncryptedCompressed { decompr, .. }
=> decompr
.read(buf
),