Home | History | Annotate | Download | only in watchlist
      1 /*
      2  * Copyright 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 
     18 package com.android.server.net.watchlist;
     19 
     20 import android.annotation.Nullable;
     21 import android.util.Log;
     22 import android.util.proto.ProtoOutputStream;
     23 
     24 import com.android.internal.annotations.VisibleForTesting;
     25 import com.android.internal.util.HexDump;
     26 import com.android.service.NetworkWatchlistReportProto;
     27 import com.android.service.NetworkWatchlistAppResultProto;
     28 
     29 import java.io.ByteArrayOutputStream;
     30 import java.util.ArrayList;
     31 import java.util.Collections;
     32 import java.util.List;
     33 import java.util.Map;
     34 
     35 /**
     36  * Helper class to encode and generate serialized DP encoded watchlist proto report.
     37  */
     38 class ReportEncoder {
     39 
     40     private static final String TAG = "ReportEncoder";
     41 
     42     // Report version number, as file format / parameters can be changed in later version, we need
     43     // to have versioning on watchlist report format
     44     private static final int REPORT_VERSION = 1;
     45 
     46     private static final int WATCHLIST_HASH_SIZE = 32;
     47 
     48     /**
     49      * Apply DP on watchlist results, and generate a serialized watchlist report ready to store
     50      * in DropBox.
     51      */
     52     @Nullable
     53     static byte[] encodeWatchlistReport(WatchlistConfig config, byte[] userSecret,
     54             List<String> appDigestList, WatchlistReportDbHelper.AggregatedResult aggregatedResult) {
     55         Map<String, Boolean> resultMap = PrivacyUtils.createDpEncodedReportMap(
     56                 config.isConfigSecure(), userSecret, appDigestList, aggregatedResult);
     57         return serializeReport(config, resultMap);
     58     }
     59 
     60     /**
     61      * Convert DP encoded watchlist report into proto format.
     62      *
     63      * @param encodedReportMap DP encoded watchlist report.
     64      * @return Watchlist report in proto format, which will be shared in Dropbox. Null if
     65      * watchlist report cannot be generated.
     66      */
     67     @Nullable
     68     @VisibleForTesting
     69     static byte[] serializeReport(WatchlistConfig config,
     70             Map<String, Boolean> encodedReportMap) {
     71         // TODO: Handle watchlist config changed case
     72         final byte[] watchlistHash = config.getWatchlistConfigHash();
     73         if (watchlistHash == null) {
     74             Log.e(TAG, "No watchlist hash");
     75             return null;
     76         }
     77         if (watchlistHash.length != WATCHLIST_HASH_SIZE) {
     78             Log.e(TAG, "Unexpected hash length");
     79             return null;
     80         }
     81         final ByteArrayOutputStream reportOutputStream = new ByteArrayOutputStream();
     82         final ProtoOutputStream proto = new ProtoOutputStream(reportOutputStream);
     83 
     84         // Set report version to report
     85         proto.write(NetworkWatchlistReportProto.REPORT_VERSION, REPORT_VERSION);
     86         proto.write(NetworkWatchlistReportProto.WATCHLIST_CONFIG_HASH,
     87                 HexDump.toHexString(watchlistHash));
     88 
     89         // Set app digest, encoded_isPha pair to report
     90         for (Map.Entry<String, Boolean> entry : encodedReportMap.entrySet()) {
     91             String key = entry.getKey();
     92             byte[] digest = HexDump.hexStringToByteArray(key);
     93             boolean encodedResult = entry.getValue();
     94             long token = proto.start(NetworkWatchlistReportProto.APP_RESULT);
     95             proto.write(NetworkWatchlistAppResultProto.APP_DIGEST, key);
     96             proto.write(NetworkWatchlistAppResultProto.ENCODED_RESULT, encodedResult);
     97             proto.end(token);
     98         }
     99         proto.flush();
    100         return reportOutputStream.toByteArray();
    101     }
    102 }
    103