Skip to content

Commit

Permalink
fix: strongbox unavailable on galaxy s24 [WPB-9639] (#2863)
Browse files Browse the repository at this point in the history
  • Loading branch information
saleniuk authored Jul 8, 2024
1 parent e497778 commit 26d21ef
Show file tree
Hide file tree
Showing 13 changed files with 72 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.resetMain
Expand All @@ -51,7 +50,7 @@ class EncryptedSettingsBuilderTest {
val context = ApplicationProvider.getApplicationContext<Context>()
(1..5000).map {
launch() {
EncryptedSettingsBuilder.build(
buildSettings(
options = SettingOptions.UserSettings(
shouldEncryptData = true,
userIDEntity = UserIDEntity(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,57 +24,63 @@ import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import com.russhwolf.settings.Settings
import com.russhwolf.settings.SharedPreferencesSettings
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

private fun SettingOptions.keyAlias(): String = when (this) {
is SettingOptions.AppSettings -> "_app_settings_master_key_"
is SettingOptions.UserSettings -> "_${this.fileName}_master_key_"
}

internal actual object EncryptedSettingsBuilder {
private fun getOrCreateMasterKey(
context: Context,
keyAlias: String
): MasterKey =
MasterKey
.Builder(context, keyAlias)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.setRequestStrongBoxBacked(true)
.build()
private val lock = Object()

actual fun build(
options: SettingOptions,
param: EncryptedSettingsPlatformParam
): Settings = synchronized(this) {
val settings = if (options.shouldEncryptData) {
encryptedSharedPref(options, param, false)
} else {
param.appContext.getSharedPreferences(options.fileName, Context.MODE_PRIVATE)
}
SharedPreferencesSettings(settings, false)
internal actual fun buildSettings(
options: SettingOptions,
param: EncryptedSettingsPlatformParam
): Settings = synchronized(lock) {
val settings = if (options.shouldEncryptData) {
encryptedSharedPref(options, param, false)
} else {
param.appContext.getSharedPreferences(options.fileName, Context.MODE_PRIVATE)
}
SharedPreferencesSettings(settings, false)
}

private fun encryptedSharedPref(
options: SettingOptions,
param: EncryptedSettingsPlatformParam,
isRetry: Boolean
): SharedPreferences {
@Suppress("TooGenericExceptionCaught")
return try {
val masterKey = getOrCreateMasterKey(param.appContext, options.keyAlias())
EncryptedSharedPreferences.create(
param.appContext,
options.fileName,
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
} catch (e: Exception) {
if (isRetry) {
throw e
}
private fun getOrCreateMasterKey(
context: Context,
keyAlias: String
): MasterKey =
MasterKey
.Builder(context, keyAlias)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.setRequestStrongBoxBacked(true)
.build()

private fun encryptedSharedPref(
options: SettingOptions,
param: EncryptedSettingsPlatformParam,
isRetry: Boolean
): SharedPreferences {
@Suppress("TooGenericExceptionCaught")
return try {
val masterKey = getOrCreateMasterKey(param.appContext, options.keyAlias())
EncryptedSharedPreferences.create(
param.appContext,
options.fileName,
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
} catch (e: Exception) {
if (isRetry) {
throw e
} else runBlocking {
delay(RETRY_DELAY)
encryptedSharedPref(options, param, true)
}
}
}

internal actual class EncryptedSettingsPlatformParam(val appContext: Context)

private const val RETRY_DELAY = 200L
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import com.wire.kalium.persistence.dbPassphrase.PassphraseStorageImpl
actual class GlobalPrefProvider(context: Context, shouldEncryptData: Boolean = true) {

private val encryptedSettingsHolder: KaliumPreferences = KaliumPreferencesSettings(
EncryptedSettingsBuilder.build(SettingOptions.AppSettings(shouldEncryptData), EncryptedSettingsPlatformParam(context))
buildSettings(SettingOptions.AppSettings(shouldEncryptData), EncryptedSettingsPlatformParam(context))
)

actual val authTokenStorage: AuthTokenStorage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ actual class UserPrefBuilder(
) {
private val encryptedSettingsHolder =
KaliumPreferencesSettings(
EncryptedSettingsBuilder.build(
buildSettings(
SettingOptions.UserSettings(shouldEncryptData = shouldEncryptData, userIDEntity = userId),
EncryptedSettingsPlatformParam(context)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,9 @@ import com.russhwolf.settings.KeychainSettings
import com.russhwolf.settings.Settings

@OptIn(ExperimentalSettingsImplementation::class)
internal actual object EncryptedSettingsBuilder {
actual fun build(
options: SettingOptions,
param: EncryptedSettingsPlatformParam
): Settings = KeychainSettings(param.serviceName)
}
internal actual fun buildSettings(
options: SettingOptions,
param: EncryptedSettingsPlatformParam
): Settings = KeychainSettings(param.serviceName)

internal actual class EncryptedSettingsPlatformParam(val serviceName: String)
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ actual class GlobalPrefProvider(
) {
private val kaliumPref =
KaliumPreferencesSettings(
EncryptedSettingsBuilder.build(
buildSettings(
SettingOptions.AppSettings(shouldEncryptData),
EncryptedSettingsPlatformParam(rootPath)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ actual class UserPrefBuilder(

private val kaliumPreferences =
KaliumPreferencesSettings(
EncryptedSettingsBuilder.build(SettingOptions.UserSettings(shouldEncryptData, userId), EncryptedSettingsPlatformParam(rootPath))
buildSettings(SettingOptions.UserSettings(shouldEncryptData, userId), EncryptedSettingsPlatformParam(rootPath))
)

actual val lastRetrievedNotificationEventStorage: LastRetrievedNotificationEventStorage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ internal sealed class SettingOptions {
}
}

internal expect object EncryptedSettingsBuilder {
fun build(options: SettingOptions, param: EncryptedSettingsPlatformParam): Settings
}
internal expect fun buildSettings(options: SettingOptions, param: EncryptedSettingsPlatformParam): Settings

internal expect class EncryptedSettingsPlatformParam
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@ import com.russhwolf.settings.Settings
import com.russhwolf.settings.StorageSettings
import org.w3c.dom.Storage

internal actual object EncryptedSettingsBuilder {
actual fun build(
options: SettingOptions,
param: EncryptedSettingsPlatformParam
): Settings = StorageSettings(param.storage)
}
internal actual fun buildSettings(
options: SettingOptions,
param: EncryptedSettingsPlatformParam
): Settings = StorageSettings(param.storage)

internal actual class EncryptedSettingsPlatformParam(val storage: Storage)
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,14 @@ private fun createOrLoad(rootPath: String, file: File): Properties {
/**
* the java implementation is not yet encrypted
*/
internal actual object EncryptedSettingsBuilder {
actual fun build(
options: SettingOptions,
param: EncryptedSettingsPlatformParam
): Settings {
val file: File = File(Paths.get(param.rootPath, options.fileName).toString())
val properties = createOrLoad(param.rootPath, file)
internal actual fun buildSettings(
options: SettingOptions,
param: EncryptedSettingsPlatformParam
): Settings {
val file = File(Paths.get(param.rootPath, options.fileName).toString())
val properties = createOrLoad(param.rootPath, file)

return PropertiesSettings(properties) { onModify(it, file) }
}
return PropertiesSettings(properties) { onModify(it, file) }
}

internal actual class EncryptedSettingsPlatformParam(val rootPath: String)
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ actual class GlobalPrefProvider(
) {
private val kaliumPref =
KaliumPreferencesSettings(
EncryptedSettingsBuilder.build(
buildSettings(
SettingOptions.AppSettings(shouldEncryptData),
EncryptedSettingsPlatformParam(rootPath)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ actual class UserPrefBuilder(

private val kaliumPref =
KaliumPreferencesSettings(
EncryptedSettingsBuilder.build(
buildSettings(
SettingOptions.UserSettings(shouldEncryptData, userId),
EncryptedSettingsPlatformParam(rootPath)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
package com.wire.kalium.persistence

import com.wire.kalium.persistence.dao.QualifiedIDEntity
import com.wire.kalium.persistence.kmmSettings.EncryptedSettingsBuilder
import com.wire.kalium.persistence.kmmSettings.EncryptedSettingsPlatformParam
import com.wire.kalium.persistence.kmmSettings.SettingOptions
import com.wire.kalium.persistence.kmmSettings.buildSettings
import org.junit.Test
import java.io.FileInputStream
import java.nio.file.Files
Expand All @@ -37,7 +37,7 @@ class EncryptedSettingsBuilderTest {
val rootPath = Files.createTempDirectory("test-rootPath").toString()
val userIDEntity = QualifiedIDEntity("user", "domain")

val encryptedSettings = EncryptedSettingsBuilder.build(
val encryptedSettings = buildSettings(
SettingOptions.UserSettings(
shouldEncryptData = false,
userIDEntity
Expand All @@ -57,7 +57,7 @@ class EncryptedSettingsBuilderTest {
fun givenJvmPropertiesSettings_WhenAppSettingsAreChanged_ThenItIsStoredInFile() {
val rootPath = Files.createTempDirectory("test-rootPath").toString()

val encryptedSettings = EncryptedSettingsBuilder.build(
val encryptedSettings = buildSettings(
SettingOptions.AppSettings(
shouldEncryptData = false
),
Expand Down

0 comments on commit 26d21ef

Please sign in to comment.