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(())
}