1use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
8
9mod builder;
10pub use crate::builder::MerkleTreeBuilder;
11
12mod tree;
13pub use crate::tree::MerkleTree;
14
15mod util;
16pub use crate::util::{
17 FsVerityDescriptor, FsVerityDescriptorRaw, FsVerityHasher, FsVerityHasherOptions,
18};
19
20mod verifier;
21pub use crate::verifier::MerkleVerifier;
22
23pub const SHA256_SALT_PADDING: u8 = 64;
24pub const SHA512_SALT_PADDING: u8 = 128;
25
26pub trait FsVerityHash:
28 FromBytes
29 + IntoBytes
30 + KnownLayout
31 + Immutable
32 + Clone
33 + Copy
34 + std::fmt::Debug
35 + Send
36 + Sync
37 + PartialEq
38 + Eq
39{
40}
41
42#[repr(transparent)]
44#[derive(Debug, Clone, Copy, PartialEq, Eq, FromBytes, IntoBytes, KnownLayout, Immutable)]
45pub struct Sha256Hash([u8; 32]);
46
47impl FsVerityHash for Sha256Hash {}
48
49impl From<[u8; 32]> for Sha256Hash {
50 fn from(bytes: [u8; 32]) -> Self {
51 Self(bytes)
52 }
53}
54
55impl From<Sha256Hash> for [u8; 32] {
56 fn from(hash: Sha256Hash) -> Self {
57 hash.0
58 }
59}
60
61#[repr(transparent)]
63#[derive(Debug, Clone, Copy, PartialEq, Eq, FromBytes, IntoBytes, KnownLayout, Immutable)]
64pub struct Sha512Hash([u8; 64]);
65
66impl FsVerityHash for Sha512Hash {}
67
68impl From<[u8; 64]> for Sha512Hash {
69 fn from(bytes: [u8; 64]) -> Self {
70 Self(bytes)
71 }
72}
73
74impl From<Sha512Hash> for [u8; 64] {
75 fn from(hash: Sha512Hash) -> Self {
76 hash.0
77 }
78}
79
80pub fn from_slice(slice: &[u8], hasher: FsVerityHasher) -> MerkleTree {
82 match hasher {
83 FsVerityHasher::Sha256(_) => from_slice_impl::<Sha256Hash>(slice, hasher),
84 FsVerityHasher::Sha512(_) => from_slice_impl::<Sha512Hash>(slice, hasher),
85 }
86}
87
88fn from_slice_impl<D: FsVerityHash>(slice: &[u8], hasher: FsVerityHasher) -> MerkleTree {
89 let mut builder = MerkleTreeBuilder::<D>::new(hasher);
90 builder.write(slice);
91 builder.finish()
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_from_slice_sha256() {
100 let file = vec![0xFF; 2105344];
101 let hasher = FsVerityHasher::Sha256(FsVerityHasherOptions::new(vec![0xFF; 8], 4096));
102 let expected = MerkleTree::from_data(&file[..], hasher.clone());
103 let actual = from_slice(&file[..], hasher);
104 assert_eq!(expected.root(), actual.root());
105 }
106
107 #[test]
108 fn test_from_slice_sha512() {
109 let file = vec![0xFF; 2105344];
110 let hasher = FsVerityHasher::Sha512(FsVerityHasherOptions::new(vec![0xFF; 8], 4096));
111 let expected = MerkleTree::from_data(&file[..], hasher.clone());
112 let actual = from_slice(&file[..], hasher);
113 assert_eq!(expected.root(), actual.root());
114 }
115}