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