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