volaris_tools/
key.rs

1use corecrypto::key::vec_to_arr;
2use corecrypto::primitives::Algorithm;
3use corecrypto::primitives::ENCRYPTED_MASTER_KEY_LEN;
4use corecrypto::primitives::MASTER_KEY_LEN;
5use corecrypto::protected::Protected;
6use corecrypto::Zeroize;
7use corecrypto::{cipher::Ciphers, header::Keyslot};
8
9pub mod add;
10pub mod change;
11pub mod delete;
12pub mod verify;
13
14#[derive(Debug)]
15pub enum Error {
16    HeaderSizeParse,
17    Unsupported,
18    IncorrectKey,
19    MasterKeyEncrypt,
20    TooManyKeyslots,
21    KeyHash,
22    CipherInit,
23    HeaderDeserialize,
24    HeaderWrite,
25    Seek,
26}
27
28impl std::fmt::Display for Error {
29    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30        match self {
31            Error::HeaderSizeParse => f.write_str("Cannot parse header size"),
32            Error::Seek => f.write_str("Unable to seek the data's cursor"),
33            Error::HeaderWrite => f.write_str("Unable to write the header"),
34            Error::HeaderDeserialize => f.write_str("Unable to deserialize the header"),
35            Error::CipherInit => f.write_str("Unable to initialize a cipher"),
36            Error::KeyHash => f.write_str("Unable to hash your key"),
37            Error::TooManyKeyslots => {
38                f.write_str("There are already too many populated keyslots within this file")
39            }
40            Error::MasterKeyEncrypt => f.write_str("Unable to encrypt master key"),
41            Error::Unsupported => {
42                f.write_str("The provided request is unsupported with this header version")
43            }
44            Error::IncorrectKey => f.write_str("The provided key is incorrect"),
45        }
46    }
47}
48
49pub fn decrypt_v5_master_key_with_index(
50    keyslots: &[Keyslot],
51    raw_key_old: Protected<Vec<u8>>,
52    algorithm: &Algorithm,
53) -> Result<(Protected<[u8; MASTER_KEY_LEN]>, usize), Error> {
54    let mut index = 0;
55    let mut master_key = [0u8; MASTER_KEY_LEN];
56
57    // we need the index, so we can't use `decrypt_master_key()`
58    for (i, keyslot) in keyslots.iter().enumerate() {
59        let key_old = keyslot
60            .hash_algorithm
61            .hash(raw_key_old.clone(), &keyslot.salt)
62            .map_err(|_| Error::KeyHash)?;
63        let cipher = Ciphers::initialize(key_old, algorithm).map_err(|_| Error::CipherInit)?;
64
65        let master_key_result = cipher.decrypt(&keyslot.nonce, keyslot.encrypted_key.as_slice());
66
67        if master_key_result.is_err() {
68            continue;
69        }
70
71        let mut master_key_decrypted = master_key_result.unwrap();
72        let len = MASTER_KEY_LEN.min(master_key_decrypted.len());
73        master_key[..len].copy_from_slice(&master_key_decrypted[..len]);
74        master_key_decrypted.zeroize();
75
76        index = i;
77
78        drop(cipher);
79        break;
80    }
81
82    drop(raw_key_old);
83
84    if master_key == [0u8; MASTER_KEY_LEN] {
85        return Err(Error::IncorrectKey);
86    }
87
88    Ok((Protected::new(master_key), index))
89}
90
91impl std::error::Error for Error {}
92
93// TODO(brxken128): make this available in the corecrypto
94pub fn encrypt_master_key(
95    master_key: Protected<[u8; MASTER_KEY_LEN]>,
96    key_new: Protected<[u8; 32]>,
97    nonce: &[u8],
98    algorithm: &Algorithm,
99) -> Result<[u8; ENCRYPTED_MASTER_KEY_LEN], Error> {
100    let cipher = Ciphers::initialize(key_new, algorithm).map_err(|_| Error::CipherInit)?;
101
102    let master_key_result = cipher.encrypt(nonce, master_key.expose().as_slice());
103
104    drop(master_key);
105
106    let master_key_encrypted = master_key_result.map_err(|_| Error::MasterKeyEncrypt)?;
107
108    Ok(vec_to_arr(master_key_encrypted))
109}