diff options
author | Michael Groover <mpgroover@google.com> | 2022-04-26 15:17:14 -0700 |
---|---|---|
committer | Michael Groover <mpgroover@google.com> | 2022-04-26 15:17:14 -0700 |
commit | 8083582d084031424d959afb679a2114c9a5d4ac (patch) | |
tree | 6c20a33b3909f7b814b3e2fb1308e605d83c82ac | |
parent | 45343b234b5c563e424177c66e6c6021edc7a013 (diff) | |
download | apksig-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.java | 9 | ||||
-rw-r--r-- | src/test/java/com/android/apksig/ApkSignerTest.java | 31 | ||||
-rw-r--r-- | src/test/resources/com/android/apksig/original-minSdk32.apk | bin | 0 -> 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 Binary files differnew file mode 100644 index 0000000..1d50f27 --- /dev/null +++ b/src/test/resources/com/android/apksig/original-minSdk32.apk |