[pm] Always load rotated certificates for v4 signature
The optimized 'unsafe' function for loading v4 signature used to
not look into the corresponding v2/3/3.1 block in the apk, and
thus only returned the information from the v4 signature file.
That information has no past certificates - and unfortunately
we would use that in PackageManager as the main signing info
for the package when removing a split as the only action of
the installation session. It's also possible that some other
place may start using the same function for loading the main
package signing info, and lose the past signers there too.
This change ensures that we always load those, making the
'unsafe' signature loading a bit slower, but much safer to use.
Bug: 378539511
Flag: android.content.pm.always_load_past_certs_v4
Test: install a v4-signed app and remove a split
Change-Id: I59e55eddd7f93a013aa5cc39c5e577a6e7e1bec9
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index e4b8c90..255a08c 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -391,3 +391,12 @@
bug: "319137634"
is_fixed_read_only: true
}
+
+flag {
+ name: "always_load_past_certs_v4"
+ is_exported: true
+ namespace: "package_manager_service"
+ description: "Always read the corresponding v3/3.1 signature block for the current v4 to get the past rotated certificates, even when not verifying integrity."
+ bug: "378539511"
+ is_fixed_read_only: true
+}
diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java
index a4c3ed9..5910434d 100644
--- a/core/java/android/util/apk/ApkSignatureVerifier.java
+++ b/core/java/android/util/apk/ApkSignatureVerifier.java
@@ -260,9 +260,11 @@
Certificate[][] nonstreamingCerts = null;
int v3BlockId = APK_SIGNATURE_SCHEME_DEFAULT;
- // If V4 contains additional signing blocks then we need to always run v2/v3 verifier
- // to figure out which block they use.
- if (verifyFull || signingInfos.signingInfoBlocks.length > 0) {
+ // We need to always run v2/v3 verifier to figure out which block they use so we can
+ // return the past signers as well as the current one - the rotation chain is important
+ // for many callers who verify the signature origin as well as the apk integrity.
+ if (android.content.pm.Flags.alwaysLoadPastCertsV4()
+ || verifyFull || signingInfos.signingInfoBlocks.length > 0) {
try {
// v4 is an add-on and requires v2 or v3 signature to validate against its
// certificate and digest