[apk_digest] Return SignatureAlgorithmID when fetching apk digest

This CL changes the apk digest fetch API's return type from raw
integer to SignatureAlgorithmID enum. This API is used in avmd
and idsig.

Bug: 246254355
Test: avmdtool_tests libidsig.test libapkverify.test
Change-Id: I4aba18e22324f74af328115a6cadd718eb45f220
diff --git a/avmd/Android.bp b/avmd/Android.bp
index 7237f5f..6d91b59 100644
--- a/avmd/Android.bp
+++ b/avmd/Android.bp
@@ -11,6 +11,7 @@
     rustlibs: [
         "libserde",
         "libapexutil_rust", // TODO(b/239413416): Remove this after adding hex
+        "libapkverify",
     ],
 }
 
diff --git a/avmd/src/avmd.rs b/avmd/src/avmd.rs
index 50cdfdf..05fc201 100644
--- a/avmd/src/avmd.rs
+++ b/avmd/src/avmd.rs
@@ -19,6 +19,7 @@
     vec::Vec,
 };
 use apexutil::to_hex_string;
+use apkverify::SignatureAlgorithmID;
 use core::fmt;
 use serde::{Deserialize, Serialize};
 
@@ -120,7 +121,7 @@
     /// It should be one of the algorithms in the [list][].
     ///
     /// [list]: https://source.android.com/security/apksigning/v2#signature-algorithm-ids
-    pub signature_algorithm_id: u32,
+    pub signature_algorithm_id: SignatureAlgorithmID,
     /// Digest of the APK's v3 signing block. TODO: fix
     pub apk_digest: Vec<u8>,
 }
@@ -130,7 +131,7 @@
         writeln!(f, "  APK descriptor:")?;
         writeln!(f, "    namespace:             {}", self.resource.namespace)?;
         writeln!(f, "    name:                  {}", self.resource.name)?;
-        writeln!(f, "    Signing algorithm ID:  {:#x}", self.signature_algorithm_id)?;
+        writeln!(f, "    Signing algorithm ID:  {:#04x}", self.signature_algorithm_id.to_u32())?;
         writeln!(f, "    APK digest:            {}", to_hex_string(&self.apk_digest))?;
         Ok(())
     }
diff --git a/avmd/tests/data/test.avmd b/avmd/tests/data/test.avmd
index 52e634f..e567125 100644
--- a/avmd/tests/data/test.avmd
+++ b/avmd/tests/data/test.avmd
Binary files differ
diff --git a/libs/apkverify/Android.bp b/libs/apkverify/Android.bp
index 9bb8f8e..78192d2 100644
--- a/libs/apkverify/Android.bp
+++ b/libs/apkverify/Android.bp
@@ -15,6 +15,7 @@
         "liblog_rust",
         "libnum_traits",
         "libopenssl",
+        "libserde",
         "libzip",
     ],
     proc_macros: ["libnum_derive"],
diff --git a/libs/apkverify/src/algorithms.rs b/libs/apkverify/src/algorithms.rs
index 9a5144c..622df3b 100644
--- a/libs/apkverify/src/algorithms.rs
+++ b/libs/apkverify/src/algorithms.rs
@@ -18,16 +18,18 @@
 
 use anyhow::{ensure, Result};
 use num_derive::{FromPrimitive, ToPrimitive};
+use num_traits::ToPrimitive;
 use openssl::hash::MessageDigest;
 use openssl::pkey::{self, PKey};
 use openssl::rsa::Padding;
 use openssl::sign::Verifier;
+use serde::{Deserialize, Serialize};
 
 /// [Signature Algorithm IDs]: https://source.android.com/docs/security/apksigning/v2#signature-algorithm-ids
 /// [SignatureAlgorithm.java]: (tools/apksig/src/main/java/com/android/apksig/internal/apk/SignatureAlgorithm.java)
 ///
 /// Some of the algorithms are not implemented. See b/197052981.
