aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Groover <mpgroover@google.com>2022-04-26 15:17:14 -0700
committerMichael Groover <mpgroover@google.com>2022-04-26 15:17:14 -0700
commit8083582d084031424d959afb679a2114c9a5d4ac (patch)
tree6c20a33b3909f7b814b3e2fb1308e605d83c82ac
parent45343b234b5c563e424177c66e6c6021edc7a013 (diff)
downloadapksig-8083582d084031424d959afb679a2114c9a5d4ac.tar.gz
Ensure v3.0 signer returned when app min SDK equals rotation min SDK
Android T introduced the v3.1 signature scheme that allows apps to target APK signing key rotation to an SDK version T+ and the original signing key will be used for previous releases. Since releases under development use the SDK version of the previously released SDK, the v3.1 scheme also supports targeting a development release; in the case of T, the v3.1 block will target Sv2's SDK version (32) during development and the v3.0 block will use 32 as the max SDK version for the block. However, if an app's minSdkVersion is set to 32, the previous behavior would only return the v3.1 signer causing v3.0 signing to fail due to a missing signing config. This commit updates the logic to continue parsing the signers if the v3.1's minSdkVersion is equal to the app's minSdkVersion when supporting a development release. Bug: 230340743 Test: gradlew test Change-Id: Ibd13f899c7686cd5db6e509b6a2ecca73992b732
-rw-r--r--src/main/java/com/android/apksig/DefaultApkSignerEngine.java9
-rw-r--r--src/test/java/com/android/apksig/ApkSignerTest.java31
-rw-r--r--src/test/resources/com/android/apksig/original-minSdk32.apkbin0 -> 12695 bytes
3 files changed, 39 insertions, 1 deletions
diff --git a/src/main/java/com/android/apksig/DefaultApkSignerEngine.java b/src/main/java/com/android/apksig/DefaultApkSignerEngine.java
index 6423804..62c24bc 100644
--- a/src/main/java/com/android/apksig/DefaultApkSignerEngine.java
+++ b/src/main/java/com/android/apksig/DefaultApkSignerEngine.java
@@ -426,7 +426,14 @@ public class DefaultApkSignerEngine implements ApkSignerEngine {
// at this point (and likely only one will be needed
processedConfigs.add(config);
currentMinSdk = config.minSdkVersion;
- if (currentMinSdk <= mMinSdkVersion || currentMinSdk <= AndroidSdkVersion.P) {
+ // If the rotation is targeting a development release and this is the v3.1 signer, then
+ // the minSdkVersion of this signer should equal the maxSdkVersion of the next signer;
+ // this ensures a package with the minSdkVersion set to the rotationMinSdkVersion has
+ // a v3.0 block with the min / max SDK version set to this same minSdkVersion from the
+ // v3.1 block.
+ if ((mRotationTargetsDevRelease && currentMinSdk < mMinSdkVersion)
+ || (!mRotationTargetsDevRelease && currentMinSdk <= mMinSdkVersion)
+ || currentMinSdk <= AndroidSdkVersion.P) {
// this satisfies all we need, stop here
break;
}
diff --git a/src/test/java/com/android/apksig/ApkSignerTest.java b/src/test/java/com/android/apksig/ApkSignerTest.java
index 46126bb..adc3a38 100644
--- a/src/test/java/com/android/apksig/ApkSignerTest.java
+++ b/src/test/java/com/android/apksig/ApkSignerTest.java
@@ -1804,6 +1804,37 @@ public class ApkSignerTest {
}
@Test
+ public void testV31_rotationMinSdkVersionEqualsMinSdkVersion_v3SignerPresent()
+ throws Exception {
+ // The SDK version for Sv2 (32) is used as the minSdkVersion for the V3.1 signature
+ // scheme to allow rotation to target the T development platform; this will be updated
+ // to the real SDK version of T once its SDK is finalized. This test verifies if a
+ // package has Sv2 as its minSdkVersion, the signing can complete as expected with the
+ // v3 block signed by the original signer and targeting just Sv2, and the v3.1 block
+ // signed by the rotated signer and targeting the dev release of Sv2 and all later releases.
+ List<ApkSigner.SignerConfig> rsa2048SignerConfigWithLineage =
+ Arrays.asList(
+ getDefaultSignerConfigFromResources(FIRST_RSA_2048_SIGNER_RESOURCE_NAME),
+ getDefaultSignerConfigFromResources(SECOND_RSA_2048_SIGNER_RESOURCE_NAME));
+ SigningCertificateLineage lineage =
+ Resources.toSigningCertificateLineage(
+ ApkSignerTest.class, LINEAGE_RSA_2048_2_SIGNERS_RESOURCE_NAME);
+
+ File signedApk = sign("original-minSdk32.apk",
+ new ApkSigner.Builder(rsa2048SignerConfigWithLineage)
+ .setV1SigningEnabled(true)
+ .setV2SigningEnabled(true)
+ .setV3SigningEnabled(true)
+ .setV4SigningEnabled(false)
+ .setMinSdkVersionForRotation(V3SchemeConstants.MIN_SDK_WITH_V31_SUPPORT)
+ .setSigningCertificateLineage(lineage));
+ ApkVerifier.Result result = verify(signedApk, null);
+
+ assertVerified(result);
+ assertEquals(AndroidSdkVersion.Sv2, result.getV3SchemeSigners().get(0).getMaxSdkVersion());
+ }
+
+ @Test
public void testV31_rotationMinSdkVersionTWithoutLineage_v30VerificationSucceeds()
throws Exception {
// apksig allows setting a rotation-min-sdk-version without providing a rotated signing
diff --git a/src/test/resources/com/android/apksig/original-minSdk32.apk b/src/test/resources/com/android/apksig/original-minSdk32.apk
new file mode 100644
index 0000000..1d50f27
--- /dev/null
+++ b/src/test/resources/com/android/apksig/original-minSdk32.apk
Binary files differ