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