1 /*
2  * Copyright (C) 2022 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.settings.biometrics;
18 
19 import static com.android.settings.biometrics.BiometricUtils.GatekeeperCredentialNotMatchException;
20 
21 import android.content.Intent;
22 import android.util.Log;
23 
24 import androidx.annotation.NonNull;
25 import androidx.annotation.Nullable;
26 
27 import com.android.internal.widget.LockPatternUtils;
28 import com.android.internal.widget.VerifyCredentialResponse;
29 import com.android.settings.password.ChooseLockSettingsHelper;
30 
31 /**
32  * Gatekeeper hat related methods
33  */
34 public class GatekeeperPasswordProvider {
35 
36     private static final String TAG = "GatekeeperPasswordProvider";
37 
38     private final LockPatternUtils mLockPatternUtils;
39 
GatekeeperPasswordProvider(LockPatternUtils lockPatternUtils)40     public GatekeeperPasswordProvider(LockPatternUtils lockPatternUtils) {
41         mLockPatternUtils = lockPatternUtils;
42     }
43 
44     /**
45      * Given the result from confirming or choosing a credential, request Gatekeeper to generate
46      * a HardwareAuthToken with the Gatekeeper Password together with a biometric challenge.
47      *
48      * @param result The onActivityResult intent from ChooseLock* or ConfirmLock*
49      * @param challenge Unique biometric challenge from FingerprintManager/FaceManager
50      * @param userId User ID that the credential/biometric operation applies to
51      * @throws GatekeeperCredentialNotMatchException if Gatekeeper response is not match
52      * @throws IllegalStateException if Gatekeeper Password is missing
53      */
requestGatekeeperHat(@onNull Intent result, long challenge, int userId)54     public byte[] requestGatekeeperHat(@NonNull Intent result, long challenge, int userId) {
55         if (!containsGatekeeperPasswordHandle(result)) {
56             throw new IllegalStateException("Gatekeeper Password is missing!!");
57         }
58         final long gatekeeperPasswordHandle = result.getLongExtra(
59                 ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 0L);
60         return requestGatekeeperHat(gatekeeperPasswordHandle, challenge, userId);
61     }
62 
63     /**
64      * Given the result from confirming or choosing a credential, request Gatekeeper to generate
65      * a HardwareAuthToken with the Gatekeeper Password together with a biometric challenge.
66      *
67      * @param gkPwHandle The Gatekeeper password handle from ChooseLock* or ConfirmLock*
68      * @param challenge Unique biometric challenge from FingerprintManager/FaceManager
69      * @param userId User ID that the credential/biometric operation applies to
70      * @throws GatekeeperCredentialNotMatchException if Gatekeeper response is not match
71      */
requestGatekeeperHat(long gkPwHandle, long challenge, int userId)72     public byte[] requestGatekeeperHat(long gkPwHandle, long challenge, int userId) {
73         final VerifyCredentialResponse response = mLockPatternUtils.verifyGatekeeperPasswordHandle(
74                 gkPwHandle, challenge, userId);
75         if (!response.isMatched()) {
76             throw new GatekeeperCredentialNotMatchException("Unable to request Gatekeeper HAT");
77         }
78         return response.getGatekeeperHAT();
79     }
80 
81     /**
82      * Intent data contains gatekeeper password handle or not
83      */
containsGatekeeperPasswordHandle(@ullable Intent data)84     public static boolean containsGatekeeperPasswordHandle(@Nullable Intent data) {
85         return data != null && data.hasExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE);
86     }
87 
88     /**
89      * Returns the gatekeeper password handle from intent
90      */
getGatekeeperPasswordHandle(@onNull Intent data)91     public static long getGatekeeperPasswordHandle(@NonNull Intent data) {
92         return data.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 0L);
93     }
94 
95     /**
96      * Requests {@link com.android.server.locksettings.LockSettingsService} to remove the
97      * gatekeeper password associated with a previous
98      * {@link ChooseLockSettingsHelper.Builder#setRequestGatekeeperPasswordHandle(boolean)}
99      *
100      * @param data The onActivityResult intent from ChooseLock* or ConfirmLock*
101      * @param alsoRemoveItFromIntent set it to true if gkPwHandle needs to be removed from intent
102      */
removeGatekeeperPasswordHandle(@ullable Intent data, boolean alsoRemoveItFromIntent)103     public void removeGatekeeperPasswordHandle(@Nullable Intent data,
104             boolean alsoRemoveItFromIntent) {
105         if (data == null) {
106             return;
107         }
108         if (!containsGatekeeperPasswordHandle(data)) {
109             return;
110         }
111         removeGatekeeperPasswordHandle(getGatekeeperPasswordHandle(data));
112         if (alsoRemoveItFromIntent) {
113             data.removeExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE);
114         }
115     }
116 
117     /**
118      * Requests {@link com.android.server.locksettings.LockSettingsService} to remove the
119      * gatekeeper password associated with a previous
120      * {@link ChooseLockSettingsHelper.Builder#setRequestGatekeeperPasswordHandle(boolean)}
121      *
122      * @param handle The Gatekeeper password handle from ChooseLock* or ConfirmLock*
123      */
removeGatekeeperPasswordHandle(long handle)124     public void removeGatekeeperPasswordHandle(long handle) {
125         mLockPatternUtils.removeGatekeeperPasswordHandle(handle);
126         Log.d(TAG, "Removed handle");
127     }
128 }
129