[apkverify] Refactor verify_signed_data to use SignatureAlgorithmID

This CL refactor verify_signed_data to use SignatureAlgorithmID
enum instead of the raw integers. There's no behavior change in
this CL.

Bug: 246254355
Test: libapkverify.integration_test
Change-Id: I1296efb9a700d2fe3f6ec93f69cdc407a6882a0d
diff --git a/libs/apkverify/src/algorithms.rs b/libs/apkverify/src/algorithms.rs
index f15f0a4..ee9c869 100644
--- a/libs/apkverify/src/algorithms.rs
+++ b/libs/apkverify/src/algorithms.rs
@@ -16,9 +16,12 @@
 
 //! Algorithms used for APK Signature Scheme.
 
-use anyhow::{bail, Result};
+use anyhow::{bail, ensure, Result};
 use num_derive::FromPrimitive;
 use openssl::hash::MessageDigest;
+use openssl::pkey::{self, PKey};
+use openssl::rsa::Padding;
+use openssl::sign::Verifier;
 use std::cmp::Ordering;
 
 /// [Signature Algorithm IDs]: https://source.android.com/docs/security/apksigning/v2#signature-algorithm-ids
@@ -76,6 +79,77 @@
             }
         }
     }
+
+    pub(crate) fn new_verifier<'a>(
+        &self,
+        public_key: &'a PKey<pkey::Public>,
+    ) -> Result<Verifier<'a>> {
+        ensure!(
+            !matches!(
+                self,
+                SignatureAlgorithmID::EcdsaWithSha512
+                    | SignatureAlgorithmID::DsaWithSha256
+                    | SignatureAlgorithmID::VerityDsaWithSha256
+            ),
+            "TODO(b/197052981): Algorithm '{:#?}' is not implemented.",
+            self
+        );
+        ensure!(public_key.id() == self.pkey_id(), "Public key has the wrong ID");
+        let mut verifier = Verifier::new(self.new_message_digest(), public_key)?;
+        if public_key.id() == pkey::Id::RSA {
+            verifier.set_rsa_padding(self.rsa_padding())?;
+        }
+        Ok(verifier)
+    }
+
+    /// Returns the message digest corresponding to the signature algorithm
+    /// according to the spec [Signature Algorithm IDs].
+    fn new_message_digest(&self) -> MessageDigest {
+        match self {
+            SignatureAlgorithmID::RsaPssWithSha256
+            | SignatureAlgorithmID::RsaPkcs1V15WithSha256
+            | SignatureAlgorithmID::EcdsaWithSha256
+            | SignatureAlgorithmID::DsaWithSha256
+            | SignatureAlgorithmID::VerityRsaPkcs1V15WithSha256
+            | SignatureAlgorithmID::VerityEcdsaWithSha256
+            | SignatureAlgorithmID::VerityDsaWithSha256 => MessageDigest::sha256(),
+            SignatureAlgorithmID::RsaPssWithSha512
+            | SignatureAlgorithmID::RsaPkcs1V15WithSha512
+            | SignatureAlgorithmID::EcdsaWithSha512 => MessageDigest::sha512(),
+        }
+    }
+
+    fn pkey_id(&self) -> pkey::Id {
+        match self {
+            SignatureAlgorithmID::RsaPssWithSha256
+            | SignatureAlgorithmID::RsaPssWithSha512
+            | SignatureAlgorithmID::RsaPkcs1V15WithSha256
+            | SignatureAlgorithmID::RsaPkcs1V15WithSha512
+            | SignatureAlgorithmID::VerityRsaPkcs1V15WithSha256 => pkey::Id::RSA,
+            SignatureAlgorithmID::EcdsaWithSha256
+            | SignatureAlgorithmID::EcdsaWithSha512
+            | SignatureAlgorithmID::VerityEcdsaWithSha256 => pkey::Id::EC,
+            SignatureAlgorithmID::DsaWithSha256 | SignatureAlgorithmID::VerityDsaWithSha256 => {
+                pkey::Id::DSA
+            }
+        }
+    }
+
+    fn rsa_padding(&self) -> Padding {
+        match self {
+            SignatureAlgorithmID::RsaPssWithSha256 | SignatureAlgorithmID::RsaPssWithSha512 => {
+                Padding::PKCS1_PSS
+            }
+            SignatureAlgorithmID::RsaPkcs1V15WithSha256
+            | SignatureAlgorithmID::VerityRsaPkcs1V15WithSha256
+            | SignatureAlgorithmID::RsaPkcs1V15WithSha512 => Padding::PKCS1,
+            SignatureAlgorithmID::EcdsaWithSha256
+            | SignatureAlgorithmID::EcdsaWithSha512
+            | SignatureAlgorithmID::VerityEcdsaWithSha256
+            | SignatureAlgorithmID::DsaWithSha256
+            | SignatureAlgorithmID::VerityDsaWithSha256 => Padding::NONE,
+        }
+    }
 }
 
 /// The rank of the content digest algorithm in this enum is used to help pick