From d97252d8d66c4927b2acf54c9b3ee290eac5a992 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Mon, 1 Jul 2013 10:15:36 -0700 Subject: [PATCH] Add ability to disable local encryption passphrase. --- AndroidManifest.xml | 1 - res/layout/change_passphrase_activity.xml | 1 + res/values/strings.xml | 7 ++ res/xml/preferences.xml | 51 +++++----- .../ApplicationPreferencesActivity.java | 96 +++++++++++-------- .../securesms/PassphraseChangeActivity.java | 48 ++++++++-- .../securesms/crypto/MasterSecretUtil.java | 22 ++++- .../securesms/service/KeyCachingService.java | 56 +++++++++-- 8 files changed, 189 insertions(+), 93 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 165167d7bd..e40aff8c11 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -126,7 +126,6 @@ diff --git a/res/values/strings.xml b/res/values/strings.xml index fc814a5a69..3699a7c274 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -14,6 +14,13 @@ Are you sure you would like to immediately trim all conversation threads to the %s most recent messages? Delete My + Disable storage encryption? + + Warning, this will disable storage encryption for all messages and keys. Your encrypted + sessions will continue to function, but anyone with physical access to your device will be + able to access them. + + Disable diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index b24af3ef9b..c5d79c3e40 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -115,23 +115,30 @@ - - - - - - + + + + + + + @@ -142,16 +149,6 @@ android:title="@string/preferences__complete_key_exchanges" android:summary="@string/preferences__automatically_complete_key_exchanges_for_new_sessions_or_for_existing_sessions_with_the_same_identity_key" /> - - - - - - () { @Override - public void run() { + protected Void doInBackground(Void... params) { if (!DatabaseUpgradeActivity.isUpdate(KeyCachingService.this)) { DecryptingQueue.schedulePendingDecrypts(KeyCachingService.this, masterSecret); MessageNotifier.updateNotification(KeyCachingService.this, masterSecret); } + return null; } - }.start(); + }.execute(); } @Override - public void onStart(Intent intent, int startId) { - if (intent == null) return; + public int onStartCommand(Intent intent, int flags, int startId) { + if (intent == null) return START_NOT_STICKY; if (intent.getAction() != null && intent.getAction().equals(CLEAR_KEY_ACTION)) handleClearKey(); @@ -99,12 +105,26 @@ public class KeyCachingService extends Service { handleActivityStopped(); else if (intent.getAction() != null && intent.getAction().equals(PASSPHRASE_EXPIRED_EVENT)) handleClearKey(); + else if (intent.getAction() != null && intent.getAction().equals(DISABLE_ACTION)) + handleDisableService(); + + return START_NOT_STICKY; } @Override public void onCreate() { super.onCreate(); - pending = PendingIntent.getService(this, 0, new Intent(PASSPHRASE_EXPIRED_EVENT, null, this, KeyCachingService.class), 0); + this.pending = PendingIntent.getService(this, 0, new Intent(PASSPHRASE_EXPIRED_EVENT, null, + this, KeyCachingService.class), 0); + + if (isPassphraseDisabled()) { + try { + MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(this, MasterSecretUtil.UNENCRYPTED_PASSPHRASE); + setMasterSecret(masterSecret); + } catch (InvalidPassphraseException e) { + Log.w("KeyCachingService", e); + } + } } @Override @@ -138,19 +158,25 @@ public class KeyCachingService extends Service { sendBroadcast(intent, KEY_PERMISSION); - new Thread() { + new AsyncTask() { @Override - public void run() { + protected Void doInBackground(Void... params) { MessageNotifier.updateNotification(KeyCachingService.this, null); + return null; } - }.start(); + }.execute(); + } + + private void handleDisableService() { + if (isPassphraseDisabled()) + stopForeground(true); } private void startTimeoutIfAppropriate() { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); boolean timeoutEnabled = sharedPreferences.getBoolean(ApplicationPreferencesActivity.PASSPHRASE_TIMEOUT_PREF, false); - if ((activitiesRunning == 0) && (this.masterSecret != null) && timeoutEnabled) { + if ((activitiesRunning == 0) && (this.masterSecret != null) && timeoutEnabled && !isPassphraseDisabled()) { long timeoutMinutes = sharedPreferences.getInt(ApplicationPreferencesActivity.PASSPHRASE_TIMEOUT_INTERVAL_PREF, 60 * 5); long timeoutMillis = timeoutMinutes * 60 * 1000; @@ -195,6 +221,11 @@ public class KeyCachingService extends Service { } private void foregroundService() { + if (isPassphraseDisabled()) { + stopForeground(true); + return; + } + if (Build.VERSION.SDK_INT >= 11) foregroundServiceModern(); else foregroundServiceLegacy(); } @@ -209,6 +240,11 @@ public class KeyCachingService extends Service { sendBroadcast(intent, KEY_PERMISSION); } + private boolean isPassphraseDisabled() { + return PreferenceManager.getDefaultSharedPreferences(this) + .getBoolean(ApplicationPreferencesActivity.DISABLE_PASSPHRASE_PREF, false); + } + @Override public IBinder onBind(Intent arg0) {