Use fsverity metadata file for authfs
Instead of alternative signature and merkle tree, authfs will use
.fsv_meta files, which are installed to the system partition with
PRODUCT_SYSTEM_FSVERITY_GENERATE_METADATA Makefile.
Bug: 205987437
Test: atest ComposHostTestCases AuthFsTestCase
Test: run "atest ." inside authfs/tests
Change-Id: Ia9db78663e0e322c7a59305c67ac5b84716d8efe
diff --git a/authfs/src/fsverity/verifier.rs b/authfs/src/fsverity/verifier.rs
index 4a18c6a..1add37a 100644
--- a/authfs/src/fsverity/verifier.rs
+++ b/authfs/src/fsverity/verifier.rs
@@ -137,7 +137,7 @@
authenticator: &A,
chunked_file: F,
file_size: u64,
- sig: Vec<u8>,
+ sig: Option<&[u8]>,
merkle_tree: M,
) -> Result<VerifiedFileReader<F, M>, FsverityError> {
let mut buf = [0u8; CHUNK_SIZE as usize];
@@ -147,7 +147,7 @@
}
let root_hash = Sha256Hasher::new()?.update(&buf[..])?.finalize()?;
let formatted_digest = build_fsverity_formatted_digest(&root_hash, file_size)?;
- let valid = authenticator.verify(&sig, &formatted_digest)?;
+ let valid = authenticator.verify(sig, &formatted_digest)?;
if valid {
Ok(VerifiedFileReader { chunked_file, file_size, merkle_tree, root_hash })
} else {
@@ -175,9 +175,9 @@
use crate::auth::FakeAuthenticator;
use crate::file::ReadByChunk;
use anyhow::Result;
+ use authfs_fsverity_metadata::{parse_fsverity_metadata, FSVerityMetadata};
use std::cmp::min;
- use std::fs::{self, File};
- use std::io::Read;
+ use std::fs::File;
use std::os::unix::fs::FileExt;
struct LocalFileReader {
@@ -210,7 +210,17 @@
}
}
- type LocalVerifiedFileReader = VerifiedFileReader<LocalFileReader, LocalFileReader>;
+ type LocalVerifiedFileReader = VerifiedFileReader<LocalFileReader, MerkleTreeReader>;
+
+ pub struct MerkleTreeReader {
+ metadata: Box<FSVerityMetadata>,
+ }
+
+ impl ReadByChunk for MerkleTreeReader {
+ fn read_chunk(&self, chunk_index: u64, buf: &mut ChunkBuffer) -> io::Result<usize> {
+ self.metadata.read_merkle_tree(chunk_index * CHUNK_SIZE, buf)
+ }
+ }
fn total_chunk_number(file_size: u64) -> u64 {
(file_size + 4095) / 4096
@@ -219,28 +229,28 @@
// Returns a reader with fs-verity verification and the file size.
fn new_reader_with_fsverity(
content_path: &str,
- merkle_tree_path: &str,
- signature_path: &str,
+ metadata_path: &str,
) -> Result<(LocalVerifiedFileReader, u64)> {
let file_reader = LocalFileReader::new(File::open(content_path)?)?;
let file_size = file_reader.len();
- let merkle_tree = LocalFileReader::new(File::open(merkle_tree_path)?)?;
- let mut sig = Vec::new();
- let _ = File::open(signature_path)?.read_to_end(&mut sig)?;
+ let metadata = parse_fsverity_metadata(File::open(metadata_path)?)?;
let authenticator = FakeAuthenticator::always_succeed();
Ok((
- VerifiedFileReader::new(&authenticator, file_reader, file_size, sig, merkle_tree)?,
+ VerifiedFileReader::new(
+ &authenticator,
+ file_reader,
+ file_size,
+ metadata.signature.clone().as_deref(),
+ MerkleTreeReader { metadata },
+ )?,
file_size,
))
}
#[test]
fn fsverity_verify_full_read_4k() -> Result<()> {
- let (file_reader, file_size) = new_reader_with_fsverity(
- "testdata/input.4k",
- "testdata/input.4k.merkle_dump",
- "testdata/input.4k.fsv_sig",
- )?;
+ let (file_reader, file_size) =
+ new_reader_with_fsverity("testdata/input.4k", "testdata/input.4k.fsv_meta")?;
for i in 0..total_chunk_number(file_size) {
let mut buf = [0u8; 4096];
@@ -251,11 +261,8 @@
#[test]
fn fsverity_verify_full_read_4k1() -> Result<()> {
- let (file_reader, file_size) = new_reader_with_fsverity(
- "testdata/input.4k1",
- "testdata/input.4k1.merkle_dump",
- "testdata/input.4k1.fsv_sig",
- )?;
+ let (file_reader, file_size) =
+ new_reader_with_fsverity("testdata/input.4k1", "testdata/input.4k1.fsv_meta")?;
for i in 0..total_chunk_number(file_size) {
let mut buf = [0u8; 4096];
@@ -266,11 +273,8 @@
#[test]
fn fsverity_verify_full_read_4m() -> Result<()> {
- let (file_reader, file_size) = new_reader_with_fsverity(
- "testdata/input.4m",
- "testdata/input.4m.merkle_dump",
- "testdata/input.4m.fsv_sig",
- )?;
+ let (file_reader, file_size) =
+ new_reader_with_fsverity("testdata/input.4m", "testdata/input.4m.fsv_meta")?;
for i in 0..total_chunk_number(file_size) {
let mut buf = [0u8; 4096];
@@ -283,8 +287,7 @@
fn fsverity_verify_bad_merkle_tree() -> Result<()> {
let (file_reader, _) = new_reader_with_fsverity(
"testdata/input.4m",
- "testdata/input.4m.merkle_dump.bad", // First leaf node is corrupted.
- "testdata/input.4m.fsv_sig",
+ "testdata/input.4m.fsv_meta.bad_merkle", // First leaf node is corrupted.
)?;
// A lowest broken node (a 4K chunk that contains 128 sha256 hashes) will fail the read
@@ -304,10 +307,15 @@
let authenticator = FakeAuthenticator::always_fail();
let file_reader = LocalFileReader::new(File::open("testdata/input.4m")?)?;
let file_size = file_reader.len();
- let merkle_tree = LocalFileReader::new(File::open("testdata/input.4m.merkle_dump")?)?;
- let sig = fs::read("testdata/input.4m.fsv_sig")?;
- assert!(VerifiedFileReader::new(&authenticator, file_reader, file_size, sig, merkle_tree)
- .is_err());
+ let metadata = parse_fsverity_metadata(File::open("testdata/input.4m.fsv_meta")?)?;
+ assert!(VerifiedFileReader::new(
+ &authenticator,
+ file_reader,
+ file_size,
+ metadata.signature.clone().as_deref(),
+ MerkleTreeReader { metadata },
+ )
+ .is_err());
Ok(())
}
}