diff options
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(); |