apkverify: Migrate from ring to openssl crate

Switch to using the certified implementation of cryptographic
algorithms, boringssl, that's available through the openssl crate.

Add an ECDSA signed APK to the test suite to give that algorithm some
coverage.

Bug: 232676161
Test: atest libapkverify.test
Test: atest libapkverify.integration_test
Change-Id: I5f86b40e110d8aaeb22109757253950bd7824833
diff --git a/libs/apkverify/Android.bp b/libs/apkverify/Android.bp
index df1cac6..4c0e1f8 100644
--- a/libs/apkverify/Android.bp
+++ b/libs/apkverify/Android.bp
@@ -13,7 +13,7 @@
         "libbyteorder",
         "libbytes",
         "liblog_rust",
-        "libring",
+        "libopenssl",
         "libx509_parser",
         "libzip",
     ],
diff --git a/libs/apkverify/src/sigutil.rs b/libs/apkverify/src/sigutil.rs
index 23dd91e..009154f 100644
--- a/libs/apkverify/src/sigutil.rs
+++ b/libs/apkverify/src/sigutil.rs
@@ -19,7 +19,7 @@
 use anyhow::{anyhow, bail, Result};
 use byteorder::{LittleEndian, ReadBytesExt};
 use bytes::{Buf, BufMut, Bytes, BytesMut};
-use ring::digest;
+use openssl::hash::{DigestBytes, Hasher, MessageDigest};
 use std::cmp::min;
 use std::io::{Cursor, Read, Seek, SeekFrom, Take};
 
@@ -107,12 +107,12 @@
                 let slice = &mut chunk[..(chunk_size as usize)];
                 data.read_exact(slice)?;
                 digests_of_chunks.put_slice(
-                    digester.digest(slice, CHUNK_HEADER_MID, chunk_size as u32).as_ref(),
+                    digester.digest(slice, CHUNK_HEADER_MID, chunk_size as u32)?.as_ref(),
                 );
                 chunk_count += 1;
             }
         }
-        Ok(digester.digest(&digests_of_chunks, CHUNK_HEADER_TOP, chunk_count).as_ref().into())
+        Ok(digester.digest(&digests_of_chunks, CHUNK_HEADER_TOP, chunk_count)?.as_ref().into())
     }
 
     fn zip_entries(&mut self) -> Result<Take<Box<dyn Read + '_>>> {
@@ -157,7 +157,7 @@
 }
 
 struct Digester {
-    algorithm: &'static digest::Algorithm,
+    algorithm: MessageDigest,
 }
 
 const CHUNK_HEADER_TOP: &[u8] = &[0x5a];
