diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/content/pm/PackageParser.java | 257 | ||||
| -rw-r--r-- | core/java/android/util/apk/ApkSignatureVerifier.java | 63 |
2 files changed, 142 insertions, 178 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 367c39dfd8ff..77eb57f25613 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -85,6 +85,7 @@ import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.TypedValue; +import android.util.apk.ApkSignatureSchemeV2Verifier; import android.util.apk.ApkSignatureVerifier; import android.view.Gravity; @@ -111,7 +112,8 @@ import java.lang.reflect.Constructor; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; -import java.security.cert.CertificateException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; import java.security.spec.EncodedKeySpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; @@ -156,6 +158,10 @@ public class PackageParser { private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false); + public static final int APK_SIGNING_UNKNOWN = 0; + public static final int APK_SIGNING_V1 = 1; + public static final int APK_SIGNING_V2 = 2; + private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f; // TODO: switch outError users to PackageParserException @@ -471,7 +477,8 @@ public class PackageParser { public final int revisionCode; public final int installLocation; public final VerifierInfo[] verifiers; - public final SigningDetails signingDetails; + public final Signature[] signatures; + public final Certificate[][] certificates; public final boolean coreApp; public final boolean debuggable; public final boolean multiArch; @@ -479,11 +486,10 @@ public class PackageParser { public final boolean extractNativeLibs; public final boolean isolatedSplits; - public ApkLite(String codePath, String packageName, String splitName, - boolean isFeatureSplit, + public ApkLite(String codePath, String packageName, String splitName, boolean isFeatureSplit, String configForSplit, String usesSplitName, int versionCode, int versionCodeMajor, int revisionCode, int installLocation, List<VerifierInfo> verifiers, - SigningDetails signingDetails, boolean coreApp, + Signature[] signatures, Certificate[][] certificates, boolean coreApp, boolean debuggable, boolean multiArch, boolean use32bitAbi, boolean extractNativeLibs, boolean isolatedSplits) { this.codePath = codePath; @@ -496,8 +502,9 @@ public class PackageParser { this.versionCodeMajor = versionCodeMajor; this.revisionCode = revisionCode; this.installLocation = installLocation; - this.signingDetails = signingDetails; this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]); + this.signatures = signatures; + this.certificates = certificates; this.coreApp = coreApp; this.debuggable = debuggable; this.multiArch = multiArch; @@ -800,10 +807,10 @@ public class PackageParser { } } if ((flags&PackageManager.GET_SIGNATURES) != 0) { - if (p.mSigningDetails.hasSignatures()) { - int numberOfSigs = p.mSigningDetails.signatures.length; - pi.signatures = new Signature[numberOfSigs]; - System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs); + int N = (p.mSignatures != null) ? p.mSignatures.length : 0; + if (N > 0) { + pi.signatures = new Signature[N]; + System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N); } } return pi; @@ -1342,7 +1349,7 @@ public class PackageParser { pkg.setVolumeUuid(volumeUuid); pkg.setApplicationVolumeUuid(volumeUuid); pkg.setBaseCodePath(apkPath); - pkg.setSigningDetails(SigningDetails.UNKNOWN); + pkg.setSignatures(null); return pkg; @@ -1462,19 +1469,57 @@ public class PackageParser { return pkg; } - /** Parses the public keys from the set of signatures. */ - public static ArraySet<PublicKey> toSigningKeys(Signature[] signatures) - throws CertificateException { - ArraySet<PublicKey> keys = new ArraySet<>(signatures.length); - for (int i = 0; i < signatures.length; i++) { - keys.add(signatures[i].getPublicKey()); + public static int getApkSigningVersion(Package pkg) { + try { + if (ApkSignatureSchemeV2Verifier.hasSignature(pkg.baseCodePath)) { + return APK_SIGNING_V2; + } + return APK_SIGNING_V1; + } catch (IOException e) { + } + return APK_SIGNING_UNKNOWN; + } + + /** + * Populates the correct packages fields with the given certificates. + * <p> + * This is useful when we've already processed the certificates [such as during package + * installation through an installer session]. We don't re-process the archive and + * simply populate the correct fields. + */ + public static void populateCertificates(Package pkg, Certificate[][] certificates) + throws PackageParserException { + pkg.mCertificates = null; + pkg.mSignatures = null; + pkg.mSigningKeys = null; + + pkg.mCertificates = certificates; + try { + pkg.mSignatures = ApkSignatureVerifier.convertToSignatures(certificates); + } catch (CertificateEncodingException e) { + // certificates weren't encoded properly; something went wrong + throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, + "Failed to collect certificates from " + pkg.baseCodePath, e); + } + pkg.mSigningKeys = new ArraySet<>(certificates.length); + for (int i = 0; i < certificates.length; i++) { + Certificate[] signerCerts = certificates[i]; + Certificate signerCert = signerCerts[0]; + pkg.mSigningKeys.add(signerCert.getPublicKey()); + } + // add signatures to child packages + final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; + for (int i = 0; i < childCount; i++) { + Package childPkg = pkg.childPackages.get(i); + childPkg.mCertificates = pkg.mCertificates; + childPkg.mSignatures = pkg.mSignatures; + childPkg.mSigningKeys = pkg.mSigningKeys; } - return keys; } /** * Collect certificates from all the APKs described in the given package, - * populating {@link Package#mSigningDetails}. Also asserts that all APK + * populating {@link Package#mSignatures}. Also asserts that all APK * contents are signed correctly and consistently. */ public static void collectCertificates(Package pkg, @ParseFlags int parseFlags) @@ -1483,13 +1528,17 @@ public class PackageParser { final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; for (int i = 0; i < childCount; i++) { Package childPkg = pkg.childPackages.get(i); - childPkg.mSigningDetails = pkg.mSigningDetails; + childPkg.mCertificates = pkg.mCertificates; + childPkg.mSignatures = pkg.mSignatures; + childPkg.mSigningKeys = pkg.mSigningKeys; } } private static void collectCertificatesInternal(Package pkg, @ParseFlags int parseFlags) throws PackageParserException { - pkg.mSigningDetails = SigningDetails.UNKNOWN; + pkg.mCertificates = null; + pkg.mSignatures = null; + pkg.mSigningKeys = null; Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); try { @@ -1509,12 +1558,12 @@ public class PackageParser { throws PackageParserException { final String apkPath = apkFile.getAbsolutePath(); - int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR; + int minSignatureScheme = ApkSignatureVerifier.VERSION_JAR_SIGNATURE_SCHEME; if (pkg.applicationInfo.isStaticSharedLibrary()) { // must use v2 signing scheme - minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2; + minSignatureScheme = ApkSignatureVerifier.VERSION_APK_SIGNATURE_SCHEME_V2; } - SigningDetails verified; + ApkSignatureVerifier.Result verified; if ((parseFlags & PARSE_IS_SYSTEM_DIR) != 0) { // systemDir APKs are already trusted, save time by not verifying verified = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts( @@ -1523,7 +1572,7 @@ public class PackageParser { verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme); } if (verified.signatureSchemeVersion - < SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2) { + < ApkSignatureVerifier.VERSION_APK_SIGNATURE_SCHEME_V2) { // TODO (b/68860689): move this logic to packagemanagerserivce if ((parseFlags & PARSE_IS_EPHEMERAL) != 0) { throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, @@ -1534,10 +1583,17 @@ public class PackageParser { // Verify that entries are signed consistently with the first pkg // we encountered. Note that for splits, certificates may have // already been populated during an earlier parse of a base APK. - if (pkg.mSigningDetails == SigningDetails.UNKNOWN) { - pkg.mSigningDetails = verified; + if (pkg.mCertificates == null) { + pkg.mCertificates = verified.certs; + pkg.mSignatures = verified.sigs; + pkg.mSigningKeys = new ArraySet<>(verified.certs.length); + for (int i = 0; i < verified.certs.length; i++) { + Certificate[] signerCerts = verified.certs[i]; + Certificate signerCert = signerCerts[0]; + pkg.mSigningKeys.add(signerCert.getPublicKey()); + } } else { - if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) { + if (!Signature.areExactMatch(pkg.mSignatures, verified.sigs)) { throw new PackageParserException( INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, apkPath + " has mismatched certificates"); @@ -1599,7 +1655,8 @@ public class PackageParser { parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); - final SigningDetails signingDetails; + final Signature[] signatures; + final Certificate[][] certificates; if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) { // TODO: factor signature related items out of Package object final Package tempPkg = new Package((String) null); @@ -1609,13 +1666,15 @@ public class PackageParser { } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } - signingDetails = tempPkg.mSigningDetails; + signatures = tempPkg.mSignatures; + certificates = tempPkg.mCertificates; } else { - signingDetails = SigningDetails.UNKNOWN; + signatures = null; + certificates = null; } final AttributeSet attrs = parser; - return parseApkLite(apkPath, parser, attrs, signingDetails); + return parseApkLite(apkPath, parser, attrs, signatures, certificates); } catch (XmlPullParserException | IOException | RuntimeException e) { Slog.w(TAG, "Failed to parse " + apkPath, e); @@ -1702,7 +1761,7 @@ public class PackageParser { } private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs, - SigningDetails signingDetails) + Signature[] signatures, Certificate[][] certificates) throws IOException, XmlPullParserException, PackageParserException { final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs); @@ -1795,7 +1854,7 @@ public class PackageParser { return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit, configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode, - installLocation, verifiers, signingDetails, coreApp, debuggable, + installLocation, verifiers, signatures, certificates, coreApp, debuggable, multiArch, use32bitAbi, extractNativeLibs, isolatedSplits); } @@ -5675,117 +5734,6 @@ public class PackageParser { return true; } - /** A container for signing-related data of an application package. */ - public static final class SigningDetails implements Parcelable { - - @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN, - SigningDetails.SignatureSchemeVersion.JAR, - SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2, - SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3}) - public @interface SignatureSchemeVersion { - int UNKNOWN = 0; - int JAR = 1; - int SIGNING_BLOCK_V2 = 2; - int SIGNING_BLOCK_V3 = 3; - } - - @Nullable - public final Signature[] signatures; - @SignatureSchemeVersion - public final int signatureSchemeVersion; - @Nullable - public final ArraySet<PublicKey> publicKeys; - - /** A representation of unknown signing details. Use instead of null. */ - public static final SigningDetails UNKNOWN = - new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null); - - @VisibleForTesting - public SigningDetails(Signature[] signatures, - @SignatureSchemeVersion int signatureSchemeVersion, - ArraySet<PublicKey> keys) { - this.signatures = signatures; - this.signatureSchemeVersion = signatureSchemeVersion; - this.publicKeys = keys; - } - - public SigningDetails(Signature[] signatures, - @SignatureSchemeVersion int signatureSchemeVersion) - throws CertificateException { - this(signatures, signatureSchemeVersion, toSigningKeys(signatures)); - } - - /** Returns true if the signing details have one or more signatures. */ - public boolean hasSignatures() { - return signatures != null && signatures.length > 0; - } - - /** Returns true if the signatures in this and other match exactly. */ - public boolean signaturesMatchExactly(SigningDetails other) { - return Signature.areExactMatch(this.signatures, other.signatures); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - boolean isUnknown = UNKNOWN == this; - dest.writeBoolean(isUnknown); - if (isUnknown) { - return; - } - dest.writeTypedArray(this.signatures, flags); - dest.writeInt(this.signatureSchemeVersion); - dest.writeArraySet(this.publicKeys); - } - - protected SigningDetails(Parcel in) { - final ClassLoader boot = Object.class.getClassLoader(); - this.signatures = in.createTypedArray(Signature.CREATOR); - this.signatureSchemeVersion = in.readInt(); - this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot); - } - - public static final Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() { - @Override - public SigningDetails createFromParcel(Parcel source) { - if (source.readBoolean()) { - return UNKNOWN; - } - return new SigningDetails(source); - } - - @Override - public SigningDetails[] newArray(int size) { - return new SigningDetails[size]; - } - }; - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof SigningDetails)) return false; - - SigningDetails that = (SigningDetails) o; - - if (signatureSchemeVersion != that.signatureSchemeVersion) return false; - if (!Signature.areExactMatch(signatures, that.signatures)) return false; - return publicKeys != null ? publicKeys.equals(that.publicKeys) - : that.publicKeys == null; - } - - @Override - public int hashCode() { - int result = +Arrays.hashCode(signatures); - result = 31 * result + signatureSchemeVersion; - result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0); - return result; - } - } - /** * Representation of a full package parsed from APK files on disk. A package * consists of a single base APK, and zero or more split APKs. @@ -5892,7 +5840,8 @@ public class PackageParser { public int mSharedUserLabel; // Signatures that were read from the package. - @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN; + public Signature[] mSignatures; + public Certificate[][] mCertificates; // For use by package manager service for quick lookup of // preferred up order. @@ -5944,6 +5893,7 @@ public class PackageParser { /** * Data used to feed the KeySetManagerService */ + public ArraySet<PublicKey> mSigningKeys; public ArraySet<String> mUpgradeKeySets; public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping; @@ -6087,13 +6037,12 @@ public class PackageParser { } } - /** Sets signing details on the package and any of its children. */ - public void setSigningDetails(@NonNull SigningDetails signingDetails) { - mSigningDetails = signingDetails; + public void setSignatures(Signature[] signatures) { + this.mSignatures = signatures; if (childPackages != null) { final int packageCount = childPackages.size(); for (int i = 0; i < packageCount; i++) { - childPackages.get(i).mSigningDetails = signingDetails; + childPackages.get(i).mSignatures = signatures; } } } @@ -6399,7 +6348,8 @@ public class PackageParser { } mSharedUserLabel = dest.readInt(); - mSigningDetails = dest.readParcelable(boot); + mSignatures = (Signature[]) dest.readParcelableArray(boot, Signature.class); + mCertificates = (Certificate[][]) dest.readSerializable(); mPreferredOrder = dest.readInt(); @@ -6439,6 +6389,7 @@ public class PackageParser { mTrustedOverlay = (dest.readInt() == 1); mCompileSdkVersion = dest.readInt(); mCompileSdkVersionCodename = dest.readString(); + mSigningKeys = (ArraySet<PublicKey>) dest.readArraySet(boot); mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot); mKeySetMapping = readKeySetMapping(dest); @@ -6538,7 +6489,8 @@ public class PackageParser { dest.writeString(mSharedUserId); dest.writeInt(mSharedUserLabel); - dest.writeParcelable(mSigningDetails, flags); + dest.writeParcelableArray(mSignatures, flags); + dest.writeSerializable(mCertificates); dest.writeInt(mPreferredOrder); @@ -6563,6 +6515,7 @@ public class PackageParser { dest.writeInt(mTrustedOverlay ? 1 : 0); dest.writeInt(mCompileSdkVersion); dest.writeString(mCompileSdkVersionCodename); + dest.writeArraySet(mSigningKeys); dest.writeArraySet(mUpgradeKeySets); writeKeySetMapping(dest, mKeySetMapping); dest.writeString(cpuAbiOverride); diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java index 555c4740389a..81467292d491 100644 --- a/core/java/android/util/apk/ApkSignatureVerifier.java +++ b/core/java/android/util/apk/ApkSignatureVerifier.java @@ -25,7 +25,6 @@ import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import android.content.pm.PackageParser; import android.content.pm.PackageParser.PackageParserException; -import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion; import android.content.pm.Signature; import android.os.Trace; import android.util.jar.StrictJarFile; @@ -53,6 +52,10 @@ import java.util.zip.ZipEntry; */ public class ApkSignatureVerifier { + public static final int VERSION_JAR_SIGNATURE_SCHEME = 1; + public static final int VERSION_APK_SIGNATURE_SCHEME_V2 = 2; + public static final int VERSION_APK_SIGNATURE_SCHEME_V3 = 3; + private static final AtomicReference<byte[]> sBuffer = new AtomicReference<>(); /** @@ -60,11 +63,10 @@ public class ApkSignatureVerifier { * * @throws PackageParserException if the APK's signature failed to verify. */ - public static PackageParser.SigningDetails verify(String apkPath, - @SignatureSchemeVersion int minSignatureSchemeVersion) + public static Result verify(String apkPath, int minSignatureSchemeVersion) throws PackageParserException { - if (minSignatureSchemeVersion > SignatureSchemeVersion.SIGNING_BLOCK_V3) { + if (minSignatureSchemeVersion > VERSION_APK_SIGNATURE_SCHEME_V3) { // V3 and before are older than the requested minimum signing version throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "No signature found in package of version " + minSignatureSchemeVersion @@ -78,11 +80,10 @@ public class ApkSignatureVerifier { ApkSignatureSchemeV3Verifier.verify(apkPath); Certificate[][] signerCerts = new Certificate[][] { vSigner.certs }; Signature[] signerSigs = convertToSignatures(signerCerts); - return new PackageParser.SigningDetails(signerSigs, - SignatureSchemeVersion.SIGNING_BLOCK_V3); + return new Result(signerCerts, signerSigs, VERSION_APK_SIGNATURE_SCHEME_V3); } catch (SignatureNotFoundException e) { // not signed with v2, try older if allowed - if (minSignatureSchemeVersion >= SignatureSchemeVersion.SIGNING_BLOCK_V3) { + if (minSignatureSchemeVersion >= VERSION_APK_SIGNATURE_SCHEME_V3) { throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "No APK Signature Scheme v3 signature in package " + apkPath, e); } @@ -96,7 +97,7 @@ public class ApkSignatureVerifier { } // redundant, protective version check - if (minSignatureSchemeVersion > SignatureSchemeVersion.SIGNING_BLOCK_V2) { + if (minSignatureSchemeVersion > VERSION_APK_SIGNATURE_SCHEME_V2) { // V2 and before are older than the requested minimum signing version throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "No signature found in package of version " + minSignatureSchemeVersion @@ -109,11 +110,10 @@ public class ApkSignatureVerifier { Certificate[][] signerCerts = ApkSignatureSchemeV2Verifier.verify(apkPath); Signature[] signerSigs = convertToSignatures(signerCerts); - return new PackageParser.SigningDetails( - signerSigs, SignatureSchemeVersion.SIGNING_BLOCK_V2); + return new Result(signerCerts, signerSigs, VERSION_APK_SIGNATURE_SCHEME_V2); } catch (SignatureNotFoundException e) { // not signed with v2, try older if allowed - if (minSignatureSchemeVersion >= SignatureSchemeVersion.SIGNING_BLOCK_V2) { + if (minSignatureSchemeVersion >= VERSION_APK_SIGNATURE_SCHEME_V2) { throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "No APK Signature Scheme v2 signature in package " + apkPath, e); } @@ -127,7 +127,7 @@ public class ApkSignatureVerifier { } // redundant, protective version check - if (minSignatureSchemeVersion > SignatureSchemeVersion.JAR) { + if (minSignatureSchemeVersion > VERSION_JAR_SIGNATURE_SCHEME) { // V1 and is older than the requested minimum signing version throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "No signature found in package of version " + minSignatureSchemeVersion @@ -145,8 +145,7 @@ public class ApkSignatureVerifier { * * @throws PackageParserException if there was a problem collecting certificates */ - private static PackageParser.SigningDetails verifyV1Signature( - String apkPath, boolean verifyFull) + private static Result verifyV1Signature(String apkPath, boolean verifyFull) throws PackageParserException { StrictJarFile jarFile = null; @@ -212,7 +211,7 @@ public class ApkSignatureVerifier { } } } - return new PackageParser.SigningDetails(lastSigs, SignatureSchemeVersion.JAR); + return new Result(lastCerts, lastSigs, VERSION_JAR_SIGNATURE_SCHEME); } catch (GeneralSecurityException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING, "Failed to collect certificates from " + apkPath, e); @@ -290,11 +289,10 @@ public class ApkSignatureVerifier { * @throws PackageParserException if the APK's signature failed to verify. * or greater is not found, except in the case of no JAR signature. */ - public static PackageParser.SigningDetails plsCertsNoVerifyOnlyCerts( - String apkPath, int minSignatureSchemeVersion) + public static Result plsCertsNoVerifyOnlyCerts(String apkPath, int minSignatureSchemeVersion) throws PackageParserException { - if (minSignatureSchemeVersion > SignatureSchemeVersion.SIGNING_BLOCK_V3) { + if (minSignatureSchemeVersion > VERSION_APK_SIGNATURE_SCHEME_V3) { // V3 and before are older than the requested minimum signing version throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "No signature found in package of version " + minSignatureSchemeVersion @@ -308,11 +306,10 @@ public class ApkSignatureVerifier { ApkSignatureSchemeV3Verifier.plsCertsNoVerifyOnlyCerts(apkPath); Certificate[][] signerCerts = new Certificate[][] { vSigner.certs }; Signature[] signerSigs = convertToSignatures(signerCerts); - return new PackageParser.SigningDetails(signerSigs, - SignatureSchemeVersion.SIGNING_BLOCK_V3); + return new Result(signerCerts, signerSigs, VERSION_APK_SIGNATURE_SCHEME_V3); } catch (SignatureNotFoundException e) { // not signed with v2, try older if allowed - if (minSignatureSchemeVersion >= SignatureSchemeVersion.SIGNING_BLOCK_V3) { + if (minSignatureSchemeVersion >= VERSION_APK_SIGNATURE_SCHEME_V3) { throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "No APK Signature Scheme v3 signature in package " + apkPath, e); } @@ -326,7 +323,7 @@ public class ApkSignatureVerifier { } // redundant, protective version check - if (minSignatureSchemeVersion > SignatureSchemeVersion.SIGNING_BLOCK_V2) { + if (minSignatureSchemeVersion > VERSION_APK_SIGNATURE_SCHEME_V2) { // V2 and before are older than the requested minimum signing version throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "No signature found in package of version " + minSignatureSchemeVersion @@ -339,11 +336,10 @@ public class ApkSignatureVerifier { Certificate[][] signerCerts = ApkSignatureSchemeV2Verifier.plsCertsNoVerifyOnlyCerts(apkPath); Signature[] signerSigs = convertToSignatures(signerCerts); - return new PackageParser.SigningDetails(signerSigs, - SignatureSchemeVersion.SIGNING_BLOCK_V2); + return new Result(signerCerts, signerSigs, VERSION_APK_SIGNATURE_SCHEME_V2); } catch (SignatureNotFoundException e) { // not signed with v2, try older if allowed - if (minSignatureSchemeVersion >= SignatureSchemeVersion.SIGNING_BLOCK_V2) { + if (minSignatureSchemeVersion >= VERSION_APK_SIGNATURE_SCHEME_V2) { throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "No APK Signature Scheme v2 signature in package " + apkPath, e); } @@ -357,7 +353,7 @@ public class ApkSignatureVerifier { } // redundant, protective version check - if (minSignatureSchemeVersion > SignatureSchemeVersion.JAR) { + if (minSignatureSchemeVersion > VERSION_JAR_SIGNATURE_SCHEME) { // V1 and is older than the requested minimum signing version throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "No signature found in package of version " + minSignatureSchemeVersion @@ -367,4 +363,19 @@ public class ApkSignatureVerifier { // v2 didn't work, try jarsigner return verifyV1Signature(apkPath, false); } + + /** + * Result of a successful APK verification operation. + */ + public static class Result { + public final Certificate[][] certs; + public final Signature[] sigs; + public final int signatureSchemeVersion; + + public Result(Certificate[][] certs, Signature[] sigs, int signingVersion) { + this.certs = certs; + this.sigs = sigs; + this.signatureSchemeVersion = signingVersion; + } + } } |
