diff options
author | Paul Crowley <paulcrowley@google.com> | 2014-11-07 00:52:57 -0800 |
---|---|---|
committer | Paul Crowley <paulcrowley@google.com> | 2014-11-08 01:43:45 +0000 |
commit | 2555e5f1040984a3422c5a4db43421e87d4ca0ce (patch) | |
tree | 158e1755b83d16d7f1d2944029915ca60785d752 /src/com/android/settings/CryptKeeper.java | |
parent | c44ad35e51db79721821817e1b8e52dce632d2bf (diff) | |
download | packages_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.java | 140 |
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; } |