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