KeySetManagerService.java revision 9d2f441f9bb2c8dcac1150e2cba1d15a86a4efb1
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 ArraySet<Long> knownKeys = null; 419 for (Long ks : deletableKeySets) { 420 knownKeys = mKeySetMapping.get(ks); 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 knownKeys = new ArraySet<Long>(); 434 for (Long ks : knownKeySets) { 435 knownKeys = mKeySetMapping.get(ks); 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 for (Long ks : deletableKeySets) { 445 mKeySets.delete(ks); 446 mKeySetMapping.delete(ks); 447 } 448 for (Long keyId : deletableKeys) { 449 mPublicKeys.delete(keyId); 450 } 451 452 // Now remove the deleted KeySets from each package's signingKeySets 453 for (String pkgName : mPackages.keySet()) { 454 PackageSetting p = mPackages.get(pkgName); 455 for (Long ks : deletableKeySets) { 456 p.keySetData.removeSigningKeySet(ks); 457 } 458 } 459 // Finally, remove all KeySets from the original package 460 PackageSetting p = mPackages.get(packageName); 461 clearPackageKeySetDataLPw(p); 462 } 463 464 private void clearPackageKeySetDataLPw(PackageSetting p) { 465 p.keySetData.removeAllSigningKeySets(); 466 p.keySetData.removeAllUpgradeKeySets(); 467 p.keySetData.removeAllDefinedKeySets(); 468 return; 469 } 470 471 private ArraySet<Long> getOriginalKeySetsByPackageNameLPr(String packageName) { 472 PackageSetting p = mPackages.get(packageName); 473 if (p == null) { 474 throw new NullPointerException("Unknown package"); 475 } 476 if (p.keySetData == null) { 477 throw new IllegalArgumentException("Package has no keySet data"); 478 } 479 ArraySet<Long> knownKeySets = new ArraySet<Long>(); 480 knownKeySets.add(p.keySetData.getProperSigningKeySet()); 481 if (p.keySetData.isUsingDefinedKeySets()) { 482 for (long ks : p.keySetData.getDefinedKeySets()) { 483 knownKeySets.add(ks); 484 } 485 } 486 return knownKeySets; 487 } 488 489 public String encodePublicKey(PublicKey k) throws IOException { 490 return new String(Base64.encode(k.getEncoded(), 0)); 491 } 492 493 public void dumpLPr(PrintWriter pw, String packageName, 494 PackageManagerService.DumpState dumpState) { 495 boolean printedHeader = false; 496 for (Map.Entry<String, PackageSetting> e : mPackages.entrySet()) { 497 String keySetPackage = e.getKey(); 498 if (packageName != null && !packageName.equals(keySetPackage)) { 499 continue; 500 } 501 if (!printedHeader) { 502 if (dumpState.onTitlePrinted()) 503 pw.println(); 504 pw.println("Key Set Manager:"); 505 printedHeader = true; 506 } 507 PackageSetting pkg = e.getValue(); 508 pw.print(" ["); pw.print(keySetPackage); pw.println("]"); 509 if (pkg.keySetData != null) { 510 boolean printedLabel = false; 511 for (Map.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) { 512 if (!printedLabel) { 513 pw.print(" KeySets Aliases: "); 514 printedLabel = true; 515 } else { 516 pw.print(", "); 517 } 518 pw.print(entry.getKey()); 519 pw.print('='); 520 pw.print(Long.toString(entry.getValue())); 521 } 522 if (printedLabel) { 523 pw.println(""); 524 } 525 printedLabel = false; 526 if (pkg.keySetData.isUsingDefinedKeySets()) { 527 for (long keySetId : pkg.keySetData.getDefinedKeySets()) { 528 if (!printedLabel) { 529 pw.print(" Defined KeySets: "); 530 printedLabel = true; 531 } else { 532 pw.print(", "); 533 } 534 pw.print(Long.toString(keySetId)); 535 } 536 } 537 if (printedLabel) { 538 pw.println(""); 539 } 540 printedLabel = false; 541 for (long keySetId : pkg.keySetData.getSigningKeySets()) { 542 if (!printedLabel) { 543 pw.print(" Signing KeySets: "); 544 printedLabel = true; 545 } else { 546 pw.print(", "); 547 } 548 pw.print(Long.toString(keySetId)); 549 } 550 if (printedLabel) { 551 pw.println(""); 552 } 553 printedLabel = false; 554 if (pkg.keySetData.isUsingUpgradeKeySets()) { 555 for (long keySetId : pkg.keySetData.getUpgradeKeySets()) { 556 if (!printedLabel) { 557 pw.print(" Upgrade KeySets: "); 558 printedLabel = true; 559 } else { 560 pw.print(", "); 561 } 562 pw.print(Long.toString(keySetId)); 563 } 564 } 565 if (printedLabel) { 566 pw.println(""); 567 } 568 } 569 } 570 } 571 572 void writeKeySetManagerServiceLPr(XmlSerializer serializer) throws IOException { 573 serializer.startTag(null, "keyset-settings"); 574 serializer.attribute(null, "version", Integer.toString(CURRENT_VERSION)); 575 writePublicKeysLPr(serializer); 576 writeKeySetsLPr(serializer); 577 serializer.startTag(null, "lastIssuedKeyId"); 578 serializer.attribute(null, "value", Long.toString(lastIssuedKeyId)); 579 serializer.endTag(null, "lastIssuedKeyId"); 580 serializer.startTag(null, "lastIssuedKeySetId"); 581 serializer.attribute(null, "value", Long.toString(lastIssuedKeySetId)); 582 serializer.endTag(null, "lastIssuedKeySetId"); 583 serializer.endTag(null, "keyset-settings"); 584 } 585 586 void writePublicKeysLPr(XmlSerializer serializer) throws IOException { 587 serializer.startTag(null, "keys"); 588 for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) { 589 long id = mPublicKeys.keyAt(pKeyIndex); 590 PublicKey key = mPublicKeys.valueAt(pKeyIndex); 591 String encodedKey = encodePublicKey(key); 592 serializer.startTag(null, "public-key"); 593 serializer.attribute(null, "identifier", Long.toString(id)); 594 serializer.attribute(null, "value", encodedKey); 595 serializer.endTag(null, "public-key"); 596 } 597 serializer.endTag(null, "keys"); 598 } 599 600 void writeKeySetsLPr(XmlSerializer serializer) throws IOException { 601 serializer.startTag(null, "keysets"); 602 for (int keySetIndex = 0; keySetIndex < mKeySetMapping.size(); keySetIndex++) { 603 long id = mKeySetMapping.keyAt(keySetIndex); 604 ArraySet<Long> keys = mKeySetMapping.valueAt(keySetIndex); 605 serializer.startTag(null, "keyset"); 606 serializer.attribute(null, "identifier", Long.toString(id)); 607 for (long keyId : keys) { 608 serializer.startTag(null, "key-id"); 609 serializer.attribute(null, "identifier", Long.toString(keyId)); 610 serializer.endTag(null, "key-id"); 611 } 612 serializer.endTag(null, "keyset"); 613 } 614 serializer.endTag(null, "keysets"); 615 } 616 617 void readKeySetsLPw(XmlPullParser parser) 618 throws XmlPullParserException, IOException { 619 int type; 620 long currentKeySetId = 0; 621 int outerDepth = parser.getDepth(); 622 String recordedVersion = parser.getAttributeValue(null, "version"); 623 if (recordedVersion == null || Integer.parseInt(recordedVersion) != CURRENT_VERSION) { 624 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 625 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 626 // Our version is different than the one which generated the old keyset data. 627 // We don't want any of the old data, but we must advance the parser 628 continue; 629 } 630 // The KeySet information read previously from packages.xml is invalid. 631 // Destroy it all. 632 for (PackageSetting p : mPackages.values()) { 633 clearPackageKeySetDataLPw(p); 634 } 635 return; 636 } 637 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 638 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 639 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 640 continue; 641 } 642 final String tagName = parser.getName(); 643 if (tagName.equals("keys")) { 644 readKeysLPw(parser); 645 } else if (tagName.equals("keysets")) { 646 readKeySetListLPw(parser); 647 } else if (tagName.equals("lastIssuedKeyId")) { 648 lastIssuedKeyId = Long.parseLong(parser.getAttributeValue(null, "value")); 649 } else if (tagName.equals("lastIssuedKeySetId")) { 650 lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value")); 651 } 652 } 653 } 654 655 void readKeysLPw(XmlPullParser parser) 656 throws XmlPullParserException, IOException { 657 int outerDepth = parser.getDepth(); 658 int type; 659 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 660 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 661 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 662 continue; 663 } 664 final String tagName = parser.getName(); 665 if (tagName.equals("public-key")) { 666 readPublicKeyLPw(parser); 667 } 668 } 669 } 670 671 void readKeySetListLPw(XmlPullParser parser) 672 throws XmlPullParserException, IOException { 673 int outerDepth = parser.getDepth(); 674 int type; 675 long currentKeySetId = 0; 676 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 677 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 678 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 679 continue; 680 } 681 final String tagName = parser.getName(); 682 if (tagName.equals("keyset")) { 683 currentKeySetId = readIdentifierLPw(parser); 684 mKeySets.put(currentKeySetId, new KeySetHandle()); 685 mKeySetMapping.put(currentKeySetId, new ArraySet<Long>()); 686 } else if (tagName.equals("key-id")) { 687 long id = readIdentifierLPw(parser); 688 mKeySetMapping.get(currentKeySetId).add(id); 689 } 690 } 691 } 692 693 long readIdentifierLPw(XmlPullParser parser) 694 throws XmlPullParserException { 695 return Long.parseLong(parser.getAttributeValue(null, "identifier")); 696 } 697 698 void readPublicKeyLPw(XmlPullParser parser) 699 throws XmlPullParserException { 700 String encodedID = parser.getAttributeValue(null, "identifier"); 701 long identifier = Long.parseLong(encodedID); 702 String encodedPublicKey = parser.getAttributeValue(null, "value"); 703 PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey); 704 if (pub != null) { 705 mPublicKeys.put(identifier, pub); 706 } 707 } 708} 709