1 use std
::io
::{BufReader, Read}
;
4 use anyhow
::{bail, format_err, Error}
;
5 use proxmox
::tools
::io
::ReadExt
;
7 use pbs_tools
::crypt_config
::CryptConfig
;
9 use crate::checksum_reader
::ChecksumReader
;
10 use crate::crypt_reader
::CryptReader
;
11 use crate::file_formats
::{self, DataBlobHeader}
;
13 enum BlobReaderState
<'reader
, R
: Read
> {
16 csum_reader
: ChecksumReader
<R
>,
20 decompr
: zstd
::stream
::read
::Decoder
<'reader
, BufReader
<ChecksumReader
<R
>>>,
24 decrypt_reader
: CryptReader
<BufReader
<ChecksumReader
<R
>>>,
28 decompr
: zstd
::stream
::read
::Decoder
<
30 BufReader
<CryptReader
<BufReader
<ChecksumReader
<R
>>>>,
36 pub struct DataBlobReader
<'reader
, R
: Read
> {
37 state
: BlobReaderState
<'reader
, R
>,
40 // zstd_safe::DCtx is not sync but we are, since
41 // the only public interface is on mutable reference
42 unsafe impl<R
: Read
> Sync
for DataBlobReader
<'_
, R
> {}
44 impl<R
: Read
> DataBlobReader
<'_
, R
> {
45 pub fn new(mut reader
: R
, config
: Option
<Arc
<CryptConfig
>>) -> Result
<Self, Error
> {
46 let head
: DataBlobHeader
= unsafe { reader.read_le_value()? }
;
48 file_formats
::UNCOMPRESSED_BLOB_MAGIC_1_0
=> {
49 let expected_crc
= u32::from_le_bytes(head
.crc
);
50 let csum_reader
= ChecksumReader
::new(reader
, None
);
52 state
: BlobReaderState
::Uncompressed
{
58 file_formats
::COMPRESSED_BLOB_MAGIC_1_0
=> {
59 let expected_crc
= u32::from_le_bytes(head
.crc
);
60 let csum_reader
= ChecksumReader
::new(reader
, None
);
62 let decompr
= zstd
::stream
::read
::Decoder
::new(csum_reader
)?
;
64 state
: BlobReaderState
::Compressed
{
70 file_formats
::ENCRYPTED_BLOB_MAGIC_1_0
=> {
72 .ok_or_else(|| format_err
!("unable to read encrypted blob without key"))?
;
73 let expected_crc
= u32::from_le_bytes(head
.crc
);
74 let mut iv
= [0u8; 16];
75 let mut expected_tag
= [0u8; 16];
76 reader
.read_exact(&mut iv
)?
;
77 reader
.read_exact(&mut expected_tag
)?
;
78 let csum_reader
= ChecksumReader
::new(reader
, None
);
79 let decrypt_reader
= CryptReader
::new(
80 BufReader
::with_capacity(64 * 1024, csum_reader
),
86 state
: BlobReaderState
::Encrypted
{
92 file_formats
::ENCR_COMPR_BLOB_MAGIC_1_0
=> {
94 .ok_or_else(|| format_err
!("unable to read encrypted blob without key"))?
;
95 let expected_crc
= u32::from_le_bytes(head
.crc
);
96 let mut iv
= [0u8; 16];
97 let mut expected_tag
= [0u8; 16];
98 reader
.read_exact(&mut iv
)?
;
99 reader
.read_exact(&mut expected_tag
)?
;
100 let csum_reader
= ChecksumReader
::new(reader
, None
);
101 let decrypt_reader
= CryptReader
::new(
102 BufReader
::with_capacity(64 * 1024, csum_reader
),
107 let decompr
= zstd
::stream
::read
::Decoder
::new(decrypt_reader
)?
;
109 state
: BlobReaderState
::EncryptedCompressed
{
115 _
=> bail
!("got wrong magic number {:?}", head
.magic
),
119 pub fn finish(self) -> Result
<R
, Error
> {
121 BlobReaderState
::Uncompressed
{
125 let (reader
, crc
, _
) = csum_reader
.finish()?
;
126 if crc
!= expected_crc
{
127 bail
!("blob crc check failed");
131 BlobReaderState
::Compressed
{
135 let csum_reader
= decompr
.finish().into_inner();
136 let (reader
, crc
, _
) = csum_reader
.finish()?
;
137 if crc
!= expected_crc
{
138 bail
!("blob crc check failed");
142 BlobReaderState
::Encrypted
{
146 let csum_reader
= decrypt_reader
.finish()?
.into_inner();
147 let (reader
, crc
, _
) = csum_reader
.finish()?
;
148 if crc
!= expected_crc
{
149 bail
!("blob crc check failed");
153 BlobReaderState
::EncryptedCompressed
{
157 let decrypt_reader
= decompr
.finish().into_inner();
158 let csum_reader
= decrypt_reader
.finish()?
.into_inner();
159 let (reader
, crc
, _
) = csum_reader
.finish()?
;
160 if crc
!= expected_crc
{
161 bail
!("blob crc check failed");
169 impl<R
: Read
> Read
for DataBlobReader
<'_
, R
> {
170 fn read(&mut self, buf
: &mut [u8]) -> Result
<usize, std
::io
::Error
> {
171 match &mut self.state
{
172 BlobReaderState
::Uncompressed { csum_reader, .. }
=> csum_reader
.read(buf
),
173 BlobReaderState
::Compressed { decompr, .. }
=> decompr
.read(buf
),
174 BlobReaderState
::Encrypted { decrypt_reader, .. }
=> decrypt_reader
.read(buf
),
175 BlobReaderState
::EncryptedCompressed { decompr, .. }
=> decompr
.read(buf
),