fix(Android): If StrongBox is not available, fallback to TEE for master key storage
This commit is contained in:
parent
3999b41d39
commit
74ef9a34ef
|
@ -2,6 +2,9 @@ package db_key_value.crypto_prefs
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.security.keystore.StrongBoxUnavailableException
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
import androidx.security.crypto.EncryptedSharedPreferences
|
||||||
import androidx.security.crypto.MasterKey
|
import androidx.security.crypto.MasterKey
|
||||||
import com.artemchep.keyguard.common.service.keyvalue.KeyValueStore
|
import com.artemchep.keyguard.common.service.keyvalue.KeyValueStore
|
||||||
|
@ -94,16 +97,25 @@ private fun getMasterKeyAlias(
|
||||||
): MasterKey {
|
): MasterKey {
|
||||||
lateinit var exception: Throwable
|
lateinit var exception: Throwable
|
||||||
|
|
||||||
|
var strongBox = true
|
||||||
val retryCount = 3
|
val retryCount = 3
|
||||||
for (i in 0 until retryCount) {
|
for (i in 0 until retryCount) {
|
||||||
try {
|
try {
|
||||||
return MasterKey.Builder(context, alias)
|
return MasterKey.Builder(context, alias)
|
||||||
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
|
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
|
||||||
.setRequestStrongBoxBacked(true)
|
.setRequestStrongBoxBacked(strongBox)
|
||||||
.setUserAuthenticationRequired(false)
|
.setUserAuthenticationRequired(false)
|
||||||
.build()
|
.build()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
if (e is GeneralSecurityException) {
|
if (e.isStrongBoxUnavailableExceptionCompat()) {
|
||||||
|
// If the StrongBox Keymaster isn't available for the given algorithm
|
||||||
|
// and key size associated with a key, the framework throws a
|
||||||
|
// StrongBoxUnavailableException. If you get this exception,
|
||||||
|
// try using TEE for your key storage as a fallback option.
|
||||||
|
//
|
||||||
|
// https://developer.android.com/privacy-and-security/keystore#HardwareSecurityModule
|
||||||
|
strongBox = false
|
||||||
|
} else if (e is GeneralSecurityException) {
|
||||||
exception = e
|
exception = e
|
||||||
onError()
|
onError()
|
||||||
} else {
|
} else {
|
||||||
|
@ -136,3 +148,11 @@ private fun clearKeystore(
|
||||||
keyStore.load(null)
|
keyStore.load(null)
|
||||||
keyStore.deleteEntry(alias)
|
keyStore.deleteEntry(alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Throwable.isStrongBoxUnavailableExceptionCompat(): Boolean =
|
||||||
|
Build.VERSION.SDK_INT >= 28 && isStrongBoxUnavailableException()
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.P)
|
||||||
|
private fun Throwable.isStrongBoxUnavailableException(): Boolean =
|
||||||
|
this is StrongBoxUnavailableException ||
|
||||||
|
cause?.isStrongBoxUnavailableException() == true
|
||||||
|
|
Loading…
Reference in New Issue