1use bssl_crypto::digest::Sha256;
6use std::mem::{size_of, size_of_val};
7
8use crate::{BLOCK_SIZE, HASH_SIZE, Hash};
9
10pub(crate) const HASHES_PER_BLOCK: usize = BLOCK_SIZE / HASH_SIZE;
11
12type BlockIdentity = [u8; size_of::<u64>() + size_of::<u32>()];
13
14fn make_identity(length: usize, level: usize, offset: usize) -> BlockIdentity {
16 let offset_or_level = (offset as u64 | level as u64).to_le_bytes();
17 let length = (length as u32).to_le_bytes();
18 let mut ret: BlockIdentity = [0; size_of::<BlockIdentity>()];
19 let (ret_offset_or_level, ret_length) = ret.split_at_mut(size_of_val(&offset_or_level));
20 ret_offset_or_level.copy_from_slice(&offset_or_level);
21 ret_length.copy_from_slice(&length);
22 ret
23}
24
25pub fn hash_block(block: &[u8], offset: usize) -> Hash {
36 assert!(block.len() <= BLOCK_SIZE);
37 assert!(offset.is_multiple_of(BLOCK_SIZE));
38
39 let mut hasher = Sha256::new();
40 hasher.update(&make_identity(block.len(), 0, offset));
41 hasher.update(block);
42 if block.len() != BLOCK_SIZE && !(block.is_empty() && offset == 0) {
45 update_with_zeros(&mut hasher, BLOCK_SIZE - block.len());
46 }
47
48 Hash::from(hasher.digest())
49}
50
51pub(crate) fn hash_hashes(hashes: &[Hash], level: usize, offset: usize) -> Hash {
77 assert_ne!(hashes.len(), 0);
78 assert!(hashes.len() <= HASHES_PER_BLOCK);
79 assert!(level > 0);
80 assert!(offset.is_multiple_of(BLOCK_SIZE));
81
82 let mut hasher = make_hash_hasher(HASHES_PER_BLOCK, level, offset);
83 for hash in hashes.iter() {
84 hasher.update(hash.as_bytes());
85 }
86 if hashes.len() != HASHES_PER_BLOCK {
87 update_with_zeros(&mut hasher, (HASHES_PER_BLOCK - hashes.len()) * HASH_SIZE);
88 }
89 Hash::from(hasher.digest())
90}
91
92pub(crate) fn update_with_zeros(hasher: &mut Sha256, mut count: usize) {
94 const BUF_SIZE: usize = 512;
95 const ZEROS: [u8; BUF_SIZE] = [0; BUF_SIZE];
96 while count >= BUF_SIZE {
97 count -= BUF_SIZE;
98 hasher.update(&ZEROS);
99 }
100 if count > 0 {
101 hasher.update(&ZEROS[0..count]);
102 }
103}
104
105pub(crate) fn make_hash_hasher(hashes_per_hash: usize, level: usize, offset: usize) -> Sha256 {
108 debug_assert!(level > 0);
109 let bytes_per_hash = hashes_per_hash * HASH_SIZE;
110 debug_assert!(offset.is_multiple_of(bytes_per_hash));
111 let mut hasher = Sha256::new();
112 hasher.update(&make_identity(bytes_per_hash, level, offset));
113 hasher
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_hash_block_empty() {
122 let block = [];
123 let hash = hash_block(&block[..], 0);
124 let expected =
125 "15ec7bf0b50732b49f8228e07d24365338f9e3ab994b00af08e5a3bffe55fd8b".parse().unwrap();
126 assert_eq!(hash, expected);
127 }
128
129 #[test]
130 fn test_hash_block_single() {
131 let block = vec![0xFF; 8192];
132 let hash = hash_block(&block[..], 0);
133 let expected =
134 "68d131bc271f9c192d4f6dcd8fe61bef90004856da19d0f2f514a7f4098b0737".parse().unwrap();
135 assert_eq!(hash, expected);
136 }
137
138 #[test]
139 fn test_hash_hashes_full_block() {
140 let mut leafs = Vec::new();
141 {
142 let block = vec![0xFF; BLOCK_SIZE];
143 for i in 0..HASHES_PER_BLOCK {
144 leafs.push(hash_block(&block, i * BLOCK_SIZE));
145 }
146 }
147 let root = hash_hashes(&leafs, 1, 0);
148 let expected =
149 "1e6e9c870e2fade25b1b0288ac7c216f6fae31c1599c0c57fb7030c15d385a8d".parse().unwrap();
150 assert_eq!(root, expected);
151 }
152
153 #[test]
154 fn test_hash_hashes_zero_pad_same_length() {
155 let data_hash =
156 "15ec7bf0b50732b49f8228e07d24365338f9e3ab994b00af08e5a3bffe55fd8b".parse().unwrap();
157 let zero_hash =
158 "0000000000000000000000000000000000000000000000000000000000000000".parse().unwrap();
159 let hash_of_single_hash = hash_hashes(&[data_hash], 1, 0);
160 let hash_of_single_hash_and_zero_hash = hash_hashes(&[data_hash, zero_hash], 1, 0);
161 assert_eq!(hash_of_single_hash, hash_of_single_hash_and_zero_hash);
162 }
163}