summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorAlex Buynytskyy <alexbuy@google.com>2021-10-21 00:05:40 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2021-10-21 00:05:40 +0000
commit28a541fff39878c2c83324fb84ffaa044d1ff6b6 (patch)
tree96f9a9206f0e5fcd4075a6393a0d566dfb5a1691 /core/java
parent3baf0f069c1f9099302e10d0921dae4eb7fa6a1d (diff)
parent0de533f5ce1160f9818d9b6194f696ac1a28ac62 (diff)
Merge "Optimization to avoid parsing v2/v3/v31 blocks."
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/util/apk/ApkSignatureSchemeV4Verifier.java27
-rw-r--r--core/java/android/util/apk/ApkSignatureVerifier.java71
2 files changed, 51 insertions, 47 deletions
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV4Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV4Verifier.java
index 49cd600d02f1..6b26155eced4 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV4Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV4Verifier.java
@@ -61,14 +61,15 @@ public class ApkSignatureSchemeV4Verifier {
*/
public static VerifiedSigner extractCertificates(String apkFile)
throws SignatureNotFoundException, SecurityException {
- V4Signature signature = extractSignature(apkFile);
- return verify(apkFile, signature, APK_SIGNATURE_SCHEME_DEFAULT);
+ Pair<V4Signature.HashingInfo, V4Signature.SigningInfos> pair = extractSignature(apkFile);
+ return verify(apkFile, pair.first, pair.second, APK_SIGNATURE_SCHEME_DEFAULT);
}
/**
* Extracts APK Signature Scheme v4 signature of the provided APK.
*/
- public static V4Signature extractSignature(String apkFile) throws SignatureNotFoundException {
+ public static Pair<V4Signature.HashingInfo, V4Signature.SigningInfos> extractSignature(
+ String apkFile) throws SignatureNotFoundException {
final File apk = new File(apkFile);
final byte[] signatureBytes = IncrementalManager.unsafeGetFileSignature(
apk.getAbsolutePath());
@@ -81,7 +82,11 @@ public class ApkSignatureSchemeV4Verifier {
throw new SecurityException(
"v4 signature version " + signature.version + " is not supported");
}
- return signature;
+ final V4Signature.HashingInfo hashingInfo = V4Signature.HashingInfo.fromByteArray(
+ signature.hashingInfo);
+ final V4Signature.SigningInfos signingInfos = V4Signature.SigningInfos.fromByteArray(
+ signature.signingInfos);
+ return Pair.create(hashingInfo, signingInfos);
} catch (IOException e) {
throw new SignatureNotFoundException("Failed to read V4 signature.", e);
}
@@ -91,17 +96,9 @@ public class ApkSignatureSchemeV4Verifier {
* Verifies APK Signature Scheme v4 signature and returns the
* certificates associated with each signer.
*/
- public static VerifiedSigner verify(String apkFile, final V4Signature signature,
- final int v3BlockId) throws SignatureNotFoundException, SecurityException {
- final V4Signature.HashingInfo hashingInfo;
- final V4Signature.SigningInfos signingInfos;
- try {
- hashingInfo = V4Signature.HashingInfo.fromByteArray(signature.hashingInfo);
- signingInfos = V4Signature.SigningInfos.fromByteArray(signature.signingInfos);
- } catch (IOException e) {
- throw new SignatureNotFoundException("Failed to read V4 signature.", e);
- }
-
+ public static VerifiedSigner verify(String apkFile, final V4Signature.HashingInfo hashingInfo,
+ final V4Signature.SigningInfos signingInfos, final int v3BlockId)
+ throws SignatureNotFoundException, SecurityException {
final V4Signature.SigningInfo signingInfo = findSigningInfoForBlockId(signingInfos,
v3BlockId);
diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java
index 13bd587ac275..41b749eb5f40 100644
--- a/core/java/android/util/apk/ApkSignatureVerifier.java
+++ b/core/java/android/util/apk/ApkSignatureVerifier.java
@@ -33,6 +33,7 @@ import android.content.pm.parsing.result.ParseResult;
import android.os.Build;
import android.os.Trace;
import android.os.incremental.V4Signature;
+import android.util.Pair;
import android.util.jar.StrictJarFile;
import com.android.internal.util.ArrayUtils;
@@ -191,47 +192,53 @@ public class ApkSignatureVerifier {
boolean verifyFull) throws SignatureNotFoundException {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, verifyFull ? "verifyV4" : "certsOnlyV4");
try {
- final V4Signature v4Signature = ApkSignatureSchemeV4Verifier.extractSignature(apkPath);
+ final Pair<V4Signature.HashingInfo, V4Signature.SigningInfos> v4Pair =
+ ApkSignatureSchemeV4Verifier.extractSignature(apkPath);
+ final V4Signature.HashingInfo hashingInfo = v4Pair.first;
+ final V4Signature.SigningInfos signingInfos = v4Pair.second;
Signature[] pastSignerSigs = null;
-
- Map<Integer, byte[]> nonstreamingDigests;
- Certificate[][] nonstreamingCerts;
+ Map<Integer, byte[]> nonstreamingDigests = null;
+ Certificate[][] nonstreamingCerts = null;
int v3BlockId = APK_SIGNATURE_SCHEME_DEFAULT;
-
- try {
- // v4 is an add-on and requires v2 or v3 signature to validate against its
- // certificate and digest
- ApkSignatureSchemeV3Verifier.VerifiedSigner v3Signer =
- ApkSignatureSchemeV3Verifier.unsafeGetCertsWithoutVerification(apkPath);
- nonstreamingDigests = v3Signer.contentDigests;
- nonstreamingCerts = new Certificate[][]{v3Signer.certs};
- if (v3Signer.por != null) {
- // populate proof-of-rotation information
- pastSignerSigs = new Signature[v3Signer.por.certs.size()];
- for (int i = 0; i < pastSignerSigs.length; i++) {
- pastSignerSigs[i] = new Signature(
- v3Signer.por.certs.get(i).getEncoded());
- pastSignerSigs[i].setFlags(v3Signer.por.flagsList.get(i));
- }
- }
- v3BlockId = v3Signer.blockId;
- } catch (SignatureNotFoundException e) {
+ // 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) {
try {
- ApkSignatureSchemeV2Verifier.VerifiedSigner v2Signer =
- ApkSignatureSchemeV2Verifier.verify(apkPath, false);
- nonstreamingDigests = v2Signer.contentDigests;
- nonstreamingCerts = v2Signer.certs;
- } catch (SignatureNotFoundException ee) {
- throw new SecurityException(
- "V4 verification failed to collect V2/V3 certificates from : "
- + apkPath, ee);
+ // v4 is an add-on and requires v2 or v3 signature to validate against its
+ // certificate and digest
+ ApkSignatureSchemeV3Verifier.VerifiedSigner v3Signer =
+ ApkSignatureSchemeV3Verifier.unsafeGetCertsWithoutVerification(apkPath);
+ nonstreamingDigests = v3Signer.contentDigests;
+ nonstreamingCerts = new Certificate[][]{v3Signer.certs};
+ if (v3Signer.por != null) {
+ // populate proof-of-rotation information
+ pastSignerSigs = new Signature[v3Signer.por.certs.size()];
+ for (int i = 0; i < pastSignerSigs.length; i++) {
+ pastSignerSigs[i] = new Signature(
+ v3Signer.por.certs.get(i).getEncoded());
+ pastSignerSigs[i].setFlags(v3Signer.por.flagsList.get(i));
+ }
+ }
+ v3BlockId = v3Signer.blockId;
+ } catch (SignatureNotFoundException e) {
+ try {
+ ApkSignatureSchemeV2Verifier.VerifiedSigner v2Signer =
+ ApkSignatureSchemeV2Verifier.verify(apkPath, false);
+ nonstreamingDigests = v2Signer.contentDigests;
+ nonstreamingCerts = v2Signer.certs;
+ } catch (SignatureNotFoundException ee) {
+ throw new SecurityException(
+ "V4 verification failed to collect V2/V3 certificates from : "
+ + apkPath, ee);
+ }
}
}
ApkSignatureSchemeV4Verifier.VerifiedSigner vSigner =
- ApkSignatureSchemeV4Verifier.verify(apkPath, v4Signature, v3BlockId);
+ ApkSignatureSchemeV4Verifier.verify(apkPath, hashingInfo, signingInfos,
+ v3BlockId);
Certificate[][] signerCerts = new Certificate[][]{vSigner.certs};
Signature[] signerSigs = convertToSignatures(signerCerts);