/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm; import android.content.pm.PackageParser; import android.content.pm.Signature; import android.util.ArrayMap; import android.util.ArraySet; import android.util.LongSparseArray; import com.android.internal.util.ArrayUtils; import java.io.File; import java.io.IOException; import java.security.cert.CertificateException; import java.security.PublicKey; import android.test.AndroidTestCase; public class KeySetManagerServiceTest extends AndroidTestCase { private ArrayMap<String, PackageSetting> mPackagesMap; private KeySetManagerService mKsms; public PackageSetting generateFakePackageSetting(String name) { return new PackageSetting(name, name, new File(mContext.getCacheDir(), "fakeCodePath"), new File(mContext.getCacheDir(), "fakeResPath"), "", "", "", "", 1, 0, 0); } @Override public void setUp() throws Exception { super.setUp(); mPackagesMap = new ArrayMap<String, PackageSetting>(); mKsms = new KeySetManagerService(mPackagesMap); } public void testPackageKeySetDataConstructorUnassignend() { PackageKeySetData pksd = new PackageKeySetData(); assertEquals(PackageKeySetData.KEYSET_UNASSIGNED, pksd.getProperSigningKeySet()); assertNull(pksd.getUpgradeKeySets()); ArrayMap<String, Long> aliases = pksd.getAliases(); assertNotNull(aliases); assertEquals(0, aliases.size()); } /* test equivalence of PackageManager cert encoding and PackageParser manifest keys */ public void testPublicKeyCertReprEquiv() throws CertificateException { PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); PublicKey keyC = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyC); Signature sigA = new Signature(KeySetStrings.ctsKeySetCertA); Signature sigB = new Signature(KeySetStrings.ctsKeySetCertB); Signature sigC = new Signature(KeySetStrings.ctsKeySetCertC); assertNotNull(keyA); assertNotNull(keyB); assertNotNull(keyC); assertEquals(keyA, sigA.getPublicKey()); assertEquals(keyB, sigB.getPublicKey()); assertEquals(keyC, sigC.getPublicKey()); byte[] bArrayPk = keyA.getEncoded(); byte[] bArrayCert = sigA.getPublicKey().getEncoded(); assertEquals(bArrayPk.length, bArrayCert.length); assertEquals(true, ArrayUtils.equals(bArrayPk, bArrayCert, bArrayPk.length)); bArrayPk = keyB.getEncoded(); bArrayCert = sigB.getPublicKey().getEncoded(); assertEquals(bArrayPk.length, bArrayCert.length); assertEquals(true, ArrayUtils.equals(bArrayPk, bArrayCert, bArrayPk.length)); bArrayPk = keyC.getEncoded(); bArrayCert = sigC.getPublicKey().getEncoded(); assertEquals(bArrayPk.length, bArrayCert.length); assertEquals(true, ArrayUtils.equals(bArrayPk, bArrayCert, bArrayPk.length)); } public void testEncodePublicKey() throws IOException { ArrayMap<String, PackageSetting> packagesMap = new ArrayMap<String, PackageSetting>(); KeySetManagerService ksms = new KeySetManagerService(packagesMap); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); PublicKey keyC = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyC); assertEquals(ksms.encodePublicKey(keyA), KeySetStrings.ctsKeySetPublicKeyA); assertEquals(ksms.encodePublicKey(keyB), KeySetStrings.ctsKeySetPublicKeyB); assertEquals(ksms.encodePublicKey(keyC), KeySetStrings.ctsKeySetPublicKeyC); } /* * Add the keyset information for a package to a system w/no previous keysets */ public void testAddSigningKSToPackageEmpty() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect signing key and add */ ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(1, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(1); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(1))); assertEquals(1, ps.keySetData.getProperSigningKeySet()); } /* * upgrade an app (same packagename) with same keyset and verify that * nothing changed. */ public void testAddSigningKSToPackageUpgradeSame() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect signing key and add */ ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); /* add again, to represent upgrade of package */ mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(1, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(1); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(1))); assertEquals(1, ps.keySetData.getProperSigningKeySet()); } /* * upgrade an app (same packagename) with different unique keyset and verify * that the old was removed. */ public void testAddSigningKSToPackageUpgradeDiff() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect signing key and add */ ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); /* now upgrade with new key */ PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); signingKeys.removeAt(0); signingKeys.add(keyB); mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2)); assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2)); assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(1, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(2); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(2))); assertEquals(2, ps.keySetData.getProperSigningKeySet()); } /* * upgrade an app (same packagename) with different keyset and verify * that the old had its ref count reduced due to reference by other ps. */ public void testAddSigningKSToPackageUpgradeDiff2() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps1 = generateFakePackageSetting("packageA"); mPackagesMap.put(ps1.name, ps1); PackageSetting ps2 = generateFakePackageSetting("packageB"); mPackagesMap.put(ps2.name, ps2); /* collect signing key and add */ ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys); mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys); /* now upgrade with new key */ PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); signingKeys.removeAt(0); signingKeys.add(keyB); mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2)); assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1)); assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(2, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(1); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(1))); mapping = ksMapping.get(2); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(2))); assertEquals(2, ps1.keySetData.getProperSigningKeySet()); assertEquals(1, ps2.keySetData.getProperSigningKeySet()); } /* * Add orthoganal keyset info to system and ensure previous keysets are * unmodified. */ public void testAddSigningKSToPackageNewOrtho() throws ReflectiveOperationException { /* create PackageSettings and add to Settings mPackages */ PackageSetting ps1 = generateFakePackageSetting("packageA"); mPackagesMap.put(ps1.name, ps1); PackageSetting ps2 = generateFakePackageSetting("packageB"); mPackagesMap.put(ps2.name, ps2); /* collect signing key and add */ ArraySet<PublicKey> signingKeys1 = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys1.add(keyA); mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys1); /* collect second signing key and add */ ArraySet<PublicKey> signingKeys2 = new ArraySet<PublicKey>(); PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); signingKeys2.add(keyB); mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys2); /* verify first is unchanged */ assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(2, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(1); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(1))); assertEquals(1, ps1.keySetData.getProperSigningKeySet()); /* verify second */ assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2)); assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2)); mapping = ksMapping.get(2); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(2))); assertEquals(2, ps2.keySetData.getProperSigningKeySet()); } /* * Add identical keyset info to system via new package and ensure previous * keysets has reference count incremented */ public void testAddSigningKSToPackageNewSame() throws ReflectiveOperationException { /* create PackageSettings and add to Settings mPackages */ PackageSetting ps1 = generateFakePackageSetting("packageA"); mPackagesMap.put(ps1.name, ps1); PackageSetting ps2 = generateFakePackageSetting("packageB"); mPackagesMap.put(ps2.name, ps2); /* collect signing key and add */ ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys); /* add again for second package */ mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys); assertEquals(2, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(1, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(1); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(1))); assertEquals(1, ps1.keySetData.getProperSigningKeySet()); assertEquals(1, ps2.keySetData.getProperSigningKeySet()); } /* * add a package which is signed by a keyset which contains a previously seen * public key and make sure its refernces are incremented. */ public void testAddSigningKSToPackageSuper() throws ReflectiveOperationException { /* create PackageSettings and add to Settings mPackages */ PackageSetting ps1 = generateFakePackageSetting("packageA"); mPackagesMap.put(ps1.name, ps1); PackageSetting ps2 = generateFakePackageSetting("packageB"); mPackagesMap.put(ps2.name, ps2); /* collect signing key and add */ ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys); /* give ps2 a superset (add keyB) */ PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); signingKeys.add(keyB); mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2)); assertEquals(2, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2)); assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1)); assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(2, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(1); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(1))); mapping = ksMapping.get(2); assertEquals(2, mapping.size()); assertTrue(mapping.contains(new Long(1))); assertTrue(mapping.contains(new Long(2))); assertEquals(1, ps1.keySetData.getProperSigningKeySet()); assertEquals(2, ps2.keySetData.getProperSigningKeySet()); } /* * Upgrade an app (same pkgName) with different keyset which contains a public * key from the previous keyset. Verify old keyset removed and pub key ref * count is accurate. */ public void testAddSigningKSToPackageUpgradeDiffSuper() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect signing key and add */ ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); /* now with additional key */ PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); signingKeys.add(keyB); mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2)); assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 3)); /* the pub key is removed w/prev keyset and may be either 2 or 3 */ assertTrue(keyA.equals(KeySetUtils.getPubKey(mKsms, 2)) || keyA.equals(KeySetUtils.getPubKey(mKsms, 3))); assertTrue(keyB.equals(KeySetUtils.getPubKey(mKsms, 2)) || keyB.equals(KeySetUtils.getPubKey(mKsms, 3))); assertFalse(KeySetUtils.getPubKey(mKsms, 2).equals(KeySetUtils.getPubKey(mKsms, 3))); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(1, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(2); assertEquals(2, mapping.size()); assertTrue(mapping.contains(new Long(2))); assertTrue(mapping.contains(new Long(3))); assertEquals(2, ps.keySetData.getProperSigningKeySet()); } /* add a defined keyset make sure it shows up */ public void testAddDefinedKSToPackageEmpty() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect key and add */ ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>(); ArraySet<PublicKey> keys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(1, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(1); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(1))); assertNotNull(ps.keySetData.getAliases().get("aliasA")); assertEquals(new Long(1), ps.keySetData.getAliases().get("aliasA")); } /* add 2 defined keysets which refer to same keyset and make sure ref-ct is 2 */ public void testAddDefinedKSToPackageDoubleAlias() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect key and add */ ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>(); ArraySet<PublicKey> keys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); definedKS.put("aliasA2", keys); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertEquals(2, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(1, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(1); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(1))); assertNotNull(ps.keySetData.getAliases().get("aliasA")); assertEquals(new Long(1), ps.keySetData.getAliases().get("aliasA")); assertNotNull(ps.keySetData.getAliases().get("aliasA2")); assertEquals(new Long(1), ps.keySetData.getAliases().get("aliasA2")); } /* upgrd defined keyset ortho (make sure previous is removed for pkg) */ public void testAddDefinedKSToPackageOrthoUpgr() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect key and add */ ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>(); ArraySet<PublicKey> keys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); /* now upgrade to different defined key-set */ keys = new ArraySet<PublicKey>(); PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); keys.add(keyB); definedKS.remove("aliasA"); definedKS.put("aliasB", keys); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2)); assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(1, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(2); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(2))); assertNull(ps.keySetData.getAliases().get("aliasA")); assertNotNull(ps.keySetData.getAliases().get("aliasB")); assertEquals(new Long(2), ps.keySetData.getAliases().get("aliasB")); } /* upgrd defined keyset ortho but reuse alias (make sure old is removed and * alias points to new keyset) */ public void testAddDefinedKSToPackageOrthoUpgrAliasSame() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect key and add */ ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>(); ArraySet<PublicKey> keys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); /* now upgrade to different set w/same alias as before */ keys = new ArraySet<PublicKey>(); PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); keys.add(keyB); definedKS.put("aliasA", keys); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2)); assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(1, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(2); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(2))); assertNotNull(ps.keySetData.getAliases().get("aliasA")); assertEquals(new Long(2), ps.keySetData.getAliases().get("aliasA")); } /* Start with defined ks of (A, B) and upgrade to (B, C). Make sure B is * unchanged. */ public void testAddDefinedKSToPackageOverlapUpgr() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect keys A and B and add */ ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>(); ArraySet<PublicKey> keys1 = new ArraySet<PublicKey>(); ArraySet<PublicKey> keys2 = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); keys1.add(keyA); keys2.add(keyB); definedKS.put("aliasA", keys1); definedKS.put("aliasB", keys2); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); /* now upgrade to different set (B, C) */ keys1 = new ArraySet<PublicKey>(); PublicKey keyC = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyC); keys1.add(keyC); definedKS.remove("aliasA"); definedKS.put("aliasC", keys1); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 3)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 3)); assertEquals(keyC, KeySetUtils.getPubKey(mKsms, 3)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(2, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(3); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(3))); assertEquals(new Long(3), ps.keySetData.getAliases().get("aliasC")); /* either keyset w/keyA or w/keyB was added first, address both cases */ if (1 == KeySetUtils.getKeySetRefCount(mKsms, 1)) { /* keyB was added first and should have keyset 1 and pub-key 1 */ assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 2)); assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 2)); assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 1)); mapping = ksMapping.get(1); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(1))); assertEquals(new Long(1), ps.keySetData.getAliases().get("aliasB")); } else { /* keyA was added first and keyB has id 2 */ assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2)); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2)); mapping = ksMapping.get(2); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(2))); assertEquals(new Long(2), ps.keySetData.getAliases().get("aliasB")); } assertNull(ps.keySetData.getAliases().get("aliasA")); } /* add defined keyset, remove it, add again and make sure diff id. */ public void testAddDefinedKSToPackageThree() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect key and add */ ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>(); ArraySet<PublicKey> keys1 = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys1.add(keyA); definedKS.put("aliasA", keys1); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); /* now upgrade to different set */ ArraySet<PublicKey> keys2 = new ArraySet<PublicKey>(); PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); keys2.add(keyB); definedKS.remove("aliasA"); definedKS.put("aliasB", keys2); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); /* upgrade back to original */ definedKS.remove("aliasB"); definedKS.put("aliasA", keys1); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 2)); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 3)); assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1)); assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 2)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 3)); assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 3)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(1, ksMapping.size()); ArraySet<Long> mapping = ksMapping.get(3); assertEquals(1, mapping.size()); assertTrue(mapping.contains(new Long(3))); assertEquals(new Long(3), ps.keySetData.getAliases().get("aliasA")); } /* add upgrade keyset for existing defined keyset and check that it is recorded */ public void testAddUpgradeKSToPackageEmpty() { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect key and add, and denote as an upgrade keyset */ ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>(); ArraySet<PublicKey> keys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); ArraySet<String> upgradeKS = new ArraySet<String>(); upgradeKS.add("aliasA"); mKsms.addUpgradeKeySetsToPackageLPw(ps, upgradeKS); assertEquals(1, ps.keySetData.getUpgradeKeySets().length); assertEquals(1, ps.keySetData.getUpgradeKeySets()[0]); } /* add upgrade keyset for non-existing defined and check that it compains */ public void testAddUpgradeKSToPackageWrong() { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect key and add and try to specify bogus upgrade keyset */ ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>(); ArraySet<PublicKey> keys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); ArraySet<String> upgradeKS = new ArraySet<String>(); upgradeKS.add("aliasB"); try { mKsms.addUpgradeKeySetsToPackageLPw(ps, upgradeKS); } catch (IllegalArgumentException e) { /* should have been caught in packagemanager, so exception thrown */ return; } fail("Expected IllegalArgumentException when adding undefined upgrade keyset!!"); } /* upgrade from defined keysets w/upgrade to different defined keysets and * make sure the previously specified upgrade keyset has been removed. */ public void testAddUpgradeKSToPackageDisappear() { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect key and add */ ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>(); ArraySet<PublicKey> keys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); ArraySet<String> upgradeKS = new ArraySet<String>(); upgradeKS.add("aliasA"); mKsms.addUpgradeKeySetsToPackageLPw(ps, upgradeKS); keys = new ArraySet<PublicKey>(); PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); keys.add(keyB); definedKS.remove("aliasA"); definedKS.put("aliasB", keys); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertNull(ps.keySetData.getUpgradeKeySets()); } /* remove package and validate that keyset and public keys are removed */ public void testRemoveAppKSDataUnique() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect signing key and add */ ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); /* remove its references */ mKsms.removeAppKeySetDataLPw(ps.name); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(0, ksMapping.size()); assertEquals(PackageKeySetData.KEYSET_UNASSIGNED, ps.keySetData.getProperSigningKeySet()); } /* remove package and validate that keysets remain if defined elsewhere but * have refcounts decreased. */ public void testRemoveAppKSDataDup() throws ReflectiveOperationException { /* create PackageSettings and add to Settings mPackages */ PackageSetting ps1 = generateFakePackageSetting("packageA"); mPackagesMap.put(ps1.name, ps1); PackageSetting ps2 = generateFakePackageSetting("packageB"); mPackagesMap.put(ps2.name, ps2); /* collect signing key and add for both packages */ ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys); mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys); /* remove references from first package */ mKsms.removeAppKeySetDataLPw(ps1.name); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(1, ksMapping.size()); assertEquals(PackageKeySetData.KEYSET_UNASSIGNED, ps1.keySetData.getProperSigningKeySet()); assertEquals(1, ps2.keySetData.getProperSigningKeySet()); } /* remove package which used defined and upgrade keysets and ensure removed */ public void testRemoveAppKSDataDefined() throws ReflectiveOperationException { /* create PackageSetting and add to Settings mPackages */ PackageSetting ps = generateFakePackageSetting("packageA"); mPackagesMap.put(ps.name, ps); /* collect key and add */ ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>(); ArraySet<PublicKey> keys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); /* removal requires signing keyset to be specified (since all apps are * assumed to have it). We skipped this in the defined tests, but can't * here. */ mKsms.addSigningKeySetToPackageLPw(ps, keys); definedKS.put("aliasA", keys); mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); ArraySet<String> upgradeKS = new ArraySet<String>(); upgradeKS.add("aliasA"); mKsms.addUpgradeKeySetsToPackageLPw(ps, upgradeKS); mKsms.removeAppKeySetDataLPw(ps.name); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1)); LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms); assertEquals(0, ksMapping.size()); assertEquals(PackageKeySetData.KEYSET_UNASSIGNED, ps.keySetData.getProperSigningKeySet()); assertEquals(0, ps.keySetData.getAliases().size()); assertNull(ps.keySetData.getUpgradeKeySets()); } }