• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 package com.android.managedprovisioning.task;
18 
19 import static java.util.Objects.requireNonNull;
20 
21 import android.content.pm.PackageInfo;
22 import android.content.pm.Signature;
23 
24 import com.android.managedprovisioning.common.ProvisionLogger;
25 import com.android.managedprovisioning.common.StoreUtils;
26 import com.android.managedprovisioning.common.Utils;
27 import com.android.managedprovisioning.model.PackageDownloadInfo;
28 
29 import java.util.Arrays;
30 import java.util.LinkedList;
31 import java.util.List;
32 
33 /**
34  * Utils related to checksum calculations and comparison.
35  */
36 final class ChecksumUtils {
37 
38     private final Utils mUtils;
39 
ChecksumUtils(Utils utils)40     ChecksumUtils(Utils utils) {
41         mUtils = requireNonNull(utils);
42     }
43 
44     /**
45      * Returns whether a signature hash of downloaded apk matches the hash given in constructor.
46      */
doesASignatureHashMatch(PackageInfo packageInfo, byte[] signatureChecksum)47     boolean doesASignatureHashMatch(PackageInfo packageInfo, byte[] signatureChecksum) {
48         ProvisionLogger.logd("Checking " + Utils.SHA256_TYPE
49                 + "-hashes of all signatures of downloaded package.");
50         List<byte[]> sigHashes = computeHashesOfAllSignatures(packageInfo.signatures);
51         if (sigHashes == null || sigHashes.isEmpty()) {
52             ProvisionLogger.loge("Downloaded package does not have any signatures.");
53             return false;
54         }
55 
56         for (byte[] sigHash : sigHashes) {
57             if (Arrays.equals(sigHash, signatureChecksum)) {
58                 return true;
59             }
60         }
61 
62         ProvisionLogger.loge("Provided hash does not match any signature hash.");
63         ProvisionLogger.loge("Hash provided by programmer: "
64                 + StoreUtils.byteArrayToString(signatureChecksum));
65         ProvisionLogger.loge("Hashes computed from package signatures: ");
66         for (byte[] sigHash : sigHashes) {
67             if (sigHash != null) {
68                 ProvisionLogger.loge(StoreUtils.byteArrayToString(sigHash));
69             }
70         }
71 
72         return false;
73     }
74 
75     /**
76      * Returns whether the package hash of downloaded file matches the hash given in {@link
77      * PackageDownloadInfo}. By default, {@code SHA-256} is used to verify the file hash.
78      */
doesPackageHashMatch(String downloadLocation, byte[] packageChecksum)79     boolean doesPackageHashMatch(String downloadLocation, byte[] packageChecksum) {
80         byte[] packageSha256Hash = null;
81 
82         ProvisionLogger.logd("Checking file hash of entire apk file.");
83         packageSha256Hash = mUtils.computeHashOfFile(downloadLocation, Utils.SHA256_TYPE);
84         if (Arrays.equals(packageChecksum, packageSha256Hash)) {
85             return true;
86         }
87 
88         ProvisionLogger.loge("Provided hash does not match file hash.");
89         ProvisionLogger.loge("Hash provided by programmer: "
90                 + StoreUtils.byteArrayToString(packageChecksum));
91         if (packageSha256Hash != null) {
92             ProvisionLogger.loge("SHA-256 Hash computed from file: "
93                     + StoreUtils.byteArrayToString(packageSha256Hash));
94         }
95         return false;
96     }
97 
computeHashesOfAllSignatures(Signature[] signatures)98     private List<byte[]> computeHashesOfAllSignatures(Signature[] signatures) {
99         if (signatures == null) {
100             return null;
101         }
102 
103         List<byte[]> hashes = new LinkedList<>();
104         for (Signature signature : signatures) {
105             byte[] hash = mUtils.computeHashOfByteArray(signature.toByteArray());
106             hashes.add(hash);
107         }
108         return hashes;
109     }
110 }
111