From 5b4c70ec3519bfb877dfecff766c391c275c1862 Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Mon, 9 Aug 2021 16:36:13 +0900 Subject: [PATCH] apkverify: signature verification over signed data Bug: 190343842 Test: MicrodroidHostTestCases Change-Id: I130daa50995f30b3a2315a46d8d2f743d20ed0f2 --- apkverify/Android.bp | 2 ++ apkverify/src/bytes_ext.rs | 2 +- apkverify/src/sigutil.rs | 20 +++++++++---------- apkverify/src/v3.rs | 41 +++++++++++++++++++++++++++++++++----- 4 files changed, 49 insertions(+), 16 deletions(-) diff --git a/apkverify/Android.bp b/apkverify/Android.bp index 2187b775..8a983206 100644 --- a/apkverify/Android.bp +++ b/apkverify/Android.bp @@ -14,6 +14,8 @@ rust_library { "libbyteorder", "libbytes", "liblog_rust", + "libring", + "libx509_parser", "libzip", ], } diff --git a/apkverify/src/bytes_ext.rs b/apkverify/src/bytes_ext.rs index 61848ad9..5efb33c5 100644 --- a/apkverify/src/bytes_ext.rs +++ b/apkverify/src/bytes_ext.rs @@ -20,7 +20,7 @@ use anyhow::{bail, Result}; use bytes::{Buf, Bytes}; use std::ops::Deref; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct LengthPrefixed { inner: T, } diff --git a/apkverify/src/sigutil.rs b/apkverify/src/sigutil.rs index 43fbe67e..9de794a1 100644 --- a/apkverify/src/sigutil.rs +++ b/apkverify/src/sigutil.rs @@ -27,16 +27,16 @@ const APK_SIG_BLOCK_MIN_SIZE: u32 = 32; 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 1bf8a611..91043ab1 100644 --- a/apkverify/src/v3.rs +++ b/apkverify/src/v3.rs @@ -26,7 +26,7 @@ use std::ops::Range; 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 @@ struct Signer { min_sdk: u32, max_sdk: u32, signatures: LengthPrefixed>>, - public_key: LengthPrefixed, + public_key: LengthPrefixed, } impl Signer { @@ -66,6 +66,7 @@ impl SignedData { } } +#[derive(Debug)] struct Signature { signature_algorithm_id: u32, signature: LengthPrefixed, @@ -76,6 +77,7 @@ struct Digest { digest: LengthPrefixed, } +type SubjectPublicKeyInfo = Bytes; type X509Certificate = Bytes; type AdditionalAttributes = Bytes; @@ -122,7 +124,7 @@ impl Signer { // 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 @@ impl Signer { } } -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(()) }