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