KeySetManagerService.java revision 0888276a1c6cd4077770844615848674de21dab3
1/*
2 * Copyright (C) 2013 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
19import android.content.pm.PackageParser;
20import android.os.Binder;
21import android.util.ArraySet;
22import android.util.Base64;
23import android.util.Slog;
24import android.util.LongSparseArray;
25
26import java.io.IOException;
27import java.io.PrintWriter;
28import java.security.PublicKey;
29import java.util.Map;
30import java.util.Set;
31
32import org.xmlpull.v1.XmlPullParser;
33import org.xmlpull.v1.XmlPullParserException;
34import org.xmlpull.v1.XmlSerializer;
35
36/*
37 * Manages system-wide KeySet state.
38 */
39public class KeySetManagerService {
40
41    static final String TAG = "KeySetManagerService";
42
43    /* original keysets implementation had no versioning info, so this is the first */
44    public static final int FIRST_VERSION = 1;
45
46    public static final int CURRENT_VERSION = FIRST_VERSION;
47
48    /** Sentinel value returned when a {@code KeySet} is not found. */
49    public static final long KEYSET_NOT_FOUND = -1;
50
51    /** Sentinel value returned when public key is not found. */
52    protected static final long PUBLIC_KEY_NOT_FOUND = -1;
53
54    private final LongSparseArray<KeySetHandle> mKeySets;
55
56    private final LongSparseArray<PublicKey> mPublicKeys;
57
58    protected final LongSparseArray<ArraySet<Long>> mKeySetMapping;
59
60    private final Map<String, PackageSetting> mPackages;
61
62    private static long lastIssuedKeySetId = 0;
63
64    private static long lastIssuedKeyId = 0;
65
66    public KeySetManagerService(Map<String, PackageSetting> packages) {
67        mKeySets = new LongSparseArray<KeySetHandle>();
68        mPublicKeys = new LongSparseArray<PublicKey>();
69        mKeySetMapping = new LongSparseArray<ArraySet<Long>>();
70        mPackages = packages;
71    }
72
73    /**
74     * Determine if a package is signed by the given KeySet.
75     *
76     * Returns false if the package was not signed by all the
77     * keys in the KeySet.
78     *
79     * Returns true if the package was signed by at least the
80     * keys in the given KeySet.
81     *
82     * Note that this can return true for multiple KeySets.
83     */
84    public boolean packageIsSignedByLPr(String packageName, KeySetHandle ks) {
85        PackageSetting pkg = mPackages.get(packageName);
86        if (pkg == null) {
87            throw new NullPointerException("Invalid package name");
88        }
89        if (pkg.keySetData == null) {
90            throw new NullPointerException("Package has no KeySet data");
91        }
92        long id = getIdByKeySetLPr(ks);
93        if (id == KEYSET_NOT_FOUND) {
94                return false;
95        }
96        return pkg.keySetData.packageIsSignedBy(id);
97    }
98
99    /**
100     * Determine if a package is signed by the given KeySet.
101     *
102     * Returns false if the package was not signed by all the
103     * keys in the KeySet, or if the package was signed by keys
104     * not in the KeySet.
105     *
106     * Note that this can return only for one KeySet.
107     */
108    public boolean packageIsSignedByExactlyLPr(String packageName, KeySetHandle ks) {
109        PackageSetting pkg = mPackages.get(packageName);
110        if (pkg == null) {
111            throw new NullPointerException("Invalid package name");
112        }
113        if (pkg.keySetData == null
114            || pkg.keySetData.getProperSigningKeySet()
115            == PackageKeySetData.KEYSET_UNASSIGNED) {
116            throw new NullPointerException("Package has no KeySet data");
117        }
118        long id = getIdByKeySetLPr(ks);
119        return pkg.keySetData.getProperSigningKeySet() == id;
120    }
121
122    /**
123     * This informs the system that the given package has defined a KeySet
124     * in its manifest that a) contains the given keys and b) is named
125     * alias by that package.
126     */
127    public void addDefinedKeySetToPackageLPw(String packageName,
128            ArraySet<PublicKey> keys, String alias) {
129        if ((packageName == null) || (keys == null) || (alias == null)) {
130            Slog.w(TAG, "Got null argument for a defined keyset, ignoring!");
131            return;
132        }
133        PackageSetting pkg = mPackages.get(packageName);
134        if (pkg == null) {
135            throw new NullPointerException("Unknown package");
136        }
137        // Add to KeySets, then to package
138        KeySetHandle ks = addKeySetLPw(keys);
139        long id = getIdByKeySetLPr(ks);
140        pkg.keySetData.addDefinedKeySet(id, alias);
141    }
142
143    /**
144     * This informs the system that the given package has defined a KeySet
145     * alias in its manifest to be an upgradeKeySet.  This must be called
146     * after all of the defined KeySets have been added.
147     */
148    public void addUpgradeKeySetToPackageLPw(String packageName, String alias) {
149        if ((packageName == null) || (alias == null)) {
150            Slog.w(TAG, "Got null argument for a defined keyset, ignoring!");
151            return;
152        }
153        PackageSetting pkg = mPackages.get(packageName);
154        if (pkg == null) {
155            throw new NullPointerException("Unknown package");
156        }
157        pkg.keySetData.addUpgradeKeySet(alias);
158    }
159
160    /**
161     * Similar to the above, this informs the system that the given package
162     * was signed by the provided KeySet.
163     */
164    public void addSigningKeySetToPackageLPw(String packageName,
165            ArraySet<PublicKey> signingKeys) {
166        if ((packageName == null) || (signingKeys == null)) {
167            Slog.w(TAG, "Got null argument for a signing keyset, ignoring!");
168            return;
169        }
170        // add the signing KeySet
171        KeySetHandle ks = addKeySetLPw(signingKeys);
172        long id = getIdByKeySetLPr(ks);
173        ArraySet<Long> publicKeyIds = mKeySetMapping.get(id);
174        if (publicKeyIds == null) {
175            throw new NullPointerException("Got invalid KeySet id");
176        }
177        // attach it to the package
178        PackageSetting pkg = mPackages.get(packageName);
179        if (pkg == null) {
180            throw new NullPointerException("No such package!");
181        }
182        pkg.keySetData.setProperSigningKeySet(id);
183        // for each KeySet which is a subset of the one above, add the
184        // KeySet id to the package's signing KeySets
185        for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) {
186            long keySetID = mKeySets.keyAt(keySetIndex);
187            ArraySet<Long> definedKeys = mKeySetMapping.get(keySetID);
188            if (publicKeyIds.containsAll(definedKeys)) {
189                pkg.keySetData.addSigningKeySet(keySetID);
190            }
191        }
192    }
193
194    /**
195     * Fetches the stable identifier associated with the given KeySet. Returns
196     * {@link #KEYSET_NOT_FOUND} if the KeySet... wasn't found.
197     */
198    private long getIdByKeySetLPr(KeySetHandle ks) {
199        for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) {
200            KeySetHandle value = mKeySets.valueAt(keySetIndex);
201            if (ks.equals(value)) {
202                return mKeySets.keyAt(keySetIndex);
203            }
204        }
205        return KEYSET_NOT_FOUND;
206    }
207
208    /**
209     * Fetches the KeySet corresponding to the given stable identifier.
210     *
211     * Returns {@link #KEYSET_NOT_FOUND} if the identifier doesn't
212     * identify a {@link KeySet}.
213     */
214    public KeySetHandle getKeySetByIdLPr(long id) {
215        return mKeySets.get(id);
216    }
217
218    /**
219     * Fetches the {@link KeySetHandle} that a given package refers to by the
220     * provided alias. Returns null if the package is unknown or does not have a
221     * KeySet corresponding to that alias.
222     */
223    public KeySetHandle getKeySetByAliasAndPackageNameLPr(String packageName, String alias) {
224        PackageSetting p = mPackages.get(packageName);
225        if (p == null || p.keySetData == null) {
226                return null;
227        }
228        Long keySetId = p.keySetData.getAliases().get(alias);
229        if (keySetId == null) {
230            throw new IllegalArgumentException("Unknown KeySet alias: " + alias);
231        }
232        return mKeySets.get(keySetId);
233    }
234
235    /**
236     * Fetches the {@link PublicKey public keys} which belong to the specified
237     * KeySet id.
238     *
239     * Returns {@code null} if the identifier doesn't
240     * identify a {@link KeySetHandle}.
241     */
242    public ArraySet<PublicKey> getPublicKeysFromKeySetLPr(long id) {
243        if(mKeySetMapping.get(id) == null) {
244            return null;
245        }
246        ArraySet<PublicKey> mPubKeys = new ArraySet<PublicKey>();
247        for (long pkId : mKeySetMapping.get(id)) {
248            mPubKeys.add(mPublicKeys.get(pkId));
249        }
250        return mPubKeys;
251    }
252
253    /**
254     * Fetches the proper {@link KeySetHandle KeySet} that signed the given
255     * package.
256     *
257     * @throws IllegalArgumentException if the package has no keyset data.
258     * @throws NullPointerException if the package is unknown.
259     */
260    public KeySetHandle  getSigningKeySetByPackageNameLPr(String packageName) {
261        PackageSetting p = mPackages.get(packageName);
262        if (p == null
263            || p.keySetData == null
264            || p.keySetData.getProperSigningKeySet()
265            == PackageKeySetData.KEYSET_UNASSIGNED) {
266            return null;
267        }
268        return mKeySets.get(p.keySetData.getProperSigningKeySet());
269    }
270
271    /**
272     * Fetches all the known {@link KeySetHandle KeySets} that may upgrade the given
273     * package.
274     *
275     * @throws IllegalArgumentException if the package has no keyset data.
276     * @throws NullPointerException if the package is unknown.
277     */
278    public ArraySet<KeySetHandle> getUpgradeKeySetsByPackageNameLPr(String packageName) {
279        ArraySet<KeySetHandle> upgradeKeySets = new ArraySet<KeySetHandle>();
280        PackageSetting p = mPackages.get(packageName);
281        if (p == null) {
282            throw new NullPointerException("Unknown package");
283        }
284        if (p.keySetData == null) {
285            throw new IllegalArgumentException("Package has no keySet data");
286        }
287        if (p.keySetData.isUsingUpgradeKeySets()) {
288            for (long l : p.keySetData.getUpgradeKeySets()) {
289                upgradeKeySets.add(mKeySets.get(l));
290            }
291        }
292        return upgradeKeySets;
293    }
294
295    /**
296     * Creates a new KeySet corresponding to the given keys.
297     *
298     * If the {@link PublicKey PublicKeys} aren't known to the system, this
299     * adds them. Otherwise, they're deduped.
300     *
301     * If the KeySet isn't known to the system, this adds that and creates the
302     * mapping to the PublicKeys. If it is known, then it's deduped.
303     *
304     * If the KeySet isn't known to the system, this adds it to all appropriate
305     * signingKeySets
306     *
307     * Throws if the provided set is {@code null}.
308     */
309    private KeySetHandle addKeySetLPw(ArraySet<PublicKey> keys) {
310        if (keys == null) {
311            throw new NullPointerException("Provided keys cannot be null");
312        }
313        // add each of the keys in the provided set
314        ArraySet<Long> addedKeyIds = new ArraySet<Long>(keys.size());
315        for (PublicKey k : keys) {
316            long id = addPublicKeyLPw(k);
317            addedKeyIds.add(id);
318        }
319
320        // check to see if the resulting keyset is new
321        long existingKeySetId = getIdFromKeyIdsLPr(addedKeyIds);
322        if (existingKeySetId != KEYSET_NOT_FOUND) {
323            return mKeySets.get(existingKeySetId);
324        }
325
326        // create the KeySet object
327        KeySetHandle ks = new KeySetHandle();
328        // get the first unoccupied slot in mKeySets
329        long id = getFreeKeySetIDLPw();
330        // add the KeySet object to it
331        mKeySets.put(id, ks);
332        // add the stable key ids to the mapping
333        mKeySetMapping.put(id, addedKeyIds);
334        // add this KeySet id to all packages which are signed by it
335        for (String pkgName : mPackages.keySet()) {
336            PackageSetting p = mPackages.get(pkgName);
337            if (p.keySetData != null) {
338                long pProperSigning = p.keySetData.getProperSigningKeySet();
339                if (pProperSigning != PackageKeySetData.KEYSET_UNASSIGNED) {
340                    ArraySet<Long> pSigningKeys = mKeySetMapping.get(pProperSigning);
341                    if (pSigningKeys.containsAll(addedKeyIds)) {
342                        p.keySetData.addSigningKeySet(id);
343                    }
344                }
345            }
346        }
347        // go home
348        return ks;
349    }
350
351    /**
352     * Adds the given PublicKey to the system, deduping as it goes.
353     */
354    private long addPublicKeyLPw(PublicKey key) {
355        // check if the public key is new
356        long existingKeyId = getIdForPublicKeyLPr(key);
357        if (existingKeyId != PUBLIC_KEY_NOT_FOUND) {
358            return existingKeyId;
359        }
360        // if it's new find the first unoccupied slot in the public keys
361        long id = getFreePublicKeyIdLPw();
362        // add the public key to it
363        mPublicKeys.put(id, key);
364        // return the stable identifier
365        return id;
366    }
367
368    /**
369     * Finds the stable identifier for a KeySet based on a set of PublicKey stable IDs.
370     *
371     * Returns KEYSET_NOT_FOUND if there isn't one.
372     */
373    private long getIdFromKeyIdsLPr(Set<Long> publicKeyIds) {
374        for (int keyMapIndex = 0; keyMapIndex < mKeySetMapping.size(); keyMapIndex++) {
375            ArraySet<Long> value = mKeySetMapping.valueAt(keyMapIndex);
376            if (value.equals(publicKeyIds)) {
377                return mKeySetMapping.keyAt(keyMapIndex);
378            }
379        }
380        return KEYSET_NOT_FOUND;
381    }
382
383    /**
384     * Finds the stable identifier for a PublicKey or PUBLIC_KEY_NOT_FOUND.
385     */
386    private long getIdForPublicKeyLPr(PublicKey k) {
387        String encodedPublicKey = new String(k.getEncoded());
388        for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) {
389            PublicKey value = mPublicKeys.valueAt(publicKeyIndex);
390            String encodedExistingKey = new String(value.getEncoded());
391            if (encodedPublicKey.equals(encodedExistingKey)) {
392                return mPublicKeys.keyAt(publicKeyIndex);
393            }
394        }
395        return PUBLIC_KEY_NOT_FOUND;
396    }
397
398    /**
399     * Gets an unused stable identifier for a KeySet.
400     */
401    private long getFreeKeySetIDLPw() {
402        lastIssuedKeySetId += 1;
403        return lastIssuedKeySetId;
404    }
405
406    /**
407     * Same as above, but for public keys.
408     */
409    private long getFreePublicKeyIdLPw() {
410        lastIssuedKeyId += 1;
411        return lastIssuedKeyId;
412    }
413
414    public void removeAppKeySetDataLPw(String packageName) {
415        // Get the package's known keys and KeySets
416        ArraySet<Long> deletableKeySets = getOriginalKeySetsByPackageNameLPr(packageName);
417        ArraySet<Long> deletableKeys = new ArraySet<Long>();
418        final int origDksSize = deletableKeySets.size();
419        for (int i = 0; i < origDksSize; i++) {
420            ArraySet<Long> knownKeys = mKeySetMapping.get(deletableKeySets.valueAt(i));
421            if (knownKeys != null) {
422                deletableKeys.addAll(knownKeys);
423            }
424        }
425
426        // Now remove the keys and KeySets on which any other package relies
427        for (String pkgName : mPackages.keySet()) {
428            if (pkgName.equals(packageName)) {
429                continue;
430            }
431            ArraySet<Long> knownKeySets = getOriginalKeySetsByPackageNameLPr(pkgName);
432            deletableKeySets.removeAll(knownKeySets);
433            final int kksSize = knownKeySets.size();
434            for (int i = 0; i < kksSize; i++) {
435                ArraySet<Long> knownKeys = mKeySetMapping.get(knownKeySets.valueAt(i));
436                if (knownKeys != null) {
437                    deletableKeys.removeAll(knownKeys);
438                }
439            }
440        }
441
442        // The remaining keys and KeySets are not relied on by any other
443        // application and so can be safely deleted.
444        final int dksSize = deletableKeySets.size();
445        for (int i = 0; i < dksSize; i++) {
446            Long ks = deletableKeySets.valueAt(i);
447            mKeySets.delete(ks);
448            mKeySetMapping.delete(ks);
449        }
450        final int dkSize = deletableKeys.size();
451        for (int i = 0; i < dkSize; i++) {
452            mPublicKeys.delete(deletableKeys.valueAt(i));
453        }
454
455        // Now remove the deleted KeySets from each package's signingKeySets
456        for (String pkgName : mPackages.keySet()) {
457            PackageSetting p = mPackages.get(pkgName);
458            for (int i = 0; i < dksSize; i++) {
459                Long ks = deletableKeySets.valueAt(i);
460                p.keySetData.removeSigningKeySet(ks);
461            }
462        }
463        // Finally, remove all KeySets from the original package
464        PackageSetting p = mPackages.get(packageName);
465        clearPackageKeySetDataLPw(p);
466    }
467
468    private void clearPackageKeySetDataLPw(PackageSetting p) {
469        p.keySetData.removeAllSigningKeySets();
470        p.keySetData.removeAllUpgradeKeySets();
471        p.keySetData.removeAllDefinedKeySets();
472        return;
473    }
474
475    private ArraySet<Long> getOriginalKeySetsByPackageNameLPr(String packageName) {
476        PackageSetting p = mPackages.get(packageName);
477        if (p == null) {
478            throw new NullPointerException("Unknown package");
479        }
480        if (p.keySetData == null) {
481            throw new IllegalArgumentException("Package has no keySet data");
482        }
483        ArraySet<Long> knownKeySets = new ArraySet<Long>();
484        knownKeySets.add(p.keySetData.getProperSigningKeySet());
485        if (p.keySetData.isUsingDefinedKeySets()) {
486            for (long ks : p.keySetData.getDefinedKeySets()) {
487                knownKeySets.add(ks);
488            }
489        }
490        return knownKeySets;
491    }
492
493    public String encodePublicKey(PublicKey k) throws IOException {
494        return new String(Base64.encode(k.getEncoded(), 0));
495    }
496
497    public void dumpLPr(PrintWriter pw, String packageName,
498                        PackageManagerService.DumpState dumpState) {
499        boolean printedHeader = false;
500        for (Map.Entry<String, PackageSetting> e : mPackages.entrySet()) {
501            String keySetPackage = e.getKey();
502            if (packageName != null && !packageName.equals(keySetPackage)) {
503                continue;
504            }
505            if (!printedHeader) {
506                if (dumpState.onTitlePrinted())
507                    pw.println();
508                pw.println("Key Set Manager:");
509                printedHeader = true;
510            }
511            PackageSetting pkg = e.getValue();
512            pw.print("  ["); pw.print(keySetPackage); pw.println("]");
513            if (pkg.keySetData != null) {
514                boolean printedLabel = false;
515                for (Map.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) {
516                    if (!printedLabel) {
517                        pw.print("      KeySets Aliases: ");
518                        printedLabel = true;
519                    } else {
520                        pw.print(", ");
521                    }
522                    pw.print(entry.getKey());
523                    pw.print('=');
524                    pw.print(Long.toString(entry.getValue()));
525                }
526                if (printedLabel) {
527                    pw.println("");
528                }
529                printedLabel = false;
530                if (pkg.keySetData.isUsingDefinedKeySets()) {
531                    for (long keySetId : pkg.keySetData.getDefinedKeySets()) {
532                        if (!printedLabel) {
533                            pw.print("      Defined KeySets: ");
534                            printedLabel = true;
535                        } else {
536                            pw.print(", ");
537                        }
538                        pw.print(Long.toString(keySetId));
539                    }
540                }
541                if (printedLabel) {
542                    pw.println("");
543                }
544                printedLabel = false;
545                final long[] signingKeySets = pkg.keySetData.getSigningKeySets();
546                if (signingKeySets != null) {
547                    for (long keySetId : signingKeySets) {
548                        if (!printedLabel) {
549                            pw.print("      Signing KeySets: ");
550                            printedLabel = true;
551                        } else {
552                            pw.print(", ");
553                        }
554                        pw.print(Long.toString(keySetId));
555                    }
556                }
557                if (printedLabel) {
558                    pw.println("");
559                }
560                printedLabel = false;
561                if (pkg.keySetData.isUsingUpgradeKeySets()) {
562                    for (long keySetId : pkg.keySetData.getUpgradeKeySets()) {
563                        if (!printedLabel) {
564                            pw.print("      Upgrade KeySets: ");
565                            printedLabel = true;
566                        } else {
567                            pw.print(", ");
568                        }
569                        pw.print(Long.toString(keySetId));
570                    }
571                }
572                if (printedLabel) {
573                    pw.println("");
574                }
575            }
576        }
577    }
578
579    void writeKeySetManagerServiceLPr(XmlSerializer serializer) throws IOException {
580        serializer.startTag(null, "keyset-settings");
581        serializer.attribute(null, "version", Integer.toString(CURRENT_VERSION));
582        writePublicKeysLPr(serializer);
583        writeKeySetsLPr(serializer);
584        serializer.startTag(null, "lastIssuedKeyId");
585        serializer.attribute(null, "value", Long.toString(lastIssuedKeyId));
586        serializer.endTag(null, "lastIssuedKeyId");
587        serializer.startTag(null, "lastIssuedKeySetId");
588        serializer.attribute(null, "value", Long.toString(lastIssuedKeySetId));
589        serializer.endTag(null, "lastIssuedKeySetId");
590        serializer.endTag(null, "keyset-settings");
591    }
592
593    void writePublicKeysLPr(XmlSerializer serializer) throws IOException {
594        serializer.startTag(null, "keys");
595        for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) {
596            long id = mPublicKeys.keyAt(pKeyIndex);
597            PublicKey key = mPublicKeys.valueAt(pKeyIndex);
598            String encodedKey = encodePublicKey(key);
599            serializer.startTag(null, "public-key");
600            serializer.attribute(null, "identifier", Long.toString(id));
601            serializer.attribute(null, "value", encodedKey);
602            serializer.endTag(null, "public-key");
603        }
604        serializer.endTag(null, "keys");
605    }
606
607    void writeKeySetsLPr(XmlSerializer serializer) throws IOException {
608        serializer.startTag(null, "keysets");
609        for (int keySetIndex = 0; keySetIndex < mKeySetMapping.size(); keySetIndex++) {
610            long id = mKeySetMapping.keyAt(keySetIndex);
611            ArraySet<Long> keys = mKeySetMapping.valueAt(keySetIndex);
612            serializer.startTag(null, "keyset");
613            serializer.attribute(null, "identifier", Long.toString(id));
614            for (long keyId : keys) {
615                serializer.startTag(null, "key-id");
616                serializer.attribute(null, "identifier", Long.toString(keyId));
617                serializer.endTag(null, "key-id");
618            }
619            serializer.endTag(null, "keyset");
620        }
621        serializer.endTag(null, "keysets");
622    }
623
624    void readKeySetsLPw(XmlPullParser parser)
625            throws XmlPullParserException, IOException {
626        int type;
627        long currentKeySetId = 0;
628        int outerDepth = parser.getDepth();
629        String recordedVersion = parser.getAttributeValue(null, "version");
630        if (recordedVersion == null || Integer.parseInt(recordedVersion) != CURRENT_VERSION) {
631            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
632                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
633                // Our version is different than the one which generated the old keyset data.
634                // We don't want any of the old data, but we must advance the parser
635                continue;
636            }
637            // The KeySet information read previously from packages.xml is invalid.
638            // Destroy it all.
639            for (PackageSetting p : mPackages.values()) {
640                clearPackageKeySetDataLPw(p);
641            }
642            return;
643        }
644        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
645               && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
646            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
647                continue;
648            }
649            final String tagName = parser.getName();
650            if (tagName.equals("keys")) {
651                readKeysLPw(parser);
652            } else if (tagName.equals("keysets")) {
653                readKeySetListLPw(parser);
654            } else if (tagName.equals("lastIssuedKeyId")) {
655                lastIssuedKeyId = Long.parseLong(parser.getAttributeValue(null, "value"));
656            } else if (tagName.equals("lastIssuedKeySetId")) {
657                lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value"));
658            }
659        }
660    }
661
662    void readKeysLPw(XmlPullParser parser)
663            throws XmlPullParserException, IOException {
664        int outerDepth = parser.getDepth();
665        int type;
666        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
667                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
668            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
669                continue;
670            }
671            final String tagName = parser.getName();
672            if (tagName.equals("public-key")) {
673                readPublicKeyLPw(parser);
674            }
675        }
676    }
677
678    void readKeySetListLPw(XmlPullParser parser)
679            throws XmlPullParserException, IOException {
680        int outerDepth = parser.getDepth();
681        int type;
682        long currentKeySetId = 0;
683        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
684                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
685            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
686                continue;
687            }
688            final String tagName = parser.getName();
689            if (tagName.equals("keyset")) {
690                currentKeySetId = readIdentifierLPw(parser);
691                mKeySets.put(currentKeySetId, new KeySetHandle());
692                mKeySetMapping.put(currentKeySetId, new ArraySet<Long>());
693            } else if (tagName.equals("key-id")) {
694                long id = readIdentifierLPw(parser);
695                mKeySetMapping.get(currentKeySetId).add(id);
696            }
697        }
698    }
699
700    long readIdentifierLPw(XmlPullParser parser)
701            throws XmlPullParserException {
702        return Long.parseLong(parser.getAttributeValue(null, "identifier"));
703    }
704
705    void readPublicKeyLPw(XmlPullParser parser)
706            throws XmlPullParserException {
707        String encodedID = parser.getAttributeValue(null, "identifier");
708        long identifier = Long.parseLong(encodedID);
709        String encodedPublicKey = parser.getAttributeValue(null, "value");
710        PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey);
711        if (pub != null) {
712            mPublicKeys.put(identifier, pub);
713        }
714    }
715}
716