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