1/*
2 * Copyright (C) 2015 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
17package com.android.server.pm;
18
19
20import android.content.pm.PackageParser;
21import android.content.pm.Signature;
22import android.util.ArrayMap;
23import android.util.ArraySet;
24import android.util.LongSparseArray;
25import com.android.internal.util.ArrayUtils;
26
27import java.io.File;
28import java.io.IOException;
29import java.security.cert.CertificateException;
30import java.security.PublicKey;
31
32import android.test.AndroidTestCase;
33
34public class KeySetManagerServiceTest extends AndroidTestCase {
35
36    private ArrayMap<String, PackageSetting> mPackagesMap;
37    private KeySetManagerService mKsms;
38
39    public PackageSetting generateFakePackageSetting(String name) {
40        return new PackageSetting(name, name, new File(mContext.getCacheDir(), "fakeCodePath"),
41                new File(mContext.getCacheDir(), "fakeResPath"), "", "", "",
42                "", 1, 0, 0, null, null, 0 /*sharedUserId*/, null /*usesStaticLibraries*/,
43                null /*usesStaticLibrariesVersions*/);
44    }
45
46    @Override
47    public void setUp() throws Exception {
48        super.setUp();
49        mPackagesMap = new ArrayMap<String, PackageSetting>();
50        mKsms = new KeySetManagerService(mPackagesMap);
51    }
52
53    public void testPackageKeySetDataConstructorUnassignend() {
54        PackageKeySetData pksd = new PackageKeySetData();
55        assertEquals(PackageKeySetData.KEYSET_UNASSIGNED, pksd.getProperSigningKeySet());
56        assertNull(pksd.getUpgradeKeySets());
57        ArrayMap<String, Long> aliases = pksd.getAliases();
58        assertNotNull(aliases);
59        assertEquals(0, aliases.size());
60    }
61
62    /* test equivalence of PackageManager cert encoding and PackageParser manifest keys */
63    public void testPublicKeyCertReprEquiv() throws CertificateException {
64        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
65        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
66        PublicKey keyC = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyC);
67
68        Signature sigA = new Signature(KeySetStrings.ctsKeySetCertA);
69        Signature sigB = new Signature(KeySetStrings.ctsKeySetCertB);
70        Signature sigC = new Signature(KeySetStrings.ctsKeySetCertC);
71
72        assertNotNull(keyA);
73        assertNotNull(keyB);
74        assertNotNull(keyC);
75
76        assertEquals(keyA, sigA.getPublicKey());
77        assertEquals(keyB, sigB.getPublicKey());
78        assertEquals(keyC, sigC.getPublicKey());
79
80        byte[] bArrayPk = keyA.getEncoded();
81        byte[] bArrayCert = sigA.getPublicKey().getEncoded();
82        assertEquals(bArrayPk.length, bArrayCert.length);
83        assertEquals(true, ArrayUtils.equals(bArrayPk, bArrayCert, bArrayPk.length));
84
85        bArrayPk = keyB.getEncoded();
86        bArrayCert = sigB.getPublicKey().getEncoded();
87        assertEquals(bArrayPk.length, bArrayCert.length);
88        assertEquals(true, ArrayUtils.equals(bArrayPk, bArrayCert, bArrayPk.length));
89
90        bArrayPk = keyC.getEncoded();
91        bArrayCert = sigC.getPublicKey().getEncoded();
92        assertEquals(bArrayPk.length, bArrayCert.length);
93        assertEquals(true, ArrayUtils.equals(bArrayPk, bArrayCert, bArrayPk.length));
94    }
95
96    public void testEncodePublicKey() throws IOException {
97        ArrayMap<String, PackageSetting> packagesMap = new ArrayMap<String, PackageSetting>();
98        KeySetManagerService ksms = new KeySetManagerService(packagesMap);
99
100        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
101        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
102        PublicKey keyC = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyC);
103
104        assertEquals(ksms.encodePublicKey(keyA), KeySetStrings.ctsKeySetPublicKeyA);
105        assertEquals(ksms.encodePublicKey(keyB), KeySetStrings.ctsKeySetPublicKeyB);
106        assertEquals(ksms.encodePublicKey(keyC), KeySetStrings.ctsKeySetPublicKeyC);
107    }
108
109    /*
110     * Add the keyset information for a package to a system w/no previous keysets
111     */
112    public void testAddSigningKSToPackageEmpty() throws ReflectiveOperationException {
113
114        /* create PackageSetting and add to Settings mPackages */
115        PackageSetting ps = generateFakePackageSetting("packageA");
116        mPackagesMap.put(ps.name, ps);
117
118        /* collect signing key and add */
119        ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>();
120        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
121        signingKeys.add(keyA);
122        mKsms.addSigningKeySetToPackageLPw(ps, signingKeys);
123
124        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
125        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
126        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
127        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
128        assertEquals(1, ksMapping.size());
129        ArraySet<Long> mapping = ksMapping.get(1);
130        assertEquals(1, mapping.size());
131        assertTrue(mapping.contains(new Long(1)));
132        assertEquals(1, ps.keySetData.getProperSigningKeySet());
133    }
134
135    /*
136     * upgrade an app (same packagename) with same keyset and verify that
137     * nothing changed.
138     */
139    public void testAddSigningKSToPackageUpgradeSame() throws ReflectiveOperationException {
140
141        /* create PackageSetting and add to Settings mPackages */
142        PackageSetting ps = generateFakePackageSetting("packageA");
143        mPackagesMap.put(ps.name, ps);
144
145        /* collect signing key and add */
146        ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>();
147        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
148        signingKeys.add(keyA);
149        mKsms.addSigningKeySetToPackageLPw(ps, signingKeys);
150
151        /* add again, to represent upgrade of package */
152        mKsms.addSigningKeySetToPackageLPw(ps, signingKeys);
153
154        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
155        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
156        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
157        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
158        assertEquals(1, ksMapping.size());
159        ArraySet<Long> mapping = ksMapping.get(1);
160        assertEquals(1, mapping.size());
161        assertTrue(mapping.contains(new Long(1)));
162        assertEquals(1, ps.keySetData.getProperSigningKeySet());
163    }
164
165    /*
166     * upgrade an app (same packagename) with different unique keyset and verify
167     * that the old was removed.
168     */
169    public void testAddSigningKSToPackageUpgradeDiff() throws ReflectiveOperationException {
170
171        /* create PackageSetting and add to Settings mPackages */
172        PackageSetting ps = generateFakePackageSetting("packageA");
173        mPackagesMap.put(ps.name, ps);
174
175        /* collect signing key and add */
176        ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>();
177        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
178        signingKeys.add(keyA);
179        mKsms.addSigningKeySetToPackageLPw(ps, signingKeys);
180
181        /* now upgrade with new key */
182        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
183        signingKeys.removeAt(0);
184        signingKeys.add(keyB);
185        mKsms.addSigningKeySetToPackageLPw(ps, signingKeys);
186
187        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
188        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
189        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
190        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
191        assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
192        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
193        assertEquals(1, ksMapping.size());
194        ArraySet<Long> mapping = ksMapping.get(2);
195        assertEquals(1, mapping.size());
196        assertTrue(mapping.contains(new Long(2)));
197        assertEquals(2, ps.keySetData.getProperSigningKeySet());
198    }
199
200    /*
201     * upgrade an app (same packagename) with different keyset and verify
202     * that the old had its ref count reduced due to reference by other ps.
203     */
204    public void testAddSigningKSToPackageUpgradeDiff2() throws ReflectiveOperationException {
205
206        /* create PackageSetting and add to Settings mPackages */
207        PackageSetting ps1 = generateFakePackageSetting("packageA");
208        mPackagesMap.put(ps1.name, ps1);
209        PackageSetting ps2 = generateFakePackageSetting("packageB");
210        mPackagesMap.put(ps2.name, ps2);
211
212        /* collect signing key and add */
213        ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>();
214        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
215        signingKeys.add(keyA);
216        mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys);
217        mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys);
218
219        /* now upgrade with new key */
220        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
221        signingKeys.removeAt(0);
222        signingKeys.add(keyB);
223        mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys);
224
225        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
226        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
227        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
228        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
229        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
230        assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
231        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
232        assertEquals(2, ksMapping.size());
233        ArraySet<Long> mapping = ksMapping.get(1);
234        assertEquals(1, mapping.size());
235        assertTrue(mapping.contains(new Long(1)));
236        mapping = ksMapping.get(2);
237        assertEquals(1, mapping.size());
238        assertTrue(mapping.contains(new Long(2)));
239        assertEquals(2, ps1.keySetData.getProperSigningKeySet());
240        assertEquals(1, ps2.keySetData.getProperSigningKeySet());
241    }
242
243    /*
244     * Add orthoganal keyset info to system and ensure previous keysets are
245     * unmodified.
246     */
247    public void testAddSigningKSToPackageNewOrtho() throws ReflectiveOperationException {
248
249        /* create PackageSettings and add to Settings mPackages */
250        PackageSetting ps1 = generateFakePackageSetting("packageA");
251        mPackagesMap.put(ps1.name, ps1);
252        PackageSetting ps2 = generateFakePackageSetting("packageB");
253        mPackagesMap.put(ps2.name, ps2);
254
255        /* collect signing key and add */
256        ArraySet<PublicKey> signingKeys1 = new ArraySet<PublicKey>();
257        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
258        signingKeys1.add(keyA);
259        mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys1);
260
261        /* collect second signing key and add */
262        ArraySet<PublicKey> signingKeys2 = new ArraySet<PublicKey>();
263        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
264        signingKeys2.add(keyB);
265        mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys2);
266
267        /* verify first is unchanged */
268        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
269        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
270        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
271        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
272        assertEquals(2, ksMapping.size());
273        ArraySet<Long> mapping = ksMapping.get(1);
274        assertEquals(1, mapping.size());
275        assertTrue(mapping.contains(new Long(1)));
276        assertEquals(1, ps1.keySetData.getProperSigningKeySet());
277
278        /* verify second */
279        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
280        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
281        assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
282        mapping = ksMapping.get(2);
283        assertEquals(1, mapping.size());
284        assertTrue(mapping.contains(new  Long(2)));
285        assertEquals(2, ps2.keySetData.getProperSigningKeySet());
286    }
287
288    /*
289     * Add identical keyset info to system via new package and ensure previous
290     * keysets has reference count incremented
291     */
292    public void testAddSigningKSToPackageNewSame() throws ReflectiveOperationException {
293
294        /* create PackageSettings and add to Settings mPackages */
295        PackageSetting ps1 = generateFakePackageSetting("packageA");
296        mPackagesMap.put(ps1.name, ps1);
297        PackageSetting ps2 = generateFakePackageSetting("packageB");
298        mPackagesMap.put(ps2.name, ps2);
299
300        /* collect signing key and add */
301        ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>();
302        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
303        signingKeys.add(keyA);
304        mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys);
305
306        /* add again for second package */
307        mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys);
308
309        assertEquals(2, KeySetUtils.getKeySetRefCount(mKsms, 1));
310        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
311        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
312        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
313        assertEquals(1, ksMapping.size());
314        ArraySet<Long> mapping = ksMapping.get(1);
315        assertEquals(1, mapping.size());
316        assertTrue(mapping.contains(new Long(1)));
317        assertEquals(1, ps1.keySetData.getProperSigningKeySet());
318        assertEquals(1, ps2.keySetData.getProperSigningKeySet());
319    }
320
321    /*
322     * add a package which is signed by a keyset which contains a previously seen
323     * public key and make sure its refernces are incremented.
324     */
325    public void testAddSigningKSToPackageSuper() throws ReflectiveOperationException {
326
327        /* create PackageSettings and add to Settings mPackages */
328        PackageSetting ps1 = generateFakePackageSetting("packageA");
329        mPackagesMap.put(ps1.name, ps1);
330        PackageSetting ps2 = generateFakePackageSetting("packageB");
331        mPackagesMap.put(ps2.name, ps2);
332
333        /* collect signing key and add */
334        ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>();
335        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
336        signingKeys.add(keyA);
337        mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys);
338
339        /* give ps2 a superset (add keyB) */
340        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
341        signingKeys.add(keyB);
342        mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys);
343
344        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
345        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
346        assertEquals(2, KeySetUtils.getPubKeyRefCount(mKsms, 1));
347        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
348        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
349        assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
350        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
351        assertEquals(2, ksMapping.size());
352        ArraySet<Long> mapping = ksMapping.get(1);
353        assertEquals(1, mapping.size());
354        assertTrue(mapping.contains(new Long(1)));
355        mapping = ksMapping.get(2);
356        assertEquals(2, mapping.size());
357        assertTrue(mapping.contains(new Long(1)));
358        assertTrue(mapping.contains(new Long(2)));
359        assertEquals(1, ps1.keySetData.getProperSigningKeySet());
360        assertEquals(2, ps2.keySetData.getProperSigningKeySet());
361    }
362
363    /*
364     * Upgrade an app (same pkgName) with different keyset which contains a public
365     * key from the previous keyset.  Verify old keyset removed and pub key ref
366     * count is accurate.
367     */
368    public void testAddSigningKSToPackageUpgradeDiffSuper() throws ReflectiveOperationException {
369
370        /* create PackageSetting and add to Settings mPackages */
371        PackageSetting ps = generateFakePackageSetting("packageA");
372        mPackagesMap.put(ps.name, ps);
373
374        /* collect signing key and add */
375        ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>();
376        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
377        signingKeys.add(keyA);
378        mKsms.addSigningKeySetToPackageLPw(ps, signingKeys);
379
380        /* now with additional key */
381        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
382        signingKeys.add(keyB);
383        mKsms.addSigningKeySetToPackageLPw(ps, signingKeys);
384
385        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
386        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
387        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
388        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
389        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 3));
390
391        /* the pub key is removed w/prev keyset and may be either 2 or 3 */
392        assertTrue(keyA.equals(KeySetUtils.getPubKey(mKsms, 2)) || keyA.equals(KeySetUtils.getPubKey(mKsms, 3)));
393        assertTrue(keyB.equals(KeySetUtils.getPubKey(mKsms, 2)) || keyB.equals(KeySetUtils.getPubKey(mKsms, 3)));
394        assertFalse(KeySetUtils.getPubKey(mKsms, 2).equals(KeySetUtils.getPubKey(mKsms, 3)));
395        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
396        assertEquals(1, ksMapping.size());
397        ArraySet<Long> mapping = ksMapping.get(2);
398        assertEquals(2, mapping.size());
399        assertTrue(mapping.contains(new Long(2)));
400        assertTrue(mapping.contains(new Long(3)));
401        assertEquals(2, ps.keySetData.getProperSigningKeySet());
402    }
403
404    /* add a defined keyset make sure it shows up */
405    public void testAddDefinedKSToPackageEmpty() throws ReflectiveOperationException {
406
407        /* create PackageSetting and add to Settings mPackages */
408        PackageSetting ps = generateFakePackageSetting("packageA");
409        mPackagesMap.put(ps.name, ps);
410
411        /* collect key and add */
412        ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>();
413        ArraySet<PublicKey> keys = new ArraySet<PublicKey>();
414        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
415        keys.add(keyA);
416        definedKS.put("aliasA", keys);
417        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
418
419        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
420        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
421        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
422        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
423        assertEquals(1, ksMapping.size());
424        ArraySet<Long> mapping = ksMapping.get(1);
425        assertEquals(1, mapping.size());
426        assertTrue(mapping.contains(new Long(1)));
427        assertNotNull(ps.keySetData.getAliases().get("aliasA"));
428        assertEquals(new Long(1), ps.keySetData.getAliases().get("aliasA"));
429    }
430
431    /* add 2 defined keysets which refer to same keyset and make sure ref-ct is 2 */
432    public void testAddDefinedKSToPackageDoubleAlias() throws ReflectiveOperationException {
433
434        /* create PackageSetting and add to Settings mPackages */
435        PackageSetting ps = generateFakePackageSetting("packageA");
436        mPackagesMap.put(ps.name, ps);
437
438        /* collect key and add */
439        ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>();
440        ArraySet<PublicKey> keys = new ArraySet<PublicKey>();
441        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
442        keys.add(keyA);
443        definedKS.put("aliasA", keys);
444        definedKS.put("aliasA2", keys);
445        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
446
447        assertEquals(2, KeySetUtils.getKeySetRefCount(mKsms, 1));
448        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
449        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
450        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
451        assertEquals(1, ksMapping.size());
452        ArraySet<Long> mapping = ksMapping.get(1);
453        assertEquals(1, mapping.size());
454        assertTrue(mapping.contains(new Long(1)));
455        assertNotNull(ps.keySetData.getAliases().get("aliasA"));
456        assertEquals(new Long(1), ps.keySetData.getAliases().get("aliasA"));
457        assertNotNull(ps.keySetData.getAliases().get("aliasA2"));
458        assertEquals(new Long(1), ps.keySetData.getAliases().get("aliasA2"));
459    }
460
461    /* upgrd defined keyset ortho (make sure previous is removed for pkg) */
462    public void testAddDefinedKSToPackageOrthoUpgr() throws ReflectiveOperationException {
463
464        /* create PackageSetting and add to Settings mPackages */
465        PackageSetting ps = generateFakePackageSetting("packageA");
466        mPackagesMap.put(ps.name, ps);
467
468        /* collect key and add */
469        ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>();
470        ArraySet<PublicKey> keys = new ArraySet<PublicKey>();
471        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
472        keys.add(keyA);
473        definedKS.put("aliasA", keys);
474        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
475
476        /* now upgrade to different defined key-set */
477        keys = new ArraySet<PublicKey>();
478        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
479        keys.add(keyB);
480        definedKS.remove("aliasA");
481        definedKS.put("aliasB", keys);
482        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
483
484        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
485        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
486        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
487        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
488        assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
489        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
490        assertEquals(1, ksMapping.size());
491        ArraySet<Long> mapping = ksMapping.get(2);
492        assertEquals(1, mapping.size());
493        assertTrue(mapping.contains(new Long(2)));
494        assertNull(ps.keySetData.getAliases().get("aliasA"));
495        assertNotNull(ps.keySetData.getAliases().get("aliasB"));
496        assertEquals(new Long(2), ps.keySetData.getAliases().get("aliasB"));
497    }
498
499    /* upgrd defined keyset ortho but reuse alias (make sure old is removed and
500     * alias points to new keyset)
501     */
502    public void testAddDefinedKSToPackageOrthoUpgrAliasSame() throws ReflectiveOperationException {
503
504        /* create PackageSetting and add to Settings mPackages */
505        PackageSetting ps = generateFakePackageSetting("packageA");
506        mPackagesMap.put(ps.name, ps);
507
508        /* collect key and add */
509        ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>();
510        ArraySet<PublicKey> keys = new ArraySet<PublicKey>();
511        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
512        keys.add(keyA);
513        definedKS.put("aliasA", keys);
514        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
515
516        /* now upgrade to different set w/same alias as before */
517        keys = new ArraySet<PublicKey>();
518        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
519        keys.add(keyB);
520        definedKS.put("aliasA", keys);
521        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
522
523        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
524        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
525        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
526        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
527        assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
528        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
529        assertEquals(1, ksMapping.size());
530        ArraySet<Long> mapping = ksMapping.get(2);
531        assertEquals(1, mapping.size());
532        assertTrue(mapping.contains(new Long(2)));
533        assertNotNull(ps.keySetData.getAliases().get("aliasA"));
534        assertEquals(new Long(2), ps.keySetData.getAliases().get("aliasA"));
535    }
536
537     /* Start with defined ks of (A, B) and upgrade to (B, C).  Make sure B is
538      * unchanged. */
539    public void testAddDefinedKSToPackageOverlapUpgr() throws ReflectiveOperationException {
540
541        /* create PackageSetting and add to Settings mPackages */
542        PackageSetting ps = generateFakePackageSetting("packageA");
543        mPackagesMap.put(ps.name, ps);
544
545        /* collect keys A and B and add */
546        ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>();
547        ArraySet<PublicKey> keys1 = new ArraySet<PublicKey>();
548        ArraySet<PublicKey> keys2 = new ArraySet<PublicKey>();
549        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
550        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
551        keys1.add(keyA);
552        keys2.add(keyB);
553        definedKS.put("aliasA", keys1);
554        definedKS.put("aliasB", keys2);
555        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
556
557        /* now upgrade to different set (B, C) */
558        keys1 = new ArraySet<PublicKey>();
559        PublicKey keyC = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyC);
560        keys1.add(keyC);
561        definedKS.remove("aliasA");
562        definedKS.put("aliasC", keys1);
563        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
564
565        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 3));
566        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 3));
567        assertEquals(keyC, KeySetUtils.getPubKey(mKsms, 3));
568        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
569        assertEquals(2, ksMapping.size());
570        ArraySet<Long> mapping = ksMapping.get(3);
571        assertEquals(1, mapping.size());
572        assertTrue(mapping.contains(new Long(3)));
573        assertEquals(new Long(3), ps.keySetData.getAliases().get("aliasC"));
574
575        /* either keyset w/keyA or w/keyB was added first, address both cases */
576        if (1 == KeySetUtils.getKeySetRefCount(mKsms, 1)) {
577
578            /* keyB was added first and should have keyset 1 and pub-key 1 */
579            assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
580            assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 2));
581            assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 2));
582            assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 1));
583            mapping = ksMapping.get(1);
584            assertEquals(1, mapping.size());
585            assertTrue(mapping.contains(new Long(1)));
586            assertEquals(new Long(1), ps.keySetData.getAliases().get("aliasB"));
587        } else {
588
589            /* keyA was added first and keyB has id 2 */
590            assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
591            assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
592            assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
593            assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
594            assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
595            mapping = ksMapping.get(2);
596            assertEquals(1, mapping.size());
597            assertTrue(mapping.contains(new Long(2)));
598            assertEquals(new Long(2), ps.keySetData.getAliases().get("aliasB"));
599        }
600        assertNull(ps.keySetData.getAliases().get("aliasA"));
601    }
602
603    /* add defined keyset, remove it, add again and make sure diff id. */
604    public void testAddDefinedKSToPackageThree() throws ReflectiveOperationException {
605
606        /* create PackageSetting and add to Settings mPackages */
607        PackageSetting ps = generateFakePackageSetting("packageA");
608        mPackagesMap.put(ps.name, ps);
609
610        /* collect key and add */
611        ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>();
612        ArraySet<PublicKey> keys1 = new ArraySet<PublicKey>();
613        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
614        keys1.add(keyA);
615        definedKS.put("aliasA", keys1);
616        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
617
618        /* now upgrade to different set */
619        ArraySet<PublicKey> keys2 = new ArraySet<PublicKey>();
620        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
621        keys2.add(keyB);
622        definedKS.remove("aliasA");
623        definedKS.put("aliasB", keys2);
624        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
625
626        /* upgrade back to original */
627        definedKS.remove("aliasB");
628        definedKS.put("aliasA", keys1);
629        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
630
631        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
632        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 2));
633        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 3));
634        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
635        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 2));
636        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 3));
637        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 3));
638        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
639        assertEquals(1, ksMapping.size());
640        ArraySet<Long> mapping = ksMapping.get(3);
641        assertEquals(1, mapping.size());
642        assertTrue(mapping.contains(new Long(3)));
643        assertEquals(new Long(3), ps.keySetData.getAliases().get("aliasA"));
644    }
645
646    /* add upgrade keyset for existing defined keyset and check that it is recorded */
647    public void testAddUpgradeKSToPackageEmpty() {
648
649        /* create PackageSetting and add to Settings mPackages */
650        PackageSetting ps = generateFakePackageSetting("packageA");
651        mPackagesMap.put(ps.name, ps);
652
653        /* collect key and add, and denote as an upgrade keyset */
654        ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>();
655        ArraySet<PublicKey> keys = new ArraySet<PublicKey>();
656        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
657        keys.add(keyA);
658        definedKS.put("aliasA", keys);
659        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
660        ArraySet<String> upgradeKS = new ArraySet<String>();
661        upgradeKS.add("aliasA");
662        mKsms.addUpgradeKeySetsToPackageLPw(ps, upgradeKS);
663
664        assertEquals(1, ps.keySetData.getUpgradeKeySets().length);
665        assertEquals(1, ps.keySetData.getUpgradeKeySets()[0]);
666    }
667
668    /* add upgrade keyset for non-existing defined and check that it compains */
669    public void testAddUpgradeKSToPackageWrong() {
670
671        /* create PackageSetting and add to Settings mPackages */
672        PackageSetting ps = generateFakePackageSetting("packageA");
673        mPackagesMap.put(ps.name, ps);
674
675        /* collect key and add and try to specify bogus upgrade keyset */
676        ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>();
677        ArraySet<PublicKey> keys = new ArraySet<PublicKey>();
678        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
679        keys.add(keyA);
680        definedKS.put("aliasA", keys);
681        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
682        ArraySet<String> upgradeKS = new ArraySet<String>();
683        upgradeKS.add("aliasB");
684        try {
685            mKsms.addUpgradeKeySetsToPackageLPw(ps, upgradeKS);
686        } catch (IllegalArgumentException e) {
687
688            /* should have been caught in packagemanager, so exception thrown */
689            return;
690        }
691        fail("Expected IllegalArgumentException when adding undefined upgrade keyset!!");
692    }
693
694    /* upgrade from defined keysets w/upgrade to different defined keysets and
695     * make sure the previously specified upgrade keyset has been removed. */
696    public void testAddUpgradeKSToPackageDisappear() {
697
698        /* create PackageSetting and add to Settings mPackages */
699        PackageSetting ps = generateFakePackageSetting("packageA");
700        mPackagesMap.put(ps.name, ps);
701
702        /* collect key and add */
703        ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>();
704        ArraySet<PublicKey> keys = new ArraySet<PublicKey>();
705        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
706        keys.add(keyA);
707        definedKS.put("aliasA", keys);
708        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
709        ArraySet<String> upgradeKS = new ArraySet<String>();
710        upgradeKS.add("aliasA");
711        mKsms.addUpgradeKeySetsToPackageLPw(ps, upgradeKS);
712
713        keys = new ArraySet<PublicKey>();
714        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
715        keys.add(keyB);
716        definedKS.remove("aliasA");
717        definedKS.put("aliasB", keys);
718        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
719        assertNull(ps.keySetData.getUpgradeKeySets());
720    }
721
722    /* remove package and validate that keyset and public keys are removed */
723    public void testRemoveAppKSDataUnique() throws ReflectiveOperationException {
724
725        /* create PackageSetting and add to Settings mPackages */
726        PackageSetting ps = generateFakePackageSetting("packageA");
727        mPackagesMap.put(ps.name, ps);
728
729        /* collect signing key and add */
730        ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>();
731        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
732        signingKeys.add(keyA);
733        mKsms.addSigningKeySetToPackageLPw(ps, signingKeys);
734
735        /* remove its references */
736        mKsms.removeAppKeySetDataLPw(ps.name);
737        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
738        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
739        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
740        assertEquals(0, ksMapping.size());
741        assertEquals(PackageKeySetData.KEYSET_UNASSIGNED, ps.keySetData.getProperSigningKeySet());
742    }
743
744    /* remove package and validate that keysets remain if defined elsewhere but
745     * have refcounts decreased. */
746    public void testRemoveAppKSDataDup() throws ReflectiveOperationException {
747
748        /* create PackageSettings and add to Settings mPackages */
749        PackageSetting ps1 = generateFakePackageSetting("packageA");
750        mPackagesMap.put(ps1.name, ps1);
751        PackageSetting ps2 = generateFakePackageSetting("packageB");
752        mPackagesMap.put(ps2.name, ps2);
753
754        /* collect signing key and add for both packages */
755        ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>();
756        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
757        signingKeys.add(keyA);
758        mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys);
759        mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys);
760
761        /* remove references from first package */
762        mKsms.removeAppKeySetDataLPw(ps1.name);
763
764        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
765        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
766        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
767        assertEquals(1, ksMapping.size());
768        assertEquals(PackageKeySetData.KEYSET_UNASSIGNED, ps1.keySetData.getProperSigningKeySet());
769        assertEquals(1, ps2.keySetData.getProperSigningKeySet());
770    }
771
772    /* remove package which used defined and upgrade keysets and ensure  removed */
773    public void testRemoveAppKSDataDefined() throws ReflectiveOperationException {
774
775        /* create PackageSetting and add to Settings mPackages */
776        PackageSetting ps = generateFakePackageSetting("packageA");
777        mPackagesMap.put(ps.name, ps);
778
779        /* collect key and add */
780        ArrayMap<String, ArraySet<PublicKey>> definedKS = new ArrayMap<String, ArraySet<PublicKey>>();
781        ArraySet<PublicKey> keys = new ArraySet<PublicKey>();
782        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
783        keys.add(keyA);
784
785        /* removal requires signing keyset to be specified (since all apps are
786         * assumed to have it).  We skipped this in the defined tests, but can't
787         * here. */
788        mKsms.addSigningKeySetToPackageLPw(ps, keys);
789
790        definedKS.put("aliasA", keys);
791        mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS);
792        ArraySet<String> upgradeKS = new ArraySet<String>();
793        upgradeKS.add("aliasA");
794        mKsms.addUpgradeKeySetsToPackageLPw(ps, upgradeKS);
795        mKsms.removeAppKeySetDataLPw(ps.name);
796
797        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
798        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
799        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
800        assertEquals(0, ksMapping.size());
801        assertEquals(PackageKeySetData.KEYSET_UNASSIGNED, ps.keySetData.getProperSigningKeySet());
802        assertEquals(0, ps.keySetData.getAliases().size());
803        assertNull(ps.keySetData.getUpgradeKeySets());
804    }
805}
806