1 /* 2 * Copyright (C) 2017 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.locksettings; 18 19 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; 20 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN; 21 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN; 22 import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback; 23 import static com.android.internal.widget.LockPatternUtils.PIN_LENGTH_UNAVAILABLE; 24 import static com.android.internal.widget.LockPatternUtils.USER_FRP; 25 import static com.android.internal.widget.LockPatternUtils.USER_REPAIR_MODE; 26 import static com.android.internal.widget.LockPatternUtils.pinOrPasswordQualityToCredentialType; 27 28 import android.annotation.IntDef; 29 import android.annotation.NonNull; 30 import android.annotation.Nullable; 31 import android.annotation.UserIdInt; 32 import android.app.admin.PasswordMetrics; 33 import android.content.Context; 34 import android.content.pm.UserInfo; 35 import android.hardware.weaver.IWeaver; 36 import android.hardware.weaver.WeaverConfig; 37 import android.hardware.weaver.WeaverReadResponse; 38 import android.hardware.weaver.WeaverReadStatus; 39 import android.os.RemoteCallbackList; 40 import android.os.RemoteException; 41 import android.os.ServiceManager; 42 import android.os.ServiceSpecificException; 43 import android.os.UserManager; 44 import android.provider.Settings; 45 import android.security.GateKeeper; 46 import android.security.Scrypt; 47 import android.service.gatekeeper.GateKeeperResponse; 48 import android.service.gatekeeper.IGateKeeperService; 49 import android.text.TextUtils; 50 import android.util.ArrayMap; 51 import android.util.ArraySet; 52 import android.util.Slog; 53 54 import com.android.internal.annotations.VisibleForTesting; 55 import com.android.internal.util.ArrayUtils; 56 import com.android.internal.util.Preconditions; 57 import com.android.internal.widget.ICheckCredentialProgressCallback; 58 import com.android.internal.widget.IWeakEscrowTokenRemovedListener; 59 import com.android.internal.widget.LockPatternUtils; 60 import com.android.internal.widget.LockscreenCredential; 61 import com.android.internal.widget.VerifyCredentialResponse; 62 import com.android.server.locksettings.LockSettingsStorage.PersistentData; 63 import com.android.server.utils.Slogf; 64 65 import libcore.util.HexEncoding; 66 67 import java.lang.annotation.Retention; 68 import java.lang.annotation.RetentionPolicy; 69 import java.nio.ByteBuffer; 70 import java.util.Arrays; 71 import java.util.Collections; 72 import java.util.HashSet; 73 import java.util.List; 74 import java.util.Map; 75 import java.util.NoSuchElementException; 76 import java.util.Objects; 77 import java.util.Set; 78 79 80 /** 81 * A class that manages a user's synthetic password (SP) ({@link #SyntheticPassword}), along with a 82 * set of SP protectors that are independent ways that the SP is protected. 83 * 84 * Invariants for SPs: 85 * 86 * - A user's SP never changes, but SP protectors can be added and removed. There is always a 87 * protector that protects the SP with the user's Lock Screen Knowledge Factor (LSKF), a.k.a. 88 * LockscreenCredential. The LSKF may be empty (none). There may be escrow token-based 89 * protectors as well, only for specific use cases such as enterprise-managed users. 90 * 91 * - The user's credential-encrypted storage is always protected by the SP. 92 * 93 * - The user's auth-bound Keystore keys are protected by the SP, but only while an LSKF is set. 94 * This works by setting the user's Keystore and Gatekeeper passwords to SP-derived secrets, but 95 * only while an LSKF is set. When the LSKF is removed, these passwords are cleared, 96 * invalidating the user's auth-bound keys. 97 * 98 * Files stored on disk for each user: 99 * For the SP itself, stored under NULL_PROTECTOR_ID: 100 * SP_HANDLE_NAME: GateKeeper password handle of a password derived from the SP. Only exists 101 * while the LSKF is nonempty. 102 * SP_E0_NAME, SP_P1_NAME: Information needed to create and use escrow token-based protectors. 103 * Deleted when escrow token support is disabled for the user. 104 * VENDOR_AUTH_SECRET_NAME: A copy of the secret passed using the IAuthSecret interface, 105 * encrypted using a secret derived from the SP using 106 * PERSONALIZATION_AUTHSECRET_ENCRYPTION_KEY. 107 * 108 * For each protector, stored under the corresponding protector ID: 109 * SP_BLOB_NAME: The encrypted SP secret (the SP itself or the P0 value). Always exists. 110 * PASSWORD_DATA_NAME: Data used for LSKF verification, such as the scrypt salt and 111 * parameters. Only exists for LSKF-based protectors. Doesn't exist when 112 * the LSKF is empty, except in old protectors. 113 * PASSWORD_METRICS_NAME: Metrics about the LSKF, encrypted by a key derived from the SP. 114 * Only exists for LSKF-based protectors. Doesn't exist when the LSKF 115 * is empty, except in old protectors. 116 * SECDISCARDABLE_NAME: A large number of random bytes that all need to be known in order to 117 * decrypt SP_BLOB_NAME. When the protector is deleted, this file is 118 * overwritten and deleted as a "best-effort" attempt to support secure 119 * deletion when hardware support for secure deletion is unavailable. 120 * Doesn't exist for LSKF-based protectors that use Weaver. 121 * WEAVER_SLOT: Contains the Weaver slot number used by this protector. Only exists if the 122 * protector uses Weaver. 123 */ 124 class SyntheticPasswordManager { 125 private static final String SP_BLOB_NAME = "spblob"; 126 private static final String SP_E0_NAME = "e0"; 127 private static final String SP_P1_NAME = "p1"; 128 private static final String SP_HANDLE_NAME = "handle"; 129 private static final String SECDISCARDABLE_NAME = "secdis"; 130 private static final int SECDISCARDABLE_LENGTH = 16 * 1024; 131 private static final String PASSWORD_DATA_NAME = "pwd"; 132 private static final String WEAVER_SLOT_NAME = "weaver"; 133 private static final String PASSWORD_METRICS_NAME = "metrics"; 134 private static final String VENDOR_AUTH_SECRET_NAME = "vendor_auth_secret"; 135 136 // used for files associated with the SP itself, not with a particular protector 137 public static final long NULL_PROTECTOR_ID = 0L; 138 139 private static final byte[] DEFAULT_PASSWORD = "default-password".getBytes(); 140 141 private static final byte WEAVER_VERSION = 1; 142 private static final int INVALID_WEAVER_SLOT = -1; 143 144 // Careful: the SYNTHETIC_PASSWORD_* version numbers are overloaded to identify both the version 145 // of the protector and the version of the synthetic password itself. All a user's protectors 146 // must use a version that treats the synthetic password itself in a compatible way. 147 private static final byte SYNTHETIC_PASSWORD_VERSION_V1 = 1; 148 private static final byte SYNTHETIC_PASSWORD_VERSION_V2 = 2; 149 private static final byte SYNTHETIC_PASSWORD_VERSION_V3 = 3; 150 151 private static final byte PROTECTOR_TYPE_LSKF_BASED = 0; 152 private static final byte PROTECTOR_TYPE_STRONG_TOKEN_BASED = 1; 153 private static final byte PROTECTOR_TYPE_WEAK_TOKEN_BASED = 2; 154 155 private static final String PROTECTOR_KEY_ALIAS_PREFIX = "synthetic_password_"; 156 157 // The security strength of the synthetic password, in bytes 158 private static final int SYNTHETIC_PASSWORD_SECURITY_STRENGTH = 256 / 8; 159 160 private static final int PASSWORD_SCRYPT_LOG_N = 11; 161 private static final int PASSWORD_SCRYPT_LOG_R = 3; 162 private static final int PASSWORD_SCRYPT_LOG_P = 1; 163 private static final int PASSWORD_SALT_LENGTH = 16; 164 private static final int STRETCHED_LSKF_LENGTH = 32; 165 private static final String TAG = "SyntheticPasswordManager"; 166 167 private static final byte[] PERSONALIZATION_SECDISCARDABLE = "secdiscardable-transform".getBytes(); 168 private static final byte[] PERSONALIZATION_KEY_STORE_PASSWORD = "keystore-password".getBytes(); 169 private static final byte[] PERSONALIZATION_USER_GK_AUTH = "user-gk-authentication".getBytes(); 170 private static final byte[] PERSONALIZATION_SP_GK_AUTH = "sp-gk-authentication".getBytes(); 171 private static final byte[] PERSONALIZATION_FBE_KEY = "fbe-key".getBytes(); 172 private static final byte[] PERSONALIZATION_AUTHSECRET_KEY = "authsecret-hal".getBytes(); 173 private static final byte[] PERSONALIZATION_AUTHSECRET_ENCRYPTION_KEY = 174 "vendor-authsecret-encryption-key".getBytes(); 175 private static final byte[] PERSONALIZATION_SP_SPLIT = "sp-split".getBytes(); 176 private static final byte[] PERSONALIZATION_PASSWORD_HASH = "pw-hash".getBytes(); 177 private static final byte[] PERSONALIZATION_E0 = "e0-encryption".getBytes(); 178 private static final byte[] PERSONALIZATION_WEAVER_PASSWORD = "weaver-pwd".getBytes(); 179 private static final byte[] PERSONALIZATION_WEAVER_KEY = "weaver-key".getBytes(); 180 private static final byte[] PERSONALIZATION_WEAVER_TOKEN = "weaver-token".getBytes(); 181 private static final byte[] PERSONALIZATION_PASSWORD_METRICS = "password-metrics".getBytes(); 182 private static final byte[] PERSONALIZATION_CONTEXT = 183 "android-synthetic-password-personalization-context".getBytes(); 184 185 static class AuthenticationResult { 186 // Non-null if password/token passes verification, null otherwise 187 @Nullable public SyntheticPassword syntheticPassword; 188 // OK: password / token passes verification, user has a lockscreen 189 // null: user does not have a lockscreen (but password / token passes verification) 190 // ERROR: password / token fails verification 191 // RETRY: password / token verification is throttled at the moment. 192 @Nullable public VerifyCredentialResponse gkResponse; 193 } 194 195 /** 196 * A synthetic password (SP) is the main cryptographic secret for a user. The SP is used only 197 * as input to a Key Derivation Function (KDF) to derive other keys. 198 * 199 * SPs are created by {@link SyntheticPassword#create()} as the hash of two random values P0 and 200 * P1. E0 (P0 encrypted by an SP-derived key) and P1 can then be stored on-disk. This approach 201 * is used instead of direct random generation of the SP so that escrow token-based protectors 202 * can protect P0 instead of the SP itself. This makes it possible to cryptographically disable 203 * the ability to create and use such protectors by deleting (or never storing) E0 and P1. 204 * 205 * When protecting the SP directly, use {@link SyntheticPassword#getSyntheticPassword()} to get 206 * the raw SP, and later {@link SyntheticPassword#recreateDirectly(byte[])} to re-create the SP. 207 * When protecting P0, use {@link SyntheticPassword#getEscrowSecret()} to get P0, and later 208 * {@link SyntheticPassword#setEscrowData(byte[], byte[])} followed by 209 * {@link SyntheticPassword#recreateFromEscrow()} to re-create the SP. 210 */ 211 static class SyntheticPassword { 212 private final byte mVersion; 213 /** 214 * Here is the relationship between these fields: 215 * Generate two random block P0 and P1. P1 is recorded in mEscrowSplit1 but P0 is not. 216 * mSyntheticPassword = hash(P0 || P1) 217 * E0 = P0 encrypted under syntheticPassword, recorded in mEncryptedEscrowSplit0. 218 */ 219 private @NonNull byte[] mSyntheticPassword; 220 private @Nullable byte[] mEncryptedEscrowSplit0; 221 private @Nullable byte[] mEscrowSplit1; 222 SyntheticPassword(byte version)223 SyntheticPassword(byte version) { 224 mVersion = version; 225 } 226 227 /** 228 * Derives a subkey from the synthetic password. For v3 and later synthetic passwords the 229 * subkeys are 256-bit; for v1 and v2 they are 512-bit. 230 */ deriveSubkey(byte[] personalization)231 private byte[] deriveSubkey(byte[] personalization) { 232 if (mVersion == SYNTHETIC_PASSWORD_VERSION_V3) { 233 return (new SP800Derive(mSyntheticPassword)) 234 .withContext(personalization, PERSONALIZATION_CONTEXT); 235 } else { 236 return SyntheticPasswordCrypto.personalizedHash(personalization, 237 mSyntheticPassword); 238 } 239 } 240 deriveKeyStorePassword()241 public byte[] deriveKeyStorePassword() { 242 return bytesToHex(deriveSubkey(PERSONALIZATION_KEY_STORE_PASSWORD)); 243 } 244 deriveGkPassword()245 public byte[] deriveGkPassword() { 246 return deriveSubkey(PERSONALIZATION_SP_GK_AUTH); 247 } 248 deriveFileBasedEncryptionKey()249 public byte[] deriveFileBasedEncryptionKey() { 250 return deriveSubkey(PERSONALIZATION_FBE_KEY); 251 } 252 deriveVendorAuthSecret()253 public byte[] deriveVendorAuthSecret() { 254 return deriveSubkey(PERSONALIZATION_AUTHSECRET_KEY); 255 } 256 derivePasswordHashFactor()257 public byte[] derivePasswordHashFactor() { 258 return deriveSubkey(PERSONALIZATION_PASSWORD_HASH); 259 } 260 261 /** Derives key used to encrypt password metrics */ deriveMetricsKey()262 public byte[] deriveMetricsKey() { 263 return deriveSubkey(PERSONALIZATION_PASSWORD_METRICS); 264 } 265 deriveVendorAuthSecretEncryptionKey()266 public byte[] deriveVendorAuthSecretEncryptionKey() { 267 return deriveSubkey(PERSONALIZATION_AUTHSECRET_ENCRYPTION_KEY); 268 } 269 270 /** 271 * Assigns escrow data to this synthetic password. This is a prerequisite to call 272 * {@link SyntheticPassword#recreateFromEscrow}. 273 */ setEscrowData(@ullable byte[] encryptedEscrowSplit0, @Nullable byte[] escrowSplit1)274 public void setEscrowData(@Nullable byte[] encryptedEscrowSplit0, 275 @Nullable byte[] escrowSplit1) { 276 mEncryptedEscrowSplit0 = encryptedEscrowSplit0; 277 mEscrowSplit1 = escrowSplit1; 278 } 279 280 /** 281 * Re-creates a synthetic password from the escrow secret (escrowSplit0, returned from 282 * {@link SyntheticPassword#getEscrowSecret}). Escrow data needs to be loaded 283 * by {@link #setEscrowData} before calling this. 284 */ recreateFromEscrow(byte[] escrowSplit0)285 public void recreateFromEscrow(byte[] escrowSplit0) { 286 Objects.requireNonNull(mEscrowSplit1); 287 Objects.requireNonNull(mEncryptedEscrowSplit0); 288 recreate(escrowSplit0, mEscrowSplit1); 289 } 290 291 /** 292 * Re-creates a synthetic password from its raw bytes. 293 */ recreateDirectly(byte[] syntheticPassword)294 public void recreateDirectly(byte[] syntheticPassword) { 295 this.mSyntheticPassword = Arrays.copyOf(syntheticPassword, syntheticPassword.length); 296 } 297 298 /** 299 * Generates a new random synthetic password with escrow data. 300 */ create()301 static SyntheticPassword create() { 302 SyntheticPassword result = new SyntheticPassword(SYNTHETIC_PASSWORD_VERSION_V3); 303 byte[] escrowSplit0 = 304 SecureRandomUtils.randomBytes(SYNTHETIC_PASSWORD_SECURITY_STRENGTH); 305 byte[] escrowSplit1 = 306 SecureRandomUtils.randomBytes(SYNTHETIC_PASSWORD_SECURITY_STRENGTH); 307 result.recreate(escrowSplit0, escrowSplit1); 308 byte[] encrypteEscrowSplit0 = SyntheticPasswordCrypto.encrypt(result.mSyntheticPassword, 309 PERSONALIZATION_E0, escrowSplit0); 310 result.setEscrowData(encrypteEscrowSplit0, escrowSplit1); 311 return result; 312 } 313 314 /** 315 * Re-creates synthetic password from both escrow splits. See javadoc for 316 * SyntheticPassword.mSyntheticPassword for details on what each block means. 317 */ recreate(byte[] escrowSplit0, byte[] escrowSplit1)318 private void recreate(byte[] escrowSplit0, byte[] escrowSplit1) { 319 mSyntheticPassword = bytesToHex(SyntheticPasswordCrypto.personalizedHash( 320 PERSONALIZATION_SP_SPLIT, escrowSplit0, escrowSplit1)); 321 } 322 323 /** 324 * Returns the escrow secret that can be used later to reconstruct this synthetic password 325 * from {@link #recreateFromEscrow(byte[])}. Only possible if escrow is not disabled 326 * (encryptedEscrowSplit0 known). 327 */ getEscrowSecret()328 public byte[] getEscrowSecret() { 329 if (mEncryptedEscrowSplit0 == null) { 330 return null; 331 } 332 return SyntheticPasswordCrypto.decrypt(mSyntheticPassword, PERSONALIZATION_E0, 333 mEncryptedEscrowSplit0); 334 } 335 336 /** 337 * Returns the raw synthetic password, for later use with {@link #recreateDirectly(byte[])}. 338 */ getSyntheticPassword()339 public byte[] getSyntheticPassword() { 340 return mSyntheticPassword; 341 } 342 343 /** 344 * Returns the version number of this synthetic password. This version number determines 345 * the algorithm used to derive subkeys. 346 */ getVersion()347 public byte getVersion() { 348 return mVersion; 349 } 350 } 351 352 static class PasswordData { 353 byte scryptLogN; 354 byte scryptLogR; 355 byte scryptLogP; 356 public int credentialType; 357 byte[] salt; 358 // When Weaver is unavailable, this is the Gatekeeper password handle that resulted from 359 // enrolling the stretched LSKF. 360 public byte[] passwordHandle; 361 /** 362 * Pin length field, only stored in version 2 of the password data and when auto confirm 363 * flag is enabled, otherwise this field contains PIN_LENGTH_UNAVAILABLE 364 */ 365 public int pinLength; 366 create(int credentialType, int pinLength)367 public static PasswordData create(int credentialType, int pinLength) { 368 PasswordData result = new PasswordData(); 369 result.scryptLogN = PASSWORD_SCRYPT_LOG_N; 370 result.scryptLogR = PASSWORD_SCRYPT_LOG_R; 371 result.scryptLogP = PASSWORD_SCRYPT_LOG_P; 372 result.credentialType = credentialType; 373 result.pinLength = pinLength; 374 result.salt = SecureRandomUtils.randomBytes(PASSWORD_SALT_LENGTH); 375 return result; 376 } 377 378 /** 379 * Returns true if the given serialized PasswordData begins with the value 2 as a short. 380 * This detects the "bad" (non-forwards-compatible) PasswordData format that was temporarily 381 * used during development of Android 14. For more details, see fromBytes() below. 382 */ isBadFormatFromAndroid14Beta(byte[] data)383 public static boolean isBadFormatFromAndroid14Beta(byte[] data) { 384 return data != null && data.length >= 2 && data[0] == 0 && data[1] == 2; 385 } 386 fromBytes(byte[] data)387 public static PasswordData fromBytes(byte[] data) { 388 PasswordData result = new PasswordData(); 389 ByteBuffer buffer = ByteBuffer.allocate(data.length); 390 buffer.put(data, 0, data.length); 391 buffer.flip(); 392 393 /* 394 * The serialized PasswordData is supposed to begin with credentialType as an int. 395 * However, all credentialType values fit in a short and the byte order is big endian, 396 * so the first two bytes don't convey any non-redundant information. For this reason, 397 * temporarily during development of Android 14, the first two bytes were "stolen" from 398 * credentialType to use for a data format version number. 399 * 400 * However, this change was reverted as it was a non-forwards-compatible change. (See 401 * toBytes() for why this data format needs to be forwards-compatible.) Therefore, 402 * recover from this misstep by ignoring the first two bytes. 403 */ 404 result.credentialType = (short) buffer.getInt(); 405 result.scryptLogN = buffer.get(); 406 result.scryptLogR = buffer.get(); 407 result.scryptLogP = buffer.get(); 408 int saltLen = buffer.getInt(); 409 result.salt = new byte[saltLen]; 410 buffer.get(result.salt); 411 int handleLen = buffer.getInt(); 412 if (handleLen > 0) { 413 result.passwordHandle = new byte[handleLen]; 414 buffer.get(result.passwordHandle); 415 } else { 416 result.passwordHandle = null; 417 } 418 if (buffer.remaining() >= Integer.BYTES) { 419 result.pinLength = buffer.getInt(); 420 } else { 421 result.pinLength = PIN_LENGTH_UNAVAILABLE; 422 } 423 return result; 424 } 425 426 /** 427 * Serializes this PasswordData into a byte array. 428 * <p> 429 * Careful: all changes to the format of the serialized PasswordData must be forwards 430 * compatible. I.e., older versions of Android must still accept the latest PasswordData. 431 * This is because a serialized PasswordData is stored in the Factory Reset Protection (FRP) 432 * persistent data block. It's possible that a device has FRP set up on a newer version of 433 * Android, is factory reset, and then is set up with an older version of Android. 434 */ toBytes()435 public byte[] toBytes() { 436 437 ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES + 3 * Byte.BYTES 438 + Integer.BYTES + salt.length + Integer.BYTES + 439 (passwordHandle != null ? passwordHandle.length : 0) + Integer.BYTES); 440 // credentialType must fit in a short. For an explanation, see fromBytes(). 441 if (credentialType < Short.MIN_VALUE || credentialType > Short.MAX_VALUE) { 442 throw new IllegalArgumentException("Unknown credential type: " + credentialType); 443 } 444 buffer.putInt(credentialType); 445 buffer.put(scryptLogN); 446 buffer.put(scryptLogR); 447 buffer.put(scryptLogP); 448 buffer.putInt(salt.length); 449 buffer.put(salt); 450 if (passwordHandle != null && passwordHandle.length > 0) { 451 buffer.putInt(passwordHandle.length); 452 buffer.put(passwordHandle); 453 } else { 454 buffer.putInt(0); 455 } 456 buffer.putInt(pinLength); 457 return buffer.array(); 458 } 459 } 460 461 private static class SyntheticPasswordBlob { 462 byte mVersion; 463 byte mProtectorType; 464 byte[] mContent; 465 create(byte version, byte protectorType, byte[] content)466 public static SyntheticPasswordBlob create(byte version, byte protectorType, 467 byte[] content) { 468 SyntheticPasswordBlob result = new SyntheticPasswordBlob(); 469 result.mVersion = version; 470 result.mProtectorType = protectorType; 471 result.mContent = content; 472 return result; 473 } 474 fromBytes(byte[] data)475 public static SyntheticPasswordBlob fromBytes(byte[] data) { 476 SyntheticPasswordBlob result = new SyntheticPasswordBlob(); 477 result.mVersion = data[0]; 478 result.mProtectorType = data[1]; 479 result.mContent = Arrays.copyOfRange(data, 2, data.length); 480 return result; 481 } 482 toByte()483 public byte[] toByte() { 484 byte[] blob = new byte[mContent.length + 1 + 1]; 485 blob[0] = mVersion; 486 blob[1] = mProtectorType; 487 System.arraycopy(mContent, 0, blob, 2, mContent.length); 488 return blob; 489 } 490 } 491 492 @Retention(RetentionPolicy.SOURCE) 493 @IntDef({TOKEN_TYPE_STRONG, TOKEN_TYPE_WEAK}) 494 @interface TokenType {} 495 static final int TOKEN_TYPE_STRONG = 0; 496 static final int TOKEN_TYPE_WEAK = 1; 497 498 private static class TokenData { 499 byte[] secdiscardableOnDisk; 500 byte[] weaverSecret; 501 byte[] aggregatedSecret; 502 @TokenType int mType; 503 EscrowTokenStateChangeCallback mCallback; 504 } 505 506 private final Context mContext; 507 private LockSettingsStorage mStorage; 508 private IWeaver mWeaver; 509 private WeaverConfig mWeaverConfig; 510 private PasswordSlotManager mPasswordSlotManager; 511 512 private final UserManager mUserManager; 513 514 private final RemoteCallbackList<IWeakEscrowTokenRemovedListener> mListeners = 515 new RemoteCallbackList<>(); 516 SyntheticPasswordManager(Context context, LockSettingsStorage storage, UserManager userManager, PasswordSlotManager passwordSlotManager)517 public SyntheticPasswordManager(Context context, LockSettingsStorage storage, 518 UserManager userManager, PasswordSlotManager passwordSlotManager) { 519 mContext = context; 520 mStorage = storage; 521 mUserManager = userManager; 522 mPasswordSlotManager = passwordSlotManager; 523 } 524 isDeviceProvisioned()525 private boolean isDeviceProvisioned() { 526 return Settings.Global.getInt(mContext.getContentResolver(), 527 Settings.Global.DEVICE_PROVISIONED, 0) != 0; 528 } 529 530 @VisibleForTesting getWeaverHidlService()531 protected android.hardware.weaver.V1_0.IWeaver getWeaverHidlService() throws RemoteException { 532 try { 533 return android.hardware.weaver.V1_0.IWeaver.getService(/* retry */ true); 534 } catch (NoSuchElementException e) { 535 return null; 536 } 537 } 538 getWeaverService()539 private IWeaver getWeaverService() { 540 // Try to get the AIDL service first 541 try { 542 IWeaver aidlWeaver = IWeaver.Stub.asInterface( 543 ServiceManager.waitForDeclaredService(IWeaver.DESCRIPTOR + "/default")); 544 if (aidlWeaver != null) { 545 Slog.i(TAG, "Using AIDL weaver service"); 546 return aidlWeaver; 547 } 548 } catch (SecurityException e) { 549 Slog.w(TAG, "Does not have permissions to get AIDL weaver service"); 550 } 551 552 // If the AIDL service can't be found, look for the HIDL service 553 try { 554 android.hardware.weaver.V1_0.IWeaver hidlWeaver = getWeaverHidlService(); 555 if (hidlWeaver != null) { 556 Slog.i(TAG, "Using HIDL weaver service"); 557 return new WeaverHidlAdapter(hidlWeaver); 558 } 559 } catch (RemoteException e) { 560 Slog.w(TAG, "Failed to get HIDL weaver service.", e); 561 } 562 Slog.w(TAG, "Device does not support weaver"); 563 return null; 564 } 565 566 @VisibleForTesting isAutoPinConfirmationFeatureAvailable()567 public boolean isAutoPinConfirmationFeatureAvailable() { 568 return LockPatternUtils.isAutoPinConfirmFeatureAvailable(); 569 } 570 isWeaverAvailable()571 private synchronized boolean isWeaverAvailable() { 572 if (mWeaver != null) { 573 return true; 574 } 575 576 // Re-initialize weaver in case there was a transient error preventing access to it. 577 IWeaver weaver = getWeaverService(); 578 if (weaver == null) { 579 return false; 580 } 581 582 final WeaverConfig weaverConfig; 583 try { 584 weaverConfig = weaver.getConfig(); 585 } catch (RemoteException | ServiceSpecificException e) { 586 Slog.e(TAG, "Failed to get weaver config", e); 587 return false; 588 } 589 if (weaverConfig == null || weaverConfig.slots <= 0) { 590 Slog.e(TAG, "Invalid weaver config"); 591 return false; 592 } 593 594 mWeaver = weaver; 595 mWeaverConfig = weaverConfig; 596 mPasswordSlotManager.refreshActiveSlots(getUsedWeaverSlots()); 597 Slog.i(TAG, "Weaver service initialized"); 598 599 return true; 600 } 601 602 /** 603 * Enroll the given key value pair into the specified weaver slot. if the given key is null, 604 * a default all-zero key is used. If the value is not specified, a fresh random secret is 605 * generated as the value. 606 * 607 * @return the value stored in the weaver slot, or null if the operation fails 608 */ weaverEnroll(int slot, byte[] key, @Nullable byte[] value)609 private byte[] weaverEnroll(int slot, byte[] key, @Nullable byte[] value) { 610 if (slot == INVALID_WEAVER_SLOT || slot >= mWeaverConfig.slots) { 611 throw new IllegalArgumentException("Invalid slot for weaver"); 612 } 613 if (key == null) { 614 key = new byte[mWeaverConfig.keySize]; 615 } else if (key.length != mWeaverConfig.keySize) { 616 throw new IllegalArgumentException("Invalid key size for weaver"); 617 } 618 if (value == null) { 619 value = SecureRandomUtils.randomBytes(mWeaverConfig.valueSize); 620 } 621 try { 622 mWeaver.write(slot, key, value); 623 } catch (RemoteException e) { 624 Slog.e(TAG, "weaver write binder call failed, slot: " + slot, e); 625 return null; 626 } catch (ServiceSpecificException e) { 627 Slog.e(TAG, "weaver write failed, slot: " + slot, e); 628 return null; 629 } 630 return value; 631 } 632 633 /** 634 * Create a VerifyCredentialResponse from a timeout base on the WeaverReadResponse. 635 * This checks the received timeout(long) to make sure it sure it fits in an int before 636 * using it. If it doesn't fit, we use Integer.MAX_VALUE. 637 */ responseFromTimeout(WeaverReadResponse response)638 private static VerifyCredentialResponse responseFromTimeout(WeaverReadResponse response) { 639 int timeout = 640 response.timeout > Integer.MAX_VALUE || response.timeout < 0 641 ? Integer.MAX_VALUE 642 : (int) response.timeout; 643 return VerifyCredentialResponse.fromTimeout(timeout); 644 } 645 646 /** 647 * Verify the supplied key against a weaver slot, returning a response indicating whether 648 * the verification is successful, throttled or failed. If successful, the bound secret 649 * is also returned. 650 */ 651 private VerifyCredentialResponse weaverVerify(int slot, byte[] key) { 652 if (slot == INVALID_WEAVER_SLOT || slot >= mWeaverConfig.slots) { 653 throw new IllegalArgumentException("Invalid slot for weaver"); 654 } 655 if (key == null) { 656 key = new byte[mWeaverConfig.keySize]; 657 } else if (key.length != mWeaverConfig.keySize) { 658 throw new IllegalArgumentException("Invalid key size for weaver"); 659 } 660 final WeaverReadResponse readResponse; 661 try { 662 readResponse = mWeaver.read(slot, key); 663 } catch (RemoteException e) { 664 Slog.e(TAG, "weaver read failed, slot: " + slot, e); 665 return VerifyCredentialResponse.ERROR; 666 } 667 668 switch (readResponse.status) { 669 case WeaverReadStatus.OK: 670 return new VerifyCredentialResponse.Builder() 671 .setGatekeeperHAT(readResponse.value) 672 .build(); 673 case WeaverReadStatus.THROTTLE: 674 Slog.e(TAG, "weaver read failed (THROTTLE), slot: " + slot); 675 return responseFromTimeout(readResponse); 676 case WeaverReadStatus.INCORRECT_KEY: 677 if (readResponse.timeout == 0) { 678 Slog.e(TAG, "weaver read failed (INCORRECT_KEY), slot: " + slot); 679 return VerifyCredentialResponse.ERROR; 680 } else { 681 Slog.e(TAG, "weaver read failed (INCORRECT_KEY/THROTTLE), slot: " + slot); 682 return responseFromTimeout(readResponse); 683 } 684 case WeaverReadStatus.FAILED: 685 Slog.e(TAG, "weaver read failed (FAILED), slot: " + slot); 686 return VerifyCredentialResponse.ERROR; 687 default: 688 Slog.e(TAG, 689 "weaver read unknown status " + readResponse.status 690 + ", slot: " + slot); 691 return VerifyCredentialResponse.ERROR; 692 } 693 } 694 removeUser(IGateKeeperService gatekeeper, int userId)695 public void removeUser(IGateKeeperService gatekeeper, int userId) { 696 for (long protectorId : mStorage.listSyntheticPasswordProtectorsForUser(SP_BLOB_NAME, 697 userId)) { 698 destroyWeaverSlot(protectorId, userId); 699 destroyProtectorKey(getProtectorKeyAlias(protectorId)); 700 } 701 // Remove potential persistent state (in RPMB), to prevent them from accumulating and 702 // causing problems. 703 try { 704 gatekeeper.clearSecureUserId(fakeUserId(userId)); 705 } catch (RemoteException ignore) { 706 Slog.w(TAG, "Failed to clear SID from gatekeeper"); 707 } 708 } 709 getPinLength(long protectorId, int userId)710 int getPinLength(long protectorId, int userId) { 711 byte[] passwordData = loadState(PASSWORD_DATA_NAME, protectorId, userId); 712 if (passwordData == null) { 713 return LockPatternUtils.PIN_LENGTH_UNAVAILABLE; 714 } 715 return PasswordData.fromBytes(passwordData).pinLength; 716 } 717 getCredentialType(long protectorId, int userId)718 int getCredentialType(long protectorId, int userId) { 719 byte[] passwordData = loadState(PASSWORD_DATA_NAME, protectorId, userId); 720 if (passwordData == null) { 721 return LockPatternUtils.CREDENTIAL_TYPE_NONE; 722 } 723 return PasswordData.fromBytes(passwordData).credentialType; 724 } 725 getSpecialUserCredentialType(int userId)726 int getSpecialUserCredentialType(int userId) { 727 final PersistentData data = getSpecialUserPersistentData(userId); 728 if (data.type != PersistentData.TYPE_SP_GATEKEEPER 729 && data.type != PersistentData.TYPE_SP_WEAVER) { 730 return CREDENTIAL_TYPE_NONE; 731 } 732 if (data.payload == null) { 733 return LockPatternUtils.CREDENTIAL_TYPE_NONE; 734 } 735 final int credentialType = PasswordData.fromBytes(data.payload).credentialType; 736 if (credentialType != CREDENTIAL_TYPE_PASSWORD_OR_PIN) { 737 return credentialType; 738 } 739 return pinOrPasswordQualityToCredentialType(data.qualityForUi); 740 } 741 getSpecialUserPersistentData(int userId)742 private PersistentData getSpecialUserPersistentData(int userId) { 743 if (userId == USER_FRP) { 744 return mStorage.readPersistentDataBlock(); 745 } 746 if (userId == USER_REPAIR_MODE) { 747 return mStorage.readRepairModePersistentData(); 748 } 749 throw new IllegalArgumentException("Unknown special user id " + userId); 750 } 751 752 /** 753 * Creates a new synthetic password (SP) for the given user. 754 * <p> 755 * Any existing SID for the user is cleared. 756 * <p> 757 * Also saves the escrow information necessary to re-generate the synthetic password under 758 * an escrow scheme. This information can be removed with {@link #destroyEscrowData} if 759 * password escrow should be disabled completely on the given user. 760 * <p> 761 * {@link syncState()} is not called yet; the caller should create a protector afterwards, which 762 * handles this. This makes it so that all the user's initial SP state files, including the 763 * initial LSKF-based protector, are efficiently created with only a single {@link syncState()}. 764 */ newSyntheticPassword(int userId)765 SyntheticPassword newSyntheticPassword(int userId) { 766 clearSidForUser(userId); 767 SyntheticPassword result = SyntheticPassword.create(); 768 saveEscrowData(result, userId); 769 return result; 770 } 771 772 /** 773 * Enroll a new password handle and SID for the given synthetic password and persist it on disk. 774 * Used when the LSKF is changed from empty to nonempty. 775 */ newSidForUser(IGateKeeperService gatekeeper, SyntheticPassword sp, int userId)776 public void newSidForUser(IGateKeeperService gatekeeper, SyntheticPassword sp, int userId) { 777 GateKeeperResponse response; 778 try { 779 response = gatekeeper.enroll(userId, null, null, sp.deriveGkPassword()); 780 } catch (RemoteException e) { 781 throw new IllegalStateException("Failed to create new SID for user", e); 782 } 783 if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) { 784 throw new IllegalStateException("Fail to create new SID for user " + userId 785 + " response: " + response.getResponseCode()); 786 } 787 saveSyntheticPasswordHandle(response.getPayload(), userId); 788 } 789 790 // Nuke the SP handle (and as a result, its SID) for the given user. clearSidForUser(int userId)791 public void clearSidForUser(int userId) { 792 destroyState(SP_HANDLE_NAME, NULL_PROTECTOR_ID, userId); 793 } 794 hasSidForUser(int userId)795 public boolean hasSidForUser(int userId) { 796 return hasState(SP_HANDLE_NAME, NULL_PROTECTOR_ID, userId); 797 } 798 799 // If this returns null, it means there is no SID associated with the user. This happens if the 800 // user has an empty LSKF, but does have an SP. loadSyntheticPasswordHandle(int userId)801 private byte[] loadSyntheticPasswordHandle(int userId) { 802 return loadState(SP_HANDLE_NAME, NULL_PROTECTOR_ID, userId); 803 } 804 saveSyntheticPasswordHandle(byte[] spHandle, int userId)805 private void saveSyntheticPasswordHandle(byte[] spHandle, int userId) { 806 saveState(SP_HANDLE_NAME, spHandle, NULL_PROTECTOR_ID, userId); 807 syncState(userId); 808 } 809 loadEscrowData(SyntheticPassword sp, int userId)810 private boolean loadEscrowData(SyntheticPassword sp, int userId) { 811 byte[] e0 = loadState(SP_E0_NAME, NULL_PROTECTOR_ID, userId); 812 byte[] p1 = loadState(SP_P1_NAME, NULL_PROTECTOR_ID, userId); 813 sp.setEscrowData(e0, p1); 814 return e0 != null && p1 != null; 815 } 816 817 /** 818 * Saves the escrow data for the synthetic password. The caller is responsible for calling 819 * {@link syncState()} afterwards, once the user's other initial synthetic password state files 820 * have been created. 821 */ saveEscrowData(SyntheticPassword sp, int userId)822 private void saveEscrowData(SyntheticPassword sp, int userId) { 823 saveState(SP_E0_NAME, sp.mEncryptedEscrowSplit0, NULL_PROTECTOR_ID, userId); 824 saveState(SP_P1_NAME, sp.mEscrowSplit1, NULL_PROTECTOR_ID, userId); 825 } 826 hasEscrowData(int userId)827 public boolean hasEscrowData(int userId) { 828 return hasState(SP_E0_NAME, NULL_PROTECTOR_ID, userId) 829 && hasState(SP_P1_NAME, NULL_PROTECTOR_ID, userId); 830 } 831 hasAnyEscrowData(int userId)832 public boolean hasAnyEscrowData(int userId) { 833 return hasState(SP_E0_NAME, NULL_PROTECTOR_ID, userId) 834 || hasState(SP_P1_NAME, NULL_PROTECTOR_ID, userId); 835 } 836 destroyEscrowData(int userId)837 public void destroyEscrowData(int userId) { 838 destroyState(SP_E0_NAME, NULL_PROTECTOR_ID, userId); 839 destroyState(SP_P1_NAME, NULL_PROTECTOR_ID, userId); 840 } 841 loadWeaverSlot(long protectorId, int userId)842 private int loadWeaverSlot(long protectorId, int userId) { 843 final int LENGTH = Byte.BYTES + Integer.BYTES; 844 byte[] data = loadState(WEAVER_SLOT_NAME, protectorId, userId); 845 if (data == null || data.length != LENGTH) { 846 return INVALID_WEAVER_SLOT; 847 } 848 ByteBuffer buffer = ByteBuffer.allocate(LENGTH); 849 buffer.put(data, 0, data.length); 850 buffer.flip(); 851 if (buffer.get() != WEAVER_VERSION) { 852 Slog.e(TAG, "Invalid weaver slot version for protector " + protectorId); 853 return INVALID_WEAVER_SLOT; 854 } 855 return buffer.getInt(); 856 } 857 858 /** 859 * Creates a file that stores the Weaver slot the protector is using. The caller is responsible 860 * for calling {@link syncState()} afterwards, once all the protector's files have been created. 861 */ saveWeaverSlot(int slot, long protectorId, int userId)862 private void saveWeaverSlot(int slot, long protectorId, int userId) { 863 ByteBuffer buffer = ByteBuffer.allocate(Byte.BYTES + Integer.BYTES); 864 buffer.put(WEAVER_VERSION); 865 buffer.putInt(slot); 866 saveState(WEAVER_SLOT_NAME, buffer.array(), protectorId, userId); 867 } 868 destroyWeaverSlot(long protectorId, int userId)869 private void destroyWeaverSlot(long protectorId, int userId) { 870 int slot = loadWeaverSlot(protectorId, userId); 871 destroyState(WEAVER_SLOT_NAME, protectorId, userId); 872 if (slot != INVALID_WEAVER_SLOT) { 873 if (!isWeaverAvailable()) { 874 Slog.e(TAG, "Cannot erase Weaver slot because Weaver is unavailable"); 875 return; 876 } 877 Set<Integer> usedSlots = getUsedWeaverSlots(); 878 if (!usedSlots.contains(slot)) { 879 Slogf.i(TAG, "Erasing Weaver slot %d", slot); 880 weaverEnroll(slot, null, null); 881 mPasswordSlotManager.markSlotDeleted(slot); 882 } else { 883 Slogf.i(TAG, "Weaver slot %d was already reused; not erasing it", slot); 884 } 885 } 886 } 887 888 /** 889 * Return the set of weaver slots that are currently in use by all users on the device. 890 * <p> 891 * <em>Note:</em> Users who are in the process of being deleted are not tracked here 892 * (due to them being marked as partial in UserManager so not visible from 893 * {@link UserManager#getUsers}). As a result their weaver slots will not be considered 894 * taken and can be reused by new users. Care should be taken when cleaning up the 895 * deleted user in {@link #removeUser}, to prevent a reused slot from being erased 896 * unintentionally. 897 */ getUsedWeaverSlots()898 private Set<Integer> getUsedWeaverSlots() { 899 Map<Integer, List<Long>> protectorIds = 900 mStorage.listSyntheticPasswordProtectorsForAllUsers(WEAVER_SLOT_NAME); 901 HashSet<Integer> slots = new HashSet<>(); 902 for (Map.Entry<Integer, List<Long>> entry : protectorIds.entrySet()) { 903 for (Long protectorId : entry.getValue()) { 904 int slot = loadWeaverSlot(protectorId, entry.getKey()); 905 slots.add(slot); 906 } 907 } 908 return slots; 909 } 910 getNextAvailableWeaverSlot()911 private int getNextAvailableWeaverSlot() { 912 Set<Integer> usedSlots = getUsedWeaverSlots(); 913 usedSlots.addAll(mPasswordSlotManager.getUsedSlots()); 914 // If the device is not yet provisioned, then the Weaver slot used by the FRP credential may 915 // be still needed and must not be reused yet. (This *should* instead check "has FRP been 916 // resolved yet?", which would allow reusing the slot a bit earlier. However, the 917 // SECURE_FRP_MODE setting gets set to 1 too late for it to be used here.) 918 if (!isDeviceProvisioned()) { 919 PersistentData persistentData = mStorage.readPersistentDataBlock(); 920 if (persistentData != null && persistentData.type == PersistentData.TYPE_SP_WEAVER) { 921 int slot = persistentData.userId; // Note: field name is misleading 922 usedSlots.add(slot); 923 } 924 } 925 for (int i = 0; i < mWeaverConfig.slots; i++) { 926 if (!usedSlots.contains(i)) { 927 return i; 928 } 929 } 930 throw new IllegalStateException("Run out of weaver slots."); 931 } 932 933 /** 934 * Creates a protector that protects the user's SP with the given LSKF (which may be empty). 935 * 936 * This method only creates a new protector that isn't referenced by anything; it doesn't handle 937 * any higher-level tasks involved in changing the LSKF. 938 * 939 * @return the ID of the new protector 940 * @throws IllegalStateException on failure 941 */ createLskfBasedProtector(IGateKeeperService gatekeeper, LockscreenCredential credential, SyntheticPassword sp, int userId)942 public long createLskfBasedProtector(IGateKeeperService gatekeeper, 943 LockscreenCredential credential, SyntheticPassword sp, int userId) { 944 long protectorId = generateProtectorId(); 945 int pinLength = PIN_LENGTH_UNAVAILABLE; 946 if (isAutoPinConfirmationFeatureAvailable()) { 947 pinLength = derivePinLength(credential.size(), credential.isPin(), userId); 948 } 949 // There's no need to store password data about an empty LSKF. 950 PasswordData pwd = credential.isNone() ? null : 951 PasswordData.create(credential.getType(), pinLength); 952 byte[] stretchedLskf = stretchLskf(credential, pwd); 953 long sid = GateKeeper.INVALID_SECURE_USER_ID; 954 final byte[] protectorSecret; 955 956 Slogf.i(TAG, "Creating LSKF-based protector %016x for user %d", protectorId, userId); 957 958 if (isWeaverAvailable()) { 959 // Weaver is available, so make the protector use it to verify the LSKF. Do this even 960 // if the LSKF is empty, as that gives us support for securely deleting the protector. 961 int weaverSlot = getNextAvailableWeaverSlot(); 962 Slogf.i(TAG, "Enrolling LSKF for user %d into Weaver slot %d", userId, weaverSlot); 963 byte[] weaverSecret = weaverEnroll(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf), 964 null); 965 if (weaverSecret == null) { 966 throw new IllegalStateException( 967 "Fail to enroll user password under weaver " + userId); 968 } 969 saveWeaverSlot(weaverSlot, protectorId, userId); 970 mPasswordSlotManager.markSlotInUse(weaverSlot); 971 // No need to pass in quality since the credential type already encodes sufficient info 972 synchronizeWeaverFrpPassword(pwd, 0, userId, weaverSlot); 973 974 protectorSecret = transformUnderWeaverSecret(stretchedLskf, weaverSecret); 975 } else { 976 // Weaver is unavailable, so make the protector use Gatekeeper (GK) to verify the LSKF. 977 // 978 // However, skip GK when the LSKF is empty. There are two reasons for this, one 979 // performance and one correctness. The performance reason is that GK wouldn't give any 980 // benefit with an empty LSKF anyway, since GK isn't expected to provide secure 981 // deletion. The correctness reason is that it is unsafe to enroll a password in the 982 // 'fakeUserId' GK range on an FRP-protected device that is in the setup wizard with FRP 983 // not passed yet, as that may overwrite the enrollment used by the FRP credential. 984 if (!credential.isNone()) { 985 // In case GK enrollment leaves persistent state around (in RPMB), this will nuke 986 // them to prevent them from accumulating and causing problems. 987 try { 988 gatekeeper.clearSecureUserId(fakeUserId(userId)); 989 } catch (RemoteException ignore) { 990 Slog.w(TAG, "Failed to clear SID from gatekeeper"); 991 } 992 Slogf.i(TAG, "Enrolling LSKF for user %d into Gatekeeper", userId); 993 GateKeeperResponse response; 994 try { 995 response = gatekeeper.enroll(fakeUserId(userId), null, null, 996 stretchedLskfToGkPassword(stretchedLskf)); 997 } catch (RemoteException e) { 998 throw new IllegalStateException("Failed to enroll LSKF for new SP protector" 999 + " for user " + userId, e); 1000 } 1001 if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) { 1002 throw new IllegalStateException("Failed to enroll LSKF for new SP protector" 1003 + " for user " + userId); 1004 } 1005 pwd.passwordHandle = response.getPayload(); 1006 sid = sidFromPasswordHandle(pwd.passwordHandle); 1007 } 1008 protectorSecret = transformUnderSecdiscardable(stretchedLskf, 1009 createSecdiscardable(protectorId, userId)); 1010 // No need to pass in quality since the credential type already encodes sufficient info 1011 synchronizeGatekeeperFrpPassword(pwd, 0, userId); 1012 } 1013 if (!credential.isNone()) { 1014 saveState(PASSWORD_DATA_NAME, pwd.toBytes(), protectorId, userId); 1015 savePasswordMetrics(credential, sp, protectorId, userId); 1016 } 1017 createSyntheticPasswordBlob(protectorId, PROTECTOR_TYPE_LSKF_BASED, sp, protectorSecret, 1018 sid, userId); 1019 syncState(userId); // ensure the new files are really saved to disk 1020 return protectorId; 1021 } 1022 derivePinLength(int sizeOfCredential, boolean isPinCredential, int userId)1023 private int derivePinLength(int sizeOfCredential, boolean isPinCredential, int userId) { 1024 if (!isPinCredential 1025 || !mStorage.isAutoPinConfirmSettingEnabled(userId) 1026 || sizeOfCredential < LockPatternUtils.MIN_AUTO_PIN_REQUIREMENT_LENGTH) { 1027 return PIN_LENGTH_UNAVAILABLE; 1028 } 1029 return sizeOfCredential; 1030 } 1031 verifySpecialUserCredential(int sourceUserId, IGateKeeperService gatekeeper, LockscreenCredential userCredential, ICheckCredentialProgressCallback progressCallback)1032 public VerifyCredentialResponse verifySpecialUserCredential(int sourceUserId, 1033 IGateKeeperService gatekeeper, LockscreenCredential userCredential, 1034 ICheckCredentialProgressCallback progressCallback) { 1035 final PersistentData persistentData = getSpecialUserPersistentData(sourceUserId); 1036 if (persistentData.type == PersistentData.TYPE_SP_GATEKEEPER) { 1037 PasswordData pwd = PasswordData.fromBytes(persistentData.payload); 1038 byte[] stretchedLskf = stretchLskf(userCredential, pwd); 1039 1040 GateKeeperResponse response; 1041 try { 1042 response = gatekeeper.verifyChallenge(fakeUserId(persistentData.userId), 1043 0 /* challenge */, pwd.passwordHandle, 1044 stretchedLskfToGkPassword(stretchedLskf)); 1045 } catch (RemoteException e) { 1046 Slog.e(TAG, "Persistent data credential verifyChallenge failed", e); 1047 return VerifyCredentialResponse.ERROR; 1048 } 1049 return VerifyCredentialResponse.fromGateKeeperResponse(response); 1050 } else if (persistentData.type == PersistentData.TYPE_SP_WEAVER) { 1051 if (!isWeaverAvailable()) { 1052 Slog.e(TAG, "No weaver service to verify SP-based persistent data credential"); 1053 return VerifyCredentialResponse.ERROR; 1054 } 1055 PasswordData pwd = PasswordData.fromBytes(persistentData.payload); 1056 byte[] stretchedLskf = stretchLskf(userCredential, pwd); 1057 int weaverSlot = persistentData.userId; 1058 1059 return weaverVerify(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf)).stripPayload(); 1060 } else { 1061 Slog.e(TAG, "persistentData.type must be TYPE_SP_GATEKEEPER or TYPE_SP_WEAVER, but is " 1062 + persistentData.type); 1063 return VerifyCredentialResponse.ERROR; 1064 } 1065 } 1066 1067 migrateFrpPasswordLocked(long protectorId, UserInfo userInfo, int requestedQuality)1068 public void migrateFrpPasswordLocked(long protectorId, UserInfo userInfo, 1069 int requestedQuality) { 1070 if (mStorage.getPersistentDataBlockManager() != null 1071 && LockPatternUtils.userOwnsFrpCredential(mContext, userInfo) 1072 && getCredentialType(protectorId, userInfo.id) != 1073 LockPatternUtils.CREDENTIAL_TYPE_NONE) { 1074 Slog.i(TAG, "Migrating FRP credential to persistent data block"); 1075 PasswordData pwd = PasswordData.fromBytes(loadState(PASSWORD_DATA_NAME, protectorId, 1076 userInfo.id)); 1077 int weaverSlot = loadWeaverSlot(protectorId, userInfo.id); 1078 if (weaverSlot != INVALID_WEAVER_SLOT) { 1079 synchronizeWeaverFrpPassword(pwd, requestedQuality, userInfo.id, weaverSlot); 1080 } else { 1081 synchronizeGatekeeperFrpPassword(pwd, requestedQuality, userInfo.id); 1082 } 1083 } 1084 } 1085 isNoneCredential(PasswordData pwd)1086 private static boolean isNoneCredential(PasswordData pwd) { 1087 return pwd == null || pwd.credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE; 1088 } 1089 shouldSynchronizeFrpCredential(@ullable PasswordData pwd, int userId)1090 private boolean shouldSynchronizeFrpCredential(@Nullable PasswordData pwd, int userId) { 1091 if (mStorage.getPersistentDataBlockManager() == null) { 1092 return false; 1093 } 1094 UserInfo userInfo = mUserManager.getUserInfo(userId); 1095 if (!LockPatternUtils.userOwnsFrpCredential(mContext, userInfo)) { 1096 return false; 1097 } 1098 // When initializing the synthetic password of the user that will own the FRP credential, 1099 // the FRP data block must not be cleared if the device isn't provisioned yet, since in this 1100 // case the old value of the block may still be needed for the FRP authentication step. The 1101 // FRP data block will instead be cleared later, by 1102 // LockSettingsService.DeviceProvisionedObserver.clearFrpCredentialIfOwnerNotSecure(). 1103 // 1104 // Don't check the SECURE_FRP_MODE setting here, as it gets set to 1 too late. 1105 // 1106 // Don't delay anything for a nonempty credential. A nonempty credential can be set before 1107 // the device has been provisioned, but it's guaranteed to be after FRP was resolved. 1108 if (isNoneCredential(pwd) && !isDeviceProvisioned()) { 1109 Slog.d(TAG, "Not clearing FRP credential yet because device is not yet provisioned"); 1110 return false; 1111 } 1112 return true; 1113 } 1114 synchronizeGatekeeperFrpPassword(@ullable PasswordData pwd, int requestedQuality, int userId)1115 private void synchronizeGatekeeperFrpPassword(@Nullable PasswordData pwd, int requestedQuality, 1116 int userId) { 1117 if (shouldSynchronizeFrpCredential(pwd, userId)) { 1118 Slogf.d(TAG, "Syncing Gatekeeper-based FRP credential tied to user %d", userId); 1119 if (!isNoneCredential(pwd)) { 1120 mStorage.writePersistentDataBlock(PersistentData.TYPE_SP_GATEKEEPER, userId, 1121 requestedQuality, pwd.toBytes()); 1122 } else { 1123 mStorage.writePersistentDataBlock(PersistentData.TYPE_NONE, userId, 0, null); 1124 } 1125 } 1126 } 1127 synchronizeWeaverFrpPassword(@ullable PasswordData pwd, int requestedQuality, int userId, int weaverSlot)1128 private void synchronizeWeaverFrpPassword(@Nullable PasswordData pwd, int requestedQuality, 1129 int userId, int weaverSlot) { 1130 if (shouldSynchronizeFrpCredential(pwd, userId)) { 1131 Slogf.d(TAG, "Syncing Weaver-based FRP credential tied to user %d", userId); 1132 if (!isNoneCredential(pwd)) { 1133 mStorage.writePersistentDataBlock(PersistentData.TYPE_SP_WEAVER, weaverSlot, 1134 requestedQuality, pwd.toBytes()); 1135 } else { 1136 mStorage.writePersistentDataBlock(PersistentData.TYPE_NONE, 0, 0, null); 1137 } 1138 } 1139 } 1140 1141 /** 1142 * Writes the user's synthetic password data to the repair mode file. 1143 * 1144 * @param protectorId current LSKF based protectorId 1145 * @param userId user id of the user 1146 */ writeRepairModeCredentialLocked(long protectorId, int userId)1147 public boolean writeRepairModeCredentialLocked(long protectorId, int userId) { 1148 if (!shouldWriteRepairModeCredential(userId)) { 1149 return false; 1150 } 1151 final byte[] data = loadState(PASSWORD_DATA_NAME, protectorId, userId); 1152 if (data == null) { 1153 Slogf.w(TAG, "Password data not found for user %d", userId); 1154 return false; 1155 } 1156 final PasswordData pwd = PasswordData.fromBytes(data); 1157 if (isNoneCredential(pwd)) { 1158 Slogf.w(TAG, "User %d has NONE credential", userId); 1159 return false; 1160 } 1161 Slogf.d(TAG, "Writing repair mode credential tied to user %d", userId); 1162 final int weaverSlot = loadWeaverSlot(protectorId, userId); 1163 if (weaverSlot != INVALID_WEAVER_SLOT) { 1164 // write weaver password 1165 mStorage.writeRepairModePersistentData( 1166 PersistentData.TYPE_SP_WEAVER, weaverSlot, pwd.toBytes()); 1167 } else { 1168 // write gatekeeper password 1169 mStorage.writeRepairModePersistentData( 1170 PersistentData.TYPE_SP_GATEKEEPER, userId, pwd.toBytes()); 1171 } 1172 return true; 1173 } 1174 shouldWriteRepairModeCredential(int userId)1175 private boolean shouldWriteRepairModeCredential(int userId) { 1176 final UserInfo userInfo = mUserManager.getUserInfo(userId); 1177 if (!LockPatternUtils.canUserEnterRepairMode(mContext, userInfo)) { 1178 Slogf.w(TAG, "User %d can't enter repair mode", userId); 1179 return false; 1180 } 1181 if (LockPatternUtils.isRepairModeActive(mContext)) { 1182 Slog.w(TAG, "Can't write repair mode credential while repair mode is already active"); 1183 return false; 1184 } 1185 if (LockPatternUtils.isGsiRunning()) { 1186 Slog.w(TAG, "Can't write repair mode credential while GSI is running"); 1187 return false; 1188 } 1189 return true; 1190 } 1191 1192 private ArrayMap<Integer, ArrayMap<Long, TokenData>> tokenMap = new ArrayMap<>(); 1193 1194 /** 1195 * Caches a pending escrow token in memory and pre-allocates an ID for a new SP protector. This 1196 * ID also serves as a handle for the pending token. 1197 * 1198 * This method doesn't persist any data, and it doesn't require access to the SP. 1199 * {@link #createTokenBasedProtector} can be called later to actually create the protector. 1200 * 1201 * @return the token handle 1202 */ addPendingToken(byte[] token, @TokenType int type, int userId, @Nullable EscrowTokenStateChangeCallback changeCallback)1203 public long addPendingToken(byte[] token, @TokenType int type, int userId, 1204 @Nullable EscrowTokenStateChangeCallback changeCallback) { 1205 long tokenHandle = generateProtectorId(); // tokenHandle is reused as protectorId later 1206 if (!tokenMap.containsKey(userId)) { 1207 tokenMap.put(userId, new ArrayMap<>()); 1208 } 1209 TokenData tokenData = new TokenData(); 1210 tokenData.mType = type; 1211 final byte[] secdiscardable = SecureRandomUtils.randomBytes(SECDISCARDABLE_LENGTH); 1212 if (isWeaverAvailable()) { 1213 tokenData.weaverSecret = SecureRandomUtils.randomBytes(mWeaverConfig.valueSize); 1214 tokenData.secdiscardableOnDisk = SyntheticPasswordCrypto.encrypt(tokenData.weaverSecret, 1215 PERSONALIZATION_WEAVER_TOKEN, secdiscardable); 1216 } else { 1217 tokenData.secdiscardableOnDisk = secdiscardable; 1218 tokenData.weaverSecret = null; 1219 } 1220 tokenData.aggregatedSecret = transformUnderSecdiscardable(token, secdiscardable); 1221 tokenData.mCallback = changeCallback; 1222 1223 tokenMap.get(userId).put(tokenHandle, tokenData); 1224 return tokenHandle; 1225 } 1226 getPendingTokensForUser(int userId)1227 public Set<Long> getPendingTokensForUser(int userId) { 1228 if (!tokenMap.containsKey(userId)) { 1229 return Collections.emptySet(); 1230 } 1231 return new ArraySet<>(tokenMap.get(userId).keySet()); 1232 } 1233 1234 /** Remove the given pending token. */ removePendingToken(long tokenHandle, int userId)1235 public boolean removePendingToken(long tokenHandle, int userId) { 1236 if (!tokenMap.containsKey(userId)) { 1237 return false; 1238 } 1239 return tokenMap.get(userId).remove(tokenHandle) != null; 1240 } 1241 createTokenBasedProtector(long tokenHandle, SyntheticPassword sp, int userId)1242 public boolean createTokenBasedProtector(long tokenHandle, SyntheticPassword sp, int userId) { 1243 if (!tokenMap.containsKey(userId)) { 1244 return false; 1245 } 1246 TokenData tokenData = tokenMap.get(userId).get(tokenHandle); 1247 if (tokenData == null) { 1248 return false; 1249 } 1250 if (!loadEscrowData(sp, userId)) { 1251 Slog.w(TAG, "User is not escrowable"); 1252 return false; 1253 } 1254 Slogf.i(TAG, "Creating token-based protector %016x for user %d", tokenHandle, userId); 1255 if (isWeaverAvailable()) { 1256 int slot = getNextAvailableWeaverSlot(); 1257 Slogf.i(TAG, "Using Weaver slot %d for new token-based protector", slot); 1258 if (weaverEnroll(slot, null, tokenData.weaverSecret) == null) { 1259 Slog.e(TAG, "Failed to enroll weaver secret when activating token"); 1260 return false; 1261 } 1262 saveWeaverSlot(slot, tokenHandle, userId); 1263 mPasswordSlotManager.markSlotInUse(slot); 1264 } 1265 saveSecdiscardable(tokenHandle, tokenData.secdiscardableOnDisk, userId); 1266 createSyntheticPasswordBlob(tokenHandle, getTokenBasedProtectorType(tokenData.mType), sp, 1267 tokenData.aggregatedSecret, 0L, userId); 1268 syncState(userId); // ensure the new files are really saved to disk 1269 tokenMap.get(userId).remove(tokenHandle); 1270 if (tokenData.mCallback != null) { 1271 tokenData.mCallback.onEscrowTokenActivated(tokenHandle, userId); 1272 } 1273 return true; 1274 } 1275 1276 /** 1277 * Creates a synthetic password blob, i.e. the file that stores the encrypted synthetic password 1278 * (or encrypted escrow secret) for a protector. The caller is responsible for calling 1279 * {@link syncState()} afterwards, once all the protector's files have been created. 1280 */ createSyntheticPasswordBlob(long protectorId, byte protectorType, SyntheticPassword sp, byte[] protectorSecret, long sid, int userId)1281 private void createSyntheticPasswordBlob(long protectorId, byte protectorType, 1282 SyntheticPassword sp, byte[] protectorSecret, long sid, int userId) { 1283 final byte[] spSecret; 1284 if (protectorType == PROTECTOR_TYPE_STRONG_TOKEN_BASED 1285 || protectorType == PROTECTOR_TYPE_WEAK_TOKEN_BASED) { 1286 spSecret = sp.getEscrowSecret(); 1287 } else { 1288 spSecret = sp.getSyntheticPassword(); 1289 } 1290 byte[] content = createSpBlob(getProtectorKeyAlias(protectorId), spSecret, protectorSecret, 1291 sid); 1292 /* 1293 * We can upgrade from v1 to v2 because that's just a change in the way that 1294 * the SP is stored. However, we can't upgrade to v3 because that is a change 1295 * in the way that passwords are derived from the SP. 1296 */ 1297 byte version = sp.mVersion == SYNTHETIC_PASSWORD_VERSION_V3 1298 ? SYNTHETIC_PASSWORD_VERSION_V3 : SYNTHETIC_PASSWORD_VERSION_V2; 1299 1300 SyntheticPasswordBlob blob = SyntheticPasswordBlob.create(version, protectorType, content); 1301 saveState(SP_BLOB_NAME, blob.toByte(), protectorId, userId); 1302 } 1303 1304 /** 1305 * Tries to unlock a user's LSKF-based SP protector, given its ID and the claimed LSKF (which 1306 * may be empty). On success, returns the user's synthetic password, and also does a Gatekeeper 1307 * verification to refresh the SID and HardwareAuthToken maintained by the system. 1308 */ unlockLskfBasedProtector(IGateKeeperService gatekeeper, long protectorId, @NonNull LockscreenCredential credential, int userId, ICheckCredentialProgressCallback progressCallback)1309 public AuthenticationResult unlockLskfBasedProtector(IGateKeeperService gatekeeper, 1310 long protectorId, @NonNull LockscreenCredential credential, int userId, 1311 ICheckCredentialProgressCallback progressCallback) { 1312 AuthenticationResult result = new AuthenticationResult(); 1313 1314 if (protectorId == SyntheticPasswordManager.NULL_PROTECTOR_ID) { 1315 // This should never happen, due to the migration done in LSS.onThirdPartyAppsStarted(). 1316 Slogf.wtf(TAG, "Synthetic password not found for user %d", userId); 1317 result.gkResponse = VerifyCredentialResponse.ERROR; 1318 return result; 1319 } 1320 1321 // Load the PasswordData file. If it doesn't exist, then the LSKF is empty (i.e., 1322 // CREDENTIAL_TYPE_NONE), and we'll skip the scrypt and Gatekeeper steps. If it exists, 1323 // then either the LSKF is nonempty, or it's an old protector that uses scrypt and 1324 // Gatekeeper even though the LSKF is empty. 1325 byte[] pwdDataBytes = loadState(PASSWORD_DATA_NAME, protectorId, userId); 1326 PasswordData pwd = null; 1327 int storedType = LockPatternUtils.CREDENTIAL_TYPE_NONE; 1328 if (pwdDataBytes != null) { 1329 pwd = PasswordData.fromBytes(pwdDataBytes); 1330 storedType = pwd.credentialType; 1331 } 1332 if (!credential.checkAgainstStoredType(storedType)) { 1333 Slogf.e(TAG, "Credential type mismatch: stored type is %s but provided type is %s", 1334 LockPatternUtils.credentialTypeToString(storedType), 1335 LockPatternUtils.credentialTypeToString(credential.getType())); 1336 result.gkResponse = VerifyCredentialResponse.ERROR; 1337 return result; 1338 } 1339 1340 byte[] stretchedLskf = stretchLskf(credential, pwd); 1341 1342 final byte[] protectorSecret; 1343 long sid = GateKeeper.INVALID_SECURE_USER_ID; 1344 int weaverSlot = loadWeaverSlot(protectorId, userId); 1345 if (weaverSlot != INVALID_WEAVER_SLOT) { 1346 // Protector uses Weaver to verify the LSKF 1347 if (!isWeaverAvailable()) { 1348 Slog.e(TAG, "Protector uses Weaver, but Weaver is unavailable"); 1349 result.gkResponse = VerifyCredentialResponse.ERROR; 1350 return result; 1351 } 1352 result.gkResponse = weaverVerify(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf)); 1353 if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { 1354 return result; 1355 } 1356 protectorSecret = transformUnderWeaverSecret(stretchedLskf, 1357 result.gkResponse.getGatekeeperHAT()); 1358 } else { 1359 // Weaver is unavailable, so the protector uses Gatekeeper to verify the LSKF, unless 1360 // the LSKF is empty in which case Gatekeeper might not have been used at all. 1361 if (pwd == null || pwd.passwordHandle == null) { 1362 if (!credential.isNone()) { 1363 Slog.e(TAG, "Missing Gatekeeper password handle for nonempty LSKF"); 1364 result.gkResponse = VerifyCredentialResponse.ERROR; 1365 return result; 1366 } 1367 } else { 1368 byte[] gkPassword = stretchedLskfToGkPassword(stretchedLskf); 1369 GateKeeperResponse response; 1370 try { 1371 response = gatekeeper.verifyChallenge(fakeUserId(userId), 0L, 1372 pwd.passwordHandle, gkPassword); 1373 } catch (RemoteException e) { 1374 Slog.e(TAG, "gatekeeper verify failed", e); 1375 result.gkResponse = VerifyCredentialResponse.ERROR; 1376 return result; 1377 } 1378 int responseCode = response.getResponseCode(); 1379 if (responseCode == GateKeeperResponse.RESPONSE_OK) { 1380 result.gkResponse = VerifyCredentialResponse.OK; 1381 if (response.getShouldReEnroll()) { 1382 GateKeeperResponse reenrollResponse; 1383 try { 1384 reenrollResponse = gatekeeper.enroll(fakeUserId(userId), 1385 pwd.passwordHandle, gkPassword, gkPassword); 1386 } catch (RemoteException e) { 1387 Slog.w(TAG, "Fail to invoke gatekeeper.enroll", e); 1388 reenrollResponse = GateKeeperResponse.ERROR; 1389 // continue the flow anyway 1390 } 1391 if (reenrollResponse.getResponseCode() == GateKeeperResponse.RESPONSE_OK) { 1392 pwd.passwordHandle = reenrollResponse.getPayload(); 1393 // Use the reenrollment opportunity to update credential type 1394 // (getting rid of CREDENTIAL_TYPE_PASSWORD_OR_PIN) 1395 pwd.credentialType = credential.getType(); 1396 saveState(PASSWORD_DATA_NAME, pwd.toBytes(), protectorId, userId); 1397 syncState(userId); 1398 synchronizeGatekeeperFrpPassword(pwd, 0, userId); 1399 } else { 1400 Slog.w(TAG, "Fail to re-enroll user password for user " + userId); 1401 // continue the flow anyway 1402 } 1403 } 1404 } else if (responseCode == GateKeeperResponse.RESPONSE_RETRY) { 1405 result.gkResponse = VerifyCredentialResponse.fromTimeout(response.getTimeout()); 1406 return result; 1407 } else { 1408 result.gkResponse = VerifyCredentialResponse.ERROR; 1409 return result; 1410 } 1411 sid = sidFromPasswordHandle(pwd.passwordHandle); 1412 } 1413 byte[] secdiscardable = loadSecdiscardable(protectorId, userId); 1414 if (secdiscardable == null) { 1415 Slog.e(TAG, "secdiscardable file not found"); 1416 result.gkResponse = VerifyCredentialResponse.ERROR; 1417 return result; 1418 } 1419 protectorSecret = transformUnderSecdiscardable(stretchedLskf, secdiscardable); 1420 } 1421 // Supplied credential passes first stage weaver/gatekeeper check so it should be correct. 1422 // Notify the callback so the keyguard UI can proceed immediately. 1423 if (progressCallback != null) { 1424 try { 1425 progressCallback.onCredentialVerified(); 1426 } catch (RemoteException e) { 1427 Slog.w(TAG, "progressCallback throws exception", e); 1428 } 1429 } 1430 result.syntheticPassword = unwrapSyntheticPasswordBlob(protectorId, 1431 PROTECTOR_TYPE_LSKF_BASED, protectorSecret, sid, userId); 1432 1433 // Perform verifyChallenge to refresh auth tokens for GK if user password exists. 1434 result.gkResponse = verifyChallenge(gatekeeper, result.syntheticPassword, 0L, userId); 1435 1436 // Upgrade case: store the metrics if the device did not have stored metrics before, should 1437 // only happen once on old protectors. 1438 if (result.syntheticPassword != null && !credential.isNone() 1439 && !hasPasswordMetrics(protectorId, userId)) { 1440 savePasswordMetrics(credential, result.syntheticPassword, protectorId, userId); 1441 syncState(userId); // Not strictly needed as the upgrade can be re-done, but be safe. 1442 } 1443 return result; 1444 } 1445 1446 /** 1447 * {@link LockPatternUtils#refreshStoredPinLength(int)} 1448 * @param passwordMetrics passwordMetrics object containing the cached pin length 1449 * @param userId userId of the user whose pin length we want to store on disk 1450 * @param protectorId current LSKF based protectorId 1451 * @return true/false depending on whether PIN length has been saved on disk 1452 */ refreshPinLengthOnDisk(PasswordMetrics passwordMetrics, long protectorId, int userId)1453 public boolean refreshPinLengthOnDisk(PasswordMetrics passwordMetrics, 1454 long protectorId, int userId) { 1455 if (!isAutoPinConfirmationFeatureAvailable()) { 1456 return false; 1457 } 1458 1459 byte[] pwdDataBytes = loadState(PASSWORD_DATA_NAME, protectorId, userId); 1460 if (pwdDataBytes == null) { 1461 return false; 1462 } 1463 1464 PasswordData pwd = PasswordData.fromBytes(pwdDataBytes); 1465 int pinLength = derivePinLength(passwordMetrics.length, 1466 passwordMetrics.credType == CREDENTIAL_TYPE_PIN, userId); 1467 if (pwd.pinLength != pinLength) { 1468 pwd.pinLength = pinLength; 1469 saveState(PASSWORD_DATA_NAME, pwd.toBytes(), protectorId, userId); 1470 syncState(userId); 1471 } 1472 return true; 1473 } 1474 1475 /** 1476 * Tries to unlock a token-based SP protector (weak or strong), given its ID and the claimed 1477 * token. On success, returns the user's synthetic password, and also does a Gatekeeper 1478 * verification to refresh the SID and HardwareAuthToken maintained by the system. 1479 */ unlockTokenBasedProtector( IGateKeeperService gatekeeper, long protectorId, byte[] token, int userId)1480 public @NonNull AuthenticationResult unlockTokenBasedProtector( 1481 IGateKeeperService gatekeeper, long protectorId, byte[] token, int userId) { 1482 SyntheticPasswordBlob blob = SyntheticPasswordBlob.fromBytes(loadState(SP_BLOB_NAME, 1483 protectorId, userId)); 1484 return unlockTokenBasedProtectorInternal(gatekeeper, protectorId, blob.mProtectorType, 1485 token, userId); 1486 } 1487 1488 /** 1489 * Like {@link #unlockTokenBasedProtector}, but throws an exception if the protector is not for 1490 * a strong token specifically. 1491 */ unlockStrongTokenBasedProtector( IGateKeeperService gatekeeper, long protectorId, byte[] token, int userId)1492 public @NonNull AuthenticationResult unlockStrongTokenBasedProtector( 1493 IGateKeeperService gatekeeper, long protectorId, byte[] token, int userId) { 1494 return unlockTokenBasedProtectorInternal(gatekeeper, protectorId, 1495 PROTECTOR_TYPE_STRONG_TOKEN_BASED, token, userId); 1496 } 1497 1498 /** 1499 * Like {@link #unlockTokenBasedProtector}, but throws an exception if the protector is not for 1500 * a weak token specifically. 1501 */ unlockWeakTokenBasedProtector( IGateKeeperService gatekeeper, long protectorId, byte[] token, int userId)1502 public @NonNull AuthenticationResult unlockWeakTokenBasedProtector( 1503 IGateKeeperService gatekeeper, long protectorId, byte[] token, int userId) { 1504 return unlockTokenBasedProtectorInternal(gatekeeper, protectorId, 1505 PROTECTOR_TYPE_WEAK_TOKEN_BASED, token, userId); 1506 } 1507 unlockTokenBasedProtectorInternal( IGateKeeperService gatekeeper, long protectorId, byte expectedProtectorType, byte[] token, int userId)1508 private @NonNull AuthenticationResult unlockTokenBasedProtectorInternal( 1509 IGateKeeperService gatekeeper, long protectorId, byte expectedProtectorType, 1510 byte[] token, int userId) { 1511 AuthenticationResult result = new AuthenticationResult(); 1512 byte[] secdiscardable = loadSecdiscardable(protectorId, userId); 1513 if (secdiscardable == null) { 1514 Slog.e(TAG, "secdiscardable file not found"); 1515 result.gkResponse = VerifyCredentialResponse.ERROR; 1516 return result; 1517 } 1518 int slotId = loadWeaverSlot(protectorId, userId); 1519 if (slotId != INVALID_WEAVER_SLOT) { 1520 if (!isWeaverAvailable()) { 1521 Slog.e(TAG, "Protector uses Weaver, but Weaver is unavailable"); 1522 result.gkResponse = VerifyCredentialResponse.ERROR; 1523 return result; 1524 } 1525 VerifyCredentialResponse response = weaverVerify(slotId, null); 1526 if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK || 1527 response.getGatekeeperHAT() == null) { 1528 Slog.e(TAG, 1529 "Failed to retrieve Weaver secret when unlocking token-based protector"); 1530 result.gkResponse = VerifyCredentialResponse.ERROR; 1531 return result; 1532 } 1533 secdiscardable = SyntheticPasswordCrypto.decrypt(response.getGatekeeperHAT(), 1534 PERSONALIZATION_WEAVER_TOKEN, secdiscardable); 1535 } 1536 byte[] protectorSecret = transformUnderSecdiscardable(token, secdiscardable); 1537 result.syntheticPassword = unwrapSyntheticPasswordBlob(protectorId, expectedProtectorType, 1538 protectorSecret, 0L, userId); 1539 if (result.syntheticPassword != null) { 1540 result.gkResponse = verifyChallenge(gatekeeper, result.syntheticPassword, 0L, userId); 1541 if (result.gkResponse == null) { 1542 // The user currently has no password. return OK with null payload so null 1543 // is propagated to unlockUser() 1544 result.gkResponse = VerifyCredentialResponse.OK; 1545 } 1546 } else { 1547 result.gkResponse = VerifyCredentialResponse.ERROR; 1548 } 1549 return result; 1550 } 1551 unwrapSyntheticPasswordBlob(long protectorId, byte expectedProtectorType, byte[] protectorSecret, long sid, int userId)1552 private SyntheticPassword unwrapSyntheticPasswordBlob(long protectorId, 1553 byte expectedProtectorType, byte[] protectorSecret, long sid, int userId) { 1554 byte[] data = loadState(SP_BLOB_NAME, protectorId, userId); 1555 if (data == null) { 1556 return null; 1557 } 1558 SyntheticPasswordBlob blob = SyntheticPasswordBlob.fromBytes(data); 1559 if (blob.mVersion != SYNTHETIC_PASSWORD_VERSION_V3 1560 && blob.mVersion != SYNTHETIC_PASSWORD_VERSION_V2 1561 && blob.mVersion != SYNTHETIC_PASSWORD_VERSION_V1) { 1562 throw new IllegalArgumentException("Unknown blob version: " + blob.mVersion); 1563 } 1564 if (blob.mProtectorType != expectedProtectorType) { 1565 throw new IllegalArgumentException("Invalid protector type: " + blob.mProtectorType); 1566 } 1567 final byte[] spSecret; 1568 if (blob.mVersion == SYNTHETIC_PASSWORD_VERSION_V1) { 1569 spSecret = SyntheticPasswordCrypto.decryptBlobV1(getProtectorKeyAlias(protectorId), 1570 blob.mContent, protectorSecret); 1571 } else { 1572 spSecret = decryptSpBlob(getProtectorKeyAlias(protectorId), blob.mContent, 1573 protectorSecret); 1574 } 1575 if (spSecret == null) { 1576 Slog.e(TAG, "Fail to decrypt SP for user " + userId); 1577 return null; 1578 } 1579 SyntheticPassword result = new SyntheticPassword(blob.mVersion); 1580 if (blob.mProtectorType == PROTECTOR_TYPE_STRONG_TOKEN_BASED 1581 || blob.mProtectorType == PROTECTOR_TYPE_WEAK_TOKEN_BASED) { 1582 if (!loadEscrowData(result, userId)) { 1583 Slog.e(TAG, "User is not escrowable: " + userId); 1584 return null; 1585 } 1586 result.recreateFromEscrow(spSecret); 1587 } else { 1588 result.recreateDirectly(spSecret); 1589 } 1590 if (blob.mVersion == SYNTHETIC_PASSWORD_VERSION_V1) { 1591 Slog.i(TAG, "Upgrading v1 SP blob for user " + userId + ", protectorType = " 1592 + blob.mProtectorType); 1593 createSyntheticPasswordBlob(protectorId, blob.mProtectorType, result, protectorSecret, 1594 sid, userId); 1595 syncState(userId); // Not strictly needed as the upgrade can be re-done, but be safe. 1596 } 1597 return result; 1598 } 1599 1600 /** 1601 * performs GK verifyChallenge and returns auth token, re-enrolling SP password handle 1602 * if required. 1603 * 1604 * Normally performing verifyChallenge with an SP should always return RESPONSE_OK, since user 1605 * authentication failures are detected earlier when trying to decrypt the SP. 1606 */ verifyChallenge(IGateKeeperService gatekeeper, @NonNull SyntheticPassword sp, long challenge, int userId)1607 public @Nullable VerifyCredentialResponse verifyChallenge(IGateKeeperService gatekeeper, 1608 @NonNull SyntheticPassword sp, long challenge, int userId) { 1609 return verifyChallengeInternal(gatekeeper, sp.deriveGkPassword(), challenge, userId); 1610 } 1611 verifyChallengeInternal( IGateKeeperService gatekeeper, @NonNull byte[] gatekeeperPassword, long challenge, int userId)1612 protected @Nullable VerifyCredentialResponse verifyChallengeInternal( 1613 IGateKeeperService gatekeeper, @NonNull byte[] gatekeeperPassword, long challenge, 1614 int userId) { 1615 byte[] spHandle = loadSyntheticPasswordHandle(userId); 1616 if (spHandle == null) { 1617 // There is no password handle associated with the given user, i.e. the user is not 1618 // secured by lockscreen and has no SID, so just return here; 1619 return null; 1620 } 1621 GateKeeperResponse response; 1622 try { 1623 response = gatekeeper.verifyChallenge(userId, challenge, 1624 spHandle, gatekeeperPassword); 1625 } catch (RemoteException e) { 1626 Slog.e(TAG, "Fail to verify with gatekeeper " + userId, e); 1627 return VerifyCredentialResponse.ERROR; 1628 } 1629 int responseCode = response.getResponseCode(); 1630 if (responseCode == GateKeeperResponse.RESPONSE_OK) { 1631 VerifyCredentialResponse result = new VerifyCredentialResponse.Builder() 1632 .setGatekeeperHAT(response.getPayload()).build(); 1633 if (response.getShouldReEnroll()) { 1634 try { 1635 response = gatekeeper.enroll(userId, spHandle, spHandle, 1636 gatekeeperPassword); 1637 } catch (RemoteException e) { 1638 Slog.e(TAG, "Failed to invoke gatekeeper.enroll", e); 1639 response = GateKeeperResponse.ERROR; 1640 } 1641 if (response.getResponseCode() == GateKeeperResponse.RESPONSE_OK) { 1642 spHandle = response.getPayload(); 1643 saveSyntheticPasswordHandle(spHandle, userId); 1644 // Call self again to re-verify with updated handle 1645 return verifyChallengeInternal(gatekeeper, gatekeeperPassword, challenge, 1646 userId); 1647 } else { 1648 // Fall through, return result from the previous verification attempt. 1649 Slog.w(TAG, "Fail to re-enroll SP handle for user " + userId); 1650 } 1651 } 1652 return result; 1653 } else if (responseCode == GateKeeperResponse.RESPONSE_RETRY) { 1654 return VerifyCredentialResponse.fromTimeout(response.getTimeout()); 1655 } else { 1656 return VerifyCredentialResponse.ERROR; 1657 } 1658 } 1659 protectorExists(long protectorId, int userId)1660 public boolean protectorExists(long protectorId, int userId) { 1661 return hasState(SP_BLOB_NAME, protectorId, userId); 1662 } 1663 1664 /** Destroy a token-based SP protector. */ destroyTokenBasedProtector(long protectorId, int userId)1665 public void destroyTokenBasedProtector(long protectorId, int userId) { 1666 Slogf.i(TAG, "Destroying token-based protector %016x for user %d", protectorId, userId); 1667 SyntheticPasswordBlob blob = SyntheticPasswordBlob.fromBytes(loadState(SP_BLOB_NAME, 1668 protectorId, userId)); 1669 destroyProtectorCommon(protectorId, userId); 1670 if (blob.mProtectorType == PROTECTOR_TYPE_WEAK_TOKEN_BASED) { 1671 notifyWeakEscrowTokenRemovedListeners(protectorId, userId); 1672 } 1673 } 1674 1675 /** Destroy all weak token-based SP protectors for the given user. */ destroyAllWeakTokenBasedProtectors(int userId)1676 public void destroyAllWeakTokenBasedProtectors(int userId) { 1677 List<Long> protectorIds = 1678 mStorage.listSyntheticPasswordProtectorsForUser(SECDISCARDABLE_NAME, userId); 1679 for (long protectorId : protectorIds) { 1680 SyntheticPasswordBlob blob = SyntheticPasswordBlob.fromBytes(loadState(SP_BLOB_NAME, 1681 protectorId, userId)); 1682 if (blob.mProtectorType == PROTECTOR_TYPE_WEAK_TOKEN_BASED) { 1683 destroyTokenBasedProtector(protectorId, userId); 1684 } 1685 } 1686 } 1687 1688 /** 1689 * Destroy an LSKF-based SP protector. This is used when the user's LSKF is changed. 1690 */ destroyLskfBasedProtector(long protectorId, int userId)1691 public void destroyLskfBasedProtector(long protectorId, int userId) { 1692 Slogf.i(TAG, "Destroying LSKF-based protector %016x for user %d", protectorId, userId); 1693 destroyProtectorCommon(protectorId, userId); 1694 destroyState(PASSWORD_DATA_NAME, protectorId, userId); 1695 destroyState(PASSWORD_METRICS_NAME, protectorId, userId); 1696 } 1697 destroyProtectorCommon(long protectorId, int userId)1698 private void destroyProtectorCommon(long protectorId, int userId) { 1699 destroyState(SP_BLOB_NAME, protectorId, userId); 1700 destroyProtectorKey(getProtectorKeyAlias(protectorId)); 1701 destroyState(SECDISCARDABLE_NAME, protectorId, userId); 1702 if (hasState(WEAVER_SLOT_NAME, protectorId, userId)) { 1703 destroyWeaverSlot(protectorId, userId); 1704 } 1705 } 1706 transformUnderWeaverSecret(byte[] data, byte[] secret)1707 private byte[] transformUnderWeaverSecret(byte[] data, byte[] secret) { 1708 byte[] weaverSecret = SyntheticPasswordCrypto.personalizedHash( 1709 PERSONALIZATION_WEAVER_PASSWORD, secret); 1710 return ArrayUtils.concat(data, weaverSecret); 1711 } 1712 transformUnderSecdiscardable(byte[] data, byte[] rawSecdiscardable)1713 private byte[] transformUnderSecdiscardable(byte[] data, byte[] rawSecdiscardable) { 1714 byte[] secdiscardable = SyntheticPasswordCrypto.personalizedHash( 1715 PERSONALIZATION_SECDISCARDABLE, rawSecdiscardable); 1716 return ArrayUtils.concat(data, secdiscardable); 1717 } 1718 1719 /** 1720 * Generates and writes the secdiscardable file for the given protector. The caller is 1721 * responsible for calling {@link syncState()} afterwards, once all the protector's files have 1722 * been created. 1723 */ createSecdiscardable(long protectorId, int userId)1724 private byte[] createSecdiscardable(long protectorId, int userId) { 1725 byte[] data = SecureRandomUtils.randomBytes(SECDISCARDABLE_LENGTH); 1726 saveSecdiscardable(protectorId, data, userId); 1727 return data; 1728 } 1729 1730 /** 1731 * Writes the secdiscardable file for the given protector. The caller is responsible for 1732 * calling {@link syncState()} afterwards, once all the protector's files have been created. 1733 */ saveSecdiscardable(long protectorId, byte[] secdiscardable, int userId)1734 private void saveSecdiscardable(long protectorId, byte[] secdiscardable, int userId) { 1735 saveState(SECDISCARDABLE_NAME, secdiscardable, protectorId, userId); 1736 } 1737 loadSecdiscardable(long protectorId, int userId)1738 private byte[] loadSecdiscardable(long protectorId, int userId) { 1739 return loadState(SECDISCARDABLE_NAME, protectorId, userId); 1740 } 1741 getTokenBasedProtectorType(@okenType int type)1742 private byte getTokenBasedProtectorType(@TokenType int type) { 1743 switch (type) { 1744 case TOKEN_TYPE_WEAK: 1745 return PROTECTOR_TYPE_WEAK_TOKEN_BASED; 1746 case TOKEN_TYPE_STRONG: 1747 default: 1748 return PROTECTOR_TYPE_STRONG_TOKEN_BASED; 1749 } 1750 } 1751 1752 @VisibleForTesting hasPasswordData(long protectorId, int userId)1753 boolean hasPasswordData(long protectorId, int userId) { 1754 return hasState(PASSWORD_DATA_NAME, protectorId, userId); 1755 } 1756 1757 /** 1758 * Retrieves a user's saved password metrics from their LSKF-based SP protector. The 1759 * SyntheticPassword itself is needed to decrypt the file containing the password metrics. 1760 */ getPasswordMetrics(SyntheticPassword sp, long protectorId, int userId)1761 public @Nullable PasswordMetrics getPasswordMetrics(SyntheticPassword sp, long protectorId, 1762 int userId) { 1763 final byte[] encrypted = loadState(PASSWORD_METRICS_NAME, protectorId, userId); 1764 if (encrypted == null) { 1765 Slogf.e(TAG, "Failed to read password metrics file for user %d", userId); 1766 return null; 1767 } 1768 final byte[] decrypted = SyntheticPasswordCrypto.decrypt(sp.deriveMetricsKey(), 1769 /* personalization= */ new byte[0], encrypted); 1770 if (decrypted == null) { 1771 Slogf.e(TAG, "Failed to decrypt password metrics file for user %d", userId); 1772 return null; 1773 } 1774 return VersionedPasswordMetrics.deserialize(decrypted).getMetrics(); 1775 } 1776 1777 /** 1778 * Creates the password metrics file: the file associated with the LSKF-based protector that 1779 * contains the encrypted metrics about the LSKF. The caller is responsible for calling 1780 * {@link syncState()} afterwards if needed. 1781 */ savePasswordMetrics(LockscreenCredential credential, SyntheticPassword sp, long protectorId, int userId)1782 private void savePasswordMetrics(LockscreenCredential credential, SyntheticPassword sp, 1783 long protectorId, int userId) { 1784 final byte[] encrypted = SyntheticPasswordCrypto.encrypt(sp.deriveMetricsKey(), 1785 /* personalization= */ new byte[0], 1786 new VersionedPasswordMetrics(credential).serialize()); 1787 saveState(PASSWORD_METRICS_NAME, encrypted, protectorId, userId); 1788 } 1789 1790 @VisibleForTesting hasPasswordMetrics(long protectorId, int userId)1791 boolean hasPasswordMetrics(long protectorId, int userId) { 1792 return hasState(PASSWORD_METRICS_NAME, protectorId, userId); 1793 } 1794 hasState(String stateName, long protectorId, int userId)1795 private boolean hasState(String stateName, long protectorId, int userId) { 1796 return !ArrayUtils.isEmpty(loadState(stateName, protectorId, userId)); 1797 } 1798 loadState(String stateName, long protectorId, int userId)1799 private byte[] loadState(String stateName, long protectorId, int userId) { 1800 return mStorage.readSyntheticPasswordState(userId, protectorId, stateName); 1801 } 1802 1803 /** 1804 * Persists the given synthetic password state for the given user ID and protector ID. 1805 * <p> 1806 * For performance reasons, this doesn't sync the user's synthetic password state directory. As 1807 * a result, it doesn't guarantee that the file will really be present after a crash. If that 1808 * is needed, call {@link syncState()} afterwards, preferably after batching up related updates. 1809 */ saveState(String stateName, byte[] data, long protectorId, int userId)1810 private void saveState(String stateName, byte[] data, long protectorId, int userId) { 1811 mStorage.writeSyntheticPasswordState(userId, protectorId, stateName, data); 1812 } 1813 syncState(int userId)1814 private void syncState(int userId) { 1815 mStorage.syncSyntheticPasswordState(userId); 1816 } 1817 destroyState(String stateName, long protectorId, int userId)1818 private void destroyState(String stateName, long protectorId, int userId) { 1819 mStorage.deleteSyntheticPasswordState(userId, protectorId, stateName); 1820 } 1821 1822 @VisibleForTesting decryptSpBlob(String protectorKeyAlias, byte[] blob, byte[] protectorSecret)1823 protected byte[] decryptSpBlob(String protectorKeyAlias, byte[] blob, byte[] protectorSecret) { 1824 return SyntheticPasswordCrypto.decryptBlob(protectorKeyAlias, blob, protectorSecret); 1825 } 1826 1827 @VisibleForTesting createSpBlob(String protectorKeyAlias, byte[] data, byte[] protectorSecret, long sid)1828 protected byte[] createSpBlob(String protectorKeyAlias, byte[] data, byte[] protectorSecret, 1829 long sid) { 1830 return SyntheticPasswordCrypto.createBlob(protectorKeyAlias, data, protectorSecret, sid); 1831 } 1832 1833 @VisibleForTesting destroyProtectorKey(String keyAlias)1834 protected void destroyProtectorKey(String keyAlias) { 1835 SyntheticPasswordCrypto.destroyProtectorKey(keyAlias); 1836 } 1837 generateProtectorId()1838 private static long generateProtectorId() { 1839 while (true) { 1840 final long result = SecureRandomUtils.randomLong(); 1841 if (result != NULL_PROTECTOR_ID) { 1842 return result; 1843 } 1844 } 1845 } 1846 1847 @VisibleForTesting fakeUserId(int userId)1848 static int fakeUserId(int userId) { 1849 return 100000 + userId; 1850 } 1851 getProtectorKeyAlias(long protectorId)1852 private String getProtectorKeyAlias(long protectorId) { 1853 // Note, this arguably has a bug: %x should be %016x so that the protector ID is left-padded 1854 // with zeroes, like how the synthetic password state files are named. It's too late to fix 1855 // this, though, and it doesn't actually matter. 1856 return TextUtils.formatSimple("%s%x", PROTECTOR_KEY_ALIAS_PREFIX, protectorId); 1857 } 1858 1859 /** 1860 * Stretches <code>credential</code>, if needed, using the parameters from <code>data</code>. 1861 * <p> 1862 * When the credential is empty, stetching provides no security benefit. Thus, new protectors 1863 * for an empty credential use <code>null</code> {@link PasswordData} and skip the stretching. 1864 * <p> 1865 * However, old protectors always stored {@link PasswordData} and did the stretching, regardless 1866 * of whether the credential was empty or not. For this reason, this method also continues to 1867 * support stretching of empty credentials so that old protectors can still be unlocked. 1868 */ 1869 @VisibleForTesting stretchLskf(LockscreenCredential credential, @Nullable PasswordData data)1870 byte[] stretchLskf(LockscreenCredential credential, @Nullable PasswordData data) { 1871 final byte[] password = credential.isNone() ? DEFAULT_PASSWORD : credential.getCredential(); 1872 if (data == null) { 1873 Preconditions.checkArgument(credential.isNone()); 1874 return Arrays.copyOf(password, STRETCHED_LSKF_LENGTH); 1875 } 1876 return scrypt(password, data.salt, 1 << data.scryptLogN, 1 << data.scryptLogR, 1877 1 << data.scryptLogP, STRETCHED_LSKF_LENGTH); 1878 } 1879 stretchedLskfToGkPassword(byte[] stretchedLskf)1880 private byte[] stretchedLskfToGkPassword(byte[] stretchedLskf) { 1881 return SyntheticPasswordCrypto.personalizedHash(PERSONALIZATION_USER_GK_AUTH, 1882 stretchedLskf); 1883 } 1884 stretchedLskfToWeaverKey(byte[] stretchedLskf)1885 private byte[] stretchedLskfToWeaverKey(byte[] stretchedLskf) { 1886 byte[] key = SyntheticPasswordCrypto.personalizedHash(PERSONALIZATION_WEAVER_KEY, 1887 stretchedLskf); 1888 if (key.length < mWeaverConfig.keySize) { 1889 throw new IllegalArgumentException("weaver key length too small"); 1890 } 1891 return Arrays.copyOf(key, mWeaverConfig.keySize); 1892 } 1893 1894 @VisibleForTesting sidFromPasswordHandle(byte[] handle)1895 protected long sidFromPasswordHandle(byte[] handle) { 1896 return nativeSidFromPasswordHandle(handle); 1897 } 1898 1899 @VisibleForTesting scrypt(byte[] password, byte[] salt, int n, int r, int p, int outLen)1900 protected byte[] scrypt(byte[] password, byte[] salt, int n, int r, int p, int outLen) { 1901 return new Scrypt().scrypt(password, salt, n, r, p, outLen); 1902 } 1903 nativeSidFromPasswordHandle(byte[] handle)1904 private native long nativeSidFromPasswordHandle(byte[] handle); 1905 1906 @VisibleForTesting bytesToHex(byte[] bytes)1907 static byte[] bytesToHex(byte[] bytes) { 1908 return HexEncoding.encodeToString(bytes).getBytes(); 1909 } 1910 1911 /** 1912 * Migrates all existing SP protector keys from uid 1000 app domain to LSS selinux domain. 1913 */ migrateKeyNamespace()1914 public boolean migrateKeyNamespace() { 1915 boolean success = true; 1916 final Map<Integer, List<Long>> allProtectors = 1917 mStorage.listSyntheticPasswordProtectorsForAllUsers(SP_BLOB_NAME); 1918 for (List<Long> userProtectors : allProtectors.values()) { 1919 for (long protectorId : userProtectors) { 1920 success &= SyntheticPasswordCrypto.migrateLockSettingsKey( 1921 getProtectorKeyAlias(protectorId)); 1922 } 1923 } 1924 return success; 1925 } 1926 1927 /** Register the given IWeakEscrowTokenRemovedListener. */ registerWeakEscrowTokenRemovedListener( IWeakEscrowTokenRemovedListener listener)1928 public boolean registerWeakEscrowTokenRemovedListener( 1929 IWeakEscrowTokenRemovedListener listener) { 1930 return mListeners.register(listener); 1931 } 1932 1933 /** Unregister the given IWeakEscrowTokenRemovedListener. */ unregisterWeakEscrowTokenRemovedListener( IWeakEscrowTokenRemovedListener listener)1934 public boolean unregisterWeakEscrowTokenRemovedListener( 1935 IWeakEscrowTokenRemovedListener listener) { 1936 return mListeners.unregister(listener); 1937 } 1938 notifyWeakEscrowTokenRemovedListeners(long protectorId, int userId)1939 private void notifyWeakEscrowTokenRemovedListeners(long protectorId, int userId) { 1940 int i = mListeners.beginBroadcast(); 1941 try { 1942 while (i > 0) { 1943 i--; 1944 try { 1945 mListeners.getBroadcastItem(i).onWeakEscrowTokenRemoved(protectorId, userId); 1946 } catch (RemoteException e) { 1947 Slog.e(TAG, "Exception while notifying WeakEscrowTokenRemovedListener.", 1948 e); 1949 } 1950 } 1951 } finally { 1952 mListeners.finishBroadcast(); 1953 } 1954 } 1955 writeVendorAuthSecret( @onNull final byte[] vendorAuthSecret, @NonNull final SyntheticPassword sp, @UserIdInt final int userId)1956 public void writeVendorAuthSecret( 1957 @NonNull final byte[] vendorAuthSecret, 1958 @NonNull final SyntheticPassword sp, 1959 @UserIdInt final int userId) { 1960 final byte[] encrypted = 1961 SyntheticPasswordCrypto.encrypt( 1962 sp.deriveVendorAuthSecretEncryptionKey(), new byte[0], vendorAuthSecret); 1963 saveState(VENDOR_AUTH_SECRET_NAME, encrypted, NULL_PROTECTOR_ID, userId); 1964 syncState(userId); 1965 } 1966 readVendorAuthSecret( @onNull final SyntheticPassword sp, @UserIdInt final int userId)1967 public @Nullable byte[] readVendorAuthSecret( 1968 @NonNull final SyntheticPassword sp, @UserIdInt final int userId) { 1969 final byte[] encrypted = loadState(VENDOR_AUTH_SECRET_NAME, NULL_PROTECTOR_ID, userId); 1970 if (encrypted == null) { 1971 return null; 1972 } 1973 return SyntheticPasswordCrypto.decrypt( 1974 sp.deriveVendorAuthSecretEncryptionKey(), new byte[0], encrypted); 1975 } 1976 } 1977