apkverify: add ziputil
apkverify doesn't need all zip features. ziputil provides zip_sections()
to discover the layout of a zip file.
Bug: 190343842
Test: cargo test
Change-Id: Ib6354828cebe819fd3f48265089815ccf29f18ea
diff --git a/apkverify/src/sigutil.rs b/apkverify/src/sigutil.rs
index de3d0dd..564831f 100644
--- a/apkverify/src/sigutil.rs
+++ b/apkverify/src/sigutil.rs
@@ -19,9 +19,9 @@
use anyhow::{anyhow, bail, Result};
use byteorder::{LittleEndian, ReadBytesExt};
use bytes::{Buf, Bytes};
-use std::io;
-use std::io::Read;
-use zip::spec::CentralDirectoryEnd as EndOfCentralDirectory;
+use std::io::{Read, Seek, SeekFrom};
+
+use crate::ziputil::zip_sections;
const APK_SIG_BLOCK_MIN_SIZE: u32 = 32;
const APK_SIG_BLOCK_MAGIC: u128 = 0x3234206b636f6c4220676953204b5041;
@@ -46,34 +46,23 @@
const CONTENT_DIGEST_SHA256: u32 = 4;
pub struct SignatureInfo {
- pub signing_block_offset: u32,
pub signature_block: Bytes,
- pub eocd_offset: u32,
- pub eocd: EndOfCentralDirectory,
}
/// Returns the APK Signature Scheme block contained in the provided file for the given ID
/// and the additional information relevant for verifying the block against the file.
-pub fn find_signature<F: Read + io::Seek>(f: &mut F, block_id: u32) -> Result<SignatureInfo> {
- let (eocd, eocd_offset) = EndOfCentralDirectory::find_and_parse(f)?;
- if eocd.disk_number != eocd.disk_with_central_directory {
- bail!("Support for multi-disk files is not implemented");
- }
- // TODO(jooyung): reject zip64 file
- let (signing_block, signing_block_offset) =
- find_signing_block(f, eocd.central_directory_offset)?;
+pub fn find_signature<F: Read + Seek>(f: F, block_id: u32) -> Result<SignatureInfo> {
+ let (mut f, sections) = zip_sections(f)?;
+
+ let (signing_block, _signing_block_offset) =
+ find_signing_block(&mut f, sections.central_directory_offset)?;
// TODO(jooyung): propagate NotFound error so that verification can fallback to V2
let signature_scheme_block = find_signature_scheme_block(signing_block, block_id)?;
- Ok(SignatureInfo {
- signing_block_offset,
- signature_block: signature_scheme_block,
- eocd_offset: eocd_offset as u32,
- eocd,
- })
+ Ok(SignatureInfo { signature_block: signature_scheme_block })
}
-fn find_signing_block<T: Read + io::Seek>(
+fn find_signing_block<T: Read + Seek>(
reader: &mut T,
central_directory_offset: u32,
) -> Result<(Bytes, u32)> {
@@ -89,7 +78,7 @@
central_directory_offset
);
}
- reader.seek(io::SeekFrom::Start((central_directory_offset - 24) as u64))?;
+ reader.seek(SeekFrom::Start((central_directory_offset - 24) as u64))?;
let size_in_footer = reader.read_u64::<LittleEndian>()? as u32;
if reader.read_u128::<LittleEndian>()? != APK_SIG_BLOCK_MAGIC {
bail!("No APK Signing Block before ZIP Central Directory")
@@ -98,7 +87,7 @@
let signing_block_offset = central_directory_offset
.checked_sub(total_size)
.ok_or_else(|| anyhow!("APK Signing Block size out of range: {}", size_in_footer))?;
- reader.seek(io::SeekFrom::Start(signing_block_offset as u64))?;
+ reader.seek(SeekFrom::Start(signing_block_offset as u64))?;
let size_in_header = reader.read_u64::<LittleEndian>()? as u32;
if size_in_header != size_in_footer {
bail!(
@@ -107,7 +96,7 @@
size_in_footer
);
}
- reader.seek(io::SeekFrom::Start(signing_block_offset as u64))?;
+ reader.seek(SeekFrom::Start(signing_block_offset as u64))?;
let mut buf = vec![0u8; total_size as usize];
reader.read_exact(&mut buf)?;
Ok((Bytes::from(buf), signing_block_offset))