]>
Commit | Line | Data |
---|---|---|
f7d4e4b5 | 1 | use anyhow::{bail, Error}; |
9025312a | 2 | use std::sync::Arc; |
018d11bb DM |
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 | ||
9025312a | 17 | pub fn new(reader: R, iv: [u8; 16], tag: [u8; 16], config: Arc<CryptConfig>) -> Result<Self, Error> { |
018d11bb DM |
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.len() > 0 { | |
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.len() == 0 { // 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(); | |
834a2f95 | 70 | Ok(buf.len()) |
018d11bb DM |
71 | } else { |
72 | buf[..count].copy_from_slice(&outbuf[..count]); | |
834a2f95 | 73 | Ok(count) |
018d11bb | 74 | } |
834a2f95 DM |
75 | } else if data.len() == 0 { // EOF |
76 | let rest = self.crypter.finalize(buf)?; | |
77 | self.finalized = true; | |
78 | Ok(rest) | |
018d11bb | 79 | } else { |
834a2f95 DM |
80 | let mut read_size = buf.len() - self.block_size; |
81 | if read_size > data.len() { | |
82 | read_size = data.len(); | |
018d11bb | 83 | } |
834a2f95 DM |
84 | let count = self.crypter.update(&data[..read_size], buf)?; |
85 | self.reader.consume(read_size); | |
86 | Ok(count) | |
018d11bb DM |
87 | } |
88 | } | |
89 | } |