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