| /* |
| * Copyright (C) 2019 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 com.android.server.integrity.serializer; |
| |
| import static com.android.server.integrity.model.ComponentBitSize.ATOMIC_FORMULA_START; |
| import static com.android.server.integrity.model.ComponentBitSize.COMPOUND_FORMULA_END; |
| import static com.android.server.integrity.model.ComponentBitSize.COMPOUND_FORMULA_START; |
| 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.KEY_BITS; |
| import static com.android.server.integrity.model.ComponentBitSize.OPERATOR_BITS; |
| import static com.android.server.integrity.model.ComponentBitSize.SEPARATOR_BITS; |
| import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS; |
| import static com.android.server.integrity.utils.TestUtils.getBits; |
| import static com.android.server.integrity.utils.TestUtils.getBytes; |
| import static com.android.server.integrity.utils.TestUtils.getValueBits; |
| import static com.android.server.testutils.TestUtils.assertExpectException; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import android.content.integrity.AppInstallMetadata; |
| import android.content.integrity.AtomicFormula; |
| import android.content.integrity.CompoundFormula; |
| import android.content.integrity.Formula; |
| import android.content.integrity.Rule; |
| |
| import androidx.annotation.NonNull; |
| |
| import com.android.server.integrity.IntegrityUtils; |
| |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.nio.charset.StandardCharsets; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Optional; |
| |
| @RunWith(JUnit4.class) |
| public class RuleBinarySerializerTest { |
| |
| private static final String SAMPLE_INSTALLER_NAME = "com.test.installer"; |
| private static final String SAMPLE_INSTALLER_CERT = "installer_cert"; |
| |
| private static final String COMPOUND_FORMULA_START_BITS = |
| getBits(COMPOUND_FORMULA_START, SEPARATOR_BITS); |
| private static final String COMPOUND_FORMULA_END_BITS = |
| getBits(COMPOUND_FORMULA_END, SEPARATOR_BITS); |
| private static final String ATOMIC_FORMULA_START_BITS = |
| getBits(ATOMIC_FORMULA_START, SEPARATOR_BITS); |
| |
| private static final String NOT = getBits(CompoundFormula.NOT, CONNECTOR_BITS); |
| private static final String AND = getBits(CompoundFormula.AND, CONNECTOR_BITS); |
| private static final String OR = getBits(CompoundFormula.OR, CONNECTOR_BITS); |
| |
| private static final String PACKAGE_NAME = getBits(AtomicFormula.PACKAGE_NAME, KEY_BITS); |
| private static final String APP_CERTIFICATE = getBits(AtomicFormula.APP_CERTIFICATE, KEY_BITS); |
| private static final String INSTALLER_NAME = getBits(AtomicFormula.INSTALLER_NAME, KEY_BITS); |
| private static final String INSTALLER_CERTIFICATE = |
| getBits(AtomicFormula.INSTALLER_CERTIFICATE, KEY_BITS); |
| private static final String VERSION_CODE = getBits(AtomicFormula.VERSION_CODE, KEY_BITS); |
| private static final String PRE_INSTALLED = getBits(AtomicFormula.PRE_INSTALLED, KEY_BITS); |
| |
| private static final String EQ = getBits(AtomicFormula.EQ, OPERATOR_BITS); |
| |
| private static final String IS_NOT_HASHED = "0"; |
| private static final String IS_HASHED = "1"; |
| |
| private static final String DENY = getBits(Rule.DENY, EFFECT_BITS); |
| |
| private static final String START_BIT = "1"; |
| private static final String END_BIT = "1"; |
| |
| private static final byte[] DEFAULT_FORMAT_VERSION_BYTES = |
| getBytes(getBits(DEFAULT_FORMAT_VERSION, FORMAT_VERSION_BITS)); |
| |
| @Test |
| public void testBinaryString_serializeNullRules() { |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| |
| assertExpectException( |
| RuleSerializeException.class, |
| /* expectedExceptionMessageRegex= */ "Index buckets cannot be created for null" |
| + " rule list.", |
| () -> binarySerializer.serialize(null, /* formatVersion= */ Optional.empty())); |
| } |
| |
| @Test |
| public void testBinaryString_emptyRules() throws Exception { |
| ByteArrayOutputStream expectedArrayOutputStream = new ByteArrayOutputStream(); |
| expectedArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); |
| |
| ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| binarySerializer.serialize( |
| Collections.emptyList(), /* formatVersion= */ Optional.empty(), outputStream); |
| |
| assertThat(outputStream.toByteArray()).isEqualTo(expectedArrayOutputStream.toByteArray()); |
| } |
| |
| @Test |
| public void testBinaryStream_serializeValidCompoundFormula() throws Exception { |
| String packageName = "com.test.app"; |
| Rule rule = |
| new Rule( |
| new CompoundFormula( |
| CompoundFormula.NOT, |
| Collections.singletonList( |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.PACKAGE_NAME, |
| packageName, |
| /* isHashedValue= */ false))), |
| Rule.DENY); |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
| String expectedBits = |
| START_BIT |
| + COMPOUND_FORMULA_START_BITS |
| + NOT |
| + ATOMIC_FORMULA_START_BITS |
| + PACKAGE_NAME |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(packageName.length(), VALUE_SIZE_BITS) |
| + getValueBits(packageName) |
| + COMPOUND_FORMULA_END_BITS |
| + DENY |
| + END_BIT; |
| ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
| byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); |
| byteArrayOutputStream.write(getBytes(expectedBits)); |
| byte[] expectedRules = byteArrayOutputStream.toByteArray(); |
| |
| binarySerializer.serialize( |
| Collections.singletonList(rule), |
| /* formatVersion= */ Optional.empty(), |
| outputStream); |
| |
| byte[] actualRules = outputStream.toByteArray(); |
| assertThat(actualRules).isEqualTo(expectedRules); |
| } |
| |
| @Test |
| public void testBinaryString_serializeValidCompoundFormula_notConnector() throws Exception { |
| String packageName = "com.test.app"; |
| Rule rule = |
| new Rule( |
| new CompoundFormula( |
| CompoundFormula.NOT, |
| Collections.singletonList( |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.PACKAGE_NAME, |
| packageName, |
| /* isHashedValue= */ false))), |
| Rule.DENY); |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| String expectedBits = |
| START_BIT |
| + COMPOUND_FORMULA_START_BITS |
| + NOT |
| + ATOMIC_FORMULA_START_BITS |
| + PACKAGE_NAME |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(packageName.length(), VALUE_SIZE_BITS) |
| + getValueBits(packageName) |
| + COMPOUND_FORMULA_END_BITS |
| + DENY |
| + END_BIT; |
| ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
| byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); |
| byteArrayOutputStream.write(getBytes(expectedBits)); |
| byte[] expectedRules = byteArrayOutputStream.toByteArray(); |
| |
| byte[] actualRules = |
| binarySerializer.serialize( |
| Collections.singletonList(rule), /* formatVersion= */ Optional.empty()); |
| |
| assertThat(actualRules).isEqualTo(expectedRules); |
| } |
| |
| @Test |
| public void testBinaryString_serializeValidCompoundFormula_andConnector() throws Exception { |
| String packageName = "com.test.app"; |
| String appCertificate = "test_cert"; |
| Rule rule = |
| new Rule( |
| new CompoundFormula( |
| CompoundFormula.AND, |
| Arrays.asList( |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.PACKAGE_NAME, |
| packageName, |
| /* isHashedValue= */ false), |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.APP_CERTIFICATE, |
| appCertificate, |
| /* isHashedValue= */ false))), |
| Rule.DENY); |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| String expectedBits = |
| START_BIT |
| + COMPOUND_FORMULA_START_BITS |
| + AND |
| + ATOMIC_FORMULA_START_BITS |
| + PACKAGE_NAME |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(packageName.length(), VALUE_SIZE_BITS) |
| + getValueBits(packageName) |
| + ATOMIC_FORMULA_START_BITS |
| + APP_CERTIFICATE |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(appCertificate.length(), VALUE_SIZE_BITS) |
| + getValueBits(appCertificate) |
| + COMPOUND_FORMULA_END_BITS |
| + DENY |
| + END_BIT; |
| ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
| byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); |
| byteArrayOutputStream.write(getBytes(expectedBits)); |
| byte[] expectedRules = byteArrayOutputStream.toByteArray(); |
| |
| byte[] actualRules = |
| binarySerializer.serialize( |
| Collections.singletonList(rule), /* formatVersion= */ Optional.empty()); |
| |
| assertThat(actualRules).isEqualTo(expectedRules); |
| } |
| |
| @Test |
| public void testBinaryString_serializeValidCompoundFormula_orConnector() throws Exception { |
| String packageName = "com.test.app"; |
| String appCertificate = "test_cert"; |
| Rule rule = |
| new Rule( |
| new CompoundFormula( |
| CompoundFormula.OR, |
| Arrays.asList( |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.PACKAGE_NAME, |
| packageName, |
| /* isHashedValue= */ false), |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.APP_CERTIFICATE, |
| appCertificate, |
| /* isHashedValue= */ false))), |
| Rule.DENY); |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| String expectedBits = |
| START_BIT |
| + COMPOUND_FORMULA_START_BITS |
| + OR |
| + ATOMIC_FORMULA_START_BITS |
| + PACKAGE_NAME |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(packageName.length(), VALUE_SIZE_BITS) |
| + getValueBits(packageName) |
| + ATOMIC_FORMULA_START_BITS |
| + APP_CERTIFICATE |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(appCertificate.length(), VALUE_SIZE_BITS) |
| + getValueBits(appCertificate) |
| + COMPOUND_FORMULA_END_BITS |
| + DENY |
| + END_BIT; |
| ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
| byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); |
| byteArrayOutputStream.write(getBytes(expectedBits)); |
| byte[] expectedRules = byteArrayOutputStream.toByteArray(); |
| |
| byte[] actualRules = |
| binarySerializer.serialize( |
| Collections.singletonList(rule), /* formatVersion= */ Optional.empty()); |
| |
| assertThat(actualRules).isEqualTo(expectedRules); |
| } |
| |
| @Test |
| public void testBinaryString_serializeValidAtomicFormula_stringValue() throws Exception { |
| String packageName = "com.test.app"; |
| Rule rule = |
| new Rule( |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.PACKAGE_NAME, |
| packageName, |
| /* isHashedValue= */ false), |
| Rule.DENY); |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| String expectedBits = |
| START_BIT |
| + ATOMIC_FORMULA_START_BITS |
| + PACKAGE_NAME |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(packageName.length(), VALUE_SIZE_BITS) |
| + getValueBits(packageName) |
| + DENY |
| + END_BIT; |
| ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
| byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); |
| byteArrayOutputStream.write(getBytes(expectedBits)); |
| byte[] expectedRules = byteArrayOutputStream.toByteArray(); |
| |
| byte[] actualRules = |
| binarySerializer.serialize( |
| Collections.singletonList(rule), /* formatVersion= */ Optional.empty()); |
| |
| assertThat(actualRules).isEqualTo(expectedRules); |
| } |
| |
| @Test |
| public void testBinaryString_serializeValidAtomicFormula_hashedValue() throws Exception { |
| String appCertificate = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; |
| Rule rule = |
| new Rule( |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.APP_CERTIFICATE, |
| IntegrityUtils.getHexDigest( |
| appCertificate.getBytes(StandardCharsets.UTF_8)), |
| /* isHashedValue= */ true), |
| Rule.DENY); |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| String expectedBits = |
| START_BIT |
| + ATOMIC_FORMULA_START_BITS |
| + APP_CERTIFICATE |
| + EQ |
| + IS_HASHED |
| + getBits(appCertificate.length(), VALUE_SIZE_BITS) |
| + getValueBits(appCertificate) |
| + DENY |
| + END_BIT; |
| ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
| byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); |
| byteArrayOutputStream.write(getBytes(expectedBits)); |
| byte[] expectedRules = byteArrayOutputStream.toByteArray(); |
| |
| byte[] actualRules = |
| binarySerializer.serialize( |
| Collections.singletonList(rule), /* formatVersion= */ Optional.empty()); |
| |
| assertThat(actualRules).isEqualTo(expectedRules); |
| } |
| |
| @Test |
| public void testBinaryString_serializeValidAtomicFormula_integerValue() throws Exception { |
| int versionCode = 1; |
| Rule rule = |
| new Rule( |
| new AtomicFormula.IntAtomicFormula( |
| AtomicFormula.VERSION_CODE, AtomicFormula.EQ, versionCode), |
| Rule.DENY); |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| String expectedBits = |
| START_BIT |
| + ATOMIC_FORMULA_START_BITS |
| + VERSION_CODE |
| + EQ |
| + getBits(versionCode, /* numOfBits= */ 32) |
| + DENY |
| + END_BIT; |
| ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
| byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); |
| byteArrayOutputStream.write(getBytes(expectedBits)); |
| byte[] expectedRules = byteArrayOutputStream.toByteArray(); |
| |
| byte[] actualRules = |
| binarySerializer.serialize( |
| Collections.singletonList(rule), /* formatVersion= */ Optional.empty()); |
| |
| assertThat(actualRules).isEqualTo(expectedRules); |
| } |
| |
| @Test |
| public void testBinaryString_serializeValidAtomicFormula_booleanValue() throws Exception { |
| String preInstalled = "1"; |
| Rule rule = |
| new Rule( |
| new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true), |
| Rule.DENY); |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| String expectedBits = |
| START_BIT |
| + ATOMIC_FORMULA_START_BITS |
| + PRE_INSTALLED |
| + EQ |
| + preInstalled |
| + DENY |
| + END_BIT; |
| ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
| byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); |
| byteArrayOutputStream.write(getBytes(expectedBits)); |
| byte[] expectedRules = byteArrayOutputStream.toByteArray(); |
| |
| byte[] actualRules = |
| binarySerializer.serialize( |
| Collections.singletonList(rule), /* formatVersion= */ Optional.empty()); |
| |
| assertThat(actualRules).isEqualTo(expectedRules); |
| } |
| |
| @Test |
| public void testBinaryString_serializeInvalidFormulaType() throws Exception { |
| Formula invalidFormula = getInvalidFormula(); |
| Rule rule = new Rule(invalidFormula, Rule.DENY); |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| |
| assertExpectException( |
| RuleSerializeException.class, |
| /* expectedExceptionMessageRegex= */ "Malformed rule identified.", |
| () -> |
| binarySerializer.serialize( |
| Collections.singletonList(rule), |
| /* formatVersion= */ Optional.empty())); |
| } |
| |
| @Test |
| public void testBinaryString_serializeFormatVersion() throws Exception { |
| int formatVersion = 1; |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| String expectedBits = getBits(formatVersion, FORMAT_VERSION_BITS); |
| byte[] expectedRules = getBytes(expectedBits); |
| |
| byte[] actualRules = |
| binarySerializer.serialize( |
| Collections.emptyList(), /* formatVersion= */ Optional.of(formatVersion)); |
| |
| assertThat(actualRules).isEqualTo(expectedRules); |
| } |
| |
| @Test |
| public void testBinaryString_serializeComplexCompoundFormula_indexingOrderValid() |
| throws Exception { |
| String packageNameA = "aaa"; |
| String packageNameB = "bbb"; |
| String packageNameC = "ccc"; |
| String appCert1 = "cert1"; |
| String appCert2 = "cert2"; |
| String appCert3 = "cert3"; |
| Rule installerRule = |
| new Rule( |
| new CompoundFormula( |
| CompoundFormula.AND, |
| Arrays.asList( |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.INSTALLER_NAME, |
| SAMPLE_INSTALLER_NAME, |
| /* isHashedValue= */ false), |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.INSTALLER_CERTIFICATE, |
| SAMPLE_INSTALLER_CERT, |
| /* isHashedValue= */ false))), |
| Rule.DENY); |
| |
| RuleSerializer binarySerializer = new RuleBinarySerializer(); |
| List<Rule> ruleList = new ArrayList(); |
| ruleList.add(getRuleWithAppCertificateAndSampleInstallerName(appCert3)); |
| ruleList.add(getRuleWithAppCertificateAndSampleInstallerName(appCert2)); |
| ruleList.add(getRuleWithAppCertificateAndSampleInstallerName(appCert1)); |
| ruleList.add(getRuleWithPackageNameAndSampleInstallerName(packageNameB)); |
| ruleList.add(getRuleWithPackageNameAndSampleInstallerName(packageNameC)); |
| ruleList.add(getRuleWithPackageNameAndSampleInstallerName(packageNameA)); |
| ruleList.add(installerRule); |
| byte[] actualRules = |
| binarySerializer.serialize(ruleList, /* formatVersion= */ Optional.empty()); |
| |
| // Note that ordering is important here and the test verifies that the rules are written |
| // in this sorted order. |
| ByteArrayOutputStream expectedArrayOutputStream = new ByteArrayOutputStream(); |
| expectedArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); |
| expectedArrayOutputStream.write( |
| getBytes( |
| getSerializedCompoundRuleWithPackageNameAndSampleInstallerName( |
| packageNameA))); |
| expectedArrayOutputStream.write( |
| getBytes( |
| getSerializedCompoundRuleWithPackageNameAndSampleInstallerName( |
| packageNameB))); |
| expectedArrayOutputStream.write( |
| getBytes( |
| getSerializedCompoundRuleWithPackageNameAndSampleInstallerName( |
| packageNameC))); |
| expectedArrayOutputStream.write( |
| getBytes( |
| getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName( |
| appCert1))); |
| expectedArrayOutputStream.write( |
| getBytes( |
| getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName( |
| appCert2))); |
| expectedArrayOutputStream.write( |
| getBytes( |
| getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName( |
| appCert3))); |
| String expectedBitsForInstallerRule = |
| START_BIT |
| + COMPOUND_FORMULA_START_BITS |
| + AND |
| + ATOMIC_FORMULA_START_BITS |
| + INSTALLER_NAME |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(SAMPLE_INSTALLER_NAME.length(), VALUE_SIZE_BITS) |
| + getValueBits(SAMPLE_INSTALLER_NAME) |
| + ATOMIC_FORMULA_START_BITS |
| + INSTALLER_CERTIFICATE |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(SAMPLE_INSTALLER_CERT.length(), VALUE_SIZE_BITS) |
| + getValueBits(SAMPLE_INSTALLER_CERT) |
| + COMPOUND_FORMULA_END_BITS |
| + DENY |
| + END_BIT; |
| expectedArrayOutputStream.write(getBytes(expectedBitsForInstallerRule)); |
| |
| assertThat(actualRules).isEqualTo(expectedArrayOutputStream.toByteArray()); |
| } |
| |
| private Rule getRuleWithPackageNameAndSampleInstallerName(String packageName) { |
| return new Rule( |
| new CompoundFormula( |
| CompoundFormula.AND, |
| Arrays.asList( |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.PACKAGE_NAME, |
| packageName, |
| /* isHashedValue= */ false), |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.INSTALLER_NAME, |
| SAMPLE_INSTALLER_NAME, |
| /* isHashedValue= */ false))), |
| Rule.DENY); |
| } |
| |
| private String getSerializedCompoundRuleWithPackageNameAndSampleInstallerName( |
| String packageName) { |
| return START_BIT |
| + COMPOUND_FORMULA_START_BITS |
| + AND |
| + ATOMIC_FORMULA_START_BITS |
| + PACKAGE_NAME |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(packageName.length(), VALUE_SIZE_BITS) |
| + getValueBits(packageName) |
| + ATOMIC_FORMULA_START_BITS |
| + INSTALLER_NAME |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(SAMPLE_INSTALLER_NAME.length(), VALUE_SIZE_BITS) |
| + getValueBits(SAMPLE_INSTALLER_NAME) |
| + COMPOUND_FORMULA_END_BITS |
| + DENY |
| + END_BIT; |
| } |
| |
| private Rule getRuleWithAppCertificateAndSampleInstallerName(String certificate) { |
| return new Rule( |
| new CompoundFormula( |
| CompoundFormula.AND, |
| Arrays.asList( |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.APP_CERTIFICATE, |
| certificate, |
| /* isHashedValue= */ false), |
| new AtomicFormula.StringAtomicFormula( |
| AtomicFormula.INSTALLER_NAME, |
| SAMPLE_INSTALLER_NAME, |
| /* isHashedValue= */ false))), |
| Rule.DENY); |
| } |
| |
| private String getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName( |
| String appCertificate) { |
| return START_BIT |
| + COMPOUND_FORMULA_START_BITS |
| + AND |
| + ATOMIC_FORMULA_START_BITS |
| + APP_CERTIFICATE |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(appCertificate.length(), VALUE_SIZE_BITS) |
| + getValueBits(appCertificate) |
| + ATOMIC_FORMULA_START_BITS |
| + INSTALLER_NAME |
| + EQ |
| + IS_NOT_HASHED |
| + getBits(SAMPLE_INSTALLER_NAME.length(), VALUE_SIZE_BITS) |
| + getValueBits(SAMPLE_INSTALLER_NAME) |
| + COMPOUND_FORMULA_END_BITS |
| + DENY |
| + END_BIT; |
| } |
| |
| private static Formula getInvalidFormula() { |
| return new Formula() { |
| @Override |
| public boolean isSatisfied(AppInstallMetadata appInstallMetadata) { |
| return false; |
| } |
| |
| @Override |
| public int getTag() { |
| return 0; |
| } |
| |
| @Override |
| public int hashCode() { |
| return super.hashCode(); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| return super.equals(obj); |
| } |
| |
| @NonNull |
| @Override |
| protected Object clone() throws CloneNotSupportedException { |
| return super.clone(); |
| } |
| |
| @Override |
| public String toString() { |
| return super.toString(); |
| } |
| |
| @Override |
| protected void finalize() throws Throwable { |
| super.finalize(); |
| } |
| }; |
| } |
| } |