-#[derive(Clone, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
 #[repr(u32)]
 pub enum SignatureAlgorithmID {
     /// RSASSA-PSS with SHA2-256 digest, SHA2-256 MGF1, 32 bytes of salt, trailer: 0xbc, content
@@ -77,6 +79,11 @@
 }
 
 impl SignatureAlgorithmID {
+    /// Converts the signature algorithm ID to the corresponding u32.
+    pub fn to_u32(&self) -> u32 {
+        ToPrimitive::to_u32(self).expect("Unsupported algorithm for to_u32.")
+    }
+
     pub(crate) fn new_verifier<'a>(
         &self,
         public_key: &'a PKey<pkey::Public>,
@@ -86,7 +93,7 @@
                 self,
                 SignatureAlgorithmID::DsaWithSha256 | SignatureAlgorithmID::VerityDsaWithSha256
             ),
-            "TODO(b/197052981): Algorithm '{:#?}' is not implemented.",
+            "TODO(b/197052981): Algorithm '{:?}' is not implemented.",
             self
         );
         ensure!(public_key.id() == self.pkey_id(), "Public key has the wrong ID");
diff --git a/libs/apkverify/src/sigutil.rs b/libs/apkverify/src/sigutil.rs
index fabb8e6..bfa51c1 100644
--- a/libs/apkverify/src/sigutil.rs
+++ b/libs/apkverify/src/sigutil.rs
@@ -16,10 +16,6 @@
 
 //! Utilities for Signature Verification
 
-// TODO(b/246254355): Remove this once we migrate all the usages of
-// raw signature algorithm id to the enum.
-#![allow(dead_code)]
-
 use anyhow::{anyhow, ensure, Error, Result};
 use byteorder::{LittleEndian, ReadBytesExt};
 use bytes::{Buf, BufMut, Bytes, BytesMut};
@@ -33,19 +29,9 @@
 const APK_SIG_BLOCK_MIN_SIZE: u32 = 32;
 const APK_SIG_BLOCK_MAGIC: u128 = 0x3234206b636f6c4220676953204b5041;
 
-// TODO(b/246254355): Migrates usages of raw signature algorithm id to the enum.
-pub const SIGNATURE_RSA_PSS_WITH_SHA256: u32 = 0x0101;
-pub const SIGNATURE_RSA_PSS_WITH_SHA512: u32 = 0x0102;
-pub const SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256: u32 = 0x0103;
-pub const SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512: u32 = 0x0104;
-pub const SIGNATURE_ECDSA_WITH_SHA256: u32 = 0x0201;
-pub const SIGNATURE_ECDSA_WITH_SHA512: u32 = 0x0202;
-pub const SIGNATURE_DSA_WITH_SHA256: u32 = 0x0301;
-pub const SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256: u32 = 0x0421;
-pub const SIGNATURE_VERITY_ECDSA_WITH_SHA256: u32 = 0x0423;
-pub const SIGNATURE_VERITY_DSA_WITH_SHA256: u32 = 0x0425;
-
 const CHUNK_SIZE_BYTES: u64 = 1024 * 1024;
+const CHUNK_HEADER_TOP: &[u8] = &[0x5a];
+const CHUNK_HEADER_MID: &[u8] = &[0xa5];
 
 /// The [APK structure] has four major sections:
 ///
@@ -166,9 +152,6 @@
     message_digest: MessageDigest,
 }
 
