1 use anyhow
::{bail, format_err, Error}
;
3 use std
::io
::{Read, BufReader}
;
4 use proxmox
::tools
::io
::ReadExt
;
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>>>>> }
,
16 pub struct DataBlobReader
<R
: Read
> {
17 state
: BlobReaderState
<R
>,
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
> {}
24 impl <R
: Read
> DataBlobReader
<R
> {
26 pub fn new(mut reader
: R
, config
: Option
<Arc
<CryptConfig
>>) -> Result
<Self, Error
> {
28 let head
: DataBlobHeader
= unsafe { reader.read_le_value()? }
;
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 }
})
35 COMPRESSED_BLOB_MAGIC_1_0
=> {
36 let expected_crc
= u32::from_le_bytes(head
.crc
);
37 let csum_reader
= ChecksumReader
::new(reader
, None
);
39 let decompr
= zstd
::stream
::read
::Decoder
::new(csum_reader
)?
;
40 Ok(Self { state: BlobReaderState::Compressed { expected_crc, decompr }
})
42 ENCRYPTED_BLOB_MAGIC_1_0
=> {
43 let config
= config
.ok_or_else(|| format_err
!("unable to read encrypted blob without key"))?
;
44 let expected_crc
= u32::from_le_bytes(head
.crc
);
45 let mut iv
= [0u8; 16];
46 let mut expected_tag
= [0u8; 16];
47 reader
.read_exact(&mut iv
)?
;
48 reader
.read_exact(&mut expected_tag
)?
;
49 let csum_reader
= ChecksumReader
::new(reader
, None
);
50 let decrypt_reader
= CryptReader
::new(BufReader
::with_capacity(64*1024, csum_reader
), iv
, expected_tag
, config
)?
;
51 Ok(Self { state: BlobReaderState::Encrypted { expected_crc, decrypt_reader }
})
53 ENCR_COMPR_BLOB_MAGIC_1_0
=> {
54 let config
= config
.ok_or_else(|| format_err
!("unable to read encrypted blob without key"))?
;
55 let expected_crc
= u32::from_le_bytes(head
.crc
);
56 let mut iv
= [0u8; 16];
57 let mut expected_tag
= [0u8; 16];
58 reader
.read_exact(&mut iv
)?
;
59 reader
.read_exact(&mut expected_tag
)?
;
60 let csum_reader
= ChecksumReader
::new(reader
, None
);
61 let decrypt_reader
= CryptReader
::new(BufReader
::with_capacity(64*1024, csum_reader
), iv
, expected_tag
, config
)?
;
62 let decompr
= zstd
::stream
::read
::Decoder
::new(decrypt_reader
)?
;
63 Ok(Self { state: BlobReaderState::EncryptedCompressed { expected_crc, decompr }
})
65 _
=> bail
!("got wrong magic number {:?}", head
.magic
)
69 pub fn finish(self) -> Result
<R
, Error
> {
71 BlobReaderState
::Uncompressed { csum_reader, expected_crc }
=> {
72 let (reader
, crc
, _
) = csum_reader
.finish()?
;
73 if crc
!= expected_crc
{
74 bail
!("blob crc check failed");
78 BlobReaderState
::Compressed { expected_crc, decompr }
=> {
79 let csum_reader
= decompr
.finish().into_inner();
80 let (reader
, crc
, _
) = csum_reader
.finish()?
;
81 if crc
!= expected_crc
{
82 bail
!("blob crc check failed");
86 BlobReaderState
::Encrypted { expected_crc, decrypt_reader }
=> {
87 let csum_reader
= decrypt_reader
.finish()?
.into_inner();
88 let (reader
, crc
, _
) = csum_reader
.finish()?
;
89 if crc
!= expected_crc
{
90 bail
!("blob crc check failed");
94 BlobReaderState
::EncryptedCompressed { expected_crc, decompr }
=> {
95 let decrypt_reader
= decompr
.finish().into_inner();
96 let csum_reader
= decrypt_reader
.finish()?
.into_inner();
97 let (reader
, crc
, _
) = csum_reader
.finish()?
;
98 if crc
!= expected_crc
{
99 bail
!("blob crc check failed");
107 impl <R
: Read
> Read
for DataBlobReader
<R
> {
109 fn read(&mut self, buf
: &mut [u8]) -> Result
<usize, std
::io
::Error
> {
110 match &mut self.state
{
111 BlobReaderState
::Uncompressed { csum_reader, .. }
=> {
112 csum_reader
.read(buf
)
114 BlobReaderState
::Compressed { decompr, .. }
=> {
117 BlobReaderState
::Encrypted { decrypt_reader, .. }
=> {
118 decrypt_reader
.read(buf
)
120 BlobReaderState
::EncryptedCompressed { decompr, .. }
=> {