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("v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid.apk"); 629 assertInstallFromBuildSucceeds( 630 "v3-ec-p256-with-por_1_2-default-caps-sharedUid-companion.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, all 639 // subsequent installs / updates with that old key 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 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid.apk"); 645 assertInstallFromBuildFails("v3-ec-p256-1-sharedUid-companion2.apk"); 646 } 647 testInstallV3SharedUidDeniedOnlyRotatedUpdateAllowed()648 public void testInstallV3SharedUidDeniedOnlyRotatedUpdateAllowed() throws Exception { 649 // To allow rotation after a signing key compromise, an APK that is already part of a 650 // shareddUserId can rotate to a new key with the old key being denied the SHARED_USER_ID 651 // capability and still be updated in the sharedUserId. Another app signed with this same 652 // lineage and capabilities that is not currently part of the sharedUserId will not be 653 // allowed to join as long as any apps signed with the untrusted key are still part of 654 // the sharedUserId. 655 assertInstallFromBuildSucceeds("v3-ec-p256-1-sharedUid.apk"); 656 assertInstallFromBuildSucceeds("v3-ec-p256-1-sharedUid-companion2.apk"); 657 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid.apk"); 658 // An app signed with the untrusted key is still part of the sharedUserId, so a new app 659 // that does not trust this key is not allowed to join the sharedUserId. 660 assertInstallFromBuildFails("v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid-companion.apk"); 661 assertInstallFromBuildSucceeds( 662 "v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid-companion2.apk"); 663 // Once all apps have rotated away from the untrusted key, a new app that also does not 664 // trust the previous key can now join the sharedUserId. 665 assertInstallFromBuildSucceeds( 666 "v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid-companion.apk"); 667 } 668 testInstallV3FirstAppOnlySignedByNewKeyLastAppOldKey()669 public void testInstallV3FirstAppOnlySignedByNewKeyLastAppOldKey() throws Exception { 670 // This test verifies the following scenario: 671 // - First installed app in sharedUid only signed with new key without lineage. 672 // - Second installed app in sharedUid signed with new key and includes lineage granting 673 // access to the old key to join the sharedUid. 674 // - Last installed app in sharedUid signed with old key. 675 // The lineage should be updated when the second app is installed to allow the installation 676 // of the app signed with the old key. 677 assertInstallFromBuildSucceeds("v3-ec-p256-2-sharedUid-companion.apk"); 678 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-default-caps-sharedUid.apk"); 679 assertInstallFromBuildSucceeds("v3-ec-p256-1-sharedUid-companion2.apk"); 680 } 681 testInstallV3AppSignedWithOldKeyUpdatedLineageDeniesShUidCap()682 public void testInstallV3AppSignedWithOldKeyUpdatedLineageDeniesShUidCap() throws Exception { 683 // If an app is installed as part of a sharedUid, and then that app is signed with a new key 684 // that rejects the previous key in the lineage the update should be allowed to proceed 685 // as the app is being updated to the newly rotated key. 686 assertInstallFromBuildSucceeds("v3-ec-p256-1-sharedUid.apk"); 687 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid.apk"); 688 } 689 testInstallV3TwoSharedUidAppsWithDivergedLineages()690 public void testInstallV3TwoSharedUidAppsWithDivergedLineages() throws Exception { 691 // Apps that are installed as part of the sharedUserId with a lineage must have common 692 // ancestors; the platform will allow the installation if the lineage of an app being 693 // installed as part of the sharedUserId is the same, a subset, or a superset of the 694 // existing lineage, but if the lineage diverges then the installation should be blocked. 695 assertInstallFromBuildSucceeds("v3-por_Y_1_2-default-caps-sharedUid.apk"); 696 assertInstallFromBuildFails("v3-por_Z_1_2-default-caps-sharedUid-companion.apk"); 697 } 698 testInstallV3WithRestoredCapabilityInSharedUserId()699 public void testInstallV3WithRestoredCapabilityInSharedUserId() throws Exception { 700 // A sharedUserId contains the shared signing lineage for all packages in the UID; this 701 // shared lineage contain the full signing history for all packages along with the merged 702 // capabilities for each signer shared between the packages. This test verifies if one 703 // package revokes a capability from a previous signer, but subsequently restores that 704 // capability, then since all packages have granted the capability, it is restored to the 705 // previous signer in the shared lineage. 706 707 // Install a package with the SHARED_USER_ID capability revoked for the original signer 708 // in the lineage; verify that a package signed with only the original signer cannot join 709 // the sharedUserId. 710 assertInstallFromBuildSucceeds( 711 "v3-ec-p256-with-por_1_2-default-caps-sharedUid-companion.apk"); 712 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid.apk"); 713 assertInstallFromBuildFails("v3-ec-p256-1-sharedUid-companion2.apk"); 714 715 // Update the package that revoked the SHARED_USER_ID with an updated lineage that restores 716 // this capability to the original signer; verify the package signed with the original 717 // signing key can now join the sharedUserId since all existing packages in the UID grant 718 // this capability to the original signer. 719 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-default-caps-sharedUid.apk"); 720 assertInstallFromBuildSucceeds("v3-ec-p256-1-sharedUid-companion2.apk"); 721 } 722 testInstallV3WithRevokedCapabilityInSharedUserId()723 public void testInstallV3WithRevokedCapabilityInSharedUserId() throws Exception { 724 // While a capability can be restored to a common signer in the shared signing lineage, if 725 // one package has revoked a capability from a common signer and another package is 726 // installed / updated which restores the capability to that signer, the revocation of 727 // the capability by the existing package should take precedence. A capability can only 728 // be restored to a common signer if all packages in the sharedUserId have granted this 729 // capability to the signer. 730 731 // Install a package with the SHARED_USER_ID capability revoked from the original signer, 732 // then install another package in the sharedUserId that grants this capability to the 733 // original signer. Since a package exists in the sharedUserId that has revoked this 734 // capability, another package signed with this capability shouldn't be able to join the 735 // sharedUserId. 736 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-shUid-cap-sharedUid.apk"); 737 assertInstallFromBuildSucceeds( 738 "v3-ec-p256-with-por_1_2-default-caps-sharedUid-companion.apk"); 739 assertInstallFromBuildFails("v3-ec-p256-1-sharedUid-companion2.apk"); 740 741 // Install the same package that grants the SHARED_USER_ID capability to the original 742 // signer; when iterating over the existing packages in the packages in the sharedUserId, 743 // the original version of this package should be skipped since the lineage from the 744 // updated package is used when merging with the shared lineage. 745 assertInstallFromBuildSucceeds( 746 "v3-ec-p256-with-por_1_2-default-caps-sharedUid-companion.apk"); 747 assertInstallFromBuildFails("v3-ec-p256-1-sharedUid-companion2.apk"); 748 749 // Install another package that has granted the SHARED_USER_ID to the original signer; this 750 // should trigger another merge with all packages in the sharedUserId. Since one still 751 // remains that revokes the capability, the capability should be revoked in the shared 752 // lineage. 753 assertInstallFromBuildSucceeds( 754 "v3-ec-p256-with-por_1_2-default-caps-sharedUid-companion3.apk"); 755 assertInstallFromBuildFails("v3-ec-p256-1-sharedUid-companion2.apk"); 756 } 757 testInstallV3UpdateAfterRotation()758 public void testInstallV3UpdateAfterRotation() throws Exception { 759 // This test performs an end to end verification of the update of an app with a rotated 760 // key. The app under test exports a bound service that performs its own PackageManager key 761 // rotation API verification, and the instrumentation test binds to the service and invokes 762 // the verifySignatures method to verify that the key rotation APIs return the expected 763 // results. The instrumentation test app is signed with the same key and lineage as the 764 // app under test to also provide a second app that can be used for the checkSignatures 765 // verification. 766 767 // Install the initial versions of the apps; the test method verifies the app under test is 768 // signed with the original signing key. 769 assertInstallFromBuildSucceeds("CtsSignatureQueryService.apk"); 770 assertInstallFromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 771 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 772 "verifySignatures_noRotation_succeeds"); 773 774 // Install the second version of the app signed with the rotated key. This test verifies the 775 // app still functions as expected after the update with the rotated key. The 776 // instrumentation test app is not updated here to allow verification of the pre-key 777 // rotation behavior for the checkSignatures APIs. These APIs should behave similar to the 778 // GET_SIGNATURES flag in that if one or both apps have a signing lineage if the oldest 779 // signers in the lineage match then the methods should return that the signatures match 780 // even if one is signed with a newer key in the lineage. 781 assertInstallFromBuildSucceeds("CtsSignatureQueryService_v2.apk"); 782 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 783 "verifySignatures_withRotation_succeeds"); 784 785 // Installs the third version of the app under test and the instrumentation test, both 786 // signed with the same rotated key and lineage. This test is intended to verify that the 787 // app can still be updated and function as expected after an update with a rotated key. 788 assertInstallFromBuildSucceeds("CtsSignatureQueryService_v3.apk"); 789 assertInstallFromBuildSucceeds("CtsSignatureQueryServiceTest_v2.apk"); 790 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 791 "verifySignatures_withRotation_succeeds"); 792 } 793 794 @CddTest(requirement="4/C-0-2") testInstallV31UpdateAfterRotation()795 public void testInstallV31UpdateAfterRotation() throws Exception { 796 // This test is the same as above, but using the v3.1 signature scheme for rotation. 797 assertInstallFromBuildSucceeds("CtsSignatureQueryService.apk"); 798 assertInstallFromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 799 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 800 "verifySignatures_noRotation_succeeds"); 801 802 assertInstallFromBuildSucceeds("CtsSignatureQueryService_v2-tgt-33.apk"); 803 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 804 "verifySignatures_withRotation_succeeds"); 805 806 assertInstallFromBuildSucceeds("CtsSignatureQueryService_v3-tgt-33.apk"); 807 assertInstallFromBuildSucceeds("CtsSignatureQueryServiceTest_v2-tgt-33.apk"); 808 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 809 "verifySignatures_withRotation_succeeds"); 810 } 811 812 @CddTest(requirement="4/C-0-9") testInstallV41UpdateAfterRotation()813 public void testInstallV41UpdateAfterRotation() throws Exception { 814 // V4 is only enabled on devices with Incremental feature 815 if (!hasIncrementalFeature()) { 816 return; 817 } 818 819 // This test is the same as above, but using the v4.1 signature scheme for rotation. 820 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService.apk"); 821 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 822 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 823 "verifySignatures_noRotation_succeeds"); 824 825 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService_v2-tgt-33.apk"); 826 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 827 "verifySignatures_withRotation_succeeds"); 828 829 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService_v3-tgt-33.apk"); 830 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest_v2-tgt-33.apk"); 831 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 832 "verifySignatures_withRotation_succeeds"); 833 } 834 835 @CddTest(requirement="4/C-0-9") testInstallV41WrongBlockId()836 public void testInstallV41WrongBlockId() throws Exception { 837 // V4 is only enabled on devices with Incremental feature 838 if (!hasIncrementalFeature()) { 839 return; 840 } 841 842 // This test is the same as above, but using the v4.1 signature scheme for rotation. 843 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService.apk"); 844 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 845 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 846 "verifySignatures_noRotation_succeeds"); 847 848 assertInstallV4FailsWithError("CtsSignatureQueryService_v2-tgt-33-wrongV41Block.apk", 849 "Failed to find V4 signature block corresponding to V3 blockId: 462663009"); 850 } 851 852 @CddTest(requirement="4/C-0-9") testInstallV41LegacyV4()853 public void testInstallV41LegacyV4() throws Exception { 854 // V4 is only enabled on devices with Incremental feature 855 if (!hasIncrementalFeature()) { 856 return; 857 } 858 859 // This test is the same as above, but using the v4.1 signature scheme for rotation. 860 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService.apk"); 861 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 862 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 863 "verifySignatures_noRotation_succeeds"); 864 865 assertInstallV4FailsWithError("CtsSignatureQueryService_v2-tgt-33-legacyV4.apk", 866 "Failed to find V4 signature block corresponding to V3 blockId: 462663009"); 867 } 868 869 @CddTest(requirement="4/C-0-9") testInstallV41WrongDigest()870 public void testInstallV41WrongDigest() throws Exception { 871 // V4 is only enabled on devices with Incremental feature 872 if (!hasIncrementalFeature()) { 873 return; 874 } 875 876 // This test is the same as above, but using the v4.1 signature scheme for rotation. 877 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService.apk"); 878 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 879 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 880 "verifySignatures_noRotation_succeeds"); 881 882 assertInstallV4FailsWithError("CtsSignatureQueryService_v2-tgt-33-wrongDigest.apk", 883 "APK digest in V4 signature does not match V2/V3"); 884 } 885 testInstallV3KeyRotationSigPerm()886 public void testInstallV3KeyRotationSigPerm() throws Exception { 887 // tests that a v3 signed APK can still get a signature permission from an app with its 888 // older signing certificate. 889 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk"); 890 assertInstallSucceeds( 891 "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-permcli-companion.apk"); 892 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 893 } 894 testInstallV3KeyRotationOlderSigPerm()895 public void testInstallV3KeyRotationOlderSigPerm() throws Exception { 896 // tests that an apk with an older signing certificate than the one which defines a 897 // signature permission it wants gets the permission if the defining APK grants the 898 // capability 899 assertInstallSucceeds( 900 "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-permdef.apk"); 901 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permcli-companion.apk"); 902 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 903 } 904 testInstallV3KeyRotationSigPermNoCap()905 public void testInstallV3KeyRotationSigPermNoCap() throws Exception { 906 // tests that an APK signed by an older signing certificate is unable to get a requested 907 // signature permission when the defining APK has rotated to a newer signing certificiate 908 // and does not grant the permission capability to the older cert 909 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permdef.apk"); 910 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permcli-companion.apk"); 911 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasNoPerm"); 912 } 913 testInstallV3KeyRotationOlderSigPermNoCap()914 public void testInstallV3KeyRotationOlderSigPermNoCap() throws Exception { 915 // tests that an APK signed by a newer signing certificate than the APK which defines a 916 // signature permission is able to get that permission, even if the newer APK does not 917 // grant the permission capability to the older signing certificate. 918 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk"); 919 assertInstallSucceeds( 920 "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permcli-companion.apk"); 921 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 922 } 923 testInstallV3NoRotationSigPerm()924 public void testInstallV3NoRotationSigPerm() throws Exception { 925 // make sure that an APK, which wants to use a signature permission defined by an APK, which 926 // has not granted that capability to older signing certificates, can still install 927 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permdef.apk"); 928 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-permcli-companion.apk"); 929 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 930 } 931 testInstallV3CommonSignerInLineageWithPermCap()932 public void testInstallV3CommonSignerInLineageWithPermCap() throws Exception { 933 // If an APK requesting a signature permission has a common signer in the lineage with the 934 // APK declaring the permission, and that signer is granted the permission capability in 935 // the declaring APK, then the permission should be granted to the requesting app even 936 // if their signers have diverged. 937 assertInstallFromBuildSucceeds( 938 "v3-ec-p256-with-por_1_2_3-1-no-caps-2-default-declperm.apk"); 939 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2_4-companion-usesperm.apk"); 940 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 941 } 942 testInstallV3CommonSignerInLineageNoCaps()943 public void testInstallV3CommonSignerInLineageNoCaps() throws Exception { 944 // If an APK requesting a signature permission has a common signer in the lineage with the 945 // APK declaring the permission, but the signer in the lineage has not been granted the 946 // permission capability the permission should not be granted to the requesting app. 947 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2_3-no-caps-declperm.apk"); 948 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2_4-companion-usesperm.apk"); 949 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasNoPerm"); 950 } 951 testKnownSignerPermGrantedWhenCurrentSignerInResource()952 public void testKnownSignerPermGrantedWhenCurrentSignerInResource() throws Exception { 953 // The knownSigner protection flag allows an app to declare other trusted signing 954 // certificates in an array resource; if a requesting app's current signer is in this array 955 // of trusted certificates then the permission should be granted. 956 assertInstallFromBuildSucceeds("v3-rsa-2048-decl-knownSigner-ec-p256-1-3.apk"); 957 assertInstallFromBuildSucceeds("v3-ec-p256_3-companion-uses-knownSigner.apk"); 958 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 959 960 // If the declaring app changes the trusted certificates on an update any requesting app 961 // that no longer meets the requirements based on its signing identity should have the 962 // permission revoked. This app update only trusts ec-p256_1 but the app that was previously 963 // granted the permission based on its signing identity is signed by ec-p256_3. 964 assertInstallFromBuildSucceeds("v3-rsa-2048-decl-knownSigner-str-res-ec-p256-1.apk"); 965 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasNoPerm"); 966 } 967 testKnownSignerPermCurrentSignerNotInResource()968 public void testKnownSignerPermCurrentSignerNotInResource() throws Exception { 969 // If an app requesting a knownSigner permission does not meet the requirements for a 970 // signature permission and is not signed by any of the trusted certificates then the 971 // permission should not be granted. 972 assertInstallFromBuildSucceeds("v3-rsa-2048-decl-knownSigner-ec-p256-1-3.apk"); 973 assertInstallFromBuildSucceeds("v3-ec-p256_2-companion-uses-knownSigner.apk"); 974 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasNoPerm"); 975 } 976 testKnownSignerPermGrantedWhenSignerInLineageInResource()977 public void testKnownSignerPermGrantedWhenSignerInLineageInResource() throws Exception { 978 // If an app requesting a knownSigner permission was previously signed by a certificate 979 // that is trusted by the declaring app then the permission should be granted. 980 assertInstallFromBuildSucceeds("v3-rsa-2048-decl-knownSigner-ec-p256-1-3.apk"); 981 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-companion-uses-knownSigner.apk"); 982 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 983 984 // If the declaring app changes the permission to no longer use the knownSigner flag then 985 // any app granted the permission based on a signing identity from the set of trusted 986 // certificates should have the permission revoked. 987 assertInstallFromBuildSucceeds("v3-rsa-2048-declperm.apk"); 988 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasNoPerm"); 989 } 990 testKnownSignerPermSignerInLineageMatchesStringResource()991 public void testKnownSignerPermSignerInLineageMatchesStringResource() throws Exception { 992 // The knownSigner protection flag allows an app to declare a single known trusted 993 // certificate digest using a string resource instead of a string-array resource. This test 994 // verifies the knownSigner permission is granted to a requesting app if the single trusted 995 // cert is in the requesting app's lineage. 996 assertInstallFromBuildSucceeds("v3-rsa-2048-decl-knownSigner-str-res-ec-p256-1.apk"); 997 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-companion-uses-knownSigner.apk"); 998 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 999 } 1000 testKnownSignerPermSignerInLineageMatchesStringConst()1001 public void testKnownSignerPermSignerInLineageMatchesStringConst() throws Exception { 1002 // The knownSigner protection flag allows an app to declare a single known trusted 1003 // certificate digest using a string constant as the knownCerts attribute value instead of a 1004 // resource. This test verifies the knownSigner permission is granted to a requesting app if 1005 // the single trusted cert is in the requesting app's lineage. 1006 assertInstallFromBuildSucceeds("v3-rsa-2048-decl-knownSigner-str-const-ec-p256-1.apk"); 1007 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-companion-uses-knownSigner.apk"); 1008 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 1009 } 1010 testInstallV3SigPermDoubleDefNewerSucceeds()1011 public void testInstallV3SigPermDoubleDefNewerSucceeds() throws Exception { 1012 // make sure that if an app defines a signature permission already defined by another app, 1013 // it successfully installs if the other app's signing cert is in its past signing certs and 1014 // the signature permission capability is granted 1015 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk"); 1016 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-permdef-companion.apk"); 1017 } 1018 testInstallV3SigPermDoubleDefOlderSucceeds()1019 public void testInstallV3SigPermDoubleDefOlderSucceeds() throws Exception { 1020 // make sure that if an app defines a signature permission already defined by another app, 1021 // it successfully installs if it is in the other app's past signing certs and the signature 1022 // permission capability is granted 1023 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-permdef-companion.apk"); 1024 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk"); 1025 } 1026 testInstallV3SigPermDoubleDefNewerNoCapFails()1027 public void testInstallV3SigPermDoubleDefNewerNoCapFails() throws Exception { 1028 // make sure that if an app defines a signature permission already defined by another app, 1029 // it fails to install if the other app's signing cert is in its past signing certs but the 1030 // signature permission capability is not granted 1031 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk"); 1032 assertInstallFails( 1033 "v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-no-perm-cap-permdef-companion.apk"); 1034 } 1035 testInstallV3SigPermDoubleDefOlderNoCapFails()1036 public void testInstallV3SigPermDoubleDefOlderNoCapFails() throws Exception { 1037 // make sure that if an app defines a signature permission already defined by another app, 1038 // it fails to install if it is in the other app's past signing certs but the signature 1039 // permission capability is not granted 1040 assertInstallSucceeds( 1041 "v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-no-perm-cap-permdef-companion.apk"); 1042 assertInstallFails("v3-rsa-pkcs1-sha256-2048-1-permdef.apk"); 1043 } 1044 testInstallV3SigPermDoubleDefSameNoCapSucceeds()1045 public void testInstallV3SigPermDoubleDefSameNoCapSucceeds() throws Exception { 1046 // make sure that if an app defines a signature permission already defined by another app, 1047 // it installs successfully when signed by the same certificate, even if the original app 1048 // does not grant signature capabilities to its past certs 1049 assertInstallSucceeds( 1050 "v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-no-perm-cap-permdef-companion.apk"); 1051 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-permdef.apk"); 1052 } 1053 testInstallV3KeyRotationGetSignatures()1054 public void testInstallV3KeyRotationGetSignatures() throws Exception { 1055 // tests that a PackageInfo w/GET_SIGNATURES flag returns the older cert 1056 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 1057 Utils.runDeviceTests( 1058 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testGetSignaturesShowsOld"); 1059 } 1060 testInstallV3KeyRotationGetSigningCertificates()1061 public void testInstallV3KeyRotationGetSigningCertificates() throws Exception { 1062 // tests that a PackageInfo w/GET_SIGNING_CERTIFICATES flag returns the old and new certs 1063 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 1064 Utils.runDeviceTests( 1065 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1066 "testGetSigningCertificatesShowsAll"); 1067 } 1068 testInstallV3KeyRotationGetApkContentsSigners()1069 public void testInstallV3KeyRotationGetApkContentsSigners() throws Exception { 1070 // The GET_SIGNING_CERTIFICATES flag results in a PackageInfo object returned with a 1071 // SigningInfo instance that can be used to query all certificates in the lineage or only 1072 // the current signer(s) via getApkContentsSigners. This test verifies when a V3 signed 1073 // package with a rotated key is queried getApkContentsSigners only returns the current 1074 // signer. 1075 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-default-caps.apk"); 1076 Utils.runDeviceTests( 1077 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1078 "testGetApkContentsSignersShowsCurrent"); 1079 } 1080 testInstallV2MultipleSignersGetApkContentsSigners()1081 public void testInstallV2MultipleSignersGetApkContentsSigners() throws Exception { 1082 // Similar to the above test, but verifies when an APK is signed with two V2 signers 1083 // getApkContentsSigners returns both of the V2 signers. 1084 assertInstallFromBuildSucceeds("v1v2-ec-p256-two-signers-targetSdk-30.apk"); 1085 Utils.runDeviceTests( 1086 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1087 "testGetApkContentsSignersShowsMultipleSigners"); 1088 } 1089 testInstallV3MultipleSignersInLineageGetSigningCertificateHistory()1090 public void testInstallV3MultipleSignersInLineageGetSigningCertificateHistory() 1091 throws Exception { 1092 // The APK used for this test is signed with a lineage containing 5 keys in the signing 1093 // history; this test verifies SigningInfo#getSigningCertificateHistory returns all of an 1094 // APKs signers in their order of rotation. 1095 assertInstallFromBuildSucceeds("v3-ec-p256-with-por-1_2_3_4_5-default-caps.apk"); 1096 Utils.runDeviceTests( 1097 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1098 "testGetSigningCertificateHistoryReturnsSignersInOrder"); 1099 } 1100 testInstallV3KeyRotationHasSigningCertificate()1101 public void testInstallV3KeyRotationHasSigningCertificate() throws Exception { 1102 // tests that hasSigningCertificate() recognizes past and current signing certs 1103 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 1104 Utils.runDeviceTests( 1105 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1106 "testHasSigningCertificate"); 1107 } 1108 testInstallV3KeyRotationHasSigningCertificateSha256()1109 public void testInstallV3KeyRotationHasSigningCertificateSha256() throws Exception { 1110 // tests that hasSigningCertificate() recognizes past and current signing certs by sha256 1111 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 1112 Utils.runDeviceTests( 1113 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1114 "testHasSigningCertificateSha256"); 1115 } 1116 testInstallV3KeyRotationHasSigningCertificateByUid()1117 public void testInstallV3KeyRotationHasSigningCertificateByUid() throws Exception { 1118 // tests that hasSigningCertificate() recognizes past and current signing certs by uid 1119 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 1120 Utils.runDeviceTests( 1121 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1122 "testHasSigningCertificateByUid"); 1123 } 1124 testInstallV3KeyRotationHasSigningCertificateByUidSha256()1125 public void testInstallV3KeyRotationHasSigningCertificateByUidSha256() throws Exception { 1126 // tests that hasSigningCertificate() recognizes past and current signing certs by uid 1127 // and sha256 1128 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps.apk"); 1129 Utils.runDeviceTests( 1130 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1131 "testHasSigningCertificateByUidSha256"); 1132 } 1133 testInstallV3KeyRotationHasDuplicateSigningCertificateHistory()1134 public void testInstallV3KeyRotationHasDuplicateSigningCertificateHistory() throws Exception { 1135 // tests that an app's proof-of-rotation signing history cannot contain the same certificate 1136 // more than once. 1137 assertInstallFails("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2_2-full-caps.apk"); 1138 } 1139 testInstallV3HasMultipleSigners()1140 public void testInstallV3HasMultipleSigners() throws Exception { 1141 // tests that an app can't be signed by multiple signers when using v3 signature scheme 1142 assertInstallFails("v3-rsa-pkcs1-sha256-2048-1_and_2.apk"); 1143 } 1144 testInstallV3HasMultiplePlatformSigners()1145 public void testInstallV3HasMultiplePlatformSigners() throws Exception { 1146 // tests that an app can be signed by multiple v3 signers if they target different platform 1147 // versions 1148 assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1_P_and_2_Qplus.apk"); 1149 } 1150 testSharedKeyInSeparateLineageRetainsDeclaredCapabilities()1151 public void testSharedKeyInSeparateLineageRetainsDeclaredCapabilities() throws Exception { 1152 // This test verifies when a key is used in the signing lineage of multiple apps each 1153 // instance of the key retains its declared capabilities. 1154 1155 // This app has granted the PERMISSION capability to the previous signer in the lineage 1156 // but has revoked the SHARED_USER_ID capability. 1157 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-shUid-cap-declperm2.apk"); 1158 // This app has granted the SHARED_USER_ID capability to the previous signer in the lineage 1159 // but has revoked the PERMISSION capability. 1160 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-perm-cap-sharedUid.apk"); 1161 1162 // Reboot the device to ensure that the capabilities written to packages.xml are properly 1163 // assigned to the packages installed above; it's possible immediately after a package 1164 // install the capabilities are as declared, but then during the reboot shared signing 1165 // keys also share the initial declared capabilities. 1166 getDevice().reboot(); 1167 1168 // This app is signed with the original shared signing key in the lineage and is part of the 1169 // sharedUserId; since the other app in this sharedUserId has granted the required 1170 // capability in the lineage the install should succeed. 1171 assertInstallFromBuildSucceeds("v3-ec-p256-1-sharedUid-companion2.apk"); 1172 // This app is signed with the original shared signing key in the lineage and requests the 1173 // signature permission declared by the test app above. Since that app granted the 1174 // PERMISSION capability to the previous signer in the lineage this app should have the 1175 // permission granted. 1176 assertInstallFromBuildSucceeds("v3-ec-p256-1-companion-usesperm.apk"); 1177 Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm"); 1178 } 1179 1180 @CddTest(requirement="4/C-0-2") testV31TargetTPlatformUsesRotatedKey()1181 public void testV31TargetTPlatformUsesRotatedKey() throws Exception { 1182 // The v3.1 signature block is intended to allow applications to target T+ for APK signing 1183 // key rotation without needing multi-targeting APKs. This test verifies a standard APK 1184 // install with the rotated key in the v3.1 signing block targeting T is recognized by the 1185 // platform, and this rotated key is used as the signing identity. 1186 assertInstallSucceeds("v31-ec-p256_2-tgt-33.apk"); 1187 Utils.runDeviceTests( 1188 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1189 "testUsingRotatedSigner"); 1190 } 1191 1192 @CddTest(requirement="4/C-0-2") testV31TargetLaterThanDevicePlatformUsesOriginalKey()1193 public void testV31TargetLaterThanDevicePlatformUsesOriginalKey() throws Exception { 1194 // The v3.1 signature block allows targeting SDK versions later than T for rotation; for 1195 // this test a target of 100001 is used assuming it will be beyond the platform's version. 1196 // Since the target version for rotation is beyond the platform's version the original 1197 // signer from the v3.0 block should be used. 1198 assertInstallSucceeds("v31-ec-p256_2-tgt-100001.apk"); 1199 Utils.runDeviceTests( 1200 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1201 "testUsingOriginalSigner"); 1202 } 1203 1204 @CddTest(requirement="4/C-0-2") testV31SignersTargetPAnd100001PlatformUsesTargetPSigner()1205 public void testV31SignersTargetPAnd100001PlatformUsesTargetPSigner() throws Exception { 1206 // The v3.1 signature scheme allows signer configs to target SDK versions; if a rotated 1207 // signer config is targeting P, the v3.0 block will include a signature with that rotated 1208 // config. This test verifies when the v3.1 signer is targeting an SDK version beyond that 1209 // of the platform's, the rotated signing config from the v3.0 block is used by the 1210 // platform. 1211 assertInstallSucceeds("v31-ec-p256_2-tgt-28-ec-p256_3-tgt-100001.apk"); 1212 Utils.runDeviceTests( 1213 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1214 "testUsingRotatedSigner"); 1215 } 1216 1217 @CddTest(requirement="4/C-0-2") testV31BlockStrippedWithV3StrippingProtectionAttrSet()1218 public void testV31BlockStrippedWithV3StrippingProtectionAttrSet() throws Exception { 1219 // With the introduction of the v3.1 signature scheme, a new stripping protection attribute 1220 // has been added to the v3.0 signer to protect against stripping and modification of the 1221 // v3.1 signing block. This test verifies a stripped v3.1 block is detected when the v3.0 1222 // stripping protection attribute is set. 1223 assertInstallFails("v31-block-stripped-v3-attr-value-33.apk"); 1224 } 1225 1226 @CddTest(requirement="4/C-0-2") testV31BlockWithMultipleSignersUsesCorrectSigner()1227 public void testV31BlockWithMultipleSignersUsesCorrectSigner() throws Exception { 1228 // All of the APKs for this test use multiple v3.1 signers; those targeting SDK versions 1229 // expected to be outside the version of a device under test use the original signer, and 1230 // those targeting an expected range for a device use the rotated key. This test is 1231 // intended to ensure the signer with the min / max SDK version that matches the device 1232 // SDK version is used. 1233 1234 // The APK used for this test contains two signers in the v3.1 signing block. The first 1235 // has a range from 100001 to Integer.MAX_VALUE and is using the original signing key; 1236 // the second targets 33 to 100000 using the rotated key. 1237 assertInstallSucceeds("v31-ec-p256_2-tgt-33-ec-p256-tgt-100001.apk"); 1238 Utils.runDeviceTests( 1239 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1240 "testUsingRotatedSigner"); 1241 uninstallPackage(); 1242 1243 // The APK for this test contains two signers in the v3.1 block, one targeting SDK versions 1244 // 1 to 27 using the original signer, and the other targeting 33+ using the rotated signer. 1245 assertInstallSucceeds("v31-ec-p256_2-tgt-33-ec-p256-tgt-1-27.apk"); 1246 Utils.runDeviceTests( 1247 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1248 "testUsingRotatedSigner"); 1249 uninstallPackage(); 1250 1251 // This APK combines the extra signers from the APKs above, one targeting 1 to 27 with the 1252 // original signing key, another targeting 100001+ with the original signing key, and the 1253 // last targeting 33 to 100000 with the rotated key. 1254 assertInstallSucceeds("v31-ec-p256_2-tgt-33-ec-p256-tgt-1-27-and-100001.apk"); 1255 Utils.runDeviceTests( 1256 getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, 1257 "testUsingRotatedSigner"); 1258 } 1259 1260 @CddTest(requirement="4/C-0-2") testV31UpdateV3ToFromV31Succeeds()1261 public void testV31UpdateV3ToFromV31Succeeds() throws Exception { 1262 // Since the v3.1 block is just intended to allow targeting SDK versions T and later for 1263 // rotation, an APK signed with the rotated key in a v3.0 signing block should support 1264 // updates to an APK signed with the same signing key in a v3.1 signing block. 1265 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-default-caps.apk"); 1266 assertInstallSucceeds("v31-ec-p256_2-tgt-33.apk"); 1267 uninstallPackage(); 1268 1269 // Similarly an APK signed with the rotated key in a v3.1 signing block should support 1270 // updates to an APK signed with the same signing key in a v3.0 signing block. 1271 assertInstallSucceeds("v31-ec-p256_2-tgt-33.apk"); 1272 assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-default-caps.apk"); 1273 uninstallPackage(); 1274 } 1275 1276 @CddTest(requirement="4/C-0-2") testV31RotationTargetModifiedReportedByV3()1277 public void testV31RotationTargetModifiedReportedByV3() throws Exception { 1278 // When determining if a signer in the v3.1 signing block should be applied, the min / max 1279 // SDK versions from the signer are compared against the device's SDK version; if the device 1280 // is not within the signer's range then the block is skipped, other v3.1 blocks are 1281 // checked, and finally the v3.0 block is used. The v3.0 signer block contains an additional 1282 // attribute with the rotation-min-sdk-version that was expected in the v3.1 signing 1283 // block; if this attribute's value does not match what was found in the v3.1 block the 1284 // APK should fail to install. 1285 assertInstallFails("v31-ec-p256_2-tgt-33-modified.apk"); 1286 } 1287 1288 @CddTest(requirement="4/C-0-2") testV31RotationTargetsDevRelease()1289 public void testV31RotationTargetsDevRelease() throws Exception { 1290 // The v3.1 signature scheme allows targeting a platform release under development through 1291 // the use of a rotation-targets-dev-release additional attribute. Since a platform under 1292 // development shares the same SDK version as the most recently released platform, the 1293 // attribute is used by the platform to determine if a signer block should be applied. If 1294 // the signer's minSdkVersion is the same as the device's SDK version and this attribute 1295 // is set, then the platform will check the value of ro.build.version.codename; a value of 1296 // "REL" indicates the platform is a release platform, so the current signer block will not 1297 // be used. During T's development, the SDK version is 31 and the codename is not "REL", so 1298 // this test APK will install on T during development as well as after its release since 1299 // the SDK version will be bumped at that point. 1300 assertInstallSucceeds("v31-ec-p256_2-tgt-31-dev-release.apk"); 1301 } 1302 1303 testInstallTargetSdk30WithV1Signers()1304 public void testInstallTargetSdk30WithV1Signers() throws Exception { 1305 // An app targeting SDK version >= 30 must have at least a V2 signature; this test verifies 1306 // an app targeting SDK version 30 with only a V1 signature fails to install. 1307 assertInstallFails("v1-ec-p256-two-signers-targetSdk-30.apk"); 1308 } 1309 testInstallTargetSdk30WithV1V2Signers()1310 public void testInstallTargetSdk30WithV1V2Signers() throws Exception { 1311 // An app targeting SDK version >= 30 must have at least a V2 signature; this test verifies 1312 // that an app targeting SDK version 30 with both a V1 and V2 signature installs 1313 // successfully. 1314 installApkFromBuild("v1v2-ec-p256-two-signers-targetSdk-30.apk"); 1315 } 1316 testInstallV4WithV2Signer()1317 public void testInstallV4WithV2Signer() throws Exception { 1318 // V4 is only enabled on devices with Incremental feature 1319 if (!hasIncrementalFeature()) { 1320 return; 1321 } 1322 1323 // APK generated with: 1324 // apksigner sign --v2-signing-enabled true --v3-signing-enabled false --v4-signing-enabled 1325 assertInstallV4Succeeds("v4-digest-v2.apk"); 1326 } 1327 testInstallV4WithV3Signer()1328 public void testInstallV4WithV3Signer() throws Exception { 1329 // V4 is only enabled on devices with Incremental feature 1330 if (!hasIncrementalFeature()) { 1331 return; 1332 } 1333 1334 // APK generated with: 1335 // apksigner sign --v2-signing-enabled false --v3-signing-enabled true --v4-signing-enabled 1336 assertInstallV4Succeeds("v4-digest-v3.apk"); 1337 } 1338 testInstallV4WithV2V3Signer()1339 public void testInstallV4WithV2V3Signer() throws Exception { 1340 // V4 is only enabled on devices with Incremental feature 1341 if (!hasIncrementalFeature()) { 1342 return; 1343 } 1344 1345 // APK generated with: 1346 // apksigner sign --v2-signing-enabled true --v3-signing-enabled true --v4-signing-enabled 1347 assertInstallV4Succeeds("v4-digest-v2v3.apk"); 1348 } 1349 testInstallV4WithV2NoVeritySigner()1350 public void testInstallV4WithV2NoVeritySigner() throws Exception { 1351 // V4 is only enabled on devices with Incremental feature 1352 if (!hasIncrementalFeature()) { 1353 return; 1354 } 1355 1356 // APK generated with: 1357 // --v2-signing-enabled true --v3-signing-enabled false --v4-signing-enabled 1358 // Full commands in generate-apks.sh 1359 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha256withDSA.apk"); 1360 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha256withEC.apk"); 1361 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha256withRSA.apk"); 1362 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha512withEC.apk"); 1363 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha512withRSA.apk"); 1364 } 1365 testInstallV4WithV2VeritySigner()1366 public void testInstallV4WithV2VeritySigner() throws Exception { 1367 // V4 is only enabled on devices with Incremental feature 1368 if (!hasIncrementalFeature()) { 1369 return; 1370 } 1371 1372 // APK generated with: 1373 // --v2-signing-enabled true --v3-signing-enabled false 1374 // --v4-signing-enabled --verity-enabled 1375 // Full commands in generate-apks.sh 1376 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha256withDSA-Verity.apk"); 1377 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha256withEC-Verity.apk"); 1378 assertInstallV4SucceedsAndUninstall("v4-digest-v2-Sha256withRSA-Verity.apk"); 1379 } 1380 testInstallV4WithV3NoVeritySigner()1381 public void testInstallV4WithV3NoVeritySigner() throws Exception { 1382 // V4 is only enabled on devices with Incremental feature 1383 if (!hasIncrementalFeature()) { 1384 return; 1385 } 1386 1387 // APK generated with: 1388 // --v2-signing-enabled false --v3-signing-enabled true --v4-signing-enabled 1389 // Full commands in generate-apks.sh 1390 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha256withDSA.apk"); 1391 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha256withEC.apk"); 1392 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha256withRSA.apk"); 1393 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha512withEC.apk"); 1394 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha512withRSA.apk"); 1395 } 1396 testInstallV4WithV3VeritySigner()1397 public void testInstallV4WithV3VeritySigner() throws Exception { 1398 // V4 is only enabled on devices with Incremental feature 1399 if (!hasIncrementalFeature()) { 1400 return; 1401 } 1402 1403 // APK generated with: 1404 // --v2-signing-enabled false --v3-signing-enabled true 1405 // --v4-signing-enabled --verity-enabled 1406 // Full commands in generate-apks.sh 1407 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha256withDSA-Verity.apk"); 1408 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha256withEC-Verity.apk"); 1409 assertInstallV4SucceedsAndUninstall("v4-digest-v3-Sha256withRSA-Verity.apk"); 1410 } 1411 testInstallV4WithV2SignerDoesNotVerify()1412 public void testInstallV4WithV2SignerDoesNotVerify() throws Exception { 1413 // V4 is only enabled on devices with Incremental feature 1414 if (!hasIncrementalFeature()) { 1415 return; 1416 } 1417 1418 // APKs generated with: 1419 // apksigner sign -v2-signing-enabled true --v3-signing-enabled false --v4-signing-enabled 1420 1421 // Malformed v4 signature - first byte of v4 signing_info.signature is flipped 1422 assertInstallV4FailsWithError("v4-digest-v2-badv4signature.apk", "did not verify"); 1423 // Malformed digest - first byte of v4 signing_info.apk_digest is flipped 1424 assertInstallV4FailsWithError("v4-digest-v2-badv2digest.apk", "did not verify"); 1425 } 1426 testInstallV4WithV3SignerDoesNotVerify()1427 public void testInstallV4WithV3SignerDoesNotVerify() throws Exception { 1428 // V4 is only enabled on devices with Incremental feature 1429 if (!hasIncrementalFeature()) { 1430 return; 1431 } 1432 1433 // APKs generated with: 1434 // apksigner sign -v2-signing-enabled false --v3-signing-enabled true --v4-signing-enabled 1435 1436 // Malformed v4 signature - first byte of v4 signing_info.signature is flipped 1437 assertInstallV4FailsWithError("v4-digest-v3-badv4signature.apk", "did not verify"); 1438 1439 // Malformed digest - first byte of v4 signing_info.apk_digest is flipped 1440 assertInstallV4FailsWithError("v4-digest-v3-badv3digest.apk", "did not verify"); 1441 1442 } 1443 testInstallV4WithV2V3SignerDoesNotVerify()1444 public void testInstallV4WithV2V3SignerDoesNotVerify() throws Exception { 1445 // V4 is only enabled on devices with Incremental feature 1446 if (!hasIncrementalFeature()) { 1447 return; 1448 } 1449 1450 // APKs generated with: 1451 // apksigner sign -v2-signing-enabled true --v3-signing-enabled true --v4-signing-enabled 1452 1453 // Malformed v4 signature - first byte of v4 signing_info.signature is flipped 1454 assertInstallV4FailsWithError("v4-digest-v2v3-badv4signature.apk", "did not verify"); 1455 1456 // Malformed digest - first byte of v4 signing_info.apk_digest is flipped 1457 assertInstallV4FailsWithError("v4-digest-v2v3-badv2v3digest.apk", "did not verify"); 1458 } 1459 testInstallV4With128BytesAdditionalDataSucceeds()1460 public void testInstallV4With128BytesAdditionalDataSucceeds() throws Exception { 1461 // V4 is only enabled on devices with Incremental feature 1462 if (!hasIncrementalFeature()) { 1463 return; 1464 } 1465 1466 // Editing apksigner to fill additional data of size 128 bytes. 1467 assertInstallV4Succeeds("v4-digest-v3-128bytes-additional-data.apk"); 1468 } 1469 testInstallV4With256BytesAdditionalDataFails()1470 public void testInstallV4With256BytesAdditionalDataFails() throws Exception { 1471 // V4 is only enabled on devices with Incremental feature 1472 if (!hasIncrementalFeature()) { 1473 return; 1474 } 1475 1476 // Editing apksigner to fill additional data of size 256 bytes. 1477 assertInstallV4FailsWithError("v4-digest-v3-256bytes-additional-data.apk", 1478 "additionalData has to be at most 128 bytes"); 1479 } 1480 testInstallV4With10MBytesAdditionalDataFails()1481 public void testInstallV4With10MBytesAdditionalDataFails() throws Exception { 1482 // V4 is only enabled on devices with Incremental feature 1483 if (!hasIncrementalFeature()) { 1484 return; 1485 } 1486 1487 // Editing apksigner to fill additional data of size 10 * 1024 * 1024 bytes. 1488 assertInstallV4FailsWithError("v4-digest-v3-10mbytes-additional-data.apk", 1489 "Failure"); 1490 } 1491 testInstallV4WithWrongBlockSize()1492 public void testInstallV4WithWrongBlockSize() throws Exception { 1493 // V4 is only enabled on devices with Incremental feature 1494 if (!hasIncrementalFeature()) { 1495 return; 1496 } 1497 1498 // Editing apksigner with the wrong block size in the v4 signature. 1499 assertInstallV4FailsWithError("v4-digest-v3-wrong-block-size.apk", 1500 "did not verify"); 1501 } 1502 testInstallV4WithDifferentBlockSize()1503 public void testInstallV4WithDifferentBlockSize() throws Exception { 1504 // V4 is only enabled on devices with Incremental feature 1505 if (!hasIncrementalFeature()) { 1506 return; 1507 } 1508 1509 // Editing apksigner with the different block size (2048 instead of 4096). 1510 assertInstallV4FailsWithError("v4-digest-v3-merkle-tree-different-block-size.apk", 1511 "Unsupported log2BlockSize: 11"); 1512 } 1513 testInstallV4WithWrongRawRootHash()1514 public void testInstallV4WithWrongRawRootHash() throws Exception { 1515 // V4 is only enabled on devices with Incremental feature 1516 if (!hasIncrementalFeature()) { 1517 return; 1518 } 1519 1520 // Editing apksigner with the wrong raw root hash in the v4 signature. 1521 assertInstallV4FailsWithError("v4-digest-v3-wrong-raw-root-hash.apk", "Failure"); 1522 } 1523 testInstallV4WithWrongSignatureBytes()1524 public void testInstallV4WithWrongSignatureBytes() throws Exception { 1525 // V4 is only enabled on devices with Incremental feature 1526 if (!hasIncrementalFeature()) { 1527 return; 1528 } 1529 1530 // Editing apksigner with the wrong signature bytes in the v4 signature. 1531 assertInstallV4FailsWithError("v4-digest-v3-wrong-sig-bytes.apk", 1532 "did not verify"); 1533 } 1534 testInstallV4WithWrongSignatureBytesSize()1535 public void testInstallV4WithWrongSignatureBytesSize() throws Exception { 1536 // V4 is only enabled on devices with Incremental feature 1537 if (!hasIncrementalFeature()) { 1538 return; 1539 } 1540 1541 // Editing apksigner with the wrong signature byte size in the v4 signature. 1542 assertInstallV4FailsWithError("v4-digest-v3-wrong-sig-bytes-size.apk", 1543 "Failure"); 1544 } 1545 testInstallV4WithNoMerkleTree()1546 public void testInstallV4WithNoMerkleTree() throws Exception { 1547 // V4 is only enabled on devices with Incremental feature 1548 if (!hasIncrementalFeature()) { 1549 return; 1550 } 1551 1552 // Editing apksigner to not include the Merkle tree. 1553 assertInstallV4FailsWithError("v4-digest-v3-no-merkle-tree.apk", 1554 "Failure"); 1555 } 1556 testInstallV4WithWithTrailingDataInMerkleTree()1557 public void testInstallV4WithWithTrailingDataInMerkleTree() throws Exception { 1558 // V4 is only enabled on devices with Incremental feature 1559 if (!hasIncrementalFeature()) { 1560 return; 1561 } 1562 1563 // Editing apksigner to add trailing data after the Merkle tree 1564 assertInstallV4FailsWithError("v4-digest-v3-merkle-tree-1mb-trailing-data.apk", 1565 "Failure"); 1566 } 1567 testInstallV4WithMerkleTreeBitsFlipped()1568 public void testInstallV4WithMerkleTreeBitsFlipped() throws Exception { 1569 // V4 is only enabled on devices with Incremental feature 1570 if (!hasIncrementalFeature()) { 1571 return; 1572 } 1573 1574 // Editing apksigner to flip few bits in the only node of the Merkle tree of a small app. 1575 assertInstallV4FailsWithError("v4-digest-v3-merkle-tree-bit-flipped.apk", 1576 "Failed to parse"); 1577 } 1578 testV4IncToV3NonIncSameKeyUpgradeSucceeds()1579 public void testV4IncToV3NonIncSameKeyUpgradeSucceeds() throws Exception { 1580 // V4 is only enabled on devices with Incremental feature 1581 if (!hasIncrementalFeature()) { 1582 return; 1583 } 1584 1585 // See cts/hostsidetests/appsecurity/res/pkgsigverify/generate-apks.sh for the command 1586 // to generate the apks 1587 assertInstallV4Succeeds("v4-inc-to-v3-noninc-ec-p256-appv1.apk"); 1588 1589 // non-incremental upgrade with the same key. 1590 assertInstallSucceeds("v4-inc-to-v3-noninc-ec-p256-appv2.apk"); 1591 } 1592 testV4IncToV3NonIncMismatchingKeyUpgradeFails()1593 public void testV4IncToV3NonIncMismatchingKeyUpgradeFails() throws Exception { 1594 // V4 is only enabled on devices with Incremental feature 1595 if (!hasIncrementalFeature()) { 1596 return; 1597 } 1598 1599 // See cts/hostsidetests/appsecurity/res/pkgsigverify/generate-apks.sh for the command 1600 // to generate the apks 1601 assertInstallV4Succeeds("v4-inc-to-v3-noninc-ec-p256-appv1.apk"); 1602 1603 // non-incremental upgrade with a mismatching key. 1604 assertInstallFailsWithError("v4-inc-to-v3-noninc-ec-p384-appv2.apk", 1605 "signatures do not match newer version"); 1606 } 1607 testV4IncToV3NonIncRotatedKeyUpgradeSucceeds()1608 public void testV4IncToV3NonIncRotatedKeyUpgradeSucceeds() throws Exception { 1609 // V4 is only enabled on devices with Incremental feature 1610 if (!hasIncrementalFeature()) { 1611 return; 1612 } 1613 1614 // See cts/hostsidetests/appsecurity/res/pkgsigverify/generate-apks.sh for the command 1615 // to generate the apks 1616 assertInstallV4Succeeds("v4-inc-to-v3-noninc-ec-p256-appv1.apk"); 1617 1618 // non-incremental upgrade with key rotation. 1619 assertInstallSucceeds("v4-inc-to-v3-noninc-ec-p384-rotated-ec-p256-appv2.apk"); 1620 } 1621 testV4IncToV3NonIncMismatchedRotatedKeyUpgradeFails()1622 public void testV4IncToV3NonIncMismatchedRotatedKeyUpgradeFails() throws Exception { 1623 // V4 is only enabled on devices with Incremental feature 1624 if (!hasIncrementalFeature()) { 1625 return; 1626 } 1627 1628 // See cts/hostsidetests/appsecurity/res/pkgsigverify/generate-apks.sh for the command 1629 // to generate the apks 1630 assertInstallV4Succeeds("v4-inc-to-v3-noninc-dsa-3072-appv1.apk"); 1631 1632 // non-incremental upgrade with key rotation mismatch with key used in app v1. 1633 assertInstallFailsWithError("v4-inc-to-v3-noninc-ec-p384-rotated-ec-p256-appv2.apk", 1634 "signatures do not match newer version"); 1635 } 1636 testV4IncToV2NonIncSameKeyUpgradeSucceeds()1637 public void testV4IncToV2NonIncSameKeyUpgradeSucceeds() throws Exception { 1638 // V4 is only enabled on devices with Incremental feature 1639 if (!hasIncrementalFeature()) { 1640 return; 1641 } 1642 1643 // See cts/hostsidetests/appsecurity/res/pkgsigverify/generate-apks.sh for the command 1644 // to generate the apks 1645 assertInstallV4Succeeds("v4-inc-to-v2-noninc-ec-p256-appv1.apk"); 1646 1647 // non-incremental upgrade with the same key. 1648 assertInstallSucceeds("v4-inc-to-v2-noninc-ec-p256-appv2.apk"); 1649 } 1650 testV4IncToV2NonIncMismatchingKeyUpgradeFails()1651 public void testV4IncToV2NonIncMismatchingKeyUpgradeFails() throws Exception { 1652 // V4 is only enabled on devices with Incremental feature 1653 if (!hasIncrementalFeature()) { 1654 return; 1655 } 1656 1657 // See cts/hostsidetests/appsecurity/res/pkgsigverify/generate-apks.sh for the command 1658 // to generate the apks 1659 assertInstallV4Succeeds("v4-inc-to-v2-noninc-ec-p256-appv1.apk"); 1660 1661 // non-incremental upgrade with a mismatching key. 1662 assertInstallFailsWithError("v4-inc-to-v2-noninc-ec-p384-appv2.apk", 1663 "signatures do not match newer version"); 1664 } 1665 testInstallV4UpdateAfterRotation()1666 public void testInstallV4UpdateAfterRotation() throws Exception { 1667 // V4 is only enabled on devices with Incremental feature 1668 if (!hasIncrementalFeature()) { 1669 return; 1670 } 1671 1672 // This test performs an end to end verification of the update of an app with a rotated 1673 // key. The app under test exports a bound service that performs its own PackageManager key 1674 // rotation API verification, and the instrumentation test binds to the service and invokes 1675 // the verifySignatures method to verify that the key rotation APIs return the expected 1676 // results. The instrumentation test app is signed with the same key and lineage as the 1677 // app under test to also provide a second app that can be used for the checkSignatures 1678 // verification. 1679 1680 // Install the initial versions of the apps; the test method verifies the app under test is 1681 // signed with the original signing key. 1682 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService.apk"); 1683 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest.apk"); 1684 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 1685 "verifySignatures_noRotation_succeeds"); 1686 1687 // Install the second version of the app signed with the rotated key. This test verifies the 1688 // app still functions as expected after the update with the rotated key. The 1689 // instrumentation test app is not updated here to allow verification of the pre-key 1690 // rotation behavior for the checkSignatures APIs. These APIs should behave similar to the 1691 // GET_SIGNATURES flag in that if one or both apps have a signing lineage if the oldest 1692 // signers in the lineage match then the methods should return that the signatures match 1693 // even if one is signed with a newer key in the lineage. 1694 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService_v2.apk"); 1695 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 1696 "verifySignatures_withRotation_succeeds"); 1697 1698 // Installs the third version of the app under test and the instrumentation test, both 1699 // signed with the same rotated key and lineage. This test is intended to verify that the 1700 // app can still be updated and function as expected after an update with a rotated key. 1701 assertInstallV4FromBuildSucceeds("CtsSignatureQueryService_v3.apk"); 1702 assertInstallV4FromBuildSucceeds("CtsSignatureQueryServiceTest_v2.apk"); 1703 Utils.runDeviceTests(getDevice(), SERVICE_TEST_PKG, SERVICE_TEST_CLASS, 1704 "verifySignatures_withRotation_succeeds"); 1705 } 1706 hasIncrementalFeature()1707 private boolean hasIncrementalFeature() throws Exception { 1708 return "true\n".equals(getDevice().executeShellCommand( 1709 "pm has-feature android.software.incremental_delivery")); 1710 } 1711 assertInstallSucceeds(String apkFilenameInResources)1712 private void assertInstallSucceeds(String apkFilenameInResources) throws Exception { 1713 String installResult = installPackageFromResource(apkFilenameInResources); 1714 if (installResult != null) { 1715 fail("Failed to install " + apkFilenameInResources + ": " + installResult); 1716 } 1717 } 1718 assertInstallEphemeralSucceeds(String apkFilenameInResources)1719 private void assertInstallEphemeralSucceeds(String apkFilenameInResources) throws Exception { 1720 String installResult = installEphemeralPackageFromResource(apkFilenameInResources); 1721 if (installResult != null) { 1722 fail("Failed to install " + apkFilenameInResources + ": " + installResult); 1723 } 1724 } 1725 assertInstallSucceedsForEach( String apkFilenamePatternInResources, String[] args)1726 private void assertInstallSucceedsForEach( 1727 String apkFilenamePatternInResources, String[] args) throws Exception { 1728 for (String arg : args) { 1729 String apkFilenameInResources = 1730 String.format(Locale.US, apkFilenamePatternInResources, arg); 1731 String installResult = installPackageFromResource(apkFilenameInResources); 1732 if (installResult != null) { 1733 fail("Failed to install " + apkFilenameInResources + ": " + installResult); 1734 } 1735 try { 1736 uninstallPackage(); 1737 } catch (Exception e) { 1738 throw new RuntimeException( 1739 "Failed to uninstall after installing " + apkFilenameInResources, e); 1740 } 1741 } 1742 } 1743 assertInstallV4Succeeds(String apkFilenameInResources)1744 private void assertInstallV4Succeeds(String apkFilenameInResources) throws Exception { 1745 String installResult = installV4PackageFromResource(apkFilenameInResources); 1746 if (!installResult.equals("Success\n")) { 1747 fail("Failed to install " + apkFilenameInResources + ": " + installResult); 1748 } 1749 } 1750 assertInstallV4FromBuildSucceeds(String apkName)1751 private void assertInstallV4FromBuildSucceeds(String apkName) throws Exception { 1752 String installResult = installV4PackageFromBuild(apkName); 1753 if (!installResult.equals("Success\n")) { 1754 fail("Failed to install " + apkName + ": " + installResult); 1755 } 1756 } 1757 assertInstallV4SucceedsAndUninstall(String apkFilenameInResources)1758 private void assertInstallV4SucceedsAndUninstall(String apkFilenameInResources) 1759 throws Exception { 1760 assertInstallV4Succeeds(apkFilenameInResources); 1761 try { 1762 uninstallPackage(); 1763 } catch (Exception e) { 1764 throw new RuntimeException( 1765 "Failed to uninstall after installing " + apkFilenameInResources, e); 1766 } 1767 } 1768 assertInstallV4FailsWithError(String apkFilenameInResources, String errorSubstring)1769 private void assertInstallV4FailsWithError(String apkFilenameInResources, String errorSubstring) 1770 throws Exception { 1771 String installResult = installV4PackageFromResource(apkFilenameInResources); 1772 if (installResult.equals("Success\n")) { 1773 fail("Install of " + apkFilenameInResources + " succeeded but was expected to fail" 1774 + " with \"" + errorSubstring + "\""); 1775 } 1776 assertContains( 1777 "Install failure message of " + apkFilenameInResources, 1778 errorSubstring, 1779 installResult); 1780 } 1781 assertInstallFailsWithError( String apkFilenameInResources, String errorSubstring)1782 private void assertInstallFailsWithError( 1783 String apkFilenameInResources, String errorSubstring) throws Exception { 1784 String installResult = installPackageFromResource(apkFilenameInResources); 1785 if (installResult == null) { 1786 fail("Install of " + apkFilenameInResources + " succeeded but was expected to fail" 1787 + " with \"" + errorSubstring + "\""); 1788 } 1789 assertContains( 1790 "Install failure message of " + apkFilenameInResources, 1791 errorSubstring, 1792 installResult); 1793 } 1794 assertInstallEphemeralFailsWithError( String apkFilenameInResources, String errorSubstring)1795 private void assertInstallEphemeralFailsWithError( 1796 String apkFilenameInResources, String errorSubstring) throws Exception { 1797 String installResult = installEphemeralPackageFromResource(apkFilenameInResources); 1798 if (installResult == null) { 1799 fail("Install of " + apkFilenameInResources + " succeeded but was expected to fail" 1800 + " with \"" + errorSubstring + "\""); 1801 } 1802 assertContains( 1803 "Install failure message of " + apkFilenameInResources, 1804 errorSubstring, 1805 installResult); 1806 } 1807 assertInstallFails(String apkFilenameInResources)1808 private void assertInstallFails(String apkFilenameInResources) throws Exception { 1809 String installResult = installPackageFromResource(apkFilenameInResources); 1810 if (installResult == null) { 1811 fail("Install of " + apkFilenameInResources + " succeeded but was expected to fail"); 1812 } 1813 } 1814 assertContains(String message, String expectedSubstring, String actual)1815 private static void assertContains(String message, String expectedSubstring, String actual) { 1816 String errorPrefix = ((message != null) && (message.length() > 0)) ? (message + ": ") : ""; 1817 if (actual == null) { 1818 fail(errorPrefix + "Expected to contain \"" + expectedSubstring + "\", but was null"); 1819 } 1820 if (!actual.contains(expectedSubstring)) { 1821 fail(errorPrefix + "Expected to contain \"" + expectedSubstring + "\", but was \"" 1822 + actual + "\""); 1823 } 1824 } 1825 installDeviceTestPkg()1826 private void installDeviceTestPkg() throws Exception { 1827 assertInstallFromBuildSucceeds(DEVICE_TESTS_APK); 1828 } 1829 assertInstallFromBuildSucceeds(String apkName)1830 private void assertInstallFromBuildSucceeds(String apkName) throws Exception { 1831 String result = installApkFromBuild(apkName); 1832 assertNull("failed to install " + apkName + ", Reason: " + result, result); 1833 } 1834 assertInstallFromBuildFails(String apkName)1835 private void assertInstallFromBuildFails(String apkName) throws Exception { 1836 String result = installApkFromBuild(apkName); 1837 assertNotNull("Successfully installed " + apkName + " when failure was expected", result); 1838 } 1839 installApkFromBuild(String apkName)1840 private String installApkFromBuild(String apkName) throws Exception { 1841 CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild); 1842 File apk = buildHelper.getTestFile(apkName); 1843 try { 1844 return getDevice().installPackage(apk, true, INSTALL_ARG_FORCE_QUERYABLE); 1845 } finally { 1846 getDevice().deleteFile("/data/local/tmp/" + apk.getName()); 1847 } 1848 } 1849 installPackageFromResource(String apkFilenameInResources, boolean ephemeral)1850 private String installPackageFromResource(String apkFilenameInResources, boolean ephemeral) 1851 throws IOException, DeviceNotAvailableException { 1852 // ITestDevice.installPackage API requires the APK to be install to be a File. We thus 1853 // copy the requested resource into a temporary file, attempt to install it, and delete the 1854 // file during cleanup. 1855 File apkFile = null; 1856 try { 1857 apkFile = getFileFromResource(apkFilenameInResources); 1858 if (ephemeral) { 1859 return getDevice().installPackage(apkFile, true, "--ephemeral", 1860 INSTALL_ARG_FORCE_QUERYABLE); 1861 } else { 1862 return getDevice().installPackage(apkFile, true, INSTALL_ARG_FORCE_QUERYABLE); 1863 } 1864 } finally { 1865 cleanUpFile(apkFile); 1866 getDevice().deleteFile("/data/local/tmp/" + apkFile.getName()); 1867 } 1868 } 1869 installV4PackageFromResource(String apkFilenameInResources)1870 private String installV4PackageFromResource(String apkFilenameInResources) 1871 throws IOException, DeviceNotAvailableException { 1872 File apkFile = null; 1873 File v4SignatureFile = null; 1874 String remoteApkFilePath = null, remoteV4SignaturePath = null; 1875 try { 1876 apkFile = getFileFromResource(apkFilenameInResources); 1877 v4SignatureFile = getFileFromResource(apkFilenameInResources + ".idsig"); 1878 remoteApkFilePath = pushFileToRemote(apkFile); 1879 remoteV4SignaturePath = pushFileToRemote(v4SignatureFile); 1880 return installV4Package(remoteApkFilePath); 1881 } finally { 1882 cleanUpFile(apkFile); 1883 cleanUpFile(v4SignatureFile); 1884 getDevice().deleteFile(remoteApkFilePath); 1885 getDevice().deleteFile(remoteV4SignaturePath); 1886 } 1887 } 1888 installV4PackageFromBuild(String apkName)1889 private String installV4PackageFromBuild(String apkName) 1890 throws IOException, DeviceNotAvailableException { 1891 CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild); 1892 File apkFile = buildHelper.getTestFile(apkName); 1893 File v4SignatureFile = buildHelper.getTestFile(apkName + ".idsig"); 1894 String remoteApkFilePath = pushFileToRemote(apkFile); 1895 String remoteV4SignaturePath = pushFileToRemote(v4SignatureFile); 1896 try { 1897 return installV4Package(remoteApkFilePath); 1898 } finally { 1899 getDevice().deleteFile(remoteApkFilePath); 1900 getDevice().deleteFile(remoteV4SignaturePath); 1901 } 1902 } 1903 pushFileToRemote(File localFile)1904 private String pushFileToRemote(File localFile) throws DeviceNotAvailableException { 1905 String remotePath = "/data/local/tmp/pkginstalltest-" + localFile.getName(); 1906 getDevice().pushFile(localFile, remotePath); 1907 return remotePath; 1908 } 1909 installV4Package(String remoteApkPath)1910 private String installV4Package(String remoteApkPath) 1911 throws DeviceNotAvailableException { 1912 String command = "pm install-incremental --force-queryable -t -g " + remoteApkPath; 1913 return getDevice().executeShellCommand(command); 1914 } 1915 getFileFromResource(String filenameInResources)1916 private File getFileFromResource(String filenameInResources) 1917 throws IOException, IllegalArgumentException { 1918 String fullResourceName = TEST_APK_RESOURCE_PREFIX + filenameInResources; 1919 File tempDir = FileUtil.createTempDir("pkginstalltest"); 1920 File file = new File(tempDir, filenameInResources); 1921 InputStream in = getClass().getResourceAsStream(fullResourceName); 1922 if (in == null) { 1923 throw new IllegalArgumentException("Resource not found: " + fullResourceName); 1924 } 1925 OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); 1926 byte[] buf = new byte[65536]; 1927 int chunkSize; 1928 while ((chunkSize = in.read(buf)) != -1) { 1929 out.write(buf, 0, chunkSize); 1930 } 1931 out.close(); 1932 return file; 1933 } 1934 cleanUpFile(File file)1935 private void cleanUpFile(File file) { 1936 if (file != null && file.exists()) { 1937 file.delete(); 1938 // Delete the parent dir as well which is a temp dir 1939 File parent = file.getParentFile(); 1940 if (parent.exists()) { 1941 parent.delete(); 1942 } 1943 } 1944 } 1945 installPackageFromResource(String apkFilenameInResources)1946 private String installPackageFromResource(String apkFilenameInResources) 1947 throws IOException, DeviceNotAvailableException { 1948 return installPackageFromResource(apkFilenameInResources, false); 1949 } 1950 installEphemeralPackageFromResource(String apkFilenameInResources)1951 private String installEphemeralPackageFromResource(String apkFilenameInResources) 1952 throws IOException, DeviceNotAvailableException { 1953 return installPackageFromResource(apkFilenameInResources, true); 1954 } 1955 uninstallPackage()1956 private String uninstallPackage() throws DeviceNotAvailableException { 1957 String result1 = getDevice().uninstallPackage(TEST_PKG); 1958 String result2 = getDevice().uninstallPackage(TEST_PKG2); 1959 return result1 != null ? result1 : result2; 1960 } 1961 uninstallCompanionPackages()1962 private String uninstallCompanionPackages() throws DeviceNotAvailableException { 1963 String result1 = getDevice().uninstallPackage(COMPANION_TEST_PKG); 1964 String result2 = getDevice().uninstallPackage(COMPANION2_TEST_PKG); 1965 String result3 = getDevice().uninstallPackage(COMPANION3_TEST_PKG); 1966 return Stream.of(result1, result2, result3) 1967 .filter(Objects::nonNull) 1968 .findFirst() 1969 .orElse(null); 1970 } 1971 uninstallDeviceTestPackage()1972 private String uninstallDeviceTestPackage() throws DeviceNotAvailableException { 1973 return getDevice().uninstallPackage(DEVICE_TESTS_PKG); 1974 } 1975 uninstallServicePackages()1976 private void uninstallServicePackages() throws DeviceNotAvailableException { 1977 getDevice().uninstallPackage(SERVICE_PKG); 1978 getDevice().uninstallPackage(SERVICE_TEST_PKG); 1979 } 1980 uninstallPackages()1981 private void uninstallPackages() throws DeviceNotAvailableException { 1982 uninstallPackage(); 1983 uninstallCompanionPackages(); 1984 uninstallDeviceTestPackage(); 1985 uninstallServicePackages(); 1986 } 1987 } 1988