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