From b29232b03e13ca5c6987b7fe5f9c59d43e72559a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20M=C3=B6ller?= <jakob.moeller@sap.com> Date: Tue, 2 Jun 2020 12:12:59 +0200 Subject: [PATCH] Switch the DB Password to use the KeyStore MasterKey (#98) Signed-off-by: d067928 <jakob.moeller@sap.com> --- .../rki/coronawarnapp/storage/AppDatabase.kt | 7 ++---- .../de/rki/coronawarnapp/storage/LocalData.kt | 21 ------------------ .../coronawarnapp/util/DataRetentionHelper.kt | 2 -- .../util/security/SecurityHelper.kt | 22 +++++++++++++++++++ 4 files changed, 24 insertions(+), 28 deletions(-) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/AppDatabase.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/AppDatabase.kt index f6ec3ec63..15e12326f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/AppDatabase.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/AppDatabase.kt @@ -10,9 +10,9 @@ import de.rki.coronawarnapp.storage.keycache.KeyCacheEntity import de.rki.coronawarnapp.storage.tracing.TracingIntervalDao import de.rki.coronawarnapp.storage.tracing.TracingIntervalEntity import de.rki.coronawarnapp.util.Converters +import de.rki.coronawarnapp.util.security.SecurityHelper import net.sqlcipher.database.SQLiteDatabase import net.sqlcipher.database.SupportFactory -import java.util.UUID @Database( entities = [ExposureSummaryEntity::class, KeyCacheEntity::class, TracingIntervalEntity::class], @@ -39,11 +39,8 @@ abstract class AppDatabase : RoomDatabase() { fun resetInstance(context: Context) = { instance = null }.also { getInstance(context) } private fun buildDatabase(context: Context): AppDatabase { - if (LocalData.databasePassword() == null) { - LocalData.databasePassword(UUID.randomUUID().toString().toCharArray()) - } return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME) - .openHelperFactory(SupportFactory(SQLiteDatabase.getBytes(LocalData.databasePassword()))) + .openHelperFactory(SupportFactory(SQLiteDatabase.getBytes(SecurityHelper.getDBPassword()))) .build() } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt index 4d7ce3c8b..93072b4a4 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt @@ -469,27 +469,6 @@ object LocalData { CoronaWarnApplication.getAppContext().getString(R.string.preference_teletan), null ) - /**************************************************** - * DATABASE PASSWORD - ****************************************************/ - - fun databasePassword(): CharArray? = getSharedPreferenceInstance().getString( - CoronaWarnApplication.getAppContext() - .getString(R.string.preference_database_password), - null - )?.toCharArray() - - fun databasePassword(password: CharArray) { - with(getSharedPreferenceInstance().edit()) { - putString( - CoronaWarnApplication.getAppContext() - .getString(R.string.preference_database_password), - password.toString() - ) - commit() - } - } - /**************************************************** * ENCRYPTED SHARED PREFERENCES HANDLING ****************************************************/ diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DataRetentionHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DataRetentionHelper.kt index a7a878fa2..a6891315c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DataRetentionHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DataRetentionHelper.kt @@ -24,7 +24,6 @@ import android.util.Log import de.rki.coronawarnapp.storage.AppDatabase import de.rki.coronawarnapp.storage.FileStorageHelper import de.rki.coronawarnapp.storage.LocalData -import java.util.UUID /** * Helper for supplying functionality regarding Data Retention @@ -44,7 +43,6 @@ object DataRetentionHelper { LocalData.getSharedPreferenceInstance().edit().clear().apply() // Delete Database Instance AppDatabase.resetInstance(context) - LocalData.databasePassword(UUID.randomUUID().toString().toCharArray()) // Export File Reset FileStorageHelper.getAllFilesInKeyExportDirectory().forEach { it.delete() } Log.w(TAG, "CWA LOCAL DATA DELETION COMPLETED.") diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt index ebfba90ca..c4ab75ad0 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt @@ -24,16 +24,30 @@ import android.content.SharedPreferences import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKeys import de.rki.coronawarnapp.CoronaWarnApplication +import java.security.KeyStore +/** + * Key Store and Password Access + */ object SecurityHelper { private const val SHARED_PREF_NAME = "shared_preferences_cwa" private val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC private val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) + private const val AndroidKeyStore = "AndroidKeyStore" + + private val keyStore: KeyStore by lazy { + KeyStore.getInstance(AndroidKeyStore).also { + it.load(null) + } + } val globalEncryptedSharedPreferencesInstance: SharedPreferences by lazy { CoronaWarnApplication.getAppContext().getEncryptedSharedPrefs(SHARED_PREF_NAME) } + /** + * Initializes the private encrypted key store + */ private fun Context.getEncryptedSharedPrefs(fileName: String) = EncryptedSharedPreferences .create( fileName, @@ -42,4 +56,12 @@ object SecurityHelper { EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) + + /** + * Retrieves the Master Key from the Android KeyStore to use in SQLCipher + */ + fun getDBPassword() = keyStore + .getKey(masterKeyAlias, null) + .toString() + .toCharArray() } -- GitLab