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