summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/content/pm/PackageParser.java257
-rw-r--r--core/java/android/util/apk/ApkSignatureVerifier.java63
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;
+ }
+ }
}