Search in sources :

Example 1 with StrictJarFile

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);
    }
}
Also used : ArraySet(android.util.ArraySet) StrictJarFile(android.util.jar.StrictJarFile) PublicKey(java.security.PublicKey) GeneralSecurityException(java.security.GeneralSecurityException) ZipEntry(java.util.zip.ZipEntry) ArrayList(java.util.ArrayList) IOException(java.io.IOException) GeneralSecurityException(java.security.GeneralSecurityException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) CertificateEncodingException(java.security.cert.CertificateEncodingException) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) IOException(java.io.IOException) Certificate(java.security.cert.Certificate)

Example 2 with StrictJarFile

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);
    }
}
Also used : ArraySet(android.util.ArraySet) StrictJarFile(android.util.jar.StrictJarFile) PublicKey(java.security.PublicKey) ZipEntry(java.util.zip.ZipEntry) GeneralSecurityException(java.security.GeneralSecurityException) ArrayList(java.util.ArrayList) IOException(java.io.IOException) GeneralSecurityException(java.security.GeneralSecurityException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) CertificateEncodingException(java.security.cert.CertificateEncodingException) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) IOException(java.io.IOException) Certificate(java.security.cert.Certificate)

Example 3 with StrictJarFile

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);
    }
}
Also used : ArraySet(android.util.ArraySet) StrictJarFile(android.util.jar.StrictJarFile) PublicKey(java.security.PublicKey) ZipEntry(java.util.zip.ZipEntry) GeneralSecurityException(java.security.GeneralSecurityException) ArrayList(java.util.ArrayList) IOException(java.io.IOException) GeneralSecurityException(java.security.GeneralSecurityException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) CertificateEncodingException(java.security.cert.CertificateEncodingException) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) IOException(java.io.IOException) Certificate(java.security.cert.Certificate)

Example 4 with StrictJarFile

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);
    }
}
Also used : ArraySet(android.util.ArraySet) StrictJarFile(android.util.jar.StrictJarFile) PublicKey(java.security.PublicKey) ZipEntry(java.util.zip.ZipEntry) GeneralSecurityException(java.security.GeneralSecurityException) ArrayList(java.util.ArrayList) IOException(java.io.IOException) GeneralSecurityException(java.security.GeneralSecurityException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) CertificateEncodingException(java.security.cert.CertificateEncodingException) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) IOException(java.io.IOException) Certificate(java.security.cert.Certificate)

Example 5 with StrictJarFile

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);
    }
}
Also used : ArraySet(android.util.ArraySet) StrictJarFile(android.util.jar.StrictJarFile) PublicKey(java.security.PublicKey) ZipEntry(java.util.zip.ZipEntry) GeneralSecurityException(java.security.GeneralSecurityException) ArrayList(java.util.ArrayList) IOException(java.io.IOException) GeneralSecurityException(java.security.GeneralSecurityException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) CertificateEncodingException(java.security.cert.CertificateEncodingException) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) IOException(java.io.IOException) Certificate(java.security.cert.Certificate)

Aggregations

ArraySet (android.util.ArraySet)5 StrictJarFile (android.util.jar.StrictJarFile)5 IOException (java.io.IOException)5 GeneralSecurityException (java.security.GeneralSecurityException)5 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)5 PublicKey (java.security.PublicKey)5 Certificate (java.security.cert.Certificate)5 CertificateEncodingException (java.security.cert.CertificateEncodingException)5 InvalidKeySpecException (java.security.spec.InvalidKeySpecException)5 ArrayList (java.util.ArrayList)5 ZipEntry (java.util.zip.ZipEntry)5 XmlPullParserException (org.xmlpull.v1.XmlPullParserException)5