summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/CryptKeeper.java
diff options
context:
space:
mode:
authorPaul Crowley <paulcrowley@google.com>2014-11-07 00:52:57 -0800
committerPaul Crowley <paulcrowley@google.com>2014-11-08 01:43:45 +0000
commit2555e5f1040984a3422c5a4db43421e87d4ca0ce (patch)
tree158e1755b83d16d7f1d2944029915ca60785d752 /src/com/android/settings/CryptKeeper.java
parentc44ad35e51db79721821817e1b8e52dce632d2bf (diff)
downloadpackages_apps_Settings-2555e5f1040984a3422c5a4db43421e87d4ca0ce.zip
packages_apps_Settings-2555e5f1040984a3422c5a4db43421e87d4ca0ce.tar.gz
packages_apps_Settings-2555e5f1040984a3422c5a4db43421e87d4ca0ce.tar.bz2
Prevent factory reset for short passwords in CryptKeeper
Since patterns and passwords can't be shorter than 4 elements, we shouldn't count them against attempts to unlock the device. If we do, we risk resetting the device due to stray input. Bug: 18211475 Bug: 18273380 Change-Id: Ib329cd3383471483cda68bfac4278b17d0c09c57 Conflicts: src/com/android/settings/CryptKeeper.java
Diffstat (limited to 'src/com/android/settings/CryptKeeper.java')
-rw-r--r--src/com/android/settings/CryptKeeper.java140
1 files changed, 87 insertions, 53 deletions
diff --git a/src/com/android/settings/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index eded55b..33fa9fd 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -135,7 +135,18 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
// how long we wait to clear a right pattern
private static final int RIGHT_PATTERN_CLEAR_TIMEOUT_MS = 500;
- private Runnable mClearPatternRunnable = new Runnable() {
+ // When the user enters a short pin/password, run this to show an error,
+ // but don't count it against attempts.
+ private final Runnable mFakeUnlockAttemptRunnable = new Runnable() {
+ public void run() {
+ handleBadAttempt(1 /* failedAttempt */);
+ }
+ };
+
+ // TODO: this should be tuned to match minimum decryption timeout
+ private static final int FAKE_ATTEMPT_DELAY = 1000;
+
+ private final Runnable mClearPatternRunnable = new Runnable() {
@Override
public void run() {
mLockPatternView.clearPattern();
@@ -164,8 +175,7 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
@Override
protected void onPreExecute() {
super.onPreExecute();
- final TextView status = (TextView) findViewById(R.id.status);
- status.setText(R.string.checking_decryption);
+ beginAttempt();
}
@Override
@@ -207,59 +217,66 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
showFactoryReset(true);
return;
} else {
- // Wrong entry. Handle pattern case.
- if (mLockPatternView != null) {
- mLockPatternView.setDisplayMode(DisplayMode.Wrong);
- mLockPatternView.removeCallbacks(mClearPatternRunnable);
- mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
- }
- if ((failedAttempts % COOL_DOWN_ATTEMPTS) == 0) {
- mCooldown = COOL_DOWN_INTERVAL;
- cooldown();
- } else {
- final TextView status = (TextView) findViewById(R.id.status);
+ handleBadAttempt(failedAttempts);
+ }
+ }
+ }
- int remainingAttempts = MAX_FAILED_ATTEMPTS - failedAttempts;
- if (remainingAttempts < COOL_DOWN_ATTEMPTS) {
- CharSequence warningTemplate = getText(R.string.crypt_keeper_warn_wipe);
- CharSequence warning = TextUtils.expandTemplate(warningTemplate,
- Integer.toString(remainingAttempts));
- status.setText(warning);
- } else {
- int passwordType = StorageManager.CRYPT_TYPE_PASSWORD;
- try {
- final IMountService service = getMountService();
- passwordType = service.getPasswordType();
- } catch (Exception e) {
- Log.e(TAG, "Error calling mount service " + e);
- }
-
- if (passwordType == StorageManager.CRYPT_TYPE_PIN) {
- status.setText(R.string.cryptkeeper_wrong_pin);
- } else if (passwordType == StorageManager.CRYPT_TYPE_PATTERN) {
- status.setText(R.string.cryptkeeper_wrong_pattern);
- } else {
- status.setText(R.string.cryptkeeper_wrong_password);
- }
- }
+ private void beginAttempt() {
+ final TextView status = (TextView) findViewById(R.id.status);
+ status.setText(R.string.checking_decryption);
+ }
+ private void handleBadAttempt(Integer failedAttempts) {
+ // Wrong entry. Handle pattern case.
+ if (mLockPatternView != null) {
+ mLockPatternView.setDisplayMode(DisplayMode.Wrong);
+ mLockPatternView.removeCallbacks(mClearPatternRunnable);
+ mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
+ }
+ if ((failedAttempts % COOL_DOWN_ATTEMPTS) == 0) {
+ mCooldown = COOL_DOWN_INTERVAL;
+ cooldown();
+ } else {
+ final TextView status = (TextView) findViewById(R.id.status);
- if (mLockPatternView != null) {
- mLockPatternView.setDisplayMode(DisplayMode.Wrong);
- }
- // Reenable the password entry
- if (mPasswordEntry != null) {
- mPasswordEntry.setEnabled(true);
- final InputMethodManager imm = (InputMethodManager) getSystemService(
- Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(mPasswordEntry, 0);
- setBackFunctionality(true);
- }
- if (mLockPatternView != null) {
- mLockPatternView.setEnabled(true);
- }
+ int remainingAttempts = MAX_FAILED_ATTEMPTS - failedAttempts;
+ if (remainingAttempts < COOL_DOWN_ATTEMPTS) {
+ CharSequence warningTemplate = getText(R.string.crypt_keeper_warn_wipe);
+ CharSequence warning = TextUtils.expandTemplate(warningTemplate,
+ Integer.toString(remainingAttempts));
+ status.setText(warning);
+ } else {
+ int passwordType = StorageManager.CRYPT_TYPE_PASSWORD;
+ try {
+ final IMountService service = getMountService();
+ passwordType = service.getPasswordType();
+ } catch (Exception e) {
+ Log.e(TAG, "Error calling mount service " + e);
+ }
+
+ if (passwordType == StorageManager.CRYPT_TYPE_PIN) {
+ status.setText(R.string.cryptkeeper_wrong_pin);
+ } else if (passwordType == StorageManager.CRYPT_TYPE_PATTERN) {
+ status.setText(R.string.cryptkeeper_wrong_pattern);
+ } else {
+ status.setText(R.string.cryptkeeper_wrong_password);
}
}
+
+ if (mLockPatternView != null) {
+ mLockPatternView.setDisplayMode(DisplayMode.Wrong);
+ mLockPatternView.setEnabled(true);
+ }
+
+ // Reenable the password entry
+ if (mPasswordEntry != null) {
+ mPasswordEntry.setEnabled(true);
+ final InputMethodManager imm = (InputMethodManager) getSystemService(
+ Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(mPasswordEntry, 0);
+ setBackFunctionality(true);
+ }
}
}
@@ -329,6 +346,8 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
| StatusBarManager.DISABLE_SEARCH
| StatusBarManager.DISABLE_RECENT;
+ protected static final int MIN_LENGTH_BEFORE_REPORT = LockPatternUtils.MIN_LOCK_PATTERN_SIZE;
+
/** @return whether or not this Activity was started for debugging the UI only. */
private boolean isDebugView() {
return getIntent().hasExtra(EXTRA_FORCE_VIEW);
@@ -701,6 +720,11 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
}
}
+ private void fakeUnlockAttempt(View postingView) {
+ beginAttempt();
+ postingView.postDelayed(mFakeUnlockAttemptRunnable, FAKE_ATTEMPT_DELAY);
+ }
+
protected LockPatternView.OnPatternListener mChooseNewLockPatternListener =
new LockPatternView.OnPatternListener() {
@@ -716,7 +740,12 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
@Override
public void onPatternDetected(List<LockPatternView.Cell> pattern) {
mLockPatternView.setEnabled(false);
- new DecryptTask().execute(LockPatternUtils.patternToString(pattern));
+ if (pattern.size() >= MIN_LENGTH_BEFORE_REPORT) {
+ new DecryptTask().execute(LockPatternUtils.patternToString(pattern));
+ } else {
+ // Allow user to make as many of these as they want.
+ fakeUnlockAttempt(mLockPatternView);
+ }
}
@Override
@@ -873,7 +902,12 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
mPasswordEntry.setEnabled(false);
setBackFunctionality(false);
- new DecryptTask().execute(password);
+ if (password.length() >= LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
+ new DecryptTask().execute(password);
+ } else {
+ // Allow user to make as many of these as they want.
+ fakeUnlockAttempt(mPasswordEntry);
+ }
return true;
}