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
This commit is contained in:
Paul Crowley
2014-11-07 00:52:57 -08:00
parent c44ad35e51
commit 2555e5f104

View File

@@ -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);
handleBadAttempt(failedAttempts);
}
}
}
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);
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 ((failedAttempts % COOL_DOWN_ATTEMPTS) == 0) {
mCooldown = COOL_DOWN_INTERVAL;
cooldown();
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 {
final TextView status = (TextView) findViewById(R.id.status);
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);
}
// 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);
}
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;
}