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 17 package android.appsecurity.cts.v3rotationtests; 18 19 import static org.junit.Assert.assertArrayEquals; 20 21 import android.content.pm.PackageInfo; 22 import android.content.pm.PackageManager; 23 import android.content.pm.Signature; 24 import android.test.AndroidTestCase; 25 26 import java.security.MessageDigest; 27 import java.security.NoSuchAlgorithmException; 28 import java.util.Arrays; 29 import java.util.HashSet; 30 import java.util.Set; 31 32 /** 33 * On-device tests for APK Signature Scheme v3 based signing certificate rotation 34 */ 35 public class V3RotationTest extends AndroidTestCase { 36 37 private static final String PKG = "android.appsecurity.cts.tinyapp"; 38 private static final String COMPANION_PKG = "android.appsecurity.cts.tinyapp_companion"; 39 private static final String PERMISSION_NAME = "android.appsecurity.cts.tinyapp.perm"; 40 41 private static final String FIRST_CERT_HEX = 42 "308203773082025fa0030201020204357f7a97300d06092a864886f70d01010b0500306c310b3009060355" 43 + "040613025553310b3009060355040813024341311630140603550407130d4d6f756e7461696e20566965" 44 + "773110300e060355040a1307416e64726f69643110300e060355040b1307556e6b6e6f776e3114301206" 45 + "03550403130b477265656e2044726f6964301e170d3138303133313138303331345a170d343530363138" 46 + "3138303331345a306c310b3009060355040613025553310b300906035504081302434131163014060355" 47 + "0407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355" 48 + "040b1307556e6b6e6f776e311430120603550403130b477265656e2044726f696430820122300d06092a" 49 + "864886f70d01010105000382010f003082010a0282010100bce0517978db6e1eb0255b4704c10fca31b8" 50 + "d8b7465d1512a36712f425009143d418743cbde9c9f7df219907fff376e44298462fb14f5dd7d0edd46e" 51 + "d764f93e82b277146f100616c4d93e97279aefdcf449a5ff000eb72445816039c7afdcd9340f39fc5f0b" 52 + "b4d0e6c4d67a0ec876bf28007cf709667250142385248af89c5fa87b8ef9cc1270577b1721c235bdde97" 53 + "87c04536706947193d38d244c8c6590e54c90b3843506b3e19c5f2c22c38a1a2893c749ad4ddce67b86f" 54 + "f5dcd7dd0d63265fa50036f4bf31f28f2b4c067fb58c95e09ab6c1686c257c3730616659b352b966ed66" 55 + "d93952c60563c9d863aa37c097f646d55c825b450f511eca39198cd70203010001a321301f301d060355" 56 + "1d0e04160414831074e3173e51fbd2ac8ed8c6681f61eca81318300d06092a864886f70d01010b050003" 57 + "820101001fa412618659f40395e38698cd8b7ca9425f63e231e39a6c8e2909af951bbdc5e6307813e25e" 58 + "31502578a56b6e6f08442a400de19449f1c7f87357e55191fd7f30b8735e1298d4c668b9cde563e143d4" 59 + "72bf8005443d8ee386f955136ad0aa16dda7f5b977dc0dee858f954aff2ae4d7473259fb1b1acc1d6161" 60 + "49b12659371ae0298222974be10817156279c9dd8f6cae5265bf15b63fa9f084e789d06b3a9b86d82749" 61 + "c95793acded24b321a31cc20fd12774c7b207325df50c2efcb78a5cf9749f62aafd86d303254880a4476" 62 + "a67801452e82d1e6c91aeb97ca837a91bcefd8324fca491de4ef648d80c6d74f4b66533684040ddad550" 63 + "0ff140edcdacf0a4"; 64 65 private static final String SECOND_CERT_HEX = 66 "3082037b30820263a00302010202044c4a644a300d06092a864886f70d01010b0500306e310b3009060355" 67 + "040613025553310b3009060355040813024341311630140603550407130d4d6f756e7461696e20566965" 68 + "773110300e060355040a1307416e64726f69643110300e060355040b1307556e6b6e6f776e3116301406" 69 + "03550403130d477265656e65722044726f6964301e170d3138303133313138303533385a170d34353036" 70 + "31383138303533385a306e310b3009060355040613025553310b30090603550408130243413116301406" 71 + "03550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e06" 72 + "0355040b1307556e6b6e6f776e311630140603550403130d477265656e65722044726f69643082012230" 73 + "0d06092a864886f70d01010105000382010f003082010a0282010100a4f3741edf04e32e7047aaadc2ce" 74 + "de0164a2847149aa7fad054dab59e70c1078dd2d5946cec64809f79551395478b08f3e0286d452fa39b9" 75 + "e6804e965a44210a61bd5cfe3c8ac0ec86017c0e91260248daa1fd7a11b1b1b519216a40d02db49e754a" 76 + "6380357c45ef1531996e4c37c13e2f507f3a9296eb52235248d0172efe4ed7bac537fe2435f03d66c5e3" 77 + "e5cbf60d77f3088bc22718ded09009d6414106d1301d1a5abf71aa5dc6469bb73b29b2cc9c09b9c42e8f" 78 + "8e81e7fc9b24ad1cb0c3e2e2832d0570bdeb87a3ff8f49aae05b03164fb3c225745b70134c6b7aaf081f" 79 + "514058776bd28a0c0a152bf45b3eddc7f2c4aaed4eace0cab67ef4650213303f0203010001a321301f30" 80 + "1d0603551d0e04160414f0c3dacf02d9583200d4d386a40341aee82dd859300d06092a864886f70d0101" 81 + "0b050003820101003a63a93be986740158574239310e987cdcdc86f735867789c2b56f8ffa7ce901a9f2" 82 + "2b0c374d345aa996a37c7474824dbf72186d1eedaa6aae0574fd1996f501def32e62703ee4010a7058df" 83 + "f0d608df1176bdbe93ebd3910172fc146307d0961a57d95806eeabc1e54b81273d9449f0f68511288377" 84 + "c82f87a032d1379260365ef83c93f1bf4c0af959b426794c558c0357fe61271ed0fb054e916e0bab8600" 85 + "3bcc16ce53f7d2c8d05b83072115b0fb2c671c2266813f1a407ca911c47f27665debfa63bc4e4071730a" 86 + "a477acbe6eecc8d575511b2b77a3551f040ccf21792f74cd95c84e3ff87ad03851db81d164c836830e31" 87 + "8208a52dcdc77e376f73b96d"; 88 89 // These are the hex encodings of the der form of the pkgsigverify/ec-p256[_2] certs used to 90 // sign APKs that are part of this test. 91 private static final String EC_P256_FIRST_CERT_HEX = 92 "3082016c30820111a003020102020900ca0fb64dfb66e772300a06082a86" 93 + "48ce3d04030230123110300e06035504030c0765632d70323536301e170d" 94 + "3136303333313134353830365a170d3433303831373134353830365a3012" 95 + "3110300e06035504030c0765632d703235363059301306072a8648ce3d02" 96 + "0106082a8648ce3d03010703420004a65f113d22cb4913908307ac31ee2b" 97 + "a0e9138b785fac6536d14ea2ce90d2b4bfe194b50cdc8e169f54a73a991e" 98 + "f0fa76329825be078cc782740703da44b4d7eba350304e301d0603551d0e" 99 + "04160414d4133568b95b30158b322071ea8c43ff5b05ccc8301f0603551d" 100 + "23041830168014d4133568b95b30158b322071ea8c43ff5b05ccc8300c06" 101 + "03551d13040530030101ff300a06082a8648ce3d04030203490030460221" 102 + "00f504a0866caef029f417142c5cb71354c79ffcd1d640618dfca4f19e16" 103 + "db78d6022100f8eea4829799c06cad08c6d3d2d2ec05e0574154e747ea0f" 104 + "dbb8042cb655aadd"; 105 106 private static final String EC_P256_SECOND_CERT_HEX = 107 "3082016d30820113a0030201020209008855bd1dd2b2b225300a06082a86" 108 + "48ce3d04030230123110300e06035504030c0765632d70323536301e170d" 109 + "3138303731333137343135315a170d3238303731303137343135315a3014" 110 + "3112301006035504030c0965632d703235365f323059301306072a8648ce" 111 + "3d020106082a8648ce3d030107034200041d4cca0472ad97ee3cecef0da9" 112 + "3d62b450c6788333b36e7553cde9f74ab5df00bbba6ba950e68461d70bbc" 113 + "271b62151dad2de2bf6203cd2076801c7a9d4422e1a350304e301d060355" 114 + "1d0e041604147991d92b0208fc448bf506d4efc9fff428cb5e5f301f0603" 115 + "551d23041830168014d4133568b95b30158b322071ea8c43ff5b05ccc830" 116 + "0c0603551d13040530030101ff300a06082a8648ce3d0403020348003045" 117 + "02202769abb1b49fc2f53479c4ae92a6631dabfd522c9acb0bba2b43ebeb" 118 + "99c63011022100d260fb1d1f176cf9b7fa60098bfd24319f4905a3e5fda1" 119 + "00a6fe1a2ab19ff09e"; 120 121 private static final String EC_P256_THIRD_CERT_HEX = 122 "3082016e30820115a0030201020209008394f5cad16a89a7300a06082a86" 123 + "48ce3d04030230143112301006035504030c0965632d703235365f32301e" 124 + "170d3138303731343030303532365a170d3238303731313030303532365a" 125 + "30143112301006035504030c0965632d703235365f333059301306072a86" 126 + "48ce3d020106082a8648ce3d03010703420004f31e62430e9db6fc5928d9" 127 + "75fc4e47419bacfcb2e07c89299e6cd7e344dd21adfd308d58cb49a1a2a3" 128 + "fecacceea4862069f30be1643bcc255040d8089dfb3743a350304e301d06" 129 + "03551d0e041604146f8d0828b13efaf577fc86b0e99fa3e54bcbcff0301f" 130 + "0603551d230418301680147991d92b0208fc448bf506d4efc9fff428cb5e" 131 + "5f300c0603551d13040530030101ff300a06082a8648ce3d040302034700" 132 + "30440220256bdaa2784c273e4cc291a595a46779dee9de9044dc9f7ab820" 133 + "309567df9fe902201a4ad8c69891b5a8c47434fe9540ed1f4979b5fad348" 134 + "3f3fa04d5677355a579e"; 135 136 private static final String EC_P256_FOURTH_CERT_HEX = 137 "3082017b30820120a00302010202146c8cb8a818433c1e6431fb16fb3ae0" 138 + "fb5ad60aa7300a06082a8648ce3d04030230143112301006035504030c09" 139 + "65632d703235365f33301e170d3230303531333139313532385a170d3330" 140 + "303531313139313532385a30143112301006035504030c0965632d703235" 141 + "365f343059301306072a8648ce3d020106082a8648ce3d03010703420004" 142 + "db4a60031e79ad49cb759007d6855d4469b91c8bab065434f2fba971ade7" 143 + "e4d19599a0f67b5e708cfda7543e5630c3769d37e093640d7c768a15144c" 144 + "d0e5dcf4a350304e301d0603551d0e041604146e78970332554336b6ee89" 145 + "24eaa70230e393f678301f0603551d230418301680146f8d0828b13efaf5" 146 + "77fc86b0e99fa3e54bcbcff0300c0603551d13040530030101ff300a0608" 147 + "2a8648ce3d0403020349003046022100ce786e79ec7547446082e9caf910" 148 + "614ff80758f9819fb0f148695067abe0fcd4022100a4881e332ddec2116a" 149 + "d2b59cf891d0f331ff7e27e77b7c6206c7988d9b539330"; 150 151 private static final String EC_P256_FIFTH_CERT_HEX = 152 "3082017930820120a003020102021450e1ee31d9f9259eadd3514a988dfa" 153 + "4bf0e7153a300a06082a8648ce3d04030230143112301006035504030c09" 154 + "65632d703235365f34301e170d3232303331353031303530385a170d3332" 155 + "303331323031303530385a30143112301006035504030c0965632d703235" 156 + "365f353059301306072a8648ce3d020106082a8648ce3d03010703420004" 157 + "75703c54a432df580e86848817b491ee028324257dc31e891fc4af93d9bd" 158 + "4bf026b39c7a145213753c344c2a12056ce7ccc21b40be8f9fad28639dca" 159 + "dbe63b4ea350304e301d0603551d0e04160414e8cc32db6a21f86c75f3c1" 160 + "96c0b199885498b73b301f0603551d230418301680146e78970332554336" 161 + "b6ee8924eaa70230e393f678300c0603551d13040530030101ff300a0608" 162 + "2a8648ce3d040302034700304402202ded97f7ddcd3229ad26783436186f" 163 + "1e74247a4422baf99f1eeb715dfe7e895502207814248b1b7742f3009602" 164 + "bdc96f66529884fc605a070ff25c84648c8fccb44b"; 165 testHasPerm()166 public void testHasPerm() throws Exception { 167 PackageManager pm = getContext().getPackageManager(); 168 assertTrue(PERMISSION_NAME + " not granted to " + COMPANION_PKG, 169 pm.checkPermission(PERMISSION_NAME, COMPANION_PKG) 170 == PackageManager.PERMISSION_GRANTED); 171 } 172 testHasNoPerm()173 public void testHasNoPerm() throws Exception { 174 PackageManager pm = getContext().getPackageManager(); 175 assertFalse(PERMISSION_NAME + " granted to " + COMPANION_PKG, 176 pm.checkPermission(PERMISSION_NAME, COMPANION_PKG) 177 == PackageManager.PERMISSION_GRANTED); 178 } 179 testGetSignaturesShowsOld()180 public void testGetSignaturesShowsOld() throws Exception { 181 // to prevent breakage due to signing certificate rotation, we report the oldest signing 182 // certificate in the now-deprecated PackageInfo signatures field. Make sure that when 183 // rotating, it still displays the older cert. 184 PackageManager pm = getContext().getPackageManager(); 185 PackageInfo pi = pm.getPackageInfo(PKG, PackageManager.GET_SIGNATURES); 186 assertNotNull("Failed to get signatures in PackageInfo of " + PKG, pi.signatures); 187 assertEquals("PackageInfo for " + PKG + "contains multiple entries", 188 1, pi.signatures.length); 189 assertEquals("signature mismatch for " + PKG + ", expected old signing certificate", 190 pi.signatures[0].toCharsString(), FIRST_CERT_HEX); 191 } 192 testGetSigningCertificatesShowsAll()193 public void testGetSigningCertificatesShowsAll() throws Exception { 194 // make sure our shiny new GET_SIGNATURES replacement does its job. It should return all of 195 // the certificates in an app's provided history, including its current one 196 PackageManager pm = getContext().getPackageManager(); 197 PackageInfo pi = pm.getPackageInfo(PKG, PackageManager.GET_SIGNING_CERTIFICATES); 198 assertNotNull("Failed to get signatures in PackageInfo of " + PKG, 199 pi.signingInfo); 200 assertFalse("Multiple signing certificates found in signing certificate history for " + PKG, 201 pi.signingInfo.hasMultipleSigners()); 202 Signature[] signingHistory = pi.signingInfo.getSigningCertificateHistory(); 203 int numSigningSets = signingHistory.length; 204 assertEquals("PackageInfo for " + PKG + "contains the wrong number of signing certificat " 205 + " rotations. Expected 2 (corresponding to one rotation). Found: " 206 + numSigningSets, 2, numSigningSets); 207 // check to see if we match the certs for which we're looking 208 boolean matchedFirst = false; 209 boolean matchedSecond = false; 210 for (int i = 0; i < numSigningSets; i++) { 211 String reportedCert = signingHistory[i].toCharsString(); 212 if (FIRST_CERT_HEX.equals(reportedCert)) { 213 matchedFirst = true; 214 } else if (SECOND_CERT_HEX.equals(reportedCert)) { 215 matchedSecond = true; 216 } 217 } 218 assertTrue("Old signing certificate not found for " + PKG + " expected " 219 + FIRST_CERT_HEX, matchedFirst); 220 assertTrue("Current signing certificate not found for " + PKG + " expected " 221 + SECOND_CERT_HEX, matchedSecond); 222 } 223 testGetApkContentsSignersShowsCurrent()224 public void testGetApkContentsSignersShowsCurrent() throws Exception { 225 // The SigningInfo instance returned from GET_SIGNING_CERTIFICATES provides an option to 226 // obtain only the current signer through getApkContentsSigners. 227 PackageManager pm = getContext().getPackageManager(); 228 PackageInfo pi = pm.getPackageInfo(PKG, PackageManager.GET_SIGNING_CERTIFICATES); 229 assertNotNull("Failed to get signatures in Package Info of " + PKG, pi.signingInfo); 230 assertFalse("Multiple signing certificates found in signing certificate history for " + PKG, 231 pi.signingInfo.hasMultipleSigners()); 232 assertExpectedSignatures(pi.signingInfo.getApkContentsSigners(), EC_P256_SECOND_CERT_HEX); 233 } 234 testGetApkContentsSignersShowsMultipleSigners()235 public void testGetApkContentsSignersShowsMultipleSigners() throws Exception { 236 // Similar to the test above when GET_SIGNING_CERTIFICATES is used to obtain the signers 237 // getApkContentSigners should return all of the current signatures when there are multiple 238 // V1 / V2 signers. 239 PackageManager pm = getContext().getPackageManager(); 240 PackageInfo pi = pm.getPackageInfo(PKG, PackageManager.GET_SIGNING_CERTIFICATES); 241 assertNotNull("Failed to get signatures in PackageInfo of " + PKG, 242 pi.signingInfo); 243 assertTrue("Multiple signing certificates should have been reported for " + PKG, 244 pi.signingInfo.hasMultipleSigners()); 245 assertExpectedSignatures(pi.signingInfo.getApkContentsSigners(), EC_P256_FIRST_CERT_HEX, 246 EC_P256_SECOND_CERT_HEX); 247 } 248 testGetSigningCertificateHistoryReturnsSignersInOrder()249 public void testGetSigningCertificateHistoryReturnsSignersInOrder() throws Exception { 250 // The test package used for this should be signed with five keys in the signing lineage, 251 // and the signatures returned from SigningInfo#getSigningCertificateHistory should be 252 // returned in their rotated order. 253 final String[] expectedSignatures = new String[]{ 254 EC_P256_FIRST_CERT_HEX, 255 EC_P256_SECOND_CERT_HEX, 256 EC_P256_THIRD_CERT_HEX, 257 EC_P256_FOURTH_CERT_HEX, 258 EC_P256_FIFTH_CERT_HEX, 259 }; 260 261 PackageManager pm = getContext().getPackageManager(); 262 PackageInfo pi = pm.getPackageInfo(PKG, PackageManager.GET_SIGNING_CERTIFICATES); 263 assertNotNull("Failed to get signatures in PackageInfo of " + PKG, 264 pi.signingInfo); 265 String[] actualSignatures = Arrays.stream(pi.signingInfo.getSigningCertificateHistory()) 266 .map(Signature::toCharsString) 267 .toArray(String[]::new); 268 assertArrayEquals(expectedSignatures, actualSignatures); 269 } 270 testHasSigningCertificate()271 public void testHasSigningCertificate() throws Exception { 272 // make sure that hasSigningCertificate() reports that both certificates in the signing 273 // history are present 274 PackageManager pm = getContext().getPackageManager(); 275 byte[] firstCertBytes = fromHexToByteArray(FIRST_CERT_HEX); 276 assertTrue("Old signing certificate not found for " + PKG, 277 pm.hasSigningCertificate(PKG, firstCertBytes, PackageManager.CERT_INPUT_RAW_X509)); 278 byte[] secondCertBytes = fromHexToByteArray(SECOND_CERT_HEX); 279 assertTrue("Current signing certificate not found for " + PKG, 280 pm.hasSigningCertificate(PKG, secondCertBytes, PackageManager.CERT_INPUT_RAW_X509)); 281 } 282 testHasSigningCertificateSha256()283 public void testHasSigningCertificateSha256() throws Exception { 284 // make sure that hasSigningCertificate() reports that both certificates in the signing 285 // history are present 286 PackageManager pm = getContext().getPackageManager(); 287 byte[] firstCertBytes = computeSha256DigestBytes(fromHexToByteArray(FIRST_CERT_HEX)); 288 289 assertTrue("Old signing certificate not found for " + PKG, 290 pm.hasSigningCertificate(PKG, firstCertBytes, PackageManager.CERT_INPUT_SHA256)); 291 byte[] secondCertBytes = computeSha256DigestBytes(fromHexToByteArray(SECOND_CERT_HEX)); 292 assertTrue("Current signing certificate not found for " + PKG, 293 pm.hasSigningCertificate(PKG, secondCertBytes, PackageManager.CERT_INPUT_SHA256)); 294 } 295 testHasSigningCertificateByUid()296 public void testHasSigningCertificateByUid() throws Exception { 297 // make sure that hasSigningCertificate() reports that both certificates in the signing 298 // history are present 299 PackageManager pm = getContext().getPackageManager(); 300 int uid = pm.getPackageUid(PKG, 0); 301 byte[] firstCertBytes = fromHexToByteArray(FIRST_CERT_HEX); 302 assertTrue("Old signing certificate not found for " + PKG, 303 pm.hasSigningCertificate(uid, firstCertBytes, PackageManager.CERT_INPUT_RAW_X509)); 304 byte[] secondCertBytes = fromHexToByteArray(SECOND_CERT_HEX); 305 assertTrue("Current signing certificate not found for " + PKG, 306 pm.hasSigningCertificate(uid, secondCertBytes, PackageManager.CERT_INPUT_RAW_X509)); 307 } 308 testHasSigningCertificateByUidSha256()309 public void testHasSigningCertificateByUidSha256() throws Exception { 310 // make sure that hasSigningCertificate() reports that both certificates in the signing 311 // history are present 312 PackageManager pm = getContext().getPackageManager(); 313 int uid = pm.getPackageUid(PKG, 0); 314 byte[] firstCertBytes = computeSha256DigestBytes(fromHexToByteArray(FIRST_CERT_HEX)); 315 316 assertTrue("Old signing certificate not found for " + PKG, 317 pm.hasSigningCertificate(uid, firstCertBytes, PackageManager.CERT_INPUT_SHA256)); 318 byte[] secondCertBytes = computeSha256DigestBytes(fromHexToByteArray(SECOND_CERT_HEX)); 319 assertTrue("Current signing certificate not found for " + PKG, 320 pm.hasSigningCertificate(uid, secondCertBytes, PackageManager.CERT_INPUT_SHA256)); 321 } 322 testUsingOriginalSigner()323 public void testUsingOriginalSigner() throws Exception { 324 // Verifies the platform only recognized the original signing key during installation. 325 PackageManager pm = getContext().getPackageManager(); 326 PackageInfo pi = pm.getPackageInfo(PKG, PackageManager.GET_SIGNING_CERTIFICATES); 327 assertFalse( 328 "APK is expected to use the original signing key, but past signing certificates " 329 + "were reported", 330 pi.signingInfo.hasPastSigningCertificates()); 331 assertExpectedSignatures(pi.signingInfo.getApkContentsSigners(), EC_P256_FIRST_CERT_HEX); 332 byte[] secondCertBytes = fromHexToByteArray(EC_P256_SECOND_CERT_HEX); 333 assertFalse("APK is not expected to have the rotated key in its signing lineage", 334 pm.hasSigningCertificate(PKG, secondCertBytes, PackageManager.CERT_INPUT_RAW_X509)); 335 } 336 testUsingRotatedSigner()337 public void testUsingRotatedSigner() throws Exception { 338 // Verifies the platform recognized the rotated signing key during installation. 339 PackageManager pm = getContext().getPackageManager(); 340 PackageInfo pi = pm.getPackageInfo(PKG, PackageManager.GET_SIGNING_CERTIFICATES); 341 assertTrue( 342 "APK is expected to be signed with the rotated signing key, but past signing " 343 + "certificates were not reported", 344 pi.signingInfo.hasPastSigningCertificates()); 345 assertExpectedSignatures(pi.signingInfo.getApkContentsSigners(), EC_P256_SECOND_CERT_HEX); 346 assertExpectedSignatures(pi.signingInfo.getSigningCertificateHistory(), 347 EC_P256_FIRST_CERT_HEX, EC_P256_SECOND_CERT_HEX); 348 byte[] firstCertBytes = fromHexToByteArray(EC_P256_FIRST_CERT_HEX); 349 assertTrue("APK is expected to have the original key in its signing lineage", 350 pm.hasSigningCertificate(PKG, firstCertBytes, PackageManager.CERT_INPUT_RAW_X509)); 351 } 352 fromHexToByteArray(String str)353 private static byte[] fromHexToByteArray(String str) { 354 if (str == null || str.length() == 0 || str.length() % 2 != 0) { 355 return null; 356 } 357 358 final char[] chars = str.toCharArray(); 359 final int charLength = chars.length; 360 final byte[] bytes = new byte[charLength / 2]; 361 362 for (int i = 0; i < bytes.length; i++) { 363 bytes[i] = 364 (byte)(((getIndex(chars[i * 2]) << 4) & 0xF0) 365 | (getIndex(chars[i * 2 + 1]) & 0x0F)); 366 } 367 return bytes; 368 } 369 370 // copy of ByteStringUtils - lowercase version (to match inputs) getIndex(char c)371 private static int getIndex(char c) { 372 final char[] HEX_ARRAY = "0123456789abcdef".toCharArray(); 373 for (int i = 0; i < HEX_ARRAY.length; i++) { 374 if (HEX_ARRAY[i] == c) { 375 return i; 376 } 377 } 378 return -1; 379 } 380 computeSha256DigestBytes(byte[] data)381 private static byte[] computeSha256DigestBytes(byte[] data) throws NoSuchAlgorithmException { 382 MessageDigest messageDigest = MessageDigest.getInstance("SHA256"); 383 messageDigest.update(data); 384 return messageDigest.digest(); 385 } 386 assertExpectedSignatures(Signature[] signatures, String... expectedSignatures)387 private static void assertExpectedSignatures(Signature[] signatures, 388 String... expectedSignatures) throws Exception { 389 int numSigners = signatures.length; 390 assertEquals("An unexpected number of signatures was returned, expected " 391 + expectedSignatures.length + ", but received " + signatures.length, 392 expectedSignatures.length, numSigners); 393 Set<String> expectedSignatureSet = new HashSet<>(Arrays.asList(expectedSignatures)); 394 for (int i = 0; i < numSigners; i++) { 395 String reportedCert = signatures[i].toCharsString(); 396 // Remove the reported certificate from the set to ensure duplicates are not matched. 397 if (!expectedSignatureSet.remove(reportedCert)) { 398 fail("Received an unexpected signature during the test: " + reportedCert); 399 } 400 } 401 } 402 } 403