@@ -167,8 +167,8 @@
     fn new(signature_algorithm_id: u32) -> Result<Digester> {
         let digest_algorithm_id = to_content_digest_algorithm(signature_algorithm_id)?;
         let algorithm = match digest_algorithm_id {
-            CONTENT_DIGEST_CHUNKED_SHA256 => &digest::SHA256,
-            CONTENT_DIGEST_CHUNKED_SHA512 => &digest::SHA512,
+            CONTENT_DIGEST_CHUNKED_SHA256 => MessageDigest::sha256(),
+            CONTENT_DIGEST_CHUNKED_SHA512 => MessageDigest::sha512(),
             // TODO(jooyung): implement
             CONTENT_DIGEST_VERITY_CHUNKED_SHA256 => {
                 bail!("TODO(b/190343842): CONTENT_DIGEST_VERITY_CHUNKED_SHA256: not implemented")
@@ -179,12 +179,12 @@
     }
 
     // v2/v3 digests are computed after prepending "header" byte and "size" info.
-    fn digest(&self, data: &[u8], header: &[u8], size: u32) -> digest::Digest {
-        let mut ctx = digest::Context::new(self.algorithm);
-        ctx.update(header);
-        ctx.update(&size.to_le_bytes());
-        ctx.update(data);
-        ctx.finish()
+    fn digest(&self, data: &[u8], header: &[u8], size: u32) -> Result<DigestBytes> {
+        let mut ctx = Hasher::new(self.algorithm)?;
+        ctx.update(header)?;
+        ctx.update(&size.to_le_bytes())?;
+        ctx.update(data)?;
+        Ok(ctx.finish()?)
     }
 }
 
diff --git a/libs/apkverify/src/v3.rs b/libs/apkverify/src/v3.rs
index eb12498..16530be 100644
--- a/libs/apkverify/src/v3.rs
+++ b/libs/apkverify/src/v3.rs
@@ -19,12 +19,12 @@
 // TODO(jooyung) remove this
 #![allow(dead_code)]
 
-use anyhow::{anyhow, bail, Context, Result};
+use anyhow::{anyhow, bail, ensure, Context, Result};
 use bytes::Bytes;
-use ring::signature::{
-    UnparsedPublicKey, VerificationAlgorithm, ECDSA_P256_SHA256_ASN1, RSA_PKCS1_2048_8192_SHA256,
-    RSA_PKCS1_2048_8192_SHA512, RSA_PSS_2048_8192_SHA256, RSA_PSS_2048_8192_SHA512,
-};
+use openssl::hash::MessageDigest;
+use openssl::pkey::{self, PKey};
+use openssl::rsa::Padding;
+use openssl::sign::Verifier;
 use std::fs::File;
 use std::io::{Read, Seek};
 use std::ops::Range;
@@ -200,14 +200,22 @@
     signature: &Signature,
     key_info: &SubjectPublicKeyInfo,
 ) -> Result<()> {
-    let verification_alg: &dyn VerificationAlgorithm = match signature.signature_algorithm_id {
-        SIGNATURE_RSA_PSS_WITH_SHA256 => &RSA_PSS_2048_8192_SHA256,
-        SIGNATURE_RSA_PSS_WITH_SHA512 => &RSA_PSS_2048_8192_SHA512,
-        SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256 | SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256 => {
-            &RSA_PKCS1_2048_8192_SHA256
+    let (pkey_id, padding, digest) = match signature.signature_algorithm_id {
+        SIGNATURE_RSA_PSS_WITH_SHA256 => {
+            (pkey::Id::RSA, Padding::PKCS1_PSS, MessageDigest::sha256())
         }
-        SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512 => &RSA_PKCS1_2048_8192_SHA512,
-        SIGNATURE_ECDSA_WITH_SHA256 | SIGNATURE_VERITY_ECDSA_WITH_SHA256 => &ECDSA_P256_SHA256_ASN1,
+        SIGNATURE_RSA_PSS_WITH_SHA512 => {
+            (pkey::Id::RSA, Padding::PKCS1_PSS, MessageDigest::sha512())
+        }
+        SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256 | SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256 => {
+            (pkey::Id::RSA, Padding::PKCS1, MessageDigest::sha256())
+        }
+        SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512 => {
+            (pkey::Id::RSA, Padding::PKCS1, MessageDigest::sha512())
+        }
+        SIGNATURE_ECDSA_WITH_SHA256 | SIGNATURE_VERITY_ECDSA_WITH_SHA256 => {
+            (pkey::Id::EC, Padding::NONE, MessageDigest::sha256())
+        }
         // TODO(b/190343842) not implemented signature algorithm
         SIGNATURE_ECDSA_WITH_SHA512
         | SIGNATURE_DSA_WITH_SHA256
@@ -219,8 +227,15 @@
         }
         _ => bail!("Unsupported signature algorithm: {:#x}", signature.signature_algorithm_id),
     };
-    let key = UnparsedPublicKey::new(verification_alg, &key_info.subject_public_key);
-    key.verify(data.as_ref(), signature.signature.as_ref())?;
+    let key = PKey::public_key_from_der(key_info.raw)?;
+    ensure!(key.id() == pkey_id, "Public key has the wrong ID");
+    let mut verifier = Verifier::new(digest, &key)?;
+    if pkey_id == pkey::Id::RSA {
+        verifier.set_rsa_padding(padding)?;
+    }
+    verifier.update(data)?;
+    let verified = verifier.verify(&signature.signature)?;
+    ensure!(verified, "Signature is invalid ");
     Ok(())
 }
 
diff --git a/libs/apkverify/tests/apkverify_test.rs b/libs/apkverify/tests/apkverify_test.rs
index ade4468..22faba4 100644
--- a/libs/apkverify/tests/apkverify_test.rs
+++ b/libs/apkverify/tests/apkverify_test.rs
@@ -23,6 +23,11 @@
 }
 
 #[test]
+fn test_verify_v3_ecdsa_sha256_p256() {
+    assert!(verify("tests/data/v3-only-with-ecdsa-sha256-p256.apk").is_ok());
+}
+
+#[test]
 fn test_verify_v3_digest_mismatch() {
     let res = verify("tests/data/v3-only-with-rsa-pkcs1-sha512-8192-digest-mismatch.apk");
     assert!(res.is_err());
diff --git a/libs/apkverify/tests/data/v3-only-with-ecdsa-sha256-p256.apk b/libs/apkverify/tests/data/v3-only-with-ecdsa-sha256-p256.apk
new file mode 100644
index 0000000..5ef4fec
--- /dev/null
+++ b/libs/apkverify/tests/data/v3-only-with-ecdsa-sha256-p256.apk
Binary files differ