aboutsummaryrefslogtreecommitdiff
path: root/src/zip/encryption/aes.rs
blob: b690482f60d8ddf731e23a7dfb6fc4e4a2e02db4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use aes::cipher::generic_array::GenericArray;
use aes::cipher::BlockEncrypt;
use std::io::{Read, Result as IoResult};

#[allow(dead_code)]
pub struct AesDecoder<Io: Read, Aes: BlockEncrypt> {
    io: Io,
    aes: Aes,

    counter: u128,
    block: [u8; 16],
    lower: usize,
    upper: usize,
}

impl<Io: Read, Aes: BlockEncrypt> AesDecoder<Io, Aes> {
    pub fn new(io: Io, aes: Aes) -> IoResult<Self> {
        let mut decoder = Self {
            io,
            aes,

            counter: 0,
            block: [0; 16],
            lower: 0,
            upper: 0,
        };

        decoder.update_block()?;

        Ok(decoder)
    }

    #[inline]
    fn update_block(&mut self) -> IoResult<()> {
        self.upper = self.io.read(&mut self.block)?;
        self.lower = 0;

        self.counter += 1;
        let mut mask = self.counter.to_le_bytes();

        self.aes
            .encrypt_block(GenericArray::from_mut_slice(&mut mask));

        for (b, m) in self.block.iter_mut().zip(mask) {
            *b ^= m
        }

        Ok(())
    }
}

impl<Io: Read, Aes: BlockEncrypt> Read for AesDecoder<Io, Aes> {
    fn read(&mut self, mut buf: &mut [u8]) -> IoResult<usize> {
        let mut bytes = 0;
        while !buf.is_empty() && self.lower != self.upper {
            for (to, fr) in buf.iter_mut().zip(&self.block[self.lower..self.upper]) {
                *to = *fr
            }

            let consumed = buf.len().min(self.upper - self.lower);
            buf = &mut buf[consumed..];
            self.lower += consumed;
            bytes += consumed;

            if self.lower == 16 {
                self.update_block()?;
            }
        }
        Ok(bytes)
    }
}