summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lawrence <paullawrence@google.com>2014-08-21 08:43:41 -0700
committerPaul Lawrence <paullawrence@google.com>2014-08-22 11:22:43 -0700
commit32d06732cdb7ee653a58e49a4dab13a780513db5 (patch)
treee7915fe34e031d09fa3e746f3504b22163b7ef99
parentf9220b39533d18b6c79099c32522b3ff712ff89b (diff)
downloadframeworks_base-32d06732cdb7ee653a58e49a4dab13a780513db5.zip
frameworks_base-32d06732cdb7ee653a58e49a4dab13a780513db5.tar.gz
frameworks_base-32d06732cdb7ee653a58e49a4dab13a780513db5.tar.bz2
Fix adb backup for encrypted case
New behavior. Backup no longer uses the encryption password. This is in part because that is hard with patterns, in part because it is a security issue - the off line backup is much easier to brute force than the phone. Instead, we simply insist on an encryption password if your device is encrypted and locked. Bug: 17159330 Change-Id: Ia22f84722522abf0b569a3ef1e16ead5527c726d
-rw-r--r--packages/BackupRestoreConfirmation/res/values/strings.xml2
-rw-r--r--packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java28
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java81
3 files changed, 37 insertions, 74 deletions
diff --git a/packages/BackupRestoreConfirmation/res/values/strings.xml b/packages/BackupRestoreConfirmation/res/values/strings.xml
index 5c90fd0..3fb3fd4 100644
--- a/packages/BackupRestoreConfirmation/res/values/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values/strings.xml
@@ -44,6 +44,8 @@
<string name="backup_enc_password_text">Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:</string>
<!-- Text for message to user that they may optionally supply an encryption password to use for a full backup operation. -->
<string name="backup_enc_password_optional">If you wish to encrypt the full backup data, enter a password below:</string>
+ <!-- Text for message to user that they must supply an encryption password to use for a full backup operation because their phone is locked. -->
+ <string name="backup_enc_password_required">Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:</string>
<!-- Text for message to user when performing a full restore operation, explaining that they must enter the password originally used to encrypt the full backup data. -->
<string name="restore_enc_password_text">If the restore data is encrypted, please enter the password below:</string>
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index 82ac8cb..c2bb90c 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -28,6 +28,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.storage.IMountService;
+import android.os.storage.StorageManager;
import android.util.Log;
import android.util.Slog;
import android.view.View;
@@ -182,25 +183,14 @@ public class BackupRestoreConfirmation extends Activity {
// We vary the password prompt depending on whether one is predefined, and whether
// the device is encrypted.
mIsEncrypted = deviceIsEncrypted();
- if (mIsEncrypted) {
- Log.d(TAG, "Device is encrypted: requiring encryption pw");
- TextView pwPrompt = (TextView) findViewById(R.id.password_desc);
- // this password is mandatory; we hide the other options during backup
- if (layoutId == R.layout.confirm_backup) {
- pwPrompt.setText(R.string.device_encryption_backup_text);
- TextView tv = (TextView) findViewById(R.id.enc_password);
- tv.setVisibility(View.GONE);
- tv = (TextView) findViewById(R.id.enc_password_desc);
- tv.setVisibility(View.GONE);
- } else {
- pwPrompt.setText(R.string.device_encryption_restore_text);
- }
- } else if (!haveBackupPassword()) {
+ if (!haveBackupPassword()) {
curPwDesc.setVisibility(View.GONE);
mCurPassword.setVisibility(View.GONE);
if (layoutId == R.layout.confirm_backup) {
TextView encPwDesc = (TextView) findViewById(R.id.enc_password_desc);
- encPwDesc.setText(R.string.backup_enc_password_optional);
+ encPwDesc.setText(mIsEncrypted
+ ? R.string.backup_enc_password_required
+ : R.string.backup_enc_password_optional);
}
}
@@ -246,8 +236,7 @@ public class BackupRestoreConfirmation extends Activity {
mDidAcknowledge = true;
try {
- CharSequence encPassword = (mIsEncrypted)
- ? mCurPassword.getText() : mEncPassword.getText();
+ CharSequence encPassword = mEncPassword.getText();
mBackupManager.acknowledgeFullBackupOrRestore(mToken,
allow,
String.valueOf(mCurPassword.getText()),
@@ -261,7 +250,10 @@ public class BackupRestoreConfirmation extends Activity {
boolean deviceIsEncrypted() {
try {
- return (mMountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE);
+ return mMountService.getEncryptionState()
+ != IMountService.ENCRYPTION_STATE_NONE
+ && mMountService.getPasswordType()
+ != StorageManager.CRYPT_TYPE_DEFAULT;
} catch (Exception e) {
// If we can't talk to the mount service we have a serious problem; fail
// "secure" i.e. assuming that the device is encrypted.
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index b576324..ab02f4c 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -75,6 +75,7 @@ import android.os.UserHandle;
import android.os.WorkSource;
import android.os.Environment.UserEnvironment;
import android.os.storage.IMountService;
+import android.os.storage.StorageManager;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
@@ -1442,43 +1443,7 @@ public class BackupManagerService extends IBackupManager.Stub {
return array;
}
- // Backup password management
boolean passwordMatchesSaved(String algorithm, String candidatePw, int rounds) {
- // First, on an encrypted device we require matching the device pw
- final boolean isEncrypted;
- try {
- isEncrypted = (mMountService.getEncryptionState() !=
- IMountService.ENCRYPTION_STATE_NONE);
- if (isEncrypted) {
- if (DEBUG) {
- Slog.i(TAG, "Device encrypted; verifying against device data pw");
- }
- // 0 means the password validated
- // -2 means device not encrypted
- // Any other result is either password failure or an error condition,
- // so we refuse the match
- final int result = mMountService.verifyEncryptionPassword(candidatePw);
- if (result == 0) {
- if (MORE_DEBUG) Slog.d(TAG, "Pw verifies");
- return true;
- } else if (result != -2) {
- if (MORE_DEBUG) Slog.d(TAG, "Pw mismatch");
- return false;
- } else {
- // ...else the device is supposedly not encrypted. HOWEVER, the
- // query about the encryption state said that the device *is*
- // encrypted, so ... we may have a problem. Log it and refuse
- // the backup.
- Slog.e(TAG, "verified encryption state mismatch against query; no match allowed");
- return false;
- }
- }
- } catch (Exception e) {
- // Something went wrong talking to the mount service. This is very bad;
- // assume that we fail password validation.
- return false;
- }
-
if (mPasswordHash == null) {
// no current password case -- require that 'currentPw' be null or empty
if (candidatePw == null || "".equals(candidatePw)) {
@@ -1583,14 +1548,7 @@ public class BackupManagerService extends IBackupManager.Stub {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"hasBackupPassword");
- try {
- return (mMountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE)
- || (mPasswordHash != null && mPasswordHash.length() > 0);
- } catch (Exception e) {
- // If we can't talk to the mount service we have a serious problem; fail
- // "secure" i.e. assuming that we require a password
- return true;
- }
+ return mPasswordHash != null && mPasswordHash.length() > 0;
}
private boolean backupPasswordMatches(String currentPw) {
@@ -3321,6 +3279,20 @@ public class BackupManagerService extends IBackupManager.Stub {
}
}
+ boolean deviceIsEncrypted() {
+ try {
+ return mMountService.getEncryptionState()
+ != IMountService.ENCRYPTION_STATE_NONE
+ && mMountService.getPasswordType()
+ != StorageManager.CRYPT_TYPE_DEFAULT;
+ } catch (Exception e) {
+ // If we can't talk to the mount service we have a serious problem; fail
+ // "secure" i.e. assuming that the device is encrypted.
+ Slog.e(TAG, "Unable to communicate with mount service: " + e.getMessage());
+ return true;
+ }
+ }
+
// Full backup task variant used for adb backup
class PerformAdbBackupTask extends FullBackupTask {
FullBackupEngine mBackupEngine;
@@ -3338,7 +3310,7 @@ public class BackupManagerService extends IBackupManager.Stub {
ArrayList<String> mPackages;
String mCurrentPassword;
String mEncryptPassword;
-
+
PerformAdbBackupTask(ParcelFileDescriptor fd, IFullBackupRestoreObserver observer,
boolean includeApks, boolean includeObbs, boolean includeShared,
boolean doWidgets, String curPassword, String encryptPassword, boolean doAllApps,
@@ -3535,6 +3507,13 @@ public class BackupManagerService extends IBackupManager.Stub {
PackageInfo pkg = null;
try {
boolean encrypting = (mEncryptPassword != null && mEncryptPassword.length() > 0);
+
+ // Only allow encrypted backups of encrypted devices
+ if (deviceIsEncrypted() && !encrypting) {
+ Slog.e(TAG, "Unencrypted backup of encrypted device; aborting");
+ return;
+ }
+
OutputStream finalOutput = ofstream;
// Verify that the given password matches the currently-active
@@ -8315,17 +8294,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
params.observer = observer;
params.curPassword = curPassword;
- boolean isEncrypted;
- try {
- isEncrypted = (mMountService.getEncryptionState() !=
- IMountService.ENCRYPTION_STATE_NONE);
- if (isEncrypted) Slog.w(TAG, "Device is encrypted; forcing enc password");
- } catch (RemoteException e) {
- // couldn't contact the mount service; fail "safe" and assume encryption
- Slog.e(TAG, "Unable to contact mount service!");
- isEncrypted = true;
- }
- params.encryptPassword = (isEncrypted) ? curPassword : encPpassword;
+ params.encryptPassword = encPpassword;
if (DEBUG) Slog.d(TAG, "Sending conf message with verb " + verb);
mWakelock.acquire();