use of android.util.jar.StrictJarFile in project android_frameworks_base by crdroidandroid.
the class PackageParser method collectCertificates.
private static void collectCertificates(Package pkg, File apkFile, int parseFlags) throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
// Try to verify the APK using APK Signature Scheme v2.
boolean verified = false;
{
Certificate[][] allSignersCerts = null;
Signature[] signatures = null;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2");
allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
signatures = convertToSignatures(allSignersCerts);
// APK verified using APK Signature Scheme v2.
verified = true;
} catch (ApkSignatureSchemeV2Verifier.SignatureNotFoundException e) {
// No APK Signature Scheme v2 signature found
} catch (Exception e) {
// APK Signature Scheme v2 signature was found but did not verify
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath + " using APK Signature Scheme v2", e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
if (verified) {
if (pkg.mCertificates == null) {
pkg.mCertificates = allSignersCerts;
pkg.mSignatures = signatures;
pkg.mSigningKeys = new ArraySet<>(allSignersCerts.length);
for (int i = 0; i < allSignersCerts.length; i++) {
Certificate[] signerCerts = allSignersCerts[i];
Certificate signerCert = signerCerts[0];
pkg.mSigningKeys.add(signerCert.getPublicKey());
}
} else {
if (!Signature.areExactMatch(pkg.mSignatures, signatures)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, apkPath + " has mismatched certificates");
}
}
// Not yet done, because we need to confirm that AndroidManifest.xml exists and,
// if requested, that classes.dex exists.
}
}
StrictJarFile jarFile = null;
final String systemDir = android.os.Environment.getRootDirectory().getPath();
final boolean isSystemApk = apkPath.startsWith(systemDir);
if (isSystemApk) {
try {
final Certificate[][] entryCerts = StrictJarFile.loadSignature(apkPath);
if (!ArrayUtils.isEmpty(entryCerts)) {
final Signature[] entrySignatures = convertToSignatures(entryCerts);
pkg.mCertificates = entryCerts;
pkg.mSignatures = entrySignatures;
pkg.mSigningKeys = new ArraySet<PublicKey>();
for (int i = 0; i < entryCerts.length; i++) {
pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
}
Slog.w(TAG, "extract public cert hack performed successful for " + apkPath);
return;
} else {
Slog.w(TAG, "No certification in " + apkPath);
}
} catch (GeneralSecurityException e) {
Slog.w(TAG, "extract public cert hack is failed", e);
} catch (RuntimeException e) {
Slog.w(TAG, "extract public cert hack is failed", e);
}
}
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
// Ignore signature stripping protections when verifying APKs from system partition.
// For those APKs we only care about extracting signer certificates, and don't care
// about verifying integrity.
boolean signatureSchemeRollbackProtectionsEnforced = (parseFlags & PARSE_IS_SYSTEM_DIR) == 0;
jarFile = new StrictJarFile(apkPath, // whether to verify JAR signature
!verified, signatureSchemeRollbackProtectionsEnforced);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
// Always verify manifest, regardless of source
final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
if (manifestEntry == null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Package " + apkPath + " has no manifest");
}
// Optimization: early termination when APK already verified
if (verified) {
return;
}
// APK's integrity needs to be verified using JAR signature scheme.
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV1");
final List<ZipEntry> toVerify = new ArrayList<>();
toVerify.add(manifestEntry);
// If we're parsing an untrusted package, verify all contents
if ((parseFlags & PARSE_IS_SYSTEM_DIR) == 0) {
final Iterator<ZipEntry> i = jarFile.iterator();
while (i.hasNext()) {
final ZipEntry entry = i.next();
if (entry.isDirectory())
continue;
final String entryName = entry.getName();
if (entryName.startsWith("META-INF/"))
continue;
if (entryName.equals(ANDROID_MANIFEST_FILENAME))
continue;
toVerify.add(entry);
}
}
// already been populated during an earlier parse of a base APK.
for (ZipEntry entry : toVerify) {
final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
if (ArrayUtils.isEmpty(entryCerts)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Package " + apkPath + " has no certificates at entry " + entry.getName());
}
final Signature[] entrySignatures = convertToSignatures(entryCerts);
if (pkg.mCertificates == null) {
pkg.mCertificates = entryCerts;
pkg.mSignatures = entrySignatures;
pkg.mSigningKeys = new ArraySet<PublicKey>();
for (int i = 0; i < entryCerts.length; i++) {
pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
}
} else {
if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath + " has mismatched certificates at entry " + entry.getName());
}
}
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
} catch (GeneralSecurityException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING, "Failed to collect certificates from " + apkPath, e);
} catch (IOException | RuntimeException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath, e);
} finally {
closeQuietly(jarFile);
}
}
use of android.util.jar.StrictJarFile in project platform_frameworks_base by android.
the class PackageParser method collectCertificates.
private static void collectCertificates(Package pkg, File apkFile, int parseFlags) throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
// Try to verify the APK using APK Signature Scheme v2.
boolean verified = false;
{
Certificate[][] allSignersCerts = null;
Signature[] signatures = null;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2");
allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
signatures = convertToSignatures(allSignersCerts);
// APK verified using APK Signature Scheme v2.
verified = true;
} catch (ApkSignatureSchemeV2Verifier.SignatureNotFoundException e) {
// No APK Signature Scheme v2 signature found
} catch (Exception e) {
// APK Signature Scheme v2 signature was found but did not verify
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath + " using APK Signature Scheme v2", e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
if (verified) {
if (pkg.mCertificates == null) {
pkg.mCertificates = allSignersCerts;
pkg.mSignatures = signatures;
pkg.mSigningKeys = new ArraySet<>(allSignersCerts.length);
for (int i = 0; i < allSignersCerts.length; i++) {
Certificate[] signerCerts = allSignersCerts[i];
Certificate signerCert = signerCerts[0];
pkg.mSigningKeys.add(signerCert.getPublicKey());
}
} else {
if (!Signature.areExactMatch(pkg.mSignatures, signatures)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, apkPath + " has mismatched certificates");
}
}
// Not yet done, because we need to confirm that AndroidManifest.xml exists and,
// if requested, that classes.dex exists.
}
}
StrictJarFile jarFile = null;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
// Ignore signature stripping protections when verifying APKs from system partition.
// For those APKs we only care about extracting signer certificates, and don't care
// about verifying integrity.
boolean signatureSchemeRollbackProtectionsEnforced = (parseFlags & PARSE_IS_SYSTEM_DIR) == 0;
jarFile = new StrictJarFile(apkPath, // whether to verify JAR signature
!verified, signatureSchemeRollbackProtectionsEnforced);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
// Always verify manifest, regardless of source
final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
if (manifestEntry == null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Package " + apkPath + " has no manifest");
}
// Optimization: early termination when APK already verified
if (verified) {
return;
}
// APK's integrity needs to be verified using JAR signature scheme.
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV1");
final List<ZipEntry> toVerify = new ArrayList<>();
toVerify.add(manifestEntry);
// If we're parsing an untrusted package, verify all contents
if ((parseFlags & PARSE_IS_SYSTEM_DIR) == 0) {
final Iterator<ZipEntry> i = jarFile.iterator();
while (i.hasNext()) {
final ZipEntry entry = i.next();
if (entry.isDirectory())
continue;
final String entryName = entry.getName();
if (entryName.startsWith("META-INF/"))
continue;
if (entryName.equals(ANDROID_MANIFEST_FILENAME))
continue;
toVerify.add(entry);
}
}
// already been populated during an earlier parse of a base APK.
for (ZipEntry entry : toVerify) {
final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
if (ArrayUtils.isEmpty(entryCerts)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Package " + apkPath + " has no certificates at entry " + entry.getName());
}
final Signature[] entrySignatures = convertToSignatures(entryCerts);
if (pkg.mCertificates == null) {
pkg.mCertificates = entryCerts;
pkg.mSignatures = entrySignatures;
pkg.mSigningKeys = new ArraySet<PublicKey>();
for (int i = 0; i < entryCerts.length; i++) {
pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
}
} else {
if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath + " has mismatched certificates at entry " + entry.getName());
}
}
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
} catch (GeneralSecurityException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING, "Failed to collect certificates from " + apkPath, e);
} catch (IOException | RuntimeException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath, e);
} finally {
closeQuietly(jarFile);
}
}
use of android.util.jar.StrictJarFile in project android_frameworks_base by AOSPA.
the class PackageParser method collectCertificates.
private static void collectCertificates(Package pkg, File apkFile, int parseFlags) throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
// Try to verify the APK using APK Signature Scheme v2.
boolean verified = false;
{
Certificate[][] allSignersCerts = null;
Signature[] signatures = null;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2");
allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
signatures = convertToSignatures(allSignersCerts);
// APK verified using APK Signature Scheme v2.
verified = true;
} catch (ApkSignatureSchemeV2Verifier.SignatureNotFoundException e) {
// No APK Signature Scheme v2 signature found
} catch (Exception e) {
// APK Signature Scheme v2 signature was found but did not verify
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath + " using APK Signature Scheme v2", e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
if (verified) {
if (pkg.mCertificates == null) {
pkg.mCertificates = allSignersCerts;
pkg.mSignatures = signatures;
pkg.mSigningKeys = new ArraySet<>(allSignersCerts.length);
for (int i = 0; i < allSignersCerts.length; i++) {
Certificate[] signerCerts = allSignersCerts[i];
Certificate signerCert = signerCerts[0];
pkg.mSigningKeys.add(signerCert.getPublicKey());
}
} else {
if (!Signature.areExactMatch(pkg.mSignatures, signatures)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, apkPath + " has mismatched certificates");
}
}
// Not yet done, because we need to confirm that AndroidManifest.xml exists and,
// if requested, that classes.dex exists.
}
}
StrictJarFile jarFile = null;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
// Ignore signature stripping protections when verifying APKs from system partition.
// For those APKs we only care about extracting signer certificates, and don't care
// about verifying integrity.
boolean signatureSchemeRollbackProtectionsEnforced = (parseFlags & PARSE_IS_SYSTEM_DIR) == 0;
jarFile = new StrictJarFile(apkPath, // whether to verify JAR signature
!verified, signatureSchemeRollbackProtectionsEnforced);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
// Always verify manifest, regardless of source
final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
if (manifestEntry == null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Package " + apkPath + " has no manifest");
}
// Optimization: early termination when APK already verified
if (verified) {
return;
}
// APK's integrity needs to be verified using JAR signature scheme.
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV1");
final List<ZipEntry> toVerify = new ArrayList<>();
toVerify.add(manifestEntry);
// If we're parsing an untrusted package, verify all contents
if ((parseFlags & PARSE_IS_SYSTEM_DIR) == 0) {
final Iterator<ZipEntry> i = jarFile.iterator();
while (i.hasNext()) {
final ZipEntry entry = i.next();
if (entry.isDirectory())
continue;
final String entryName = entry.getName();
if (entryName.startsWith("META-INF/"))
continue;
if (entryName.equals(ANDROID_MANIFEST_FILENAME))
continue;
toVerify.add(entry);
}
}
// already been populated during an earlier parse of a base APK.
for (ZipEntry entry : toVerify) {
final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
if (ArrayUtils.isEmpty(entryCerts)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Package " + apkPath + " has no certificates at entry " + entry.getName());
}
final Signature[] entrySignatures = convertToSignatures(entryCerts);
if (pkg.mCertificates == null) {
pkg.mCertificates = entryCerts;
pkg.mSignatures = entrySignatures;
pkg.mSigningKeys = new ArraySet<PublicKey>();
for (int i = 0; i < entryCerts.length; i++) {
pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
}
} else {
if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath + " has mismatched certificates at entry " + entry.getName());
}
}
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
} catch (GeneralSecurityException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING, "Failed to collect certificates from " + apkPath, e);
} catch (IOException | RuntimeException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath, e);
} finally {
closeQuietly(jarFile);
}
}
use of android.util.jar.StrictJarFile in project android_frameworks_base by DirtyUnicorns.
the class PackageParser method collectCertificates.
private static void collectCertificates(Package pkg, File apkFile, int parseFlags) throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
// Try to verify the APK using APK Signature Scheme v2.
boolean verified = false;
{
Certificate[][] allSignersCerts = null;
Signature[] signatures = null;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2");
allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
signatures = convertToSignatures(allSignersCerts);
// APK verified using APK Signature Scheme v2.
verified = true;
} catch (ApkSignatureSchemeV2Verifier.SignatureNotFoundException e) {
// No APK Signature Scheme v2 signature found
} catch (Exception e) {
// APK Signature Scheme v2 signature was found but did not verify
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath + " using APK Signature Scheme v2", e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
if (verified) {
if (pkg.mCertificates == null) {
pkg.mCertificates = allSignersCerts;
pkg.mSignatures = signatures;
pkg.mSigningKeys = new ArraySet<>(allSignersCerts.length);
for (int i = 0; i < allSignersCerts.length; i++) {
Certificate[] signerCerts = allSignersCerts[i];
Certificate signerCert = signerCerts[0];
pkg.mSigningKeys.add(signerCert.getPublicKey());
}
} else {
if (!Signature.areExactMatch(pkg.mSignatures, signatures)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, apkPath + " has mismatched certificates");
}
}
// Not yet done, because we need to confirm that AndroidManifest.xml exists and,
// if requested, that classes.dex exists.
}
}
StrictJarFile jarFile = null;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
// Ignore signature stripping protections when verifying APKs from system partition.
// For those APKs we only care about extracting signer certificates, and don't care
// about verifying integrity.
boolean signatureSchemeRollbackProtectionsEnforced = (parseFlags & PARSE_IS_SYSTEM_DIR) == 0;
jarFile = new StrictJarFile(apkPath, // whether to verify JAR signature
!verified, signatureSchemeRollbackProtectionsEnforced);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
// Always verify manifest, regardless of source
final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
if (manifestEntry == null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Package " + apkPath + " has no manifest");
}
// Optimization: early termination when APK already verified
if (verified) {
return;
}
// APK's integrity needs to be verified using JAR signature scheme.
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV1");
final List<ZipEntry> toVerify = new ArrayList<>();
toVerify.add(manifestEntry);
// If we're parsing an untrusted package, verify all contents
if ((parseFlags & PARSE_IS_SYSTEM_DIR) == 0) {
final Iterator<ZipEntry> i = jarFile.iterator();
while (i.hasNext()) {
final ZipEntry entry = i.next();
if (entry.isDirectory())
continue;
final String entryName = entry.getName();
if (entryName.startsWith("META-INF/"))
continue;
if (entryName.equals(ANDROID_MANIFEST_FILENAME))
continue;
toVerify.add(entry);
}
}
// already been populated during an earlier parse of a base APK.
for (ZipEntry entry : toVerify) {
final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
if (ArrayUtils.isEmpty(entryCerts)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Package " + apkPath + " has no certificates at entry " + entry.getName());
}
final Signature[] entrySignatures = convertToSignatures(entryCerts);
if (pkg.mCertificates == null) {
pkg.mCertificates = entryCerts;
pkg.mSignatures = entrySignatures;
pkg.mSigningKeys = new ArraySet<PublicKey>();
for (int i = 0; i < entryCerts.length; i++) {
pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
}
} else {
if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath + " has mismatched certificates at entry " + entry.getName());
}
}
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
} catch (GeneralSecurityException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING, "Failed to collect certificates from " + apkPath, e);
} catch (IOException | RuntimeException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath, e);
} finally {
closeQuietly(jarFile);
}
}
use of android.util.jar.StrictJarFile in project android_frameworks_base by ResurrectionRemix.
the class PackageParser method collectCertificates.
private static void collectCertificates(Package pkg, File apkFile, int parseFlags) throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
// Try to verify the APK using APK Signature Scheme v2.
boolean verified = false;
{
Certificate[][] allSignersCerts = null;
Signature[] signatures = null;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2");
allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
signatures = convertToSignatures(allSignersCerts);
// APK verified using APK Signature Scheme v2.
verified = true;
} catch (ApkSignatureSchemeV2Verifier.SignatureNotFoundException e) {
// No APK Signature Scheme v2 signature found
} catch (Exception e) {
// APK Signature Scheme v2 signature was found but did not verify
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath + " using APK Signature Scheme v2", e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
if (verified) {
if (pkg.mCertificates == null) {
pkg.mCertificates = allSignersCerts;
pkg.mSignatures = signatures;
pkg.mSigningKeys = new ArraySet<>(allSignersCerts.length);
for (int i = 0; i < allSignersCerts.length; i++) {
Certificate[] signerCerts = allSignersCerts[i];
Certificate signerCert = signerCerts[0];
pkg.mSigningKeys.add(signerCert.getPublicKey());
}
} else {
if (!Signature.areExactMatch(pkg.mSignatures, signatures)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, apkPath + " has mismatched certificates");
}
}
// Not yet done, because we need to confirm that AndroidManifest.xml exists and,
// if requested, that classes.dex exists.
}
}
StrictJarFile jarFile = null;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
// Ignore signature stripping protections when verifying APKs from system partition.
// For those APKs we only care about extracting signer certificates, and don't care
// about verifying integrity.
boolean signatureSchemeRollbackProtectionsEnforced = (parseFlags & PARSE_IS_SYSTEM_DIR) == 0;
jarFile = new StrictJarFile(apkPath, // whether to verify JAR signature
!verified, signatureSchemeRollbackProtectionsEnforced);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
// Always verify manifest, regardless of source
final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
if (manifestEntry == null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Package " + apkPath + " has no manifest");
}
// Optimization: early termination when APK already verified
if (verified) {
return;
}
// APK's integrity needs to be verified using JAR signature scheme.
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV1");
final List<ZipEntry> toVerify = new ArrayList<>();
toVerify.add(manifestEntry);
// If we're parsing an untrusted package, verify all contents
if ((parseFlags & PARSE_IS_SYSTEM_DIR) == 0) {
final Iterator<ZipEntry> i = jarFile.iterator();
while (i.hasNext()) {
final ZipEntry entry = i.next();
if (entry.isDirectory())
continue;
final String entryName = entry.getName();
if (entryName.startsWith("META-INF/"))
continue;
if (entryName.equals(ANDROID_MANIFEST_FILENAME))
continue;
toVerify.add(entry);
}
}
// already been populated during an earlier parse of a base APK.
for (ZipEntry entry : toVerify) {
final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
if (ArrayUtils.isEmpty(entryCerts)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Package " + apkPath + " has no certificates at entry " + entry.getName());
}
final Signature[] entrySignatures = convertToSignatures(entryCerts);
if (pkg.mCertificates == null) {
pkg.mCertificates = entryCerts;
pkg.mSignatures = entrySignatures;
pkg.mSigningKeys = new ArraySet<PublicKey>();
for (int i = 0; i < entryCerts.length; i++) {
pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
}
} else {
if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath + " has mismatched certificates at entry " + entry.getName());
}
}
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
} catch (GeneralSecurityException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING, "Failed to collect certificates from " + apkPath, e);
} catch (IOException | RuntimeException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath, e);
} finally {
closeQuietly(jarFile);
}
}
Aggregations