Improve APK signature handling
There are two changes here:
- The maxSdk property of a signature is inclusive not exclusive
(https://source.android.com/docs/security/features/apksigning/v3),
so our mapping to a Rust Range was wrong.
- We hard-wired the platform SDK as 31; but really we should use the
version of the platform we're running on.
I thought the APK Verify library shouldn't really be reading
properties, so instead I changed the function signatures to accept the
current SDK version as a parameter. That does mean duplicating the
code to read it in virtualization manager & microdroid manager, but I
can live with that for now.
Bug: 271500509
Bug: 190343842
Test: atest MicrodroidTests
Test: run a VM from an APK signed with minSdk = 33
Change-Id: I7ec7a201d05a6545847eb9b264abe642de883e0b
diff --git a/libs/apkverify/tests/apkverify_test.rs b/libs/apkverify/tests/apkverify_test.rs
index baf7c42..f08b357 100644
--- a/libs/apkverify/tests/apkverify_test.rs
+++ b/libs/apkverify/tests/apkverify_test.rs
@@ -23,10 +23,12 @@
const KEY_NAMES_ECDSA: &[&str] = &["p256", "p384", "p521"];
const KEY_NAMES_RSA: &[&str] = &["1024", "2048", "3072", "4096", "8192", "16384"];
+const SDK_INT: u32 = 31;
+
#[test]
fn test_verify_truncated_cd() {
use zip::result::ZipError;
- let res = verify("tests/data/v2-only-truncated-cd.apk");
+ let res = verify("tests/data/v2-only-truncated-cd.apk", SDK_INT);
// TODO(b/190343842): consider making a helper for err assertion
assert!(matches!(
res.unwrap_err().root_cause().downcast_ref::<ZipError>().unwrap(),
@@ -42,7 +44,7 @@
#[test]
fn apks_signed_with_v3_dsa_sha256_are_not_supported() {
for key_name in KEY_NAMES_DSA.iter() {
- let res = verify(format!("tests/data/v3-only-with-dsa-sha256-{}.apk", key_name));
+ let res = verify(format!("tests/data/v3-only-with-dsa-sha256-{}.apk", key_name), SDK_INT);
assert!(res.is_err(), "DSA algorithm is not supported for verification. See b/197052981.");
assert_contains(&res.unwrap_err().to_string(), "No supported APK signatures found");
}
@@ -95,7 +97,7 @@
"tests/data/v3-only-with-rsa-pkcs1-sha256-3072-sig-does-not-verify.apk",
];
for path in path_list.iter() {
- let res = verify(path);
+ let res = verify(path, SDK_INT);
assert!(res.is_err());
assert_contains(&res.unwrap_err().to_string(), "Signature is invalid");
}
@@ -103,22 +105,25 @@
#[test]
fn test_verify_v3_digest_mismatch() {
- let res = verify("tests/data/v3-only-with-rsa-pkcs1-sha512-8192-digest-mismatch.apk");
+ let res = verify("tests/data/v3-only-with-rsa-pkcs1-sha512-8192-digest-mismatch.apk", SDK_INT);
assert!(res.is_err());
assert_contains(&res.unwrap_err().to_string(), "Digest mismatch");
}
#[test]
fn test_verify_v3_wrong_apk_sig_block_magic() {
- let res = verify("tests/data/v3-only-with-ecdsa-sha512-p384-wrong-apk-sig-block-magic.apk");
+ let res =
+ verify("tests/data/v3-only-with-ecdsa-sha512-p384-wrong-apk-sig-block-magic.apk", SDK_INT);
assert!(res.is_err());
assert_contains(&res.unwrap_err().to_string(), "No APK Signing Block");
}
#[test]
fn test_verify_v3_apk_sig_block_size_mismatch() {
- let res =
- verify("tests/data/v3-only-with-rsa-pkcs1-sha512-4096-apk-sig-block-size-mismatch.apk");
+ let res = verify(
+ "tests/data/v3-only-with-rsa-pkcs1-sha512-4096-apk-sig-block-size-mismatch.apk",
+ SDK_INT,
+ );
assert!(res.is_err());
assert_contains(
&res.unwrap_err().to_string(),
@@ -128,35 +133,35 @@
#[test]
fn test_verify_v3_cert_and_public_key_mismatch() {
- let res = verify("tests/data/v3-only-cert-and-public-key-mismatch.apk");
+ let res = verify("tests/data/v3-only-cert-and-public-key-mismatch.apk", SDK_INT);
assert!(res.is_err());
assert_contains(&res.unwrap_err().to_string(), "Public key mismatch");
}
#[test]
fn test_verify_v3_empty() {
- let res = verify("tests/data/v3-only-empty.apk");
+ let res = verify("tests/data/v3-only-empty.apk", SDK_INT);
assert!(res.is_err());
assert_contains(&res.unwrap_err().to_string(), "APK too small for APK Signing Block");
}
#[test]
fn test_verify_v3_no_certs_in_sig() {
- let res = verify("tests/data/v3-only-no-certs-in-sig.apk");
+ let res = verify("tests/data/v3-only-no-certs-in-sig.apk", SDK_INT);
assert!(res.is_err());
assert_contains(&res.unwrap_err().to_string(), "No certificates listed");
}
#[test]
fn test_verify_v3_no_supported_sig_algs() {
- let res = verify("tests/data/v3-only-no-supported-sig-algs.apk");
+ let res = verify("tests/data/v3-only-no-supported-sig-algs.apk", SDK_INT);
assert!(res.is_err());
assert_contains(&res.unwrap_err().to_string(), "No supported APK signatures found");
}
#[test]
fn test_verify_v3_signatures_and_digests_block_mismatch() {
- let res = verify("tests/data/v3-only-signatures-and-digests-block-mismatch.apk");
+ let res = verify("tests/data/v3-only-signatures-and-digests-block-mismatch.apk", SDK_INT);
assert!(res.is_err());
assert_contains(
&res.unwrap_err().to_string(),
@@ -203,14 +208,14 @@
/// * public key extracted from apk without verification
/// * expected public key from the corresponding .der file
fn validate_apk_public_key<P: AsRef<Path>>(apk_path: P) {
- let public_key_from_verification = verify(&apk_path);
+ let public_key_from_verification = verify(&apk_path, SDK_INT);
let public_key_from_verification =
public_key_from_verification.expect("Error in verification result");
let expected_public_key_path = format!("{}.der", apk_path.as_ref().to_str().unwrap());
assert_bytes_eq_to_data_in_file(&public_key_from_verification, expected_public_key_path);
- let public_key_from_apk = get_public_key_der(&apk_path);
+ let public_key_from_apk = get_public_key_der(&apk_path, SDK_INT);
let public_key_from_apk =
public_key_from_apk.expect("Error when extracting public key from apk");
assert_eq!(
@@ -226,15 +231,17 @@
fn validate_apk_digest<P: AsRef<Path>>(apk_path: P, expected_algorithm_id: SignatureAlgorithmID) {
let apk = fs::File::open(&apk_path).expect("Unabled to open apk file");
- let (verified_algorithm_id, verified_digest) = get_apk_digest(&apk, /*verify=*/ true)
- .expect("Error when extracting apk digest with verification.");
+ let (verified_algorithm_id, verified_digest) =
+ get_apk_digest(&apk, SDK_INT, /*verify=*/ true)
+ .expect("Error when extracting apk digest with verification.");
assert_eq!(expected_algorithm_id, verified_algorithm_id);
let expected_digest_path = format!("{}.apk_digest", apk_path.as_ref().to_str().unwrap());
assert_bytes_eq_to_data_in_file(&verified_digest, expected_digest_path);
- let (unverified_algorithm_id, unverified_digest) = get_apk_digest(&apk, /*verify=*/ false)
- .expect("Error when extracting apk digest without verification.");
+ let (unverified_algorithm_id, unverified_digest) =
+ get_apk_digest(&apk, SDK_INT, /*verify=*/ false)
+ .expect("Error when extracting apk digest without verification.");
assert_eq!(expected_algorithm_id, unverified_algorithm_id);
assert_eq!(verified_digest, unverified_digest);
}