• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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.internal.widget;
18 
19 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
20 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
21 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
22 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
23 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
24 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
25 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
26 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
27 
28 import android.annotation.IntDef;
29 import android.annotation.Nullable;
30 import android.annotation.UnsupportedAppUsage;
31 import android.app.admin.DevicePolicyManager;
32 import android.app.admin.PasswordMetrics;
33 import android.app.trust.IStrongAuthTracker;
34 import android.app.trust.TrustManager;
35 import android.content.ComponentName;
36 import android.content.ContentResolver;
37 import android.content.Context;
38 import android.content.pm.PackageManager;
39 import android.content.pm.UserInfo;
40 import android.os.AsyncTask;
41 import android.os.Handler;
42 import android.os.IBinder;
43 import android.os.Looper;
44 import android.os.Message;
45 import android.os.RemoteException;
46 import android.os.ServiceManager;
47 import android.os.SystemClock;
48 import android.os.UserHandle;
49 import android.os.UserManager;
50 import android.os.storage.IStorageManager;
51 import android.os.storage.StorageManager;
52 import android.provider.Settings;
53 import android.text.TextUtils;
54 import android.util.Log;
55 import android.util.SparseIntArray;
56 import android.util.SparseLongArray;
57 
58 import com.android.internal.annotations.VisibleForTesting;
59 import com.android.server.LocalServices;
60 
61 import com.google.android.collect.Lists;
62 
63 import libcore.util.HexEncoding;
64 
65 import java.lang.annotation.Retention;
66 import java.lang.annotation.RetentionPolicy;
67 import java.security.MessageDigest;
68 import java.security.NoSuchAlgorithmException;
69 import java.security.SecureRandom;
70 import java.util.ArrayList;
71 import java.util.Arrays;
72 import java.util.Collection;
73 import java.util.List;
74 import java.util.StringJoiner;
75 
76 /**
77  * Utilities for the lock pattern and its settings.
78  */
79 public class LockPatternUtils {
80 
81     private static final String TAG = "LockPatternUtils";
82     private static final boolean FRP_CREDENTIAL_ENABLED = true;
83 
84     /**
85      * The key to identify when the lock pattern enabled flag is being accessed for legacy reasons.
86      */
87     public static final String LEGACY_LOCK_PATTERN_ENABLED = "legacy_lock_pattern_enabled";
88 
89     /**
90      * The interval of the countdown for showing progress of the lockout.
91      */
92     public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L;
93 
94 
95     /**
96      * This dictates when we start telling the user that continued failed attempts will wipe
97      * their device.
98      */
99     public static final int FAILED_ATTEMPTS_BEFORE_WIPE_GRACE = 5;
100 
101     /**
102      * The minimum number of dots in a valid pattern.
103      */
104     public static final int MIN_LOCK_PATTERN_SIZE = 4;
105 
106     /**
107      * The minimum size of a valid password.
108      */
109     public static final int MIN_LOCK_PASSWORD_SIZE = 4;
110 
111     /**
112      * The minimum number of dots the user must include in a wrong pattern attempt for it to be
113      * counted.
114      */
115     public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE;
116 
117     public static final int CREDENTIAL_TYPE_NONE = -1;
118     public static final int CREDENTIAL_TYPE_PATTERN = 1;
119     public static final int CREDENTIAL_TYPE_PASSWORD = 2;
120 
121     @Retention(RetentionPolicy.SOURCE)
122     @IntDef(prefix = {"CREDENTIAL_TYPE_"}, value = {
123             CREDENTIAL_TYPE_NONE,
124             CREDENTIAL_TYPE_PATTERN,
125             CREDENTIAL_TYPE_PASSWORD, // Either pin or password.
126     })
127     public @interface CredentialType {}
128 
129     /**
130      * Special user id for triggering the FRP verification flow.
131      */
132     public static final int USER_FRP = UserHandle.USER_NULL + 1;
133 
134     @Deprecated
135     public final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
136     public final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
137     public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
138     @Deprecated
139     public final static String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
140     public final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
141     public final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled";
142     public final static String LOCKSCREEN_OPTIONS = "lockscreen.options";
143     @Deprecated
144     public final static String LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK
145             = "lockscreen.biometric_weak_fallback";
146     @Deprecated
147     public final static String BIOMETRIC_WEAK_EVER_CHOSEN_KEY
148             = "lockscreen.biometricweakeverchosen";
149     public final static String LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS
150             = "lockscreen.power_button_instantly_locks";
151     @Deprecated
152     public final static String LOCKSCREEN_WIDGETS_ENABLED = "lockscreen.widgets_enabled";
153 
154     public final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory";
155 
156     private static final String LOCK_SCREEN_OWNER_INFO = Settings.Secure.LOCK_SCREEN_OWNER_INFO;
157     private static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
158             Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
159 
160     private static final String LOCK_SCREEN_DEVICE_OWNER_INFO = "lockscreen.device_owner_info";
161 
162     private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
163     private static final String IS_TRUST_USUALLY_MANAGED = "lockscreen.istrustusuallymanaged";
164 
165     public static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_";
166     public static final String PROFILE_KEY_NAME_DECRYPT = "profile_key_name_decrypt_";
167     public static final String SYNTHETIC_PASSWORD_KEY_PREFIX = "synthetic_password_";
168 
169     public static final String SYNTHETIC_PASSWORD_HANDLE_KEY = "sp-handle";
170     public static final String SYNTHETIC_PASSWORD_ENABLED_KEY = "enable-sp";
171     private static final String HISTORY_DELIMITER = ",";
172 
173     @UnsupportedAppUsage
174     private final Context mContext;
175     @UnsupportedAppUsage
176     private final ContentResolver mContentResolver;
177     private DevicePolicyManager mDevicePolicyManager;
178     private ILockSettings mLockSettingsService;
179     private UserManager mUserManager;
180     private final Handler mHandler;
181     private final SparseLongArray mLockoutDeadlines = new SparseLongArray();
182     private Boolean mHasSecureLockScreen;
183 
184     /**
185      * Use {@link TrustManager#isTrustUsuallyManaged(int)}.
186      *
187      * This returns the lazily-peristed value and should only be used by TrustManagerService.
188      */
isTrustUsuallyManaged(int userId)189     public boolean isTrustUsuallyManaged(int userId) {
190         if (!(mLockSettingsService instanceof ILockSettings.Stub)) {
191             throw new IllegalStateException("May only be called by TrustManagerService. "
192                     + "Use TrustManager.isTrustUsuallyManaged()");
193         }
194         try {
195             return getLockSettings().getBoolean(IS_TRUST_USUALLY_MANAGED, false, userId);
196         } catch (RemoteException e) {
197             return false;
198         }
199     }
200 
setTrustUsuallyManaged(boolean managed, int userId)201     public void setTrustUsuallyManaged(boolean managed, int userId) {
202         try {
203             getLockSettings().setBoolean(IS_TRUST_USUALLY_MANAGED, managed, userId);
204         } catch (RemoteException e) {
205             // System dead.
206         }
207     }
208 
userPresent(int userId)209     public void userPresent(int userId) {
210         try {
211             getLockSettings().userPresent(userId);
212         } catch (RemoteException e) {
213             throw e.rethrowFromSystemServer();
214         }
215     }
216 
217     public static final class RequestThrottledException extends Exception {
218         private int mTimeoutMs;
219         @UnsupportedAppUsage
RequestThrottledException(int timeoutMs)220         public RequestThrottledException(int timeoutMs) {
221             mTimeoutMs = timeoutMs;
222         }
223 
224         /**
225          * @return The amount of time in ms before another request may
226          * be executed
227          */
228         @UnsupportedAppUsage
getTimeoutMs()229         public int getTimeoutMs() {
230             return mTimeoutMs;
231         }
232 
233     }
234 
235     @UnsupportedAppUsage
getDevicePolicyManager()236     public DevicePolicyManager getDevicePolicyManager() {
237         if (mDevicePolicyManager == null) {
238             mDevicePolicyManager =
239                 (DevicePolicyManager)mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
240             if (mDevicePolicyManager == null) {
241                 Log.e(TAG, "Can't get DevicePolicyManagerService: is it running?",
242                         new IllegalStateException("Stack trace:"));
243             }
244         }
245         return mDevicePolicyManager;
246     }
247 
getUserManager()248     private UserManager getUserManager() {
249         if (mUserManager == null) {
250             mUserManager = UserManager.get(mContext);
251         }
252         return mUserManager;
253     }
254 
getTrustManager()255     private TrustManager getTrustManager() {
256         TrustManager trust = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
257         if (trust == null) {
258             Log.e(TAG, "Can't get TrustManagerService: is it running?",
259                     new IllegalStateException("Stack trace:"));
260         }
261         return trust;
262     }
263 
264     @UnsupportedAppUsage
LockPatternUtils(Context context)265     public LockPatternUtils(Context context) {
266         mContext = context;
267         mContentResolver = context.getContentResolver();
268 
269         Looper looper = Looper.myLooper();
270         mHandler = looper != null ? new Handler(looper) : null;
271     }
272 
273     @UnsupportedAppUsage
274     @VisibleForTesting
getLockSettings()275     public ILockSettings getLockSettings() {
276         if (mLockSettingsService == null) {
277             ILockSettings service = ILockSettings.Stub.asInterface(
278                     ServiceManager.getService("lock_settings"));
279             mLockSettingsService = service;
280         }
281         return mLockSettingsService;
282     }
283 
getRequestedMinimumPasswordLength(int userId)284     public int getRequestedMinimumPasswordLength(int userId) {
285         return getDevicePolicyManager().getPasswordMinimumLength(null, userId);
286     }
287 
getMaximumPasswordLength(int quality)288     public int getMaximumPasswordLength(int quality) {
289         return getDevicePolicyManager().getPasswordMaximumLength(quality);
290     }
291 
292     /**
293      * Gets the device policy password mode. If the mode is non-specific, returns
294      * MODE_PATTERN which allows the user to choose anything.
295      */
getRequestedPasswordQuality(int userId)296     public int getRequestedPasswordQuality(int userId) {
297         return getDevicePolicyManager().getPasswordQuality(null, userId);
298     }
299 
getRequestedPasswordHistoryLength(int userId)300     private int getRequestedPasswordHistoryLength(int userId) {
301         return getDevicePolicyManager().getPasswordHistoryLength(null, userId);
302     }
303 
getRequestedPasswordMinimumLetters(int userId)304     public int getRequestedPasswordMinimumLetters(int userId) {
305         return getDevicePolicyManager().getPasswordMinimumLetters(null, userId);
306     }
307 
getRequestedPasswordMinimumUpperCase(int userId)308     public int getRequestedPasswordMinimumUpperCase(int userId) {
309         return getDevicePolicyManager().getPasswordMinimumUpperCase(null, userId);
310     }
311 
getRequestedPasswordMinimumLowerCase(int userId)312     public int getRequestedPasswordMinimumLowerCase(int userId) {
313         return getDevicePolicyManager().getPasswordMinimumLowerCase(null, userId);
314     }
315 
getRequestedPasswordMinimumNumeric(int userId)316     public int getRequestedPasswordMinimumNumeric(int userId) {
317         return getDevicePolicyManager().getPasswordMinimumNumeric(null, userId);
318     }
319 
getRequestedPasswordMinimumSymbols(int userId)320     public int getRequestedPasswordMinimumSymbols(int userId) {
321         return getDevicePolicyManager().getPasswordMinimumSymbols(null, userId);
322     }
323 
getRequestedPasswordMinimumNonLetter(int userId)324     public int getRequestedPasswordMinimumNonLetter(int userId) {
325         return getDevicePolicyManager().getPasswordMinimumNonLetter(null, userId);
326     }
327 
328     @UnsupportedAppUsage
reportFailedPasswordAttempt(int userId)329     public void reportFailedPasswordAttempt(int userId) {
330         if (userId == USER_FRP && frpCredentialEnabled(mContext)) {
331             return;
332         }
333         getDevicePolicyManager().reportFailedPasswordAttempt(userId);
334         getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
335     }
336 
337     @UnsupportedAppUsage
reportSuccessfulPasswordAttempt(int userId)338     public void reportSuccessfulPasswordAttempt(int userId) {
339         if (userId == USER_FRP && frpCredentialEnabled(mContext)) {
340             return;
341         }
342         getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId);
343         getTrustManager().reportUnlockAttempt(true /* authenticated */, userId);
344     }
345 
reportPasswordLockout(int timeoutMs, int userId)346     public void reportPasswordLockout(int timeoutMs, int userId) {
347         if (userId == USER_FRP && frpCredentialEnabled(mContext)) {
348             return;
349         }
350         getTrustManager().reportUnlockLockout(timeoutMs, userId);
351     }
352 
getCurrentFailedPasswordAttempts(int userId)353     public int getCurrentFailedPasswordAttempts(int userId) {
354         if (userId == USER_FRP && frpCredentialEnabled(mContext)) {
355             return 0;
356         }
357         return getDevicePolicyManager().getCurrentFailedPasswordAttempts(userId);
358     }
359 
getMaximumFailedPasswordsForWipe(int userId)360     public int getMaximumFailedPasswordsForWipe(int userId) {
361         if (userId == USER_FRP && frpCredentialEnabled(mContext)) {
362             return 0;
363         }
364         return getDevicePolicyManager().getMaximumFailedPasswordsForWipe(
365                 null /* componentName */, userId);
366     }
367 
verifyCredential(byte[] credential, int type, long challenge, int userId)368     private byte[] verifyCredential(byte[] credential, int type, long challenge, int userId)
369             throws RequestThrottledException {
370         try {
371             VerifyCredentialResponse response = getLockSettings().verifyCredential(credential,
372                     type, challenge, userId);
373             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
374                 return response.getPayload();
375             } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
376                 throw new RequestThrottledException(response.getTimeout());
377             } else {
378                 return null;
379             }
380         } catch (RemoteException re) {
381             return null;
382         }
383     }
384 
checkCredential(byte[] credential, int type, int userId, @Nullable CheckCredentialProgressCallback progressCallback)385     private boolean checkCredential(byte[] credential, int type, int userId,
386             @Nullable CheckCredentialProgressCallback progressCallback)
387             throws RequestThrottledException {
388         try {
389             VerifyCredentialResponse response = getLockSettings().checkCredential(credential, type,
390                     userId, wrapCallback(progressCallback));
391 
392             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
393                 return true;
394             } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
395                 throw new RequestThrottledException(response.getTimeout());
396             } else {
397                 return false;
398             }
399         } catch (RemoteException re) {
400             return false;
401         }
402     }
403 
404     /**
405      * Check to see if a pattern matches the saved pattern.
406      * If pattern matches, return an opaque attestation that the challenge
407      * was verified.
408      *
409      * @param pattern The pattern to check.
410      * @param challenge The challenge to verify against the pattern
411      * @return the attestation that the challenge was verified, or null.
412      */
verifyPattern(List<LockPatternView.Cell> pattern, long challenge, int userId)413     public byte[] verifyPattern(List<LockPatternView.Cell> pattern, long challenge, int userId)
414             throws RequestThrottledException {
415         throwIfCalledOnMainThread();
416         return verifyCredential(patternToByteArray(pattern), CREDENTIAL_TYPE_PATTERN, challenge,
417                 userId);
418     }
419 
420     /**
421      * Check to see if a pattern matches the saved pattern.  If no pattern exists,
422      * always returns true.
423      * @param pattern The pattern to check.
424      * @return Whether the pattern matches the stored one.
425      */
checkPattern(List<LockPatternView.Cell> pattern, int userId)426     public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId)
427             throws RequestThrottledException {
428         return checkPattern(pattern, userId, null /* progressCallback */);
429     }
430 
431     /**
432      * Check to see if a pattern matches the saved pattern.  If no pattern exists,
433      * always returns true.
434      * @param pattern The pattern to check.
435      * @return Whether the pattern matches the stored one.
436      */
checkPattern(List<LockPatternView.Cell> pattern, int userId, @Nullable CheckCredentialProgressCallback progressCallback)437     public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId,
438             @Nullable CheckCredentialProgressCallback progressCallback)
439             throws RequestThrottledException {
440         throwIfCalledOnMainThread();
441         return checkCredential(patternToByteArray(pattern), CREDENTIAL_TYPE_PATTERN, userId,
442                 progressCallback);
443     }
444 
445     /**
446      * Check to see if a password matches the saved password.
447      * If password matches, return an opaque attestation that the challenge
448      * was verified.
449      *
450      * @param password The password to check.
451      * @param challenge The challenge to verify against the password
452      * @return the attestation that the challenge was verified, or null.
453      */
verifyPassword(byte[] password, long challenge, int userId)454     public byte[] verifyPassword(byte[] password, long challenge, int userId)
455             throws RequestThrottledException {
456         throwIfCalledOnMainThread();
457         return verifyCredential(password, CREDENTIAL_TYPE_PASSWORD, challenge, userId);
458     }
459 
460 
461     /**
462      * Check to see if a password matches the saved password.
463      * If password matches, return an opaque attestation that the challenge
464      * was verified.
465      *
466      * @param password The password to check.
467      * @param challenge The challenge to verify against the password
468      * @return the attestation that the challenge was verified, or null.
469      */
verifyTiedProfileChallenge(byte[] password, boolean isPattern, long challenge, int userId)470     public byte[] verifyTiedProfileChallenge(byte[] password, boolean isPattern, long challenge,
471             int userId) throws RequestThrottledException {
472         throwIfCalledOnMainThread();
473         try {
474             VerifyCredentialResponse response =
475                     getLockSettings().verifyTiedProfileChallenge(password,
476                             isPattern ? CREDENTIAL_TYPE_PATTERN : CREDENTIAL_TYPE_PASSWORD, challenge,
477                             userId);
478 
479             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
480                 return response.getPayload();
481             } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
482                 throw new RequestThrottledException(response.getTimeout());
483             } else {
484                 return null;
485             }
486         } catch (RemoteException re) {
487             return null;
488         }
489     }
490 
491     /**
492      *
493      * Check to see if a password matches the saved password.  If no password exists,
494      * always returns true.
495      * @param password The password to check.
496      * @return Whether the password matches the stored one.
497      */
498     @UnsupportedAppUsage
checkPassword(String password, int userId)499     public boolean checkPassword(String password, int userId) throws RequestThrottledException {
500         byte[] passwordBytes = password != null ? password.getBytes() : null;
501         return checkPassword(passwordBytes, userId, null /* progressCallback */);
502     }
503 
504 
505     /**
506      *
507      * Check to see if a password matches the saved password.  If no password exists,
508      * always returns true.
509      * @param password The password to check.
510      * @return Whether the password matches the stored one.
511      */
checkPassword(byte[] password, int userId)512     public boolean checkPassword(byte[] password, int userId) throws RequestThrottledException {
513         return checkPassword(password, userId, null /* progressCallback */);
514     }
515 
516     // TODO(b/120484642): This method is necessary for vendor/qcom code and is a hidden api
517     /* *
518      * Check to see if a password matches the saved password.  If no password exists,
519      * always returns true.
520      * @param password The password to check.
521      * @return Whether the password matches the stored one.
522      */
checkPassword(String password, int userId, @Nullable CheckCredentialProgressCallback progressCallback)523     public boolean checkPassword(String password, int userId,
524             @Nullable CheckCredentialProgressCallback progressCallback)
525             throws RequestThrottledException {
526         byte[] passwordBytes = password != null ? password.getBytes() : null;
527         throwIfCalledOnMainThread();
528         return checkCredential(passwordBytes, CREDENTIAL_TYPE_PASSWORD, userId, progressCallback);
529 
530     }
531 
532     /**
533      * Check to see if a password matches the saved password.  If no password exists,
534      * always returns true.
535      * @param password The password to check.
536      * @return Whether the password matches the stored one.
537      */
538 
checkPassword(byte[] password, int userId, @Nullable CheckCredentialProgressCallback progressCallback)539     public boolean checkPassword(byte[] password, int userId,
540             @Nullable CheckCredentialProgressCallback progressCallback)
541             throws RequestThrottledException {
542         throwIfCalledOnMainThread();
543         return checkCredential(password, CREDENTIAL_TYPE_PASSWORD, userId, progressCallback);
544     }
545 
546     /**
547      * Check to see if vold already has the password.
548      * Note that this also clears vold's copy of the password.
549      * @return Whether the vold password matches or not.
550      */
checkVoldPassword(int userId)551     public boolean checkVoldPassword(int userId) {
552         try {
553             return getLockSettings().checkVoldPassword(userId);
554         } catch (RemoteException re) {
555             return false;
556         }
557     }
558 
559     /**
560      * Returns the password history hash factor, needed to check new password against password
561      * history with {@link #checkPasswordHistory(String, byte[], int)}
562      */
getPasswordHistoryHashFactor(byte[] currentPassword, int userId)563     public byte[] getPasswordHistoryHashFactor(byte[] currentPassword, int userId) {
564         try {
565             return getLockSettings().getHashFactor(currentPassword, userId);
566         } catch (RemoteException e) {
567             Log.e(TAG, "failed to get hash factor", e);
568             return null;
569         }
570     }
571 
572     /**
573      * Check to see if a password matches any of the passwords stored in the
574      * password history.
575      *
576      * @param passwordToCheck The password to check.
577      * @param hashFactor Hash factor of the current user returned from
578      *        {@link ILockSettings#getHashFactor}
579      * @return Whether the password matches any in the history.
580      */
checkPasswordHistory(byte[] passwordToCheck, byte[] hashFactor, int userId)581     public boolean checkPasswordHistory(byte[] passwordToCheck, byte[] hashFactor, int userId) {
582         if (passwordToCheck == null || passwordToCheck.length == 0) {
583             Log.e(TAG, "checkPasswordHistory: empty password");
584             return false;
585         }
586         String passwordHistory = getString(PASSWORD_HISTORY_KEY, userId);
587         if (TextUtils.isEmpty(passwordHistory)) {
588             return false;
589         }
590         int passwordHistoryLength = getRequestedPasswordHistoryLength(userId);
591         if(passwordHistoryLength == 0) {
592             return false;
593         }
594         String legacyHash = legacyPasswordToHash(passwordToCheck, userId);
595         String passwordHash = passwordToHistoryHash(passwordToCheck, hashFactor, userId);
596         String[] history = passwordHistory.split(HISTORY_DELIMITER);
597         // Password History may be too long...
598         for (int i = 0; i < Math.min(passwordHistoryLength, history.length); i++) {
599             if (history[i].equals(legacyHash) || history[i].equals(passwordHash)) {
600                 return true;
601             }
602         }
603         return false;
604     }
605 
606     /**
607      * Check to see if the user has stored a lock pattern.
608      * @return Whether a saved pattern exists.
609      */
savedPatternExists(int userId)610     private boolean savedPatternExists(int userId) {
611         try {
612             return getLockSettings().havePattern(userId);
613         } catch (RemoteException re) {
614             return false;
615         }
616     }
617 
618     /**
619      * Check to see if the user has stored a lock pattern.
620      * @return Whether a saved pattern exists.
621      */
savedPasswordExists(int userId)622     private boolean savedPasswordExists(int userId) {
623         try {
624             return getLockSettings().havePassword(userId);
625         } catch (RemoteException re) {
626             return false;
627         }
628     }
629 
630     /**
631      * Return true if the user has ever chosen a pattern.  This is true even if the pattern is
632      * currently cleared.
633      *
634      * @return True if the user has ever chosen a pattern.
635      */
isPatternEverChosen(int userId)636     public boolean isPatternEverChosen(int userId) {
637         return getBoolean(PATTERN_EVER_CHOSEN_KEY, false, userId);
638     }
639 
640     /**
641      * Records that the user has chosen a pattern at some time, even if the pattern is
642      * currently cleared.
643      */
reportPatternWasChosen(int userId)644     public void reportPatternWasChosen(int userId) {
645         setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
646     }
647 
648     /**
649      * Used by device policy manager to validate the current password
650      * information it has.
651      */
652     @UnsupportedAppUsage
getActivePasswordQuality(int userId)653     public int getActivePasswordQuality(int userId) {
654         int quality = getKeyguardStoredPasswordQuality(userId);
655 
656         if (isLockPasswordEnabled(quality, userId)) {
657             // Quality is a password and a password exists. Return the quality.
658             return quality;
659         }
660 
661         if (isLockPatternEnabled(quality, userId)) {
662             // Quality is a pattern and a pattern exists. Return the quality.
663             return quality;
664         }
665 
666         return PASSWORD_QUALITY_UNSPECIFIED;
667     }
668 
669     /**
670      * Use it to reset keystore without wiping work profile
671      */
resetKeyStore(int userId)672     public void resetKeyStore(int userId) {
673         try {
674             getLockSettings().resetKeyStore(userId);
675         } catch (RemoteException e) {
676             // It should not happen
677             Log.e(TAG, "Couldn't reset keystore " + e);
678         }
679     }
680 
681     /**
682      * Clear any lock pattern or password.
683      */
clearLock(byte[] savedCredential, int userHandle)684     public boolean clearLock(byte[] savedCredential, int userHandle) {
685         return clearLock(savedCredential, userHandle, false);
686     }
687 
688     /**
689      * Clear any lock pattern or password, with the option to ignore incorrect existing credential.
690      */
clearLock(byte[] savedCredential, int userHandle, boolean allowUntrustedChange)691     public boolean clearLock(byte[] savedCredential, int userHandle, boolean allowUntrustedChange) {
692         final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
693         setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED, userHandle);
694 
695         try{
696             getLockSettings().setLockCredential(null, CREDENTIAL_TYPE_NONE,
697                     savedCredential, PASSWORD_QUALITY_UNSPECIFIED, userHandle,
698                     allowUntrustedChange);
699         } catch (Exception e) {
700             Log.e(TAG, "Failed to clear lock", e);
701             setKeyguardStoredPasswordQuality(currentQuality, userHandle);
702             return false;
703         }
704 
705         if (userHandle == UserHandle.USER_SYSTEM) {
706             // Set the encryption password to default.
707             updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
708             setCredentialRequiredToDecrypt(false);
709         }
710 
711         onAfterChangingPassword(userHandle);
712         return true;
713     }
714 
715     /**
716      * Disable showing lock screen at all for a given user.
717      * This is only meaningful if pattern, pin or password are not set.
718      *
719      * @param disable Disables lock screen when true
720      * @param userId User ID of the user this has effect on
721      */
setLockScreenDisabled(boolean disable, int userId)722     public void setLockScreenDisabled(boolean disable, int userId) {
723         setBoolean(DISABLE_LOCKSCREEN_KEY, disable, userId);
724     }
725 
726     /**
727      * Determine if LockScreen is disabled for the current user. This is used to decide whether
728      * LockScreen is shown after reboot or after screen timeout / short press on power.
729      *
730      * @return true if lock screen is disabled
731      */
732     @UnsupportedAppUsage
isLockScreenDisabled(int userId)733     public boolean isLockScreenDisabled(int userId) {
734         if (isSecure(userId)) {
735             return false;
736         }
737         boolean disabledByDefault = mContext.getResources().getBoolean(
738                 com.android.internal.R.bool.config_disableLockscreenByDefault);
739         boolean isSystemUser = UserManager.isSplitSystemUser() && userId == UserHandle.USER_SYSTEM;
740         UserInfo userInfo = getUserManager().getUserInfo(userId);
741         boolean isDemoUser = UserManager.isDeviceInDemoMode(mContext) && userInfo != null
742                 && userInfo.isDemo();
743         return getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId)
744                 || (disabledByDefault && !isSystemUser)
745                 || isDemoUser;
746     }
747 
748     /**
749      * Save a lock pattern.
750      * @param pattern The new pattern to save.
751      * @param savedPattern The previously saved pattern, converted to byte[] format
752      * @param userId the user whose pattern is to be saved.
753      *
754      * @return whether this was successful or not.
755      */
saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern, int userId)756     public boolean saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern,
757             int userId) {
758         return saveLockPattern(pattern, savedPattern, userId, false);
759     }
760 
761     /**
762      * Save a lock pattern.
763      * @param pattern The new pattern to save.
764      * @param savedPattern The previously saved pattern, converted to byte[] format
765      * @param userId the user whose pattern is to be saved.
766      * @param allowUntrustedChange whether we want to allow saving a new password if the existing
767      * password being provided is incorrect.
768      *
769      * @return whether this was successful or not.
770      */
saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern, int userId, boolean allowUntrustedChange)771     public boolean saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern,
772             int userId, boolean allowUntrustedChange) {
773         if (!hasSecureLockScreen()) {
774             throw new UnsupportedOperationException(
775                     "This operation requires the lock screen feature.");
776         }
777         if (pattern == null || pattern.size() < MIN_LOCK_PATTERN_SIZE) {
778             throw new IllegalArgumentException("pattern must not be null and at least "
779                     + MIN_LOCK_PATTERN_SIZE + " dots long.");
780         }
781 
782         final byte[] bytePattern = patternToByteArray(pattern);
783         final int currentQuality = getKeyguardStoredPasswordQuality(userId);
784         setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_SOMETHING, userId);
785         try {
786             getLockSettings().setLockCredential(bytePattern, CREDENTIAL_TYPE_PATTERN, savedPattern,
787                     PASSWORD_QUALITY_SOMETHING, userId, allowUntrustedChange);
788         } catch (Exception e) {
789             Log.e(TAG, "Couldn't save lock pattern", e);
790             setKeyguardStoredPasswordQuality(currentQuality, userId);
791             return false;
792         }
793         // Update the device encryption password.
794         if (userId == UserHandle.USER_SYSTEM
795                 && LockPatternUtils.isDeviceEncryptionEnabled()) {
796             if (!shouldEncryptWithCredentials(true)) {
797                 clearEncryptionPassword();
798             } else {
799                 updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, bytePattern);
800             }
801         }
802 
803         reportPatternWasChosen(userId);
804         onAfterChangingPassword(userId);
805         return true;
806     }
807 
updateCryptoUserInfo(int userId)808     private void updateCryptoUserInfo(int userId) {
809         if (userId != UserHandle.USER_SYSTEM) {
810             return;
811         }
812 
813         final String ownerInfo = isOwnerInfoEnabled(userId) ? getOwnerInfo(userId) : "";
814 
815         IBinder service = ServiceManager.getService("mount");
816         if (service == null) {
817             Log.e(TAG, "Could not find the mount service to update the user info");
818             return;
819         }
820 
821         IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
822         try {
823             Log.d(TAG, "Setting owner info");
824             storageManager.setField(StorageManager.OWNER_INFO_KEY, ownerInfo);
825         } catch (RemoteException e) {
826             Log.e(TAG, "Error changing user info", e);
827         }
828     }
829 
830     @UnsupportedAppUsage
setOwnerInfo(String info, int userId)831     public void setOwnerInfo(String info, int userId) {
832         setString(LOCK_SCREEN_OWNER_INFO, info, userId);
833         updateCryptoUserInfo(userId);
834     }
835 
836     @UnsupportedAppUsage
setOwnerInfoEnabled(boolean enabled, int userId)837     public void setOwnerInfoEnabled(boolean enabled, int userId) {
838         setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled, userId);
839         updateCryptoUserInfo(userId);
840     }
841 
842     @UnsupportedAppUsage
getOwnerInfo(int userId)843     public String getOwnerInfo(int userId) {
844         return getString(LOCK_SCREEN_OWNER_INFO, userId);
845     }
846 
isOwnerInfoEnabled(int userId)847     public boolean isOwnerInfoEnabled(int userId) {
848         return getBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, false, userId);
849     }
850 
851     /**
852      * Sets the device owner information. If the information is {@code null} or empty then the
853      * device owner info is cleared.
854      *
855      * @param info Device owner information which will be displayed instead of the user
856      * owner info.
857      */
setDeviceOwnerInfo(String info)858     public void setDeviceOwnerInfo(String info) {
859         if (info != null && info.isEmpty()) {
860             info = null;
861         }
862 
863         setString(LOCK_SCREEN_DEVICE_OWNER_INFO, info, UserHandle.USER_SYSTEM);
864     }
865 
getDeviceOwnerInfo()866     public String getDeviceOwnerInfo() {
867         return getString(LOCK_SCREEN_DEVICE_OWNER_INFO, UserHandle.USER_SYSTEM);
868     }
869 
isDeviceOwnerInfoEnabled()870     public boolean isDeviceOwnerInfoEnabled() {
871         return getDeviceOwnerInfo() != null;
872     }
873 
874     /** Update the encryption password if it is enabled **/
updateEncryptionPassword(final int type, final byte[] password)875     private void updateEncryptionPassword(final int type, final byte[] password) {
876         if (!hasSecureLockScreen()) {
877             throw new UnsupportedOperationException(
878                     "This operation requires the lock screen feature.");
879         }
880         if (!isDeviceEncryptionEnabled()) {
881             return;
882         }
883         final IBinder service = ServiceManager.getService("mount");
884         if (service == null) {
885             Log.e(TAG, "Could not find the mount service to update the encryption password");
886             return;
887         }
888 
889         // TODO(b/120484642): This is a location where we still use a String for vold
890         String passwordString = password != null ? new String(password) : null;
891         new AsyncTask<Void, Void, Void>() {
892             @Override
893             protected Void doInBackground(Void... dummy) {
894                 IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
895                 try {
896                     storageManager.changeEncryptionPassword(type, passwordString);
897                 } catch (RemoteException e) {
898                     Log.e(TAG, "Error changing encryption password", e);
899                 }
900                 return null;
901             }
902         }.execute();
903     }
904 
905     /**
906      * Save a lock password.  Does not ensure that the password is as good
907      * as the requested mode, but will adjust the mode to be as good as the
908      * password.
909      * @param password The password to save
910      * @param savedPassword The previously saved lock password, or null if none
911      * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality(
912      * android.content.ComponentName)}
913      * @param userHandle The userId of the user to change the password for
914      *
915      * @return whether this was successful or not.
916      *
917      * @deprecated Pass password as a byte array
918      */
919     @Deprecated
saveLockPassword(String password, String savedPassword, int requestedQuality, int userHandle)920     public boolean saveLockPassword(String password, String savedPassword, int requestedQuality,
921             int userHandle) {
922         byte[] passwordBytes = password != null ? password.getBytes() : null;
923         byte[] savedPasswordBytes = savedPassword != null ? savedPassword.getBytes() : null;
924         return saveLockPassword(passwordBytes, savedPasswordBytes, requestedQuality, userHandle);
925     }
926 
927     /**
928      * Save a lock password.  Does not ensure that the password is as good
929      * as the requested mode, but will adjust the mode to be as good as the
930      * password.
931      * @param password The password to save
932      * @param savedPassword The previously saved lock password, or null if none
933      * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality(
934      * android.content.ComponentName)}
935      * @param userHandle The userId of the user to change the password for
936      *
937      * @return whether this was successful or not.
938      */
saveLockPassword(byte[] password, byte[] savedPassword, int requestedQuality, int userHandle)939     public boolean saveLockPassword(byte[] password, byte[] savedPassword, int requestedQuality,
940             int userHandle) {
941         return saveLockPassword(password, savedPassword, requestedQuality,
942                 userHandle, false);
943     }
944 
945     /**
946      * Save a lock password.  Does not ensure that the password is as good
947      * as the requested mode, but will adjust the mode to be as good as the
948      * password.
949      * @param password The password to save
950      * @param savedPassword The previously saved lock password, or null if none
951      * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality(
952      * android.content.ComponentName)}
953      * @param userHandle The userId of the user to change the password for
954      * @param allowUntrustedChange whether we want to allow saving a new password if the existing
955      * password being provided is incorrect.
956      *
957      * @return whether this method saved the new password successfully or not. This flow will fail
958      * and return false if the given credential is wrong and allowUntrustedChange is false.
959      */
saveLockPassword(byte[] password, byte[] savedPassword, int requestedQuality, int userHandle, boolean allowUntrustedChange)960     public boolean saveLockPassword(byte[] password, byte[] savedPassword,
961             int requestedQuality, int userHandle, boolean allowUntrustedChange) {
962         if (!hasSecureLockScreen()) {
963             throw new UnsupportedOperationException(
964                     "This operation requires the lock screen feature.");
965         }
966         if (password == null || password.length < MIN_LOCK_PASSWORD_SIZE) {
967             throw new IllegalArgumentException("password must not be null and at least "
968                     + "of length " + MIN_LOCK_PASSWORD_SIZE);
969         }
970 
971         if (requestedQuality < PASSWORD_QUALITY_NUMERIC) {
972             throw new IllegalArgumentException("quality must be at least NUMERIC, but was "
973                     + requestedQuality);
974         }
975 
976         final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
977         final int passwordQuality = PasswordMetrics.computeForPassword(password).quality;
978         final int newKeyguardQuality =
979                 computeKeyguardQuality(CREDENTIAL_TYPE_PASSWORD, requestedQuality, passwordQuality);
980         setKeyguardStoredPasswordQuality(newKeyguardQuality, userHandle);
981         try {
982             getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD, savedPassword,
983                     requestedQuality, userHandle, allowUntrustedChange);
984         } catch (Exception e) {
985             Log.e(TAG, "Unable to save lock password", e);
986             setKeyguardStoredPasswordQuality(currentQuality, userHandle);
987             return false;
988         }
989 
990         updateEncryptionPasswordIfNeeded(password, passwordQuality, userHandle);
991         updatePasswordHistory(password, userHandle);
992         onAfterChangingPassword(userHandle);
993         return true;
994     }
995 
996     /**
997      * Compute keyguard credential quality to store in PASSWORD_TYPE_KEY by computing max between
998      * them so that digit-only password is distinguished from PIN.
999      *
1000      * TODO: remove this method and make CREDENTIAL_TYPE distinguish between PIN and password, so
1001      * that this quality is no longer needs to be persisted.
1002      */
computeKeyguardQuality( @redentialType int credentialType, int requestedQuality, int passwordQuality)1003     private int computeKeyguardQuality(
1004             @CredentialType int credentialType, int requestedQuality, int passwordQuality) {
1005         return credentialType == CREDENTIAL_TYPE_PASSWORD
1006                 ? Math.max(passwordQuality, requestedQuality) : passwordQuality;
1007     }
1008 
1009     /**
1010      * Update device encryption password if calling user is USER_SYSTEM and device supports
1011      * encryption.
1012      */
updateEncryptionPasswordIfNeeded(byte[] password, int quality, int userHandle)1013     private void updateEncryptionPasswordIfNeeded(byte[] password, int quality, int userHandle) {
1014         // Update the device encryption password.
1015         if (userHandle == UserHandle.USER_SYSTEM
1016                 && LockPatternUtils.isDeviceEncryptionEnabled()) {
1017             if (!shouldEncryptWithCredentials(true)) {
1018                 clearEncryptionPassword();
1019             } else {
1020                 boolean numeric = quality == PASSWORD_QUALITY_NUMERIC;
1021                 boolean numericComplex = quality == PASSWORD_QUALITY_NUMERIC_COMPLEX;
1022                 int type = numeric || numericComplex ? StorageManager.CRYPT_TYPE_PIN
1023                         : StorageManager.CRYPT_TYPE_PASSWORD;
1024                 updateEncryptionPassword(type, password);
1025             }
1026         }
1027     }
1028 
1029     /**
1030      * Store the hash of the *current* password in the password history list, if device policy
1031      * enforces password history requirement.
1032      */
updatePasswordHistory(byte[] password, int userHandle)1033     private void updatePasswordHistory(byte[] password, int userHandle) {
1034         if (password == null || password.length == 0) {
1035             Log.e(TAG, "checkPasswordHistory: empty password");
1036             return;
1037         }
1038         // Add the password to the password history. We assume all
1039         // password hashes have the same length for simplicity of implementation.
1040         String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
1041         if (passwordHistory == null) {
1042             passwordHistory = "";
1043         }
1044         int passwordHistoryLength = getRequestedPasswordHistoryLength(userHandle);
1045         if (passwordHistoryLength == 0) {
1046             passwordHistory = "";
1047         } else {
1048             final byte[] hashFactor = getPasswordHistoryHashFactor(password, userHandle);
1049             String hash = passwordToHistoryHash(password, hashFactor, userHandle);
1050             if (hash == null) {
1051                 Log.e(TAG, "Compute new style password hash failed, fallback to legacy style");
1052                 hash = legacyPasswordToHash(password, userHandle);
1053             }
1054             if (TextUtils.isEmpty(passwordHistory)) {
1055                 passwordHistory = hash;
1056             } else {
1057                 String[] history = passwordHistory.split(HISTORY_DELIMITER);
1058                 StringJoiner joiner = new StringJoiner(HISTORY_DELIMITER);
1059                 joiner.add(hash);
1060                 for (int i = 0; i < passwordHistoryLength - 1 && i < history.length; i++) {
1061                     joiner.add(history[i]);
1062                 }
1063                 passwordHistory = joiner.toString();
1064             }
1065         }
1066         setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
1067     }
1068 
1069     /**
1070      * Determine if the device supports encryption, even if it's set to default. This
1071      * differs from isDeviceEncrypted() in that it returns true even if the device is
1072      * encrypted with the default password.
1073      * @return true if device encryption is enabled
1074      */
1075     @UnsupportedAppUsage
isDeviceEncryptionEnabled()1076     public static boolean isDeviceEncryptionEnabled() {
1077         return StorageManager.isEncrypted();
1078     }
1079 
1080     /**
1081      * Determine if the device is file encrypted
1082      * @return true if device is file encrypted
1083      */
isFileEncryptionEnabled()1084     public static boolean isFileEncryptionEnabled() {
1085         return StorageManager.isFileEncryptedNativeOrEmulated();
1086     }
1087 
1088     /**
1089      * Clears the encryption password.
1090      */
clearEncryptionPassword()1091     public void clearEncryptionPassword() {
1092         updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
1093     }
1094 
1095     /**
1096      * Retrieves the quality mode for {@param userHandle}.
1097      * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
1098      *
1099      * @return stored password quality
1100      */
1101     @UnsupportedAppUsage
getKeyguardStoredPasswordQuality(int userHandle)1102     public int getKeyguardStoredPasswordQuality(int userHandle) {
1103         return (int) getLong(PASSWORD_TYPE_KEY, PASSWORD_QUALITY_UNSPECIFIED, userHandle);
1104     }
1105 
setKeyguardStoredPasswordQuality(int quality, int userHandle)1106     private void setKeyguardStoredPasswordQuality(int quality, int userHandle) {
1107         setLong(PASSWORD_TYPE_KEY, quality, userHandle);
1108     }
1109 
1110     /**
1111      * Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op
1112      * for user handles that do not belong to a managed profile.
1113      *
1114      * @param userHandle Managed profile user id
1115      * @param enabled True if separate challenge is enabled
1116      * @param managedUserPassword Managed profile previous password. Null when {@param enabled} is
1117      *            true
1118      */
setSeparateProfileChallengeEnabled(int userHandle, boolean enabled, byte[] managedUserPassword)1119     public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled,
1120             byte[] managedUserPassword) {
1121         if (!isManagedProfile(userHandle)) {
1122             return;
1123         }
1124         try {
1125             getLockSettings().setSeparateProfileChallengeEnabled(userHandle, enabled,
1126                     managedUserPassword);
1127             onAfterChangingPassword(userHandle);
1128         } catch (RemoteException e) {
1129             Log.e(TAG, "Couldn't update work profile challenge enabled");
1130         }
1131     }
1132 
1133     /**
1134      * Returns true if {@param userHandle} is a managed profile with separate challenge.
1135      */
isSeparateProfileChallengeEnabled(int userHandle)1136     public boolean isSeparateProfileChallengeEnabled(int userHandle) {
1137         return isManagedProfile(userHandle) && hasSeparateChallenge(userHandle);
1138     }
1139 
1140     /**
1141      * Returns true if {@param userHandle} is a managed profile with unified challenge.
1142      */
isManagedProfileWithUnifiedChallenge(int userHandle)1143     public boolean isManagedProfileWithUnifiedChallenge(int userHandle) {
1144         return isManagedProfile(userHandle) && !hasSeparateChallenge(userHandle);
1145     }
1146 
1147     /**
1148      * Retrieves whether the current DPM allows use of the Profile Challenge.
1149      */
isSeparateProfileChallengeAllowed(int userHandle)1150     public boolean isSeparateProfileChallengeAllowed(int userHandle) {
1151         return isManagedProfile(userHandle)
1152                 && getDevicePolicyManager().isSeparateProfileChallengeAllowed(userHandle);
1153     }
1154 
1155     /**
1156      * Retrieves whether the current profile and device locks can be unified.
1157      * @param userHandle profile user handle.
1158      */
isSeparateProfileChallengeAllowedToUnify(int userHandle)1159     public boolean isSeparateProfileChallengeAllowedToUnify(int userHandle) {
1160         return getDevicePolicyManager().isProfileActivePasswordSufficientForParent(userHandle)
1161                 && !getUserManager().hasUserRestriction(
1162                         UserManager.DISALLOW_UNIFIED_PASSWORD, UserHandle.of(userHandle));
1163     }
1164 
hasSeparateChallenge(int userHandle)1165     private boolean hasSeparateChallenge(int userHandle) {
1166         try {
1167             return getLockSettings().getSeparateProfileChallengeEnabled(userHandle);
1168         } catch (RemoteException e) {
1169             Log.e(TAG, "Couldn't get separate profile challenge enabled");
1170             // Default value is false
1171             return false;
1172         }
1173     }
1174 
isManagedProfile(int userHandle)1175     private boolean isManagedProfile(int userHandle) {
1176         final UserInfo info = getUserManager().getUserInfo(userHandle);
1177         return info != null && info.isManagedProfile();
1178     }
1179 
1180     /**
1181      * Deserialize a pattern.
1182      * @param string The pattern serialized with {@link #patternToString}
1183      * @return The pattern.
1184      * @deprecated Pass patterns as byte[] and use byteArrayToPattern
1185      */
1186     @Deprecated
stringToPattern(String string)1187     public static List<LockPatternView.Cell> stringToPattern(String string) {
1188         if (string == null) {
1189             return null;
1190         }
1191         return byteArrayToPattern(string.getBytes());
1192     }
1193 
1194     /**
1195      * Deserialize a pattern.
1196      * @param  bytes The pattern serialized with {@link #patternToByteArray}
1197      * @return The pattern.
1198      */
byteArrayToPattern(byte[] bytes)1199     public static List<LockPatternView.Cell> byteArrayToPattern(byte[] bytes) {
1200         if (bytes == null) {
1201             return null;
1202         }
1203 
1204         List<LockPatternView.Cell> result = Lists.newArrayList();
1205 
1206         for (int i = 0; i < bytes.length; i++) {
1207             byte b = (byte) (bytes[i] - '1');
1208             result.add(LockPatternView.Cell.of(b / 3, b % 3));
1209         }
1210         return result;
1211     }
1212 
1213     /**
1214      * Serialize a pattern.
1215      * @param pattern The pattern.
1216      * @return The pattern in string form.
1217      * @deprecated Use patternToByteArray instead.
1218      */
1219     @UnsupportedAppUsage
1220     @Deprecated
patternToString(List<LockPatternView.Cell> pattern)1221     public static String patternToString(List<LockPatternView.Cell> pattern) {
1222         return new String(patternToByteArray(pattern));
1223     }
1224 
1225 
1226     /**
1227      * Serialize a pattern.
1228      * @param pattern The pattern.
1229      * @return The pattern in byte array form.
1230      */
patternToByteArray(List<LockPatternView.Cell> pattern)1231     public static byte[] patternToByteArray(List<LockPatternView.Cell> pattern) {
1232         if (pattern == null) {
1233             return new byte[0];
1234         }
1235         final int patternSize = pattern.size();
1236 
1237         byte[] res = new byte[patternSize];
1238         for (int i = 0; i < patternSize; i++) {
1239             LockPatternView.Cell cell = pattern.get(i);
1240             res[i] = (byte) (cell.getRow() * 3 + cell.getColumn() + '1');
1241         }
1242         return res;
1243     }
1244 
1245     /**
1246      * Transform a pattern byte array to base zero form.
1247      * @param bytes pattern byte array.
1248      * @return The pattern in base zero form.
1249      */
patternByteArrayToBaseZero(byte[] bytes)1250     public static byte[] patternByteArrayToBaseZero(byte[] bytes) {
1251         if (bytes == null) {
1252             return new byte[0];
1253         }
1254         final int patternSize = bytes.length;
1255         byte[] res = new byte[patternSize];
1256         for (int i = 0; i < patternSize; i++) {
1257             res[i] = (byte) (bytes[i] - '1');
1258         }
1259         return res;
1260     }
1261 
1262     /*
1263      * Generate an SHA-1 hash for the pattern. Not the most secure, but it is
1264      * at least a second level of protection. First level is that the file
1265      * is in a location only readable by the system process.
1266      * @param pattern the gesture pattern.
1267      * @return the hash of the pattern in a byte array.
1268      */
1269     @UnsupportedAppUsage
patternToHash(List<LockPatternView.Cell> pattern)1270     public static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
1271         if (pattern == null) {
1272             return null;
1273         }
1274 
1275         final int patternSize = pattern.size();
1276         byte[] res = new byte[patternSize];
1277         for (int i = 0; i < patternSize; i++) {
1278             LockPatternView.Cell cell = pattern.get(i);
1279             res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
1280         }
1281         try {
1282             MessageDigest md = MessageDigest.getInstance("SHA-1");
1283             byte[] hash = md.digest(res);
1284             return hash;
1285         } catch (NoSuchAlgorithmException nsa) {
1286             return res;
1287         }
1288     }
1289 
getSalt(int userId)1290     private String getSalt(int userId) {
1291         long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0, userId);
1292         if (salt == 0) {
1293             try {
1294                 salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
1295                 setLong(LOCK_PASSWORD_SALT_KEY, salt, userId);
1296                 Log.v(TAG, "Initialized lock password salt for user: " + userId);
1297             } catch (NoSuchAlgorithmException e) {
1298                 // Throw an exception rather than storing a password we'll never be able to recover
1299                 throw new IllegalStateException("Couldn't get SecureRandom number", e);
1300             }
1301         }
1302         return Long.toHexString(salt);
1303     }
1304 
1305     /**
1306      * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
1307      * Not the most secure, but it is at least a second level of protection. First level is that
1308      * the file is in a location only readable by the system process.
1309      *
1310      * @param password the gesture pattern.
1311      *
1312      * @return the hash of the pattern in a byte array.
1313      */
legacyPasswordToHash(byte[] password, int userId)1314     public String legacyPasswordToHash(byte[] password, int userId) {
1315         if (password == null || password.length == 0) {
1316             return null;
1317         }
1318 
1319         try {
1320             // Previously the password was passed as a String with the following code:
1321             // byte[] saltedPassword = (password + getSalt(userId)).getBytes();
1322             // The code below creates the identical digest preimage using byte arrays:
1323             byte[] salt = getSalt(userId).getBytes();
1324             byte[] saltedPassword = Arrays.copyOf(password, password.length + salt.length);
1325             System.arraycopy(salt, 0, saltedPassword, password.length, salt.length);
1326             byte[] sha1 = MessageDigest.getInstance("SHA-1").digest(saltedPassword);
1327             byte[] md5 = MessageDigest.getInstance("MD5").digest(saltedPassword);
1328 
1329             byte[] combined = new byte[sha1.length + md5.length];
1330             System.arraycopy(sha1, 0, combined, 0, sha1.length);
1331             System.arraycopy(md5, 0, combined, sha1.length, md5.length);
1332 
1333             final char[] hexEncoded = HexEncoding.encode(combined);
1334             Arrays.fill(saltedPassword, (byte) 0);
1335             return new String(hexEncoded);
1336         } catch (NoSuchAlgorithmException e) {
1337             throw new AssertionError("Missing digest algorithm: ", e);
1338         }
1339     }
1340 
1341     /**
1342      * Hash the password for password history check purpose.
1343      */
passwordToHistoryHash(byte[] passwordToHash, byte[] hashFactor, int userId)1344     private String passwordToHistoryHash(byte[] passwordToHash, byte[] hashFactor, int userId) {
1345         if (passwordToHash == null || passwordToHash.length == 0 || hashFactor == null) {
1346             return null;
1347         }
1348         try {
1349             MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
1350             sha256.update(hashFactor);
1351             byte[] salt = getSalt(userId).getBytes();
1352             byte[] saltedPassword = Arrays.copyOf(passwordToHash, passwordToHash.length
1353                     + salt.length);
1354             System.arraycopy(salt, 0, saltedPassword, passwordToHash.length, salt.length);
1355             sha256.update(saltedPassword);
1356             Arrays.fill(saltedPassword, (byte) 0);
1357             return new String(HexEncoding.encode(sha256.digest()));
1358         } catch (NoSuchAlgorithmException e) {
1359             throw new AssertionError("Missing digest algorithm: ", e);
1360         }
1361     }
1362 
1363     /**
1364      * @param userId the user for which to report the value
1365      * @return Whether the lock screen is secured.
1366      */
1367     @UnsupportedAppUsage
isSecure(int userId)1368     public boolean isSecure(int userId) {
1369         int mode = getKeyguardStoredPasswordQuality(userId);
1370         return isLockPatternEnabled(mode, userId) || isLockPasswordEnabled(mode, userId);
1371     }
1372 
1373     @UnsupportedAppUsage
isLockPasswordEnabled(int userId)1374     public boolean isLockPasswordEnabled(int userId) {
1375         return isLockPasswordEnabled(getKeyguardStoredPasswordQuality(userId), userId);
1376     }
1377 
isLockPasswordEnabled(int mode, int userId)1378     private boolean isLockPasswordEnabled(int mode, int userId) {
1379         final boolean passwordEnabled = mode == PASSWORD_QUALITY_ALPHABETIC
1380                 || mode == PASSWORD_QUALITY_NUMERIC
1381                 || mode == PASSWORD_QUALITY_NUMERIC_COMPLEX
1382                 || mode == PASSWORD_QUALITY_ALPHANUMERIC
1383                 || mode == PASSWORD_QUALITY_COMPLEX
1384                 || mode == PASSWORD_QUALITY_MANAGED;
1385         return passwordEnabled && savedPasswordExists(userId);
1386     }
1387 
1388     /**
1389      * @return Whether the lock pattern is enabled
1390      */
1391     @UnsupportedAppUsage
isLockPatternEnabled(int userId)1392     public boolean isLockPatternEnabled(int userId) {
1393         return isLockPatternEnabled(getKeyguardStoredPasswordQuality(userId), userId);
1394     }
1395 
1396     @Deprecated
isLegacyLockPatternEnabled(int userId)1397     public boolean isLegacyLockPatternEnabled(int userId) {
1398         // Note: this value should default to {@code true} to avoid any reset that might result.
1399         // We must use a special key to read this value, since it will by default return the value
1400         // based on the new logic.
1401         return getBoolean(LEGACY_LOCK_PATTERN_ENABLED, true, userId);
1402     }
1403 
1404     @Deprecated
setLegacyLockPatternEnabled(int userId)1405     public void setLegacyLockPatternEnabled(int userId) {
1406         setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, true, userId);
1407     }
1408 
isLockPatternEnabled(int mode, int userId)1409     private boolean isLockPatternEnabled(int mode, int userId) {
1410         return mode == PASSWORD_QUALITY_SOMETHING && savedPatternExists(userId);
1411     }
1412 
1413     /**
1414      * @return Whether the visible pattern is enabled.
1415      */
1416     @UnsupportedAppUsage
isVisiblePatternEnabled(int userId)1417     public boolean isVisiblePatternEnabled(int userId) {
1418         return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false, userId);
1419     }
1420 
1421     /**
1422      * Set whether the visible pattern is enabled.
1423      */
setVisiblePatternEnabled(boolean enabled, int userId)1424     public void setVisiblePatternEnabled(boolean enabled, int userId) {
1425         setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled, userId);
1426 
1427         // Update for crypto if owner
1428         if (userId != UserHandle.USER_SYSTEM) {
1429             return;
1430         }
1431 
1432         IBinder service = ServiceManager.getService("mount");
1433         if (service == null) {
1434             Log.e(TAG, "Could not find the mount service to update the user info");
1435             return;
1436         }
1437 
1438         IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
1439         try {
1440             storageManager.setField(StorageManager.PATTERN_VISIBLE_KEY, enabled ? "1" : "0");
1441         } catch (RemoteException e) {
1442             Log.e(TAG, "Error changing pattern visible state", e);
1443         }
1444     }
1445 
isVisiblePatternEverChosen(int userId)1446     public boolean isVisiblePatternEverChosen(int userId) {
1447         return getString(Settings.Secure.LOCK_PATTERN_VISIBLE, userId) != null;
1448     }
1449 
1450     /**
1451      * Set whether the visible password is enabled for cryptkeeper screen.
1452      */
setVisiblePasswordEnabled(boolean enabled, int userId)1453     public void setVisiblePasswordEnabled(boolean enabled, int userId) {
1454         // Update for crypto if owner
1455         if (userId != UserHandle.USER_SYSTEM) {
1456             return;
1457         }
1458 
1459         IBinder service = ServiceManager.getService("mount");
1460         if (service == null) {
1461             Log.e(TAG, "Could not find the mount service to update the user info");
1462             return;
1463         }
1464 
1465         IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
1466         try {
1467             storageManager.setField(StorageManager.PASSWORD_VISIBLE_KEY, enabled ? "1" : "0");
1468         } catch (RemoteException e) {
1469             Log.e(TAG, "Error changing password visible state", e);
1470         }
1471     }
1472 
1473     /**
1474      * @return Whether tactile feedback for the pattern is enabled.
1475      */
1476     @UnsupportedAppUsage
isTactileFeedbackEnabled()1477     public boolean isTactileFeedbackEnabled() {
1478         return Settings.System.getIntForUser(mContentResolver,
1479                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
1480     }
1481 
1482     /**
1483      * Set and store the lockout deadline, meaning the user can't attempt his/her unlock
1484      * pattern until the deadline has passed.
1485      * @return the chosen deadline.
1486      */
1487     @UnsupportedAppUsage
setLockoutAttemptDeadline(int userId, int timeoutMs)1488     public long setLockoutAttemptDeadline(int userId, int timeoutMs) {
1489         final long deadline = SystemClock.elapsedRealtime() + timeoutMs;
1490         if (userId == USER_FRP) {
1491             // For secure password storage (that is required for FRP), the underlying storage also
1492             // enforces the deadline. Since we cannot store settings for the FRP user, don't.
1493             return deadline;
1494         }
1495         mLockoutDeadlines.put(userId, deadline);
1496         return deadline;
1497     }
1498 
1499     /**
1500      * @return The elapsed time in millis in the future when the user is allowed to
1501      *   attempt to enter his/her lock pattern, or 0 if the user is welcome to
1502      *   enter a pattern.
1503      */
getLockoutAttemptDeadline(int userId)1504     public long getLockoutAttemptDeadline(int userId) {
1505         final long deadline = mLockoutDeadlines.get(userId, 0L);
1506         final long now = SystemClock.elapsedRealtime();
1507         if (deadline < now && deadline != 0) {
1508             // timeout expired
1509             mLockoutDeadlines.put(userId, 0);
1510             return 0L;
1511         }
1512         return deadline;
1513     }
1514 
getBoolean(String secureSettingKey, boolean defaultValue, int userId)1515     private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) {
1516         try {
1517             return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId);
1518         } catch (RemoteException re) {
1519             return defaultValue;
1520         }
1521     }
1522 
setBoolean(String secureSettingKey, boolean enabled, int userId)1523     private void setBoolean(String secureSettingKey, boolean enabled, int userId) {
1524         try {
1525             getLockSettings().setBoolean(secureSettingKey, enabled, userId);
1526         } catch (RemoteException re) {
1527             // What can we do?
1528             Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re);
1529         }
1530     }
1531 
getLong(String secureSettingKey, long defaultValue, int userHandle)1532     private long getLong(String secureSettingKey, long defaultValue, int userHandle) {
1533         try {
1534             return getLockSettings().getLong(secureSettingKey, defaultValue, userHandle);
1535         } catch (RemoteException re) {
1536             return defaultValue;
1537         }
1538     }
1539 
1540     @UnsupportedAppUsage
setLong(String secureSettingKey, long value, int userHandle)1541     private void setLong(String secureSettingKey, long value, int userHandle) {
1542         try {
1543             getLockSettings().setLong(secureSettingKey, value, userHandle);
1544         } catch (RemoteException re) {
1545             // What can we do?
1546             Log.e(TAG, "Couldn't write long " + secureSettingKey + re);
1547         }
1548     }
1549 
1550     @UnsupportedAppUsage
getString(String secureSettingKey, int userHandle)1551     private String getString(String secureSettingKey, int userHandle) {
1552         try {
1553             return getLockSettings().getString(secureSettingKey, null, userHandle);
1554         } catch (RemoteException re) {
1555             return null;
1556         }
1557     }
1558 
1559     @UnsupportedAppUsage
setString(String secureSettingKey, String value, int userHandle)1560     private void setString(String secureSettingKey, String value, int userHandle) {
1561         try {
1562             getLockSettings().setString(secureSettingKey, value, userHandle);
1563         } catch (RemoteException re) {
1564             // What can we do?
1565             Log.e(TAG, "Couldn't write string " + secureSettingKey + re);
1566         }
1567     }
1568 
setPowerButtonInstantlyLocks(boolean enabled, int userId)1569     public void setPowerButtonInstantlyLocks(boolean enabled, int userId) {
1570         setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled, userId);
1571     }
1572 
1573     @UnsupportedAppUsage
getPowerButtonInstantlyLocks(int userId)1574     public boolean getPowerButtonInstantlyLocks(int userId) {
1575         return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true, userId);
1576     }
1577 
isPowerButtonInstantlyLocksEverChosen(int userId)1578     public boolean isPowerButtonInstantlyLocksEverChosen(int userId) {
1579         return getString(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, userId) != null;
1580     }
1581 
setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId)1582     public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) {
1583         StringBuilder sb = new StringBuilder();
1584         for (ComponentName cn : activeTrustAgents) {
1585             if (sb.length() > 0) {
1586                 sb.append(',');
1587             }
1588             sb.append(cn.flattenToShortString());
1589         }
1590         setString(ENABLED_TRUST_AGENTS, sb.toString(), userId);
1591         getTrustManager().reportEnabledTrustAgentsChanged(userId);
1592     }
1593 
getEnabledTrustAgents(int userId)1594     public List<ComponentName> getEnabledTrustAgents(int userId) {
1595         String serialized = getString(ENABLED_TRUST_AGENTS, userId);
1596         if (TextUtils.isEmpty(serialized)) {
1597             return null;
1598         }
1599         String[] split = serialized.split(",");
1600         ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length);
1601         for (String s : split) {
1602             if (!TextUtils.isEmpty(s)) {
1603                 activeTrustAgents.add(ComponentName.unflattenFromString(s));
1604             }
1605         }
1606         return activeTrustAgents;
1607     }
1608 
1609     /**
1610      * Disable trust until credentials have been entered for user {@param userId}.
1611      *
1612      * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
1613      *
1614      * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
1615      */
requireCredentialEntry(int userId)1616     public void requireCredentialEntry(int userId) {
1617         requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
1618     }
1619 
1620     /**
1621      * Requests strong authentication for user {@param userId}.
1622      *
1623      * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
1624      *
1625      * @param strongAuthReason a combination of {@link StrongAuthTracker.StrongAuthFlags} indicating
1626      *                         the reason for and the strength of the requested authentication.
1627      * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
1628      */
requireStrongAuth(@trongAuthTracker.StrongAuthFlags int strongAuthReason, int userId)1629     public void requireStrongAuth(@StrongAuthTracker.StrongAuthFlags int strongAuthReason,
1630             int userId) {
1631         try {
1632             getLockSettings().requireStrongAuth(strongAuthReason, userId);
1633         } catch (RemoteException e) {
1634             Log.e(TAG, "Error while requesting strong auth: " + e);
1635         }
1636     }
1637 
onAfterChangingPassword(int userHandle)1638     private void onAfterChangingPassword(int userHandle) {
1639         getTrustManager().reportEnabledTrustAgentsChanged(userHandle);
1640     }
1641 
isCredentialRequiredToDecrypt(boolean defaultValue)1642     public boolean isCredentialRequiredToDecrypt(boolean defaultValue) {
1643         final int value = Settings.Global.getInt(mContentResolver,
1644                 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, -1);
1645         return value == -1 ? defaultValue : (value != 0);
1646     }
1647 
setCredentialRequiredToDecrypt(boolean required)1648     public void setCredentialRequiredToDecrypt(boolean required) {
1649         if (!(getUserManager().isSystemUser() || getUserManager().isPrimaryUser())) {
1650             throw new IllegalStateException(
1651                     "Only the system or primary user may call setCredentialRequiredForDecrypt()");
1652         }
1653 
1654         if (isDeviceEncryptionEnabled()){
1655             Settings.Global.putInt(mContext.getContentResolver(),
1656                Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, required ? 1 : 0);
1657         }
1658     }
1659 
isDoNotAskCredentialsOnBootSet()1660     private boolean isDoNotAskCredentialsOnBootSet() {
1661         return getDevicePolicyManager().getDoNotAskCredentialsOnBoot();
1662     }
1663 
shouldEncryptWithCredentials(boolean defaultValue)1664     private boolean shouldEncryptWithCredentials(boolean defaultValue) {
1665         return isCredentialRequiredToDecrypt(defaultValue) && !isDoNotAskCredentialsOnBootSet();
1666     }
1667 
throwIfCalledOnMainThread()1668     private void throwIfCalledOnMainThread() {
1669         if (Looper.getMainLooper().isCurrentThread()) {
1670             throw new IllegalStateException("should not be called from the main thread.");
1671         }
1672     }
1673 
registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker)1674     public void registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
1675         try {
1676             getLockSettings().registerStrongAuthTracker(strongAuthTracker.mStub);
1677         } catch (RemoteException e) {
1678             throw new RuntimeException("Could not register StrongAuthTracker");
1679         }
1680     }
1681 
unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker)1682     public void unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
1683         try {
1684             getLockSettings().unregisterStrongAuthTracker(strongAuthTracker.mStub);
1685         } catch (RemoteException e) {
1686             Log.e(TAG, "Could not unregister StrongAuthTracker", e);
1687         }
1688     }
1689 
1690     /**
1691      * @see StrongAuthTracker#getStrongAuthForUser
1692      */
getStrongAuthForUser(int userId)1693     public int getStrongAuthForUser(int userId) {
1694         try {
1695             return getLockSettings().getStrongAuthForUser(userId);
1696         } catch (RemoteException e) {
1697             Log.e(TAG, "Could not get StrongAuth", e);
1698             return StrongAuthTracker.getDefaultFlags(mContext);
1699         }
1700     }
1701 
1702     /**
1703      * @see StrongAuthTracker#isTrustAllowedForUser
1704      */
isTrustAllowedForUser(int userId)1705     public boolean isTrustAllowedForUser(int userId) {
1706         return getStrongAuthForUser(userId) == StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
1707     }
1708 
1709     /**
1710      * @see StrongAuthTracker#isBiometricAllowedForUser(int)
1711      */
isBiometricAllowedForUser(int userId)1712     public boolean isBiometricAllowedForUser(int userId) {
1713         return (getStrongAuthForUser(userId) & ~StrongAuthTracker.ALLOWING_BIOMETRIC) == 0;
1714     }
1715 
isUserInLockdown(int userId)1716     public boolean isUserInLockdown(int userId) {
1717         return getStrongAuthForUser(userId)
1718                 == StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
1719     }
1720 
wrapCallback( final CheckCredentialProgressCallback callback)1721     private ICheckCredentialProgressCallback wrapCallback(
1722             final CheckCredentialProgressCallback callback) {
1723         if (callback == null) {
1724             return null;
1725         } else {
1726             if (mHandler == null) {
1727                 throw new IllegalStateException("Must construct LockPatternUtils on a looper thread"
1728                         + " to use progress callbacks.");
1729             }
1730             return new ICheckCredentialProgressCallback.Stub() {
1731 
1732                 @Override
1733                 public void onCredentialVerified() throws RemoteException {
1734                     mHandler.post(callback::onEarlyMatched);
1735                 }
1736             };
1737         }
1738     }
1739 
1740     private LockSettingsInternal getLockSettingsInternal() {
1741         LockSettingsInternal service = LocalServices.getService(LockSettingsInternal.class);
1742         if (service == null) {
1743             throw new SecurityException("Only available to system server itself");
1744         }
1745         return service;
1746     }
1747     /**
1748      * Create an escrow token for the current user, which can later be used to unlock FBE
1749      * or change user password.
1750      *
1751      * After adding, if the user currently has lockscreen password, he will need to perform a
1752      * confirm credential operation in order to activate the token for future use. If the user
1753      * has no secure lockscreen, then the token is activated immediately.
1754      *
1755      * <p>This method is only available to code running in the system server process itself.
1756      *
1757      * @return a unique 64-bit token handle which is needed to refer to this token later.
1758      */
1759     public long addEscrowToken(byte[] token, int userId,
1760             @Nullable EscrowTokenStateChangeCallback callback) {
1761         return getLockSettingsInternal().addEscrowToken(token, userId, callback);
1762     }
1763 
1764     /**
1765      * Callback interface to notify when an added escrow token has been activated.
1766      */
1767     public interface EscrowTokenStateChangeCallback {
1768         /**
1769          * The method to be called when the token is activated.
1770          * @param handle 64 bit handle corresponding to the escrow token
1771          * @param userid user for whom the escrow token has been added
1772          */
1773         void onEscrowTokenActivated(long handle, int userid);
1774     }
1775 
1776     /**
1777      * Remove an escrow token.
1778      *
1779      * <p>This method is only available to code running in the system server process itself.
1780      *
1781      * @return true if the given handle refers to a valid token previously returned from
1782      * {@link #addEscrowToken}, whether it's active or not. return false otherwise.
1783      */
1784     public boolean removeEscrowToken(long handle, int userId) {
1785         return getLockSettingsInternal().removeEscrowToken(handle, userId);
1786     }
1787 
1788     /**
1789      * Check if the given escrow token is active or not. Only active token can be used to call
1790      * {@link #setLockCredentialWithToken} and {@link #unlockUserWithToken}
1791      *
1792      * <p>This method is only available to code running in the system server process itself.
1793      */
1794     public boolean isEscrowTokenActive(long handle, int userId) {
1795         return getLockSettingsInternal().isEscrowTokenActive(handle, userId);
1796     }
1797 
1798     /**
1799      * Change a user's lock credential with a pre-configured escrow token.
1800      *
1801      * <p>This method is only available to code running in the system server process itself.
1802      *
1803      * @param credential The new credential to be set
1804      * @param type Credential type: password / pattern / none.
1805      * @param requestedQuality the requested password quality by DevicePolicyManager.
1806      *        See {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
1807      * @param tokenHandle Handle of the escrow token
1808      * @param token Escrow token
1809      * @param userId The user who's lock credential to be changed
1810      * @return {@code true} if the operation is successful.
1811      */
1812     public boolean setLockCredentialWithToken(byte[] credential, int type, int requestedQuality,
1813             long tokenHandle, byte[] token, int userId) {
1814         if (!hasSecureLockScreen()) {
1815             throw new UnsupportedOperationException(
1816                     "This operation requires the lock screen feature.");
1817         }
1818         LockSettingsInternal localService = getLockSettingsInternal();
1819         if (type != CREDENTIAL_TYPE_NONE) {
1820             if (credential == null || credential.length < MIN_LOCK_PASSWORD_SIZE) {
1821                 throw new IllegalArgumentException("password must not be null and at least "
1822                         + "of length " + MIN_LOCK_PASSWORD_SIZE);
1823             }
1824             final int quality = PasswordMetrics.computeForCredential(type, credential).quality;
1825             final int keyguardQuality = computeKeyguardQuality(type, quality, requestedQuality);
1826             if (!localService.setLockCredentialWithToken(credential, type, tokenHandle, token,
1827                     keyguardQuality, userId)) {
1828                 return false;
1829             }
1830             setKeyguardStoredPasswordQuality(quality, userId);
1831 
1832             updateEncryptionPasswordIfNeeded(credential, quality, userId);
1833             updatePasswordHistory(credential, userId);
1834             onAfterChangingPassword(userId);
1835         } else {
1836             if (!(credential == null || credential.length == 0)) {
1837                 throw new IllegalArgumentException("password must be emtpy for NONE type");
1838             }
1839             if (!localService.setLockCredentialWithToken(null, CREDENTIAL_TYPE_NONE, tokenHandle,
1840                     token, PASSWORD_QUALITY_UNSPECIFIED, userId)) {
1841                 return false;
1842             }
1843             setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED, userId);
1844 
1845             if (userId == UserHandle.USER_SYSTEM) {
1846                 // Set the encryption password to default.
1847                 updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
1848                 setCredentialRequiredToDecrypt(false);
1849             }
1850         }
1851         onAfterChangingPassword(userId);
1852         return true;
1853     }
1854 
1855     /**
1856      * Unlock the specified user by an pre-activated escrow token. This should have the same effect
1857      * on device encryption as the user entering his lockscreen credentials for the first time after
1858      * boot, this includes unlocking the user's credential-encrypted storage as well as the keystore
1859      *
1860      * <p>This method is only available to code running in the system server process itself.
1861      *
1862      * @return {@code true} if the supplied token is valid and unlock succeeds,
1863      *         {@code false} otherwise.
1864      */
1865     public boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
1866         return getLockSettingsInternal().unlockUserWithToken(tokenHandle, token, userId);
1867     }
1868 
1869 
1870     /**
1871      * Callback to be notified about progress when checking credentials.
1872      */
1873     public interface CheckCredentialProgressCallback {
1874 
1875         /**
1876          * Called as soon as possible when we know that the credentials match but the user hasn't
1877          * been fully unlocked.
1878          */
1879         void onEarlyMatched();
1880     }
1881 
1882     /**
1883      * Tracks the global strong authentication state.
1884      */
1885     public static class StrongAuthTracker {
1886 
1887         @IntDef(flag = true,
1888                 value = { STRONG_AUTH_NOT_REQUIRED,
1889                         STRONG_AUTH_REQUIRED_AFTER_BOOT,
1890                         STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
1891                         SOME_AUTH_REQUIRED_AFTER_USER_REQUEST,
1892                         STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
1893                         STRONG_AUTH_REQUIRED_AFTER_TIMEOUT,
1894                         STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN})
1895         @Retention(RetentionPolicy.SOURCE)
1896         public @interface StrongAuthFlags {}
1897 
1898         /**
1899          * Strong authentication is not required.
1900          */
1901         public static final int STRONG_AUTH_NOT_REQUIRED = 0x0;
1902 
1903         /**
1904          * Strong authentication is required because the user has not authenticated since boot.
1905          */
1906         public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1;
1907 
1908         /**
1909          * Strong authentication is required because a device admin has requested it.
1910          */
1911         public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2;
1912 
1913         /**
1914          * Some authentication is required because the user has temporarily disabled trust.
1915          */
1916         public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
1917 
1918         /**
1919          * Strong authentication is required because the user has been locked out after too many
1920          * attempts.
1921          */
1922         public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
1923 
1924         /**
1925          * Strong authentication is required because it hasn't been used for a time required by
1926          * a device admin.
1927          */
1928         public static final int STRONG_AUTH_REQUIRED_AFTER_TIMEOUT = 0x10;
1929 
1930         /**
1931          * Strong authentication is required because the user has triggered lockdown.
1932          */
1933         public static final int STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN = 0x20;
1934 
1935         /**
1936          * Strong auth flags that do not prevent biometric methods from being accepted as auth.
1937          * If any other flags are set, biometric authentication is disabled.
1938          */
1939         private static final int ALLOWING_BIOMETRIC = STRONG_AUTH_NOT_REQUIRED
1940                 | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
1941 
1942         private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
1943         private final H mHandler;
1944         private final int mDefaultStrongAuthFlags;
1945 
1946         public StrongAuthTracker(Context context) {
1947             this(context, Looper.myLooper());
1948         }
1949 
1950         /**
1951          * @param looper the looper on whose thread calls to {@link #onStrongAuthRequiredChanged}
1952          *               will be scheduled.
1953          * @param context the current {@link Context}
1954          */
1955         public StrongAuthTracker(Context context, Looper looper) {
1956             mHandler = new H(looper);
1957             mDefaultStrongAuthFlags = getDefaultFlags(context);
1958         }
1959 
1960         public static @StrongAuthFlags int getDefaultFlags(Context context) {
1961             boolean strongAuthRequired = context.getResources().getBoolean(
1962                     com.android.internal.R.bool.config_strongAuthRequiredOnBoot);
1963             return strongAuthRequired ? STRONG_AUTH_REQUIRED_AFTER_BOOT : STRONG_AUTH_NOT_REQUIRED;
1964         }
1965 
1966         /**
1967          * Returns {@link #STRONG_AUTH_NOT_REQUIRED} if strong authentication is not required,
1968          * otherwise returns a combination of {@link StrongAuthFlags} indicating why strong
1969          * authentication is required.
1970          *
1971          * @param userId the user for whom the state is queried.
1972          */
1973         public @StrongAuthFlags int getStrongAuthForUser(int userId) {
1974             return mStrongAuthRequiredForUser.get(userId, mDefaultStrongAuthFlags);
1975         }
1976 
1977         /**
1978          * @return true if unlocking with trust alone is allowed for {@param userId} by the current
1979          * strong authentication requirements.
1980          */
1981         public boolean isTrustAllowedForUser(int userId) {
1982             return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED;
1983         }
1984 
1985         /**
1986          * @return true if unlocking with a biometric method alone is allowed for {@param userId}
1987          * by the current strong authentication requirements.
1988          */
1989         public boolean isBiometricAllowedForUser(int userId) {
1990             return (getStrongAuthForUser(userId) & ~ALLOWING_BIOMETRIC) == 0;
1991         }
1992 
1993         /**
1994          * Called when the strong authentication requirements for {@param userId} changed.
1995          */
1996         public void onStrongAuthRequiredChanged(int userId) {
1997         }
1998 
1999         protected void handleStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
2000                 int userId) {
2001             int oldValue = getStrongAuthForUser(userId);
2002             if (strongAuthFlags != oldValue) {
2003                 if (strongAuthFlags == mDefaultStrongAuthFlags) {
2004                     mStrongAuthRequiredForUser.delete(userId);
2005                 } else {
2006                     mStrongAuthRequiredForUser.put(userId, strongAuthFlags);
2007                 }
2008                 onStrongAuthRequiredChanged(userId);
2009             }
2010         }
2011 
2012 
2013         protected final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() {
2014             @Override
2015             public void onStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
2016                     int userId) {
2017                 mHandler.obtainMessage(H.MSG_ON_STRONG_AUTH_REQUIRED_CHANGED,
2018                         strongAuthFlags, userId).sendToTarget();
2019             }
2020         };
2021 
2022         private class H extends Handler {
2023             static final int MSG_ON_STRONG_AUTH_REQUIRED_CHANGED = 1;
2024 
2025             public H(Looper looper) {
2026                 super(looper);
2027             }
2028 
2029             @Override
2030             public void handleMessage(Message msg) {
2031                 switch (msg.what) {
2032                     case MSG_ON_STRONG_AUTH_REQUIRED_CHANGED:
2033                         handleStrongAuthRequiredChanged(msg.arg1, msg.arg2);
2034                         break;
2035                 }
2036             }
2037         }
2038     }
2039 
2040     public void enableSyntheticPassword() {
2041         setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1L, UserHandle.USER_SYSTEM);
2042     }
2043 
2044     public void disableSyntheticPassword() {
2045         setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0L, UserHandle.USER_SYSTEM);
2046     }
2047 
2048     public boolean isSyntheticPasswordEnabled() {
2049         return getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM) != 0;
2050     }
2051 
2052     /**
2053      * Returns whether the given user has pending escrow tokens
2054      */
2055     public boolean hasPendingEscrowToken(int userId) {
2056         try {
2057             return getLockSettings().hasPendingEscrowToken(userId);
2058         } catch (RemoteException e) {
2059             e.rethrowFromSystemServer();
2060         }
2061         return false;
2062     }
2063 
2064     /**
2065      * Return true if the device supports the lock screen feature, false otherwise.
2066      */
2067     public boolean hasSecureLockScreen() {
2068         if (mHasSecureLockScreen == null) {
2069             mHasSecureLockScreen = Boolean.valueOf(mContext.getPackageManager()
2070                     .hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN));
2071         }
2072         return mHasSecureLockScreen.booleanValue();
2073     }
2074 
2075     public static boolean userOwnsFrpCredential(Context context, UserInfo info) {
2076         return info != null && info.isPrimary() && info.isAdmin() && frpCredentialEnabled(context);
2077     }
2078 
2079     public static boolean frpCredentialEnabled(Context context) {
2080         return FRP_CREDENTIAL_ENABLED && context.getResources().getBoolean(
2081                 com.android.internal.R.bool.config_enableCredentialFactoryResetProtection);
2082     }
2083 
2084     /**
2085      * Converts a CharSequence to a byte array without requiring a toString(), which creates an
2086      * additional copy.
2087      *
2088      * @param chars The CharSequence to convert
2089      * @return A byte array representing the input
2090      */
2091     public static byte[] charSequenceToByteArray(CharSequence chars) {
2092         if (chars == null) {
2093             return null;
2094         }
2095         byte[] bytes = new byte[chars.length()];
2096         for (int i = 0; i < chars.length(); i++) {
2097             bytes[i] = (byte) chars.charAt(i);
2098         }
2099         return bytes;
2100     }
2101 }
2102