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

Commit 5d08fb7a authored by Ömer Yaveroğlu's avatar Ömer Yaveroğlu Committed by Android (Google) Code Review
Browse files

Merge "Add a new install-time integrity formula type to check the lineages of the app certificate."

parents 9da38b87 70a8f68d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3027,6 +3027,7 @@ package android.content.integrity {
  }
  public static final class IntegrityFormula.Application {
    method @NonNull public static android.content.integrity.IntegrityFormula certificateLineageContains(@NonNull String);
    method @NonNull public static android.content.integrity.IntegrityFormula certificatesContain(@NonNull String);
    method @NonNull public static android.content.integrity.IntegrityFormula isPreInstalled();
    method @NonNull public static android.content.integrity.IntegrityFormula packageNameEquals(@NonNull String);
+25 −0
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ public final class AppInstallMetadata {
    private final String mPackageName;
    // Raw string encoding for the SHA-256 hash of the certificate of the app.
    private final List<String> mAppCertificates;
    // Raw string encoding for the SHA-256 hash of the certificate lineage/history of the app.
    private final List<String> mAppCertificateLineage;
    private final String mInstallerName;
    // Raw string encoding for the SHA-256 hash of the certificate of the installer.
    private final List<String> mInstallerCertificates;
@@ -52,6 +54,7 @@ public final class AppInstallMetadata {
    private AppInstallMetadata(Builder builder) {
        this.mPackageName = builder.mPackageName;
        this.mAppCertificates = builder.mAppCertificates;
        this.mAppCertificateLineage = builder.mAppCertificateLineage;
        this.mInstallerName = builder.mInstallerName;
        this.mInstallerCertificates = builder.mInstallerCertificates;
        this.mVersionCode = builder.mVersionCode;
@@ -73,6 +76,11 @@ public final class AppInstallMetadata {
        return mAppCertificates;
    }

    @NonNull
    public List<String> getAppCertificateLineage() {
        return mAppCertificateLineage;
    }

    @NonNull
    public String getInstallerName() {
        return mInstallerName;
@@ -126,6 +134,7 @@ public final class AppInstallMetadata {
                    + " %b, StampVerified = %b, StampTrusted = %b, StampCert = %s }",
                mPackageName,
                mAppCertificates,
                mAppCertificateLineage,
                mInstallerName == null ? "null" : mInstallerName,
                mInstallerCertificates == null ? "null" : mInstallerCertificates,
                mVersionCode,
@@ -140,6 +149,7 @@ public final class AppInstallMetadata {
    public static final class Builder {
        private String mPackageName;
        private List<String> mAppCertificates;
        private List<String> mAppCertificateLineage;
        private String mInstallerName;
        private List<String> mInstallerCertificates;
        private long mVersionCode;
@@ -191,6 +201,20 @@ public final class AppInstallMetadata {
            return this;
        }

        /**
         * Set the list of (old and new) certificates used for signing the app to be installed.
         *
         * <p>It is represented as the raw string encoding for the SHA-256 hash of the certificate
         * lineage/history of the app.
         *
         * @see AppInstallMetadata#getAppCertificateLineage()
         */
        @NonNull
        public Builder setAppCertificateLineage(@NonNull List<String> appCertificateLineage) {
            this.mAppCertificateLineage = Objects.requireNonNull(appCertificateLineage);
            return this;
        }

        /**
         * Set name of the installer installing the app.
         *
@@ -294,6 +318,7 @@ public final class AppInstallMetadata {
        public AppInstallMetadata build() {
            Objects.requireNonNull(mPackageName);
            Objects.requireNonNull(mAppCertificates);
            Objects.requireNonNull(mAppCertificateLineage);
            return new AppInstallMetadata(this);
        }
    }
+40 −7
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ public abstract class AtomicFormula extends IntegrityFormula {
                PRE_INSTALLED,
                STAMP_TRUSTED,
                STAMP_CERTIFICATE_HASH,
                APP_CERTIFICATE_LINEAGE,
            })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Key {}
@@ -122,6 +123,13 @@ public abstract class AtomicFormula extends IntegrityFormula {
     */
    public static final int STAMP_CERTIFICATE_HASH = 7;

    /**
     * SHA-256 of a certificate in the signing lineage of the app.
     *
     * <p>Can only be used in {@link StringAtomicFormula}.
     */
    public static final int APP_CERTIFICATE_LINEAGE = 8;

    public static final int EQ = 0;
    public static final int GT = 1;
    public static final int GTE = 2;
@@ -224,6 +232,11 @@ public abstract class AtomicFormula extends IntegrityFormula {
            return false;
        }

        @Override
        public boolean isAppCertificateLineageFormula() {
            return false;
        }

        @Override
        public boolean isInstallerFormula() {
            return false;
@@ -314,7 +327,8 @@ public abstract class AtomicFormula extends IntegrityFormula {
                            || key == APP_CERTIFICATE
                            || key == INSTALLER_CERTIFICATE
                            || key == INSTALLER_NAME
                            || key == STAMP_CERTIFICATE_HASH,
                            || key == STAMP_CERTIFICATE_HASH
                            || key == APP_CERTIFICATE_LINEAGE,
                    "Key %s cannot be used with StringAtomicFormula", keyToString(key));
            mValue = null;
            mIsHashedValue = null;
@@ -335,7 +349,8 @@ public abstract class AtomicFormula extends IntegrityFormula {
                            || key == APP_CERTIFICATE
                            || key == INSTALLER_CERTIFICATE
                            || key == INSTALLER_NAME
                            || key == STAMP_CERTIFICATE_HASH,
                            || key == STAMP_CERTIFICATE_HASH
                            || key == APP_CERTIFICATE_LINEAGE,
                    "Key %s cannot be used with StringAtomicFormula", keyToString(key));
            mValue = value;
            mIsHashedValue = isHashed;
@@ -348,8 +363,9 @@ public abstract class AtomicFormula extends IntegrityFormula {
         * <p>The value will be automatically hashed with SHA256 and the hex digest will be computed
         * when the key is PACKAGE_NAME or INSTALLER_NAME and the value is more than 32 characters.
         *
         * <p>The APP_CERTIFICATES, INSTALLER_CERTIFICATES, and STAMP_CERTIFICATE_HASH are always
         * delivered in hashed form. So the isHashedValue is set to true by default.
         * <p>The APP_CERTIFICATES, INSTALLER_CERTIFICATES, STAMP_CERTIFICATE_HASH and
         * APP_CERTIFICATE_LINEAGE are always delivered in hashed form. So the isHashedValue is set
         * to true by default.
         *
         * @throws IllegalArgumentException if {@code key} cannot be used with string value.
         */
@@ -360,13 +376,15 @@ public abstract class AtomicFormula extends IntegrityFormula {
                            || key == APP_CERTIFICATE
                            || key == INSTALLER_CERTIFICATE
                            || key == INSTALLER_NAME
                            || key == STAMP_CERTIFICATE_HASH,
                            || key == STAMP_CERTIFICATE_HASH
                            || key == APP_CERTIFICATE_LINEAGE,
                    "Key %s cannot be used with StringAtomicFormula", keyToString(key));
            mValue = hashValue(key, value);
            mIsHashedValue =
                    (key == APP_CERTIFICATE
                                    || key == INSTALLER_CERTIFICATE
                                    || key == STAMP_CERTIFICATE_HASH)
                                    || key == STAMP_CERTIFICATE_HASH
                                    || key == APP_CERTIFICATE_LINEAGE)
                            || !mValue.equals(value);
        }

@@ -408,6 +426,11 @@ public abstract class AtomicFormula extends IntegrityFormula {
            return getKey() == APP_CERTIFICATE;
        }

        @Override
        public boolean isAppCertificateLineageFormula() {
            return getKey() == APP_CERTIFICATE_LINEAGE;
        }

        @Override
        public boolean isInstallerFormula() {
            return getKey() == INSTALLER_NAME || getKey() == INSTALLER_CERTIFICATE;
@@ -474,6 +497,8 @@ public abstract class AtomicFormula extends IntegrityFormula {
                    return Collections.singletonList(appInstallMetadata.getInstallerName());
                case AtomicFormula.STAMP_CERTIFICATE_HASH:
                    return Collections.singletonList(appInstallMetadata.getStampCertificateHash());
                case AtomicFormula.APP_CERTIFICATE_LINEAGE:
                    return appInstallMetadata.getAppCertificateLineage();
                default:
                    throw new IllegalStateException(
                            "Unexpected key in StringAtomicFormula: " + key);
@@ -576,6 +601,11 @@ public abstract class AtomicFormula extends IntegrityFormula {
            return false;
        }

        @Override
        public boolean isAppCertificateLineageFormula() {
            return false;
        }

        @Override
        public boolean isInstallerFormula() {
            return false;
@@ -660,6 +690,8 @@ public abstract class AtomicFormula extends IntegrityFormula {
                return "STAMP_TRUSTED";
            case STAMP_CERTIFICATE_HASH:
                return "STAMP_CERTIFICATE_HASH";
            case APP_CERTIFICATE_LINEAGE:
                return "APP_CERTIFICATE_LINEAGE";
            default:
                throw new IllegalArgumentException("Unknown key " + key);
        }
@@ -686,6 +718,7 @@ public abstract class AtomicFormula extends IntegrityFormula {
                || key == INSTALLER_CERTIFICATE
                || key == PRE_INSTALLED
                || key == STAMP_TRUSTED
                || key == STAMP_CERTIFICATE_HASH;
                || key == STAMP_CERTIFICATE_HASH
                || key == APP_CERTIFICATE_LINEAGE;
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -136,6 +136,11 @@ public final class CompoundFormula extends IntegrityFormula implements Parcelabl
        return getFormulas().stream().anyMatch(formula -> formula.isAppCertificateFormula());
    }

    @Override
    public boolean isAppCertificateLineageFormula() {
        return getFormulas().stream().anyMatch(formula -> formula.isAppCertificateLineageFormula());
    }

    @Override
    public boolean isInstallerFormula() {
        return getFormulas().stream().anyMatch(formula -> formula.isInstallerFormula());
+5 −0
Original line number Diff line number Diff line
@@ -72,6 +72,11 @@ public class InstallerAllowedByManifestFormula extends IntegrityFormula implemen
        return false;
    }

    @Override
    public boolean isAppCertificateLineageFormula() {
        return false;
    }

    @Override
    public boolean isInstallerFormula() {
        return true;
Loading