1use crate::binary;
2
3use aes::Aes256;
4use cipher::generic_array::GenericArray;
5use cipher::BlockEncryptMut;
6use hmac::digest::CtOutput;
7use hmac::{Hmac, Mac};
8use sha2::{Digest, Sha256, Sha512};
9use std::string::ToString;
10use thiserror::Error;
11
12type HmacSha256 = Hmac<Sha256>;
13
14pub struct CompositeKey {
29 pw: Option<String>,
30 keyfile: Option<Vec<u8>>,
31}
32
33impl CompositeKey {
34 pub fn new(pw: Option<String>, keyfile: Option<Vec<u8>>) -> CompositeKey {
36 CompositeKey { pw, keyfile }
37 }
38
39 pub fn from_password(pw: &str) -> CompositeKey {
41 CompositeKey::new(Some(pw.into()), None)
42 }
43
44 pub(crate) fn composed(&self) -> ComposedKey {
45 let mut buffer = Vec::new();
46 if let Some(ref pw) = self.pw {
47 buffer.extend(Sha256::digest(pw.as_bytes()))
48 }
50 if let Some(ref keyfile) = self.keyfile {
51 buffer.extend(Sha256::digest(keyfile))
52 }
53
54 ComposedKey(Sha256::digest(&buffer).iter().cloned().collect())
55 }
56}
57
58#[derive(Debug)]
59pub struct ComposedKey(Vec<u8>);
61
62impl ComposedKey {
63 pub fn master_key(
65 &self,
66 kdf_options: &binary::KdfParams,
67 ) -> Result<MasterKey, KeyGenerationError> {
68 match kdf_options {
69 binary::KdfParams::Argon2 {
70 variant,
71 memory_bytes,
72 version,
73 iterations,
74 lanes,
75 salt,
76 } => {
77 let config = argon2::Config {
78 variant: *variant,
79 version: argon2::Version::from_u32(*version)
80 .map_err(|e| KeyGenerationError::KeyGeneration(e.to_string()))?,
81 lanes: *lanes,
82 mem_cost: (memory_bytes / 1024) as u32,
83 time_cost: *iterations as u32,
84 ..Default::default()
85 };
86 let hash = argon2::hash_raw(&self.0, salt, &config)
87 .map_err(|e| KeyGenerationError::KeyGeneration(e.to_string()))?;
88
89 Ok(MasterKey(hash))
90 }
91 binary::KdfParams::Aes { rounds, salt } => {
92 use cipher::KeyInit;
93 let mut cipher = Aes256::new_from_slice(salt).unwrap();
94 let chunked: Vec<GenericArray<u8, _>> = self
95 .0
96 .chunks_exact(16)
97 .map(|chunk| *GenericArray::from_slice(chunk))
98 .collect();
99 let mut blocks = [chunked[0], chunked[1]];
100 for _ in 0..*rounds {
101 cipher.encrypt_blocks_mut(&mut blocks);
102 }
103 let mut transformed_hasher = Sha256::new();
104 transformed_hasher.update(blocks[0]);
105 transformed_hasher.update(blocks[1]);
106 let transformed = transformed_hasher.finalize().to_vec();
107
108 Ok(MasterKey(transformed))
109 }
110 _ => Ok(MasterKey(Vec::new())),
111 }
112 }
113}
114
115#[derive(Debug)]
117pub struct MasterKey(Vec<u8>);
118
119impl MasterKey {
120 pub(crate) fn hmac_key(&self, seed: &[u8]) -> HmacKey {
122 let mut data_to_hash = Vec::new();
123 data_to_hash.extend(seed.iter());
124 data_to_hash.extend(self.0.iter());
125 data_to_hash.push(1);
126
127 HmacKey(Sha512::digest(&data_to_hash).iter().cloned().collect())
128 }
129
130 pub(crate) fn cipher_key(&self, seed: &[u8]) -> CipherKey {
132 let mut data_to_hash = Vec::new();
133 data_to_hash.extend(seed.iter());
134 data_to_hash.extend(self.0.iter());
135
136 CipherKey(Sha256::digest(&data_to_hash).iter().cloned().collect())
137 }
138}
139
140pub(crate) struct CipherKey(pub(crate) Vec<u8>);
142
143pub(crate) struct HmacKey(Vec<u8>);
145
146impl HmacKey {
147 pub(crate) fn block_key(&self, block_idx: u64) -> HmacBlockKey {
149 let mut block_key_hash = Sha512::new();
150 block_key_hash.update(block_idx.to_le_bytes());
151 block_key_hash.update(&*self.0);
152 HmacBlockKey(block_idx, block_key_hash.finalize().to_vec())
153 }
154}
155
156pub(crate) struct HmacBlockKey(u64, Vec<u8>);
158
159impl HmacBlockKey {
160 pub(crate) fn verify_data_block(&self, hmac: &[u8], data: &[u8]) -> bool {
162 let mut calc_hmac = HmacSha256::new_from_slice(&self.1).unwrap();
163 calc_hmac.update(&self.0.to_le_bytes());
164 calc_hmac.update(&(data.len() as u32).to_le_bytes());
165 calc_hmac.update(data);
166 calc_hmac.verify_slice(hmac).is_ok()
167 }
168
169 pub(crate) fn calculate_data_hmac(
171 &self,
172 data: &[u8],
173 ) -> Result<CtOutput<HmacSha256>, cipher::InvalidLength> {
174 let mut calc_hmac: HmacSha256 = HmacSha256::new_from_slice(&self.1).unwrap();
175 calc_hmac.update(&self.0.to_le_bytes());
176 calc_hmac.update(&(data.len() as u32).to_le_bytes());
177 calc_hmac.update(data);
178 Ok(calc_hmac.finalize())
179 }
180
181 pub(crate) fn calculate_header_hmac(
183 &self,
184 data: &[u8],
185 ) -> Result<CtOutput<HmacSha256>, cipher::InvalidLength> {
186 let mut calc_hmac = HmacSha256::new_from_slice(&self.1)?;
187 calc_hmac.update(data);
188 Ok(calc_hmac.finalize())
189 }
190
191 pub(crate) fn verify_header_block(&self, hmac: &[u8], data: &[u8]) -> bool {
193 let mut calc_hmac = HmacSha256::new_from_slice(&self.1).unwrap();
194 calc_hmac.update(data);
195 calc_hmac.verify_slice(hmac).is_ok()
196 }
197}
198
199pub(crate) fn verify_sha256(data: &[u8], expected_sha: &[u8]) -> bool {
201 expected_sha == &*Sha256::digest(data)
202}
203
204pub(crate) fn sha256(data: &[u8]) -> Vec<u8> {
205 Sha256::digest(data).as_slice().to_vec()
206}
207
208#[derive(Debug, Error)]
209pub enum KeyGenerationError {
211 #[error("Could not generate key: {0}")]
213 KeyGeneration(String),
214 #[error("Generation for KDF Options: {0:?} not implemented")]
216 UnimplementedKdfOptions(binary::KdfParams),
217}