deadbolt_parser/
header.rs1use std::error::Error;
2
3use deadbolt_crypto::rand::Random;
4
5use crate::config::KdfParams;
6
7pub const MAGIC_HEADER: [u8; 4] = [0xde, 0xad, 0xb0, 0x17];
8
9const ENCRYPTION_ALGORITHMS: [u8; 2] = [0x01, 0x02];
10const HASH_ALGORITHMS: [u8; 1] = [0x01];
11const KDF_ALGORITHMS: [u8; 2] = [0x01, 0x02];
12const COMPRESSION_ALGORITHMS: [u8; 2] = [0x00, 0x01];
13
14#[derive(PartialEq, Debug)]
15pub struct Header {
16 pub version: u16,
17 pub data_length: u16,
18 pub encryption_alg: u8,
19 pub hash_alg: u8,
20 pub kdf_alg: u8,
21 pub kdf_params: KdfParams,
22 pub compression_alg: u8,
23 pub master_salt: Vec<u8>,
24 pub nonce: Option<Vec<u8>>,
25 pub root_key_nonce: Option<Vec<u8>>,
26 pub root_key_ciphertext: Option<Vec<u8>>,
27}
28
29impl Header {
30 pub fn new(
31 encryption_alg: Option<u8>,
32 hash_alg: Option<u8>,
33 kdf_alg: Option<u8>,
34 compression_alg: Option<u8>,
35 master_salt: Option<Vec<u8>>,
36 ) -> Header {
37 Header {
38 version: 0x01,
39 data_length: 0,
40 encryption_alg: encryption_alg.unwrap_or(0x01),
41 hash_alg: hash_alg.unwrap_or(0x01),
42 kdf_alg: kdf_alg.unwrap_or(0x01),
43 kdf_params: KdfParams::default(),
44 compression_alg: compression_alg.unwrap_or(0x00),
45 master_salt: master_salt.unwrap_or_else(Random::get_rand_bytes),
46 nonce: Default::default(),
47 root_key_nonce: Default::default(),
48 root_key_ciphertext: Default::default(),
49 }
50 }
51
52 pub fn quick_lookup(data: Vec<u8>) -> Result<(u16, u16), Box<dyn Error>> {
55 if data[0..4] != MAGIC_HEADER {
56 Err("Data is not valid deadbolt database")?;
57 }
58
59 let version = ((data[4] as u16) << 8) | (data[5] as u16);
60 let data_length = ((data[6] as u16) << 8) | (data[7] as u16);
61
62 Ok((version, data_length))
63 }
64
65 pub fn new_from_vector(data: Vec<u8>) -> Result<Header, Box<dyn Error>> {
67 let (version, data_length) = Header::quick_lookup(data[..8].to_vec())?;
68 let mut header = Header::new(None, None, None, None, None);
69 header.version = version;
70 header.data_length = data_length;
71 header.parse_tlv_header(data[8..].to_vec())?;
72
73 Ok(header)
74 }
75
76 pub fn parse_tlv_header(&mut self, data: Vec<u8>) -> Result<(), Box<dyn Error>> {
78 let mut index = 0;
79
80 loop {
81 let data_type = data[index];
82 index += 1;
83 let start = index + 1;
84 let end = start + usize::from(data[index]);
85 index = end;
86
87 match data_type {
88 1 => {
89 self.encryption_alg = u8::from_be_bytes(data[start..end].try_into()?);
90 }
91 2 => {
92 self.hash_alg = u8::from_be_bytes(data[start..end].try_into()?);
93 }
94 3 => {
95 self.kdf_alg = u8::from_be_bytes(data[start..end].try_into()?);
96 }
97 4 => {
98 self.compression_alg = u8::from_be_bytes(data[start..end].try_into()?);
99 }
100 6 => {
101 self.master_salt = data[start..end].to_vec();
102 }
103 7 => {
104 self.nonce = Some(data[start..end].to_vec());
105 }
106 8 => {
107 self.root_key_nonce = Some(data[start..end].to_vec());
108 }
109 9 => {
110 self.root_key_ciphertext = Some(data[start..end].to_vec());
111 }
112 10 => {
113 self.kdf_params.iterations = u8::from_be_bytes(data[start..end].try_into()?);
114 }
115 11 => {
116 self.kdf_params.threads = u8::from_be_bytes(data[start..end].try_into()?);
117 }
118 12 => {
119 self.kdf_params.memory = u32::from_be_bytes(data[start..end].try_into()?);
120 }
121 0 => {
122 break;
123 }
124 _ => {}
125 }
126 }
127
128 Ok(())
129 }
130
131 pub fn construct_header(&mut self) -> Result<Vec<u8>, Box<dyn Error>> {
134 let mut buffer: Vec<u8> = MAGIC_HEADER.to_vec();
135 buffer.extend(self.version.to_be_bytes());
136
137 let mut tmp_buffer: Vec<u8> = vec![];
138 tmp_buffer.extend([0x01, 0x01]);
140 tmp_buffer.push(self.encryption_alg);
141
142 tmp_buffer.extend([0x02, 0x01]);
144 tmp_buffer.push(self.hash_alg);
145
146 tmp_buffer.extend([0x03, 0x01]);
148 tmp_buffer.push(self.kdf_alg);
149
150 tmp_buffer.extend([0x04, 0x01]);
152 tmp_buffer.push(self.compression_alg);
153
154 tmp_buffer.push(0x06);
156 tmp_buffer.push(self.master_salt.len().try_into()?);
157 tmp_buffer.extend(self.master_salt.clone());
158
159 let nonce = self.nonce.as_ref().unwrap();
161 let nonce_size: u8 = nonce.len().try_into()?;
162 tmp_buffer.push(0x07);
163 tmp_buffer.push(nonce_size);
164 tmp_buffer.extend(nonce);
165
166 let root_key_nonce = self.root_key_nonce.as_ref().unwrap();
168 let nonce_size: u8 = root_key_nonce.len().try_into()?;
169 tmp_buffer.push(0x08);
170 tmp_buffer.push(nonce_size);
171 tmp_buffer.extend(root_key_nonce);
172
173 let root_key_ciphertext = self.root_key_ciphertext.as_ref().unwrap();
175 let key_size: u8 = root_key_ciphertext.len().try_into()?;
176 tmp_buffer.push(0x09);
177 tmp_buffer.push(key_size);
178 tmp_buffer.extend(root_key_ciphertext);
179
180 tmp_buffer.extend([0x0a, 0x01]);
183 tmp_buffer.push(self.kdf_params.iterations);
184 tmp_buffer.extend([0x0b, 0x01]);
186 tmp_buffer.push(self.kdf_params.threads);
187 tmp_buffer.extend([0x0c, 0x04]);
189 tmp_buffer.extend(self.kdf_params.memory.to_be_bytes());
190
191 tmp_buffer.extend([0x0, 0x0]);
193
194 let header_length: u16 = (tmp_buffer.len() + 8).try_into()?;
196 buffer.extend(header_length.to_be_bytes());
197 buffer.extend(tmp_buffer);
198
199 self.data_length = header_length;
200
201 Ok(buffer)
202 }
203
204 pub fn validate_version(&mut self) -> bool {
206 match self.version {
207 0x01 => {
208 if !ENCRYPTION_ALGORITHMS.contains(&self.encryption_alg) {
209 return false;
210 }
211 if !HASH_ALGORITHMS.contains(&self.hash_alg) {
212 return false;
213 }
214 if !KDF_ALGORITHMS.contains(&self.kdf_alg) {
215 return false;
216 }
217 if !COMPRESSION_ALGORITHMS.contains(&self.compression_alg) {
218 return false;
219 }
220 true
221 }
222 _ => false,
223 }
224 }
225}