1 /* 2 * Copyright 2016, 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 android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; 20 21 import static com.android.managedprovisioning.task.VerifyPackageTask.ERROR_DEVICE_ADMIN_MISSING; 22 import static com.android.managedprovisioning.task.VerifyPackageTask.ERROR_HASH_MISMATCH; 23 24 import static org.mockito.Matchers.any; 25 import static org.mockito.Mockito.mock; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.Mockito.verifyNoMoreInteractions; 28 import static org.mockito.Mockito.when; 29 30 import android.content.ComponentName; 31 import android.content.Context; 32 import android.content.pm.PackageInfo; 33 import android.content.pm.PackageManager; 34 import android.content.pm.Signature; 35 36 import androidx.test.filters.SmallTest; 37 import androidx.test.runner.AndroidJUnit4; 38 39 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker; 40 import com.android.managedprovisioning.common.Utils; 41 import com.android.managedprovisioning.model.PackageDownloadInfo; 42 import com.android.managedprovisioning.model.ProvisioningParams; 43 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.Mock; 48 import org.mockito.MockitoAnnotations; 49 50 import java.io.File; 51 52 /** 53 * Unit tests for {@link VerifyPackageTask}. 54 */ 55 @RunWith(AndroidJUnit4.class) 56 @SmallTest 57 public class VerifyPackageTaskTest { 58 59 private static final String TEST_PACKAGE_NAME = "sample.package.name"; 60 private static final String TEST_ADMIN_NAME = TEST_PACKAGE_NAME + ".DeviceAdmin"; 61 private static final String TEST_PACKAGE_LOCATION = "http://www.some.uri.com"; 62 private static final String TEST_LOCAL_FILENAME = "/local/filename"; 63 private static final File TEST_LOCAL_FILE = new File(TEST_LOCAL_FILENAME); 64 private static final int TEST_USER_ID = 123; 65 private static final byte[] TEST_BAD_HASH = new byte[] { 'b', 'a', 'd' }; 66 private static final byte[] TEST_PACKAGE_CHECKSUM_HASH = new byte[] { '1', '2', '3', '4', '5' }; 67 private static final byte[] TEST_SIGNATURE_HASH = new byte[] {'a', 'b', 'c', 'd'}; 68 private static final byte[] EMPTY_BYTE_ARRAY = new byte[] {}; 69 private static final Signature[] TEST_SIGNATURES = new Signature[] { new Signature("1986") }; 70 71 @Mock private Context mContext; 72 @Mock private DownloadPackageTask mDownloadPackageTask; 73 @Mock private AbstractProvisioningTask.Callback mCallback; 74 @Mock private PackageManager mPackageManager; 75 @Mock private Utils mUtils; 76 @Mock private PackageInfo mPackageInfo; 77 78 private AbstractProvisioningTask mTask; 79 80 @Before setUp()81 public void setUp() throws Exception { 82 // This is necessary for mockito to work 83 MockitoAnnotations.initMocks(this); 84 85 when(mContext.getPackageManager()).thenReturn(mPackageManager); 86 87 mPackageInfo.packageName = TEST_PACKAGE_NAME; 88 mPackageInfo.signatures = TEST_SIGNATURES; 89 90 when(mPackageManager.getPackageArchiveInfo(TEST_LOCAL_FILENAME, 91 PackageManager.GET_SIGNATURES | PackageManager.GET_RECEIVERS)) 92 .thenReturn(mPackageInfo); 93 94 when(mDownloadPackageTask.getPackageLocation()).thenReturn(TEST_LOCAL_FILE); 95 96 when(mUtils.findDeviceAdminInPackageInfo(TEST_PACKAGE_NAME, null, mPackageInfo)) 97 .thenReturn(new ComponentName(TEST_PACKAGE_NAME, TEST_ADMIN_NAME)); 98 } 99 100 @Test testDownloadLocationNull()101 public void testDownloadLocationNull() { 102 // GIVEN that the download package location is null 103 when(mDownloadPackageTask.getPackageLocation()).thenReturn(null); 104 105 // WHEN running the VerifyPackageTask 106 runWithDownloadInfo(TEST_PACKAGE_CHECKSUM_HASH, EMPTY_BYTE_ARRAY); 107 108 // THEN success should be called 109 verify(mCallback).onSuccess(mTask); 110 verifyNoMoreInteractions(mCallback); 111 } 112 113 @Test testMissingDeviceAdminComponent()114 public void testMissingDeviceAdminComponent() { 115 // GIVEN that the device admin component cannot be found 116 when(mUtils.findDeviceAdminInPackageInfo(TEST_PACKAGE_NAME, null, mPackageInfo)) 117 .thenReturn(null); 118 119 // WHEN running the VerifyPackageTask 120 runWithDownloadInfo(TEST_PACKAGE_CHECKSUM_HASH, EMPTY_BYTE_ARRAY); 121 122 // THEN an error should be reported 123 verify(mCallback).onError(mTask, ERROR_DEVICE_ADMIN_MISSING); 124 verifyNoMoreInteractions(mCallback); 125 } 126 127 @Test testPackageChecksumSha256_success()128 public void testPackageChecksumSha256_success() throws Exception { 129 // GIVEN the hash of the downloaded file matches the parameter value 130 when(mUtils.computeHashOfFile(TEST_LOCAL_FILENAME, Utils.SHA256_TYPE)) 131 .thenReturn(TEST_PACKAGE_CHECKSUM_HASH); 132 133 // WHEN running the VerifyPackageTask 134 runWithDownloadInfo(TEST_PACKAGE_CHECKSUM_HASH, EMPTY_BYTE_ARRAY); 135 136 // THEN success should be called 137 verify(mCallback).onSuccess(mTask); 138 verifyNoMoreInteractions(mCallback); 139 } 140 141 @Test testSignatureHash_success()142 public void testSignatureHash_success() throws Exception { 143 // GIVEN the hash of the signature matches the parameter value 144 when(mUtils.computeHashOfByteArray(TEST_SIGNATURES[0].toByteArray())) 145 .thenReturn(TEST_SIGNATURE_HASH); 146 147 // WHEN running the VerifyPackageTask 148 runWithDownloadInfo(EMPTY_BYTE_ARRAY, TEST_SIGNATURE_HASH); 149 150 // THEN success should be called 151 verify(mCallback).onSuccess(mTask); 152 verifyNoMoreInteractions(mCallback); 153 } 154 155 @Test testSignatureHash_failure()156 public void testSignatureHash_failure() throws Exception { 157 // GIVEN the hash of the signature does not match the parameter value 158 when(mUtils.computeHashOfByteArray(TEST_SIGNATURES[0].toByteArray())) 159 .thenReturn(TEST_BAD_HASH); 160 161 // WHEN running the VerifyPackageTask 162 runWithDownloadInfo(EMPTY_BYTE_ARRAY, TEST_SIGNATURE_HASH); 163 164 // THEN hash mismatch error should be called 165 verify(mCallback).onError(mTask, ERROR_HASH_MISMATCH); 166 verifyNoMoreInteractions(mCallback); 167 } 168 169 @Test testSignatureHash_noSignature()170 public void testSignatureHash_noSignature() throws Exception { 171 // GIVEN the package has no signature 172 mPackageInfo.signatures = null; 173 174 // WHEN running the VerifyPackageTask 175 runWithDownloadInfo(EMPTY_BYTE_ARRAY, TEST_SIGNATURE_HASH); 176 177 // THEN hash mismatch error should be called 178 verify(mCallback).onError(mTask, ERROR_HASH_MISMATCH); 179 verifyNoMoreInteractions(mCallback); 180 } 181 182 @Test testSignatureHash_digestFailure()183 public void testSignatureHash_digestFailure() throws Exception { 184 // GIVEN the package has no signature 185 when(mUtils.computeHashOfByteArray(any(byte[].class))).thenReturn(null); 186 187 // WHEN running the VerifyPackageTask 188 runWithDownloadInfo(EMPTY_BYTE_ARRAY, TEST_SIGNATURE_HASH); 189 190 // THEN hash mismatch error should be called 191 verify(mCallback).onError(mTask, ERROR_HASH_MISMATCH); 192 verifyNoMoreInteractions(mCallback); 193 } 194 runWithDownloadInfo(byte[] packageChecksum, byte[] signatureChecksum)195 private void runWithDownloadInfo(byte[] packageChecksum, byte[] signatureChecksum) { 196 PackageDownloadInfo downloadInfo = new PackageDownloadInfo.Builder() 197 .setLocation(TEST_PACKAGE_LOCATION) 198 .setPackageChecksum(packageChecksum) 199 .setSignatureChecksum(signatureChecksum) 200 .build(); 201 ProvisioningParams params = new ProvisioningParams.Builder() 202 .setProvisioningAction(ACTION_PROVISION_MANAGED_DEVICE) 203 .setDeviceAdminPackageName(TEST_PACKAGE_NAME) 204 .setDeviceAdminDownloadInfo(downloadInfo) 205 .build(); 206 mTask = new VerifyPackageTask(mUtils, mDownloadPackageTask, mContext, params, mCallback, 207 mock(ProvisioningAnalyticsTracker.class)); 208 mTask.run(TEST_USER_ID); 209 } 210 } 211