From 8c3425123d9aa54b3e656817130e500228433f21 Mon Sep 17 00:00:00 2001 From: Grisha Kruglov Date: Mon, 4 Nov 2019 17:12:26 -0800 Subject: [PATCH] [components] Use a more descriptive/accurate name for the encrypted sharedprefs wrapper --- ...dPreferences.kt => SecureAbove22Preferences.kt} | 26 ++++++---------------- ...ncesTest.kt => SecureAbove22PreferencesTest.kt} | 11 ++++----- .../java/mozilla/components/service/fxa/Config.kt | 4 ++-- .../service/fxa/sync/WorkManagerSyncManager.kt | 13 ++--------- .../android/android-components/docs/changelog.md | 2 +- .../mozilla/samples/dataprotect/MainActivity.kt | 6 ++--- .../samples/dataprotect/ProtectedDataAdapter.kt | 4 ++-- 7 files changed, 23 insertions(+), 43 deletions(-) rename mobile/android/android-components/components/lib/dataprotect/src/main/java/mozilla/components/lib/dataprotect/{KeySharedPreferences.kt => SecureAbove22Preferences.kt} (86%) rename mobile/android/android-components/components/lib/dataprotect/src/test/java/mozilla/components/lib/dataprotect/{KeySharedPreferencesTest.kt => SecureAbove22PreferencesTest.kt} (90%) diff --git a/mobile/android/android-components/components/lib/dataprotect/src/main/java/mozilla/components/lib/dataprotect/KeySharedPreferences.kt b/mobile/android/android-components/components/lib/dataprotect/src/main/java/mozilla/components/lib/dataprotect/SecureAbove22Preferences.kt similarity index 86% rename from mobile/android/android-components/components/lib/dataprotect/src/main/java/mozilla/components/lib/dataprotect/KeySharedPreferences.kt rename to mobile/android/android-components/components/lib/dataprotect/src/main/java/mozilla/components/lib/dataprotect/SecureAbove22Preferences.kt index 547aeb29cae5..9fada16567c1 100644 --- a/mobile/android/android-components/components/lib/dataprotect/src/main/java/mozilla/components/lib/dataprotect/KeySharedPreferences.kt +++ b/mobile/android/android-components/components/lib/dataprotect/src/main/java/mozilla/components/lib/dataprotect/SecureAbove22Preferences.kt @@ -14,8 +14,6 @@ import mozilla.components.support.base.log.logger.Logger import java.nio.charset.StandardCharsets import java.security.GeneralSecurityException -private const val BASE_64_FLAGS = Base64.URL_SAFE or Base64.NO_PADDING - /** * A wrapper around [SharedPreferences] which encrypts contents on supported API versions (23+). * Otherwise, this simply delegates to [SharedPreferences]. @@ -24,30 +22,20 @@ private const val BASE_64_FLAGS = Base64.URL_SAFE or Base64.NO_PADDING * in which case previously stored values will be lost as well. Applications are encouraged to instrument such events. * * @param context A [Context], used for accessing [SharedPreferences]. - * @param keystore An optional [Keystore]: required when running on API23+, expected as `null` otherwise. */ -class KeySharedPreferences( - context: Context, - private val keystore: Keystore? = null -) { - +class SecureAbove22Preferences(context: Context) { companion object { const val KEY_PREFERENCES = "key_preferences" + private const val BASE_64_FLAGS = Base64.URL_SAFE or Base64.NO_PADDING } - init { - if (Build.VERSION.SDK_INT < M) { - require(keystore == null) { - "Keystore isn't supported for pre-23 API versions" - } - } else { - require(keystore != null) { - "Keystore must be configured for 23+ API versions" - } - } + private val keystore: Keystore? = if (Build.VERSION.SDK_INT < M) { + null + } else { + Keystore(context.packageName) } - private val logger = Logger("KeySharedPreferences") + private val logger = Logger("SecureAbove22Preferences") private val prefs = context.getSharedPreferences(KEY_PREFERENCES, MODE_PRIVATE) /** diff --git a/mobile/android/android-components/components/lib/dataprotect/src/test/java/mozilla/components/lib/dataprotect/KeySharedPreferencesTest.kt b/mobile/android/android-components/components/lib/dataprotect/src/test/java/mozilla/components/lib/dataprotect/SecureAbove22PreferencesTest.kt similarity index 90% rename from mobile/android/android-components/components/lib/dataprotect/src/test/java/mozilla/components/lib/dataprotect/KeySharedPreferencesTest.kt rename to mobile/android/android-components/components/lib/dataprotect/src/test/java/mozilla/components/lib/dataprotect/SecureAbove22PreferencesTest.kt index c924f5f12117..68d49e711232 100644 --- a/mobile/android/android-components/components/lib/dataprotect/src/test/java/mozilla/components/lib/dataprotect/KeySharedPreferencesTest.kt +++ b/mobile/android/android-components/components/lib/dataprotect/src/test/java/mozilla/components/lib/dataprotect/SecureAbove22PreferencesTest.kt @@ -15,11 +15,11 @@ import org.robolectric.annotation.Config import java.security.Security @RunWith(AndroidJUnit4::class) -class KeySharedPreferencesTest { +class SecureAbove22PreferencesTest { @Config(sdk = [21]) @Test fun `CRUD tests API level 21 unencrypted`() { - val storage = KeySharedPreferences(testContext) + val storage = SecureAbove22Preferences(testContext) // no keys assertNull(storage.getString("hello")) @@ -47,7 +47,7 @@ class KeySharedPreferencesTest { @Config(sdk = [22]) @Test fun `CRUD tests API level 22 unencrypted`() { - val storage = KeySharedPreferences(testContext) + val storage = SecureAbove22Preferences(testContext) // no keys assertNull(storage.getString("hello")) @@ -73,12 +73,13 @@ class KeySharedPreferencesTest { } @Ignore("https://github.com/mozilla-mobile/android-components/issues/4956") + @Config(sdk = [23]) @Test fun `CRUD tests API level 23+ encrypted`() { - // TODO find out what this is. + // TODO find out what this is; lockwise tests set it. Security.setProperty("crypto.policy", "unlimited") - val storage = KeySharedPreferences(testContext, Keystore("test-keys", true, MockStoreWrapper())) + val storage = SecureAbove22Preferences(testContext) // no keys assertNull(storage.getString("hello")) diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/Config.kt b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/Config.kt index a56350ad8598..4b554e58ae56 100644 --- a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/Config.kt +++ b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/Config.kt @@ -8,7 +8,7 @@ import mozilla.components.concept.sync.DeviceCapability import mozilla.components.concept.sync.DeviceType import mozilla.components.service.fxa.manager.FxaAccountManager import mozilla.components.service.fxa.sync.GlobalSyncableStoreProvider -import mozilla.components.lib.dataprotect.KeySharedPreferences +import mozilla.components.lib.dataprotect.SecureAbove22Preferences typealias ServerConfig = mozilla.appservices.fxaclient.Config @@ -68,7 +68,7 @@ sealed class SyncEngine(val nativeName: String) { /** * A 'logins/passwords' engine. When using this engine, make sure to set an encryption key used to unlock the store - * as 'passwords_key' via [KeySharedPreferences]. + * as 'passwords_key' via [SecureAbove22Preferences]. */ object Passwords : SyncEngine("passwords") diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/sync/WorkManagerSyncManager.kt b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/sync/WorkManagerSyncManager.kt index 05991f736fd5..7409ac95614e 100644 --- a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/sync/WorkManagerSyncManager.kt +++ b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/sync/WorkManagerSyncManager.kt @@ -5,7 +5,6 @@ package mozilla.components.service.fxa.sync import android.content.Context -import android.os.Build import androidx.annotation.UiThread import androidx.work.BackoffPolicy import androidx.work.Constraints @@ -27,8 +26,7 @@ import mozilla.appservices.syncmanager.SyncManager as RustSyncManager import mozilla.components.concept.sync.AuthException import mozilla.components.concept.sync.AuthExceptionType import mozilla.components.concept.sync.LockableStore -import mozilla.components.lib.dataprotect.KeySharedPreferences -import mozilla.components.lib.dataprotect.Keystore +import mozilla.components.lib.dataprotect.SecureAbove22Preferences import mozilla.components.service.fxa.FxaDeviceSettingsCache import mozilla.components.service.fxa.SyncAuthInfoCache import mozilla.components.service.fxa.SyncConfig @@ -309,14 +307,7 @@ class WorkManagerSyncWorker( // If password storage is configured to be synced, we need to make sure it's decrypted during a sync. passwordStore?.let { - val keySharedPreferences = KeySharedPreferences( - context, - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - Keystore(context.packageName) - } else { - null - } - ) + val keySharedPreferences = SecureAbove22Preferences(context) (it as LockableStore).ensureUnlocked( keySharedPreferences.getString("passwords_key") ?: throw IllegalStateException( diff --git a/mobile/android/android-components/docs/changelog.md b/mobile/android/android-components/docs/changelog.md index 7c6676ed9a5c..4661972fd36d 100644 --- a/mobile/android/android-components/docs/changelog.md +++ b/mobile/android/android-components/docs/changelog.md @@ -53,7 +53,7 @@ permalink: /changelog/ * Adds support for Web Share API using `ShareDelegate`. * **lib-dataprotect** - * Added new `KeySharedPreferences` helper class, which is an encryption-aware wrapper for `SharedPreferences`. Only actually encrypts stored values when running on API23+. + * Added new `SecureAbove22Preferences` helper class, which is an encryption-aware wrapper for `SharedPreferences`. Only actually encrypts stored values when running on API23+. * **service-firefox-accounts** * Support for keeping `SyncEngine.Passwords` engine unlocked during sync. diff --git a/mobile/android/android-components/samples/dataprotect/src/main/java/org/mozilla/samples/dataprotect/MainActivity.kt b/mobile/android/android-components/samples/dataprotect/src/main/java/org/mozilla/samples/dataprotect/MainActivity.kt index fbbf68c086aa..43954329415f 100644 --- a/mobile/android/android-components/samples/dataprotect/src/main/java/org/mozilla/samples/dataprotect/MainActivity.kt +++ b/mobile/android/android-components/samples/dataprotect/src/main/java/org/mozilla/samples/dataprotect/MainActivity.kt @@ -9,7 +9,7 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import mozilla.components.lib.dataprotect.KeySharedPreferences +import mozilla.components.lib.dataprotect.SecureAbove22Preferences import mozilla.components.lib.dataprotect.Keystore import org.mozilla.samples.dataprotect.Constants.KEYSTORE_LABEL @@ -24,7 +24,7 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - val prefs = KeySharedPreferences( + val prefs = SecureAbove22Preferences( this, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) Keystore(KEYSTORE_LABEL) else null ) @@ -41,7 +41,7 @@ class MainActivity : AppCompatActivity() { } } - private fun prepareProtectedData(prefs: KeySharedPreferences) { + private fun prepareProtectedData(prefs: SecureAbove22Preferences) { for (datakey in itemKeys) { val plain = "value for $datakey" prefs.putString(datakey, plain) diff --git a/mobile/android/android-components/samples/dataprotect/src/main/java/org/mozilla/samples/dataprotect/ProtectedDataAdapter.kt b/mobile/android/android-components/samples/dataprotect/src/main/java/org/mozilla/samples/dataprotect/ProtectedDataAdapter.kt index 717375b4ab66..efeacc48d07f 100644 --- a/mobile/android/android-components/samples/dataprotect/src/main/java/org/mozilla/samples/dataprotect/ProtectedDataAdapter.kt +++ b/mobile/android/android-components/samples/dataprotect/src/main/java/org/mozilla/samples/dataprotect/ProtectedDataAdapter.kt @@ -9,10 +9,10 @@ import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.recyclerview.widget.RecyclerView -import mozilla.components.lib.dataprotect.KeySharedPreferences +import mozilla.components.lib.dataprotect.SecureAbove22Preferences class ProtectedDataAdapter( - private val prefs: KeySharedPreferences, + private val prefs: SecureAbove22Preferences, private val itemKeys: List ) : RecyclerView.Adapter() { override fun getItemCount(): Int = itemKeys.size -- 2.11.4.GIT