-const CHUNK_HEADER_TOP: &[u8] = &[0x5a];
-const CHUNK_HEADER_MID: &[u8] = &[0xa5];
-
 impl Digester {
     // v2/v3 digests are computed after prepending "header" byte and "size" info.
     fn digest(&self, data: &[u8], header: &[u8], size: u32) -> Result<DigestBytes> {
diff --git a/libs/apkverify/src/v3.rs b/libs/apkverify/src/v3.rs
index 2f8fb45..875fec8 100644
--- a/libs/apkverify/src/v3.rs
+++ b/libs/apkverify/src/v3.rs
@@ -127,7 +127,7 @@
 /// Gets the v4 [apk_digest].
 ///
 /// [apk_digest]: https://source.android.com/docs/security/apksigning/v4#apk-digest
-pub fn pick_v4_apk_digest<R: Read + Seek>(apk: R) -> Result<(u32, Box<[u8]>)> {
+pub fn pick_v4_apk_digest<R: Read + Seek>(apk: R) -> Result<(SignatureAlgorithmID, 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>()?;
@@ -151,7 +151,7 @@
             .context("No supported signatures found")?)
     }
 
-    fn pick_v4_apk_digest(&self) -> Result<(u32, Box<[u8]>)> {
+    fn pick_v4_apk_digest(&self) -> Result<(SignatureAlgorithmID, Box<[u8]>)> {
         let strongest = self.strongest_signature()?;
         let signed_data: SignedData = self.signed_data.slice(..).read()?;
         let digest = signed_data
@@ -159,7 +159,10 @@
             .iter()
             .find(|&dig| dig.signature_algorithm_id == strongest.signature_algorithm_id)
             .context("Digest not found")?;
-        Ok((digest.signature_algorithm_id, digest.digest.as_ref().to_vec().into_boxed_slice()))
+        // TODO(b/246254355): Remove this conversion once Digest contains the enum SignatureAlgorithmID
+        let signature_algorithm_id = SignatureAlgorithmID::from_u32(digest.signature_algorithm_id)
+            .context("Unsupported algorithm")?;
+        Ok((signature_algorithm_id, digest.digest.as_ref().to_vec().into_boxed_slice()))
     }
 
     /// The steps in this method implements APK Signature Scheme v3 verification step 3.
@@ -297,7 +300,7 @@
     fn test_pick_v4_apk_digest_only_with_v3_dsa_sha256() {
         check_v4_apk_digest(
             "tests/data/v3-only-with-dsa-sha256-1024.apk",
-            SIGNATURE_DSA_WITH_SHA256,
+            SignatureAlgorithmID::DsaWithSha256,
             "0DF2426EA33AEDAF495D88E5BE0C6A1663FF0A81C5ED12D5B2929AE4B4300F2F",
         );
     }
@@ -306,13 +309,17 @@
     fn test_pick_v4_apk_digest_only_with_v3_pkcs1_sha512() {
         check_v4_apk_digest(
             "tests/data/v3-only-with-rsa-pkcs1-sha512-1024.apk",
-            SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512,
+            SignatureAlgorithmID::RsaPkcs1V15WithSha512,
             "9B9AE02DA60B18999BF541790F00D380006FDF0655C3C482AA0BB0AF17CF7A42\
              ECF56B973518546C9080B2FEF83027E895ED2882BFC88EA19790BBAB29AF53B3",
         );
     }
 
-    fn check_v4_apk_digest(apk_filename: &str, expected_algorithm: u32, expected_digest: &str) {
+    fn check_v4_apk_digest(
+        apk_filename: &str,
+        expected_algorithm: SignatureAlgorithmID,
+        expected_digest: &str,
+    ) {
         let apk_file = File::open(apk_filename).unwrap();
         let (signature_algorithm_id, apk_digest) = pick_v4_apk_digest(apk_file).unwrap();
 
diff --git a/libs/idsig/src/apksigv4.rs b/libs/idsig/src/apksigv4.rs
index 92f8963..c1b6495 100644
--- a/libs/idsig/src/apksigv4.rs
+++ b/libs/idsig/src/apksigv4.rs
@@ -159,11 +159,7 @@
 
         apk.seek(SeekFrom::Start(start))?;
         let (signature_algorithm_id, apk_digest) = pick_v4_apk_digest(apk)?;
-        // TODO(b/246254355): Removes this conversion once pick_v4_apk_digest
-        // returns the enum SignatureAlgorithmID instead of raw integer.
-        ret.signing_info.signature_algorithm_id =
-            SignatureAlgorithmID::from_u32(signature_algorithm_id)
-                .context("Unsupported algorithm")?;
+        ret.signing_info.signature_algorithm_id = signature_algorithm_id;
         ret.signing_info.apk_digest = apk_digest;
         // TODO(jiyong): add a signature to the signing_info struct
 
@@ -261,7 +257,7 @@
         write_sized_array(&mut w, &self.x509_certificate)?;
         write_sized_array(&mut w, &self.additional_data)?;
         write_sized_array(&mut w, &self.public_key)?;
-        w.write_u32::<LittleEndian>(self.signature_algorithm_id.to_u32().unwrap())?;
+        w.write_u32::<LittleEndian>(self.signature_algorithm_id.to_u32())?;
         write_sized_array(&mut w, &self.signature)?;
 
         // Determine the size of signing_info, and write it in front of the struct where the value