1 use std
::io
::{BufReader, Read}
;
4 use anyhow
::{bail, format_err, Error}
;
6 use proxmox_io
::ReadExt
;
8 use pbs_tools
::crypt_config
::CryptConfig
;
10 use crate::checksum_reader
::ChecksumReader
;
11 use crate::crypt_reader
::CryptReader
;
12 use crate::file_formats
::{self, DataBlobHeader}
;
14 enum BlobReaderState
<'reader
, R
: Read
> {
17 csum_reader
: ChecksumReader
<R
>,
21 decompr
: zstd
::stream
::read
::Decoder
<'reader
, BufReader
<ChecksumReader
<R
>>>,
25 decrypt_reader
: CryptReader
<BufReader
<ChecksumReader
<R
>>>,
29 decompr
: zstd
::stream
::read
::Decoder
<
31 BufReader
<CryptReader
<BufReader
<ChecksumReader
<R
>>>>,
37 pub struct DataBlobReader
<'reader
, R
: Read
> {
38 state
: BlobReaderState
<'reader
, R
>,
41 // zstd_safe::DCtx is not sync but we are, since
42 // the only public interface is on mutable reference
43 unsafe impl<R
: Read
> Sync
for DataBlobReader
<'_
, R
> {}
45 impl<R
: Read
> DataBlobReader
<'_
, R
> {
46 pub fn new(mut reader
: R
, config
: Option
<Arc
<CryptConfig
>>) -> Result
<Self, Error
> {
47 let head
: DataBlobHeader
= unsafe { reader.read_le_value()? }
;
49 file_formats
::UNCOMPRESSED_BLOB_MAGIC_1_0
=> {
50 let expected_crc
= u32::from_le_bytes(head
.crc
);
51 let csum_reader
= ChecksumReader
::new(reader
, None
);
53 state
: BlobReaderState
::Uncompressed
{
59 file_formats
::COMPRESSED_BLOB_MAGIC_1_0
=> {
60 let expected_crc
= u32::from_le_bytes(head
.crc
);
61 let csum_reader
= ChecksumReader
::new(reader
, None
);
63 let decompr
= zstd
::stream
::read
::Decoder
::new(csum_reader
)?
;
65 state
: BlobReaderState
::Compressed
{
71 file_formats
::ENCRYPTED_BLOB_MAGIC_1_0
=> {
73 .ok_or_else(|| format_err
!("unable to read encrypted blob without key"))?
;
74 let expected_crc
= u32::from_le_bytes(head
.crc
);
75 let mut iv
= [0u8; 16];
76 let mut expected_tag
= [0u8; 16];
77 reader
.read_exact(&mut iv
)?
;
78 reader
.read_exact(&mut expected_tag
)?
;
79 let csum_reader
= ChecksumReader
::new(reader
, None
);
80 let decrypt_reader
= CryptReader
::new(
81 BufReader
::with_capacity(64 * 1024, csum_reader
),
87 state
: BlobReaderState
::Encrypted
{
93 file_formats
::ENCR_COMPR_BLOB_MAGIC_1_0
=> {
95 .ok_or_else(|| format_err
!("unable to read encrypted blob without key"))?
;
96 let expected_crc
= u32::from_le_bytes(head
.crc
);
97 let mut iv
= [0u8; 16];
98 let mut expected_tag
= [0u8; 16];
99 reader
.read_exact(&mut iv
)?
;
100 reader
.read_exact(&mut expected_tag
)?
;
101 let csum_reader
= ChecksumReader
::new(reader
, None
);
102 let decrypt_reader
= CryptReader
::new(
103 BufReader
::with_capacity(64 * 1024, csum_reader
),
108 let decompr
= zstd
::stream
::read
::Decoder
::new(decrypt_reader
)?
;
110 state
: BlobReaderState
::EncryptedCompressed
{
116 _
=> bail
!("got wrong magic number {:?}", head
.magic
),
120 pub fn finish(self) -> Result
<R
, Error
> {
122 BlobReaderState
::Uncompressed
{
126 let (reader
, crc
, _
) = csum_reader
.finish()?
;
127 if crc
!= expected_crc
{
128 bail
!("blob crc check failed");
132 BlobReaderState
::Compressed
{
136 let csum_reader
= decompr
.finish().into_inner();
137 let (reader
, crc
, _
) = csum_reader
.finish()?
;
138 if crc
!= expected_crc
{
139 bail
!("blob crc check failed");
143 BlobReaderState
::Encrypted
{
147 let csum_reader
= decrypt_reader
.finish()?
.into_inner();
148 let (reader
, crc
, _
) = csum_reader
.finish()?
;
149 if crc
!= expected_crc
{
150 bail
!("blob crc check failed");
154 BlobReaderState
::EncryptedCompressed
{
158 let decrypt_reader
= decompr
.finish().into_inner();
159 let csum_reader
= decrypt_reader
.finish()?
.into_inner();
160 let (reader
, crc
, _
) = csum_reader
.finish()?
;
161 if crc
!= expected_crc
{
162 bail
!("blob crc check failed");
170 impl<R
: Read
> Read
for DataBlobReader
<'_
, R
> {
171 fn read(&mut self, buf
: &mut [u8]) -> Result
<usize, std
::io
::Error
> {
172 match &mut self.state
{
173 BlobReaderState
::Uncompressed { csum_reader, .. }
=> csum_reader
.read(buf
),
174 BlobReaderState
::Compressed { decompr, .. }
=> decompr
.read(buf
),
175 BlobReaderState
::Encrypted { decrypt_reader, .. }
=> decrypt_reader
.read(buf
),
176 BlobReaderState
::EncryptedCompressed { decompr, .. }
=> decompr
.read(buf
),