[apkverify] Use SignatureAlgorithmID in Digest/Signature

This CL uses SignatureAlgorithmID for the signature_algorithm_id
field in Digest/Signature.

Bug: 246254355
Test: libapkverify.integration_test
Change-Id: Ic36c001b007f80498479c2cc2cdf8991c548d1da
diff --git a/libs/apkverify/src/algorithms.rs b/libs/apkverify/src/algorithms.rs
index 622df3b..a1cf368 100644
--- a/libs/apkverify/src/algorithms.rs
+++ b/libs/apkverify/src/algorithms.rs
@@ -17,19 +17,22 @@
 //! Algorithms used for APK Signature Scheme.
 
 use anyhow::{ensure, Result};
+use bytes::{Buf, Bytes};
 use num_derive::{FromPrimitive, ToPrimitive};
-use num_traits::ToPrimitive;
+use num_traits::{FromPrimitive, ToPrimitive};
 use openssl::hash::MessageDigest;
 use openssl::pkey::{self, PKey};
 use openssl::rsa::Padding;
 use openssl::sign::Verifier;
 use serde::{Deserialize, Serialize};
 
+use crate::bytes_ext::ReadFromBytes;
+
 /// [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(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
+#[derive(Serialize, Deserialize, Clone, Copy, 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
@@ -78,6 +81,12 @@
     }
 }
 
+impl ReadFromBytes for Option<SignatureAlgorithmID> {
+    fn read_from_bytes(buf: &mut Bytes) -> Result<Self> {
+        Ok(SignatureAlgorithmID::from_u32(buf.get_u32_le()))
+    }
+}
+
 impl SignatureAlgorithmID {
     /// Converts the signature algorithm ID to the corresponding u32.
     pub fn to_u32(&self) -> u32 {
@@ -153,7 +162,7 @@
         }
     }
 
-    pub(crate) fn to_content_digest_algorithm(&self) -> ContentDigestAlgorithm {
+    pub(crate) fn content_digest_algorithm(&self) -> ContentDigestAlgorithm {
         match self {
             SignatureAlgorithmID::RsaPssWithSha256
             | SignatureAlgorithmID::RsaPkcs1V15WithSha256
diff --git a/libs/apkverify/src/v3.rs b/libs/apkverify/src/v3.rs
index 0fe2f2b..a3e738b 100644
--- a/libs/apkverify/src/v3.rs
+++ b/libs/apkverify/src/v3.rs
@@ -20,7 +20,6 @@
 
 use anyhow::{ensure, Context, Result};
 use bytes::Bytes;
-use num_traits::FromPrimitive;
 use openssl::pkey::{self, PKey};
 use openssl::x509::X509;
 use std::fs::File;
@@ -70,13 +69,13 @@
 
 #[derive(Debug)]
 struct Signature {
-    /// TODO(b/246254355): Change the type of signature_algorithm_id to SignatureAlgorithmID
-    signature_algorithm_id: u32,
+    /// Option is used here to allow us to ignore unsupported algorithm.
+    signature_algorithm_id: Option<SignatureAlgorithmID>,
     signature: LengthPrefixed<Bytes>,
 }
 
 struct Digest {
-    signature_algorithm_id: u32,
+    signature_algorithm_id: Option<SignatureAlgorithmID>,
     digest: LengthPrefixed<Bytes>,
 }
 
@@ -142,12 +141,8 @@
         Ok(self
             .signatures
             .iter()
-            .filter(|sig| SignatureAlgorithmID::from_u32(sig.signature_algorithm_id).is_some())
-            .max_by_key(|sig| {
-                SignatureAlgorithmID::from_u32(sig.signature_algorithm_id)
-                    .unwrap()
-                    .to_content_digest_algorithm()
-            })
+            .filter(|sig| sig.signature_algorithm_id.is_some())
+            .max_by_key(|sig| sig.signature_algorithm_id.unwrap().content_digest_algorithm())
             .context("No supported signatures found")?)
     }
 
@@ -159,10 +154,10 @@
             .iter()
             .find(|&dig| dig.signature_algorithm_id == strongest.signature_algorithm_id)
             .context("Digest not found")?;
-        // 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()))
+        Ok((
+            digest.signature_algorithm_id.context("Unsupported algorithm")?,
+            digest.digest.as_ref().to_vec().into_boxed_slice(),
+        ))
     }
 
     /// The steps in this method implements APK Signature Scheme v3 verification step 3.
@@ -202,12 +197,8 @@
             .iter()
             .find(|&dig| dig.signature_algorithm_id == strongest.signature_algorithm_id)
             .unwrap(); // ok to unwrap since we check if two lists are the same above
-        let computed = sections.compute_digest(
-            // TODO(b/246254355): Removes the conversion once Digest contains the enum
-            // SignatureAlgorithmID.
-            SignatureAlgorithmID::from_u32(digest.signature_algorithm_id)
-                .context("Unsupported algorithm")?,
-        )?;
+        let computed = sections
+            .compute_digest(digest.signature_algorithm_id.context("Unsupported algorithm")?)?;
 
         // 6. Verify that the computed digest is identical to the corresponding digest from digests.
         ensure!(
@@ -238,7 +229,8 @@
     signature: &Signature,
     public_key: &PKey<pkey::Public>,
 ) -> Result<()> {
-    let mut verifier = SignatureAlgorithmID::from_u32(signature.signature_algorithm_id)
+    let mut verifier = signature
+        .signature_algorithm_id
         .context("Unsupported algorithm")?
         .new_verifier(public_key)?;
     verifier.update(data)?;