Better unlock settings

This commit is contained in:
J-Jamet
2020-11-23 20:47:50 +01:00
parent 75f245c7dc
commit 84bb47aa53
5 changed files with 106 additions and 43 deletions

View File

@@ -90,12 +90,12 @@ class UnavailableFeatureDialogFragment : DialogFragment() {
}
}
if (apiName.isEmpty()) {
val mapper = arrayOf("ANDROID BASE", "ANDROID BASE 1.1", "CUPCAKE", "DONUT", "ECLAIR", "ECLAIR_0_1", "ECLAIR_MR1", "FROYO", "GINGERBREAD", "GINGERBREAD_MR1", "HONEYCOMB", "HONEYCOMB_MR1", "HONEYCOMB_MR2", "ICE_CREAM_SANDWICH", "ICE_CREAM_SANDWICH_MR1", "JELLY_BEAN", "JELLY_BEAN", "JELLY_BEAN", "KITKAT", "KITKAT", "LOLLIPOOP", "LOLLIPOOP_MR1", "MARSHMALLOW", "NOUGAT", "NOUGAT", "OREO", "OREO")
val mapper = arrayOf("ANDROID BASE", "ANDROID BASE 1.1", "CUPCAKE", "DONUT", "ECLAIR", "ECLAIR_0_1", "ECLAIR_MR1", "FROYO", "GINGERBREAD", "GINGERBREAD_MR1", "HONEYCOMB", "HONEYCOMB_MR1", "HONEYCOMB_MR2", "ICE_CREAM_SANDWICH", "ICE_CREAM_SANDWICH_MR1", "JELLY_BEAN", "JELLY_BEAN", "JELLY_BEAN", "KITKAT", "KITKAT", "LOLLIPOOP", "LOLLIPOOP_MR1", "MARSHMALLOW", "NOUGAT", "NOUGAT", "OREO", "OREO", "PIE", "", "")
val index = apiNumber - 1
apiName = if (index < mapper.size) mapper[index] else "UNKNOWN_VERSION"
}
if (version.isEmpty()) {
val versions = arrayOf("1.0", "1.1", "1.5", "1.6", "2.0", "2.0.1", "2.1", "2.2.X", "2.3", "2.3.3", "3.0", "3.1", "3.2.0", "4.0.1", "4.0.3", "4.1.0", "4.2.0", "4.3.0", "4.4", "4.4", "5.0", "5.1", "6.0", "7.0", "7.1", "8.0.0", "8.1.0")
val versions = arrayOf("1.0", "1.1", "1.5", "1.6", "2.0", "2.0.1", "2.1", "2.2.X", "2.3", "2.3.3", "3.0", "3.1", "3.2.0", "4.0.1", "4.0.3", "4.1.0", "4.2.0", "4.3.0", "4.4", "4.4", "5.0", "5.1", "6.0", "7.0", "7.1", "8.0.0", "8.1.0", "9", "10", "11")
val index = apiNumber - 1
version = if (index < versions.size) versions[index] else "UNKNOWN_VERSION"
}

View File

