Merge changes from topic "idsig"

* changes:
  idsig: Include the APK digest
  apkverify: Add function to pick v4 apk digest
  apkverify: Rank based on v4 preferences
diff --git a/libs/apkverify/Android.bp b/libs/apkverify/Android.bp
index 2445dd5..d45a77f 100644
--- a/libs/apkverify/Android.bp
+++ b/libs/apkverify/Android.bp
@@ -24,6 +24,7 @@
     defaults: ["libapkverify.defaults"],
     // TODO(b/204562227): move to host_supported to the defaults to include tests
     host_supported: true,
+    apex_available: ["com.android.virt"],
 }
 
 rust_test {
diff --git a/libs/apkverify/src/lib.rs b/libs/apkverify/src/lib.rs
index 290a79a..c5aa9e5 100644
--- a/libs/apkverify/src/lib.rs
+++ b/libs/apkverify/src/lib.rs
@@ -24,4 +24,4 @@
 mod ziputil;
 
 // TODO(jooyung) fallback to v2 when v3 not found
-pub use v3::{get_public_key_der, verify};
+pub use v3::{get_public_key_der, pick_v4_apk_digest, verify};
diff --git a/libs/apkverify/src/sigutil.rs b/libs/apkverify/src/sigutil.rs
index 009154f..2b2f9da 100644
--- a/libs/apkverify/src/sigutil.rs
+++ b/libs/apkverify/src/sigutil.rs
@@ -282,6 +282,7 @@
     }
 }
 
+/// Rank the signature algorithm according to the preferences of the v4 signing scheme.
 pub fn rank_signature_algorithm(algo: u32) -> Result<u32> {
     rank_content_digest_algorithm(to_content_digest_algorithm(algo)?)
 }
diff --git a/libs/apkverify/src/v3.rs b/libs/apkverify/src/v3.rs
index 16530be..96ca7bc 100644
--- a/libs/apkverify/src/v3.rs
+++ b/libs/apkverify/src/v3.rs
@@ -128,16 +128,43 @@
     })
 }
 
+/// Gets the APK digest.
+pub fn pick_v4_apk_digest<R: Read + Seek>(apk: R) -> Result<(u32, Box<[u8]>)> {
+    let mut sections = ApkSections::new(apk)?;
+    let mut block = sections.find_signature(APK_SIGNATURE_SCHEME_V3_BLOCK_ID)?;
+    let signers = block.read::<Signers>()?;
+    if signers.len() != 1 {
+        bail!("should only have one signer");
+    }
+    signers[0].pick_v4_apk_digest()
+}
+
 impl Signer {
-    fn verify<R: Read + Seek>(&self, sections: &mut ApkSections<R>) -> Result<Box<[u8]>> {
-        // 1. Choose the strongest supported signature algorithm ID from signatures. The strength
-        //    ordering is up to each implementation/platform version.
-        let strongest: &Signature = self
+    /// Select the signature that uses the strongest algorithm according to the preferences of the
+    /// v4 signing scheme.
+    fn strongest_signature(&self) -> Result<&Signature> {
+        Ok(self
             .signatures
             .iter()
             .filter(|sig| is_supported_signature_algorithm(sig.signature_algorithm_id))
             .max_by_key(|sig| rank_signature_algorithm(sig.signature_algorithm_id).unwrap())
-            .ok_or_else(|| anyhow!("No supported signatures found"))?;
+            .ok_or_else(|| anyhow!("No supported signatures found"))?)
+    }
+
+    fn pick_v4_apk_digest(&self) -> Result<(u32, Box<[u8]>)> {
+        let strongest = self.strongest_signature()?;
+        let signed_data: SignedData = self.signed_data.slice(..).read()?;
+        let digest = signed_data
+            .digests
+            .iter()
+            .find(|&dig| dig.signature_algorithm_id == strongest.signature_algorithm_id)
+            .ok_or_else(|| anyhow!("Digest not found"))?;
+        Ok((digest.signature_algorithm_id, digest.digest.as_ref().to_vec().into_boxed_slice()))
+    }
+
+    fn verify<R: Read + Seek>(&self, sections: &mut ApkSections<R>) -> Result<Box<[u8]>> {
+        // 1. Choose the strongest supported signature algorithm ID from signatures.
+        let strongest = self.strongest_signature()?;
 
         // 2. Verify the corresponding signature from signatures against signed data using public key.
         //    (It is now safe to parse signed data.)
diff --git a/libs/idsig/Android.bp b/libs/idsig/Android.bp
index 2e9c663..25eeae4 100644
--- a/libs/idsig/Android.bp
+++ b/libs/idsig/Android.bp
@@ -10,6 +10,7 @@
     prefer_rlib: true,
     rustlibs: [
         "libanyhow",
+        "libapkverify",
         "libbyteorder",
         "libnum_traits",
         "libopenssl",
diff --git a/libs/idsig/src/apksigv4.rs b/libs/idsig/src/apksigv4.rs
index 3004ed1..db8a8c6 100644
--- a/libs/idsig/src/apksigv4.rs
+++ b/libs/idsig/src/apksigv4.rs
@@ -15,6 +15,7 @@
  */
 
 use anyhow::{anyhow, bail, Context, Result};
+use apkverify::pick_v4_apk_digest;
 use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
 use num_derive::{FromPrimitive, ToPrimitive};
 use num_traits::{FromPrimitive, ToPrimitive};
@@ -190,9 +191,12 @@
         ret.hashing_info.raw_root_hash = hash_tree.root_hash.into_boxed_slice();
         ret.hashing_info.log2_blocksize = log2(block_size);
 
-        // TODO(jiyong): fill the signing_info struct by reading the APK file. The information,
-        // especially `apk_digest` is needed to check if `V4Signature` is outdated, in which case
-        // it needs to be created from the updated APK.
+        apk.seek(SeekFrom::Start(start))?;
+        let (signature_algorithm_id, apk_digest) = pick_v4_apk_digest(apk)?;
+        ret.signing_info.signature_algorithm_id =
+            SignatureAlgorithmId::from(signature_algorithm_id)?;
+        ret.signing_info.apk_digest = apk_digest;
+        // TODO(jiyong): add a signature to the signing_info struct
 
         Ok(ret)
     }