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 static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; 20 21 import com.android.internal.util.Preconditions; 22 import android.content.pm.PackageParser; 23 import android.util.ArrayMap; 24 import android.util.ArraySet; 25 import android.util.Base64; 26 import android.util.Slog; 27 import android.util.LongSparseArray; 28 29 import java.io.IOException; 30 import java.io.PrintWriter; 31 import java.security.PublicKey; 32 import java.util.Set; 33 34 import org.xmlpull.v1.XmlPullParser; 35 import org.xmlpull.v1.XmlPullParserException; 36 import org.xmlpull.v1.XmlSerializer; 37 38 /* 39 * Manages system-wide KeySet state. 40 */ 41 public class KeySetManagerService { 42 43 static final String TAG = "KeySetManagerService"; 44 45 /* original keysets implementation had no versioning info, so this is the first */ 46 public static final int FIRST_VERSION = 1; 47 48 public static final int CURRENT_VERSION = FIRST_VERSION; 49 50 /** Sentinel value returned when a {@code KeySet} is not found. */ 51 public static final long KEYSET_NOT_FOUND = -1; 52 53 /** Sentinel value returned when public key is not found. */ 54 protected static final long PUBLIC_KEY_NOT_FOUND = -1; 55 56 private final LongSparseArray<KeySetHandle> mKeySets; 57 58 private final LongSparseArray<PublicKeyHandle> mPublicKeys; 59 60 protected final LongSparseArray<ArraySet<Long>> mKeySetMapping; 61 62 private final ArrayMap<String, PackageSetting> mPackages; 63 64 private long lastIssuedKeySetId = 0; 65 66 private long lastIssuedKeyId = 0; 67 68 class PublicKeyHandle { 69 private final PublicKey mKey; 70 private final long mId; 71 private int mRefCount; 72 PublicKeyHandle(long id, PublicKey key)73 public PublicKeyHandle(long id, PublicKey key) { 74 mId = id; 75 mRefCount = 1; 76 mKey = key; 77 } 78 79 /* 80 * Only used when reading state from packages.xml 81 */ PublicKeyHandle(long id, int refCount, PublicKey key)82 private PublicKeyHandle(long id, int refCount, PublicKey key) { 83 mId = id; 84 mRefCount = refCount; 85 mKey = key; 86 } 87 getId()88 public long getId() { 89 return mId; 90 } 91 getKey()92 public PublicKey getKey() { 93 return mKey; 94 } 95 getRefCountLPr()96 public int getRefCountLPr() { 97 return mRefCount; 98 } 99 incrRefCountLPw()100 public void incrRefCountLPw() { 101 mRefCount++; 102 return; 103 } 104 decrRefCountLPw()105 public long decrRefCountLPw() { 106 mRefCount--; 107 return mRefCount; 108 } 109 } 110 KeySetManagerService(ArrayMap<String, PackageSetting> packages)111 public KeySetManagerService(ArrayMap<String, PackageSetting> packages) { 112 mKeySets = new LongSparseArray<KeySetHandle>(); 113 mPublicKeys = new LongSparseArray<PublicKeyHandle>(); 114 mKeySetMapping = new LongSparseArray<ArraySet<Long>>(); 115 mPackages = packages; 116 } 117 118 /** 119 * Determine if a package is signed by the given KeySet. 120 * 121 * Returns false if the package was not signed by all the 122 * keys in the KeySet. 123 * 124 * Returns true if the package was signed by at least the 125 * keys in the given KeySet. 126 * 127 * Note that this can return true for multiple KeySets. 128 */ packageIsSignedByLPr(String packageName, KeySetHandle ks)129 public boolean packageIsSignedByLPr(String packageName, KeySetHandle ks) { 130 PackageSetting pkg = mPackages.get(packageName); 131 if (pkg == null) { 132 throw new NullPointerException("Invalid package name"); 133 } 134 if (pkg.keySetData == null) { 135 throw new NullPointerException("Package has no KeySet data"); 136 } 137 long id = getIdByKeySetLPr(ks); 138 if (id == KEYSET_NOT_FOUND) { 139 return false; 140 } 141 ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet()); 142 ArraySet<Long> testKeys = mKeySetMapping.get(id); 143 return pkgKeys.containsAll(testKeys); 144 } 145 146 /** 147 * Determine if a package is signed by the given KeySet. 148 * 149 * Returns false if the package was not signed by all the 150 * keys in the KeySet, or if the package was signed by keys 151 * not in the KeySet. 152 * 153 * Note that this can return only for one KeySet. 154 */ packageIsSignedByExactlyLPr(String packageName, KeySetHandle ks)155 public boolean packageIsSignedByExactlyLPr(String packageName, KeySetHandle ks) { 156 PackageSetting pkg = mPackages.get(packageName); 157 if (pkg == null) { 158 throw new NullPointerException("Invalid package name"); 159 } 160 if (pkg.keySetData == null 161 || pkg.keySetData.getProperSigningKeySet() 162 == PackageKeySetData.KEYSET_UNASSIGNED) { 163 throw new NullPointerException("Package has no KeySet data"); 164 } 165 long id = getIdByKeySetLPr(ks); 166 if (id == KEYSET_NOT_FOUND) { 167 return false; 168 } 169 ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet()); 170 ArraySet<Long> testKeys = mKeySetMapping.get(id); 171 return pkgKeys.equals(testKeys); 172 } 173 174 /** 175 * addScannedPackageLPw directly modifies the package metadata in pm.Settings 176 * at a point of no-return. We need to make sure that the scanned package does 177 * not contain bad keyset meta-data that could generate an incorrect 178 * PackageSetting. Verify that there is a signing keyset, there are no issues 179 * with null objects, and the upgrade and defined keysets match. 180 * 181 * Returns true if the package can safely be added to the keyset metadata. 182 */ assertScannedPackageValid(PackageParser.Package pkg)183 public void assertScannedPackageValid(PackageParser.Package pkg) 184 throws PackageManagerException { 185 if (pkg == null || pkg.packageName == null) { 186 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 187 "Passed invalid package to keyset validation."); 188 } 189 ArraySet<PublicKey> signingKeys = pkg.mSigningKeys; 190 if (signingKeys == null || !(signingKeys.size() > 0) || signingKeys.contains(null)) { 191 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 192 "Package has invalid signing-key-set."); 193 } 194 ArrayMap<String, ArraySet<PublicKey>> definedMapping = pkg.mKeySetMapping; 195 if (definedMapping != null) { 196 if (definedMapping.containsKey(null) || definedMapping.containsValue(null)) { 197 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 198 "Package has null defined key set."); 199 } 200 int defMapSize = definedMapping.size(); 201 for (int i = 0; i < defMapSize; i++) { 202 if (!(definedMapping.valueAt(i).size() > 0) 203 || definedMapping.valueAt(i).contains(null)) { 204 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 205 "Package has null/no public keys for defined key-sets."); 206 } 207 } 208 } 209 ArraySet<String> upgradeAliases = pkg.mUpgradeKeySets; 210 if (upgradeAliases != null) { 211 if (definedMapping == null || !(definedMapping.keySet().containsAll(upgradeAliases))) { 212 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 213 "Package has upgrade-key-sets without corresponding definitions."); 214 } 215 } 216 } 217 addScannedPackageLPw(PackageParser.Package pkg)218 public void addScannedPackageLPw(PackageParser.Package pkg) { 219 Preconditions.checkNotNull(pkg, "Attempted to add null pkg to ksms."); 220 Preconditions.checkNotNull(pkg.packageName, "Attempted to add null pkg to ksms."); 221 PackageSetting ps = mPackages.get(pkg.packageName); 222 Preconditions.checkNotNull(ps, "pkg: " + pkg.packageName 223 + "does not have a corresponding entry in mPackages."); 224 addSigningKeySetToPackageLPw(ps, pkg.mSigningKeys); 225 if (pkg.mKeySetMapping != null) { 226 addDefinedKeySetsToPackageLPw(ps, pkg.mKeySetMapping); 227 if (pkg.mUpgradeKeySets != null) { 228 addUpgradeKeySetsToPackageLPw(ps, pkg.mUpgradeKeySets); 229 } 230 } 231 } 232 233 /** 234 * Informs the system that the given package was signed by the provided KeySet. 235 */ addSigningKeySetToPackageLPw(PackageSetting pkg, ArraySet<PublicKey> signingKeys)236 void addSigningKeySetToPackageLPw(PackageSetting pkg, 237 ArraySet<PublicKey> signingKeys) { 238 239 /* check existing keyset for reuse or removal */ 240 long signingKeySetId = pkg.keySetData.getProperSigningKeySet(); 241 242 if (signingKeySetId != PackageKeySetData.KEYSET_UNASSIGNED) { 243 ArraySet<PublicKey> existingKeys = getPublicKeysFromKeySetLPr(signingKeySetId); 244 if (existingKeys != null && existingKeys.equals(signingKeys)) { 245 246 /* no change in signing keys, leave PackageSetting alone */ 247 return; 248 } else { 249 250 /* old keyset no longer valid, remove ref */ 251 decrementKeySetLPw(signingKeySetId); 252 } 253 } 254 255 /* create and add a new keyset */ 256 KeySetHandle ks = addKeySetLPw(signingKeys); 257 long id = ks.getId(); 258 pkg.keySetData.setProperSigningKeySet(id); 259 return; 260 } 261 262 /** 263 * Fetches the stable identifier associated with the given KeySet. Returns 264 * {@link #KEYSET_NOT_FOUND} if the KeySet... wasn't found. 265 */ getIdByKeySetLPr(KeySetHandle ks)266 private long getIdByKeySetLPr(KeySetHandle ks) { 267 for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) { 268 KeySetHandle value = mKeySets.valueAt(keySetIndex); 269 if (ks.equals(value)) { 270 return mKeySets.keyAt(keySetIndex); 271 } 272 } 273 return KEYSET_NOT_FOUND; 274 } 275 276 /** 277 * Inform the system that the given package defines the given KeySets. 278 * Remove any KeySets the package no longer defines. 279 */ addDefinedKeySetsToPackageLPw(PackageSetting pkg, ArrayMap<String, ArraySet<PublicKey>> definedMapping)280 void addDefinedKeySetsToPackageLPw(PackageSetting pkg, 281 ArrayMap<String, ArraySet<PublicKey>> definedMapping) { 282 ArrayMap<String, Long> prevDefinedKeySets = pkg.keySetData.getAliases(); 283 284 /* add all of the newly defined KeySets */ 285 ArrayMap<String, Long> newKeySetAliases = new ArrayMap<String, Long>(); 286 final int defMapSize = definedMapping.size(); 287 for (int i = 0; i < defMapSize; i++) { 288 String alias = definedMapping.keyAt(i); 289 ArraySet<PublicKey> pubKeys = definedMapping.valueAt(i); 290 if (alias != null && pubKeys != null || pubKeys.size() > 0) { 291 KeySetHandle ks = addKeySetLPw(pubKeys); 292 newKeySetAliases.put(alias, ks.getId()); 293 } 294 } 295 296 /* remove each of the old references */ 297 final int prevDefSize = prevDefinedKeySets.size(); 298 for (int i = 0; i < prevDefSize; i++) { 299 decrementKeySetLPw(prevDefinedKeySets.valueAt(i)); 300 } 301 pkg.keySetData.removeAllUpgradeKeySets(); 302 303 /* switch to the just-added */ 304 pkg.keySetData.setAliases(newKeySetAliases); 305 return; 306 } 307 308 /** 309 * This informs the system that the given package has defined a KeySet 310 * alias in its manifest to be an upgradeKeySet. This must be called 311 * after all of the defined KeySets have been added. 312 */ addUpgradeKeySetsToPackageLPw(PackageSetting pkg, ArraySet<String> upgradeAliases)313 void addUpgradeKeySetsToPackageLPw(PackageSetting pkg, 314 ArraySet<String> upgradeAliases) { 315 final int uaSize = upgradeAliases.size(); 316 for (int i = 0; i < uaSize; i++) { 317 pkg.keySetData.addUpgradeKeySet(upgradeAliases.valueAt(i)); 318 } 319 return; 320 } 321 322 /** 323 * Fetched the {@link KeySetHandle} that a given package refers to by the 324 * provided alias. Returns null if the package is unknown or does not have a 325 * KeySet corresponding to that alias. 326 */ getKeySetByAliasAndPackageNameLPr(String packageName, String alias)327 public KeySetHandle getKeySetByAliasAndPackageNameLPr(String packageName, String alias) { 328 PackageSetting p = mPackages.get(packageName); 329 if (p == null || p.keySetData == null) { 330 return null; 331 } 332 Long keySetId = p.keySetData.getAliases().get(alias); 333 if (keySetId == null) { 334 throw new IllegalArgumentException("Unknown KeySet alias: " + alias); 335 } 336 return mKeySets.get(keySetId); 337 } 338 339 /* Checks if an identifier refers to a known keyset */ isIdValidKeySetId(long id)340 public boolean isIdValidKeySetId(long id) { 341 return mKeySets.get(id) != null; 342 } 343 344 /** 345 * Fetches the {@link PublicKey public keys} which belong to the specified 346 * KeySet id. 347 * 348 * Returns {@code null} if the identifier doesn't 349 * identify a {@link KeySetHandle}. 350 */ getPublicKeysFromKeySetLPr(long id)351 public ArraySet<PublicKey> getPublicKeysFromKeySetLPr(long id) { 352 ArraySet<Long> pkIds = mKeySetMapping.get(id); 353 if (pkIds == null) { 354 return null; 355 } 356 ArraySet<PublicKey> mPubKeys = new ArraySet<PublicKey>(); 357 final int pkSize = pkIds.size(); 358 for (int i = 0; i < pkSize; i++) { 359 mPubKeys.add(mPublicKeys.get(pkIds.valueAt(i)).getKey()); 360 } 361 return mPubKeys; 362 } 363 364 /** 365 * Fetches the proper {@link KeySetHandle KeySet} that signed the given 366 * package. 367 * 368 * @throws IllegalArgumentException if the package has no keyset data. 369 * @throws NullPointerException if the packgae is unknown. 370 */ getSigningKeySetByPackageNameLPr(String packageName)371 public KeySetHandle getSigningKeySetByPackageNameLPr(String packageName) { 372 PackageSetting p = mPackages.get(packageName); 373 if (p == null 374 || p.keySetData == null 375 || p.keySetData.getProperSigningKeySet() 376 == PackageKeySetData.KEYSET_UNASSIGNED) { 377 return null; 378 } 379 return mKeySets.get(p.keySetData.getProperSigningKeySet()); 380 } 381 382 /** 383 * Creates a new KeySet corresponding to the given keys. 384 * 385 * If the {@link PublicKey PublicKeys} aren't known to the system, this 386 * adds them. Otherwise, they're deduped and the reference count 387 * incremented. 388 * 389 * If the KeySet isn't known to the system, this adds that and creates the 390 * mapping to the PublicKeys. If it is known, then it's deduped and the 391 * reference count is incremented. 392 * 393 * Throws if the provided set is {@code null}. 394 */ addKeySetLPw(ArraySet<PublicKey> keys)395 private KeySetHandle addKeySetLPw(ArraySet<PublicKey> keys) { 396 if (keys == null || keys.size() == 0) { 397 throw new IllegalArgumentException("Cannot add an empty set of keys!"); 398 } 399 400 /* add each of the keys in the provided set */ 401 ArraySet<Long> addedKeyIds = new ArraySet<Long>(keys.size()); 402 final int kSize = keys.size(); 403 for (int i = 0; i < kSize; i++) { 404 long id = addPublicKeyLPw(keys.valueAt(i)); 405 addedKeyIds.add(id); 406 } 407 408 /* check to see if the resulting keyset is new */ 409 long existingKeySetId = getIdFromKeyIdsLPr(addedKeyIds); 410 if (existingKeySetId != KEYSET_NOT_FOUND) { 411 412 /* public keys were incremented, but we aren't adding a new keyset: undo */ 413 for (int i = 0; i < kSize; i++) { 414 decrementPublicKeyLPw(addedKeyIds.valueAt(i)); 415 } 416 KeySetHandle ks = mKeySets.get(existingKeySetId); 417 ks.incrRefCountLPw(); 418 return ks; 419 } 420 421 // get the next keyset id 422 long id = getFreeKeySetIDLPw(); 423 424 // create the KeySet object and add to mKeySets and mapping 425 KeySetHandle ks = new KeySetHandle(id); 426 mKeySets.put(id, ks); 427 mKeySetMapping.put(id, addedKeyIds); 428 return ks; 429 } 430 431 /* 432 * Decrements the reference to KeySet represented by the given id. If this 433 * drops to zero, then also decrement the reference to each public key it 434 * contains and remove the KeySet. 435 */ decrementKeySetLPw(long id)436 private void decrementKeySetLPw(long id) { 437 KeySetHandle ks = mKeySets.get(id); 438 if (ks == null) { 439 /* nothing to do */ 440 return; 441 } 442 if (ks.decrRefCountLPw() <= 0) { 443 ArraySet<Long> pubKeys = mKeySetMapping.get(id); 444 final int pkSize = pubKeys.size(); 445 for (int i = 0; i < pkSize; i++) { 446 decrementPublicKeyLPw(pubKeys.valueAt(i)); 447 } 448 mKeySets.delete(id); 449 mKeySetMapping.delete(id); 450 } 451 } 452 453 /* 454 * Decrements the reference to PublicKey represented by the given id. If 455 * this drops to zero, then remove it. 456 */ decrementPublicKeyLPw(long id)457 private void decrementPublicKeyLPw(long id) { 458 PublicKeyHandle pk = mPublicKeys.get(id); 459 if (pk == null) { 460 /* nothing to do */ 461 return; 462 } 463 if (pk.decrRefCountLPw() <= 0) { 464 mPublicKeys.delete(id); 465 } 466 } 467 468 /** 469 * Adds the given PublicKey to the system, deduping as it goes. 470 */ addPublicKeyLPw(PublicKey key)471 private long addPublicKeyLPw(PublicKey key) { 472 Preconditions.checkNotNull(key, "Cannot add null public key!"); 473 long id = getIdForPublicKeyLPr(key); 474 if (id != PUBLIC_KEY_NOT_FOUND) { 475 476 /* We already know about this key, increment its ref count and ret */ 477 mPublicKeys.get(id).incrRefCountLPw(); 478 return id; 479 } 480 481 /* if it's new find the first unoccupied slot in the public keys */ 482 id = getFreePublicKeyIdLPw(); 483 mPublicKeys.put(id, new PublicKeyHandle(id, key)); 484 return id; 485 } 486 487 /** 488 * Finds the stable identifier for a KeySet based on a set of PublicKey stable IDs. 489 * 490 * Returns KEYSET_NOT_FOUND if there isn't one. 491 */ getIdFromKeyIdsLPr(Set<Long> publicKeyIds)492 private long getIdFromKeyIdsLPr(Set<Long> publicKeyIds) { 493 for (int keyMapIndex = 0; keyMapIndex < mKeySetMapping.size(); keyMapIndex++) { 494 ArraySet<Long> value = mKeySetMapping.valueAt(keyMapIndex); 495 if (value.equals(publicKeyIds)) { 496 return mKeySetMapping.keyAt(keyMapIndex); 497 } 498 } 499 return KEYSET_NOT_FOUND; 500 } 501 502 /** 503 * Finds the stable identifier for a PublicKey or PUBLIC_KEY_NOT_FOUND. 504 */ getIdForPublicKeyLPr(PublicKey k)505 private long getIdForPublicKeyLPr(PublicKey k) { 506 String encodedPublicKey = new String(k.getEncoded()); 507 for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) { 508 PublicKey value = mPublicKeys.valueAt(publicKeyIndex).getKey(); 509 String encodedExistingKey = new String(value.getEncoded()); 510 if (encodedPublicKey.equals(encodedExistingKey)) { 511 return mPublicKeys.keyAt(publicKeyIndex); 512 } 513 } 514 return PUBLIC_KEY_NOT_FOUND; 515 } 516 517 /** 518 * Gets an unused stable identifier for a KeySet. 519 */ getFreeKeySetIDLPw()520 private long getFreeKeySetIDLPw() { 521 lastIssuedKeySetId += 1; 522 return lastIssuedKeySetId; 523 } 524 525 /** 526 * Same as above, but for public keys. 527 */ getFreePublicKeyIdLPw()528 private long getFreePublicKeyIdLPw() { 529 lastIssuedKeyId += 1; 530 return lastIssuedKeyId; 531 } 532 533 /* 534 * This package is being removed from the system, so we need to 535 * remove its keyset and public key references, then remove its 536 * keyset data. 537 */ removeAppKeySetDataLPw(String packageName)538 public void removeAppKeySetDataLPw(String packageName) { 539 540 /* remove refs from common keysets and public keys */ 541 PackageSetting pkg = mPackages.get(packageName); 542 Preconditions.checkNotNull(pkg, "pkg name: " + packageName 543 + "does not have a corresponding entry in mPackages."); 544 long signingKeySetId = pkg.keySetData.getProperSigningKeySet(); 545 decrementKeySetLPw(signingKeySetId); 546 ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases(); 547 for (int i = 0; i < definedKeySets.size(); i++) { 548 decrementKeySetLPw(definedKeySets.valueAt(i)); 549 } 550 551 /* remove from package */ 552 clearPackageKeySetDataLPw(pkg); 553 return; 554 } 555 clearPackageKeySetDataLPw(PackageSetting pkg)556 private void clearPackageKeySetDataLPw(PackageSetting pkg) { 557 pkg.keySetData.setProperSigningKeySet(PackageKeySetData.KEYSET_UNASSIGNED); 558 pkg.keySetData.removeAllDefinedKeySets(); 559 pkg.keySetData.removeAllUpgradeKeySets(); 560 return; 561 } 562 encodePublicKey(PublicKey k)563 public String encodePublicKey(PublicKey k) throws IOException { 564 return new String(Base64.encode(k.getEncoded(), Base64.NO_WRAP)); 565 } 566 dumpLPr(PrintWriter pw, String packageName, PackageManagerService.DumpState dumpState)567 public void dumpLPr(PrintWriter pw, String packageName, 568 PackageManagerService.DumpState dumpState) { 569 boolean printedHeader = false; 570 for (ArrayMap.Entry<String, PackageSetting> e : mPackages.entrySet()) { 571 String keySetPackage = e.getKey(); 572 if (packageName != null && !packageName.equals(keySetPackage)) { 573 continue; 574 } 575 if (!printedHeader) { 576 if (dumpState.onTitlePrinted()) 577 pw.println(); 578 pw.println("Key Set Manager:"); 579 printedHeader = true; 580 } 581 PackageSetting pkg = e.getValue(); 582 pw.print(" ["); pw.print(keySetPackage); pw.println("]"); 583 if (pkg.keySetData != null) { 584 boolean printedLabel = false; 585 for (ArrayMap.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) { 586 if (!printedLabel) { 587 pw.print(" KeySets Aliases: "); 588 printedLabel = true; 589 } else { 590 pw.print(", "); 591 } 592 pw.print(entry.getKey()); 593 pw.print('='); 594 pw.print(Long.toString(entry.getValue())); 595 } 596 if (printedLabel) { 597 pw.println(""); 598 } 599 printedLabel = false; 600 if (pkg.keySetData.isUsingDefinedKeySets()) { 601 ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases(); 602 final int dksSize = definedKeySets.size(); 603 for (int i = 0; i < dksSize; i++) { 604 if (!printedLabel) { 605 pw.print(" Defined KeySets: "); 606 printedLabel = true; 607 } else { 608 pw.print(", "); 609 } 610 pw.print(Long.toString(definedKeySets.valueAt(i))); 611 } 612 } 613 if (printedLabel) { 614 pw.println(""); 615 } 616 printedLabel = false; 617 final long signingKeySet = pkg.keySetData.getProperSigningKeySet(); 618 pw.print(" Signing KeySets: "); 619 pw.print(Long.toString(signingKeySet)); 620 pw.println(""); 621 if (pkg.keySetData.isUsingUpgradeKeySets()) { 622 for (long keySetId : pkg.keySetData.getUpgradeKeySets()) { 623 if (!printedLabel) { 624 pw.print(" Upgrade KeySets: "); 625 printedLabel = true; 626 } else { 627 pw.print(", "); 628 } 629 pw.print(Long.toString(keySetId)); 630 } 631 } 632 if (printedLabel) { 633 pw.println(""); 634 } 635 } 636 } 637 } 638 writeKeySetManagerServiceLPr(XmlSerializer serializer)639 void writeKeySetManagerServiceLPr(XmlSerializer serializer) throws IOException { 640 serializer.startTag(null, "keyset-settings"); 641 serializer.attribute(null, "version", Integer.toString(CURRENT_VERSION)); 642 writePublicKeysLPr(serializer); 643 writeKeySetsLPr(serializer); 644 serializer.startTag(null, "lastIssuedKeyId"); 645 serializer.attribute(null, "value", Long.toString(lastIssuedKeyId)); 646 serializer.endTag(null, "lastIssuedKeyId"); 647 serializer.startTag(null, "lastIssuedKeySetId"); 648 serializer.attribute(null, "value", Long.toString(lastIssuedKeySetId)); 649 serializer.endTag(null, "lastIssuedKeySetId"); 650 serializer.endTag(null, "keyset-settings"); 651 } 652 writePublicKeysLPr(XmlSerializer serializer)653 void writePublicKeysLPr(XmlSerializer serializer) throws IOException { 654 serializer.startTag(null, "keys"); 655 for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) { 656 long id = mPublicKeys.keyAt(pKeyIndex); 657 PublicKeyHandle pkh = mPublicKeys.valueAt(pKeyIndex); 658 String encodedKey = encodePublicKey(pkh.getKey()); 659 serializer.startTag(null, "public-key"); 660 serializer.attribute(null, "identifier", Long.toString(id)); 661 serializer.attribute(null, "value", encodedKey); 662 serializer.endTag(null, "public-key"); 663 } 664 serializer.endTag(null, "keys"); 665 } 666 writeKeySetsLPr(XmlSerializer serializer)667 void writeKeySetsLPr(XmlSerializer serializer) throws IOException { 668 serializer.startTag(null, "keysets"); 669 for (int keySetIndex = 0; keySetIndex < mKeySetMapping.size(); keySetIndex++) { 670 long id = mKeySetMapping.keyAt(keySetIndex); 671 ArraySet<Long> keys = mKeySetMapping.valueAt(keySetIndex); 672 serializer.startTag(null, "keyset"); 673 serializer.attribute(null, "identifier", Long.toString(id)); 674 for (long keyId : keys) { 675 serializer.startTag(null, "key-id"); 676 serializer.attribute(null, "identifier", Long.toString(keyId)); 677 serializer.endTag(null, "key-id"); 678 } 679 serializer.endTag(null, "keyset"); 680 } 681 serializer.endTag(null, "keysets"); 682 } 683 readKeySetsLPw(XmlPullParser parser, ArrayMap<Long, Integer> keySetRefCounts)684 void readKeySetsLPw(XmlPullParser parser, ArrayMap<Long, Integer> keySetRefCounts) 685 throws XmlPullParserException, IOException { 686 int type; 687 long currentKeySetId = 0; 688 int outerDepth = parser.getDepth(); 689 String recordedVersionStr = parser.getAttributeValue(null, "version"); 690 if (recordedVersionStr == null) { 691 // The keyset information comes from pre-versioned devices, and 692 // is inaccurate, don't collect any of it. 693 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 694 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 695 continue; 696 } 697 // The KeySet information read previously from packages.xml is invalid. 698 // Destroy it all. 699 for (PackageSetting p : mPackages.values()) { 700 clearPackageKeySetDataLPw(p); 701 } 702 return; 703 } 704 int recordedVersion = Integer.parseInt(recordedVersionStr); 705 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 706 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 707 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 708 continue; 709 } 710 final String tagName = parser.getName(); 711 if (tagName.equals("keys")) { 712 readKeysLPw(parser); 713 } else if (tagName.equals("keysets")) { 714 readKeySetListLPw(parser); 715 } else if (tagName.equals("lastIssuedKeyId")) { 716 lastIssuedKeyId = Long.parseLong(parser.getAttributeValue(null, "value")); 717 } else if (tagName.equals("lastIssuedKeySetId")) { 718 lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value")); 719 } 720 } 721 722 addRefCountsFromSavedPackagesLPw(keySetRefCounts); 723 } 724 readKeysLPw(XmlPullParser parser)725 void readKeysLPw(XmlPullParser parser) 726 throws XmlPullParserException, IOException { 727 int outerDepth = parser.getDepth(); 728 int type; 729 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 730 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 731 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 732 continue; 733 } 734 final String tagName = parser.getName(); 735 if (tagName.equals("public-key")) { 736 readPublicKeyLPw(parser); 737 } 738 } 739 } 740 readKeySetListLPw(XmlPullParser parser)741 void readKeySetListLPw(XmlPullParser parser) 742 throws XmlPullParserException, IOException { 743 int outerDepth = parser.getDepth(); 744 int type; 745 long currentKeySetId = 0; 746 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 747 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 748 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 749 continue; 750 } 751 final String tagName = parser.getName(); 752 if (tagName.equals("keyset")) { 753 String encodedID = parser.getAttributeValue(null, "identifier"); 754 currentKeySetId = Long.parseLong(encodedID); 755 int refCount = 0; 756 mKeySets.put(currentKeySetId, new KeySetHandle(currentKeySetId, refCount)); 757 mKeySetMapping.put(currentKeySetId, new ArraySet<Long>()); 758 } else if (tagName.equals("key-id")) { 759 String encodedID = parser.getAttributeValue(null, "identifier"); 760 long id = Long.parseLong(encodedID); 761 mKeySetMapping.get(currentKeySetId).add(id); 762 } 763 } 764 } 765 readPublicKeyLPw(XmlPullParser parser)766 void readPublicKeyLPw(XmlPullParser parser) 767 throws XmlPullParserException { 768 String encodedID = parser.getAttributeValue(null, "identifier"); 769 long identifier = Long.parseLong(encodedID); 770 int refCount = 0; 771 String encodedPublicKey = parser.getAttributeValue(null, "value"); 772 PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey); 773 if (pub != null) { 774 PublicKeyHandle pkh = new PublicKeyHandle(identifier, refCount, pub); 775 mPublicKeys.put(identifier, pkh); 776 } 777 } 778 779 /* 780 * Set each KeySet ref count. Also increment all public keys in each keyset. 781 */ addRefCountsFromSavedPackagesLPw(ArrayMap<Long, Integer> keySetRefCounts)782 private void addRefCountsFromSavedPackagesLPw(ArrayMap<Long, Integer> keySetRefCounts) { 783 final int numRefCounts = keySetRefCounts.size(); 784 for (int i = 0; i < numRefCounts; i++) { 785 KeySetHandle ks = mKeySets.get(keySetRefCounts.keyAt(i)); 786 if (ks == null) { 787 /* something went terribly wrong and we have references to a non-existent key-set */ 788 Slog.wtf(TAG, "Encountered non-existent key-set reference when reading settings"); 789 continue; 790 } 791 ks.setRefCountLPw(keySetRefCounts.valueAt(i)); 792 } 793 794 /* 795 * In case something went terribly wrong and we have keysets with no associated packges 796 * that refer to them, record the orphaned keyset ids, and remove them using 797 * decrementKeySetLPw() after all keyset references have been set so that the associtaed 798 * public keys have the appropriate references from all keysets. 799 */ 800 ArraySet<Long> orphanedKeySets = new ArraySet<Long>(); 801 final int numKeySets = mKeySets.size(); 802 for (int i = 0; i < numKeySets; i++) { 803 if (mKeySets.valueAt(i).getRefCountLPr() == 0) { 804 Slog.wtf(TAG, "Encountered key-set w/out package references when reading settings"); 805 orphanedKeySets.add(mKeySets.keyAt(i)); 806 } 807 ArraySet<Long> pubKeys = mKeySetMapping.valueAt(i); 808 final int pkSize = pubKeys.size(); 809 for (int j = 0; j < pkSize; j++) { 810 mPublicKeys.get(pubKeys.valueAt(j)).incrRefCountLPw(); 811 } 812 } 813 final int numOrphans = orphanedKeySets.size(); 814 for (int i = 0; i < numOrphans; i++) { 815 decrementKeySetLPw(orphanedKeySets.valueAt(i)); 816 } 817 } 818 } 819