summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/net/watchlist/HarmfulCrcs.java63
-rw-r--r--services/core/java/com/android/server/net/watchlist/WatchlistConfig.java33
-rw-r--r--services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulCrcsTests.java60
3 files changed, 137 insertions, 19 deletions
diff --git a/services/core/java/com/android/server/net/watchlist/HarmfulCrcs.java b/services/core/java/com/android/server/net/watchlist/HarmfulCrcs.java
new file mode 100644
index 000000000000..65a4b23225c2
--- /dev/null
+++ b/services/core/java/com/android/server/net/watchlist/HarmfulCrcs.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 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.net.watchlist;
+
+import com.android.internal.util.HexDump;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Helper class to store a set of harmful CRC32s in memory.
+ * TODO: Optimize memory usage using int array with binary search.
+ */
+class HarmfulCrcs {
+
+ private final Set<Integer> mCrcSet;
+
+ HarmfulCrcs(List<byte[]> digests) {
+ final HashSet<Integer> crcSet = new HashSet<>();
+ final int size = digests.size();
+ for (int i = 0; i < size; i++) {
+ byte[] bytes = digests.get(i);
+ if (bytes.length <= 4) {
+ int crc = 0;
+ for (byte b : bytes) {
+ // Remember byte is signed
+ crc = (crc << 8) | (b & 0xff);
+ }
+ crcSet.add(crc);
+ }
+ }
+ mCrcSet = Collections.unmodifiableSet(crcSet);
+ }
+
+ public boolean contains(int crc) {
+ return mCrcSet.contains(crc);
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ for (int crc : mCrcSet) {
+ pw.println(HexDump.toHexString(crc));
+ }
+ pw.println("");
+ }
+}
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java b/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
index 8352ca60e362..7d06de335e84 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
@@ -18,7 +18,6 @@ package com.android.server.net.watchlist;
import android.annotation.Nullable;
import android.os.FileUtils;
-import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
import android.util.Xml;
@@ -66,11 +65,11 @@ class WatchlistConfig {
}
private static class CrcShaDigests {
- final HarmfulDigests crc32Digests;
- final HarmfulDigests sha256Digests;
+ public final HarmfulCrcs crc32s;
+ public final HarmfulDigests sha256Digests;
- public CrcShaDigests(HarmfulDigests crc32Digests, HarmfulDigests sha256Digests) {
- this.crc32Digests = crc32Digests;
+ CrcShaDigests(HarmfulCrcs crc32s, HarmfulDigests sha256Digests) {
+ this.crc32s = crc32s;
this.sha256Digests = sha256Digests;
}
}
@@ -140,9 +139,9 @@ class WatchlistConfig {
}
}
parser.require(XmlPullParser.END_TAG, null, XmlTags.WATCHLIST_CONFIG);
- mDomainDigests = new CrcShaDigests(new HarmfulDigests(crc32DomainList),
+ mDomainDigests = new CrcShaDigests(new HarmfulCrcs(crc32DomainList),
new HarmfulDigests(sha256DomainList));
- mIpDigests = new CrcShaDigests(new HarmfulDigests(crc32IpList),
+ mIpDigests = new CrcShaDigests(new HarmfulCrcs(crc32IpList),
new HarmfulDigests(sha256IpList));
Log.i(TAG, "Reload watchlist done");
} catch (IllegalStateException | NullPointerException | NumberFormatException |
@@ -171,8 +170,8 @@ class WatchlistConfig {
return false;
}
// First it does a quick CRC32 check.
- final byte[] crc32 = getCrc32(domain);
- if (!domainDigests.crc32Digests.contains(crc32)) {
+ final int crc32 = getCrc32(domain);
+ if (!domainDigests.crc32s.contains(crc32)) {
return false;
}
// Now we do a slow SHA256 check.
@@ -187,8 +186,8 @@ class WatchlistConfig {
return false;
}
// First it does a quick CRC32 check.
- final byte[] crc32 = getCrc32(ip);
- if (!ipDigests.crc32Digests.contains(crc32)) {
+ final int crc32 = getCrc32(ip);
+ if (!ipDigests.crc32s.contains(crc32)) {
return false;
}
// Now we do a slow SHA256 check.
@@ -198,15 +197,11 @@ class WatchlistConfig {
/** Get CRC32 of a string
- *
- * TODO: Review if we should use CRC32 or other algorithms
*/
- private byte[] getCrc32(String str) {
+ private int getCrc32(String str) {
final CRC32 crc = new CRC32();
crc.update(str.getBytes());
- final long tmp = crc.getValue();
- return new byte[]{(byte) (tmp >> 24 & 255), (byte) (tmp >> 16 & 255),
- (byte) (tmp >> 8 & 255), (byte) (tmp & 255)};
+ return (int) crc.getValue();
}
/** Get SHA256 of a string */
@@ -279,7 +274,7 @@ class WatchlistConfig {
pw.println("Domain CRC32 digest list:");
// mDomainDigests won't go from non-null to null so it's safe
if (mDomainDigests != null) {
- mDomainDigests.crc32Digests.dump(fd, pw, args);
+ mDomainDigests.crc32s.dump(fd, pw, args);
}
pw.println("Domain SHA256 digest list:");
if (mDomainDigests != null) {
@@ -288,7 +283,7 @@ class WatchlistConfig {
pw.println("Ip CRC32 digest list:");
// mIpDigests won't go from non-null to null so it's safe
if (mIpDigests != null) {
- mIpDigests.crc32Digests.dump(fd, pw, args);
+ mIpDigests.crc32s.dump(fd, pw, args);
}
pw.println("Ip SHA256 digest list:");
if (mIpDigests != null) {
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulCrcsTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulCrcsTests.java
new file mode 100644
index 000000000000..23f128115ea0
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulCrcsTests.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 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.net.watchlist;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.HexDump;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+/**
+ * runtest frameworks-services -c com.android.server.net.watchlist.HarmfulCrcTests
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class HarmfulCrcsTests {
+
+ private static final byte[] TEST_DIGEST = HexDump.hexStringToByteArray("AABBCCDD");
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testHarmfulCrcs_setAndContains() throws Exception {
+ HarmfulCrcs harmfulCrcs = new HarmfulCrcs(
+ Arrays.asList(new byte[][] {TEST_DIGEST}));
+ assertTrue(harmfulCrcs.contains(0xaabbccdd));
+ assertFalse(harmfulCrcs.contains(0xbbbbbbbb));
+ assertFalse(harmfulCrcs.contains(0x01020304));
+ assertFalse(harmfulCrcs.contains(0xddccbbaa));
+ }
+}