Merge "Two API changes:"

This commit is contained in:
TreeHugger Robot
2020-02-11 10:13:19 +00:00
committed by Android (Google) Code Review
15 changed files with 351 additions and 219 deletions

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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()));
}
}

View File

@@ -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.

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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));

View File

@@ -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()));

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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