Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e60d72f4 authored by Alex Klyubin's avatar Alex Klyubin Committed by Android (Google) Code Review
Browse files

Merge "Ignore signature stripping protection for preinstalled APKs." into nyc-dev

parents d7285c29 9b59bc45
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -1158,10 +1158,15 @@ public class PackageParser {
        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) == 0;
            jarFile = new StrictJarFile(
                    apkPath,
                    !verified // whether to verify JAR signature
                    );
                    !verified, // whether to verify JAR signature
                    signatureSchemeRollbackProtectionsEnforced);
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

            // Always verify manifest, regardless of source
+20 −4
Original line number Diff line number Diff line
@@ -58,10 +58,21 @@ public final class StrictJarFile {

    public StrictJarFile(String fileName)
            throws IOException, SecurityException {
        this(fileName, true);
        this(fileName, true, true);
    }

    public StrictJarFile(String fileName, boolean verify)
    /**
     *
     * @param verify whether to verify the file's JAR signatures and collect the corresponding
     *        signer certificates.
     * @param signatureSchemeRollbackProtectionsEnforced {@code true} to enforce protections against
     *        stripping newer signature schemes (e.g., APK Signature Scheme v2) from the file, or
     *        {@code false} to ignore any such protections. This parameter is ignored when
     *        {@code verify} is {@code false}.
     */
    public StrictJarFile(String fileName,
            boolean verify,
            boolean signatureSchemeRollbackProtectionsEnforced)
                    throws IOException, SecurityException {
        this.nativeHandle = nativeOpenJarFile(fileName);
        this.raf = new RandomAccessFile(fileName, "r");
@@ -73,7 +84,12 @@ public final class StrictJarFile {
            if (verify) {
                HashMap<String, byte[]> metaEntries = getMetaEntries();
                this.manifest = new StrictJarManifest(metaEntries.get(JarFile.MANIFEST_NAME), true);
                this.verifier = new StrictJarVerifier(fileName, manifest, metaEntries);
                this.verifier =
                        new StrictJarVerifier(
                                fileName,
                                manifest,
                                metaEntries,
                                signatureSchemeRollbackProtectionsEnforced);
                Set<String> files = manifest.getEntries().keySet();
                for (String file : files) {
                    if (findEntry(file) == null) {
+42 −33
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ class StrictJarVerifier {
    private final StrictJarManifest manifest;
    private final HashMap<String, byte[]> metaEntries;
    private final int mainAttributesEnd;
    private final boolean signatureSchemeRollbackProtectionsEnforced;

    private final Hashtable<String, HashMap<String, Attributes>> signatures =
            new Hashtable<String, HashMap<String, Attributes>>(5);
@@ -164,13 +165,19 @@ class StrictJarVerifier {
     *
     * @param name
     *            the name of the JAR file being verified.
     *
     * @param signatureSchemeRollbackProtectionsEnforced {@code true} to enforce protections against
     *        stripping newer signature schemes (e.g., APK Signature Scheme v2) from the file, or
     *        {@code false} to ignore any such protections.
     */
    StrictJarVerifier(String name, StrictJarManifest manifest,
        HashMap<String, byte[]> metaEntries) {
        HashMap<String, byte[]> metaEntries, boolean signatureSchemeRollbackProtectionsEnforced) {
        jarName = name;
        this.manifest = manifest;
        this.metaEntries = metaEntries;
        this.mainAttributesEnd = manifest.getMainAttributesEnd();
        this.signatureSchemeRollbackProtectionsEnforced =
                signatureSchemeRollbackProtectionsEnforced;
    }

    /**
@@ -357,15 +364,16 @@ class StrictJarVerifier {
            return;
        }

        // Check whether APK Signature Scheme v2 signature was stripped.
        // If requested, check whether APK Signature Scheme v2 signature was stripped.
        if (signatureSchemeRollbackProtectionsEnforced) {
            String apkSignatureSchemeIdList =
                    attributes.getValue(
                            ApkSignatureSchemeV2Verifier.SF_ATTRIBUTE_ANDROID_APK_SIGNED_NAME);
            if (apkSignatureSchemeIdList != null) {
            // This field contains a comma-separated list of APK signature scheme IDs which were
            // used to sign this APK. If an ID is known to us, it means signatures of that scheme
            // were stripped from the APK because otherwise we wouldn't have fallen back to
            // verifying the APK using the JAR signature scheme.
                // This field contains a comma-separated list of APK signature scheme IDs which
                // were used to sign this APK. If an ID is known to us, it means signatures of that
                // scheme were stripped from the APK because otherwise we wouldn't have fallen back
                // to verifying the APK using the JAR signature scheme.
                boolean v2SignatureGenerated = false;
                StringTokenizer tokenizer = new StringTokenizer(apkSignatureSchemeIdList, ",");
                while (tokenizer.hasMoreTokens()) {
@@ -380,17 +388,18 @@ class StrictJarVerifier {
                        continue;
                    }
                    if (id == ApkSignatureSchemeV2Verifier.SF_ATTRIBUTE_ANDROID_APK_SIGNED_ID) {
                    // This APK was supposed to be signed with APK Signature Scheme v2 but no such
                    // signature was found.
                        // This APK was supposed to be signed with APK Signature Scheme v2 but no
                        // such signature was found.
                        v2SignatureGenerated = true;
                        break;
                    }
                }

                if (v2SignatureGenerated) {
                throw new SecurityException(signatureFile + " indicates " + jarName + " is signed"
                        + " using APK Signature Scheme v2, but no such signature was found."
                        + " Signature stripped?");
                    throw new SecurityException(signatureFile + " indicates " + jarName
                            + " is signed using APK Signature Scheme v2, but no such signature was"
                            + " found. Signature stripped?");
                }
            }
        }