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 17 package com.android.server.pm; 18 19 import android.content.pm.PackageParser; 20 import android.os.Binder; 21 import android.util.ArraySet; 22 import android.util.Base64; 23 import android.util.Slog; 24 import android.util.LongSparseArray; 25 26 import java.io.IOException; 27 import java.io.PrintWriter; 28 import java.security.PublicKey; 29 import java.util.Map; 30 import java.util.Set; 31 32 import org.xmlpull.v1.XmlPullParser; 33 import org.xmlpull.v1.XmlPullParserException; 34 import org.xmlpull.v1.XmlSerializer; 35 36 /* 37 * Manages system-wide KeySet state. 38 */ 39 public 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 KeySetManagerService(Map<String, PackageSetting> packages)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 */ packageIsSignedByLPr(String packageName, KeySetHandle ks)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 */ packageIsSignedByExactlyLPr(String packageName, KeySetHandle ks)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 */ addDefinedKeySetToPackageLPw(String packageName, ArraySet<PublicKey> keys, String alias)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 */ addUpgradeKeySetToPackageLPw(String packageName, String alias)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 */ addSigningKeySetToPackageLPw(String packageName, ArraySet<PublicKey> signingKeys)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 */ getIdByKeySetLPr(KeySetHandle ks)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 */ getKeySetByIdLPr(long id)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 */ getKeySetByAliasAndPackageNameLPr(String packageName, String alias)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 */ getPublicKeysFromKeySetLPr(long id)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 */ getSigningKeySetByPackageNameLPr(String packageName)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 */ getUpgradeKeySetsByPackageNameLPr(String packageName)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 */ addKeySetLPw(ArraySet<PublicKey> keys)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 */ addPublicKeyLPw(PublicKey key)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 */ getIdFromKeyIdsLPr(Set<Long> publicKeyIds)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 */ getIdForPublicKeyLPr(PublicKey k)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 */ getFreeKeySetIDLPw()401 private long getFreeKeySetIDLPw() { 402 lastIssuedKeySetId += 1; 403 return lastIssuedKeySetId; 404 } 405 406 /** 407 * Same as above, but for public keys. 408 */ getFreePublicKeyIdLPw()409 private long getFreePublicKeyIdLPw() { 410 lastIssuedKeyId += 1; 411 return lastIssuedKeyId; 412 } 413 removeAppKeySetDataLPw(String packageName)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 clearPackageKeySetDataLPw(PackageSetting p)464 private void clearPackageKeySetDataLPw(PackageSetting p) { 465 p.keySetData.removeAllSigningKeySets(); 466 p.keySetData.removeAllUpgradeKeySets(); 467 p.keySetData.removeAllDefinedKeySets(); 468 return; 469 } 470 getOriginalKeySetsByPackageNameLPr(String packageName)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 encodePublicKey(PublicKey k)489 public String encodePublicKey(PublicKey k) throws IOException { 490 return new String(Base64.encode(k.getEncoded(), 0)); 491 } 492 dumpLPr(PrintWriter pw, String packageName, PackageManagerService.DumpState dumpState)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 final long[] signingKeySets = pkg.keySetData.getSigningKeySets(); 542 if (signingKeySets != null) { 543 for (long keySetId : signingKeySets) { 544 if (!printedLabel) { 545 pw.print(" Signing KeySets: "); 546 printedLabel = true; 547 } else { 548 pw.print(", "); 549 } 550 pw.print(Long.toString(keySetId)); 551 } 552 } 553 if (printedLabel) { 554 pw.println(""); 555 } 556 printedLabel = false; 557 if (pkg.keySetData.isUsingUpgradeKeySets()) { 558 for (long keySetId : pkg.keySetData.getUpgradeKeySets()) { 559 if (!printedLabel) { 560 pw.print(" Upgrade KeySets: "); 561 printedLabel = true; 562 } else { 563 pw.print(", "); 564 } 565 pw.print(Long.toString(keySetId)); 566 } 567 } 568 if (printedLabel) { 569 pw.println(""); 570 } 571 } 572 } 573 } 574 writeKeySetManagerServiceLPr(XmlSerializer serializer)575 void writeKeySetManagerServiceLPr(XmlSerializer serializer) throws IOException { 576 serializer.startTag(null, "keyset-settings"); 577 serializer.attribute(null, "version", Integer.toString(CURRENT_VERSION)); 578 writePublicKeysLPr(serializer); 579 writeKeySetsLPr(serializer); 580 serializer.startTag(null, "lastIssuedKeyId"); 581 serializer.attribute(null, "value", Long.toString(lastIssuedKeyId)); 582 serializer.endTag(null, "lastIssuedKeyId"); 583 serializer.startTag(null, "lastIssuedKeySetId"); 584 serializer.attribute(null, "value", Long.toString(lastIssuedKeySetId)); 585 serializer.endTag(null, "lastIssuedKeySetId"); 586 serializer.endTag(null, "keyset-settings"); 587 } 588 writePublicKeysLPr(XmlSerializer serializer)589 void writePublicKeysLPr(XmlSerializer serializer) throws IOException { 590 serializer.startTag(null, "keys"); 591 for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) { 592 long id = mPublicKeys.keyAt(pKeyIndex); 593 PublicKey key = mPublicKeys.valueAt(pKeyIndex); 594 String encodedKey = encodePublicKey(key); 595 serializer.startTag(null, "public-key"); 596 serializer.attribute(null, "identifier", Long.toString(id)); 597 serializer.attribute(null, "value", encodedKey); 598 serializer.endTag(null, "public-key"); 599 } 600 serializer.endTag(null, "keys"); 601 } 602 writeKeySetsLPr(XmlSerializer serializer)603 void writeKeySetsLPr(XmlSerializer serializer) throws IOException { 604 serializer.startTag(null, "keysets"); 605 for (int keySetIndex = 0; keySetIndex < mKeySetMapping.size(); keySetIndex++) { 606 long id = mKeySetMapping.keyAt(keySetIndex); 607 ArraySet<Long> keys = mKeySetMapping.valueAt(keySetIndex); 608 serializer.startTag(null, "keyset"); 609 serializer.attribute(null, "identifier", Long.toString(id)); 610 for (long keyId : keys) { 611 serializer.startTag(null, "key-id"); 612 serializer.attribute(null, "identifier", Long.toString(keyId)); 613 serializer.endTag(null, "key-id"); 614 } 615 serializer.endTag(null, "keyset"); 616 } 617 serializer.endTag(null, "keysets"); 618 } 619 readKeySetsLPw(XmlPullParser parser)620 void readKeySetsLPw(XmlPullParser parser) 621 throws XmlPullParserException, IOException { 622 int type; 623 long currentKeySetId = 0; 624 int outerDepth = parser.getDepth(); 625 String recordedVersion = parser.getAttributeValue(null, "version"); 626 if (recordedVersion == null || Integer.parseInt(recordedVersion) != CURRENT_VERSION) { 627 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 628 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 629 // Our version is different than the one which generated the old keyset data. 630 // We don't want any of the old data, but we must advance the parser 631 continue; 632 } 633 // The KeySet information read previously from packages.xml is invalid. 634 // Destroy it all. 635 for (PackageSetting p : mPackages.values()) { 636 clearPackageKeySetDataLPw(p); 637 } 638 return; 639 } 640 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 641 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 642 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 643 continue; 644 } 645 final String tagName = parser.getName(); 646 if (tagName.equals("keys")) { 647 readKeysLPw(parser); 648 } else if (tagName.equals("keysets")) { 649 readKeySetListLPw(parser); 650 } else if (tagName.equals("lastIssuedKeyId")) { 651 lastIssuedKeyId = Long.parseLong(parser.getAttributeValue(null, "value")); 652 } else if (tagName.equals("lastIssuedKeySetId")) { 653 lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value")); 654 } 655 } 656 } 657 readKeysLPw(XmlPullParser parser)658 void readKeysLPw(XmlPullParser parser) 659 throws XmlPullParserException, IOException { 660 int outerDepth = parser.getDepth(); 661 int type; 662 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 663 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 664 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 665 continue; 666 } 667 final String tagName = parser.getName(); 668 if (tagName.equals("public-key")) { 669 readPublicKeyLPw(parser); 670 } 671 } 672 } 673 readKeySetListLPw(XmlPullParser parser)674 void readKeySetListLPw(XmlPullParser parser) 675 throws XmlPullParserException, IOException { 676 int outerDepth = parser.getDepth(); 677 int type; 678 long currentKeySetId = 0; 679 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 680 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 681 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 682 continue; 683 } 684 final String tagName = parser.getName(); 685 if (tagName.equals("keyset")) { 686 currentKeySetId = readIdentifierLPw(parser); 687 mKeySets.put(currentKeySetId, new KeySetHandle()); 688 mKeySetMapping.put(currentKeySetId, new ArraySet<Long>()); 689 } else if (tagName.equals("key-id")) { 690 long id = readIdentifierLPw(parser); 691 mKeySetMapping.get(currentKeySetId).add(id); 692 } 693 } 694 } 695 readIdentifierLPw(XmlPullParser parser)696 long readIdentifierLPw(XmlPullParser parser) 697 throws XmlPullParserException { 698 return Long.parseLong(parser.getAttributeValue(null, "identifier")); 699 } 700 readPublicKeyLPw(XmlPullParser parser)701 void readPublicKeyLPw(XmlPullParser parser) 702 throws XmlPullParserException { 703 String encodedID = parser.getAttributeValue(null, "identifier"); 704 long identifier = Long.parseLong(encodedID); 705 String encodedPublicKey = parser.getAttributeValue(null, "value"); 706 PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey); 707 if (pub != null) { 708 mPublicKeys.put(identifier, pub); 709 } 710 } 711 } 712