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

Commit 27eef5cf authored by Michael Groover's avatar Michael Groover
Browse files

Add support for knownSigner permission protection flag

This commit adds support for a new permission protection flag that
allows a permission declaration to also include an array resource of
trusted signing certificate digests. A permission declared with this
new knownSigner permission flag will be granted to a requesting app
if that app's current signer, or any of the previous signers in its
lineage, are in the declared trusted signing certificate set.

Bug: 172970984
Test: atest SigningDetailsTest
Test: atest PkgInstallSignatureVerificationTest
Change-Id: I54ff2ac720c3a1828d0606426197f7f0e0d0d4b5
parent 17e971d5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -849,6 +849,7 @@ package android {
    field public static final int keyboardNavigationCluster = 16844096; // 0x1010540
    field public static final int keycode = 16842949; // 0x10100c5
    field public static final int killAfterRestore = 16843420; // 0x101029c
    field public static final int knownCerts = 16844330; // 0x101062a
    field public static final int label = 16842753; // 0x1010001
    field public static final int labelFor = 16843718; // 0x10103c6
    field @Deprecated public static final int labelTextSize = 16843317; // 0x1010235
+1 −0
Original line number Diff line number Diff line
@@ -2632,6 +2632,7 @@ package android.content.pm {
    field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000
    field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
    field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000
    field public static final int PROTECTION_FLAG_KNOWN_SIGNER = 134217728; // 0x8000000
    field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
    field public static final int PROTECTION_FLAG_RECENTS = 33554432; // 0x2000000
    field public static final int PROTECTION_FLAG_RETAIL_DEMO = 16777216; // 0x1000000
+50 −0
Original line number Diff line number Diff line
@@ -6150,6 +6150,56 @@ public class PackageParser {
            return getDescendantOrSelf(otherSigningDetails) != null;
        }

        /**
         * Returns whether this instance is currently signed, or has ever been signed, with a
         * signing certificate from the provided {@link Set} of {@code certDigests}.
         *
         * <p>The provided {@code certDigests} should contain the SHA-256 digest of the DER encoding
         * of each trusted certificate with the digest characters in upper case. If this instance
         * has multiple signers then all signers must be in the provided {@code Set}. If this
         * instance has a signing lineage then this method will return true if any of the previous
         * signers in the lineage match one of the entries in the {@code Set}.
         */
        public boolean hasAncestorOrSelfWithDigest(Set<String> certDigests) {
            if (this == UNKNOWN || certDigests == null || certDigests.size() == 0) {
                return false;
            }
            // If an app is signed by multiple signers then all of the signers must be in the Set.
            if (signatures.length > 1) {
                // If the Set has less elements than the number of signatures then immediately
                // return false as there's no way to satisfy the requirement of all signatures being
                // in the Set.
                if (certDigests.size() < signatures.length) {
                    return false;
                }
                for (Signature signature : signatures) {
                    String signatureDigest = PackageUtils.computeSha256Digest(
                            signature.toByteArray());
                    if (!certDigests.contains(signatureDigest)) {
                        return false;
                    }
                }
                return true;
            }

            String signatureDigest = PackageUtils.computeSha256Digest(signatures[0].toByteArray());
            if (certDigests.contains(signatureDigest)) {
                return true;
            }
            if (hasPastSigningCertificates()) {
                // The last element in the pastSigningCertificates array is the current signer;
                // since that was verified above just check all the signers in the lineage.
                for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
                    signatureDigest = PackageUtils.computeSha256Digest(
                            pastSigningCertificates[i].toByteArray());
                    if (certDigests.contains(signatureDigest)) {
                        return true;
                    }
                }
            }
            return false;
        }

        /**
         * Returns the SigningDetails with a descendant (or same) signer after verifying the
         * descendant has the same, a superset, or a subset of the lineage of the ancestor.
+23 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.text.TextUtils;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Set;

/**
 * Information you can retrieve about a particular security permission
@@ -278,6 +279,15 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
    @SystemApi
    public static final int PROTECTION_FLAG_ROLE = 0x4000000;

    /**
     * Additional flag for {@link #protectionLevel}, correspoinding to the {@code knownSigner} value
     * of {@link android.R.attr#protectionLevel}.
     *
     * @hide
     */
    @SystemApi
    public static final int PROTECTION_FLAG_KNOWN_SIGNER = 0x8000000;

    /** @hide */
    @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = {
            PROTECTION_FLAG_PRIVILEGED,
@@ -303,6 +313,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
            PROTECTION_FLAG_RETAIL_DEMO,
            PROTECTION_FLAG_RECENTS,
            PROTECTION_FLAG_ROLE,
            PROTECTION_FLAG_KNOWN_SIGNER,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ProtectionFlags {}
@@ -466,6 +477,15 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
     */
    public @Nullable CharSequence nonLocalizedDescription;

    /**
     * A {@link Set} of trusted signing certificate digests. If this permission has the {@link
     * #PROTECTION_FLAG_KNOWN_SIGNER} flag set the permission will be granted to a requesting app
     * if the app is signed by any of these certificates.
     *
     * @hide
     */
    public @Nullable Set<String> knownCerts;

    /** @hide */
    public static int fixProtectionLevel(int level) {
        if (level == PROTECTION_SIGNATURE_OR_SYSTEM) {
@@ -570,6 +590,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
        if ((level & PermissionInfo.PROTECTION_FLAG_ROLE) != 0) {
            protLevel.append("|role");
        }
        if ((level & PermissionInfo.PROTECTION_FLAG_KNOWN_SIGNER) != 0) {
            protLevel.append("|knownSigner");
        }
        return protLevel.toString();
    }

+1 −0
Original line number Diff line number Diff line
@@ -655,6 +655,7 @@ public class PackageInfoWithoutStateUtils {
        pi.protectionLevel = p.getProtectionLevel();
        pi.descriptionRes = p.getDescriptionRes();
        pi.flags = p.getFlags();
        pi.knownCerts = p.getKnownCerts();

        if ((flags & PackageManager.GET_META_DATA) == 0) {
            return pi;
Loading