authfs: Add MerkleLeaves for integrity bookkeeping
MerkleLeaves will be used by a "writer" for remembering the hashes of
written blocks for integrity checking. For example, when a file is
written from a trusted environment to an untrusted storage / remote,
MerkleLeaves allows the writer to verify the reads later with a
cryptographical strong hash.
Besides verification, if requested, the tree can grow from the leaves(!)
to generate the root hash and fs-verity digest.
- fsverity/builder.rs: implements MerkleLeaves
- fsverity/verifier.rs: renamed from fsverity.rs with minor changes
- fsverity/common.rs: common utils from the original fsverity.rs with
one addition error in the enum
- crypto.rs: more helper function / constant
Bug: 171279640
Test: atest authfs_device_test_src_lib
Change-Id: I76e5ebd81a2f2afa017e3c670774ccbb797766df
diff --git a/authfs/src/crypto.rs b/authfs/src/crypto.rs
index 8b8905c..672dfb6 100644
--- a/authfs/src/crypto.rs
+++ b/authfs/src/crypto.rs
@@ -26,6 +26,8 @@
use authfs_crypto_bindgen::{SHA256_Final, SHA256_Init, SHA256_Update, SHA256_CTX};
+pub type Sha256Hash = [u8; Sha256Hasher::HASH_SIZE];
+
pub struct Sha256Hasher {
ctx: SHA256_CTX,
}
@@ -33,6 +35,12 @@
impl Sha256Hasher {
pub const HASH_SIZE: usize = 32;
+ pub const HASH_OF_4096_ZEROS: [u8; Self::HASH_SIZE] = [
+ 0xad, 0x7f, 0xac, 0xb2, 0x58, 0x6f, 0xc6, 0xe9, 0x66, 0xc0, 0x04, 0xd7, 0xd1, 0xd1, 0x6b,
+ 0x02, 0x4f, 0x58, 0x05, 0xff, 0x7c, 0xb4, 0x7c, 0x7a, 0x85, 0xda, 0xbd, 0x8b, 0x48, 0x89,
+ 0x2c, 0xa7,
+ ];
+
pub fn new() -> Result<Sha256Hasher, CryptoError> {
// Safe assuming the crypto FFI should initialize the uninitialized `ctx`, which is
// currently a pure data struct.
@@ -58,6 +66,17 @@
}
}
+ pub fn update_from<I, T>(&mut self, iter: I) -> Result<&mut Self, CryptoError>
+ where
+ I: IntoIterator<Item = T>,
+ T: AsRef<[u8]>,
+ {
+ for data in iter {
+ self.update(data.as_ref())?;
+ }
+ Ok(self)
+ }
+
pub fn finalize(&mut self) -> Result<[u8; Self::HASH_SIZE], CryptoError> {
let mut md = [0u8; Self::HASH_SIZE];
// Safe assuming the crypto FFI will not touch beyond `ctx` as pure data.
@@ -93,4 +112,11 @@
assert_eq!(s, "039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81");
Ok(())
}
+
+ #[test]
+ fn sha256_of_4096_zeros() -> Result<(), CryptoError> {
+ let hash = Sha256Hasher::new()?.update(&[0u8; 4096])?.finalize()?;
+ assert_eq!(hash, Sha256Hasher::HASH_OF_4096_ZEROS);
+ Ok(())
+ }
}