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