1103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai/* 2103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * Copyright 2017 The Android Open Source Project 3103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * 4103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * Licensed under the Apache License, Version 2.0 (the "License"); 5103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * you may not use this file except in compliance with the License. 6103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * You may obtain a copy of the License at 7103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * 8103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * http://www.apache.org/licenses/LICENSE-2.0 9103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * 10103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * Unless required by applicable law or agreed to in writing, software 11103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * distributed under the License is distributed on an "AS IS" BASIS, 12103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * See the License for the specific language governing permissions and 14103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * limitations under the License. 15103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai */ 16103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 17103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 18103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Waipackage com.android.server.net.watchlist; 19103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 20103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Waiimport android.annotation.Nullable; 21103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Waiimport android.util.Log; 22d89243bf546501fd6105d0373754e4c62681812aRicky Waiimport android.util.proto.ProtoOutputStream; 23103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 24103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Waiimport com.android.internal.annotations.VisibleForTesting; 25103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Waiimport com.android.internal.util.HexDump; 26d89243bf546501fd6105d0373754e4c62681812aRicky Waiimport com.android.service.NetworkWatchlistReportProto; 27d89243bf546501fd6105d0373754e4c62681812aRicky Waiimport com.android.service.NetworkWatchlistAppResultProto; 28103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 29d89243bf546501fd6105d0373754e4c62681812aRicky Waiimport java.io.ByteArrayOutputStream; 30103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Waiimport java.util.ArrayList; 31103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Waiimport java.util.Collections; 32103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Waiimport java.util.List; 33103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Waiimport java.util.Map; 34103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 35103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai/** 36d89243bf546501fd6105d0373754e4c62681812aRicky Wai * Helper class to encode and generate serialized DP encoded watchlist proto report. 37103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai */ 38103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Waiclass ReportEncoder { 39103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 40103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai private static final String TAG = "ReportEncoder"; 41103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 42103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai // Report version number, as file format / parameters can be changed in later version, we need 43103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai // to have versioning on watchlist report format 44d89243bf546501fd6105d0373754e4c62681812aRicky Wai private static final int REPORT_VERSION = 1; 45103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 46103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai private static final int WATCHLIST_HASH_SIZE = 32; 47103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 48103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai /** 49103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * Apply DP on watchlist results, and generate a serialized watchlist report ready to store 50103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * in DropBox. 51103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai */ 529973345b15fb0e45c89ba87e76ed727147215d7fRicky Wai @Nullable 53103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai static byte[] encodeWatchlistReport(WatchlistConfig config, byte[] userSecret, 54103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai List<String> appDigestList, WatchlistReportDbHelper.AggregatedResult aggregatedResult) { 55103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai Map<String, Boolean> resultMap = PrivacyUtils.createDpEncodedReportMap( 56103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai config.isConfigSecure(), userSecret, appDigestList, aggregatedResult); 57103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai return serializeReport(config, resultMap); 58103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai } 59103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 60103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai /** 61d89243bf546501fd6105d0373754e4c62681812aRicky Wai * Convert DP encoded watchlist report into proto format. 62103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * 63103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * @param encodedReportMap DP encoded watchlist report. 64d89243bf546501fd6105d0373754e4c62681812aRicky Wai * @return Watchlist report in proto format, which will be shared in Dropbox. Null if 65103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai * watchlist report cannot be generated. 66103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai */ 67103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai @Nullable 68103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai @VisibleForTesting 69103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai static byte[] serializeReport(WatchlistConfig config, 70103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai Map<String, Boolean> encodedReportMap) { 71103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai // TODO: Handle watchlist config changed case 72103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai final byte[] watchlistHash = config.getWatchlistConfigHash(); 73103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai if (watchlistHash == null) { 74103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai Log.e(TAG, "No watchlist hash"); 75103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai return null; 76103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai } 77103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai if (watchlistHash.length != WATCHLIST_HASH_SIZE) { 78103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai Log.e(TAG, "Unexpected hash length"); 79103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai return null; 80103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai } 81d89243bf546501fd6105d0373754e4c62681812aRicky Wai final ByteArrayOutputStream reportOutputStream = new ByteArrayOutputStream(); 82d89243bf546501fd6105d0373754e4c62681812aRicky Wai final ProtoOutputStream proto = new ProtoOutputStream(reportOutputStream); 83103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 84103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai // Set report version to report 85d89243bf546501fd6105d0373754e4c62681812aRicky Wai proto.write(NetworkWatchlistReportProto.REPORT_VERSION, REPORT_VERSION); 86d89243bf546501fd6105d0373754e4c62681812aRicky Wai proto.write(NetworkWatchlistReportProto.WATCHLIST_CONFIG_HASH, 87d89243bf546501fd6105d0373754e4c62681812aRicky Wai HexDump.toHexString(watchlistHash)); 88103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai 89103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai // Set app digest, encoded_isPha pair to report 90d89243bf546501fd6105d0373754e4c62681812aRicky Wai for (Map.Entry<String, Boolean> entry : encodedReportMap.entrySet()) { 91d89243bf546501fd6105d0373754e4c62681812aRicky Wai String key = entry.getKey(); 92103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai byte[] digest = HexDump.hexStringToByteArray(key); 93d89243bf546501fd6105d0373754e4c62681812aRicky Wai boolean encodedResult = entry.getValue(); 94d89243bf546501fd6105d0373754e4c62681812aRicky Wai long token = proto.start(NetworkWatchlistReportProto.APP_RESULT); 95d89243bf546501fd6105d0373754e4c62681812aRicky Wai proto.write(NetworkWatchlistAppResultProto.APP_DIGEST, key); 96d89243bf546501fd6105d0373754e4c62681812aRicky Wai proto.write(NetworkWatchlistAppResultProto.ENCODED_RESULT, encodedResult); 97d89243bf546501fd6105d0373754e4c62681812aRicky Wai proto.end(token); 98103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai } 99d89243bf546501fd6105d0373754e4c62681812aRicky Wai proto.flush(); 100d89243bf546501fd6105d0373754e4c62681812aRicky Wai return reportOutputStream.toByteArray(); 101103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai } 102103ebf5bc56b25c8b4d77daa82692a026da32e85Ricky Wai} 103