pvcrypt/
read.rs

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()); // Dont care if it cant see stats
41                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()); // empty vec
58                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); // Dont care if it cant see stats
75            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()); // empty vec
83    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}