Merge "Two API changes:"
This commit is contained in:
committed by
Android (Google) Code Review
commit
456ffd240f
@@ -1922,18 +1922,22 @@ package android.content.integrity {
|
||||
public abstract class IntegrityFormula {
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula all(@NonNull android.content.integrity.IntegrityFormula...);
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula any(@NonNull android.content.integrity.IntegrityFormula...);
|
||||
method @NonNull public android.content.integrity.IntegrityFormula equalTo(@NonNull String);
|
||||
method @NonNull public android.content.integrity.IntegrityFormula equalTo(boolean);
|
||||
method @NonNull public android.content.integrity.IntegrityFormula equalTo(long);
|
||||
method @NonNull public android.content.integrity.IntegrityFormula greaterThan(long);
|
||||
method @NonNull public android.content.integrity.IntegrityFormula greaterThanOrEquals(long);
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula not(@NonNull android.content.integrity.IntegrityFormula);
|
||||
field @NonNull public static final android.content.integrity.IntegrityFormula APP_CERTIFICATE;
|
||||
field @NonNull public static final android.content.integrity.IntegrityFormula INSTALLER_CERTIFICATE;
|
||||
field @NonNull public static final android.content.integrity.IntegrityFormula INSTALLER_NAME;
|
||||
field @NonNull public static final android.content.integrity.IntegrityFormula PACKAGE_NAME;
|
||||
field @NonNull public static final android.content.integrity.IntegrityFormula PRE_INSTALLED;
|
||||
field @NonNull public static final android.content.integrity.IntegrityFormula VERSION_CODE;
|
||||
}
|
||||
|
||||
public static final class IntegrityFormula.Application {
|
||||
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);
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula versionCodeEquals(@NonNull long);
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula versionCodeGreaterThan(@NonNull long);
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula versionCodeGreaterThanOrEqualTo(@NonNull long);
|
||||
}
|
||||
|
||||
public static final class IntegrityFormula.Installer {
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula certificatesContain(@NonNull String);
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula notAllowedByManifest();
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula packageNameEquals(@NonNull String);
|
||||
}
|
||||
|
||||
public final class Rule implements android.os.Parcelable {
|
||||
|
||||
@@ -812,18 +812,22 @@ package android.content.integrity {
|
||||
public abstract class IntegrityFormula {
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula all(@NonNull android.content.integrity.IntegrityFormula...);
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula any(@NonNull android.content.integrity.IntegrityFormula...);
|
||||
method @NonNull public android.content.integrity.IntegrityFormula equalTo(@NonNull String);
|
||||
method @NonNull public android.content.integrity.IntegrityFormula equalTo(boolean);
|
||||
method @NonNull public android.content.integrity.IntegrityFormula equalTo(long);
|
||||
method @NonNull public android.content.integrity.IntegrityFormula greaterThan(long);
|
||||
method @NonNull public android.content.integrity.IntegrityFormula greaterThanOrEquals(long);
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula not(@NonNull android.content.integrity.IntegrityFormula);
|
||||
field @NonNull public static final android.content.integrity.IntegrityFormula APP_CERTIFICATE;
|
||||
field @NonNull public static final android.content.integrity.IntegrityFormula INSTALLER_CERTIFICATE;
|
||||
field @NonNull public static final android.content.integrity.IntegrityFormula INSTALLER_NAME;
|
||||
field @NonNull public static final android.content.integrity.IntegrityFormula PACKAGE_NAME;
|
||||
field @NonNull public static final android.content.integrity.IntegrityFormula PRE_INSTALLED;
|
||||
field @NonNull public static final android.content.integrity.IntegrityFormula VERSION_CODE;
|
||||
}
|
||||
|
||||
public static final class IntegrityFormula.Application {
|
||||
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);
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula versionCodeEquals(@NonNull long);
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula versionCodeGreaterThan(@NonNull long);
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula versionCodeGreaterThanOrEqualTo(@NonNull long);
|
||||
}
|
||||
|
||||
public static final class IntegrityFormula.Installer {
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula certificatesContain(@NonNull String);
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula notAllowedByManifest();
|
||||
method @NonNull public static android.content.integrity.IntegrityFormula packageNameEquals(@NonNull String);
|
||||
}
|
||||
|
||||
public final class Rule implements android.os.Parcelable {
|
||||
|
||||
@@ -18,7 +18,9 @@ package android.content.integrity;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -40,6 +42,7 @@ public final class AppInstallMetadata {
|
||||
private final List<String> mInstallerCertificates;
|
||||
private final long mVersionCode;
|
||||
private final boolean mIsPreInstalled;
|
||||
private final Map<String, String> mAllowedInstallersAndCertificates;
|
||||
|
||||
private AppInstallMetadata(Builder builder) {
|
||||
this.mPackageName = builder.mPackageName;
|
||||
@@ -48,6 +51,7 @@ public final class AppInstallMetadata {
|
||||
this.mInstallerCertificates = builder.mInstallerCertificates;
|
||||
this.mVersionCode = builder.mVersionCode;
|
||||
this.mIsPreInstalled = builder.mIsPreInstalled;
|
||||
this.mAllowedInstallersAndCertificates = builder.mAllowedInstallersAndCertificates;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -80,6 +84,13 @@ public final class AppInstallMetadata {
|
||||
return mIsPreInstalled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the allowed installers and their corresponding cert.
|
||||
*/
|
||||
public Map<String, String> getAllowedInstallersAndCertificates() {
|
||||
return mAllowedInstallersAndCertificates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
@@ -101,6 +112,23 @@ public final class AppInstallMetadata {
|
||||
private List<String> mInstallerCertificates;
|
||||
private long mVersionCode;
|
||||
private boolean mIsPreInstalled;
|
||||
private Map<String, String> mAllowedInstallersAndCertificates;
|
||||
|
||||
public Builder() {
|
||||
mAllowedInstallersAndCertificates = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add allowed installers and cert.
|
||||
*
|
||||
* @see AppInstallMetadata#getAllowedInstallersAndCertificates()
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setAllowedInstallersAndCert(
|
||||
@NonNull Map<String, String> allowedInstallersAndCertificates) {
|
||||
this.mAllowedInstallersAndCertificates = allowedInstallersAndCertificates;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set package name of the app to be installed.
|
||||
|
||||
@@ -55,14 +55,12 @@ public abstract class AtomicFormula extends IntegrityFormula {
|
||||
PRE_INSTALLED,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Key {
|
||||
}
|
||||
public @interface Key {}
|
||||
|
||||
/** @hide */
|
||||
@IntDef(value = {EQ, GT, GTE})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Operator {
|
||||
}
|
||||
public @interface Operator {}
|
||||
|
||||
/**
|
||||
* Package name of the app.
|
||||
@@ -354,7 +352,8 @@ public abstract class AtomicFormula extends IntegrityFormula {
|
||||
"Key %s cannot be used with StringAtomicFormula", keyToString(key)));
|
||||
mValue = hashValue(key, value);
|
||||
mIsHashedValue =
|
||||
key == APP_CERTIFICATE || key == INSTALLER_CERTIFICATE
|
||||
key == APP_CERTIFICATE
|
||||
|| key == INSTALLER_CERTIFICATE
|
||||
? true
|
||||
: !mValue.equals(value);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.content.integrity;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An atomic formula that evaluates to true if the installer of the current install is specified in
|
||||
* the "allowed installer" field in the android manifest. Note that an empty "allowed installer" by
|
||||
* default means containing all possible installers.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class InstallerAllowedByManifestFormula extends IntegrityFormula {
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return IntegrityFormula.INSTALLER_ALLOWED_BY_MANIFEST_FORMULA_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(AppInstallMetadata appInstallMetadata) {
|
||||
Map<String, String> allowedInstallersAndCertificates =
|
||||
appInstallMetadata.getAllowedInstallersAndCertificates();
|
||||
return allowedInstallersAndCertificates.isEmpty()
|
||||
|| installerInAllowedInstallersFromManifest(
|
||||
appInstallMetadata, allowedInstallersAndCertificates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAppCertificateFormula() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInstallerFormula() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean installerInAllowedInstallersFromManifest(
|
||||
AppInstallMetadata appInstallMetadata,
|
||||
Map<String, String> allowedInstallersAndCertificates) {
|
||||
return allowedInstallersAndCertificates.containsKey(appInstallMetadata.getInstallerName())
|
||||
&& appInstallMetadata.getInstallerCertificates()
|
||||
.contains(
|
||||
allowedInstallersAndCertificates
|
||||
.get(appInstallMetadata.getInstallerName()));
|
||||
}
|
||||
}
|
||||
@@ -42,66 +42,88 @@ import java.util.Arrays;
|
||||
@VisibleForTesting
|
||||
public abstract class IntegrityFormula {
|
||||
|
||||
/**
|
||||
* A static formula base for package name formulas.
|
||||
*
|
||||
* This formulation is incomplete and should always be used with {@code equals} formulation.
|
||||
* Evaluates to false when used directly and cannot be written as a parcel.
|
||||
*/
|
||||
@NonNull
|
||||
public static final IntegrityFormula PACKAGE_NAME =
|
||||
new StringAtomicFormula(AtomicFormula.PACKAGE_NAME);
|
||||
/** Factory class for creating integrity formulas based on the app being installed. */
|
||||
public static final class Application {
|
||||
/** Returns an integrity formula that checks the equality to a package name. */
|
||||
@NonNull
|
||||
public static IntegrityFormula packageNameEquals(@NonNull String packageName) {
|
||||
return new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, packageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* A static formula base for app certificate formulas.
|
||||
*
|
||||
* This formulation is incomplete and should always be used with {@code equals} formulation.
|
||||
* Evaluates to false when used directly and cannot be written as a parcel.
|
||||
*/
|
||||
@NonNull
|
||||
public static final IntegrityFormula APP_CERTIFICATE =
|
||||
new StringAtomicFormula(AtomicFormula.APP_CERTIFICATE);
|
||||
/**
|
||||
* Returns an integrity formula that checks if the app certificates contain {@code
|
||||
* appCertificate}.
|
||||
*/
|
||||
@NonNull
|
||||
public static IntegrityFormula certificatesContain(@NonNull String appCertificate) {
|
||||
return new StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, appCertificate);
|
||||
}
|
||||
|
||||
/**
|
||||
* A static formula base for installer name formulas.
|
||||
*
|
||||
* This formulation is incomplete and should always be used with {@code equals} formulation.
|
||||
* Evaluates to false when used directly and cannot be written as a parcel.
|
||||
*/
|
||||
@NonNull
|
||||
public static final IntegrityFormula INSTALLER_NAME =
|
||||
new StringAtomicFormula(AtomicFormula.INSTALLER_NAME);
|
||||
/** Returns an integrity formula that checks the equality to a version code. */
|
||||
@NonNull
|
||||
public static IntegrityFormula versionCodeEquals(@NonNull long versionCode) {
|
||||
return new LongAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, versionCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* A static formula base for installer certificate formulas.
|
||||
*
|
||||
* This formulation is incomplete and should always be used with {@code equals} formulation.
|
||||
* Evaluates to false when used directly and cannot be written as a parcel.
|
||||
*/
|
||||
@NonNull
|
||||
public static final IntegrityFormula INSTALLER_CERTIFICATE =
|
||||
new StringAtomicFormula(AtomicFormula.INSTALLER_CERTIFICATE);
|
||||
/**
|
||||
* Returns an integrity formula that checks the app's version code is greater than the
|
||||
* provided value.
|
||||
*/
|
||||
@NonNull
|
||||
public static IntegrityFormula versionCodeGreaterThan(@NonNull long versionCode) {
|
||||
return new LongAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT, versionCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* A static formula base for version code name formulas.
|
||||
*
|
||||
* This formulation is incomplete and should always be used with {@code equals},
|
||||
* {@code greaterThan} and {@code greaterThanEquals} formulation. Evaluates to false when used
|
||||
* directly and cannot be written as a parcel.
|
||||
*/
|
||||
@NonNull
|
||||
public static final IntegrityFormula VERSION_CODE =
|
||||
new LongAtomicFormula(AtomicFormula.VERSION_CODE);
|
||||
/**
|
||||
* Returns an integrity formula that checks the app's version code is greater than or equal
|
||||
* to the provided value.
|
||||
*/
|
||||
@NonNull
|
||||
public static IntegrityFormula versionCodeGreaterThanOrEqualTo(@NonNull long versionCode) {
|
||||
return new LongAtomicFormula(
|
||||
AtomicFormula.VERSION_CODE, AtomicFormula.GTE, versionCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* A static formula base for pre-installed status formulas.
|
||||
*
|
||||
* This formulation is incomplete and should always be used with {@code equals} formulation.
|
||||
* Evaluates to false when used directly and cannot be written as a parcel.
|
||||
*/
|
||||
@NonNull
|
||||
public static final IntegrityFormula PRE_INSTALLED =
|
||||
new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED);
|
||||
/** Returns an integrity formula that is valid when app is pre-installed. */
|
||||
@NonNull
|
||||
public static IntegrityFormula isPreInstalled() {
|
||||
return new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true);
|
||||
}
|
||||
|
||||
private Application() {
|
||||
}
|
||||
}
|
||||
|
||||
/** Factory class for creating integrity formulas based on installer. */
|
||||
public static final class Installer {
|
||||
/** Returns an integrity formula that checks the equality to an installer name. */
|
||||
@NonNull
|
||||
public static IntegrityFormula packageNameEquals(@NonNull String installerName) {
|
||||
return new StringAtomicFormula(AtomicFormula.INSTALLER_NAME, installerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* An static formula that evaluates to true if the installer is NOT allowed according to the
|
||||
* "allowed installer" field in the android manifest.
|
||||
*/
|
||||
@NonNull
|
||||
public static IntegrityFormula notAllowedByManifest() {
|
||||
return not(new InstallerAllowedByManifestFormula());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an integrity formula that checks if the installer certificates contain {@code
|
||||
* installerCertificate}.
|
||||
*/
|
||||
@NonNull
|
||||
public static IntegrityFormula certificatesContain(@NonNull String installerCertificate) {
|
||||
return new StringAtomicFormula(AtomicFormula.INSTALLER_CERTIFICATE,
|
||||
installerCertificate);
|
||||
}
|
||||
|
||||
private Installer() {
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@IntDef(
|
||||
@@ -109,10 +131,12 @@ public abstract class IntegrityFormula {
|
||||
COMPOUND_FORMULA_TAG,
|
||||
STRING_ATOMIC_FORMULA_TAG,
|
||||
LONG_ATOMIC_FORMULA_TAG,
|
||||
BOOLEAN_ATOMIC_FORMULA_TAG
|
||||
BOOLEAN_ATOMIC_FORMULA_TAG,
|
||||
INSTALLER_ALLOWED_BY_MANIFEST_FORMULA_TAG
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface Tag {}
|
||||
@interface Tag {
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static final int COMPOUND_FORMULA_TAG = 0;
|
||||
@@ -122,6 +146,8 @@ public abstract class IntegrityFormula {
|
||||
public static final int LONG_ATOMIC_FORMULA_TAG = 2;
|
||||
/** @hide */
|
||||
public static final int BOOLEAN_ATOMIC_FORMULA_TAG = 3;
|
||||
/** @hide */
|
||||
public static final int INSTALLER_ALLOWED_BY_MANIFEST_FORMULA_TAG = 4;
|
||||
|
||||
/**
|
||||
* Returns the tag that identifies the current class.
|
||||
@@ -135,14 +161,14 @@ public abstract class IntegrityFormula {
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public abstract @Tag boolean matches(AppInstallMetadata appInstallMetadata);
|
||||
public abstract boolean matches(AppInstallMetadata appInstallMetadata);
|
||||
|
||||
/**
|
||||
* Returns true when the formula (or one of its atomic formulas) has app certificate as key.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public abstract @Tag boolean isAppCertificateFormula();
|
||||
public abstract boolean isAppCertificateFormula();
|
||||
|
||||
/**
|
||||
* Returns true when the formula (or one of its atomic formulas) has installer package name
|
||||
@@ -150,7 +176,7 @@ public abstract class IntegrityFormula {
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public abstract @Tag boolean isInstallerFormula();
|
||||
public abstract boolean isInstallerFormula();
|
||||
|
||||
/**
|
||||
* Write an {@link IntegrityFormula} to {@link android.os.Parcel}.
|
||||
@@ -159,7 +185,6 @@ public abstract class IntegrityFormula {
|
||||
* {@link Parcelable}.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@link IntegrityFormula} is not a recognized subclass
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static void writeToParcel(
|
||||
@@ -194,70 +219,6 @@ public abstract class IntegrityFormula {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an integrity formula that evaluates to true when value of the key matches to the
|
||||
* provided string value.
|
||||
*
|
||||
* <p>The value will be hashed with SHA256 and the hex digest will be computed; for
|
||||
* all cases except when the key is PACKAGE_NAME or INSTALLER_NAME and the value is less than
|
||||
* 32 characters.
|
||||
*
|
||||
* <p>Throws an {@link IllegalArgumentException} if the key is not string typed.
|
||||
*/
|
||||
@NonNull
|
||||
public IntegrityFormula equalTo(@NonNull String value) {
|
||||
AtomicFormula baseFormula = (AtomicFormula) this;
|
||||
return new AtomicFormula.StringAtomicFormula(baseFormula.getKey(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an integrity formula that evaluates to true when the boolean value of the key matches
|
||||
* the provided boolean value. It can only be used with the boolean comparison keys.
|
||||
*
|
||||
* <p>Throws an {@link IllegalArgumentException} if the key is not boolean typed.
|
||||
*/
|
||||
@NonNull
|
||||
public IntegrityFormula equalTo(boolean value) {
|
||||
AtomicFormula baseFormula = (AtomicFormula) this;
|
||||
return new AtomicFormula.BooleanAtomicFormula(baseFormula.getKey(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formula that evaluates to true when the value of the key in the package being
|
||||
* installed is equal to {@code value}.
|
||||
*
|
||||
* <p>Throws an {@link IllegalArgumentException} if the key is not long typed.
|
||||
*/
|
||||
@NonNull
|
||||
public IntegrityFormula equalTo(long value) {
|
||||
AtomicFormula baseFormula = (AtomicFormula) this;
|
||||
return new AtomicFormula.LongAtomicFormula(baseFormula.getKey(), AtomicFormula.EQ, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formula that evaluates to true when the value of the key in the package being
|
||||
* installed is greater than {@code value}.
|
||||
*
|
||||
* <p>Throws an {@link IllegalArgumentException} if the key is not long typed.
|
||||
*/
|
||||
@NonNull
|
||||
public IntegrityFormula greaterThan(long value) {
|
||||
AtomicFormula baseFormula = (AtomicFormula) this;
|
||||
return new AtomicFormula.LongAtomicFormula(baseFormula.getKey(), AtomicFormula.GT, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formula that evaluates to true when the value of the key in the package being
|
||||
* installed is greater than or equals to the {@code value}.
|
||||
*
|
||||
* <p>Throws an {@link IllegalArgumentException} if the key is not long typed.
|
||||
*/
|
||||
@NonNull
|
||||
public IntegrityFormula greaterThanOrEquals(long value) {
|
||||
AtomicFormula baseFormula = (AtomicFormula) this;
|
||||
return new AtomicFormula.LongAtomicFormula(baseFormula.getKey(), AtomicFormula.GTE, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formula that evaluates to true when any formula in {@code formulae} evaluates to
|
||||
* true.
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.content.integrity;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
public class InstallerAllowedByManifestFormulaTest {
|
||||
|
||||
private static final InstallerAllowedByManifestFormula
|
||||
FORMULA = new InstallerAllowedByManifestFormula();
|
||||
|
||||
@Test
|
||||
public void testFormulaMatches_installerAndCertBothInManifest() {
|
||||
AppInstallMetadata appInstallMetadata = getAppInstallMetadataBuilder()
|
||||
.setInstallerName("installer1")
|
||||
.setInstallerCertificates(Arrays.asList("installer_cert1", "random_cert"))
|
||||
.setAllowedInstallersAndCert(ImmutableMap.of(
|
||||
"installer1", "installer_cert1",
|
||||
"installer2", "installer_cert2"
|
||||
)).build();
|
||||
|
||||
assertThat(FORMULA.matches(appInstallMetadata)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormulaMatches_installerAndCertDoesNotMatchInManifest() {
|
||||
AppInstallMetadata appInstallMetadata = getAppInstallMetadataBuilder()
|
||||
.setInstallerName("installer1")
|
||||
.setInstallerCertificates(Arrays.asList("installer_cert1", "random_cert"))
|
||||
.setAllowedInstallersAndCert(ImmutableMap.of(
|
||||
"installer1", "installer_cert2",
|
||||
"installer2", "installer_cert1"
|
||||
)).build();
|
||||
|
||||
assertThat(FORMULA.matches(appInstallMetadata)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormulaMatches_installerNotInManifest() {
|
||||
AppInstallMetadata appInstallMetadata = getAppInstallMetadataBuilder()
|
||||
.setInstallerName("installer3")
|
||||
.setInstallerCertificates(Arrays.asList("installer_cert1", "random_cert"))
|
||||
.setAllowedInstallersAndCert(ImmutableMap.of(
|
||||
"installer1", "installer_cert2",
|
||||
"installer2", "installer_cert1"
|
||||
)).build();
|
||||
|
||||
assertThat(FORMULA.matches(appInstallMetadata)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormulaMatches_certificateNotInManifest() {
|
||||
AppInstallMetadata appInstallMetadata = getAppInstallMetadataBuilder()
|
||||
.setInstallerName("installer1")
|
||||
.setInstallerCertificates(Arrays.asList("installer_cert3", "random_cert"))
|
||||
.setAllowedInstallersAndCert(ImmutableMap.of(
|
||||
"installer1", "installer_cert2",
|
||||
"installer2", "installer_cert1"
|
||||
)).build();
|
||||
|
||||
assertThat(FORMULA.matches(appInstallMetadata)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormulaMatches_emptyManifest() {
|
||||
AppInstallMetadata appInstallMetadata = getAppInstallMetadataBuilder()
|
||||
.setInstallerName("installer1")
|
||||
.setInstallerCertificates(Arrays.asList("installer_cert3", "random_cert"))
|
||||
.setAllowedInstallersAndCert(ImmutableMap.of()).build();
|
||||
|
||||
assertThat(FORMULA.matches(appInstallMetadata)).isTrue();
|
||||
}
|
||||
|
||||
/** Returns a builder with all fields filled with some dummy data. */
|
||||
private AppInstallMetadata.Builder getAppInstallMetadataBuilder() {
|
||||
return new AppInstallMetadata.Builder()
|
||||
.setPackageName("abc")
|
||||
.setAppCertificates(Collections.emptyList())
|
||||
.setInstallerCertificates(Collections.emptyList())
|
||||
.setInstallerName("abc")
|
||||
.setVersionCode(-1)
|
||||
.setIsPreInstalled(true);
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,6 @@ import static android.content.integrity.IntegrityFormula.COMPOUND_FORMULA_TAG;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
@@ -32,8 +30,7 @@ public class IntegrityFormulaTest {
|
||||
@Test
|
||||
public void createEqualsFormula_packageName() {
|
||||
String packageName = "com.test.app";
|
||||
IntegrityFormula formula =
|
||||
IntegrityFormula.PACKAGE_NAME.equalTo(packageName);
|
||||
IntegrityFormula formula = IntegrityFormula.Application.packageNameEquals(packageName);
|
||||
|
||||
AtomicFormula.StringAtomicFormula stringAtomicFormula =
|
||||
(AtomicFormula.StringAtomicFormula) formula;
|
||||
@@ -46,8 +43,7 @@ public class IntegrityFormulaTest {
|
||||
@Test
|
||||
public void createEqualsFormula_appCertificate() {
|
||||
String appCertificate = "com.test.app";
|
||||
IntegrityFormula formula =
|
||||
IntegrityFormula.APP_CERTIFICATE.equalTo(appCertificate);
|
||||
IntegrityFormula formula = IntegrityFormula.Application.certificatesContain(appCertificate);
|
||||
|
||||
AtomicFormula.StringAtomicFormula stringAtomicFormula =
|
||||
(AtomicFormula.StringAtomicFormula) formula;
|
||||
@@ -60,8 +56,7 @@ public class IntegrityFormulaTest {
|
||||
@Test
|
||||
public void createEqualsFormula_installerName() {
|
||||
String installerName = "com.test.app";
|
||||
IntegrityFormula formula =
|
||||
IntegrityFormula.INSTALLER_NAME.equalTo(installerName);
|
||||
IntegrityFormula formula = IntegrityFormula.Installer.packageNameEquals(installerName);
|
||||
|
||||
AtomicFormula.StringAtomicFormula stringAtomicFormula =
|
||||
(AtomicFormula.StringAtomicFormula) formula;
|
||||
@@ -75,7 +70,7 @@ public class IntegrityFormulaTest {
|
||||
public void createEqualsFormula_installerCertificate() {
|
||||
String installerCertificate = "com.test.app";
|
||||
IntegrityFormula formula =
|
||||
IntegrityFormula.INSTALLER_CERTIFICATE.equalTo(installerCertificate);
|
||||
IntegrityFormula.Installer.certificatesContain(installerCertificate);
|
||||
|
||||
AtomicFormula.StringAtomicFormula stringAtomicFormula =
|
||||
(AtomicFormula.StringAtomicFormula) formula;
|
||||
@@ -88,8 +83,7 @@ public class IntegrityFormulaTest {
|
||||
@Test
|
||||
public void createEqualsFormula_versionCode() {
|
||||
int versionCode = 12;
|
||||
IntegrityFormula formula =
|
||||
IntegrityFormula.VERSION_CODE.equalTo(versionCode);
|
||||
IntegrityFormula formula = IntegrityFormula.Application.versionCodeEquals(versionCode);
|
||||
|
||||
AtomicFormula.LongAtomicFormula stringAtomicFormula =
|
||||
(AtomicFormula.LongAtomicFormula) formula;
|
||||
@@ -99,25 +93,10 @@ public class IntegrityFormulaTest {
|
||||
assertThat(stringAtomicFormula.getOperator()).isEqualTo(AtomicFormula.EQ);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createEqualsFormula_invalidKeyTypeForStringParameter() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> IntegrityFormula.PRE_INSTALLED.equalTo("wrongString"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createEqualsFormula_invalidKeyTypeForLongParameter() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> IntegrityFormula.PACKAGE_NAME.equalTo(12));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createGreaterThanFormula_versionCode() {
|
||||
int versionCode = 12;
|
||||
IntegrityFormula formula =
|
||||
IntegrityFormula.VERSION_CODE.greaterThan(versionCode);
|
||||
IntegrityFormula formula = IntegrityFormula.Application.versionCodeGreaterThan(versionCode);
|
||||
|
||||
AtomicFormula.LongAtomicFormula stringAtomicFormula =
|
||||
(AtomicFormula.LongAtomicFormula) formula;
|
||||
@@ -127,18 +106,11 @@ public class IntegrityFormulaTest {
|
||||
assertThat(stringAtomicFormula.getOperator()).isEqualTo(AtomicFormula.GT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createGreaterThanFormula_invalidKeyTypeForLongParameter() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> IntegrityFormula.PACKAGE_NAME.greaterThan(12));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createGreaterThanOrEqualsToFormula_versionCode() {
|
||||
int versionCode = 12;
|
||||
IntegrityFormula formula =
|
||||
IntegrityFormula.VERSION_CODE.greaterThanOrEquals(versionCode);
|
||||
IntegrityFormula formula = IntegrityFormula.Application.versionCodeGreaterThanOrEqualTo(
|
||||
versionCode);
|
||||
|
||||
AtomicFormula.LongAtomicFormula stringAtomicFormula =
|
||||
(AtomicFormula.LongAtomicFormula) formula;
|
||||
@@ -148,16 +120,9 @@ public class IntegrityFormulaTest {
|
||||
assertThat(stringAtomicFormula.getOperator()).isEqualTo(AtomicFormula.GTE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createGreaterThanOrEqualsToFormula_invalidKeyTypeForLongParameter() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> IntegrityFormula.PACKAGE_NAME.greaterThanOrEquals(12));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createIsTrueFormula_preInstalled() {
|
||||
IntegrityFormula formula = IntegrityFormula.PRE_INSTALLED.equalTo(true);
|
||||
IntegrityFormula formula = IntegrityFormula.Application.isPreInstalled();
|
||||
|
||||
AtomicFormula.BooleanAtomicFormula stringAtomicFormula =
|
||||
(AtomicFormula.BooleanAtomicFormula) formula;
|
||||
@@ -166,21 +131,13 @@ public class IntegrityFormulaTest {
|
||||
assertThat(stringAtomicFormula.getValue()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createIsTrueFormula_invalidKeyTypeForBoolParameter() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> IntegrityFormula.PACKAGE_NAME.equalTo(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAllFormula() {
|
||||
String packageName = "com.test.package";
|
||||
String certificateName = "certificate";
|
||||
IntegrityFormula formula1 =
|
||||
IntegrityFormula.PACKAGE_NAME.equalTo(packageName);
|
||||
IntegrityFormula formula2 =
|
||||
IntegrityFormula.APP_CERTIFICATE.equalTo(certificateName);
|
||||
IntegrityFormula formula1 = IntegrityFormula.Application.packageNameEquals(packageName);
|
||||
IntegrityFormula formula2 = IntegrityFormula.Application.certificatesContain(
|
||||
certificateName);
|
||||
|
||||
IntegrityFormula compoundFormula = IntegrityFormula.all(formula1, formula2);
|
||||
|
||||
@@ -191,10 +148,9 @@ public class IntegrityFormulaTest {
|
||||
public void createAnyFormula() {
|
||||
String packageName = "com.test.package";
|
||||
String certificateName = "certificate";
|
||||
IntegrityFormula formula1 =
|
||||
IntegrityFormula.PACKAGE_NAME.equalTo(packageName);
|
||||
IntegrityFormula formula2 =
|
||||
IntegrityFormula.APP_CERTIFICATE.equalTo(certificateName);
|
||||
IntegrityFormula formula1 = IntegrityFormula.Application.packageNameEquals(packageName);
|
||||
IntegrityFormula formula2 = IntegrityFormula.Application.certificatesContain(
|
||||
certificateName);
|
||||
|
||||
IntegrityFormula compoundFormula = IntegrityFormula.any(formula1, formula2);
|
||||
|
||||
@@ -206,8 +162,7 @@ public class IntegrityFormulaTest {
|
||||
String packageName = "com.test.package";
|
||||
|
||||
IntegrityFormula compoundFormula =
|
||||
IntegrityFormula.not(
|
||||
IntegrityFormula.PACKAGE_NAME.equalTo(packageName));
|
||||
IntegrityFormula.not(IntegrityFormula.Application.packageNameEquals(packageName));
|
||||
|
||||
assertThat(compoundFormula.getTag()).isEqualTo(COMPOUND_FORMULA_TAG);
|
||||
}
|
||||
|
||||
@@ -29,13 +29,14 @@ public final class ComponentBitSize {
|
||||
public static final int KEY_BITS = 4;
|
||||
public static final int OPERATOR_BITS = 3;
|
||||
public static final int CONNECTOR_BITS = 2;
|
||||
public static final int SEPARATOR_BITS = 2;
|
||||
public static final int SEPARATOR_BITS = 3;
|
||||
public static final int VALUE_SIZE_BITS = 8;
|
||||
public static final int IS_HASHED_BITS = 1;
|
||||
|
||||
public static final int ATOMIC_FORMULA_START = 0;
|
||||
public static final int COMPOUND_FORMULA_START = 1;
|
||||
public static final int COMPOUND_FORMULA_END = 2;
|
||||
public static final int INSTALLER_ALLOWED_BY_MANIFEST_START = 3;
|
||||
|
||||
public static final int DEFAULT_FORMAT_VERSION = 1;
|
||||
public static final int SIGNAL_BIT = 1;
|
||||
|
||||
@@ -23,6 +23,7 @@ import static com.android.server.integrity.model.ComponentBitSize.COMPOUND_FORMU
|
||||
import static com.android.server.integrity.model.ComponentBitSize.CONNECTOR_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.EFFECT_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.FORMAT_VERSION_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.INSTALLER_ALLOWED_BY_MANIFEST_START;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.IS_HASHED_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.KEY_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.OPERATOR_BITS;
|
||||
@@ -35,6 +36,7 @@ import static com.android.server.integrity.parser.BinaryFileOperations.getString
|
||||
|
||||
import android.content.integrity.AtomicFormula;
|
||||
import android.content.integrity.CompoundFormula;
|
||||
import android.content.integrity.InstallerAllowedByManifestFormula;
|
||||
import android.content.integrity.IntegrityFormula;
|
||||
import android.content.integrity.Rule;
|
||||
|
||||
@@ -140,6 +142,8 @@ public class RuleBinaryParser implements RuleParser {
|
||||
return parseCompoundFormula(bitInputStream);
|
||||
case COMPOUND_FORMULA_END:
|
||||
return null;
|
||||
case INSTALLER_ALLOWED_BY_MANIFEST_START:
|
||||
return new InstallerAllowedByManifestFormula();
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Unknown formula separator: %s", separator));
|
||||
|
||||
@@ -23,6 +23,7 @@ import static com.android.server.integrity.model.ComponentBitSize.CONNECTOR_BITS
|
||||
import static com.android.server.integrity.model.ComponentBitSize.DEFAULT_FORMAT_VERSION;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.EFFECT_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.FORMAT_VERSION_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.INSTALLER_ALLOWED_BY_MANIFEST_START;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.KEY_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.OPERATOR_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.SEPARATOR_BITS;
|
||||
@@ -36,6 +37,7 @@ import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAG
|
||||
|
||||
import android.content.integrity.AtomicFormula;
|
||||
import android.content.integrity.CompoundFormula;
|
||||
import android.content.integrity.InstallerAllowedByManifestFormula;
|
||||
import android.content.integrity.IntegrityFormula;
|
||||
import android.content.integrity.IntegrityUtils;
|
||||
import android.content.integrity.Rule;
|
||||
@@ -202,6 +204,8 @@ public class RuleBinarySerializer implements RuleSerializer {
|
||||
serializeAtomicFormula((AtomicFormula) formula, bitOutputStream);
|
||||
} else if (formula instanceof CompoundFormula) {
|
||||
serializeCompoundFormula((CompoundFormula) formula, bitOutputStream);
|
||||
} else if (formula instanceof InstallerAllowedByManifestFormula) {
|
||||
bitOutputStream.setNext(SEPARATOR_BITS, INSTALLER_ALLOWED_BY_MANIFEST_START);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Invalid formula type: %s", formula.getClass()));
|
||||
|
||||
@@ -84,6 +84,7 @@ class RuleIndexingDetailsIdentifier {
|
||||
return getIndexingDetailsForStringAtomicFormula(
|
||||
(AtomicFormula.StringAtomicFormula) formula);
|
||||
case IntegrityFormula.LONG_ATOMIC_FORMULA_TAG:
|
||||
case IntegrityFormula.INSTALLER_ALLOWED_BY_MANIFEST_FORMULA_TAG:
|
||||
case IntegrityFormula.BOOLEAN_ATOMIC_FORMULA_TAG:
|
||||
// Package name and app certificate related formulas are string atomic formulas.
|
||||
return new RuleIndexingDetails(NOT_INDEXED);
|
||||
|
||||
@@ -211,7 +211,8 @@ public class AppIntegrityManagerServiceImplTest {
|
||||
IntentSender mockReceiver = mock(IntentSender.class);
|
||||
List<Rule> rules =
|
||||
Arrays.asList(
|
||||
new Rule(IntegrityFormula.PACKAGE_NAME.equalTo(PACKAGE_NAME), Rule.DENY));
|
||||
new Rule(IntegrityFormula.Application.packageNameEquals(PACKAGE_NAME),
|
||||
Rule.DENY));
|
||||
|
||||
mService.updateRuleSet(VERSION, new ParceledListSlice<>(rules), mockReceiver);
|
||||
runJobInHandler();
|
||||
@@ -230,7 +231,8 @@ public class AppIntegrityManagerServiceImplTest {
|
||||
IntentSender mockReceiver = mock(IntentSender.class);
|
||||
List<Rule> rules =
|
||||
Arrays.asList(
|
||||
new Rule(IntegrityFormula.PACKAGE_NAME.equalTo(PACKAGE_NAME), Rule.DENY));
|
||||
new Rule(IntegrityFormula.Application.packageNameEquals(PACKAGE_NAME),
|
||||
Rule.DENY));
|
||||
|
||||
mService.updateRuleSet(VERSION, new ParceledListSlice<>(rules), mockReceiver);
|
||||
runJobInHandler();
|
||||
@@ -390,7 +392,7 @@ public class AppIntegrityManagerServiceImplTest {
|
||||
public void getCurrentRules() throws Exception {
|
||||
whitelistUsAsRuleProvider();
|
||||
makeUsSystemApp();
|
||||
Rule rule = new Rule(IntegrityFormula.PACKAGE_NAME.equalTo("package"), Rule.DENY);
|
||||
Rule rule = new Rule(IntegrityFormula.Application.packageNameEquals("package"), Rule.DENY);
|
||||
when(mIntegrityFileManager.readRules(any())).thenReturn(Arrays.asList(rule));
|
||||
|
||||
assertThat(mService.getCurrentRules().getList()).containsExactly(rule);
|
||||
|
||||
@@ -58,7 +58,7 @@ public class RuleBinaryParserTest {
|
||||
getBits(COMPOUND_FORMULA_END, SEPARATOR_BITS);
|
||||
private static final String ATOMIC_FORMULA_START_BITS =
|
||||
getBits(ATOMIC_FORMULA_START, SEPARATOR_BITS);
|
||||
private static final int INVALID_FORMULA_SEPARATOR_VALUE = 3;
|
||||
private static final int INVALID_FORMULA_SEPARATOR_VALUE = (1 << SEPARATOR_BITS) - 1;
|
||||
private static final String INVALID_FORMULA_SEPARATOR_BITS =
|
||||
getBits(INVALID_FORMULA_SEPARATOR_VALUE, SEPARATOR_BITS);
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ public class RuleIndexingDetailsIdentifierTest {
|
||||
ATOMIC_FORMULA_WITH_VERSION_CODE,
|
||||
ATOMIC_FORMULA_WITH_ISPREINSTALLED)),
|
||||
Rule.DENY);
|
||||
public static final int INVALID_FORMULA_TAG = -1;
|
||||
|
||||
@Test
|
||||
public void getIndexType_nullRule() {
|
||||
@@ -290,7 +291,7 @@ public class RuleIndexingDetailsIdentifierTest {
|
||||
return new AtomicFormula(0) {
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 4;
|
||||
return INVALID_FORMULA_TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user