apkverify: signature verification over signed data

Bug: 190343842
Test: MicrodroidHostTestCases
Change-Id: I130daa50995f30b3a2315a46d8d2f743d20ed0f2
diff --git a/apkverify/Android.bp b/apkverify/Android.bp
index 2187b77..8a98320 100644
--- a/apkverify/Android.bp
+++ b/apkverify/Android.bp
@@ -14,6 +14,8 @@
         "libbyteorder",
         "libbytes",
         "liblog_rust",
+        "libring",
+        "libx509_parser",
         "libzip",
     ],
 }
diff --git a/apkverify/src/bytes_ext.rs b/apkverify/src/bytes_ext.rs
index 61848ad..5efb33c 100644
--- a/apkverify/src/bytes_ext.rs
+++ b/apkverify/src/bytes_ext.rs
@@ -20,7 +20,7 @@
 use bytes::{Buf, Bytes};
 use std::ops::Deref;
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct LengthPrefixed<T> {
     inner: T,
 }
diff --git a/apkverify/src/sigutil.rs b/apkverify/src/sigutil.rs
index 43fbe67..9de794a 100644
--- a/apkverify/src/sigutil.rs
+++ b/apkverify/src/sigutil.rs
@@ -27,16 +27,16 @@
 const APK_SIG_BLOCK_MAGIC: u128 = 0x3234206b636f6c4220676953204b5041;
 
 // TODO(jooyung): introduce type
-const SIGNATURE_RSA_PSS_WITH_SHA256: u32 = 0x0101;
-const SIGNATURE_RSA_PSS_WITH_SHA512: u32 = 0x0102;
-const SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256: u32 = 0x0103;
-const SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512: u32 = 0x0104;
-const SIGNATURE_ECDSA_WITH_SHA256: u32 = 0x0201;
-const SIGNATURE_ECDSA_WITH_SHA512: u32 = 0x0202;
-const SIGNATURE_DSA_WITH_SHA256: u32 = 0x0301;
-const SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256: u32 = 0x0421;
-const SIGNATURE_VERITY_ECDSA_WITH_SHA256: u32 = 0x0423;
-const SIGNATURE_VERITY_DSA_WITH_SHA256: u32 = 0x0425;
+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;
 
 // TODO(jooyung): introduce type
 const CONTENT_DIGEST_CHUNKED_SHA256: u32 = 1;
diff --git a/apkverify/src/v3.rs b/apkverify/src/v3.rs
index 1bf8a61..91043ab 100644
--- a/apkverify/src/v3.rs
+++ b/apkverify/src/v3.rs
@@ -26,7 +26,7 @@
 use std::path::Path;
 
 use crate::bytes_ext::{BytesExt, LengthPrefixed, ReadFromBytes};
-use crate::sigutil::{find_signature, is_supported_signature_algorithm, rank_signature_algorithm};
+use crate::sigutil::*;
 
 pub const APK_SIGNATURE_SCHEME_V3_BLOCK_ID: u32 = 0xf05368c0;
 
@@ -43,7 +43,7 @@
     min_sdk: u32,
     max_sdk: u32,
     signatures: LengthPrefixed<Vec<LengthPrefixed<Signature>>>,
-    public_key: LengthPrefixed<Bytes>,
+    public_key: LengthPrefixed<SubjectPublicKeyInfo>,
 }
 
 impl Signer {
@@ -66,6 +66,7 @@
     }
 }
 
+#[derive(Debug)]
 struct Signature {
     signature_algorithm_id: u32,
     signature: LengthPrefixed<Bytes>,
@@ -76,6 +77,7 @@
     digest: LengthPrefixed<Bytes>,
 }
 
+type SubjectPublicKeyInfo = Bytes;
 type X509Certificate = Bytes;
 type AdditionalAttributes = Bytes;
 
@@ -122,7 +124,7 @@
 
         // 2. Verify the corresponding signature from signatures against signed data using public key.
         //    (It is now safe to parse signed data.)
-        verify_data(&self.signed_data, strongest, &self.public_key)?;
+        verify_signed_data(&self.signed_data, strongest, &self.public_key)?;
 
         // It is now safe to parse signed data.
         let signed_data: SignedData = self.signed_data.slice(..).read()?;
@@ -141,8 +143,37 @@
     }
 }
 
-fn verify_data(_data: &Bytes, _signature: &Signature, _public_key: &Bytes) -> Result<()> {
-    // TODO(jooyung): verify signed_data with signature/public key
+fn verify_signed_data(
+    data: &Bytes,
+    signature: &Signature,
+    public_key: &SubjectPublicKeyInfo,
+) -> Result<()> {
+    use ring::signature;
+    let (_, key_info) = x509_parser::x509::SubjectPublicKeyInfo::from_der(public_key.as_ref())?;
+    let verification_alg: &dyn signature::VerificationAlgorithm =
+        match signature.signature_algorithm_id {
+            SIGNATURE_RSA_PSS_WITH_SHA256 => &signature::RSA_PSS_2048_8192_SHA256,
+            SIGNATURE_RSA_PSS_WITH_SHA512 => &signature::RSA_PSS_2048_8192_SHA512,
+            SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256 | SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256 => {
+                &signature::RSA_PKCS1_2048_8192_SHA256
+            }
+            SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512 => &signature::RSA_PKCS1_2048_8192_SHA512,
+            SIGNATURE_ECDSA_WITH_SHA256 | SIGNATURE_VERITY_ECDSA_WITH_SHA256 => {
+                &signature::ECDSA_P256_SHA256_ASN1
+            }
+            // TODO(b/190343842) not implemented signature algorithm
+            SIGNATURE_ECDSA_WITH_SHA512
+            | SIGNATURE_DSA_WITH_SHA256
+            | SIGNATURE_VERITY_DSA_WITH_SHA256 => {
+                bail!(
+                    "TODO(b/190343842) not implemented signature algorithm: {:#x}",
+                    signature.signature_algorithm_id
+                );
+            }
+            _ => bail!("Unsupported signature algorithm: {:#x}", signature.signature_algorithm_id),
+        };
+    let key = signature::UnparsedPublicKey::new(verification_alg, key_info.subject_public_key.data);
+    key.verify(data.as_ref(), signature.signature.as_ref())?;
     Ok(())
 }