1 /* 2 * Copyright (C) 2018 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 package com.android.server.pm; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertNotNull; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertTrue; 22 import static org.junit.Assert.fail; 23 24 import android.content.Context; 25 import android.content.pm.PackageParser; 26 import android.content.pm.Signature; 27 import android.util.Xml; 28 29 import androidx.test.InstrumentationRegistry; 30 import androidx.test.runner.AndroidJUnit4; 31 32 import com.android.internal.util.HexDump; 33 34 import org.junit.Before; 35 import org.junit.Test; 36 import org.junit.runner.RunWith; 37 import org.xmlpull.v1.XmlPullParser; 38 39 import java.io.File; 40 import java.io.InputStream; 41 import java.nio.charset.StandardCharsets; 42 import java.util.ArrayList; 43 import java.util.HashMap; 44 import java.util.HashSet; 45 import java.util.Map; 46 import java.util.Set; 47 48 @RunWith(AndroidJUnit4.class) 49 public class PackageSignaturesTest { 50 private static final String TEST_RESOURCES_FOLDER = "PackageSignaturesTest"; 51 52 private Context mContext; 53 54 private PackageSetting mPackageSetting; 55 56 // These signatures are the DER encoding of the ec-p256[_X] X509 certificates in the certs/ 57 // directory. The apksigner tool was used to sign a test APK with these certificates and the 58 // corresponding ec-p256{_X].pk8 private key file. For the lineage tests the 59 // ec-p256-lineage-X-signers file was provided as the parameter to the --lineage option when 60 // signing the APK. The APK was then installed on a test device, the packages.xml file was 61 // pulled from the device, and the APK's <sig> tag was used as the basis for these tests. 62 // For more details see the README under the xml/ directory. 63 private static final String FIRST_EXPECTED_SIGNATURE = 64 "3082016c30820111a003020102020900ca0fb64dfb66e772300a06082a8648ce3d04030230123110300e06" 65 + "035504030c0765632d70323536301e170d3136303333313134353830365a170d34333038313731343538" 66 + "30365a30123110300e06035504030c0765632d703235363059301306072a8648ce3d020106082a8648ce" 67 + "3d03010703420004a65f113d22cb4913908307ac31ee2ba0e9138b785fac6536d14ea2ce90d2b4bfe194" 68 + "b50cdc8e169f54a73a991ef0fa76329825be078cc782740703da44b4d7eba350304e301d0603551d0e04" 69 + "160414d4133568b95b30158b322071ea8c43ff5b05ccc8301f0603551d23041830168014d4133568b95b" 70 + "30158b322071ea8c43ff5b05ccc8300c0603551d13040530030101ff300a06082a8648ce3d0403020349" 71 + "003046022100f504a0866caef029f417142c5cb71354c79ffcd1d640618dfca4f19e16db78d6022100f8" 72 + "eea4829799c06cad08c6d3d2d2ec05e0574154e747ea0fdbb8042cb655aadd"; 73 private static final String SECOND_EXPECTED_SIGNATURE = 74 "3082016d30820113a0030201020209008855bd1dd2b2b225300a06082a8648ce3d04030230123110300e06" 75 + "035504030c0765632d70323536301e170d3138303731333137343135315a170d32383037313031373431" 76 + "35315a30143112301006035504030c0965632d703235365f323059301306072a8648ce3d020106082a86" 77 + "48ce3d030107034200041d4cca0472ad97ee3cecef0da93d62b450c6788333b36e7553cde9f74ab5df00" 78 + "bbba6ba950e68461d70bbc271b62151dad2de2bf6203cd2076801c7a9d4422e1a350304e301d0603551d" 79 + "0e041604147991d92b0208fc448bf506d4efc9fff428cb5e5f301f0603551d23041830168014d4133568" 80 + "b95b30158b322071ea8c43ff5b05ccc8300c0603551d13040530030101ff300a06082a8648ce3d040302" 81 + "034800304502202769abb1b49fc2f53479c4ae92a6631dabfd522c9acb0bba2b43ebeb99c63011022100" 82 + "d260fb1d1f176cf9b7fa60098bfd24319f4905a3e5fda100a6fe1a2ab19ff09e"; 83 private static final String THIRD_EXPECTED_SIGNATURE = 84 "3082016e30820115a0030201020209008394f5cad16a89a7300a06082a8648ce3d04030230143112301006" 85 + "035504030c0965632d703235365f32301e170d3138303731343030303532365a170d3238303731313030" 86 + "303532365a30143112301006035504030c0965632d703235365f333059301306072a8648ce3d02010608" 87 + "2a8648ce3d03010703420004f31e62430e9db6fc5928d975fc4e47419bacfcb2e07c89299e6cd7e344dd" 88 + "21adfd308d58cb49a1a2a3fecacceea4862069f30be1643bcc255040d8089dfb3743a350304e301d0603" 89 + "551d0e041604146f8d0828b13efaf577fc86b0e99fa3e54bcbcff0301f0603551d230418301680147991" 90 + "d92b0208fc448bf506d4efc9fff428cb5e5f300c0603551d13040530030101ff300a06082a8648ce3d04" 91 + "030203470030440220256bdaa2784c273e4cc291a595a46779dee9de9044dc9f7ab820309567df9fe902" 92 + "201a4ad8c69891b5a8c47434fe9540ed1f4979b5fad3483f3fa04d5677355a579e"; 93 94 // When running tests using the pastSigs tag / lineage the past signers and their capabilities 95 // should be returned in the SigningDetails. The flags attribute of the cert tag under the 96 // pastSigs tag contains these capabilities; for tests that verify the lineage the capabilities 97 // of the signers should be set to the values in this Map. 98 private static final Map<String, Integer> SIGNATURE_TO_CAPABILITY_MAP; 99 100 static { 101 SIGNATURE_TO_CAPABILITY_MAP = new HashMap<>(); SIGNATURE_TO_CAPABILITY_MAP.put(FIRST_EXPECTED_SIGNATURE, 3)102 SIGNATURE_TO_CAPABILITY_MAP.put(FIRST_EXPECTED_SIGNATURE, 3); SIGNATURE_TO_CAPABILITY_MAP.put(SECOND_EXPECTED_SIGNATURE, 7)103 SIGNATURE_TO_CAPABILITY_MAP.put(SECOND_EXPECTED_SIGNATURE, 7); SIGNATURE_TO_CAPABILITY_MAP.put(THIRD_EXPECTED_SIGNATURE, 23)104 SIGNATURE_TO_CAPABILITY_MAP.put(THIRD_EXPECTED_SIGNATURE, 23); 105 } 106 107 private static final int[] CAPABILITIES = 108 {PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA, 109 PackageParser.SigningDetails.CertCapabilities.SHARED_USER_ID, 110 PackageParser.SigningDetails.CertCapabilities.PERMISSION, 111 PackageParser.SigningDetails.CertCapabilities.ROLLBACK}; 112 113 @Before setUp()114 public void setUp() throws Exception { 115 mContext = InstrumentationRegistry.getContext(); 116 mPackageSetting = createPackageSetting(); 117 } 118 119 @Test testReadXmlWithOneSignerCompletesSuccessfully()120 public void testReadXmlWithOneSignerCompletesSuccessfully() throws Exception { 121 // Verifies the good path of reading a single sigs tag with one signer returns the 122 // expected signature and scheme version. 123 verifyReadXmlReturnsExpectedSignatures("xml/one-signer.xml", 1, FIRST_EXPECTED_SIGNATURE); 124 } 125 126 @Test testReadXmlWithTwoV1V2Signers()127 public void testReadXmlWithTwoV1V2Signers() throws Exception { 128 // Verifies the good path of reading a single sigs tag with multiple signers returns the 129 // expected signatures and scheme version. 130 verifyReadXmlReturnsExpectedSignatures("xml/two-signers-v1v2.xml", 2, 131 FIRST_EXPECTED_SIGNATURE, SECOND_EXPECTED_SIGNATURE); 132 } 133 134 @Test testReadXmlFromTwoSigsTagsWithSameSigner()135 public void testReadXmlFromTwoSigsTagsWithSameSigner() throws Exception { 136 // Verifies the good path of reading two separate packages tags from the same signer. The 137 // first call to readXml should return the list with the expected signature, then the second 138 // call should reference this signature and complete successfully with no new entries in the 139 // List. 140 XmlPullParser parser = getXMLFromResources("xml/one-signer.xml"); 141 ArrayList<Signature> signatures = new ArrayList<>(); 142 mPackageSetting.signatures.readXml(parser, signatures); 143 Set<String> expectedSignatures = createSetOfSignatures(FIRST_EXPECTED_SIGNATURE); 144 verifySignaturesContainExpectedValues(signatures, expectedSignatures); 145 parser = getXMLFromResources("xml/one-signer-previous-cert.xml"); 146 mPackageSetting.signatures.readXml(parser, signatures); 147 expectedSignatures = createSetOfSignatures(FIRST_EXPECTED_SIGNATURE); 148 verifySignaturesContainExpectedValues(signatures, expectedSignatures); 149 } 150 151 @Test testReadXmlWithSigningLineage()152 public void testReadXmlWithSigningLineage() throws Exception { 153 // Verifies the good path of reading a single sigs tag including pastSigs with the 154 // signing lineage returns the expected signatures and lineage for two and three signers 155 // in the lineage. 156 verifyReadXmlReturnsExpectedSignaturesAndLineage("xml/two-signers-in-lineage.xml", 3, 157 FIRST_EXPECTED_SIGNATURE, SECOND_EXPECTED_SIGNATURE); 158 verifyReadXmlReturnsExpectedSignaturesAndLineage("xml/three-signers-in-lineage.xml", 3, 159 FIRST_EXPECTED_SIGNATURE, SECOND_EXPECTED_SIGNATURE, THIRD_EXPECTED_SIGNATURE); 160 } 161 162 @Test testReadXmlWithInvalidPublicKeyInCertKey()163 public void testReadXmlWithInvalidPublicKeyInCertKey() throws Exception { 164 // If the cert tag key attribute does not contain a valid public key then a 165 // CertificateException should be thrown when attempting to build the SigningDetails; in 166 // this case the signing details should be set to UNKNOWN. 167 XmlPullParser parser = getXMLFromResources( 168 "xml/one-signer-invalid-public-key-cert-key.xml"); 169 ArrayList<Signature> signatures = new ArrayList<>(); 170 mPackageSetting.signatures.readXml(parser, signatures); 171 assertEquals( 172 "The signing details was not UNKNOWN after parsing an invalid public key cert key" 173 + " attribute", 174 PackageParser.SigningDetails.UNKNOWN, mPackageSetting.signatures.mSigningDetails); 175 } 176 177 @Test testReadXmlWithMissingSigsCount()178 public void testReadXmlWithMissingSigsCount() throws Exception { 179 // Verifies if the sigs count attribute is missing then the signature cannot be read but the 180 // method does not throw an exception. 181 verifyReadXmlReturnsExpectedSignatures("xml/one-signer-missing-sigs-count.xml", 182 PackageParser.SigningDetails.SignatureSchemeVersion.UNKNOWN); 183 } 184 185 @Test testReadXmlWithMissingSchemeVersion()186 public void testReadXmlWithMissingSchemeVersion() throws Exception { 187 // Verifies if the schemeVersion is an invalid value the signature can still be obtained. 188 verifyReadXmlReturnsExpectedSignatures("xml/one-signer-missing-scheme-version.xml", 189 PackageParser.SigningDetails.SignatureSchemeVersion.UNKNOWN, 190 FIRST_EXPECTED_SIGNATURE); 191 } 192 193 @Test testReadXmlWithSigningLineageWithMissingSchemeVersion()194 public void testReadXmlWithSigningLineageWithMissingSchemeVersion() throws Exception { 195 // Verifies if the scheme version cannot be read the signers in the lineage can still be 196 // obtained. 197 verifyReadXmlReturnsExpectedSignaturesAndLineage( 198 "xml/three-signers-in-lineage-missing-scheme-version.xml", 199 PackageParser.SigningDetails.SignatureSchemeVersion.UNKNOWN, 200 FIRST_EXPECTED_SIGNATURE, SECOND_EXPECTED_SIGNATURE, THIRD_EXPECTED_SIGNATURE); 201 } 202 203 @Test testReadXmlWithInvalidCertIndex()204 public void testReadXmlWithInvalidCertIndex() throws Exception { 205 // If the cert index attribute is invalid the signature will not be read but the call 206 // should exit gracefully. 207 verifyReadXmlReturnsExpectedSignatures("xml/one-signer-invalid-cert-index.xml", 3); 208 } 209 210 @Test testReadXmlWithMissingCertIndex()211 public void testReadXmlWithMissingCertIndex() throws Exception { 212 // If the cert index attribute is missing the signature will not be read but the call should 213 // exit gracefully. 214 verifyReadXmlReturnsExpectedSignatures("xml/one-signer-missing-cert-index.xml", 3); 215 } 216 217 @Test testReadXmlWithInvalidCertKey()218 public void testReadXmlWithInvalidCertKey() throws Exception { 219 // If the cert key value is invalid the signature cannot be read but the call should exit 220 // gracefully. 221 verifyReadXmlReturnsExpectedSignatures("xml/one-signer-invalid-cert-key.xml", 3); 222 } 223 224 @Test testReadXmlWithMissingCertKey()225 public void testReadXmlWithMissingCertKey() throws Exception { 226 // If the cert key is missing the signature cannot be read but the call should exit 227 // gracefully. 228 verifyReadXmlReturnsExpectedSignatures("xml/one-signer-missing-cert-key.xml", 3); 229 } 230 231 @Test testReadXmlWithMissingCertTag()232 public void testReadXmlWithMissingCertTag() throws Exception { 233 // If the cert tag is missing there is no signature to read but the call should exit 234 // gracefully. 235 verifyReadXmlReturnsExpectedSignatures("xml/one-signer-missing-cert-tag.xml", 3); 236 } 237 238 @Test testReadXmlWithTooFewCertTags()239 public void testReadXmlWithTooFewCertTags() throws Exception { 240 // If the number of cert tags is less than that specified in the count attribute then the 241 // signatures that could be read are copied to a smaller array to be used when building 242 // the SigningDetails object. This test verifies if there are too few cert tags the 243 // available signatures can still be obtained. 244 verifyReadXmlReturnsExpectedSignatures("xml/two-signers-v1v2-missing-cert-tag.xml", 1, 245 FIRST_EXPECTED_SIGNATURE); 246 } 247 248 @Test testReadXmlWithExtraCertTag()249 public void testReadXmlWithExtraCertTag() throws Exception { 250 // Verifies if there are more cert tags than specified by the count attribute the extra cert 251 // tag is ignored and the expected signature from the first cert tag is returned. 252 verifyReadXmlReturnsExpectedSignatures("xml/one-signer-extra-cert-tag.xml", 3, 253 FIRST_EXPECTED_SIGNATURE); 254 } 255 256 @Test testReadXmlWithInvalidTag()257 public void testReadXmlWithInvalidTag() throws Exception { 258 // Verifies an invalid tag under sigs is ignored and the expected signature is returned. 259 verifyReadXmlReturnsExpectedSignatures("xml/one-signer-invalid-tag.xml", 3, 260 FIRST_EXPECTED_SIGNATURE); 261 } 262 263 @Test testReadXmlWithInvalidPastSigsCount()264 public void testReadXmlWithInvalidPastSigsCount() throws Exception { 265 // Verifies if the pastSigs tag contains an invalid count attribute the current signature 266 // is still returned; in this case the third expected signature is the most recent signer. 267 verifyReadXmlReturnsExpectedSignatures( 268 "xml/three-signers-in-lineage-invalid-pastSigs-count.xml", 3, 269 THIRD_EXPECTED_SIGNATURE); 270 } 271 272 @Test testReadXmlWithMissingPastSigsCount()273 public void testReadXmlWithMissingPastSigsCount() throws Exception { 274 // Verifies if the pastSigs tag is missing the count attribute the current signature is 275 // still returned; in this case the third expected signature is the most recent signer. 276 verifyReadXmlReturnsExpectedSignaturesAndLineage( 277 "xml/three-signers-in-lineage-missing-pastSigs-count.xml", 3, 278 THIRD_EXPECTED_SIGNATURE); 279 } 280 281 @Test testReadXmlWithInvalidCertFlags()282 public void testReadXmlWithInvalidCertFlags() throws Exception { 283 // Verifies if the cert tag contains an invalid flags attribute the expected signatures 284 // are still returned, although since the flags could not be read these signatures will not 285 // include the capabilities of the previous signers in the lineage. 286 verifyReadXmlReturnsExpectedSignatures("xml/two-signers-in-lineage-invalid-certs-flags.xml", 287 3, FIRST_EXPECTED_SIGNATURE, SECOND_EXPECTED_SIGNATURE); 288 } 289 290 @Test testReadXmlWithMissingCertFlags()291 public void testReadXmlWithMissingCertFlags() throws Exception { 292 // Verifies if the cert tag does not contain a flags attribute the expected signatures are 293 // still returned, although since there are no flags to read these signatures will not 294 // include the capabilities of the previous signers in the lineage. 295 verifyReadXmlReturnsExpectedSignatures("xml/two-signers-in-lineage-missing-certs-flags.xml", 296 3, FIRST_EXPECTED_SIGNATURE, SECOND_EXPECTED_SIGNATURE); 297 } 298 299 @Test testReadXmlWithMultiplePastSigsTags()300 public void testReadXmlWithMultiplePastSigsTags() throws Exception { 301 // Verifies if multiple pastSigs tags are found under the sigs tag the additional pastSigs 302 // tag is ignored and the expected signatures are returned along with the previous signer in 303 // the lineage. 304 verifyReadXmlReturnsExpectedSignaturesAndLineage( 305 "xml/two-signers-in-lineage-multiple-pastSigs-tags.xml", 3, 306 FIRST_EXPECTED_SIGNATURE, SECOND_EXPECTED_SIGNATURE); 307 } 308 309 @Test testReadXmlWithInvalidPastSigsCertIndex()310 public void testReadXmlWithInvalidPastSigsCertIndex() throws Exception { 311 // If the pastSigs cert tag contains an invalid index attribute that signature cannot be 312 // read but the current signature should still be returned. 313 verifyReadXmlReturnsExpectedSignaturesAndLineage( 314 "xml/two-signers-in-lineage-invalid-pastSigs-cert-index.xml", 3, 315 SECOND_EXPECTED_SIGNATURE); 316 } 317 318 @Test testReadXmlWithMissingPastSigsCertIndex()319 public void testReadXmlWithMissingPastSigsCertIndex() throws Exception { 320 // If the pastSigs cert tag does not contain an index attribute that signature cannot be 321 // read but the current signature should still be returned. 322 verifyReadXmlReturnsExpectedSignaturesAndLineage( 323 "xml/two-signers-in-lineage-missing-pastSigs-cert-index.xml", 3, 324 SECOND_EXPECTED_SIGNATURE); 325 } 326 327 @Test testReadXmlWithUndefinedPastSigsIndex()328 public void testReadXmlWithUndefinedPastSigsIndex() throws Exception { 329 // If a cert tag does not contain a key attribute it is assumed that the index attribute 330 // refers to a previously seen signature. If a signature does not yet exist at this index 331 // then the current signature cannot be read but any other signatures should still be 332 // returned. 333 verifyReadXmlReturnsExpectedSignatures( 334 "xml/two-signers-in-lineage-undefined-pastSigs-index.xml", 3, 335 FIRST_EXPECTED_SIGNATURE, null); 336 } 337 338 @Test testReadXmlWithTooFewPastSigsCertTags()339 public void testReadXmlWithTooFewPastSigsCertTags() throws Exception { 340 // If the number of cert tags is less than that specified in the count attribute of the 341 // pastSigs tag then the signatures that could be read are copied to a smaller array to be 342 // used when building the SigningDetails object. This test verifies if there are too few 343 // cert tags the available signatures and lineage can still be obtained. 344 verifyReadXmlReturnsExpectedSignaturesAndLineage( 345 "xml/three-signers-in-lineage-missing-pastSigs-cert-tag.xml", 3, 346 FIRST_EXPECTED_SIGNATURE, THIRD_EXPECTED_SIGNATURE); 347 } 348 349 @Test testReadXmlWithPastSignerWithNoCapabilities()350 public void testReadXmlWithPastSignerWithNoCapabilities() throws Exception { 351 // When rotating the signing key a developer is able to specify the capabilities granted to 352 // the apps signed with the previous key. This test verifies a previous signing certificate 353 // with the flags set to 0 does not have any capabilities. 354 XmlPullParser parser = getXMLFromResources("xml/two-signers-in-lineage-no-caps.xml"); 355 ArrayList<Signature> signatures = new ArrayList<>(); 356 mPackageSetting.signatures.readXml(parser, signatures); 357 // obtain the Signature in the list matching the previous signing certificate 358 Signature previousSignature = null; 359 for (Signature signature : signatures) { 360 String signatureValue = HexDump.toHexString(signature.toByteArray(), false); 361 if (signatureValue.equals(FIRST_EXPECTED_SIGNATURE)) { 362 previousSignature = signature; 363 break; 364 } 365 } 366 assertNotNull("Unable to find the expected previous signer", previousSignature); 367 for (int capability : CAPABILITIES) { 368 assertFalse("The previous signer should not have the " + capability + " capability", 369 mPackageSetting.signatures.mSigningDetails.hasCertificate(previousSignature, 370 capability)); 371 } 372 } 373 374 /** 375 * Verifies reading the sigs tag of the provided XML file returns the specified signature scheme 376 * version and the provided signatures. 377 */ verifyReadXmlReturnsExpectedSignatures(String xmlFile, int expectedSchemeVersion, String... expectedSignatureValues)378 private void verifyReadXmlReturnsExpectedSignatures(String xmlFile, int expectedSchemeVersion, 379 String... expectedSignatureValues) throws Exception { 380 XmlPullParser parser = getXMLFromResources(xmlFile); 381 ArrayList<Signature> signatures = new ArrayList<>(); 382 mPackageSetting.signatures.readXml(parser, signatures); 383 Set<String> expectedSignatures = createSetOfSignatures(expectedSignatureValues); 384 verifySignaturesContainExpectedValues(signatures, expectedSignatures); 385 assertEquals("The returned signature scheme is not the expected value", 386 expectedSchemeVersion, 387 mPackageSetting.signatures.mSigningDetails.signatureSchemeVersion); 388 } 389 390 /** 391 * Verifies reading the sigs tag of the provided XML file returns the specified signature scheme 392 * version, the provided signatures, and that the previous signers have the expected 393 * capabilities. 394 */ verifyReadXmlReturnsExpectedSignaturesAndLineage(String xmlFile, int schemeVersion, String... expectedSignatureValues)395 private void verifyReadXmlReturnsExpectedSignaturesAndLineage(String xmlFile, 396 int schemeVersion, String... expectedSignatureValues) throws Exception { 397 XmlPullParser parser = getXMLFromResources(xmlFile); 398 ArrayList<Signature> signatures = new ArrayList<>(); 399 mPackageSetting.signatures.readXml(parser, signatures); 400 Set<String> expectedSignatures = createSetOfSignatures(expectedSignatureValues); 401 verifySignaturesContainExpectedValues(signatures, expectedSignatures); 402 assertEquals("The returned signature scheme is not the expected value", schemeVersion, 403 mPackageSetting.signatures.mSigningDetails.signatureSchemeVersion); 404 for (Signature signature : signatures) { 405 String signatureValue = HexDump.toHexString(signature.toByteArray(), false); 406 int expectedCapabilities = SIGNATURE_TO_CAPABILITY_MAP.get(signatureValue); 407 assertTrue("The signature " + signatureValue 408 + " was not found with the expected capabilities of " + 409 expectedCapabilities 410 + " in the signing details", 411 mPackageSetting.signatures.mSigningDetails.hasCertificate(signature, 412 expectedCapabilities)); 413 } 414 } 415 416 /** 417 * Verifies the provided {@code List} contains Signatures that match the provided hex encoded 418 * signature values. 419 * 420 * The provided {@code Set} will be modified by this method as elements will be removed to 421 * ensure duplicate expected Signatures are not in the {@code List}. 422 */ verifySignaturesContainExpectedValues(ArrayList<Signature> signatures, Set<String> expectedSignatures)423 private static void verifySignaturesContainExpectedValues(ArrayList<Signature> signatures, 424 Set<String> expectedSignatures) { 425 assertEquals("The number of signatures does not equal the expected number of signatures", 426 expectedSignatures.size(), signatures.size()); 427 for (Signature signature : signatures) { 428 String signatureString = null; 429 if (signature != null) { 430 signatureString = HexDump.toHexString(signature.toByteArray(), false); 431 } 432 // If the signature is in the expected set then remove it so that duplicate matching 433 // signatures are reported. 434 if (expectedSignatures.contains(signatureString)) { 435 expectedSignatures.remove(signatureString); 436 } else { 437 fail("The following unexpected signature was returned: " + signatureString); 438 } 439 } 440 } 441 createSetOfSignatures(String... signatures)442 private static Set<String> createSetOfSignatures(String... signatures) { 443 Set<String> result = new HashSet<String>(); 444 for (String signature : signatures) { 445 result.add(signature); 446 } 447 return result; 448 } 449 getXMLFromResources(String xmlFile)450 private XmlPullParser getXMLFromResources(String xmlFile) throws Exception { 451 InputStream xmlStream = mContext.getResources().getAssets().open( 452 TEST_RESOURCES_FOLDER + "/" + xmlFile); 453 XmlPullParser result = Xml.newPullParser(); 454 result.setInput(xmlStream, StandardCharsets.UTF_8.name()); 455 int type; 456 // advance the parser to the first tag 457 while ((type = result.next()) != XmlPullParser.START_TAG 458 && type != XmlPullParser.END_DOCUMENT) { 459 ; 460 } 461 return result; 462 } 463 createPackageSetting()464 private static PackageSetting createPackageSetting() { 465 // Generic PackageSetting object with values from a test app installed on a device to be 466 // used to test the methods under the PackageSignatures signatures data member. 467 File appPath = new File("/data/app/app"); 468 PackageSetting result = new PackageSetting("test.app", null, appPath, appPath, 469 "/data/app/app", null, null, null, 470 1, 940097092, 0, null, 471 null, 0 /*userId*/, null, null); 472 return result; 473 } 474 } 475