]> git.proxmox.com Git - proxmox-backup.git/blob - src/backup/crypt_reader.rs
api2/admin/datastore: refactor list_dir_content in catalog_reader
[proxmox-backup.git] / src / backup / crypt_reader.rs
1 use anyhow::{bail, Error};
2 use std::sync::Arc;
3 use std::io::{Read, BufRead};
4
5 use super::CryptConfig;
6
7 pub struct CryptReader<R> {
8 reader: R,
9 small_read_buf: Vec<u8>,
10 block_size: usize,
11 crypter: openssl::symm::Crypter,
12 finalized: bool,
13 }
14
15 impl <R: BufRead> CryptReader<R> {
16
17 pub fn new(reader: R, iv: [u8; 16], tag: [u8; 16], config: Arc<CryptConfig>) -> Result<Self, Error> {
18 let block_size = config.cipher().block_size(); // Note: block size is normally 1 byte for stream ciphers
19 if block_size.count_ones() != 1 || block_size > 512 {
20 bail!("unexpected Cipher block size {}", block_size);
21 }
22 let mut crypter = config.data_crypter(&iv, openssl::symm::Mode::Decrypt)?;
23 crypter.set_tag(&tag)?;
24
25 Ok(Self { reader, crypter, block_size, finalized: false, small_read_buf: Vec::new() })
26 }
27
28 pub fn finish(self) -> Result<R, Error> {
29 if !self.finalized {
30 bail!("CryptReader not successfully finalized.");
31 }
32 Ok(self.reader)
33 }
34 }
35
36 impl <R: BufRead> Read for CryptReader<R> {
37
38 fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
39 if !self.small_read_buf.is_empty() {
40 let max = if self.small_read_buf.len() > buf.len() { buf.len() } else { self.small_read_buf.len() };
41 let rest = self.small_read_buf.split_off(max);
42 buf[..max].copy_from_slice(&self.small_read_buf);
43 self.small_read_buf = rest;
44 return Ok(max);
45 }
46
47 let data = self.reader.fill_buf()?;
48
49 // handle small read buffers
50 if buf.len() <= 2*self.block_size {
51 let mut outbuf = [0u8; 1024];
52
53 let count = if data.is_empty() { // EOF
54 let written = self.crypter.finalize(&mut outbuf)?;
55 self.finalized = true;
56 written
57 } else {
58 let mut read_size = outbuf.len() - self.block_size;
59 if read_size > data.len() {
60 read_size = data.len();
61 }
62 let written = self.crypter.update(&data[..read_size], &mut outbuf)?;
63 self.reader.consume(read_size);
64 written
65 };
66
67 if count > buf.len() {
68 buf.copy_from_slice(&outbuf[..buf.len()]);
69 self.small_read_buf = outbuf[buf.len()..count].to_vec();
70 Ok(buf.len())
71 } else {
72 buf[..count].copy_from_slice(&outbuf[..count]);
73 Ok(count)
74 }
75 } else if data.is_empty() { // EOF
76 let rest = self.crypter.finalize(buf)?;
77 self.finalized = true;
78 Ok(rest)
79 } else {
80 let mut read_size = buf.len() - self.block_size;
81 if read_size > data.len() {
82 read_size = data.len();
83 }
84 let count = self.crypter.update(&data[..read_size], buf)?;
85 self.reader.consume(read_size);
86 Ok(count)
87 }
88 }
89 }