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