From 6609b0c22ae89a24d1b07dc3c4143452616d4450 Mon Sep 17 00:00:00 2001 From: Andres Morales Date: Sun, 12 Apr 2015 15:38:25 -0700 Subject: [PATCH] pipe auth token through confirm and set password ConfirmDeviceCredentialsActivity and ChooseLockGeneric now understand CLSH.EXTRA_KEY_HAS_CHALLENGE and CLSH.EXTRA_KEY_CHALLENGE in their launching intents. If present, they return a hw_auth_token_t verifying the challenge passed in as a field in keyed by CLSH.EXTRA_KEY_CHALLENGE_TOKEN in their result intents. Change-Id: I0b4e02b6a798a9e57d02522880a180dffadfcde1 --- .../android/settings/ChooseLockGeneric.java | 39 ++++++++++++++--- .../android/settings/ChooseLockPassword.java | 27 +++++++++++- .../android/settings/ChooseLockPattern.java | 29 +++++++++++-- .../settings/ChooseLockSettingsHelper.java | 43 ++++++++++++++++--- .../ConfirmDeviceCredentialActivity.java | 11 +++++ .../android/settings/ConfirmLockPassword.java | 28 +++++++++++- .../android/settings/ConfirmLockPattern.java | 29 ++++++++++++- 7 files changed, 188 insertions(+), 18 deletions(-) diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java index 51614a6b74d..a53eca0dc19 100644 --- a/src/com/android/settings/ChooseLockGeneric.java +++ b/src/com/android/settings/ChooseLockGeneric.java @@ -89,6 +89,8 @@ public class ChooseLockGeneric extends SettingsActivity { private ChooseLockSettingsHelper mChooseLockSettingsHelper; private DevicePolicyManager mDPM; private KeyStore mKeyStore; + private boolean mHasChallenge = false; + private long mChallenge; private boolean mPasswordConfirmed = false; private boolean mWaitingForConfirmation = false; private int mEncryptionRequestQuality; @@ -133,6 +135,11 @@ public class ChooseLockGeneric extends SettingsActivity { mPasswordConfirmed = !confirmCredentials; } + mHasChallenge = getActivity().getIntent().getBooleanExtra( + ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); + mChallenge = getActivity().getIntent().getLongExtra( + ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); + if (savedInstanceState != null) { mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED); mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION); @@ -389,8 +396,13 @@ public class ChooseLockGeneric extends SettingsActivity { maxLength, requirePasswordToDecrypt, confirmCredentials); } - // SetupWizard version will not need this as they will never be changing a password - // TODO: confirm + protected Intent getLockPasswordIntent(Context context, int quality, + int minLength, final int maxLength, + boolean requirePasswordToDecrypt, long challenge) { + return ChooseLockPassword.createIntent(context, quality, minLength, + maxLength, requirePasswordToDecrypt, challenge); + } + private Intent getLockPasswordIntent(Context context, int quality, int minLength, final int maxLength, boolean requirePasswordToDecrypt, String password) { return ChooseLockPassword.createIntent(context, quality, minLength, maxLength, @@ -403,8 +415,11 @@ public class ChooseLockGeneric extends SettingsActivity { confirmCredentials); } - // SetupWizard version will not need this as they will never be changing a password - // TODO: confirm + protected Intent getLockPatternIntent(Context context, final boolean requirePassword, + long challenge) { + return ChooseLockPattern.createIntent(context, requirePassword, challenge); + } + private Intent getLockPatternIntent(Context context, final boolean requirePassword, final String pattern) { return ChooseLockPattern.createIntent(context, requirePassword, pattern); @@ -439,12 +454,24 @@ public class ChooseLockGeneric extends SettingsActivity { minLength = MIN_PASSWORD_LENGTH; } final int maxLength = mDPM.getPasswordMaximumLength(quality); - Intent intent = getLockPasswordIntent(context, quality, minLength, + Intent intent; + if (mHasChallenge) { + intent = getLockPasswordIntent(context, quality, minLength, + maxLength, mRequirePassword, mChallenge); + } else { + intent = getLockPasswordIntent(context, quality, minLength, maxLength, mRequirePassword, mUserPassword); + } startActivityForResult(intent, CHOOSE_LOCK_REQUEST); } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { - Intent intent = getLockPatternIntent(context, mRequirePassword, + Intent intent; + if (mHasChallenge) { + intent = getLockPatternIntent(context, mRequirePassword, + mChallenge); + } else { + intent = getLockPatternIntent(context, mRequirePassword, mUserPassword); + } startActivityForResult(intent, CHOOSE_LOCK_REQUEST); } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { mChooseLockSettingsHelper.utils().clearLock(); diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java index 7ef044a1eb8..4e28eab73e5 100644 --- a/src/com/android/settings/ChooseLockPassword.java +++ b/src/com/android/settings/ChooseLockPassword.java @@ -84,6 +84,15 @@ public class ChooseLockPassword extends SettingsActivity { return intent; } + public static Intent createIntent(Context context, int quality, + int minLength, final int maxLength, boolean requirePasswordToDecrypt, long challenge) { + Intent intent = createIntent(context, quality, minLength, maxLength, requirePasswordToDecrypt, + false); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); + return intent; + } + @Override protected boolean isValidFragment(String fragmentName) { if (ChooseLockPasswordFragment.class.getName().equals(fragmentName)) return true; @@ -112,6 +121,8 @@ public class ChooseLockPassword extends SettingsActivity { private static final String KEY_CURRENT_PASSWORD = "current_password"; private String mCurrentPassword; + private boolean mHasChallenge; + private long mChallenge; private TextView mPasswordEntry; private int mPasswordMinLength = LockPatternUtils.MIN_LOCK_PASSWORD_SIZE; private int mPasswordMaxLength = 16; @@ -249,8 +260,12 @@ public class ChooseLockPassword extends SettingsActivity { : (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD)); Intent intent = getActivity().getIntent(); - final boolean confirmCredentials = intent.getBooleanExtra("confirm_credentials", true); + final boolean confirmCredentials = intent.getBooleanExtra( + ChooseLockGeneric.CONFIRM_CREDENTIALS, true); mCurrentPassword = intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + mHasChallenge = intent.getBooleanExtra( + ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); + mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); if (savedInstanceState == null) { updateStage(Stage.Introduction); if (confirmCredentials) { @@ -463,7 +478,15 @@ public class ChooseLockPassword extends SettingsActivity { EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true); mLockPatternUtils.setCredentialRequiredToDecrypt(required); mLockPatternUtils.saveLockPassword(pin, mCurrentPassword, mRequestedQuality); - getActivity().setResult(RESULT_FINISHED); + + if (mHasChallenge) { + Intent intent = new Intent(); + byte[] token = mLockPatternUtils.verifyPassword(pin, mChallenge); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); + getActivity().setResult(RESULT_FINISHED, intent); + } else { + getActivity().setResult(RESULT_FINISHED); + } getActivity().finish(); mDone = true; if (!wasSecureBefore) { diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java index c516ad09d45..e3b7d4b612f 100644 --- a/src/com/android/settings/ChooseLockPattern.java +++ b/src/com/android/settings/ChooseLockPattern.java @@ -84,6 +84,15 @@ public class ChooseLockPattern extends SettingsActivity { return intent; } + + public static Intent createIntent(Context context, + boolean requirePassword, long challenge) { + Intent intent = createIntent(context, requirePassword, false); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); + return intent; + } + @Override protected boolean isValidFragment(String fragmentName) { if (ChooseLockPatternFragment.class.getName().equals(fragmentName)) return true; @@ -123,6 +132,8 @@ public class ChooseLockPattern extends SettingsActivity { private static final int ID_EMPTY_MESSAGE = -1; private String mCurrentPattern; + private boolean mHasChallenge; + private long mChallenge; protected TextView mHeaderText; protected LockPatternView mLockPatternView; protected TextView mFooterText; @@ -384,8 +395,11 @@ public class ChooseLockPattern extends SettingsActivity { final boolean confirmCredentials = getActivity().getIntent() .getBooleanExtra("confirm_credentials", true); - mCurrentPattern = getActivity().getIntent() - .getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + Intent intent = getActivity().getIntent(); + mCurrentPattern = intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); + mHasChallenge = intent.getBooleanExtra( + ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); + mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); if (savedInstanceState == null) { if (confirmCredentials) { @@ -606,7 +620,16 @@ public class ChooseLockPattern extends SettingsActivity { if (!wasSecureBefore) { startActivity(getRedactionInterstitialIntent(getActivity())); } - getActivity().setResult(RESULT_FINISHED); + + if (mHasChallenge) { + Intent intent = new Intent(); + byte[] token = utils.verifyPattern(mChosenPattern, mChallenge); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); + getActivity().setResult(RESULT_FINISHED, intent); + } else { + getActivity().setResult(RESULT_FINISHED); + } + getActivity().finish(); mDone = true; } diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java index 65697f69708..c113b1d67f2 100644 --- a/src/com/android/settings/ChooseLockSettingsHelper.java +++ b/src/com/android/settings/ChooseLockSettingsHelper.java @@ -28,6 +28,10 @@ public final class ChooseLockSettingsHelper { static final String EXTRA_KEY_TYPE = "type"; static final String EXTRA_KEY_PASSWORD = "password"; + static final String EXTRA_KEY_HAS_CHALLENGE = "has_challenge"; + static final String EXTRA_KEY_CHALLENGE = "challenge"; + static final String EXTRA_KEY_CHALLENGE_TOKEN = "hw_auth_token"; + private LockPatternUtils mLockPatternUtils; private Activity mActivity; @@ -87,13 +91,38 @@ public final class ChooseLockSettingsHelper { boolean launchConfirmationActivity(int request, @Nullable CharSequence title, @Nullable CharSequence header, @Nullable CharSequence description, boolean returnCredentials, boolean external) { + return launchConfirmationActivity(request, title, header, description, + returnCredentials, external, false, 0); + } + + /** + * If a pattern, password or PIN exists, prompt the user before allowing them to change it. + * @param message optional message to display about the action about to be done + * @param details optional detail message to display + * @param challenge a challenge to be verified against the device credential. + * This method can only be called internally. + * @return true if one exists and we launched an activity to confirm it + * @see #onActivityResult(int, int, android.content.Intent) + */ + boolean launchConfirmationActivity(int request, @Nullable CharSequence title, + @Nullable CharSequence header, @Nullable CharSequence description, + long challenge) { + return launchConfirmationActivity(request, title, header, description, + false, false, true, challenge); + } + + private boolean launchConfirmationActivity(int request, @Nullable CharSequence title, + @Nullable CharSequence header, @Nullable CharSequence description, + boolean returnCredentials, boolean external, boolean hasChallenge, + long challenge) { boolean launched = false; switch (mLockPatternUtils.getKeyguardStoredPasswordQuality()) { case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: launched = launchConfirmationActivity(request, title, header, description, - returnCredentials + returnCredentials || hasChallenge ? ConfirmLockPattern.InternalActivity.class - : ConfirmLockPattern.class, external); + : ConfirmLockPattern.class, external, + hasChallenge, challenge); break; case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: @@ -101,16 +130,18 @@ public final class ChooseLockSettingsHelper { case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: launched = launchConfirmationActivity(request, title, header, description, - returnCredentials + returnCredentials || hasChallenge ? ConfirmLockPassword.InternalActivity.class - : ConfirmLockPassword.class, external); + : ConfirmLockPassword.class, external, + hasChallenge, challenge); break; } return launched; } private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header, - CharSequence message, Class activityClass, boolean external) { + CharSequence message, Class activityClass, boolean external, boolean hasChallenge, + long challenge) { final Intent intent = new Intent(); intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title); intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header); @@ -119,6 +150,8 @@ public final class ChooseLockSettingsHelper { intent.putExtra(ConfirmDeviceCredentialBaseFragment.DARK_THEME, external); intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_CANCEL_BUTTON, external); intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, external); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, hasChallenge); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); intent.setClassName(ConfirmDeviceCredentialBaseFragment.PACKAGE, activityClass.getName()); if (mFragment != null) { mFragment.startActivityForResult(intent, request); diff --git a/src/com/android/settings/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/ConfirmDeviceCredentialActivity.java index 9a7f843ac3c..7653603b2da 100644 --- a/src/com/android/settings/ConfirmDeviceCredentialActivity.java +++ b/src/com/android/settings/ConfirmDeviceCredentialActivity.java @@ -39,6 +39,17 @@ public class ConfirmDeviceCredentialActivity extends Activity { return intent; } + public static Intent createIntent(CharSequence title, CharSequence details, long challenge) { + Intent intent = new Intent(); + intent.setClassName("com.android.settings", + ConfirmDeviceCredentialActivity.class.getName()); + intent.putExtra(KeyguardManager.EXTRA_TITLE, title); + intent.putExtra(KeyguardManager.EXTRA_DESCRIPTION, details); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); + return intent; + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java index 44c599b70de..d9622c015a5 100644 --- a/src/com/android/settings/ConfirmLockPassword.java +++ b/src/com/android/settings/ConfirmLockPassword.java @@ -183,8 +183,34 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { private void handleNext() { final String pin = mPasswordEntry.getText().toString(); - if (mLockPatternUtils.checkPassword(pin)) { + final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra( + ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); + boolean matched = false; + Intent intent = new Intent(); + if (verifyChallenge) { + if (getActivity() instanceof ConfirmLockPassword.InternalActivity) { + long challenge = getActivity().getIntent().getLongExtra( + ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); + byte[] token = mLockPatternUtils.verifyPassword(pin, challenge); + if (token != null) { + matched = true; + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); + } + } + } else if (mLockPatternUtils.checkPassword(pin)) { + matched = true; + if (getActivity() instanceof ConfirmLockPassword.InternalActivity) { + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, + mIsAlpha ? StorageManager.CRYPT_TYPE_PASSWORD + : StorageManager.CRYPT_TYPE_PIN); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pin); + } + } + + if (matched) { authenticationSucceeded(pin); + getActivity().setResult(RESULT_OK, intent); + getActivity().finish(); } else { if (++mNumWrongConfirmAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) { long deadline = mLockPatternUtils.setLockoutAttemptDeadline(); diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java index 8c4fabcd639..9db1719738a 100644 --- a/src/com/android/settings/ConfirmLockPattern.java +++ b/src/com/android/settings/ConfirmLockPattern.java @@ -273,8 +273,35 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { } public void onPatternDetected(List pattern) { - if (mLockPatternUtils.checkPattern(pattern)) { + final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra( + ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); + boolean matched = false; + Intent intent = new Intent(); + if (verifyChallenge) { + if (getActivity() instanceof ConfirmLockPattern.InternalActivity) { + long challenge = getActivity().getIntent().getLongExtra( + ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); + byte[] token = mLockPatternUtils.verifyPattern(pattern, challenge); + if (token != null) { + matched = true; + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); + } + } + } else if (mLockPatternUtils.checkPattern(pattern)) { + matched = true; + if (getActivity() instanceof ConfirmLockPattern.InternalActivity) { + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, + StorageManager.CRYPT_TYPE_PATTERN); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, + LockPatternUtils.patternToString(pattern)); + } + + } + + if (matched) { authenticationSucceeded(LockPatternUtils.patternToString(pattern)); + getActivity().setResult(Activity.RESULT_OK, intent); + getActivity().finish(); } else { if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL && ++mNumWrongConfirmAttempts