2/n: Add setRequestGatekeeperPassword to ChooseLockSettingsHelper
This change adds the plumbing on Settings side for ConfirmLock*. ChooseLock* will be done in a follow-up CL. The changes in this CL are not invoked by any code path yet. This will also be integrated in a follow-up CL. Bug: 161765592 Perform the following with a local change to use ChooseLockSettingsHelper#setRequestGatekeeperPassword(true) Test: GK PW is received when setRequestGatekeeperPassword(true) Test: GK PW + Challenge sent to GK, GK verifies and caller receives GK HAT successfully Change-Id: Ibd809784b5599343f34836bc5f3e709627b7f22a
This commit is contained in:
@@ -77,6 +77,7 @@ import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
|
||||
import com.android.internal.widget.LockscreenCredential;
|
||||
import com.android.internal.widget.PasswordValidationError;
|
||||
import com.android.internal.widget.TextViewInputDisabler;
|
||||
import com.android.internal.widget.VerifyCredentialResponse;
|
||||
import com.android.settings.EncryptionInterstitial;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
@@ -967,19 +968,24 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
}
|
||||
Intent result = null;
|
||||
if (success && mHasChallenge) {
|
||||
byte[] token;
|
||||
VerifyCredentialResponse response;
|
||||
try {
|
||||
token = mUtils.verifyCredential(mChosenPassword, mChallenge, mUserId);
|
||||
response = mUtils.verifyCredential(mChosenPassword, mChallenge, mUserId,
|
||||
0 /* flags */);
|
||||
} catch (RequestThrottledException e) {
|
||||
token = null;
|
||||
response = null;
|
||||
}
|
||||
|
||||
if (token == null) {
|
||||
Log.e(TAG, "critical: no token returned for known good password.");
|
||||
if (response == null) {
|
||||
Log.e(TAG, "critical: null response for known good password");
|
||||
} else if (!response.isMatched() || response.getGatekeeperHAT() == null) {
|
||||
Log.e(TAG, "critical: bad response or missing GK HAT for known good password: "
|
||||
+ response.toString());
|
||||
}
|
||||
|
||||
result = new Intent();
|
||||
result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
||||
result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
|
||||
response.getGatekeeperHAT());
|
||||
}
|
||||
return Pair.create(success, result);
|
||||
}
|
||||
|
@@ -47,6 +47,7 @@ import com.android.internal.widget.LockPatternView;
|
||||
import com.android.internal.widget.LockPatternView.Cell;
|
||||
import com.android.internal.widget.LockPatternView.DisplayMode;
|
||||
import com.android.internal.widget.LockscreenCredential;
|
||||
import com.android.internal.widget.VerifyCredentialResponse;
|
||||
import com.android.settings.EncryptionInterstitial;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
@@ -913,19 +914,24 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
}
|
||||
Intent result = null;
|
||||
if (success && mHasChallenge) {
|
||||
byte[] token;
|
||||
VerifyCredentialResponse response;
|
||||
try {
|
||||
token = mUtils.verifyCredential(mChosenPattern, mChallenge, userId);
|
||||
response = mUtils.verifyCredential(mChosenPattern, mChallenge, userId,
|
||||
0 /* flags */);
|
||||
} catch (RequestThrottledException e) {
|
||||
token = null;
|
||||
response = null;
|
||||
}
|
||||
|
||||
if (token == null) {
|
||||
Log.e(TAG, "critical: no token returned for known good pattern");
|
||||
if (response == null) {
|
||||
Log.e(TAG, "critial: null response for known good pattern");
|
||||
} else if (!response.isMatched() || response.getGatekeeperHAT() == null) {
|
||||
Log.e(TAG, "critical: bad response or missing GK HAT for known good pattern: "
|
||||
+ response.toString());
|
||||
}
|
||||
|
||||
result = new Intent();
|
||||
result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
||||
result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
|
||||
response.getGatekeeperHAT());
|
||||
}
|
||||
return Pair.create(success, result);
|
||||
}
|
||||
|
@@ -47,11 +47,16 @@ public final class ChooseLockSettingsHelper {
|
||||
public static final String EXTRA_KEY_RETURN_CREDENTIALS = "return_credentials";
|
||||
public static final String EXTRA_KEY_HAS_CHALLENGE = "has_challenge";
|
||||
public static final String EXTRA_KEY_CHALLENGE = "challenge";
|
||||
// Gatekeeper HardwareAuthToken
|
||||
public static final String EXTRA_KEY_CHALLENGE_TOKEN = "hw_auth_token";
|
||||
public static final String EXTRA_KEY_FOR_FINGERPRINT = "for_fingerprint";
|
||||
public static final String EXTRA_KEY_FOR_FACE = "for_face";
|
||||
public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot";
|
||||
public static final String EXTRA_KEY_FOREGROUND_ONLY = "foreground_only";
|
||||
public static final String EXTRA_KEY_REQUEST_GK_PW = "request_gk_pw";
|
||||
// Gatekeeper password, which can subsequently be used to generate Gatekeeper
|
||||
// HardwareAuthToken(s) via LockSettingsService#verifyGatekeeperPassword
|
||||
public static final String EXTRA_KEY_GK_PW = "gk_pw";
|
||||
|
||||
/**
|
||||
* When EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL and EXTRA_KEY_UNIFICATION_PROFILE_ID are
|
||||
@@ -119,6 +124,7 @@ public final class ChooseLockSettingsHelper {
|
||||
private boolean mAllowAnyUserId;
|
||||
// The challenge can be 0, which is different than "no challenge"
|
||||
@Nullable Long mChallenge;
|
||||
boolean mRequestGatekeeperPassword;
|
||||
|
||||
public Builder(@NonNull Activity activity) {
|
||||
mActivity = activity;
|
||||
@@ -174,7 +180,7 @@ public final class ChooseLockSettingsHelper {
|
||||
* @param returnCredentials if true, puts the following credentials into intent for
|
||||
* onActivityResult with the following keys:
|
||||
* {@link #EXTRA_KEY_TYPE}, {@link #EXTRA_KEY_PASSWORD},
|
||||
* {@link #EXTRA_KEY_CHALLENGE_TOKEN}.
|
||||
* {@link #EXTRA_KEY_CHALLENGE_TOKEN}, {@link #EXTRA_KEY_GK_PW}
|
||||
* Note that if this is true, this can only be called internally.
|
||||
*/
|
||||
@NonNull public Builder setReturnCredentials(boolean returnCredentials) {
|
||||
@@ -231,6 +237,24 @@ public final class ChooseLockSettingsHelper {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that LockSettingsService return the Gatekeeper Password (instead of the
|
||||
* Gatekeeper HAT). This allows us to use a single entry of the user's credential
|
||||
* to create multiple Gatekeeper HATs containing distinct challenges via
|
||||
* {@link LockPatternUtils#verifyGatekeeperPassword(byte[], long, int)}.
|
||||
*
|
||||
* Upon confirmation of the user's password, the Gatekeeper Password will be returned via
|
||||
* onActivityResult with the key being {@link #EXTRA_KEY_GK_PW}.
|
||||
* @param requestGatekeeperPassword
|
||||
*
|
||||
* Note that invoking {@link #setChallenge(long)} will be treated as a no-op if Gatekeeper
|
||||
* Password has been requested.
|
||||
*/
|
||||
@NonNull public Builder setRequestGatekeeperPassword(boolean requestGatekeeperPassword) {
|
||||
mRequestGatekeeperPassword = requestGatekeeperPassword;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull public ChooseLockSettingsHelper build() {
|
||||
if (!mAllowAnyUserId && mUserId != LockPatternUtils.USER_FRP) {
|
||||
Utils.enforceSameOwner(mActivity, mUserId);
|
||||
@@ -265,14 +289,15 @@ public final class ChooseLockSettingsHelper {
|
||||
return launchConfirmationActivity(mBuilder.mRequestCode, mBuilder.mTitle, mBuilder.mHeader,
|
||||
mBuilder.mDescription, mBuilder.mReturnCredentials, mBuilder.mExternal,
|
||||
mBuilder.mChallenge != null, challenge, mBuilder.mUserId,
|
||||
mBuilder.mAlternateButton, mBuilder.mAllowAnyUserId, mBuilder.mForegroundOnly);
|
||||
mBuilder.mAlternateButton, mBuilder.mAllowAnyUserId, mBuilder.mForegroundOnly,
|
||||
mBuilder.mRequestGatekeeperPassword);
|
||||
}
|
||||
|
||||
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
|
||||
@Nullable CharSequence header, @Nullable CharSequence description,
|
||||
boolean returnCredentials, boolean external, boolean hasChallenge,
|
||||
long challenge, int userId, @Nullable CharSequence alternateButton,
|
||||
boolean allowAnyUser, boolean foregroundOnly) {
|
||||
boolean allowAnyUser, boolean foregroundOnly, boolean requestGatekeeperPassword) {
|
||||
final int effectiveUserId = UserManager.get(mActivity).getCredentialOwnerProfile(userId);
|
||||
boolean launched = false;
|
||||
|
||||
@@ -283,7 +308,7 @@ public final class ChooseLockSettingsHelper {
|
||||
? ConfirmLockPattern.InternalActivity.class
|
||||
: ConfirmLockPattern.class, returnCredentials, external,
|
||||
hasChallenge, challenge, userId, alternateButton, allowAnyUser,
|
||||
foregroundOnly);
|
||||
foregroundOnly, requestGatekeeperPassword);
|
||||
break;
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
|
||||
@@ -296,7 +321,7 @@ public final class ChooseLockSettingsHelper {
|
||||
? ConfirmLockPassword.InternalActivity.class
|
||||
: ConfirmLockPassword.class, returnCredentials, external,
|
||||
hasChallenge, challenge, userId, alternateButton, allowAnyUser,
|
||||
foregroundOnly);
|
||||
foregroundOnly, requestGatekeeperPassword);
|
||||
break;
|
||||
}
|
||||
return launched;
|
||||
@@ -306,7 +331,7 @@ public final class ChooseLockSettingsHelper {
|
||||
CharSequence message, Class<?> activityClass, boolean returnCredentials,
|
||||
boolean external, boolean hasChallenge, long challenge,
|
||||
int userId, @Nullable CharSequence alternateButton, boolean allowAnyUser,
|
||||
boolean foregroundOnly) {
|
||||
boolean foregroundOnly, boolean requestGatekeeperPassword) {
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
|
||||
intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
|
||||
@@ -323,6 +348,8 @@ public final class ChooseLockSettingsHelper {
|
||||
intent.putExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL, alternateButton);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOREGROUND_ONLY, foregroundOnly);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_ALLOW_ANY_USER, allowAnyUser);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW,
|
||||
requestGatekeeperPassword);
|
||||
|
||||
intent.setClassName(SETTINGS_PACKAGE_NAME, activityClass.getName());
|
||||
if (external) {
|
||||
|
@@ -71,6 +71,8 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
protected static final long CLEAR_WRONG_ATTEMPT_TIMEOUT_MS = 3000;
|
||||
|
||||
protected boolean mReturnCredentials = false;
|
||||
protected boolean mReturnGatekeeperPassword = false;
|
||||
protected boolean mVerifyChallenge = false;
|
||||
protected Button mCancelButton;
|
||||
/** Button allowing managed profile password reset, null when is not shown. */
|
||||
@Nullable protected Button mForgotButton;
|
||||
@@ -93,12 +95,18 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mFrpAlternateButtonText = getActivity().getIntent().getCharSequenceExtra(
|
||||
final Intent intent = getActivity().getIntent();
|
||||
mFrpAlternateButtonText = intent.getCharSequenceExtra(
|
||||
KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
|
||||
mReturnCredentials = getActivity().getIntent().getBooleanExtra(
|
||||
mReturnCredentials = intent.getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, false);
|
||||
|
||||
mReturnGatekeeperPassword = intent.getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW, false);
|
||||
mVerifyChallenge = intent.getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
|
||||
|
||||
// Only take this argument into account if it belongs to the current profile.
|
||||
Intent intent = getActivity().getIntent();
|
||||
mUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras(),
|
||||
isInternalActivity());
|
||||
mFrp = (mUserId == LockPatternUtils.USER_FRP);
|
||||
|
@@ -49,6 +49,7 @@ import com.android.internal.widget.LockPatternChecker;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockscreenCredential;
|
||||
import com.android.internal.widget.TextViewInputDisabler;
|
||||
import com.android.internal.widget.VerifyCredentialResponse;
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.animation.AppearAnimationUtils;
|
||||
import com.android.settingslib.animation.DisappearAnimationUtils;
|
||||
@@ -380,13 +381,18 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
: LockscreenCredential.createPin(passwordText);
|
||||
|
||||
mPasswordEntryInputDisabler.setInputEnabled(false);
|
||||
final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
|
||||
|
||||
Intent intent = new Intent();
|
||||
if (verifyChallenge) {
|
||||
// TODO(b/161956762): Sanitize this
|
||||
if (mReturnGatekeeperPassword) {
|
||||
if (isInternalActivity()) {
|
||||
startVerifyPassword(credential, intent);
|
||||
startVerifyPassword(credential, intent,
|
||||
LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW);
|
||||
return;
|
||||
}
|
||||
} else if (mVerifyChallenge) {
|
||||
if (isInternalActivity()) {
|
||||
startVerifyPassword(credential, intent, 0 /* flags */);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -401,34 +407,34 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
return getActivity() instanceof ConfirmLockPassword.InternalActivity;
|
||||
}
|
||||
|
||||
private void startVerifyPassword(LockscreenCredential credential, final Intent intent) {
|
||||
private void startVerifyPassword(LockscreenCredential credential, final Intent intent,
|
||||
@LockPatternUtils.VerifyFlag int flags) {
|
||||
long challenge = getActivity().getIntent().getLongExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
|
||||
final int localEffectiveUserId = mEffectiveUserId;
|
||||
final int localUserId = mUserId;
|
||||
final LockPatternChecker.OnVerifyCallback onVerifyCallback =
|
||||
new LockPatternChecker.OnVerifyCallback() {
|
||||
@Override
|
||||
public void onVerified(byte[] token, int timeoutMs) {
|
||||
mPendingLockCheck = null;
|
||||
boolean matched = false;
|
||||
if (token != null) {
|
||||
matched = true;
|
||||
if (mReturnCredentials) {
|
||||
intent.putExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
|
||||
token);
|
||||
}
|
||||
}
|
||||
mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs,
|
||||
localEffectiveUserId);
|
||||
}
|
||||
final LockPatternChecker.OnVerifyCallback onVerifyCallback = (response, timeoutMs) -> {
|
||||
mPendingLockCheck = null;
|
||||
final boolean matched = response.isMatched();
|
||||
if (matched && mReturnCredentials) {
|
||||
if ((flags & LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW) != 0) {
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW,
|
||||
response.getGatekeeperPw());
|
||||
} else {
|
||||
intent.putExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
|
||||
response.getGatekeeperHAT());
|
||||
}
|
||||
}
|
||||
mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs,
|
||||
localEffectiveUserId);
|
||||
};
|
||||
mPendingLockCheck = (localEffectiveUserId == localUserId)
|
||||
? LockPatternChecker.verifyCredential(
|
||||
mLockPatternUtils, credential, challenge, localUserId, onVerifyCallback)
|
||||
mLockPatternUtils, credential, challenge, localUserId, flags,
|
||||
onVerifyCallback)
|
||||
: LockPatternChecker.verifyTiedProfileChallenge(
|
||||
mLockPatternUtils, credential, challenge, localUserId,
|
||||
mLockPatternUtils, credential, challenge, localUserId, flags,
|
||||
onVerifyCallback);
|
||||
}
|
||||
|
||||
|
@@ -40,6 +40,7 @@ import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockPatternView;
|
||||
import com.android.internal.widget.LockPatternView.Cell;
|
||||
import com.android.internal.widget.LockscreenCredential;
|
||||
import com.android.internal.widget.VerifyCredentialResponse;
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.animation.AppearAnimationCreator;
|
||||
import com.android.settingslib.animation.AppearAnimationUtils;
|
||||
@@ -422,14 +423,18 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
|
||||
mLockPatternView.setEnabled(false);
|
||||
|
||||
final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
|
||||
final LockscreenCredential credential = LockscreenCredential.createPattern(pattern);
|
||||
//TODO: how to sanitize this?
|
||||
// TODO(b/161956762): Sanitize this
|
||||
Intent intent = new Intent();
|
||||
if (verifyChallenge) {
|
||||
if (mReturnGatekeeperPassword) {
|
||||
if (isInternalActivity()) {
|
||||
startVerifyPattern(credential, intent);
|
||||
startVerifyPattern(credential, intent,
|
||||
LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW);
|
||||
return;
|
||||
}
|
||||
} else if (mVerifyChallenge) {
|
||||
if (isInternalActivity()) {
|
||||
startVerifyPattern(credential, intent, 0 /* flags */);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -445,36 +450,35 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
|
||||
private void startVerifyPattern(final LockscreenCredential pattern,
|
||||
final Intent intent) {
|
||||
final Intent intent, @LockPatternUtils.VerifyFlag int flags) {
|
||||
final int localEffectiveUserId = mEffectiveUserId;
|
||||
final int localUserId = mUserId;
|
||||
long challenge = getActivity().getIntent().getLongExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
|
||||
final LockPatternChecker.OnVerifyCallback onVerifyCallback =
|
||||
new LockPatternChecker.OnVerifyCallback() {
|
||||
@Override
|
||||
public void onVerified(byte[] token, int timeoutMs) {
|
||||
mPendingLockCheck = null;
|
||||
boolean matched = false;
|
||||
if (token != null) {
|
||||
matched = true;
|
||||
if (mReturnCredentials) {
|
||||
intent.putExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
|
||||
token);
|
||||
}
|
||||
(response, timeoutMs) -> {
|
||||
mPendingLockCheck = null;
|
||||
final boolean matched = response.isMatched();
|
||||
if (matched && mReturnCredentials) {
|
||||
if ((flags & LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW) != 0) {
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW,
|
||||
response.getGatekeeperPw());
|
||||
} else {
|
||||
intent.putExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
|
||||
response.getGatekeeperHAT());
|
||||
}
|
||||
mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs,
|
||||
localEffectiveUserId);
|
||||
}
|
||||
};
|
||||
mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs,
|
||||
localEffectiveUserId);
|
||||
};
|
||||
mPendingLockCheck = (localEffectiveUserId == localUserId)
|
||||
? LockPatternChecker.verifyCredential(
|
||||
mLockPatternUtils, pattern, challenge, localUserId,
|
||||
mLockPatternUtils, pattern, challenge, localUserId, flags,
|
||||
onVerifyCallback)
|
||||
: LockPatternChecker.verifyTiedProfileChallenge(
|
||||
mLockPatternUtils, pattern,
|
||||
challenge, localUserId, onVerifyCallback);
|
||||
mLockPatternUtils, pattern, challenge, localUserId, flags,
|
||||
onVerifyCallback);
|
||||
}
|
||||
|
||||
private void startCheckPattern(final LockscreenCredential pattern,
|
||||
|
Reference in New Issue
Block a user