diff options
| author | Alex Buynytskyy <alexbuy@google.com> | 2021-10-21 00:05:40 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2021-10-21 00:05:40 +0000 |
| commit | 28a541fff39878c2c83324fb84ffaa044d1ff6b6 (patch) | |
| tree | 96f9a9206f0e5fcd4075a6393a0d566dfb5a1691 /core/java | |
| parent | 3baf0f069c1f9099302e10d0921dae4eb7fa6a1d (diff) | |
| parent | 0de533f5ce1160f9818d9b6194f696ac1a28ac62 (diff) | |
Merge "Optimization to avoid parsing v2/v3/v31 blocks."
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/util/apk/ApkSignatureSchemeV4Verifier.java | 27 | ||||
| -rw-r--r-- | core/java/android/util/apk/ApkSignatureVerifier.java | 71 |
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); |
