1 /* 2 * Copyright (C) 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 android.appsecurity.cts; 18 19 import android.platform.test.annotations.AsbSecurityTest; 20 import android.platform.test.annotations.Presubmit; 21 22 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; 23 import com.android.compatibility.common.util.CddTest; 24 import com.android.tradefed.build.IBuildInfo; 25 import com.android.tradefed.device.DeviceNotAvailableException; 26 import com.android.tradefed.testtype.DeviceTestCase; 27 import com.android.tradefed.testtype.IBuildReceiver; 28 import com.android.tradefed.util.FileUtil; 29 30 import java.io.BufferedOutputStream; 31 import java.io.File; 32 import java.io.FileOutputStream; 33 import java.io.IOException; 34 import java.io.InputStream; 35 import java.io.OutputStream; 36 import java.util.Locale; 37 import java.util.Objects; 38 import java.util.stream.Stream; 39 40 /** 41 * Tests for APK signature verification during installation. 42 */ 43 @Presubmit 44 public class PkgInstallSignatureVerificationTest extends DeviceTestCase implements IBuildReceiver { 45 46 private static final String TEST_PKG = "android.appsecurity.cts.tinyapp"; 47 private static final String TEST_PKG2 = "android.appsecurity.cts.tinyapp2"; 48 private static final String COMPANION_TEST_PKG = "android.appsecurity.cts.tinyapp_companion"; 49 private static final String COMPANION2_TEST_PKG = "android.appsecurity.cts.tinyapp_companion2"; 50 private static final String COMPANION3_TEST_PKG = "android.appsecurity.cts.tinyapp_companion3"; 51 private static final String DEVICE_TESTS_APK = "CtsV3SigningSchemeRotationTest.apk"; 52 private static final String DEVICE_TESTS_PKG = "android.appsecurity.cts.v3rotationtests"; 53 private static final String DEVICE_TESTS_CLASS = DEVICE_TESTS_PKG + ".V3RotationTest"; 54 private static final String SERVICE_PKG = "android.appsecurity.cts.keyrotationtest"; 55 private static final String SERVICE_TEST_PKG = "android.appsecurity.cts.keyrotationtest.test"; 56 private static final String SERVICE_TEST_CLASS = 57 SERVICE_TEST_PKG + ".SignatureQueryServiceInstrumentationTest"; 58 private static final String TEST_APK_RESOURCE_PREFIX = "/pkgsigverify/"; 59 private static final String INSTALL_ARG_FORCE_QUERYABLE = "--force-queryable"; 60 61 private static final String[] DSA_KEY_NAMES = {"1024", "2048", "3072"}; 62 private static final String[] EC_KEY_NAMES = {"p256", "p384", "p521"}; 63 private static final String[] RSA_KEY_NAMES = {"1024", "2048", "3072", "4096", "8192", "16384"}; 64 private static final String[] RSA_KEY_NAMES_2048_AND_LARGER = 65 {"2048", "3072", "4096", "8192", "16384"}; 66 67 private IBuildInfo mCtsBuild; 68 69 @Override setBuild(IBuildInfo buildInfo)70 public void setBuild(IBuildInfo buildInfo) { 71 mCtsBuild = buildInfo; 72 } 73 74 @Override setUp()75 protected void setUp() throws Exception { 76 super.setUp(); 77 78 Utils.prepareSingleUser(getDevice()); 79 assertNotNull(mCtsBuild); 80 uninstallPackage(); 81 uninstallCompanionPackages(); 82 installDeviceTestPkg(); 83 } 84 85 @Override tearDown()86 protected void tearDown() throws Exception { 87 try { 88 uninstallPackages(); 89 } catch (DeviceNotAvailableException ignored) { 90 } finally { 91 super.tearDown(); 92 } 93 } 94 testInstallOriginalSucceeds()95 public void testInstallOriginalSucceeds() throws Exception { 96 // APK signed with v1 and v2 schemes. Obtained by building 97 // cts/hostsidetests/appsecurity/test-apps/tinyapp. 98 assertInstallSucceeds("original.apk"); 99 } 100 testInstallV1OneSignerMD5withRSA()101 public void testInstallV1OneSignerMD5withRSA() throws Exception { 102 // APK signed with v1 scheme only, one signer. 103 assertInstallSucceedsForEach( 104 "v1-only-with-rsa-pkcs1-md5-1.2.840.113549.1.1.1-%s.apk", RSA_KEY_NAMES); 105 assertInstallSucceedsForEach( 106 "v1-only-with-rsa-pkcs1-md5-1.2.840.113549.1.1.4-%s.apk", RSA_KEY_NAMES); 107 } 108 testInstallV1OneSignerSHA1withRSA()109 public void testInstallV1OneSignerSHA1withRSA() throws Exception { 110 // APK signed with v1 scheme only, one signer. 111 assertInstallSucceedsForEach( 112 "v1-only-with-rsa-pkcs1-sha1-1.2.840.113549.1.1.1-%s.apk", RSA_KEY_NAMES); 113 assertInstallSucceedsForEach( 114 "v1-only-with-rsa-pkcs1-sha1-1.2.840.113549.1.1.5-%s.apk", RSA_KEY_NAMES); 115 } 116 testInstallV1OneSignerSHA224withRSA()117 public void testInstallV1OneSignerSHA224withRSA() throws Exception { 118 // APK signed with v1 scheme only, one signer. 119 assertInstallSucceedsForEach( 120 "v1-only-with-rsa-pkcs1-sha224-1.2.840.113549.1.1.1-%s.apk", RSA_KEY_NAMES); 121 assertInstallSucceedsForEach( 122 "v1-only-with-rsa-pkcs1-sha224-1.2.840.113549.1.1.14-%s.apk", RSA_KEY_NAMES); 123 } 124 testInstallV1OneSignerSHA256withRSA()125 public void testInstallV1OneSignerSHA256withRSA() throws Exception { 126 // APK signed with v1 scheme only, one signer. 127 assertInstallSucceedsForEach( 128 "v1-only-with-rsa-pkcs1-sha256-1.2.840.113549.1.1.1-%s.apk", RSA_KEY_NAMES); 129 assertInstallSucceedsForEach( 130 "v1-only-with-rsa-pkcs1-sha256-1.2.840.113549.1.1.11-%s.apk", RSA_KEY_NAMES); 131 } 132 testInstallV1OneSignerSHA384withRSA()133 public void testInstallV1OneSignerSHA384withRSA() throws Exception { 134 // APK signed with v1 scheme only, one signer. 135 assertInstallSucceedsForEach( 136 "v1-only-with-rsa-pkcs1-sha384-1.2.840.113549.1.1.1-%s.apk", RSA_KEY_NAMES); 137 assertInstallSucceedsForEach( 138 "v1-only-with-rsa-pkcs1-sha384-1.2.840.113549.1.1.12-%s.apk", RSA_KEY_NAMES); 139 } 140 testInstallV1OneSignerSHA512withRSA()141 public void testInstallV1OneSignerSHA512withRSA() throws Exception { 142 // APK signed with v1 scheme only, one signer. 143 assertInstallSucceedsForEach( 144 "v1-only-with-rsa-pkcs1-sha512-1.2.840.113549.1.1.1-%s.apk", RSA_KEY_NAMES); 145 assertInstallSucceedsForEach( 146 "v1-only-with-rsa-pkcs1-sha512-1.2.840.113549.1.1.13-%s.apk", RSA_KEY_NAMES); 147 } 148 testInstallV1OneSignerSHA1withECDSA()149 public void testInstallV1OneSignerSHA1withECDSA() throws Exception { 150 // APK signed with v1 scheme only, one signer. 151 assertInstallSucceedsForEach( 152 "v1-only-with-ecdsa-sha1-1.2.840.10045.2.1-%s.apk", EC_KEY_NAMES); 153 assertInstallSucceedsForEach( 154 "v1-only-with-ecdsa-sha1-1.2.840.10045.4.1-%s.apk", EC_KEY_NAMES); 155 } 156 testInstallV1OneSignerSHA224withECDSA()157 public void testInstallV1OneSignerSHA224withECDSA() throws Exception { 158 // APK signed with v1 scheme only, one signer. 159 assertInstallSucceedsForEach( 160 "v1-only-with-ecdsa-sha224-1.2.840.10045.2.1-%s.apk", EC_KEY_NAMES); 161 assertInstallSucceedsForEach( 162 "v1-only-with-ecdsa-sha224-1.2.840.10045.4.3.1-%s.apk", EC_KEY_NAMES); 163 } 164 testInstallV1OneSignerSHA256withECDSA()165 public void testInstallV1OneSignerSHA256withECDSA() throws Exception { 166 // APK signed with v1 scheme only, one signer. 167 assertInstallSucceedsForEach( 168 "v1-only-with-ecdsa-sha256-1.2.840.10045.2.1-%s.apk", EC_KEY_NAMES); 169 assertInstallSucceedsForEach( 170 "v1-only-with-ecdsa-sha256-1.2.840.10045.4.3.2-%s.apk", EC_KEY_NAMES); 171 } 172 testInstallV1OneSignerSHA384withECDSA()173 public void testInstallV1OneSignerSHA384withECDSA() throws Exception { 174 // APK signed with v1 scheme only, one signer. 175 assertInstallSucceedsForEach( 176 "v1-only-with-ecdsa-sha384-1.2.840.10045.2.1-%s.apk", EC_KEY_NAMES); 177 assertInstallSucceedsForEach( 178 "v1-only-with-ecdsa-sha384-1.2.840.10045.4.3.3-%s.apk", EC_KEY_NAMES); 179 } 180 testInstallV1OneSignerSHA512withECDSA()181 public void testInstallV1OneSignerSHA512withECDSA() throws Exception { 182 // APK signed with v1 scheme only, one signer. 183 assertInstallSucceedsForEach( 184 "v1-only-with-ecdsa-sha512-1.2.840.10045.2.1-%s.apk", EC_KEY_NAMES); 185 assertInstallSucceedsForEach( 186 "v1-only-with-ecdsa-sha512-1.2.840.10045.4.3.4-%s.apk", EC_KEY_NAMES); 187 } 188 testInstallV1OneSignerSHA1withDSA()189 public void testInstallV1OneSignerSHA1withDSA() throws Exception { 190 // APK signed with v1 scheme only, one signer. 191 assertInstallSucceedsForEach( 192 "v1-only-with-dsa-sha1-1.2.840.10040.4.1-%s.apk", DSA_KEY_NAMES); 193 assertInstallSucceedsForEach( 194 "v1-only-with-dsa-sha1-1.2.840.10040.4.3-%s.apk", DSA_KEY_NAMES); 195 } 196 testInstallV1OneSignerSHA224withDSA()197 public void testInstallV1OneSignerSHA224withDSA() throws Exception { 198 // APK signed with v1 scheme only, one signer. 199 assertInstallSucceedsForEach( 200 "v1-only-with-dsa-sha224-1.2.840.10040.4.1-%s.apk", DSA_KEY_NAMES); 201 assertInstallSucceedsForEach( 202 "v1-only-with-dsa-sha224-2.16.840.1.101.3.4.3.1-%s.apk", DSA_KEY_NAMES); 203 } 204 testInstallV1OneSignerSHA256withDSA()205 public void testInstallV1OneSignerSHA256withDSA() throws Exception { 206 // APK signed with v1 scheme only, one signer. 207 assertInstallSucceedsForEach( 208 "v1-only-with-dsa-sha256-1.2.840.10040.4.1-%s.apk", DSA_KEY_NAMES); 209 assertInstallSucceedsForEach( 210 "v1-only-with-dsa-sha256-2.16.840.1.101.3.4.3.2-%s.apk", DSA_KEY_NAMES); 211 } 212 213 // Android platform doesn't support DSA with SHA-384 and SHA-512. 214 // public void testInstallV1OneSignerSHA384withDSA() throws Exception { 215 // // APK signed with v1 scheme only, one signer. 216 // assertInstallSucceedsForEach( 217 // "v1-only-with-dsa-sha384-2.16.840.1.101.3.4.3.3-%s.apk", DSA_KEY_NAMES); 218 // } 219 // 220 // public void testInstallV1OneSignerSHA512withDSA() throws Exception { 221 // // APK signed with v1 scheme only, one signer. 222 // assertInstallSucceedsForEach( 223 // "v1-only-with-dsa-sha512-2.16.840.1.101.3.4.3.3-%s.apk", DSA_KEY_NAMES); 224 // } 225 testInstallV2StrippedFails()226 public void testInstallV2StrippedFails() throws Exception { 227 // APK signed with v1 and v2 schemes, but v2 signature was stripped from the file (by using 228 // zipalign). 229 // This should fail because the v1 signature indicates that the APK was supposed to be 230 // signed with v2 scheme as well, making the platform's anti-stripping protections reject 231 // the APK. 232 assertInstallFailsWithError("v2-stripped.apk", "Signature stripped"); 233 234 // Similar to above, but the X-Android-APK-Signed anti-stripping header in v1 signature 235 // lists unknown signature schemes in addition to APK Signature Scheme v2. Unknown schemes 236 // should be ignored. 237 assertInstallFailsWithError( 238 "v2-stripped-with-ignorable-signing-schemes.apk", "Signature stripped"); 239 } 240 testInstallV2OneSignerOneSignature()241 public void testInstallV2OneSignerOneSignature() throws Exception { 242 // APK signed with v2 scheme only, one signer, one signature. 243 assertInstallSucceedsForEach("v2-only-with-dsa-sha256-%s.apk", DSA_KEY_NAMES); 244 assertInstallSucceedsForEach("v2-only-with-ecdsa-sha256-%s.apk", EC_KEY_NAMES); 245 assertInstallSucceedsForEach("v2-only-with-rsa-pkcs1-sha256-%s.apk", RSA_KEY_NAMES); 246 assertInstallSucceedsForEach("v2-only-with-rsa-pss-sha256-%s.apk", RSA_KEY_NAMES); 247 248 // DSA with SHA-512 is not supported by Android platform and thus APK Signature Scheme v2 249 // does not support that either 250 // assertInstallSucceedsForEach("v2-only-with-dsa-sha512-%s.apk", DSA_KEY_NAMES); 251 assertInstallSucceedsForEach("v2-only-with-ecdsa-sha512-%s.apk", EC_KEY_NAMES); 252 assertInstallSucceedsForEach("v2-only-with-rsa-pkcs1-sha512-%s.apk", RSA_KEY_NAMES); 253 assertInstallSucceedsForEach( 254 "v2-only-with-rsa-pss-sha512-%s.apk", 255 RSA_KEY_NAMES_2048_AND_LARGER // 1024-bit key is too short for PSS with SHA-512 256 ); 257 } 258 testInstallV1SignatureOnlyDoesNotVerify()259 public void testInstallV1SignatureOnlyDoesNotVerify() throws Exception { 260 // APK signed with v1 scheme only, but not all digests match those recorded in 261 // META-INF/MANIFEST.MF. 262 String error = "META-INF/MANIFEST.MF has invalid digest"; 263 264 // Bitflip in classes.dex of otherwise good file. 265 assertInstallFailsWithError( 266 "v1-only-with-tampered-classes-dex.apk", error); 267 } 268 testInstallV2SignatureDoesNotVerify()269 public void testInstallV2SignatureDoesNotVerify() throws Exception { 270 // APK signed with v2 scheme only, but the signature over signed-data does not verify. 271 String error = "signature did not verify"; 272 273 // Bitflip in certificate field inside signed-data. Based on 274 // v2-only-with-dsa-sha256-1024.apk. 275 assertInstallFailsWithError("v2-only-with-dsa-sha256-1024-sig-does-not-verify.apk", error); 276 277 // Signature claims to be RSA PKCS#1 v1.5 with SHA-256, but is actually using SHA-512. 278 // Based on v2-only-with-rsa-pkcs1-sha256-2048.apk. 279 assertInstallFailsWithError( 280 "v2-only-with-rsa-pkcs1-sha256-2048-sig-does-not-verify.apk", error); 281 282 // Signature claims to be RSA PSS with SHA-256 and 32 bytes of salt, but is actually using 0 283 // bytes of salt. Based on v2-only-with-rsa-pkcs1-sha256-2048.apk. Obtained by modifying APK 284 // signer to use the wrong amount of salt. 285 assertInstallFailsWithError( 286 "v2-only-with-rsa-pss-sha256-2048-sig-does-not-verify.apk", error); 287 288 // Bitflip in the ECDSA signature. Based on v2-only-with-ecdsa-sha256-p256.apk. 289 assertInstallFailsWithError( 290 "v2-only-with-ecdsa-sha256-p256-sig-does-not-verify.apk", error); 291 } 292 testInstallV2ContentDigestMismatch()293 public void testInstallV2ContentDigestMismatch() throws Exception { 294 // APK signed with v2 scheme only, but the digest of contents does not match the digest 295 // stored in signed-data. 296 String error = "digest of contents did not verify"; 297 298 // Based on v2-only-with-rsa-pkcs1-sha512-4096.apk. Obtained by modifying APK signer to 299 // flip the leftmost bit in content digest before signing signed-data. 300 assertInstallFailsWithError( 301 "v2-only-with-rsa-pkcs1-sha512-4096-digest-mismatch.apk", error); 302 303 // Based on v2-only-with-ecdsa-sha256-p256.apk. Obtained by modifying APK signer to flip the 304 // leftmost bit in content digest before signing signed-data. 305 assertInstallFailsWithError( 306 "v2-only-with-ecdsa-sha256-p256-digest-mismatch.apk", error); 307 } 308 testInstallNoApkSignatureSchemeBlock()309 public void testInstallNoApkSignatureSchemeBlock() throws Exception { 310 // APK signed with v2 scheme only, but the rules for verifying APK Signature Scheme v2 311 // signatures say that this APK must not be verified using APK Signature Scheme v2. 312 313 // Obtained from v2-only-with-rsa-pkcs1-sha512-4096.apk by flipping a bit in the magic 314 // field in the footer of APK Signing Block. This makes the APK Signing Block disappear. 315 assertInstallFails("v2-only-wrong-apk-sig-block-magic.apk"); 316 317 // Obtained by modifying APK signer to insert "GARBAGE" between ZIP Central Directory and 318 // End of Central Directory. The APK is otherwise fine and is signed with APK Signature 319 // Scheme v2. Based on v2-only-with-rsa-pkcs1-sha256.apk. 320 assertInstallFails("v2-only-garbage-between-cd-and-eocd.apk"); 321 322 // Obtained by modifying APK signer to truncate the ZIP Central Directory by one byte. The 323 // APK is otherwise fine and is signed with APK Signature Scheme v2. Based on 324 // v2-only-with-rsa-pkcs1-sha256.apk 325 assertInstallFails("v2-only-truncated-cd.apk"); 326 327 // Obtained by modifying the size in APK Signature Block header. Based on 328 // v2-only-with-ecdsa-sha512-p521.apk. 329 assertInstallFails("v2-only-apk-sig-block-size-mismatch.apk"); 330 331 // Obtained by modifying the ID under which APK Signature Scheme v2 Block is stored in 332 // APK Signing Block and by modifying the APK signer to not insert anti-stripping 333 // protections into JAR Signature. The APK should appear as having no APK Signature Scheme 334 // v2 Block and should thus successfully verify using JAR Signature Scheme. 335 assertInstallSucceeds("v1-with-apk-sig-block-but-without-apk-sig-scheme-v2-block.apk"); 336 } 337 testInstallV2UnknownPairIgnoredInApkSigningBlock()338 public void testInstallV2UnknownPairIgnoredInApkSigningBlock() throws Exception { 339 // Obtained by modifying APK signer to emit an unknown ID-value pair into APK Signing Block 340 // before the ID-value pair containing the APK Signature Scheme v2 Block. The unknown 341 // ID-value should be ignored. 342 assertInstallSucceeds("v2-only-unknown-pair-in-apk-sig-block.apk"); 343 } 344 testInstallV2IgnoresUnknownSignatureAlgorithms()345 public void testInstallV2IgnoresUnknownSignatureAlgorithms() throws Exception { 346 // APK is signed with a known signature algorithm and with a couple of unknown ones. 347 // Obtained by modifying APK signer to use "unknown" signature algorithms in addition to 348 // known ones. 349 assertInstallSucceeds("v2-only-with-ignorable-unsupported-sig-algs.apk"); 350 } 351 testInstallV2RejectsMismatchBetweenSignaturesAndDigestsBlocks()352 public void testInstallV2RejectsMismatchBetweenSignaturesAndDigestsBlocks() throws Exception { 353 // APK is signed with a single signature algorithm, but the digests block claims that it is 354 // signed with two different signature algorithms. Obtained by modifying APK Signer to 355 // emit an additional digest record with signature algorithm 0x12345678. 356 assertInstallFailsWithError( 357 "v2-only-signatures-and-digests-block-mismatch.apk", 358 "Signature algorithms don't match between digests and signatures records"); 359 } 360 testInstallV2RejectsMismatchBetweenPublicKeyAndCertificate()361 public void testInstallV2RejectsMismatchBetweenPublicKeyAndCertificate() throws Exception { 362 // APK is signed with v2 only. The public key field does not match the public key in the 363 // leaf certificate. Obtained by modifying APK signer to write out a modified leaf 364 // certificate where the RSA modulus has a bitflip. 365 assertInstallFailsWithError( 366 "v2-only-cert-and-public-key-mismatch.apk", 367 "Public key mismatch between certificate and signature record"); 368 } 369 testInstallV2RejectsSignerBlockWithNoCertificates()370 public void testInstallV2RejectsSignerBlockWithNoCertificates() throws Exception { 371 // APK is signed with v2 only. There are no certificates listed in the signer block. 372 // Obtained by modifying APK signer to output no certificates. 373 assertInstallFailsWithError("v2-only-no-certs-in-sig.apk", "No certificates listed"); 374 } 375 testInstallTwoSigners()376 public void testInstallTwoSigners() throws Exception { 377 // APK signed by two different signers. 378 assertInstallSucceeds("two-signers.apk"); 379 // Because the install attempt below is an update, it also tests that the signing 380 // certificates exposed by v2 signatures above are the same as the one exposed by v1 381 // signatures in this APK. 382 assertInstallSucceeds("v1-only-two-signers.apk"); 383 assertInstallSucceeds("v2-only-two-signers.apk"); 384 } 385 testInstallNegativeModulus()386 public void testInstallNegativeModulus() throws Exception { 387 // APK signed with a certificate that has a negative RSA modulus. 388 assertInstallSucceeds("v1-only-negative-modulus.apk"); 389 assertInstallSucceeds("v2-only-negative-modulus.apk"); 390 assertInstallSucceeds("v3-only-negative-modulus.apk"); 391 } 392 testInstallV2TwoSignersRejectsWhenOneBroken()393 public void testInstallV2TwoSignersRejectsWhenOneBroken() throws Exception { 394 // Bitflip in the ECDSA signature of second signer. Based on two-signers.apk. 395 // This asserts that breakage in any signer leads to rejection of the APK. 396 assertInstallFailsWithError( 397 "two-signers-second-signer-v2-broken.apk", "signature did not verify"); 398 } 399 testInstallV2TwoSignersRejectsWhenOneWithoutSignatures()400 public void testInstallV2TwoSignersRejectsWhenOneWithoutSignatures() throws Exception { 401 // APK v2-signed by two different signers. However, there are no signatures for the second 402 // signer. 403 assertInstallFailsWithError( 404 "v2-only-two-signers-second-signer-no-sig.apk", "No signatures"); 405 } 406 testInstallV2TwoSignersRejectsWhenOneWithoutSupportedSignatures()407 public void testInstallV2TwoSignersRejectsWhenOneWithoutSupportedSignatures() throws Exception { 408 // APK v2-signed by two different signers. However, there are no supported signatures for 409 // the second signer. 410 assertInstallFailsWithError( 411 "v2-only-two-signers-second-signer-no-supported-sig.apk", 412 "No supported signatures"); 413 } 414 testInstallV2RejectsWhenMissingCode()415 public void testInstallV2RejectsWhenMissingCode() throws Exception { 416 // Obtained by removing classes.dex from original.apk and then signing with v2 only. 417 // Although this has nothing to do with v2 signature verification, package manager wants 418 // signature verification / certificate collection to reject APKs with missing code 419 // (classes.dex) unless requested otherwise. 420 assertInstallFailsWithError("v2-only-missing-classes.dex.apk", "code is missing"); 421 } 422 testCorrectCertUsedFromPkcs7SignedDataCertsSet()423 public void testCorrectCertUsedFromPkcs7SignedDataCertsSet() throws Exception { 424 // Obtained by prepending the rsa-1024 certificate to the PKCS#7 SignedData certificates set 425 // of v1-only-with-rsa-pkcs1-sha1-1.2.840.113549.1.1.1-2048.apk META-INF/CERT.RSA. The certs 426 // (in the order of appearance in the file) are thus: rsa-1024, rsa-2048. The package's 427 // signing cert is rsa-2048. 428 assertInstallSucceeds("v1-only-pkcs7-cert-bag-first-cert-not-used.apk"); 429 430 // Check that rsa-1024 was not used as the previously installed package's signing cert. 431 assertInstallFailsWithError( 432 "v1-only-with-rsa-pkcs1-sha1-1.2.840.113549.1.1.1-1024.apk", 433 "signatures do not match"); 434 435 // Check that rsa-2048 was used as the previously installed package's signing cert. 436 assertInstallSucceeds("v1-only-with-rsa-pkcs1-sha1-1.2.840.113549.1.1.1-2048.apk"); 437 } 438 testV1SchemeSignatureCertNotReencoded()439 public void testV1SchemeSignatureCertNotReencoded() throws Exception { 440 // Regression test for b/30148997 and b/18228011. When PackageManager does not preserve the 441 // original encoded form of signing certificates, bad things happen, such as rejection of 442 // completely valid updates to apps. The issue in b/30148997 and b/18228011 was that 443 // PackageManager started re-encoding signing certs into DER. This normally produces exactly 444 // the original form because X.509 certificates are supposed to be DER-encoded. However, a 445 // small fraction of Android apps uses X.509 certificates which are not DER-encoded. For 446 // such apps, re-encoding into DER changes the serialized form of the certificate, creating 447 // a mismatch with the serialized form stored in the PackageManager database, leading to the 448 // rejection of updates for the app. 449 // 450 // The signing certs of the two APKs differ only in how the cert's signature is encoded. 451 // From Android's perspective, these two APKs are signed by different entities and thus 452 // cannot be used to update one another. If signature verification code re-encodes certs 453 // into DER, both certs will be exactly the same and Android will accept these APKs as 454 // updates of each other. This test is thus asserting that the two APKs are not accepted as 455 // updates of each other. 456 // 457 // * v1-only-with-rsa-1024.apk cert's signature is DER-encoded 458 // * v1-only-with-rsa-1024-cert-not-der.apk cert's signature is not DER-encoded. It is 459 // BER-encoded, with length encoded as two bytes instead of just one. 460 // v1-only-with-rsa-1024-cert-not-der.apk META-INF/CERT.RSA was obtained from 461 // v1-only-with-rsa-1024.apk META-INF/CERT.RSA by manually modifying the ASN.1 structure. 462 assertInstallSucceeds("v1-only-with-rsa-1024.apk"); 463 assertInstallFailsWithError( 464 "v1-only-with-rsa-1024-cert-not-der.apk", "signatures do not match"); 465 466 uninstallPackage(); 467 assertInstallSucceeds("v1-only-with-rsa-1024-cert-not-der.apk"); 468 assertInstallFailsWithError("v1-only-with-rsa-1024.apk", "signatures do not match"); 469 } 470 testV2SchemeSignatureCertNotReencoded()471 public void testV2SchemeSignatureCertNotReencoded() throws Exception { 472 // This test is here to catch something like b/30148997 and b/18228011 happening to the 473 // handling of APK Signature Scheme v2 signatures by PackageManager. When PackageManager 474 // does not preserve the original encoded form of signing certificates, bad things happen, 475 // such as rejection of completely valid updates to apps. The issue in b/30148997 and 476 // b/18228011 was that PackageManager started re-encoding signing certs into DER. This 477 // normally produces exactly the original form because X.509 certificates are supposed to be 478 // DER-encoded. However, a small fraction of Android apps uses X.509 certificates which are 479 // not DER-encoded. For such apps, re-encoding into DER changes the serialized form of the 480 // certificate, creating a mismatch with the serialized form stored in the PackageManager 481 // database, leading to the rejection of updates for the app. 482 // 483 // The signing certs of the two APKs differ only in how the cert's signature is encoded. 484 // From Android's perspective, these two APKs are signed by different entities and thus 485 // cannot be used to update one another. If signature verification code re-encodes certs 486 // into DER, both certs will be exactly the same and Android will accept these APKs as 487 // updates of each other. This test is thus asserting that the two APKs are not accepted as 488 // updates of each other. 489 // 490 // * v2-only-with-rsa-pkcs1-sha256-1024.apk cert's signature is DER-encoded 491 // * v2-only-with-rsa-pkcs1-sha256-1024-cert-not-der.apk cert's signature is not DER-encoded 492 // It is BER-encoded, with length encoded as two bytes instead of just one. 493 assertInstallSucceeds("v2-only-with-rsa-pkcs1-sha256-1024.apk"); 494 assertInstallFailsWithError( 495 "v2-only-with-rsa-pkcs1-sha256-1024-cert-not-der.apk", "signatures do not match"); 496 497 uninstallPackage(); 498 assertInstallSucceeds("v2-only-with-rsa-pkcs1-sha256-1024-cert-not-der.apk"); 499 assertInstallFailsWithError( 500 "v2-only-with-rsa-pkcs1-sha256-1024.apk", "signatures do not match"); 501 } 502 testInstallMaxSizedZipEocdComment()503 public void testInstallMaxSizedZipEocdComment() throws Exception { 504 // Obtained by modifying apksigner to produce a max-sized (0xffff bytes long) ZIP End of 505 // Central Directory comment, and signing the original.apk using the modified apksigner. 506 assertInstallSucceeds("v1-only-max-sized-eocd-comment.apk"); 507 assertInstallSucceeds("v2-only-max-sized-eocd-comment.apk"); 508 } 509 testInstallEphemeralRequiresV2Signature()510 public void testInstallEphemeralRequiresV2Signature() throws Exception { 511 assertInstallEphemeralFailsWithError("unsigned-ephemeral.apk", 512 "Failed to collect certificates"); 513 assertInstallEphemeralFailsWithError("v1-only-ephemeral.apk", 514 "must be signed with APK Signature Scheme v2 or greater"); 515 assertInstallEphemeralSucceeds("v2-only-ephemeral.apk"); 516 assertInstallEphemeralSucceeds("v1-v2-ephemeral.apk"); // signed with both schemes 517 } 518 testInstallEmpty()519 public void testInstallEmpty() throws Exception { 520 assertInstallFailsWithError("empty-unsigned.apk", "Unknown failure"); 521 assertInstallFailsWithError("v1-only-empty.apk", "Unknown failure"); 522 assertInstallFailsWithError("v2-only-empty.apk", "Unknown failure"); 523 } 524 525 @AsbSecurityTest(cveBugId = 64211847) testInstallApkWhichDoesNotStartWithZipLocalFileHeaderMagic()526 public void testInstallApkWhichDoesNotStartWithZipLocalFileHeaderMagic() throws Exception { 527 // The APKs below are competely fine except they don't start with ZIP Local File Header 528 // magic. Thus, these APKs will install just fine unless Package Manager requires that APKs 529 // start with ZIP Local File Header magic. 530 String error = "Unknown failure"; 531 532 // Obtained by modifying apksigner to output four unused 0x00 bytes at the start of the APK 533 assertInstallFailsWithError("v1-only-starts-with-00000000-magic.apk", error); 534 assertInstallFailsWithError("v2-only-starts-with-00000000-magic.apk", error); 535 536 // Obtained by modifying apksigner to output 8 unused bytes (DEX magic and version) at the 537 // start of the APK 538 assertInstallFailsWithError("v1-only-starts-with-dex-magic.apk", error); 539 assertInstallFailsWithError("v2-only-starts-with-dex-magic.apk", error); 540 } 541 testInstallV3KeyRotation()542 public void testInstallV3KeyRotation() throws Exception { 543 // tests that a v3 signed APK with RSA key can rotate to a new key 544 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1.apk"); 545 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 546 } 547 testInstallV3KeyRotationToAncestor()548 public void testInstallV3KeyRotationToAncestor() throws Exception { 549 // tests that a v3 signed APK with RSA key cannot be upgraded by one of its past certs 550 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 551 assertInstallFails("v3-rsa-pkcs1-sha256-2048-1.apk"); 552 } 553 testInstallV3KeyRotationToAncestorWithRollback()554 public void testInstallV3KeyRotationToAncestorWithRollback() throws Exception { 555 // tests that a v3 signed APK with RSA key can be upgraded by one of its past certs if it 556 // has granted that cert the rollback capability 557 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-and-roll-caps.apk"); 558 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1.apk"); 559 } 560 testInstallV3KeyRotationMultipleHops()561 public void testInstallV3KeyRotationMultipleHops() throws Exception { 562 // tests that a v3 signed APK with RSA key can rotate to a new key which is the result of 563 // multiple rotations from the original: APK signed with key 1 can be updated by key 3, when 564 // keys were: 1 -> 2 -> 3 565 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1.apk"); 566 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-3-with-por_1_2_3-full-caps.apk"); 567 } 568 testInstallV3PorSignerMismatch()569 public void testInstallV3PorSignerMismatch() throws Exception { 570 // tests that an APK with a proof-of-rotation struct that doesn't include the current 571 // signing certificate fails to install 572 assertInstallFails("v3-rsa-pkcs1-sha256-2048-3-with-por_1_2-full-caps.apk"); 573 } 574 testInstallV3KeyRotationWrongPor()575 public void testInstallV3KeyRotationWrongPor() throws Exception { 576 // tests that a valid APK with a proof-of-rotation record can't upgrade an APK with a 577 // signing certificate that isn't in the proof-of-rotation record 578 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1.apk"); 579 assertInstallFails("v3-rsa-pkcs1-sha256-2048-3-with-por_2_3-full-caps.apk"); 580 } 581 testInstallV3KeyRotationSharedUid()582 public void testInstallV3KeyRotationSharedUid() throws Exception { 583 // tests that a v3 signed sharedUid APK can still be sharedUid with apps with its older 584 // signing certificate, if it so desires 585 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-sharedUid.apk"); 586 assertInstallSucceeds( 587 "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-sharedUid-companion.apk"); 588 } 589 testInstallV3KeyRotationOlderSharedUid()590 public void testInstallV3KeyRotationOlderSharedUid() throws Exception { 591 // tests that a sharedUid APK can still install with another app that is signed by a newer 592 // signing certificate, but which allows sharedUid with the older one 593 assertInstallSucceeds( 594 "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-sharedUid-companion.apk"); 595 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-sharedUid.apk"); 596 } 597 testInstallV3KeyRotationSharedUidNoCap()598 public void testInstallV3KeyRotationSharedUidNoCap() throws Exception { 599 // tests that a v3 signed sharedUid APK cannot be sharedUid with apps with its older 600 // signing certificate, when it has not granted that certificate the sharedUid capability 601 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-sharedUid.apk"); 602 assertInstallFails( 603 "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-shUid-cap-sharedUid-companion.apk"); 604 } 605 testInstallV3KeyRotationOlderSharedUidNoCap()606 public void testInstallV3KeyRotationOlderSharedUidNoCap() throws Exception { 607 // tests that a sharedUid APK signed with an old certificate cannot install with 608 // an app having a proof-of-rotation structure that hasn't granted the older 609 // certificate the sharedUid capability 610 assertInstallSucceeds( 611 "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-shUid-cap-sharedUid-companion.apk"); 612 assertInstallFails("v3-rsa-pkcs1-sha256-2048-1-sharedUid.apk"); 613 } 614 testInstallV3NoRotationSharedUid()615 public void testInstallV3NoRotationSharedUid() throws Exception { 616 // tests that a sharedUid APK signed with a new certificate installs with 617 // an app having a proof-of-rotation structure that hasn't granted an older 618 // certificate the sharedUid capability 619 assertInstallSucceeds( 620 "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-shUid-cap-sharedUid-companion.apk"); 621 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-sharedUid.apk"); 622 } 623 testInstallV3MultipleAppsOneDeniesOldKeySharedUid()624 public void testInstallV3MultipleAppsOneDeniesOldKeySharedUid() throws Exception { 625 // If two apps are installed as part of a sharedUid, one granting access to the sharedUid 626 // to the previous key and the other revoking access to the sharedUid, then when an app 627 // signed with the old key attempts to join the sharedUid the installation should be blocked 628 assertInstallFromBuildSucceeds( 629 "v3-ec-p256-with-por_1_2-default-caps-sharedUid-companion.apk"); 630 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid.apk"); 631 assertInstallFromBuildFails("v3-ec-p256-1-sharedUid-companion2.apk"); 632 } 633 testInstallV3MultipleAppsOneUpdatedToDenyOldKeySharedUid()634 public void testInstallV3MultipleAppsOneUpdatedToDenyOldKeySharedUid() throws Exception { 635 // Similar to the test above if two apps are installed as part of a sharedUid with both 636 // granting access to the sharedUid to the previous key then an app signed with the previous 637 // key should be allowed to install and join the sharedUid. If one of the first two apps 638 // is then updated with a lineage that denies access to the sharedUid for the old key the 639 // installation of this updated app should be blocked. 640 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-default-caps-sharedUid.apk"); 641 assertInstallFromBuildSucceeds( 642 "v3-ec-p256-with-por_1_2-default-caps-sharedUid-companion.apk"); 643 assertInstallFromBuildSucceeds("v3-ec-p256-1-sharedUid-companion2.apk"); 644 assertInstallFromBuildFails("v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid.apk"); 645 } 646 testInstallV3FirstAppOnlySignedByNewKeyLastAppOldKey()647 public void testInstallV3FirstAppOnlySignedByNewKeyLastAppOldKey() throws Exception { 648 // This test verifies the following scenario: 649 // - First installed app in sharedUid only signed with new key without lineage. 650 // - Second installed app in sharedUid signed with new key and includes lineage granting 651 // access to the old key to join the sharedUid. 652 // - Last installed app in sharedUid signed with old key. 653 // The lineage should be updated when the second app is installed to allow the installation 654 // of the app signed with the old key. 655 assertInstallFromBuildSucceeds("v3-ec-p256-2-sharedUid-companion.apk"); 656 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-default-caps-sharedUid.apk"); 657 assertInstallFromBuildSucceeds("v3-ec-p256-1-sharedUid-companion2.apk"); 658 } 659 testInstallV3AppSignedWithOldKeyUpdatedLineageDeniesShUidCap()660 public void testInstallV3AppSignedWithOldKeyUpdatedLineageDeniesShUidCap() throws Exception { 661 // If an app is installed as part of a sharedUid, and then that app is signed with a new key 662 // that rejects the previous key in the lineage the update should be allowed to proceed 663 // as the app is being updated to the newly rotated key. 664 assertInstallFromBuildSucceeds("v3-ec-p256-1-sharedUid.apk"); 665 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid.apk"); 666 } 667 testInstallV3TwoSharedUidAppsWithDivergedLineages()668 public void testInstallV3TwoSharedUidAppsWithDivergedLineages() throws Exception { 669 // Apps that are installed as part of the sharedUserId with a lineage must have common 670 // ancestors; the platform will allow the installation if the lineage of an app being 671 // installed as part of the sharedUserId is the same, a subset, or a superset of the 672 // existing lineage, but if the lineage diverges then the installation should be blocked. 673 assertInstallFromBuildSucceeds("v3-por_Y_1_2-default-caps-sharedUid.apk"); 674 assertInstallFromBuildFails("v3-por_Z_1_2-default-caps-sharedUid-companion.apk"); 675 } 676 testInstallV3WithRestoredCapabilityInSharedUserId()677 public void testInstallV3WithRestoredCapabilityInSharedUserId() throws Exception { 678 // A sharedUserId contains the shared signing lineage for all packages in the UID; this 679 // shared lineage contain the full signing history for all packages along with the merged 680 // capabilities for each signer shared between the packages. This test verifies if one 681 // package revokes a capability from a previous signer, but subsequently restores that 682 // capability, then since all packages have granted the capability, it is restored to the 683 // previous signer in the shared lineage. 684 685 // Install a package with the SHARED_USER_ID capability revoked for the original signer 686 // in the lineage; verify that a package signed with only the original signer cannot join 687 // the sharedUserId. 688 assertInstallFromBuildSucceeds( 689 "v3-ec-p256-with-por_1_2-default-caps-sharedUid-companion.apk"); 690 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid.apk"); 691 assertInstallFromBuildFails("v3-ec-p256-1-sharedUid-companion2.apk"); 692 693 // Update the package that revoked the SHARED_USER_ID with an updated lineage that restores 694 // this capability to the original signer; verify the package signed with the original 695 // signing key can now join the sharedUserId since all existing packages in the UID grant 696 // this capability to the original signer. 697 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-default-caps-sharedUid.apk"); 698 assertInstallFromBuildSucceeds("v3-ec-p256-1-sharedUid-companion2.apk"); 699 } 700 testInstallV3WithRevokedCapabilityInSharedUserId()701 public void testInstallV3WithRevokedCapabilityInSharedUserId() throws Exception { 702 // While a capability can be restored to a common signer in the shared signing lineage, if 703 // one package has revoked a capability from a common signer and another package is 704 // installed / updated which restores the capability to that signer, the revocation of 705 // the capability by the existing package should take precedence. A capability can only 706 // be restored to a common signer if all packages in the sharedUserId have granted this 707 // capability to the signer. 708 709 // Install a package with the SHARED_USER_ID capability revoked from the original signer, 710 // then install another package in the sharedUserId that grants this capability to the 711 // original signer. Since a package exists in the sharedUserId that has revoked this 712 // capability, another package signed with this capability shouldn't be able to join the 713 // sharedUserId. 714 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid.apk"); 715 assertInstallFromBuildSucceeds( 716 "v3-ec-p256-with-por_1_2-default-caps-sharedUid-companion.apk"); 717 assertInstallFromBuildFails("v3-ec-p256-1-sharedUid-companion2.apk"); 718 719 // Install the same package that grants the SHARED_USER_ID capability to the original 720 // signer; when iterating over the existing packages in the packages in the sharedUserId, 721 // the original version of this package should be skipped since the lineage from the 722 // updated package is used when merging with the shared lineage. 723 assertInstallFromBuildSucceeds( 724 "v3-ec-p256-with-por_1_2-default-caps-sharedUid-companion.apk"); 725 assertInstallFromBuildFails("v3-ec-p256-1-sharedUid-companion2.apk"); 726 727 // Install another package that has granted the SHARED_USER_ID to the original signer; this 728 // should trigger another merge with all packages in the sharedUserId. Since one still 729 // remains that revokes the capability, the capability should be revoked in the shared 730 // lineage. 731 assertInstallFromBuildSucceeds( 732 "v3-ec-p256-with-por_1_2-default-caps-sharedUid-companion3.apk"); 733 assertInstallFromBuildFails("v3-ec-p256-1-sharedUid-companion2.apk"); 734 } 735 testInstallV3UpdateAfterRotation()736 public void testInstallV3UpdateAfterRotation() throws Exception { 737 // This test performs an end to end verification of the update of an app with a rotated 738 // key. The app under test exports a bound service that performs its own PackageManager key 739 // rotation API verification, and the instrumentation test binds to the service and invokes 740 // the verifySignatures method to verify that the key rotation APIs return the expected 741 // results. The instrumentation test app is signed with the same key and lineage as the 742 // app under test to also provide a second app that can be used for the checkSignatures 743 // verification. 744 745 // Install the initial versions of the apps; the test method verifies the app under test is 746 // signed with the original signing key. 747 assertInstallFromBuildSucceeds("CtsSignatureQueryService.apk"); 748 assertInstallFromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 749 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 750 "verifySignatures_noRotation_succeeds"); 751 752 // Install the second version of the app signed with the rotated key. This test verifies the 753 // app still functions as expected after the update with the rotated key. The 754 // instrumentation test app is not updated here to allow verification of the pre-key 755 // rotation behavior for the checkSignatures APIs. These APIs should behave similar to the 756 // GET_SIGNATURES flag in that if one or both apps have a signing lineage if the oldest 757 // signers in the lineage match then the methods should return that the signatures match 758 // even if one is signed with a newer key in the lineage. 759 assertInstallFromBuildSucceeds("CtsSignatureQueryService_v2.apk"); 760 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 761 "verifySignatures_withRotation_succeeds"); 762 763 // Installs the third version of the app under test and the instrumentation test, both 764 // signed with the same rotated key and lineage. This test is intended to verify that the 765 // app can still be updated and function as expected after an update with a rotated key. 766 assertInstallFromBuildSucceeds("CtsSignatureQueryService_v3.apk"); 767 assertInstallFromBuildSucceeds("CtsSignatureQueryServiceTest_v2.apk"); 768 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 769 "verifySignatures_withRotation_succeeds"); 770 } 771 772 @CddTest(requirement="4/C-0-2") testInstallV31UpdateAfterRotation()773 public void testInstallV31UpdateAfterRotation() throws Exception { 774 // This test is the same as above, but using the v3.1 signature scheme for rotation. 775 assertInstallFromBuildSucceeds("CtsSignatureQueryService.apk"); 776 assertInstallFromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 777 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 778 "verifySignatures_noRotation_succeeds"); 779 780 assertInstallFromBuildSucceeds("CtsSignatureQueryService_v2-tgt-33.apk"); 781 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 782 "verifySignatures_withRotation_succeeds"); 783 784 assertInstallFromBuildSucceeds("CtsSignatureQueryService_v3-tgt-33.apk"); 785 assertInstallFromBuildSucceeds("CtsSignatureQueryServiceTest_v2-tgt-33.apk"); 786 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 787 "verifySignatures_withRotation_succeeds"); 788 } 789 790 @CddTest(requirement="4/C-0-9") testInstallV41UpdateAfterRotation()791 public void testInstallV41UpdateAfterRotation() throws Exception { 792 // V4 is only enabled on devices with Incremental feature 793 if (!hasIncrementalFeature()) { 794 return; 795 } 796 797 // This test is the same as above, but using the v4.1 signature scheme for rotation. 798 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService.apk"); 799 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 800 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 801 "verifySignatures_noRotation_succeeds"); 802 803 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService_v2-tgt-33.apk"); 804 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 805 "verifySignatures_withRotation_succeeds"); 806 807 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService_v3-tgt-33.apk"); 808 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest_v2-tgt-33.apk"); 809 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 810 "verifySignatures_withRotation_succeeds"); 811 } 812 813 @CddTest(requirement="4/C-0-9") testInstallV41WrongBlockId()814 public void testInstallV41WrongBlockId() throws Exception { 815 // V4 is only enabled on devices with Incremental feature 816 if (!hasIncrementalFeature()) { 817 return; 818 } 819 820 // This test is the same as above, but using the v4.1 signature scheme for rotation. 821 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService.apk"); 822 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 823 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 824 "verifySignatures_noRotation_succeeds"); 825 826 assertInstallV4FailsWithError("CtsSignatureQueryService_v2-tgt-33-wrongV41Block.apk", 827 "Failed to find V4 signature block corresponding to V3 blockId: 462663009"); 828 } 829 830 @CddTest(requirement="4/C-0-9") testInstallV41LegacyV4()831 public void testInstallV41LegacyV4() throws Exception { 832 // V4 is only enabled on devices with Incremental feature 833 if (!hasIncrementalFeature()) { 834 return; 835 } 836 837 // This test is the same as above, but using the v4.1 signature scheme for rotation. 838 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService.apk"); 839 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 840 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 841 "verifySignatures_noRotation_succeeds"); 842 843 assertInstallV4FailsWithError("CtsSignatureQueryService_v2-tgt-33-legacyV4.apk", 844 "Failed to find V4 signature block corresponding to V3 blockId: 462663009"); 845 } 846 847 @CddTest(requirement="4/C-0-9") testInstallV41WrongDigest()848 public void testInstallV41WrongDigest() throws Exception { 849 // V4 is only enabled on devices with Incremental feature 850 if (!hasIncrementalFeature()) { 851 return; 852 } 853 854 // This test is the same as above, but using the v4.1 signature scheme for rotation. 855 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService.apk"); 856 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 857 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 858 "verifySignatures_noRotation_succeeds"); 859 860 assertInstallV4FailsWithError("CtsSignatureQueryService_v2-tgt-33-wrongDigest.apk", 861 "APK digest in V4 signature does not match V2/V3"); 862 } 863 testInstallV3KeyRotationSigPerm()864 public void testInstallV3KeyRotationSigPerm() throws Exception { 865 // tests that a v3 signed APK can still get a signature permission from an app with its 866 // older signing certificate. 867 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk"); 868 assertInstallSucceeds( 869 "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-permcli-companion.apk"); 870 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 871 } 872 testInstallV3KeyRotationOlderSigPerm()873 public void testInstallV3KeyRotationOlderSigPerm() throws Exception { 874 // tests that an apk with an older signing certificate than the one which defines a 875 // signature permission it wants gets the permission if the defining APK grants the 876 // capability 877 assertInstallSucceeds( 878 "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-permdef.apk"); 879 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permcli-companion.apk"); 880 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 881 } 882 testInstallV3KeyRotationSigPermNoCap()883 public void testInstallV3KeyRotationSigPermNoCap() throws Exception { 884 // tests that an APK signed by an older signing certificate is unable to get a requested 885 // signature permission when the defining APK has rotated to a newer signing certificiate 886 // and does not grant the permission capability to the older cert 887 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permdef.apk"); 888 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permcli-companion.apk"); 889 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasNoPerm"); 890 } 891 testInstallV3KeyRotationOlderSigPermNoCap()892 public void testInstallV3KeyRotationOlderSigPermNoCap() throws Exception { 893 // tests that an APK signed by a newer signing certificate than the APK which defines a 894 // signature permission is able to get that permission, even if the newer APK does not 895 // grant the permission capability to the older signing certificate. 896 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk"); 897 assertInstallSucceeds( 898 "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permcli-companion.apk"); 899 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 900 } 901 testInstallV3NoRotationSigPerm()902 public void testInstallV3NoRotationSigPerm() throws Exception { 903 // make sure that an APK, which wants to use a signature permission defined by an APK, which 904 // has not granted that capability to older signing certificates, can still install 905 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permdef.apk"); 906 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-permcli-companion.apk"); 907 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 908 } 909 testInstallV3CommonSignerInLineageWithPermCap()910 public void testInstallV3CommonSignerInLineageWithPermCap() throws Exception { 911 // If an APK requesting a signature permission has a common signer in the lineage with the 912 // APK declaring the permission, and that signer is granted the permission capability in 913 // the declaring APK, then the permission should be granted to the requesting app even 914 // if their signers have diverged. 915 assertInstallFromBuildSucceeds( 916 "v3-ec-p256-with-por_1_2_3-1-no-caps-2-default-declperm.apk"); 917 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2_4-companion-usesperm.apk"); 918 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 919 } 920 testInstallV3CommonSignerInLineageNoCaps()921 public void testInstallV3CommonSignerInLineageNoCaps() throws Exception { 922 // If an APK requesting a signature permission has a common signer in the lineage with the 923 // APK declaring the permission, but the signer in the lineage has not been granted the 924 // permission capability the permission should not be granted to the requesting app. 925 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2_3-no-caps-declperm.apk"); 926 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2_4-companion-usesperm.apk"); 927 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasNoPerm"); 928 } 929 testKnownSignerPermGrantedWhenCurrentSignerInResource()930 public void testKnownSignerPermGrantedWhenCurrentSignerInResource() throws Exception { 931 // The knownSigner protection flag allows an app to declare other trusted signing 932 // certificates in an array resource; if a requesting app's current signer is in this array 933 // of trusted certificates then the permission should be granted. 934 assertInstallFromBuildSucceeds("v3-rsa-2048-decl-knownSigner-ec-p256-1-3.apk"); 935 assertInstallFromBuildSucceeds("v3-ec-p256_3-companion-uses-knownSigner.apk"); 936 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 937 938 // If the declaring app changes the trusted certificates on an update any requesting app 939 // that no longer meets the requirements based on its signing identity should have the 940 // permission revoked. This app update only trusts ec-p256_1 but the app that was previously 941 // granted the permission based on its signing identity is signed by ec-p256_3. 942 assertInstallFromBuildSucceeds("v3-rsa-2048-decl-knownSigner-str-res-ec-p256-1.apk"); 943 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasNoPerm"); 944 } 945 testKnownSignerPermCurrentSignerNotInResource()946 public void testKnownSignerPermCurrentSignerNotInResource() throws Exception { 947 // If an app requesting a knownSigner permission does not meet the requirements for a 948 // signature permission and is not signed by any of the trusted certificates then the 949 // permission should not be granted. 950 assertInstallFromBuildSucceeds("v3-rsa-2048-decl-knownSigner-ec-p256-1-3.apk"); 951 assertInstallFromBuildSucceeds("v3-ec-p256_2-companion-uses-knownSigner.apk"); 952 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasNoPerm"); 953 } 954 testKnownSignerPermGrantedWhenSignerInLineageInResource()955 public void testKnownSignerPermGrantedWhenSignerInLineageInResource() throws Exception { 956 // If an app requesting a knownSigner permission was previously signed by a certificate 957 // that is trusted by the declaring app then the permission should be granted. 958 assertInstallFromBuildSucceeds("v3-rsa-2048-decl-knownSigner-ec-p256-1-3.apk"); 959 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-companion-uses-knownSigner.apk"); 960 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 961 962 // If the declaring app changes the permission to no longer use the knownSigner flag then 963 // any app granted the permission based on a signing identity from the set of trusted 964 // certificates should have the permission revoked. 965 assertInstallFromBuildSucceeds("v3-rsa-2048-declperm.apk"); 966 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasNoPerm"); 967 } 968 testKnownSignerPermSignerInLineageMatchesStringResource()969 public void testKnownSignerPermSignerInLineageMatchesStringResource() throws Exception { 970 // The knownSigner protection flag allows an app to declare a single known trusted 971 // certificate digest using a string resource instead of a string-array resource. This test 972 // verifies the knownSigner permission is granted to a requesting app if the single trusted 973 // cert is in the requesting app's lineage. 974 assertInstallFromBuildSucceeds("v3-rsa-2048-decl-knownSigner-str-res-ec-p256-1.apk"); 975 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-companion-uses-knownSigner.apk"); 976 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 977 } 978 testKnownSignerPermSignerInLineageMatchesStringConst()979 public void testKnownSignerPermSignerInLineageMatchesStringConst() throws Exception { 980 // The knownSigner protection flag allows an app to declare a single known trusted 981 // certificate digest using a string constant as the knownCerts attribute value instead of a 982 // resource. This test verifies the knownSigner permission is granted to a requesting app if 983 // the single trusted cert is in the requesting app's lineage. 984 assertInstallFromBuildSucceeds("v3-rsa-2048-decl-knownSigner-str-const-ec-p256-1.apk"); 985 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-companion-uses-knownSigner.apk"); 986 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 987 } 988 testInstallV3SigPermDoubleDefNewerSucceeds()989 public void testInstallV3SigPermDoubleDefNewerSucceeds() throws Exception { 990 // make sure that if an app defines a signature permission already defined by another app, 991 // it successfully installs if the other app's signing cert is in its past signing certs and 992 // the signature permission capability is granted 993 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk"); 994 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-permdef-companion.apk"); 995 } 996 testInstallV3SigPermDoubleDefOlderSucceeds()997 public void testInstallV3SigPermDoubleDefOlderSucceeds() throws Exception { 998 // make sure that if an app defines a signature permission already defined by another app, 999 // it successfully installs if it is in the other app's past signing certs and the signature 1000 // permission capability is granted 1001 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-permdef-companion.apk"); 1002 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk"); 1003 } 1004 testInstallV3SigPermDoubleDefNewerNoCapFails()1005 public void testInstallV3SigPermDoubleDefNewerNoCapFails() throws Exception { 1006 // make sure that if an app defines a signature permission already defined by another app, 1007 // it fails to install if the other app's signing cert is in its past signing certs but the 1008 // signature permission capability is not granted 1009 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk"); 1010 assertInstallFails( 1011 "v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-no-perm-cap-permdef-companion.apk"); 1012 } 1013 testInstallV3SigPermDoubleDefOlderNoCapFails()1014 public void testInstallV3SigPermDoubleDefOlderNoCapFails() throws Exception { 1015 // make sure that if an app defines a signature permission already defined by another app, 1016 // it fails to install if it is in the other app's past signing certs but the signature 1017 // permission capability is not granted 1018 assertInstallSucceeds( 1019 "v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-no-perm-cap-permdef-companion.apk"); 1020 assertInstallFails("v3-rsa-pkcs1-sha256-2048-1-permdef.apk"); 1021 } 1022 testInstallV3SigPermDoubleDefSameNoCapSucceeds()1023 public void testInstallV3SigPermDoubleDefSameNoCapSucceeds() throws Exception { 1024 // make sure that if an app defines a signature permission already defined by another app, 1025 // it installs successfully when signed by the same certificate, even if the original app 1026 // does not grant signature capabilities to its past certs 1027 assertInstallSucceeds( 1028 "v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-no-perm-cap-permdef-companion.apk"); 1029 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-permdef.apk"); 1030 } 1031 testInstallV3KeyRotationGetSignatures()1032 public void testInstallV3KeyRotationGetSignatures() throws Exception { 1033 // tests that a PackageInfo w/GET_SIGNATURES flag returns the older cert 1034 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 1035 Utils.runDeviceTests( 1036 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testGetSignaturesShowsOld"); 1037 } 1038 testInstallV3KeyRotationGetSigningCertificates()1039 public void testInstallV3KeyRotationGetSigningCertificates() throws Exception { 1040 // tests that a PackageInfo w/GET_SIGNING_CERTIFICATES flag returns the old and new certs 1041 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 1042 Utils.runDeviceTests( 1043 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1044 "testGetSigningCertificatesShowsAll"); 1045 } 1046 testInstallV3KeyRotationGetApkContentsSigners()1047 public void testInstallV3KeyRotationGetApkContentsSigners() throws Exception { 1048 // The GET_SIGNING_CERTIFICATES flag results in a PackageInfo object returned with a 1049 // SigningInfo instance that can be used to query all certificates in the lineage or only 1050 // the current signer(s) via getApkContentsSigners. This test verifies when a V3 signed 1051 // package with a rotated key is queried getApkContentsSigners only returns the current 1052 // signer. 1053 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-default-caps.apk"); 1054 Utils.runDeviceTests( 1055 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1056 "testGetApkContentsSignersShowsCurrent"); 1057 } 1058 testInstallV2MultipleSignersGetApkContentsSigners()1059 public void testInstallV2MultipleSignersGetApkContentsSigners() throws Exception { 1060 // Similar to the above test, but verifies when an APK is signed with two V2 signers 1061 // getApkContentsSigners returns both of the V2 signers. 1062 assertInstallFromBuildSucceeds("v1v2-ec-p256-two-signers-targetSdk-30.apk"); 1063 Utils.runDeviceTests( 1064 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1065 "testGetApkContentsSignersShowsMultipleSigners"); 1066 } 1067 testInstallV3MultipleSignersInLineageGetSigningCertificateHistory()1068 public void testInstallV3MultipleSignersInLineageGetSigningCertificateHistory() 1069 throws Exception { 1070 // The APK used for this test is signed with a lineage containing 5 keys in the signing 1071 // history; this test verifies SigningInfo#getSigningCertificateHistory returns all of an 1072 // APKs signers in their order of rotation. 1073 assertInstallFromBuildSucceeds("v3-ec-p256-with-por-1_2_3_4_5-default-caps.apk"); 1074 Utils.runDeviceTests( 1075 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1076 "testGetSigningCertificateHistoryReturnsSignersInOrder"); 1077 } 1078 testInstallV3KeyRotationHasSigningCertificate()1079 public void testInstallV3KeyRotationHasSigningCertificate() throws Exception { 1080 // tests that hasSigningCertificate() recognizes past and current signing certs 1081 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 1082 Utils.runDeviceTests( 1083 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1084 "testHasSigningCertificate"); 1085 } 1086 testInstallV3KeyRotationHasSigningCertificateSha256()1087 public void testInstallV3KeyRotationHasSigningCertificateSha256() throws Exception { 1088 // tests that hasSigningCertificate() recognizes past and current signing certs by sha256 1089 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 1090 Utils.runDeviceTests( 1091 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1092 "testHasSigningCertificateSha256"); 1093 } 1094 testInstallV3KeyRotationHasSigningCertificateByUid()1095 public void testInstallV3KeyRotationHasSigningCertificateByUid() throws Exception { 1096 // tests that hasSigningCertificate() recognizes past and current signing certs by uid 1097 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 1098 Utils.runDeviceTests( 1099 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1100 "testHasSigningCertificateByUid"); 1101 } 1102 testInstallV3KeyRotationHasSigningCertificateByUidSha256()1103 public void testInstallV3KeyRotationHasSigningCertificateByUidSha256() throws Exception { 1104 // tests that hasSigningCertificate() recognizes past and current signing certs by uid 1105 // and sha256 1106 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 1107 Utils.runDeviceTests( 1108 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1109 "testHasSigningCertificateByUidSha256"); 1110 } 1111 testInstallV3KeyRotationHasDuplicateSigningCertificateHistory()1112 public void testInstallV3KeyRotationHasDuplicateSigningCertificateHistory() throws Exception { 1113 // tests that an app's proof-of-rotation signing history cannot contain the same certificate 1114 // more than once. 1115 assertInstallFails("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2_2-full-caps.apk"); 1116 } 1117 testInstallV3HasMultipleSigners()1118 public void testInstallV3HasMultipleSigners() throws Exception { 1119 // tests that an app can't be signed by multiple signers when using v3 signature scheme 1120 assertInstallFails("v3-rsa-pkcs1-sha256-2048-1_and_2.apk"); 1121 } 1122 testInstallV3HasMultiplePlatformSigners()1123 public void testInstallV3HasMultiplePlatformSigners() throws Exception { 1124 // tests that an app can be signed by multiple v3 signers if they target different platform 1125 // versions 1126 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1_P_and_2_Qplus.apk"); 1127 } 1128 testSharedKeyInSeparateLineageRetainsDeclaredCapabilities()1129 public void testSharedKeyInSeparateLineageRetainsDeclaredCapabilities() throws Exception { 1130 // This test verifies when a key is used in the signing lineage of multiple apps each 1131 // instance of the key retains its declared capabilities. 1132 1133 // This app has granted the PERMISSION capability to the previous signer in the lineage 1134 // but has revoked the SHARED_USER_ID capability. 1135 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-shUid-cap-declperm2.apk"); 1136 // This app has granted the SHARED_USER_ID capability to the previous signer in the lineage 1137 // but has revoked the PERMISSION capability. 1138 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-perm-cap-sharedUid.apk"); 1139 1140 // Reboot the device to ensure that the capabilities written to packages.xml are properly 1141 // assigned to the packages installed above; it's possible immediately after a package 1142 // install the capabilities are as declared, but then during the reboot shared signing 1143 // keys also share the initial declared capabilities. 1144 getDevice().reboot(); 1145 1146 // This app is signed with the original shared signing key in the lineage and is part of the 1147 // sharedUserId; since the other app in this sharedUserId has granted the required 1148 // capability in the lineage the install should succeed. 1149 assertInstallFromBuildSucceeds("v3-ec-p256-1-sharedUid-companion2.apk"); 1150 // This app is signed with the original shared signing key in the lineage and requests the 1151 // signature permission declared by the test app above. Since that app granted the 1152 // PERMISSION capability to the previous signer in the lineage this app should have the 1153 // permission granted. 1154 assertInstallFromBuildSucceeds("v3-ec-p256-1-companion-usesperm.apk"); 1155 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 1156 } 1157 1158 @CddTest(requirement="4/C-0-2") testV31TargetTPlatformUsesRotatedKey()1159 public void testV31TargetTPlatformUsesRotatedKey() throws Exception { 1160 // The v3.1 signature block is intended to allow applications to target T+ for APK signing 1161 // key rotation without needing multi-targeting APKs. This test verifies a standard APK 1162 // install with the rotated key in the v3.1 signing block targeting T is recognized by the 1163 // platform, and this rotated key is used as the signing identity. 1164 assertInstallSucceeds("v31-ec-p256_2-tgt-33.apk"); 1165 Utils.runDeviceTests( 1166 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1167 "testUsingRotatedSigner"); 1168 } 1169 1170 @CddTest(requirement="4/C-0-2") testV31TargetLaterThanDevicePlatformUsesOriginalKey()1171 public void testV31TargetLaterThanDevicePlatformUsesOriginalKey() throws Exception { 1172 // The v3.1 signature block allows targeting SDK versions later than T for rotation; for 1173 // this test a target of 100001 is used assuming it will be beyond the platform's version. 1174 // Since the target version for rotation is beyond the platform's version the original 1175 // signer from the v3.0 block should be used. 1176 assertInstallSucceeds("v31-ec-p256_2-tgt-100001.apk"); 1177 Utils.runDeviceTests( 1178 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1179 "testUsingOriginalSigner"); 1180 } 1181 1182 @CddTest(requirement="4/C-0-2") testV31BlockStrippedWithV3StrippingProtectionAttrSet()1183 public void testV31BlockStrippedWithV3StrippingProtectionAttrSet() throws Exception { 1184 // With the introduction of the v3.1 signature scheme, a new stripping protection attribute 1185 // has been added to the v3.0 signer to protect against stripping and modification of the 1186 // v3.1 signing block. This test verifies a stripped v3.1 block is detected when the v3.0 1187 // stripping protection attribute is set. 1188 assertInstallFails("v31-block-stripped-v3-attr-value-33.apk"); 1189 } 1190 1191 @CddTest(requirement="4/C-0-2") testV31BlockWithMultipleSignersUsesCorrectSigner()1192 public void testV31BlockWithMultipleSignersUsesCorrectSigner() throws Exception { 1193 // All of the APKs for this test use multiple v3.1 signers; those targeting SDK versions 1194 // expected to be outside the version of a device under test use the original signer, and 1195 // those targeting an expected range for a device use the rotated key. This test is 1196 // intended to ensure the signer with the min / max SDK version that matches the device 1197 // SDK version is used. 1198 1199 // The APK used for this test contains two signers in the v3.1 signing block. The first 1200 // has a range from 100001 to Integer.MAX_VALUE and is using the original signing key; 1201 // the second targets 33 to 100000 using the rotated key. 1202 assertInstallSucceeds("v31-ec-p256_2-tgt-33-ec-p256-tgt-100001.apk"); 1203 Utils.runDeviceTests( 1204 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1205 "testUsingRotatedSigner"); 1206 uninstallPackage(); 1207 1208 // The APK for this test contains two signers in the v3.1 block, one targeting SDK versions 1209 // 1 to 27 using the original signer, and the other targeting 33+ using the rotated signer. 1210 assertInstallSucceeds("v31-ec-p256_2-tgt-33-ec-p256-tgt-1-27.apk"); 1211 Utils.runDeviceTests( 1212 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1213 "testUsingRotatedSigner"); 1214 uninstallPackage(); 1215 1216 // This APK combines the extra signers from the APKs above, one targeting 1 to 27 with the 1217 // original signing key, another targeting 100001+ with the original signing key, and the 1218 // last targeting 33 to 100000 with the rotated key. 1219 assertInstallSucceeds("v31-ec-p256_2-tgt-33-ec-p256-tgt-1-27-and-100001.apk"); 1220 Utils.runDeviceTests( 1221 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1222 "testUsingRotatedSigner"); 1223 } 1224 1225 @CddTest(requirement="4/C-0-2") testV31UpdateV3ToFromV31Succeeds()1226 public void testV31UpdateV3ToFromV31Succeeds() throws Exception { 1227 // Since the v3.1 block is just intended to allow targeting SDK versions T and later for 1228 // rotation, an APK signed with the rotated key in a v3.0 signing block should support 1229 // updates to an APK signed with the same signing key in a v3.1 signing block. 1230 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-default-caps.apk"); 1231 assertInstallSucceeds("v31-ec-p256_2-tgt-33.apk"); 1232 uninstallPackage(); 1233 1234 // Similarly an APK signed with the rotated key in a v3.1 signing block should support 1235 // updates to an APK signed with the same signing key in a v3.0 signing block. 1236 assertInstallSucceeds("v31-ec-p256_2-tgt-33.apk"); 1237 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-default-caps.apk"); 1238 uninstallPackage(); 1239 } 1240 1241 @CddTest(requirement="4/C-0-2") testV31RotationTargetModifiedReportedByV3()1242 public void testV31RotationTargetModifiedReportedByV3() throws Exception { 1243 // When determining if a signer in the v3.1 signing block should be applied, the min / max 1244 // SDK versions from the signer are compared against the device's SDK version; if the device 1245 // is not within the signer's range then the block is skipped, other v3.1 blocks are 1246 // checked, and finally the v3.0 block is used. The v3.0 signer block contains an additional 1247 // attribute with the rotation-min-sdk-version that was expected in the v3.1 signing 1248 // block; if this attribute's value does not match what was found in the v3.1 block the 1249 // APK should fail to install. 1250 assertInstallFails("v31-ec-p256_2-tgt-33-modified.apk"); 1251 } 1252 1253 @CddTest(requirement="4/C-0-2") testV31RotationTargetsDevRelease()1254 public void testV31RotationTargetsDevRelease() throws Exception { 1255 // The v3.1 signature scheme allows targeting a platform release under development through 1256 // the use of a rotation-targets-dev-release additional attribute. Since a platform under 1257 // development shares the same SDK version as the most recently released platform, the 1258 // attribute is used by the platform to determine if a signer block should be applied. If 1259 // the signer's minSdkVersion is the same as the device's SDK version and this attribute 1260 // is set, then the platform will check the value of ro.build.version.codename; a value of 1261 // "REL" indicates the platform is a release platform, so the current signer block will not 1262 // be used. During T's development, the SDK version is 31 and the codename is not "REL", so 1263 // this test APK will install on T during development as well as after its release since 1264 // the SDK version will be bumped at that point. 1265 assertInstallSucceeds("v31-ec-p256_2-tgt-31-dev-release.apk"); 1266 } 1267 1268 testInstallTargetSdk30WithV1Signers()1269 public void testInstallTargetSdk30WithV1Signers() throws Exception { 1270 // An app targeting SDK version >= 30 must have at least a V2 signature; this test verifies 1271 // an app targeting SDK version 30 with only a V1 signature fails to install. 1272 assertInstallFails("v1-ec-p256-two-signers-targetSdk-30.apk"); 1273 } 1274 testInstallTargetSdk30WithV1V2Signers()1275 public void testInstallTargetSdk30WithV1V2Signers() throws Exception { 1276 // An app targeting SDK version >= 30 must have at least a V2 signature; this test verifies 1277 // that an app targeting SDK version 30 with both a V1 and V2 signature installs 1278 // successfully. 1279 installApkFromBuild("v1v2-ec-p256-two-signers-targetSdk-30.apk"); 1280 } 1281 testInstallV4WithV2Signer()1282 public void testInstallV4WithV2Signer() throws Exception { 1283 // V4 is only enabled on devices with Incremental feature 1284 if (!hasIncrementalFeature()) { 1285 return; 1286 } 1287 1288 // APK generated with: 1289 // apksigner sign --v2-signing-enabled true --v3-signing-enabled false --v4-signing-enabled 1290 assertInstallV4Succeeds("v4-digest-v2.apk"); 1291 } 1292 testInstallV4WithV3Signer()1293 public void testInstallV4WithV3Signer() throws Exception { 1294 // V4 is only enabled on devices with Incremental feature 1295 if (!hasIncrementalFeature()) { 1296 return; 1297 } 1298 1299 // APK generated with: 1300 // apksigner sign --v2-signing-enabled false --v3-signing-enabled true --v4-signing-enabled 1301 assertInstallV4Succeeds("v4-digest-v3.apk"); 1302 } 1303 testInstallV4WithV2V3Signer()1304 public void testInstallV4WithV2V3Signer() throws Exception { 1305 // V4 is only enabled on devices with Incremental feature 1306 if (!hasIncrementalFeature()) { 1307 return; 1308 } 1309 1310 // APK generated with: 1311 // apksigner sign --v2-signing-enabled true --v3-signing-enabled true --v4-signing-enabled 1312 assertInstallV4Succeeds("v4-digest-v2v3.apk"); 1313 } 1314 testInstallV4WithV2NoVeritySigner()1315 public void testInstallV4WithV2NoVeritySigner() throws Exception { 1316 // V4 is only enabled on devices with Incremental feature 1317 if (!hasIncrementalFeature()) { 1318 return; 1319 } 1320 1321 // APK generated with: 1322 // --v2-signing-enabled true --v3-signing-enabled false --v4-signing-enabled 1323 // Full commands in generate-apks.sh 1324 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha256withDSA.apk"); 1325 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha256withEC.apk"); 1326 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha256withRSA.apk"); 1327 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha512withEC.apk"); 1328 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha512withRSA.apk"); 1329 } 1330 testInstallV4WithV2VeritySigner()1331 public void testInstallV4WithV2VeritySigner() throws Exception { 1332 // V4 is only enabled on devices with Incremental feature 1333 if (!hasIncrementalFeature()) { 1334 return; 1335 } 1336 1337 // APK generated with: 1338 // --v2-signing-enabled true --v3-signing-enabled false 1339 // --v4-signing-enabled --verity-enabled 1340 // Full commands in generate-apks.sh 1341 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha256withDSA-Verity.apk"); 1342 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha256withEC-Verity.apk"); 1343 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha256withRSA-Verity.apk"); 1344 } 1345 testInstallV4WithV3NoVeritySigner()1346 public void testInstallV4WithV3NoVeritySigner() throws Exception { 1347 // V4 is only enabled on devices with Incremental feature 1348 if (!hasIncrementalFeature()) { 1349 return; 1350 } 1351 1352 // APK generated with: 1353 // --v2-signing-enabled false --v3-signing-enabled true --v4-signing-enabled 1354 // Full commands in generate-apks.sh 1355 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha256withDSA.apk"); 1356 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha256withEC.apk"); 1357 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha256withRSA.apk"); 1358 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha512withEC.apk"); 1359 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha512withRSA.apk"); 1360 } 1361 testInstallV4WithV3VeritySigner()1362 public void testInstallV4WithV3VeritySigner() throws Exception { 1363 // V4 is only enabled on devices with Incremental feature 1364 if (!hasIncrementalFeature()) { 1365 return; 1366 } 1367 1368 // APK generated with: 1369 // --v2-signing-enabled false --v3-signing-enabled true 1370 // --v4-signing-enabled --verity-enabled 1371 // Full commands in generate-apks.sh 1372 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha256withDSA-Verity.apk"); 1373 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha256withEC-Verity.apk"); 1374 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha256withRSA-Verity.apk"); 1375 } 1376 testInstallV4WithV2SignerDoesNotVerify()1377 public void testInstallV4WithV2SignerDoesNotVerify() throws Exception { 1378 // V4 is only enabled on devices with Incremental feature 1379 if (!hasIncrementalFeature()) { 1380 return; 1381 } 1382 1383 // APKs generated with: 1384 // apksigner sign -v2-signing-enabled true --v3-signing-enabled false --v4-signing-enabled 1385 1386 // Malformed v4 signature - first byte of v4 signing_info.signature is flipped 1387 assertInstallV4FailsWithError("v4-digest-v2-badv4signature.apk", "did not verify"); 1388 // Malformed digest - first byte of v4 signing_info.apk_digest is flipped 1389 assertInstallV4FailsWithError("v4-digest-v2-badv2digest.apk", "did not verify"); 1390 } 1391 testInstallV4WithV3SignerDoesNotVerify()1392 public void testInstallV4WithV3SignerDoesNotVerify() throws Exception { 1393 // V4 is only enabled on devices with Incremental feature 1394 if (!hasIncrementalFeature()) { 1395 return; 1396 } 1397 1398 // APKs generated with: 1399 // apksigner sign -v2-signing-enabled false --v3-signing-enabled true --v4-signing-enabled 1400 1401 // Malformed v4 signature - first byte of v4 signing_info.signature is flipped 1402 assertInstallV4FailsWithError("v4-digest-v3-badv4signature.apk", "did not verify"); 1403 1404 // Malformed digest - first byte of v4 signing_info.apk_digest is flipped 1405 assertInstallV4FailsWithError("v4-digest-v3-badv3digest.apk", "did not verify"); 1406 1407 } 1408 testInstallV4WithV2V3SignerDoesNotVerify()1409 public void testInstallV4WithV2V3SignerDoesNotVerify() throws Exception { 1410 // V4 is only enabled on devices with Incremental feature 1411 if (!hasIncrementalFeature()) { 1412 return; 1413 } 1414 1415 // APKs generated with: 1416 // apksigner sign -v2-signing-enabled true --v3-signing-enabled true --v4-signing-enabled 1417 1418 // Malformed v4 signature - first byte of v4 signing_info.signature is flipped 1419 assertInstallV4FailsWithError("v4-digest-v2v3-badv4signature.apk", "did not verify"); 1420 1421 // Malformed digest - first byte of v4 signing_info.apk_digest is flipped 1422 assertInstallV4FailsWithError("v4-digest-v2v3-badv2v3digest.apk", "did not verify"); 1423 } 1424 testInstallV4With128BytesAdditionalDataSucceeds()1425 public void testInstallV4With128BytesAdditionalDataSucceeds() throws Exception { 1426 // V4 is only enabled on devices with Incremental feature 1427 if (!hasIncrementalFeature()) { 1428 return; 1429 } 1430 1431 // Editing apksigner to fill additional data of size 128 bytes. 1432 assertInstallV4Succeeds("v4-digest-v3-128bytes-additional-data.apk"); 1433 } 1434 testInstallV4With256BytesAdditionalDataFails()1435 public void testInstallV4With256BytesAdditionalDataFails() throws Exception { 1436 // V4 is only enabled on devices with Incremental feature 1437 if (!hasIncrementalFeature()) { 1438 return; 1439 } 1440 1441 // Editing apksigner to fill additional data of size 256 bytes. 1442 assertInstallV4FailsWithError("v4-digest-v3-256bytes-additional-data.apk", 1443 "additionalData has to be at most 128 bytes"); 1444 } 1445 testInstallV4With10MBytesAdditionalDataFails()1446 public void testInstallV4With10MBytesAdditionalDataFails() throws Exception { 1447 // V4 is only enabled on devices with Incremental feature 1448 if (!hasIncrementalFeature()) { 1449 return; 1450 } 1451 1452 // Editing apksigner to fill additional data of size 10 * 1024 * 1024 bytes. 1453 assertInstallV4FailsWithError("v4-digest-v3-10mbytes-additional-data.apk", 1454 "Failure"); 1455 } 1456 testInstallV4WithWrongBlockSize()1457 public void testInstallV4WithWrongBlockSize() throws Exception { 1458 // V4 is only enabled on devices with Incremental feature 1459 if (!hasIncrementalFeature()) { 1460 return; 1461 } 1462 1463 // Editing apksigner with the wrong block size in the v4 signature. 1464 assertInstallV4FailsWithError("v4-digest-v3-wrong-block-size.apk", 1465 "did not verify"); 1466 } 1467 testInstallV4WithDifferentBlockSize()1468 public void testInstallV4WithDifferentBlockSize() throws Exception { 1469 // V4 is only enabled on devices with Incremental feature 1470 if (!hasIncrementalFeature()) { 1471 return; 1472 } 1473 1474 // Editing apksigner with the different block size (2048 instead of 4096). 1475 assertInstallV4FailsWithError("v4-digest-v3-merkle-tree-different-block-size.apk", 1476 "Unsupported log2BlockSize: 11"); 1477 } 1478 testInstallV4WithWrongRawRootHash()1479 public void testInstallV4WithWrongRawRootHash() throws Exception { 1480 // V4 is only enabled on devices with Incremental feature 1481 if (!hasIncrementalFeature()) { 1482 return; 1483 } 1484 1485 // Editing apksigner with the wrong raw root hash in the v4 signature. 1486 assertInstallV4FailsWithError("v4-digest-v3-wrong-raw-root-hash.apk", "Failure"); 1487 } 1488 testInstallV4WithWrongSignatureBytes()1489 public void testInstallV4WithWrongSignatureBytes() throws Exception { 1490 // V4 is only enabled on devices with Incremental feature 1491 if (!hasIncrementalFeature()) { 1492 return; 1493 } 1494 1495 // Editing apksigner with the wrong signature bytes in the v4 signature. 1496 assertInstallV4FailsWithError("v4-digest-v3-wrong-sig-bytes.apk", 1497 "did not verify"); 1498 } 1499 testInstallV4WithWrongSignatureBytesSize()1500 public void testInstallV4WithWrongSignatureBytesSize() throws Exception { 1501 // V4 is only enabled on devices with Incremental feature 1502 if (!hasIncrementalFeature()) { 1503 return; 1504 } 1505 1506 // Editing apksigner with the wrong signature byte size in the v4 signature. 1507 assertInstallV4FailsWithError("v4-digest-v3-wrong-sig-bytes-size.apk", 1508 "Failure"); 1509 } 1510 testInstallV4WithNoMerkleTree()1511 public void testInstallV4WithNoMerkleTree() throws Exception { 1512 // V4 is only enabled on devices with Incremental feature 1513 if (!hasIncrementalFeature()) { 1514 return; 1515 } 1516 1517 // Editing apksigner to not include the Merkle tree. 1518 assertInstallV4FailsWithError("v4-digest-v3-no-merkle-tree.apk", 1519 "Failure"); 1520 } 1521 testInstallV4WithWithTrailingDataInMerkleTree()1522 public void testInstallV4WithWithTrailingDataInMerkleTree() throws Exception { 1523 // V4 is only enabled on devices with Incremental feature 1524 if (!hasIncrementalFeature()) { 1525 return; 1526 } 1527 1528 // Editing apksigner to add trailing data after the Merkle tree 1529 assertInstallV4FailsWithError("v4-digest-v3-merkle-tree-1mb-trailing-data.apk", 1530 "Failure"); 1531 } 1532 testInstallV4WithMerkleTreeBitsFlipped()1533 public void testInstallV4WithMerkleTreeBitsFlipped() throws Exception { 1534 // V4 is only enabled on devices with Incremental feature 1535 if (!hasIncrementalFeature()) { 1536 return; 1537 } 1538 1539 // Editing apksigner to flip few bits in the only node of the Merkle tree of a small app. 1540 assertInstallV4FailsWithError("v4-digest-v3-merkle-tree-bit-flipped.apk", 1541 "Failed to parse"); 1542 } 1543 testV4IncToV3NonIncSameKeyUpgradeSucceeds()1544 public void testV4IncToV3NonIncSameKeyUpgradeSucceeds() throws Exception { 1545 // V4 is only enabled on devices with Incremental feature 1546 if (!hasIncrementalFeature()) { 1547 return; 1548 } 1549 1550 // See cts/hostsidetests/appsecurity/res/pkgsigverify/generate-apks.sh for the command 1551 // to generate the apks 1552 assertInstallV4Succeeds("v4-inc-to-v3-noninc-ec-p256-appv1.apk"); 1553 1554 // non-incremental upgrade with the same key. 1555 assertInstallSucceeds("v4-inc-to-v3-noninc-ec-p256-appv2.apk"); 1556 } 1557 testV4IncToV3NonIncMismatchingKeyUpgradeFails()1558 public void testV4IncToV3NonIncMismatchingKeyUpgradeFails() throws Exception { 1559 // V4 is only enabled on devices with Incremental feature 1560 if (!hasIncrementalFeature()) { 1561 return; 1562 } 1563 1564 // See cts/hostsidetests/appsecurity/res/pkgsigverify/generate-apks.sh for the command 1565 // to generate the apks 1566 assertInstallV4Succeeds("v4-inc-to-v3-noninc-ec-p256-appv1.apk"); 1567 1568 // non-incremental upgrade with a mismatching key. 1569 assertInstallFailsWithError("v4-inc-to-v3-noninc-ec-p384-appv2.apk", 1570 "signatures do not match newer version"); 1571 } 1572 testV4IncToV3NonIncRotatedKeyUpgradeSucceeds()1573 public void testV4IncToV3NonIncRotatedKeyUpgradeSucceeds() throws Exception { 1574 // V4 is only enabled on devices with Incremental feature 1575 if (!hasIncrementalFeature()) { 1576 return; 1577 } 1578 1579 // See cts/hostsidetests/appsecurity/res/pkgsigverify/generate-apks.sh for the command 1580 // to generate the apks 1581 assertInstallV4Succeeds("v4-inc-to-v3-noninc-ec-p256-appv1.apk"); 1582 1583 // non-incremental upgrade with key rotation. 1584 assertInstallSucceeds("v4-inc-to-v3-noninc-ec-p384-rotated-ec-p256-appv2.apk"); 1585 } 1586 testV4IncToV3NonIncMismatchedRotatedKeyUpgradeFails()1587 public void testV4IncToV3NonIncMismatchedRotatedKeyUpgradeFails() throws Exception { 1588 // V4 is only enabled on devices with Incremental feature 1589 if (!hasIncrementalFeature()) { 1590 return; 1591 } 1592 1593 // See cts/hostsidetests/appsecurity/res/pkgsigverify/generate-apks.sh for the command 1594 // to generate the apks 1595 assertInstallV4Succeeds("v4-inc-to-v3-noninc-dsa-3072-appv1.apk"); 1596 1597 // non-incremental upgrade with key rotation mismatch with key used in app v1. 1598 assertInstallFailsWithError("v4-inc-to-v3-noninc-ec-p384-rotated-ec-p256-appv2.apk", 1599 "signatures do not match newer version"); 1600 } 1601 testV4IncToV2NonIncSameKeyUpgradeSucceeds()1602 public void testV4IncToV2NonIncSameKeyUpgradeSucceeds() throws Exception { 1603 // V4 is only enabled on devices with Incremental feature 1604 if (!hasIncrementalFeature()) { 1605 return; 1606 } 1607 1608 // See cts/hostsidetests/appsecurity/res/pkgsigverify/generate-apks.sh for the command 1609 // to generate the apks 1610 assertInstallV4Succeeds("v4-inc-to-v2-noninc-ec-p256-appv1.apk"); 1611 1612 // non-incremental upgrade with the same key. 1613 assertInstallSucceeds("v4-inc-to-v2-noninc-ec-p256-appv2.apk"); 1614 } 1615 testV4IncToV2NonIncMismatchingKeyUpgradeFails()1616 public void testV4IncToV2NonIncMismatchingKeyUpgradeFails() throws Exception { 1617 // V4 is only enabled on devices with Incremental feature 1618 if (!hasIncrementalFeature()) { 1619 return; 1620 } 1621 1622 // See cts/hostsidetests/appsecurity/res/pkgsigverify/generate-apks.sh for the command 1623 // to generate the apks 1624 assertInstallV4Succeeds("v4-inc-to-v2-noninc-ec-p256-appv1.apk"); 1625 1626 // non-incremental upgrade with a mismatching key. 1627 assertInstallFailsWithError("v4-inc-to-v2-noninc-ec-p384-appv2.apk", 1628 "signatures do not match newer version"); 1629 } 1630 testInstallV4UpdateAfterRotation()1631 public void testInstallV4UpdateAfterRotation() throws Exception { 1632 // V4 is only enabled on devices with Incremental feature 1633 if (!hasIncrementalFeature()) { 1634 return; 1635 } 1636 1637 // This test performs an end to end verification of the update of an app with a rotated 1638 // key. The app under test exports a bound service that performs its own PackageManager key 1639 // rotation API verification, and the instrumentation test binds to the service and invokes 1640 // the verifySignatures method to verify that the key rotation APIs return the expected 1641 // results. The instrumentation test app is signed with the same key and lineage as the 1642 // app under test to also provide a second app that can be used for the checkSignatures 1643 // verification. 1644 1645 // Install the initial versions of the apps; the test method verifies the app under test is 1646 // signed with the original signing key. 1647 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService.apk"); 1648 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 1649 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 1650 "verifySignatures_noRotation_succeeds"); 1651 1652 // Install the second version of the app signed with the rotated key. This test verifies the 1653 // app still functions as expected after the update with the rotated key. The 1654 // instrumentation test app is not updated here to allow verification of the pre-key 1655 // rotation behavior for the checkSignatures APIs. These APIs should behave similar to the 1656 // GET_SIGNATURES flag in that if one or both apps have a signing lineage if the oldest 1657 // signers in the lineage match then the methods should return that the signatures match 1658 // even if one is signed with a newer key in the lineage. 1659 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService_v2.apk"); 1660 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 1661 "verifySignatures_withRotation_succeeds"); 1662 1663 // Installs the third version of the app under test and the instrumentation test, both 1664 // signed with the same rotated key and lineage. This test is intended to verify that the 1665 // app can still be updated and function as expected after an update with a rotated key. 1666 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService_v3.apk"); 1667 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest_v2.apk"); 1668 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 1669 "verifySignatures_withRotation_succeeds"); 1670 } 1671 hasIncrementalFeature()1672 private boolean hasIncrementalFeature() throws Exception { 1673 return "true\n".equals(getDevice().executeShellCommand( 1674 "pm has-feature android.software.incremental_delivery")); 1675 } 1676 assertInstallSucceeds(String apkFilenameInResources)1677 private void assertInstallSucceeds(String apkFilenameInResources) throws Exception { 1678 String installResult = installPackageFromResource(apkFilenameInResources); 1679 if (installResult != null) { 1680 fail("Failed to install " + apkFilenameInResources + ": " + installResult); 1681 } 1682 } 1683 assertInstallEphemeralSucceeds(String apkFilenameInResources)1684 private void assertInstallEphemeralSucceeds(String apkFilenameInResources) throws Exception { 1685 String installResult = installEphemeralPackageFromResource(apkFilenameInResources); 1686 if (installResult != null) { 1687 fail("Failed to install " + apkFilenameInResources + ": " + installResult); 1688 } 1689 } 1690 assertInstallSucceedsForEach( String apkFilenamePatternInResources, String[] args)1691 private void assertInstallSucceedsForEach( 1692 String apkFilenamePatternInResources, String[] args) throws Exception { 1693 for (String arg : args) { 1694 String apkFilenameInResources = 1695 String.format(Locale.US, apkFilenamePatternInResources, arg); 1696 String installResult = installPackageFromResource(apkFilenameInResources); 1697 if (installResult != null) { 1698 fail("Failed to install " + apkFilenameInResources + ": " + installResult); 1699 } 1700 try { 1701 uninstallPackage(); 1702 } catch (Exception e) { 1703 throw new RuntimeException( 1704 "Failed to uninstall after installing " + apkFilenameInResources, e); 1705 } 1706 } 1707 } 1708 assertInstallV4Succeeds(String apkFilenameInResources)1709 private void assertInstallV4Succeeds(String apkFilenameInResources) throws Exception { 1710 String installResult = installV4PackageFromResource(apkFilenameInResources); 1711 if (!installResult.equals("Success\n")) { 1712 fail("Failed to install " + apkFilenameInResources + ": " + installResult); 1713 } 1714 } 1715 assertInstallV4FromBuildSucceeds(String apkName)1716 private void assertInstallV4FromBuildSucceeds(String apkName) throws Exception { 1717 String installResult = installV4PackageFromBuild(apkName); 1718 if (!installResult.equals("Success\n")) { 1719 fail("Failed to install " + apkName + ": " + installResult); 1720 } 1721 } 1722 assertInstallV4SucceedsAndUninstall(String apkFilenameInResources)1723 private void assertInstallV4SucceedsAndUninstall(String apkFilenameInResources) 1724 throws Exception { 1725 assertInstallV4Succeeds(apkFilenameInResources); 1726 try { 1727 uninstallPackage(); 1728 } catch (Exception e) { 1729 throw new RuntimeException( 1730 "Failed to uninstall after installing " + apkFilenameInResources, e); 1731 } 1732 } 1733 assertInstallV4FailsWithError(String apkFilenameInResources, String errorSubstring)1734 private void assertInstallV4FailsWithError(String apkFilenameInResources, String errorSubstring) 1735 throws Exception { 1736 String installResult = installV4PackageFromResource(apkFilenameInResources); 1737 if (installResult.equals("Success\n")) { 1738 fail("Install of " + apkFilenameInResources + " succeeded but was expected to fail" 1739 + " with \"" + errorSubstring + "\""); 1740 } 1741 assertContains( 1742 "Install failure message of " + apkFilenameInResources, 1743 errorSubstring, 1744 installResult); 1745 } 1746 assertInstallFailsWithError( String apkFilenameInResources, String errorSubstring)1747 private void assertInstallFailsWithError( 1748 String apkFilenameInResources, String errorSubstring) throws Exception { 1749 String installResult = installPackageFromResource(apkFilenameInResources); 1750 if (installResult == null) { 1751 fail("Install of " + apkFilenameInResources + " succeeded but was expected to fail" 1752 + " with \"" + errorSubstring + "\""); 1753 } 1754 assertContains( 1755 "Install failure message of " + apkFilenameInResources, 1756 errorSubstring, 1757 installResult); 1758 } 1759 assertInstallEphemeralFailsWithError( String apkFilenameInResources, String errorSubstring)1760 private void assertInstallEphemeralFailsWithError( 1761 String apkFilenameInResources, String errorSubstring) throws Exception { 1762 String installResult = installEphemeralPackageFromResource(apkFilenameInResources); 1763 if (installResult == null) { 1764 fail("Install of " + apkFilenameInResources + " succeeded but was expected to fail" 1765 + " with \"" + errorSubstring + "\""); 1766 } 1767 assertContains( 1768 "Install failure message of " + apkFilenameInResources, 1769 errorSubstring, 1770 installResult); 1771 } 1772 assertInstallFails(String apkFilenameInResources)1773 private void assertInstallFails(String apkFilenameInResources) throws Exception { 1774 String installResult = installPackageFromResource(apkFilenameInResources); 1775 if (installResult == null) { 1776 fail("Install of " + apkFilenameInResources + " succeeded but was expected to fail"); 1777 } 1778 } 1779 assertContains(String message, String expectedSubstring, String actual)1780 private static void assertContains(String message, String expectedSubstring, String actual) { 1781 String errorPrefix = ((message != null) && (message.length() > 0)) ? (message + ": ") : ""; 1782 if (actual == null) { 1783 fail(errorPrefix + "Expected to contain \"" + expectedSubstring + "\", but was null"); 1784 } 1785 if (!actual.contains(expectedSubstring)) { 1786 fail(errorPrefix + "Expected to contain \"" + expectedSubstring + "\", but was \"" 1787 + actual + "\""); 1788 } 1789 } 1790 installDeviceTestPkg()1791 private void installDeviceTestPkg() throws Exception { 1792 assertInstallFromBuildSucceeds(DEVICE_TESTS_APK); 1793 } 1794 assertInstallFromBuildSucceeds(String apkName)1795 private void assertInstallFromBuildSucceeds(String apkName) throws Exception { 1796 String result = installApkFromBuild(apkName); 1797 assertNull("failed to install " + apkName + ", Reason: " + result, result); 1798 } 1799 assertInstallFromBuildFails(String apkName)1800 private void assertInstallFromBuildFails(String apkName) throws Exception { 1801 String result = installApkFromBuild(apkName); 1802 assertNotNull("Successfully installed " + apkName + " when failure was expected", result); 1803 } 1804 installApkFromBuild(String apkName)1805 private String installApkFromBuild(String apkName) throws Exception { 1806 CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild); 1807 File apk = buildHelper.getTestFile(apkName); 1808 return getDevice().installPackage(apk, true, INSTALL_ARG_FORCE_QUERYABLE); 1809 } 1810 installPackageFromResource(String apkFilenameInResources, boolean ephemeral)1811 private String installPackageFromResource(String apkFilenameInResources, boolean ephemeral) 1812 throws IOException, DeviceNotAvailableException { 1813 // ITestDevice.installPackage API requires the APK to be install to be a File. We thus 1814 // copy the requested resource into a temporary file, attempt to install it, and delete the 1815 // file during cleanup. 1816 File apkFile = null; 1817 try { 1818 apkFile = getFileFromResource(apkFilenameInResources); 1819 if (ephemeral) { 1820 return getDevice().installPackage(apkFile, true, "--ephemeral", 1821 INSTALL_ARG_FORCE_QUERYABLE); 1822 } else { 1823 return getDevice().installPackage(apkFile, true, INSTALL_ARG_FORCE_QUERYABLE); 1824 } 1825 } finally { 1826 cleanUpFile(apkFile); 1827 } 1828 } 1829 installV4PackageFromResource(String apkFilenameInResources)1830 private String installV4PackageFromResource(String apkFilenameInResources) 1831 throws IOException, DeviceNotAvailableException { 1832 File apkFile = null; 1833 File v4SignatureFile = null; 1834 try { 1835 apkFile = getFileFromResource(apkFilenameInResources); 1836 v4SignatureFile = getFileFromResource(apkFilenameInResources + ".idsig"); 1837 String remoteApkFilePath = pushFileToRemote(apkFile); 1838 pushFileToRemote(v4SignatureFile); 1839 return installV4Package(remoteApkFilePath); 1840 } finally { 1841 cleanUpFile(apkFile); 1842 cleanUpFile(v4SignatureFile); 1843 } 1844 } 1845 installV4PackageFromBuild(String apkName)1846 private String installV4PackageFromBuild(String apkName) 1847 throws IOException, DeviceNotAvailableException { 1848 CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild); 1849 File apkFile = buildHelper.getTestFile(apkName); 1850 File v4SignatureFile = buildHelper.getTestFile(apkName + ".idsig"); 1851 String remoteApkFilePath = pushFileToRemote(apkFile); 1852 pushFileToRemote(v4SignatureFile); 1853 return installV4Package(remoteApkFilePath); 1854 } 1855 pushFileToRemote(File localFile)1856 private String pushFileToRemote(File localFile) throws DeviceNotAvailableException { 1857 String remotePath = "/data/local/tmp/pkginstalltest-" + localFile.getName(); 1858 getDevice().pushFile(localFile, remotePath); 1859 return remotePath; 1860 } 1861 installV4Package(String remoteApkPath)1862 private String installV4Package(String remoteApkPath) 1863 throws DeviceNotAvailableException { 1864 String command = "pm install-incremental --force-queryable -t -g " + remoteApkPath; 1865 return getDevice().executeShellCommand(command); 1866 } 1867 getFileFromResource(String filenameInResources)1868 private File getFileFromResource(String filenameInResources) 1869 throws IOException, IllegalArgumentException { 1870 String fullResourceName = TEST_APK_RESOURCE_PREFIX + filenameInResources; 1871 File tempDir = FileUtil.createTempDir("pkginstalltest"); 1872 File file = new File(tempDir, filenameInResources); 1873 InputStream in = getClass().getResourceAsStream(fullResourceName); 1874 if (in == null) { 1875 throw new IllegalArgumentException("Resource not found: " + fullResourceName); 1876 } 1877 OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); 1878 byte[] buf = new byte[65536]; 1879 int chunkSize; 1880 while ((chunkSize = in.read(buf)) != -1) { 1881 out.write(buf, 0, chunkSize); 1882 } 1883 out.close(); 1884 return file; 1885 } 1886 cleanUpFile(File file)1887 private void cleanUpFile(File file) { 1888 if (file != null && file.exists()) { 1889 file.delete(); 1890 } 1891 } 1892 installPackageFromResource(String apkFilenameInResources)1893 private String installPackageFromResource(String apkFilenameInResources) 1894 throws IOException, DeviceNotAvailableException { 1895 return installPackageFromResource(apkFilenameInResources, false); 1896 } 1897 installEphemeralPackageFromResource(String apkFilenameInResources)1898 private String installEphemeralPackageFromResource(String apkFilenameInResources) 1899 throws IOException, DeviceNotAvailableException { 1900 return installPackageFromResource(apkFilenameInResources, true); 1901 } 1902 uninstallPackage()1903 private String uninstallPackage() throws DeviceNotAvailableException { 1904 String result1 = getDevice().uninstallPackage(TEST_PKG); 1905 String result2 = getDevice().uninstallPackage(TEST_PKG2); 1906 return result1 != null ? result1 : result2; 1907 } 1908 uninstallCompanionPackages()1909 private String uninstallCompanionPackages() throws DeviceNotAvailableException { 1910 String result1 = getDevice().uninstallPackage(COMPANION_TEST_PKG); 1911 String result2 = getDevice().uninstallPackage(COMPANION2_TEST_PKG); 1912 String result3 = getDevice().uninstallPackage(COMPANION3_TEST_PKG); 1913 return Stream.of(result1, result2, result3) 1914 .filter(Objects::nonNull) 1915 .findFirst() 1916 .orElse(null); 1917 } 1918 uninstallDeviceTestPackage()1919 private String uninstallDeviceTestPackage() throws DeviceNotAvailableException { 1920 return getDevice().uninstallPackage(DEVICE_TESTS_PKG); 1921 } 1922 uninstallServicePackages()1923 private void uninstallServicePackages() throws DeviceNotAvailableException { 1924 getDevice().uninstallPackage(SERVICE_PKG); 1925 getDevice().uninstallPackage(SERVICE_TEST_PKG); 1926 } 1927 uninstallPackages()1928 private void uninstallPackages() throws DeviceNotAvailableException { 1929 uninstallPackage(); 1930 uninstallCompanionPackages(); 1931 uninstallDeviceTestPackage(); 1932 uninstallServicePackages(); 1933 } 1934 } 1935