1use crate::CHUNK_SIZE;
2use crossbeam::channel::Sender;
3
4use std::fs::File;
5use std::io::{self, BufReader, Read, Result};
6
7use aes_gcm_stream::Aes256GcmStreamDecryptor;
8use zeroize::Zeroize;
9
10pub fn read_loop(
11 infile: &str,
12 stats_tx: Sender<usize>,
13 write_tx: Sender<Vec<u8>>,
14 deccode: &str,
15) -> Result<()> {
16 let mut reader: Box<dyn Read> = if !infile.is_empty() {
17 Box::new(BufReader::new(File::open(infile)?))
18 } else {
19 Box::new(BufReader::new(io::stdin()))
20 };
21 let mut buffer = [0; CHUNK_SIZE];
22
23 if !deccode.is_empty() {
24 let (mut nonce, mut key) = read_nonce_and_key(deccode)?;
25 let key_array: [u8; 32] = key.clone().try_into().expect("key must be 32 bytes");
26 let mut decryptor = Aes256GcmStreamDecryptor::new(key_array, &nonce);
27
28 loop {
29 let num_read = match reader.read(&mut buffer) {
30 Ok(0) => break,
31 Ok(x) => x,
32 Err(_) => break,
33 };
34 if num_read == 0 {
35 break;
36 }
37
38 let mut plaintext = decryptor.update(&buffer[..num_read]);
39 if !plaintext.is_empty() {
40 let _ = stats_tx.send(plaintext.len()); if write_tx.send(plaintext).is_err() {
42 break;
43 };
44 }
45 }
46 match decryptor.finalize() {
47 Ok(mut last_block) => {
48 if !last_block.is_empty() {
49 let _ = stats_tx.send(last_block.len());
50 let _ = write_tx.send(last_block);
51 }
52 }
53 Err(_) => {
54 nonce.zeroize();
55 key.zeroize();
56 let _ = stats_tx.send(0);
57 let _ = write_tx.send(Vec::new()); return Err(io::Error::new(
59 io::ErrorKind::InvalidData,
60 "decryption failed: authentication tag mismatch",
61 ));
62 }
63 }
64
65 nonce.zeroize();
66 key.zeroize();
67 } else {
68 loop {
69 let num_read = match reader.read(&mut buffer) {
70 Ok(0) => break,
71 Ok(x) => x,
72 Err(_) => break,
73 };
74 let _ = stats_tx.send(num_read); if write_tx.send(Vec::from(&buffer[..num_read])).is_err() {
76 break;
77 };
78 }
79 }
80
81 let _ = stats_tx.send(0);
82 let _ = write_tx.send(Vec::new()); Ok(())
84}
85
86fn read_nonce_and_key(deccode: &str) -> Result<([u8; 12], [u8; 32])> {
87 let mut file = File::open(deccode)?;
88 let mut nonce = [0u8; 12];
89 let mut key = [0u8; 32];
90 file.read_exact(&mut nonce)?;
91 file.read_exact(&mut key)?;
92 Ok((nonce, key))
93}