diff options
9 files changed, 0 insertions, 1991 deletions
diff --git a/services/core/java/com/android/server/integrity/parser/RuleMetadataParser.java b/services/core/java/com/android/server/integrity/parser/RuleMetadataParser.java deleted file mode 100644 index e831e40e70d1..000000000000 --- a/services/core/java/com/android/server/integrity/parser/RuleMetadataParser.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.parser; - -import android.annotation.Nullable; -import android.util.Xml; - -import com.android.modules.utils.TypedXmlPullParser; -import com.android.server.integrity.model.RuleMetadata; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.io.InputStream; - -/** Helper class for parsing rule metadata. */ -public class RuleMetadataParser { - - public static final String RULE_PROVIDER_TAG = "P"; - public static final String VERSION_TAG = "V"; - - /** Parse the rule metadata from an input stream. */ - @Nullable - public static RuleMetadata parse(InputStream inputStream) - throws XmlPullParserException, IOException { - - String ruleProvider = ""; - String version = ""; - - TypedXmlPullParser xmlPullParser = Xml.resolvePullParser(inputStream); - - int eventType; - while ((eventType = xmlPullParser.next()) != XmlPullParser.END_DOCUMENT) { - if (eventType == XmlPullParser.START_TAG) { - String tag = xmlPullParser.getName(); - switch (tag) { - case RULE_PROVIDER_TAG: - ruleProvider = xmlPullParser.nextText(); - break; - case VERSION_TAG: - version = xmlPullParser.nextText(); - break; - default: - throw new IllegalStateException("Unknown tag in metadata: " + tag); - } - } - } - - return new RuleMetadata(ruleProvider, version); - } -} diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java deleted file mode 100644 index 8ba5870aef0f..000000000000 --- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java +++ /dev/null @@ -1,324 +0,0 @@ -/* - * 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.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; -import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS; -import static com.android.server.integrity.model.IndexingFileConstants.END_INDEXING_KEY; -import static com.android.server.integrity.model.IndexingFileConstants.INDEXING_BLOCK_SIZE; -import static com.android.server.integrity.model.IndexingFileConstants.START_INDEXING_KEY; -import static com.android.server.integrity.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED; -import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED; -import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED; - -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; - -import com.android.internal.util.Preconditions; -import com.android.server.integrity.model.BitOutputStream; -import com.android.server.integrity.model.ByteTrackedOutputStream; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; - -/** A helper class to serialize rules from the {@link Rule} model to Binary representation. */ -public class RuleBinarySerializer implements RuleSerializer { - static final int TOTAL_RULE_SIZE_LIMIT = 200000; - static final int INDEXED_RULE_SIZE_LIMIT = 100000; - static final int NONINDEXED_RULE_SIZE_LIMIT = 1000; - - // Get the byte representation for a list of rules. - @Override - public byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion) - throws RuleSerializeException { - try { - ByteArrayOutputStream rulesOutputStream = new ByteArrayOutputStream(); - serialize(rules, formatVersion, rulesOutputStream, new ByteArrayOutputStream()); - return rulesOutputStream.toByteArray(); - } catch (Exception e) { - throw new RuleSerializeException(e.getMessage(), e); - } - } - - // Get the byte representation for a list of rules, and write them to an output stream. - @Override - public void serialize( - List<Rule> rules, - Optional<Integer> formatVersion, - OutputStream rulesFileOutputStream, - OutputStream indexingFileOutputStream) - throws RuleSerializeException { - try { - if (rules == null) { - throw new IllegalArgumentException("Null rules cannot be serialized."); - } - - if (rules.size() > TOTAL_RULE_SIZE_LIMIT) { - throw new IllegalArgumentException("Too many rules provided: " + rules.size()); - } - - // Determine the indexing groups and the order of the rules within each indexed group. - Map<Integer, Map<String, List<Rule>>> indexedRules = - RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules); - - // Validate the rule blocks are not larger than expected limits. - verifySize(indexedRules.get(PACKAGE_NAME_INDEXED), INDEXED_RULE_SIZE_LIMIT); - verifySize(indexedRules.get(APP_CERTIFICATE_INDEXED), INDEXED_RULE_SIZE_LIMIT); - verifySize(indexedRules.get(NOT_INDEXED), NONINDEXED_RULE_SIZE_LIMIT); - - // Serialize the rules. - ByteTrackedOutputStream ruleFileByteTrackedOutputStream = - new ByteTrackedOutputStream(rulesFileOutputStream); - serializeRuleFileMetadata(formatVersion, ruleFileByteTrackedOutputStream); - LinkedHashMap<String, Integer> packageNameIndexes = - serializeRuleList( - indexedRules.get(PACKAGE_NAME_INDEXED), - ruleFileByteTrackedOutputStream); - LinkedHashMap<String, Integer> appCertificateIndexes = - serializeRuleList( - indexedRules.get(APP_CERTIFICATE_INDEXED), - ruleFileByteTrackedOutputStream); - LinkedHashMap<String, Integer> unindexedRulesIndexes = - serializeRuleList( - indexedRules.get(NOT_INDEXED), ruleFileByteTrackedOutputStream); - - // Serialize their indexes. - BitOutputStream indexingBitOutputStream = new BitOutputStream(indexingFileOutputStream); - serializeIndexGroup(packageNameIndexes, indexingBitOutputStream, /* isIndexed= */ true); - serializeIndexGroup( - appCertificateIndexes, indexingBitOutputStream, /* isIndexed= */ true); - serializeIndexGroup( - unindexedRulesIndexes, indexingBitOutputStream, /* isIndexed= */ false); - indexingBitOutputStream.flush(); - } catch (Exception e) { - throw new RuleSerializeException(e.getMessage(), e); - } - } - - private void verifySize(Map<String, List<Rule>> ruleListMap, int ruleSizeLimit) { - int totalRuleCount = - ruleListMap.values().stream() - .map(list -> list.size()) - .collect(Collectors.summingInt(Integer::intValue)); - if (totalRuleCount > ruleSizeLimit) { - throw new IllegalArgumentException( - "Too many rules provided in the indexing group. Provided " - + totalRuleCount - + " limit " - + ruleSizeLimit); - } - } - - private void serializeRuleFileMetadata( - Optional<Integer> formatVersion, ByteTrackedOutputStream outputStream) - throws IOException { - int formatVersionValue = formatVersion.orElse(DEFAULT_FORMAT_VERSION); - - BitOutputStream bitOutputStream = new BitOutputStream(outputStream); - bitOutputStream.setNext(FORMAT_VERSION_BITS, formatVersionValue); - bitOutputStream.flush(); - } - - private LinkedHashMap<String, Integer> serializeRuleList( - Map<String, List<Rule>> rulesMap, ByteTrackedOutputStream outputStream) - throws IOException { - Preconditions.checkArgument( - rulesMap != null, "serializeRuleList should never be called with null rule list."); - - BitOutputStream bitOutputStream = new BitOutputStream(outputStream); - LinkedHashMap<String, Integer> indexMapping = new LinkedHashMap(); - indexMapping.put(START_INDEXING_KEY, outputStream.getWrittenBytesCount()); - - List<String> sortedKeys = rulesMap.keySet().stream().sorted().collect(Collectors.toList()); - int indexTracker = 0; - for (String key : sortedKeys) { - if (indexTracker >= INDEXING_BLOCK_SIZE) { - indexMapping.put(key, outputStream.getWrittenBytesCount()); - indexTracker = 0; - } - - for (Rule rule : rulesMap.get(key)) { - serializeRule(rule, bitOutputStream); - bitOutputStream.flush(); - indexTracker++; - } - } - indexMapping.put(END_INDEXING_KEY, outputStream.getWrittenBytesCount()); - - return indexMapping; - } - - private void serializeRule(Rule rule, BitOutputStream bitOutputStream) throws IOException { - if (rule == null) { - throw new IllegalArgumentException("Null rule can not be serialized"); - } - - // Start with a '1' bit to mark the start of a rule. - bitOutputStream.setNext(); - - serializeFormula(rule.getFormula(), bitOutputStream); - bitOutputStream.setNext(EFFECT_BITS, rule.getEffect()); - - // End with a '1' bit to mark the end of a rule. - bitOutputStream.setNext(); - } - - private void serializeFormula(IntegrityFormula formula, BitOutputStream bitOutputStream) - throws IOException { - if (formula instanceof AtomicFormula) { - 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())); - } - } - - private void serializeCompoundFormula( - CompoundFormula compoundFormula, BitOutputStream bitOutputStream) throws IOException { - if (compoundFormula == null) { - throw new IllegalArgumentException("Null compound formula can not be serialized"); - } - - bitOutputStream.setNext(SEPARATOR_BITS, COMPOUND_FORMULA_START); - bitOutputStream.setNext(CONNECTOR_BITS, compoundFormula.getConnector()); - for (IntegrityFormula formula : compoundFormula.getFormulas()) { - serializeFormula(formula, bitOutputStream); - } - bitOutputStream.setNext(SEPARATOR_BITS, COMPOUND_FORMULA_END); - } - - private void serializeAtomicFormula( - AtomicFormula atomicFormula, BitOutputStream bitOutputStream) throws IOException { - if (atomicFormula == null) { - throw new IllegalArgumentException("Null atomic formula can not be serialized"); - } - - bitOutputStream.setNext(SEPARATOR_BITS, ATOMIC_FORMULA_START); - bitOutputStream.setNext(KEY_BITS, atomicFormula.getKey()); - if (atomicFormula.getTag() == AtomicFormula.STRING_ATOMIC_FORMULA_TAG) { - AtomicFormula.StringAtomicFormula stringAtomicFormula = - (AtomicFormula.StringAtomicFormula) atomicFormula; - bitOutputStream.setNext(OPERATOR_BITS, AtomicFormula.EQ); - serializeStringValue( - stringAtomicFormula.getValue(), - stringAtomicFormula.getIsHashedValue(), - bitOutputStream); - } else if (atomicFormula.getTag() == AtomicFormula.LONG_ATOMIC_FORMULA_TAG) { - AtomicFormula.LongAtomicFormula longAtomicFormula = - (AtomicFormula.LongAtomicFormula) atomicFormula; - bitOutputStream.setNext(OPERATOR_BITS, longAtomicFormula.getOperator()); - // TODO(b/147880712): Temporary hack until we support long values in bitOutputStream - long value = longAtomicFormula.getValue(); - serializeIntValue((int) (value >>> 32), bitOutputStream); - serializeIntValue((int) value, bitOutputStream); - } else if (atomicFormula.getTag() == AtomicFormula.BOOLEAN_ATOMIC_FORMULA_TAG) { - AtomicFormula.BooleanAtomicFormula booleanAtomicFormula = - (AtomicFormula.BooleanAtomicFormula) atomicFormula; - bitOutputStream.setNext(OPERATOR_BITS, AtomicFormula.EQ); - serializeBooleanValue(booleanAtomicFormula.getValue(), bitOutputStream); - } else { - throw new IllegalArgumentException( - String.format("Invalid atomic formula type: %s", atomicFormula.getClass())); - } - } - - private void serializeIndexGroup( - LinkedHashMap<String, Integer> indexes, - BitOutputStream bitOutputStream, - boolean isIndexed) - throws IOException { - // Output the starting location of this indexing group. - serializeStringValue(START_INDEXING_KEY, /* isHashedValue= */ false, bitOutputStream); - serializeIntValue(indexes.get(START_INDEXING_KEY), bitOutputStream); - - // If the group is indexed, output the locations of the indexes. - if (isIndexed) { - for (Map.Entry<String, Integer> entry : indexes.entrySet()) { - if (!entry.getKey().equals(START_INDEXING_KEY) - && !entry.getKey().equals(END_INDEXING_KEY)) { - serializeStringValue( - entry.getKey(), /* isHashedValue= */ false, bitOutputStream); - serializeIntValue(entry.getValue(), bitOutputStream); - } - } - } - - // Output the end location of this indexing group. - serializeStringValue(END_INDEXING_KEY, /*isHashedValue= */ false, bitOutputStream); - serializeIntValue(indexes.get(END_INDEXING_KEY), bitOutputStream); - } - - private void serializeStringValue( - String value, boolean isHashedValue, BitOutputStream bitOutputStream) - throws IOException { - if (value == null) { - throw new IllegalArgumentException("String value can not be null."); - } - byte[] valueBytes = getBytesForString(value, isHashedValue); - - bitOutputStream.setNext(isHashedValue); - bitOutputStream.setNext(VALUE_SIZE_BITS, valueBytes.length); - for (byte valueByte : valueBytes) { - bitOutputStream.setNext(/* numOfBits= */ 8, valueByte); - } - } - - private void serializeIntValue(int value, BitOutputStream bitOutputStream) throws IOException { - bitOutputStream.setNext(/* numOfBits= */ 32, value); - } - - private void serializeBooleanValue(boolean value, BitOutputStream bitOutputStream) - throws IOException { - bitOutputStream.setNext(value); - } - - // Get the byte array for a value. - // If the value is not hashed, use its byte array form directly. - // If the value is hashed, get the raw form decoding of the value. All hashed values are - // hex-encoded. Serialized values are in raw form. - private static byte[] getBytesForString(String value, boolean isHashedValue) { - if (!isHashedValue) { - return value.getBytes(StandardCharsets.UTF_8); - } - return IntegrityUtils.getBytesFromHexDigest(value); - } -} diff --git a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetails.java b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetails.java deleted file mode 100644 index 2cbd4ede5214..000000000000 --- a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetails.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 android.annotation.IntDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** Holds the indexing type and indexing key of a given formula. */ -class RuleIndexingDetails { - - static final int NOT_INDEXED = 0; - static final int PACKAGE_NAME_INDEXED = 1; - static final int APP_CERTIFICATE_INDEXED = 2; - - static final String DEFAULT_RULE_KEY = "N/A"; - - /** Represents which indexed file the rule should be located. */ - @IntDef( - value = { - NOT_INDEXED, - PACKAGE_NAME_INDEXED, - APP_CERTIFICATE_INDEXED - }) - @Retention(RetentionPolicy.SOURCE) - public @interface IndexType { - } - - private @IndexType int mIndexType; - private String mRuleKey; - - /** Constructor without a ruleKey for {@code NOT_INDEXED}. */ - RuleIndexingDetails(@IndexType int indexType) { - this.mIndexType = indexType; - this.mRuleKey = DEFAULT_RULE_KEY; - } - - /** Constructor with a ruleKey for indexed rules. */ - RuleIndexingDetails(@IndexType int indexType, String ruleKey) { - this.mIndexType = indexType; - this.mRuleKey = ruleKey; - } - - /** Returns the indexing type for the rule. */ - @IndexType - public int getIndexType() { - return mIndexType; - } - - /** Returns the identified rule key. */ - public String getRuleKey() { - return mRuleKey; - } -} diff --git a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java deleted file mode 100644 index e7235591fb9b..000000000000 --- a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED; -import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED; -import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED; - -import android.content.integrity.AtomicFormula; -import android.content.integrity.CompoundFormula; -import android.content.integrity.IntegrityFormula; -import android.content.integrity.Rule; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -/** A helper class for identifying the indexing type and key of a given rule. */ -class RuleIndexingDetailsIdentifier { - - /** - * Splits a given rule list into three indexing categories. Each rule category is returned as a - * TreeMap that is sorted by their indexing keys -- where keys correspond to package name for - * PACKAGE_NAME_INDEXED rules, app certificate for APP_CERTIFICATE_INDEXED rules and N/A for - * NOT_INDEXED rules. - */ - public static Map<Integer, Map<String, List<Rule>>> splitRulesIntoIndexBuckets( - List<Rule> rules) { - if (rules == null) { - throw new IllegalArgumentException( - "Index buckets cannot be created for null rule list."); - } - - Map<Integer, Map<String, List<Rule>>> typeOrganizedRuleMap = new HashMap(); - typeOrganizedRuleMap.put(NOT_INDEXED, new HashMap()); - typeOrganizedRuleMap.put(PACKAGE_NAME_INDEXED, new HashMap<>()); - typeOrganizedRuleMap.put(APP_CERTIFICATE_INDEXED, new HashMap<>()); - - // Split the rules into the appropriate indexed pattern. The Tree Maps help us to keep the - // entries sorted by their index key. - for (Rule rule : rules) { - RuleIndexingDetails indexingDetails; - try { - indexingDetails = getIndexingDetails(rule.getFormula()); - } catch (Exception e) { - throw new IllegalArgumentException( - String.format("Malformed rule identified. [%s]", rule.toString())); - } - - int ruleIndexType = indexingDetails.getIndexType(); - String ruleKey = indexingDetails.getRuleKey(); - - if (!typeOrganizedRuleMap.get(ruleIndexType).containsKey(ruleKey)) { - typeOrganizedRuleMap.get(ruleIndexType).put(ruleKey, new ArrayList()); - } - - typeOrganizedRuleMap.get(ruleIndexType).get(ruleKey).add(rule); - } - - return typeOrganizedRuleMap; - } - - private static RuleIndexingDetails getIndexingDetails(IntegrityFormula formula) { - switch (formula.getTag()) { - case IntegrityFormula.COMPOUND_FORMULA_TAG: - return getIndexingDetailsForCompoundFormula((CompoundFormula) formula); - case IntegrityFormula.STRING_ATOMIC_FORMULA_TAG: - 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); - default: - throw new IllegalArgumentException( - String.format("Invalid formula tag type: %s", formula.getTag())); - } - } - - private static RuleIndexingDetails getIndexingDetailsForCompoundFormula( - CompoundFormula compoundFormula) { - int connector = compoundFormula.getConnector(); - List<IntegrityFormula> formulas = compoundFormula.getFormulas(); - - switch (connector) { - case CompoundFormula.AND: - case CompoundFormula.OR: - // If there is a package name related atomic rule, return package name indexed. - Optional<RuleIndexingDetails> packageNameRule = - formulas.stream() - .map(formula -> getIndexingDetails(formula)) - .filter(ruleIndexingDetails -> ruleIndexingDetails.getIndexType() - == PACKAGE_NAME_INDEXED) - .findAny(); - if (packageNameRule.isPresent()) { - return packageNameRule.get(); - } - - // If there is an app certificate related atomic rule but no package name related - // atomic rule, return app certificate indexed. - Optional<RuleIndexingDetails> appCertificateRule = - formulas.stream() - .map(formula -> getIndexingDetails(formula)) - .filter(ruleIndexingDetails -> ruleIndexingDetails.getIndexType() - == APP_CERTIFICATE_INDEXED) - .findAny(); - if (appCertificateRule.isPresent()) { - return appCertificateRule.get(); - } - - // Do not index when there is not package name or app certificate indexing. - return new RuleIndexingDetails(NOT_INDEXED); - default: - // Having a NOT operator in the indexing messes up the indexing; e.g., deny - // installation if app certificate is NOT X (should not be indexed with app cert - // X). We will not keep these rules indexed. - // Also any other type of unknown operators will not be indexed. - return new RuleIndexingDetails(NOT_INDEXED); - } - } - - private static RuleIndexingDetails getIndexingDetailsForStringAtomicFormula( - AtomicFormula.StringAtomicFormula atomicFormula) { - switch (atomicFormula.getKey()) { - case AtomicFormula.PACKAGE_NAME: - return new RuleIndexingDetails(PACKAGE_NAME_INDEXED, atomicFormula.getValue()); - case AtomicFormula.APP_CERTIFICATE: - return new RuleIndexingDetails(APP_CERTIFICATE_INDEXED, atomicFormula.getValue()); - default: - return new RuleIndexingDetails(NOT_INDEXED); - } - } -} - diff --git a/services/core/java/com/android/server/integrity/serializer/RuleMetadataSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleMetadataSerializer.java deleted file mode 100644 index 022b4b8cb7eb..000000000000 --- a/services/core/java/com/android/server/integrity/serializer/RuleMetadataSerializer.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.parser.RuleMetadataParser.RULE_PROVIDER_TAG; -import static com.android.server.integrity.parser.RuleMetadataParser.VERSION_TAG; - -import android.util.Xml; - -import com.android.modules.utils.TypedXmlSerializer; -import com.android.server.integrity.model.RuleMetadata; - -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; - -/** Helper class for writing rule metadata. */ -public class RuleMetadataSerializer { - /** Serialize the rule metadata to an output stream. */ - public static void serialize(RuleMetadata ruleMetadata, OutputStream outputStream) - throws IOException { - TypedXmlSerializer xmlSerializer = Xml.resolveSerializer(outputStream); - - serializeTaggedValue(xmlSerializer, RULE_PROVIDER_TAG, ruleMetadata.getRuleProvider()); - serializeTaggedValue(xmlSerializer, VERSION_TAG, ruleMetadata.getVersion()); - - xmlSerializer.endDocument(); - } - - private static void serializeTaggedValue(TypedXmlSerializer xmlSerializer, String tag, - String value) throws IOException { - xmlSerializer.startTag(/* namespace= */ null, tag); - xmlSerializer.text(value); - xmlSerializer.endTag(/* namespace= */ null, tag); - } -} diff --git a/services/core/java/com/android/server/integrity/serializer/RuleSerializeException.java b/services/core/java/com/android/server/integrity/serializer/RuleSerializeException.java deleted file mode 100644 index 60cfc4876414..000000000000 --- a/services/core/java/com/android/server/integrity/serializer/RuleSerializeException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 android.annotation.NonNull; - -/** - * Thrown when rule serialization fails. - */ -public class RuleSerializeException extends Exception { - public RuleSerializeException(@NonNull String message) { - super(message); - } - - public RuleSerializeException(@NonNull String message, @NonNull Throwable cause) { - super(message, cause); - } -} diff --git a/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java deleted file mode 100644 index 2941856915a8..000000000000 --- a/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 android.content.integrity.Rule; - -import java.io.OutputStream; -import java.util.List; -import java.util.Optional; - -/** A helper class to serialize rules from the {@link Rule} model. */ -public interface RuleSerializer { - - /** Serialize rules to an output stream */ - void serialize( - List<Rule> rules, - Optional<Integer> formatVersion, - OutputStream ruleFileOutputStream, - OutputStream indexingFileOutputStream) - throws RuleSerializeException; - - /** Serialize rules to a ByteArray. */ - byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion) - throws RuleSerializeException; -} diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java deleted file mode 100644 index 9ed2e88bd6a2..000000000000 --- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java +++ /dev/null @@ -1,914 +0,0 @@ -/* - * 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.model.IndexingFileConstants.END_INDEXING_KEY; -import static com.android.server.integrity.model.IndexingFileConstants.INDEXING_BLOCK_SIZE; -import static com.android.server.integrity.model.IndexingFileConstants.START_INDEXING_KEY; -import static com.android.server.integrity.serializer.RuleBinarySerializer.INDEXED_RULE_SIZE_LIMIT; -import static com.android.server.integrity.serializer.RuleBinarySerializer.NONINDEXED_RULE_SIZE_LIMIT; -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.IntegrityFormula; -import android.content.integrity.IntegrityUtils; -import android.content.integrity.Rule; - -import androidx.annotation.NonNull; - -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)); - - private static final String SERIALIZED_START_INDEXING_KEY = - IS_NOT_HASHED - + getBits(START_INDEXING_KEY.length(), VALUE_SIZE_BITS) - + getValueBits(START_INDEXING_KEY); - private static final String SERIALIZED_END_INDEXING_KEY = - IS_NOT_HASHED - + getBits(END_INDEXING_KEY.length(), VALUE_SIZE_BITS) - + getValueBits(END_INDEXING_KEY); - - @Test - public void testBinaryString_serializeNullRules() { - RuleSerializer binarySerializer = new RuleBinarySerializer(); - - assertExpectException( - RuleSerializeException.class, - /* expectedExceptionMessageRegex= */ "Null rules cannot be serialized.", - () -> binarySerializer.serialize(null, /* formatVersion= */ Optional.empty())); - } - - @Test - public void testBinaryString_emptyRules() throws Exception { - ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream(); - ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream(); - RuleSerializer binarySerializer = new RuleBinarySerializer(); - - binarySerializer.serialize( - Collections.emptyList(), - /* formatVersion= */ Optional.empty(), - ruleOutputStream, - indexingOutputStream); - - ByteArrayOutputStream expectedRuleOutputStream = new ByteArrayOutputStream(); - expectedRuleOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); - assertThat(ruleOutputStream.toByteArray()) - .isEqualTo(expectedRuleOutputStream.toByteArray()); - - ByteArrayOutputStream expectedIndexingOutputStream = new ByteArrayOutputStream(); - String serializedIndexingBytes = - SERIALIZED_START_INDEXING_KEY - + getBits(DEFAULT_FORMAT_VERSION_BYTES.length, /* numOfBits= */ 32) - + SERIALIZED_END_INDEXING_KEY - + getBits(DEFAULT_FORMAT_VERSION_BYTES.length, /* numOfBits= */ 32); - byte[] expectedIndexingBytes = - getBytes( - serializedIndexingBytes - + serializedIndexingBytes - + serializedIndexingBytes); - expectedIndexingOutputStream.write(expectedIndexingBytes); - assertThat(indexingOutputStream.toByteArray()) - .isEqualTo(expectedIndexingOutputStream.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); - - ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream(); - ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream(); - RuleSerializer binarySerializer = new RuleBinarySerializer(); - binarySerializer.serialize( - Collections.singletonList(rule), - /* formatVersion= */ Optional.empty(), - ruleOutputStream, - indexingOutputStream); - - 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 expectedRuleOutputStream = new ByteArrayOutputStream(); - expectedRuleOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); - expectedRuleOutputStream.write(getBytes(expectedBits)); - assertThat(ruleOutputStream.toByteArray()) - .isEqualTo(expectedRuleOutputStream.toByteArray()); - - ByteArrayOutputStream expectedIndexingOutputStream = new ByteArrayOutputStream(); - String expectedIndexingBitsForIndexed = - SERIALIZED_START_INDEXING_KEY - + getBits(DEFAULT_FORMAT_VERSION_BYTES.length, /* numOfBits= */ 32) - + SERIALIZED_END_INDEXING_KEY - + getBits(DEFAULT_FORMAT_VERSION_BYTES.length, /* numOfBits= */ 32); - String expectedIndexingBitsForUnindexed = - SERIALIZED_START_INDEXING_KEY - + getBits(DEFAULT_FORMAT_VERSION_BYTES.length, /* numOfBits= */ 32) - + SERIALIZED_END_INDEXING_KEY - + getBits( - DEFAULT_FORMAT_VERSION_BYTES.length + getBytes(expectedBits).length, - /* numOfBits= */ 32); - expectedIndexingOutputStream.write( - getBytes( - expectedIndexingBitsForIndexed - + expectedIndexingBitsForIndexed - + expectedIndexingBitsForUnindexed)); - - assertThat(indexingOutputStream.toByteArray()) - .isEqualTo(expectedIndexingOutputStream.toByteArray()); - } - - @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 { - long versionCode = 1; - Rule rule = - new Rule( - new AtomicFormula.LongAtomicFormula( - 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= */ 64) - + 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 { - IntegrityFormula 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_verifyManyRulesAreIndexedCorrectly() throws Exception { - int ruleCount = 225; - String packagePrefix = "package.name."; - String appCertificatePrefix = "app.cert."; - String installerNamePrefix = "installer."; - - // Create the rule set with 225 package name based rules, 225 app certificate indexed rules, - // and 225 non-indexed rules.. - List<Rule> ruleList = new ArrayList(); - for (int count = 0; count < ruleCount; count++) { - ruleList.add( - getRuleWithPackageNameAndSampleInstallerName( - String.format("%s%04d", packagePrefix, count))); - } - for (int count = 0; count < ruleCount; count++) { - ruleList.add( - getRuleWithAppCertificateAndSampleInstallerName( - String.format("%s%04d", appCertificatePrefix, count))); - } - for (int count = 0; count < ruleCount; count++) { - ruleList.add( - getNonIndexedRuleWithInstallerName( - String.format("%s%04d", installerNamePrefix, count))); - } - - // Serialize the rules. - ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream(); - ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream(); - RuleSerializer binarySerializer = new RuleBinarySerializer(); - binarySerializer.serialize( - ruleList, - /* formatVersion= */ Optional.empty(), - ruleOutputStream, - indexingOutputStream); - - // Verify the rules file and index files. - ByteArrayOutputStream expectedOrderedRuleOutputStream = new ByteArrayOutputStream(); - ByteArrayOutputStream expectedIndexingOutputStream = new ByteArrayOutputStream(); - - expectedOrderedRuleOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES); - int totalBytesWritten = DEFAULT_FORMAT_VERSION_BYTES.length; - - String expectedIndexingBytesForPackageNameIndexed = - SERIALIZED_START_INDEXING_KEY + getBits(totalBytesWritten, /* numOfBits= */ 32); - for (int count = 0; count < ruleCount; count++) { - String packageName = String.format("%s%04d", packagePrefix, count); - if (count > 0 && count % INDEXING_BLOCK_SIZE == 0) { - expectedIndexingBytesForPackageNameIndexed += - IS_NOT_HASHED - + getBits(packageName.length(), VALUE_SIZE_BITS) - + getValueBits(packageName) - + getBits(totalBytesWritten, /* numOfBits= */ 32); - } - - byte[] bytesForPackage = - getBytes( - getSerializedCompoundRuleWithPackageNameAndSampleInstallerName( - packageName)); - expectedOrderedRuleOutputStream.write(bytesForPackage); - totalBytesWritten += bytesForPackage.length; - } - expectedIndexingBytesForPackageNameIndexed += - SERIALIZED_END_INDEXING_KEY + getBits(totalBytesWritten, /* numOfBits= */ 32); - - String expectedIndexingBytesForAppCertificateIndexed = - SERIALIZED_START_INDEXING_KEY + getBits(totalBytesWritten, /* numOfBits= */ 32); - for (int count = 0; count < ruleCount; count++) { - String appCertificate = String.format("%s%04d", appCertificatePrefix, count); - if (count > 0 && count % INDEXING_BLOCK_SIZE == 0) { - expectedIndexingBytesForAppCertificateIndexed += - IS_NOT_HASHED - + getBits(appCertificate.length(), VALUE_SIZE_BITS) - + getValueBits(appCertificate) - + getBits(totalBytesWritten, /* numOfBits= */ 32); - } - - byte[] bytesForPackage = - getBytes( - getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName( - appCertificate)); - expectedOrderedRuleOutputStream.write(bytesForPackage); - totalBytesWritten += bytesForPackage.length; - } - expectedIndexingBytesForAppCertificateIndexed += - SERIALIZED_END_INDEXING_KEY + getBits(totalBytesWritten, /* numOfBits= */ 32); - - String expectedIndexingBytesForUnindexed = - SERIALIZED_START_INDEXING_KEY + getBits(totalBytesWritten, /* numOfBits= */ 32); - for (int count = 0; count < ruleCount; count++) { - byte[] bytesForPackage = - getBytes( - getSerializedCompoundRuleWithInstallerNameAndInstallerCert( - String.format("%s%04d", installerNamePrefix, count))); - expectedOrderedRuleOutputStream.write(bytesForPackage); - totalBytesWritten += bytesForPackage.length; - } - expectedIndexingBytesForUnindexed += - SERIALIZED_END_INDEXING_KEY + getBits(totalBytesWritten, /* numOfBits= */ 32); - expectedIndexingOutputStream.write( - getBytes( - expectedIndexingBytesForPackageNameIndexed - + expectedIndexingBytesForAppCertificateIndexed - + expectedIndexingBytesForUnindexed)); - - assertThat(ruleOutputStream.toByteArray()) - .isEqualTo(expectedOrderedRuleOutputStream.toByteArray()); - assertThat(indexingOutputStream.toByteArray()) - .isEqualTo(expectedIndexingOutputStream.toByteArray()); - } - - @Test - public void testBinaryString_totalRuleSizeLimitReached() { - int ruleCount = INDEXED_RULE_SIZE_LIMIT - 1; - String packagePrefix = "package.name."; - String appCertificatePrefix = "app.cert."; - String installerNamePrefix = "installer."; - - // Create the rule set with more rules than the system can handle in total. - List<Rule> ruleList = new ArrayList(); - for (int count = 0; count < ruleCount; count++) { - ruleList.add( - getRuleWithPackageNameAndSampleInstallerName( - String.format("%s%04d", packagePrefix, count))); - } - for (int count = 0; count < ruleCount; count++) { - ruleList.add( - getRuleWithAppCertificateAndSampleInstallerName( - String.format("%s%04d", appCertificatePrefix, count))); - } - for (int count = 0; count < NONINDEXED_RULE_SIZE_LIMIT - 1; count++) { - ruleList.add( - getNonIndexedRuleWithInstallerName( - String.format("%s%04d", installerNamePrefix, count))); - } - - // Serialize the rules. - ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream(); - ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream(); - RuleSerializer binarySerializer = new RuleBinarySerializer(); - - assertExpectException( - RuleSerializeException.class, - "Too many rules provided", - () -> - binarySerializer.serialize( - ruleList, - /* formatVersion= */ Optional.empty(), - ruleOutputStream, - indexingOutputStream)); - } - - @Test - public void testBinaryString_tooManyPackageNameIndexedRules() { - String packagePrefix = "package.name."; - - // Create a rule set with too many package name indexed rules. - List<Rule> ruleList = new ArrayList(); - for (int count = 0; count < INDEXED_RULE_SIZE_LIMIT + 1; count++) { - ruleList.add( - getRuleWithPackageNameAndSampleInstallerName( - String.format("%s%04d", packagePrefix, count))); - } - - // Serialize the rules. - ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream(); - ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream(); - RuleSerializer binarySerializer = new RuleBinarySerializer(); - - assertExpectException( - RuleSerializeException.class, - "Too many rules provided in the indexing group.", - () -> - binarySerializer.serialize( - ruleList, - /* formatVersion= */ Optional.empty(), - ruleOutputStream, - indexingOutputStream)); - } - - @Test - public void testBinaryString_tooManyAppCertificateIndexedRules() { - String appCertificatePrefix = "app.cert."; - - // Create a rule set with too many app certificate indexed rules. - List<Rule> ruleList = new ArrayList(); - for (int count = 0; count < INDEXED_RULE_SIZE_LIMIT + 1; count++) { - ruleList.add( - getRuleWithAppCertificateAndSampleInstallerName( - String.format("%s%04d", appCertificatePrefix, count))); - } - - // Serialize the rules. - ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream(); - ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream(); - RuleSerializer binarySerializer = new RuleBinarySerializer(); - - assertExpectException( - RuleSerializeException.class, - "Too many rules provided in the indexing group.", - () -> - binarySerializer.serialize( - ruleList, - /* formatVersion= */ Optional.empty(), - ruleOutputStream, - indexingOutputStream)); - } - - @Test - public void testBinaryString_tooManyNonIndexedRules() { - String installerNamePrefix = "installer."; - - // Create a rule set with too many unindexed rules. - List<Rule> ruleList = new ArrayList(); - for (int count = 0; count < NONINDEXED_RULE_SIZE_LIMIT + 1; count++) { - ruleList.add( - getNonIndexedRuleWithInstallerName( - String.format("%s%04d", installerNamePrefix, count))); - } - - // Serialize the rules. - ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream(); - ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream(); - RuleSerializer binarySerializer = new RuleBinarySerializer(); - - assertExpectException( - RuleSerializeException.class, - "Too many rules provided in the indexing group.", - () -> - binarySerializer.serialize( - ruleList, - /* formatVersion= */ Optional.empty(), - ruleOutputStream, - indexingOutputStream)); - } - - 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 Rule getNonIndexedRuleWithInstallerName(String installerName) { - return new Rule( - new CompoundFormula( - CompoundFormula.AND, - Arrays.asList( - new AtomicFormula.StringAtomicFormula( - AtomicFormula.INSTALLER_NAME, - installerName, - /* isHashedValue= */ false), - new AtomicFormula.StringAtomicFormula( - AtomicFormula.INSTALLER_CERTIFICATE, - SAMPLE_INSTALLER_CERT, - /* isHashedValue= */ false))), - Rule.DENY); - } - - private String getSerializedCompoundRuleWithInstallerNameAndInstallerCert( - String installerName) { - return START_BIT - + COMPOUND_FORMULA_START_BITS - + AND - + ATOMIC_FORMULA_START_BITS - + INSTALLER_NAME - + EQ - + IS_NOT_HASHED - + getBits(installerName.length(), VALUE_SIZE_BITS) - + getValueBits(installerName) - + 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; - } - - private static IntegrityFormula getInvalidFormula() { - return new AtomicFormula(0) { - @Override - public int getTag() { - return 0; - } - - @Override - public boolean matches(AppInstallMetadata appInstallMetadata) { - return false; - } - - @Override - public boolean isAppCertificateFormula() { - return false; - } - - @Override - public boolean isAppCertificateLineageFormula() { - return false; - } - - @Override - public boolean isInstallerFormula() { - return false; - } - - @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(); - } - }; - } -} diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java deleted file mode 100644 index 6dccdf51af02..000000000000 --- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * 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.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED; -import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED; -import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED; -import static com.android.server.integrity.serializer.RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets; -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.IntegrityFormula; -import android.content.integrity.Rule; - -import androidx.annotation.NonNull; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -/** Unit tests for {@link RuleIndexingDetailsIdentifier}. */ -@RunWith(JUnit4.class) -public class RuleIndexingDetailsIdentifierTest { - - private static final String SAMPLE_APP_CERTIFICATE = "testcert"; - private static final String SAMPLE_INSTALLER_NAME = "com.test.installer"; - private static final String SAMPLE_INSTALLER_CERTIFICATE = "installercert"; - private static final String SAMPLE_PACKAGE_NAME = "com.test.package"; - - private static final AtomicFormula ATOMIC_FORMULA_WITH_PACKAGE_NAME = - new AtomicFormula.StringAtomicFormula( - AtomicFormula.PACKAGE_NAME, - SAMPLE_PACKAGE_NAME, - /* isHashedValue= */ false); - private static final AtomicFormula ATOMIC_FORMULA_WITH_APP_CERTIFICATE = - new AtomicFormula.StringAtomicFormula( - AtomicFormula.APP_CERTIFICATE, - SAMPLE_APP_CERTIFICATE, - /* isHashedValue= */ false); - private static final AtomicFormula ATOMIC_FORMULA_WITH_INSTALLER_NAME = - new AtomicFormula.StringAtomicFormula( - AtomicFormula.INSTALLER_NAME, - SAMPLE_INSTALLER_NAME, - /* isHashedValue= */ false); - private static final AtomicFormula ATOMIC_FORMULA_WITH_INSTALLER_CERTIFICATE = - new AtomicFormula.StringAtomicFormula( - AtomicFormula.INSTALLER_CERTIFICATE, - SAMPLE_INSTALLER_CERTIFICATE, - /* isHashedValue= */ false); - private static final AtomicFormula ATOMIC_FORMULA_WITH_VERSION_CODE = - new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, - AtomicFormula.EQ, 12); - private static final AtomicFormula ATOMIC_FORMULA_WITH_ISPREINSTALLED = - new AtomicFormula.BooleanAtomicFormula( - AtomicFormula.PRE_INSTALLED, /* booleanValue= */ - true); - - - private static final Rule RULE_WITH_PACKAGE_NAME = - new Rule( - new CompoundFormula( - CompoundFormula.AND, - Arrays.asList( - ATOMIC_FORMULA_WITH_PACKAGE_NAME, - ATOMIC_FORMULA_WITH_INSTALLER_NAME)), - Rule.DENY); - private static final Rule RULE_WITH_APP_CERTIFICATE = - new Rule( - new CompoundFormula( - CompoundFormula.AND, - Arrays.asList( - ATOMIC_FORMULA_WITH_APP_CERTIFICATE, - ATOMIC_FORMULA_WITH_INSTALLER_NAME)), - Rule.DENY); - private static final Rule RULE_WITH_INSTALLER_RESTRICTIONS = - new Rule( - new CompoundFormula( - CompoundFormula.AND, - Arrays.asList( - ATOMIC_FORMULA_WITH_INSTALLER_NAME, - ATOMIC_FORMULA_WITH_INSTALLER_CERTIFICATE)), - Rule.DENY); - - private static final Rule RULE_WITH_NONSTRING_RESTRICTIONS = - new Rule( - new CompoundFormula( - CompoundFormula.AND, - Arrays.asList( - ATOMIC_FORMULA_WITH_VERSION_CODE, - ATOMIC_FORMULA_WITH_ISPREINSTALLED)), - Rule.DENY); - public static final int INVALID_FORMULA_TAG = -1; - - @Test - public void getIndexType_nullRule() { - List<Rule> ruleList = null; - - assertExpectException( - IllegalArgumentException.class, - /* expectedExceptionMessageRegex= */ - "Index buckets cannot be created for null rule list.", - () -> splitRulesIntoIndexBuckets(ruleList)); - } - - @Test - public void getIndexType_invalidFormula() { - List<Rule> ruleList = new ArrayList(); - ruleList.add(new Rule(getInvalidFormula(), Rule.DENY)); - - assertExpectException( - IllegalArgumentException.class, - /* expectedExceptionMessageRegex= */ "Malformed rule identified.", - () -> splitRulesIntoIndexBuckets(ruleList)); - } - - @Test - public void getIndexType_ruleContainingPackageNameFormula() { - List<Rule> ruleList = new ArrayList(); - ruleList.add(RULE_WITH_PACKAGE_NAME); - - Map<Integer, Map<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList); - - // Verify the resulting map content. - assertThat(result.keySet()) - .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED); - assertThat(result.get(NOT_INDEXED)).isEmpty(); - assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty(); - assertThat(result.get(PACKAGE_NAME_INDEXED).keySet()).containsExactly(SAMPLE_PACKAGE_NAME); - assertThat(result.get(PACKAGE_NAME_INDEXED).get(SAMPLE_PACKAGE_NAME)) - .containsExactly(RULE_WITH_PACKAGE_NAME); - } - - @Test - public void getIndexType_ruleContainingAppCertificateFormula() { - List<Rule> ruleList = new ArrayList(); - ruleList.add(RULE_WITH_APP_CERTIFICATE); - - Map<Integer, Map<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList); - - assertThat(result.keySet()) - .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED); - assertThat(result.get(NOT_INDEXED)).isEmpty(); - assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty(); - assertThat(result.get(APP_CERTIFICATE_INDEXED).keySet()) - .containsExactly(SAMPLE_APP_CERTIFICATE); - assertThat(result.get(APP_CERTIFICATE_INDEXED).get(SAMPLE_APP_CERTIFICATE)) - .containsExactly(RULE_WITH_APP_CERTIFICATE); - } - - @Test - public void getIndexType_ruleWithUnindexedCompoundFormula() { - List<Rule> ruleList = new ArrayList(); - ruleList.add(RULE_WITH_INSTALLER_RESTRICTIONS); - - Map<Integer, Map<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList); - - assertThat(result.keySet()) - .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED); - assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty(); - assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty(); - assertThat(result.get(NOT_INDEXED).get("N/A")) - .containsExactly(RULE_WITH_INSTALLER_RESTRICTIONS); - } - - @Test - public void getIndexType_ruleContainingCompoundFormulaWithIntAndBoolean() { - List<Rule> ruleList = new ArrayList(); - ruleList.add(RULE_WITH_NONSTRING_RESTRICTIONS); - - Map<Integer, Map<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList); - - assertThat(result.keySet()) - .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED); - assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty(); - assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty(); - assertThat(result.get(NOT_INDEXED).get("N/A")) - .containsExactly(RULE_WITH_NONSTRING_RESTRICTIONS); - } - - @Test - public void getIndexType_negatedRuleContainingPackageNameFormula() { - Rule negatedRule = - new Rule( - new CompoundFormula( - CompoundFormula.NOT, - Arrays.asList( - new CompoundFormula( - CompoundFormula.AND, - Arrays.asList( - ATOMIC_FORMULA_WITH_PACKAGE_NAME, - ATOMIC_FORMULA_WITH_APP_CERTIFICATE)))), - Rule.DENY); - List<Rule> ruleList = new ArrayList(); - ruleList.add(negatedRule); - - Map<Integer, Map<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList); - - assertThat(result.keySet()) - .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED); - assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty(); - assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty(); - assertThat(result.get(NOT_INDEXED).get("N/A")).containsExactly(negatedRule); - } - - @Test - public void getIndexType_allRulesTogetherSplitCorrectly() { - Rule packageNameRuleA = getRuleWithPackageName("aaa"); - Rule packageNameRuleB = getRuleWithPackageName("bbb"); - Rule packageNameRuleC = getRuleWithPackageName("ccc"); - Rule certificateRule1 = getRuleWithAppCertificate("cert1"); - Rule certificateRule2 = getRuleWithAppCertificate("cert2"); - Rule certificateRule3 = getRuleWithAppCertificate("cert3"); - - List<Rule> ruleList = new ArrayList(); - ruleList.add(packageNameRuleB); - ruleList.add(packageNameRuleC); - ruleList.add(packageNameRuleA); - ruleList.add(certificateRule3); - ruleList.add(certificateRule2); - ruleList.add(certificateRule1); - ruleList.add(RULE_WITH_INSTALLER_RESTRICTIONS); - ruleList.add(RULE_WITH_NONSTRING_RESTRICTIONS); - - Map<Integer, Map<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList); - - assertThat(result.keySet()) - .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED); - - // We check asserts this way to ensure ordering based on package name. - assertThat(result.get(PACKAGE_NAME_INDEXED).keySet()).containsExactly("aaa", "bbb", "ccc"); - - // We check asserts this way to ensure ordering based on app certificate. - assertThat(result.get(APP_CERTIFICATE_INDEXED).keySet()).containsExactly("cert1", "cert2", - "cert3"); - - assertThat(result.get(NOT_INDEXED).get("N/A")) - .containsExactly(RULE_WITH_INSTALLER_RESTRICTIONS, - RULE_WITH_NONSTRING_RESTRICTIONS); - } - - private Rule getRuleWithPackageName(String packageName) { - return new Rule( - new CompoundFormula( - CompoundFormula.AND, - Arrays.asList( - new AtomicFormula.StringAtomicFormula( - AtomicFormula.PACKAGE_NAME, - packageName, - /* isHashedValue= */ false), - ATOMIC_FORMULA_WITH_INSTALLER_NAME)), - Rule.DENY); - } - - private Rule getRuleWithAppCertificate(String certificate) { - return new Rule( - new CompoundFormula( - CompoundFormula.AND, - Arrays.asList( - new AtomicFormula.StringAtomicFormula( - AtomicFormula.APP_CERTIFICATE, - certificate, - /* isHashedValue= */ false), - ATOMIC_FORMULA_WITH_INSTALLER_NAME)), - Rule.DENY); - } - - private IntegrityFormula getInvalidFormula() { - return new AtomicFormula(0) { - @Override - public int getTag() { - return INVALID_FORMULA_TAG; - } - - @Override - public boolean matches(AppInstallMetadata appInstallMetadata) { - return false; - } - - @Override - public boolean isAppCertificateFormula() { - return false; - } - - @Override - public boolean isAppCertificateLineageFormula() { - return false; - } - - @Override - public boolean isInstallerFormula() { - return false; - } - - @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(); - } - }; - } -} |