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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use crypto::aessafe::AesSafe128Decryptor;
use crypto::blockmodes::{EcbDecryptor, NoPadding};
use crate::error::Error;
use crate::header::decrypt;
use std::convert::TryInto;

pub struct KeyParams<'a> {
    wrapped_key: &'a [u8],
    salt: &'a [u8],
    iterations: u32,
}

const KEY_START: usize = 0;
const KEY_LENGTH: usize = 16 + 8;

const SALT_START: usize = KEY_START + KEY_LENGTH;
const SALT_LENGTH: usize = 16;

const ITERATIONS_STARTS: usize = SALT_START + SALT_LENGTH;
const ITERATIONS_LENGTH: usize = 4;

const AES_KEY_LENGTH: u32 = 16;
const KEY_ROUNDS_BASE: u64 = AES_KEY_LENGTH as u64 / 8;

impl<'a> KeyParams<'a> {
    pub fn parse(key_wrap: &[u8]) -> KeyParams {
        let key = &key_wrap[KEY_START..(KEY_START + KEY_LENGTH)];
        let salt = &key_wrap[SALT_START..(SALT_START + SALT_LENGTH)];
        let iterations = &key_wrap[ITERATIONS_STARTS..(ITERATIONS_STARTS + ITERATIONS_LENGTH)];
        let iterations = u32::from_le_bytes(iterations.try_into().unwrap());

        KeyParams {
            wrapped_key: key,
            salt,
            iterations,
        }
    }

    pub fn unwrap_key(&self, key: &[u8]) -> Result<Vec<u8>, Error> {
        let salted_key: Vec<u8> = xor(key, self.salt);

        let mut wrapped = self.wrapped_key.to_vec();

        let aes_dec = AesSafe128Decryptor::new(salted_key.as_slice());
        let mut decryptor = Box::new(EcbDecryptor::new(aes_dec, NoPadding));

        let rounds: u64 = KEY_ROUNDS_BASE * self.iterations as u64;
        for t in (1..(rounds + 1)).rev() {
            let block = &wrapped[0..8];
            let mut block = xor(block, &t.to_le_bytes());
            let second_start: usize = ((((t + 1) % KEY_ROUNDS_BASE) + 1) * 8) as usize;

            block.extend_from_slice(&wrapped[second_start..(second_start + 8)]);

            decryptor.reset();
            let buffer = decrypt(decryptor.as_mut(), block.as_slice(), 16)?;

            let (first_half, second_half) = buffer.split_at(8);
            wrapped.splice(..8, first_half.to_vec());
            wrapped.splice(second_start..(second_start + 8), second_half.to_vec());
        }

        Ok(wrapped[8..].to_vec())
    }
}

fn xor(a: &[u8], b: &[u8]) -> Vec<u8> {
    a.iter()
        .zip(b.iter())
        .map(|(x1, x2)| *x1 ^ *x2)
        .collect::<Vec<u8>>()
}


#[cfg(test)]
mod tests {
    use crate::key::KeyParams;

    #[test]
    fn unwrap_key() {
        let wrapped_key: [u8; 44] = [
            // raw key
            0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47, 0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82, 0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5,
            // salt
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            // iterations
            6, 0, 0, 0
        ];
        let encryption_key: [u8; 16] = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F];

        let params = KeyParams::parse(&wrapped_key);
        let result = params.unwrap_key(&encryption_key);

        let expected: Vec<u8> = vec![237, 149, 127, 244, 80, 250, 212, 169, 7, 60, 73, 31, 165, 26, 13, 46];
        assert_eq!(result.unwrap(), expected);
    }

}