Prevent factory reset for short passwords in CryptKeeper

automerge: 8fca3fc

* commit '8fca3fcc06cfa7c4baf16b3bc53c4e52c9678fbb':
  Prevent factory reset for short passwords in CryptKeeper
This commit is contained in:
Paul Crowley
2014-11-19 20:49:13 +00:00
committed by android-build-merger

View File

@@ -137,6 +137,17 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
// how long we wait to clear a right pattern // how long we wait to clear a right pattern
private static final int RIGHT_PATTERN_CLEAR_TIMEOUT_MS = 500; private static final int RIGHT_PATTERN_CLEAR_TIMEOUT_MS = 500;
// 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 Runnable mClearPatternRunnable = new Runnable() { private Runnable mClearPatternRunnable = new Runnable() {
public void run() { public void run() {
mLockPatternView.clearPattern(); mLockPatternView.clearPattern();
@@ -200,43 +211,47 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
showFactoryReset(true); showFactoryReset(true);
return; return;
} else { } else {
// Wrong entry. Handle pattern case. handleBadAttempt(failedAttempts);
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);
int remainingAttempts = MAX_FAILED_ATTEMPTS - failedAttempts; private void handleBadAttempt(Integer failedAttempts) {
if (remainingAttempts < COOL_DOWN_ATTEMPTS) { // Wrong entry. Handle pattern case.
CharSequence warningTemplate = getText(R.string.crypt_keeper_warn_wipe); if (mLockPatternView != null) {
CharSequence warning = TextUtils.expandTemplate(warningTemplate, mLockPatternView.setDisplayMode(DisplayMode.Wrong);
Integer.toString(remainingAttempts)); mLockPatternView.removeCallbacks(mClearPatternRunnable);
status.setText(warning); mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
} else { }
status.setText(R.string.try_again); if ((failedAttempts % COOL_DOWN_ATTEMPTS) == 0) {
} mCooldown = COOL_DOWN_INTERVAL;
cooldown();
} else {
final TextView status = (TextView) findViewById(R.id.status);
if (mLockPatternView != null) { int remainingAttempts = MAX_FAILED_ATTEMPTS - failedAttempts;
mLockPatternView.setDisplayMode(DisplayMode.Wrong); if (remainingAttempts < COOL_DOWN_ATTEMPTS) {
} CharSequence warningTemplate = getText(R.string.crypt_keeper_warn_wipe);
// Reenable the password entry CharSequence warning = TextUtils.expandTemplate(warningTemplate,
if (mPasswordEntry != null) { Integer.toString(remainingAttempts));
mPasswordEntry.setEnabled(true); status.setText(warning);
final InputMethodManager imm = (InputMethodManager) getSystemService( } else {
Context.INPUT_METHOD_SERVICE); status.setText(R.string.try_again);
imm.showSoftInput(mPasswordEntry, 0); }
setBackFunctionality(true);
} if (mLockPatternView != null) {
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);
}
if (mLockPatternView != null) {
mLockPatternView.setEnabled(true);
} }
} }
} }
@@ -307,6 +322,8 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
| StatusBarManager.DISABLE_SEARCH | StatusBarManager.DISABLE_SEARCH
| StatusBarManager.DISABLE_RECENT; | 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. */ /** @return whether or not this Activity was started for debugging the UI only. */
private boolean isDebugView() { private boolean isDebugView() {
return getIntent().hasExtra(EXTRA_FORCE_VIEW); return getIntent().hasExtra(EXTRA_FORCE_VIEW);
@@ -679,6 +696,10 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
} }
} }
private void fakeUnlockAttempt(View postingView) {
postingView.postDelayed(mFakeUnlockAttemptRunnable, FAKE_ATTEMPT_DELAY);
}
protected LockPatternView.OnPatternListener mChooseNewLockPatternListener = protected LockPatternView.OnPatternListener mChooseNewLockPatternListener =
new LockPatternView.OnPatternListener() { new LockPatternView.OnPatternListener() {
@@ -694,7 +715,12 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
@Override @Override
public void onPatternDetected(List<LockPatternView.Cell> pattern) { public void onPatternDetected(List<LockPatternView.Cell> pattern) {
mLockPatternView.setEnabled(false); 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 @Override
@@ -851,8 +877,13 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
mPasswordEntry.setEnabled(false); mPasswordEntry.setEnabled(false);
setBackFunctionality(false); setBackFunctionality(false);
Log.d(TAG, "Attempting to send command to decrypt"); if (password.length() >= LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
new DecryptTask().execute(password); Log.d(TAG, "Attempting to send command to decrypt");
new DecryptTask().execute(password);
} else {
// Allow user to make as many of these as they want.
fakeUnlockAttempt(mPasswordEntry);
}
return true; return true;
} }