@@ -307,21 +307,26 @@ class BiometricUnlockDatabaseHelper(private val context: FragmentActivity) {
private const val BIOMETRIC_BLOCKS_MODES = KeyProperties.BLOCK_MODE_CBC
private const val BIOMETRIC_ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7
@RequiresApi(api = Build.VERSION_CODES.M)
fun canAuthenticate(context: Context): Int {
return try {
BiometricManager.from(context).canAuthenticate(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
BiometricManager.from(context).canAuthenticate(BIOMETRIC_STRONG or DEVICE_CREDENTIAL)
BIOMETRIC_STRONG or DEVICE_CREDENTIAL
} else {
BiometricManager.from(context).canAuthenticate(BIOMETRIC_STRONG)
BIOMETRIC_STRONG
}
)
} catch (e: Exception) {
Log.e(TAG, "Unable to authenticate with strong biometric.", e)
try {
BiometricManager.from(context).canAuthenticate(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
BiometricManager.from(context).canAuthenticate(BIOMETRIC_WEAK or DEVICE_CREDENTIAL)
BIOMETRIC_WEAK or DEVICE_CREDENTIAL
} else {
BiometricManager.from(context).canAuthenticate(BIOMETRIC_WEAK)
BIOMETRIC_WEAK
}
)
} catch (e: Exception) {
Log.e(TAG, "Unable to authenticate with weak biometric.", e)
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
@@ -329,6 +334,7 @@ class BiometricUnlockDatabaseHelper(private val context: FragmentActivity) {
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
fun allowInitKeyStore(context: Context): Boolean {
val biometricCanAuthenticate = canAuthenticate(context)
return ( biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS
@@ -336,8 +342,30 @@ class BiometricUnlockDatabaseHelper(private val context: FragmentActivity) {
)
}
fun unlockSupported(context: Context): Boolean {
val biometricCanAuthenticate = canAuthenticate(context)
@RequiresApi(api = Build.VERSION_CODES.M)
fun biometricUnlockSupported(context: Context): Boolean {
val biometricCanAuthenticate = try {
BiometricManager.from(context).canAuthenticate(BIOMETRIC_STRONG)
} catch (e: Exception) {
Log.e(TAG, "Unable to authenticate with strong biometric.", e)
try {
BiometricManager.from(context).canAuthenticate(BIOMETRIC_WEAK)
} catch (e: Exception) {
Log.e(TAG, "Unable to authenticate with weak biometric.", e)
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
}
}
return (biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_STATUS_UNKNOWN
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED
)
}
@RequiresApi(api = Build.VERSION_CODES.R)
fun deviceCredentialUnlockSupported(context: Context): Boolean {
val biometricCanAuthenticate = BiometricManager.from(context).canAuthenticate(DEVICE_CREDENTIAL)
return (biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_STATUS_UNKNOWN
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
@@ -349,6 +377,7 @@ class BiometricUnlockDatabaseHelper(private val context: FragmentActivity) {
/**
* Remove entry key in keystore
*/
@RequiresApi(api = Build.VERSION_CODES.M)
fun deleteEntryKeyInKeystoreForBiometric(context: FragmentActivity,
biometricCallback: BiometricUnlockErrorCallback) {
BiometricUnlockDatabaseHelper(context).apply {

View File

@@ -30,7 +30,6 @@ import android.view.autofill.AutofillManager
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
import androidx.biometric.BiometricManager
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.SwitchPreference
@@ -209,14 +208,15 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
activity?.let { activity ->
val biometricUnlockEnablePreference: SwitchPreference? = findPreference(getString(R.string.biometric_unlock_enable_key))
val deleteKeysFingerprints: Preference? = findPreference(getString(R.string.biometric_delete_all_key_key))
// < M solve verifyError exception
val deviceCredentialUnlockEnablePreference: SwitchPreference? = findPreference(getString(R.string.device_credential_unlock_enable_key))
val autoOpenPromptPreference: SwitchPreference? = findPreference(getString(R.string.biometric_auto_open_prompt_key))
val biometricUnlockSupported = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
BiometricUnlockDatabaseHelper.unlockSupported(activity)
BiometricUnlockDatabaseHelper.biometricUnlockSupported(activity)
} else false
if (!biometricUnlockSupported) {
// False if under Marshmallow
biometricUnlockEnablePreference?.apply {
// False if under Marshmallow
if (!biometricUnlockSupported) {
isChecked = false
setOnPreferenceClickListener { preference ->
(preference as SwitchPreference).isChecked = false
@@ -224,9 +224,48 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
.show(parentFragmentManager, "unavailableFeatureDialog")
false
}
}
deleteKeysFingerprints?.isEnabled = false
} else {
setOnPreferenceChangeListener { _, newValue ->
val checked = (newValue as Boolean)
autoOpenPromptPreference?.isEnabled = checked
|| deviceCredentialUnlockEnablePreference?.isChecked == true
if (checked)
deviceCredentialUnlockEnablePreference?.isChecked = false
true
}
}
}
val deviceCredentialUnlockSupported = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
BiometricUnlockDatabaseHelper.deviceCredentialUnlockSupported(activity)
} else false
deviceCredentialUnlockEnablePreference?.apply {
if (!deviceCredentialUnlockSupported) {
isChecked = false
setOnPreferenceClickListener { preference ->
(preference as SwitchPreference).isChecked = false
UnavailableFeatureDialogFragment.getInstance(Build.VERSION_CODES.R)
.show(parentFragmentManager, "unavailableFeatureDialog")
false
}
} else {
setOnPreferenceChangeListener { _, newValue ->
val checked = (newValue as Boolean)
autoOpenPromptPreference?.isEnabled = checked ||
biometricUnlockEnablePreference?.isChecked == true
if (checked)
biometricUnlockEnablePreference?.isChecked = false
true
}
}
}
autoOpenPromptPreference?.isEnabled = biometricUnlockEnablePreference?.isChecked == true
|| deviceCredentialUnlockEnablePreference?.isChecked == true
val deleteKeysFingerprints: Preference? = findPreference(getString(R.string.biometric_delete_all_key_key))
if (biometricUnlockSupported || deviceCredentialUnlockSupported) {
deleteKeysFingerprints?.setOnPreferenceClickListener {
context?.let { context ->
AlertDialog.Builder(context)
@@ -260,6 +299,8 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
}
false
}
} else {
deleteKeysFingerprints?.isEnabled = false
}
}

View File

@@ -324,8 +324,8 @@
<string name="biometric_unlock_enable_summary">Lets you scan your biometric to open the database</string>
<string name="device_credential_unlock_enable_title">Device credential unlocking</string>
<string name="device_credential_unlock_enable_summary">Lets you use your device credential to open the database</string>
<string name="biometric_auto_open_prompt_title">Auto-open biometric prompt</string>
<string name="biometric_auto_open_prompt_summary">Automatically ask for biometric if the database is set up to use it</string>
<string name="biometric_auto_open_prompt_title">Auto-open prompt</string>
<string name="biometric_auto_open_prompt_summary">Automatically request advanced unlock if the database is set up to use it</string>
<string name="biometric_delete_all_key_title">Delete encryption keys</string>
<string name="biometric_delete_all_key_summary">Delete all encryption keys related to advanced unlock recognition</string>
<string name="biometric_delete_all_key_warning">Delete all encryption keys related to advanced unlock recognition?</string>

View File

@@ -18,34 +18,27 @@
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/general">
<Preference
android:key="@string/advanced_unlock_explanation_key"
android:icon="@drawable/prefs_info_24dp"
android:summary="@string/advanced_unlock_explanation_summary"/>
<PreferenceCategory
android:title="@string/biometric">
<SwitchPreference
android:key="@string/biometric_unlock_enable_key"
android:title="@string/biometric_unlock_enable_title"
android:summary="@string/biometric_unlock_enable_summary"
android:defaultValue="@bool/biometric_unlock_enable_default"/>
<SwitchPreference
android:key="@string/biometric_auto_open_prompt_key"
android:title="@string/biometric_auto_open_prompt_title"
android:summary="@string/biometric_auto_open_prompt_summary"
android:dependency="@string/biometric_unlock_enable_key"
android:defaultValue="@bool/biometric_auto_open_prompt_default"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/device_credential">
<SwitchPreference
android:key="@string/device_credential_unlock_enable_key"
android:title="@string/device_credential_unlock_enable_title"
android:summary="@string/device_credential_unlock_enable_summary"
android:defaultValue="@bool/device_credential_unlock_enable_default"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/general">
<SwitchPreference
android:key="@string/biometric_auto_open_prompt_key"
android:title="@string/biometric_auto_open_prompt_title"
android:summary="@string/biometric_auto_open_prompt_summary"
android:defaultValue="@bool/biometric_auto_open_prompt_default"/>
<Preference
android:key="@string/biometric_delete_all_key_key"
android:title="@string/biometric_delete_all_key_title"