1use crate::{crypto::aes_aead_decrypt, prologue::AeaPrologue};
2use anyhow::Result;
3use sha2::Sha256;
4
5pub enum RootHeaderEnum {
6 Unencrypted(RootHeader),
7 Encrypted([u8; 48]),
8}
9
10pub struct RootHeader {
11 pub raw_size: [u8; 8],
12 pub container_size: [u8; 8],
13 pub segment_size: [u8; 4],
14 pub segments_per_cluster: [u8; 4],
15 pub compression_algorithm: [u8; 1],
16 pub checksum_algorithm: [u8; 1],
17 }
19
20impl RootHeader {
21 pub fn decrypt_root_header(
23 prologue: &AeaPrologue,
24 amk: &[u8; 32],
25 ) -> Result<Option<RootHeader>> {
26 let root_header_encrypted = match &prologue.root_header {
27 RootHeaderEnum::Encrypted(data) => data,
28 RootHeaderEnum::Unencrypted(_) => return Ok(None),
29 };
30
31 let hk_rhek = hkdf::Hkdf::<Sha256>::new(None, amk);
32 let mut rhek = [0u8; 80];
33 hk_rhek
34 .expand(b"AEA_RHEK", &mut rhek)
35 .map_err(|_| anyhow::anyhow!("RHEK expand fail"))?;
36
37 let mut ad = Vec::new();
38 ad.extend_from_slice(&prologue.first_cluster_hmac);
39 ad.extend_from_slice(&prologue.auth_data);
40
41 let decrypted_header =
42 aes_aead_decrypt(&rhek, root_header_encrypted, &ad, &prologue.root_hmac)?;
43
44 let root_header = RootHeader::from_decrypted_data(&decrypted_header);
45 Ok(Some(root_header))
46 }
47
48 pub fn from_decrypted_data(data: &[u8]) -> Self {
49 let mut raw_size = [0u8; 8];
50 raw_size.copy_from_slice(&data[0..8]);
51
52 let mut container_size = [0u8; 8];
53 container_size.copy_from_slice(&data[8..16]);
54
55 let mut segment_size = [0u8; 4];
56 segment_size.copy_from_slice(&data[16..20]);
57
58 let mut segments_per_cluster = [0u8; 4];
59 segments_per_cluster.copy_from_slice(&data[20..24]);
60
61 let compression_algorithm = data[24];
62 let checksum_algorithm = data[25];
63
64 Self {
65 raw_size,
66 container_size,
67 segment_size,
68 segments_per_cluster,
69 compression_algorithm: [compression_algorithm],
70 checksum_algorithm: [checksum_algorithm],
71 }
72 }
73}