diff --git a/src/Android/MainApplication.cs b/src/Android/MainApplication.cs index 72dc30f3c..be1cf8174 100644 --- a/src/Android/MainApplication.cs +++ b/src/Android/MainApplication.cs @@ -21,6 +21,7 @@ using Bit.App.Utilities; using Bit.App.Pages; using Bit.App.Utilities.AccountManagement; using Bit.App.Controls; +using Bit.Core.Enums; #if !FDROID using Android.Gms.Security; #endif @@ -147,7 +148,7 @@ namespace Bit.Droid var storageMediatorService = new StorageMediatorService(mobileStorageService, secureStorageService, preferencesStorage); var stateService = new StateService(mobileStorageService, secureStorageService, storageMediatorService, messagingService); var stateMigrationService = - new StateMigrationService(liteDbStorage, preferencesStorage, secureStorageService); + new StateMigrationService(DeviceType.Android, liteDbStorage, preferencesStorage, secureStorageService); var clipboardService = new ClipboardService(stateService); var deviceActionService = new DeviceActionService(stateService, messagingService); var fileService = new FileService(stateService, broadcasterService); @@ -155,7 +156,7 @@ namespace Bit.Droid messagingService, broadcasterService); var autofillHandler = new AutofillHandler(stateService, messagingService, clipboardService, platformUtilsService, new LazyResolve()); - var biometricService = new BiometricService(); + var biometricService = new BiometricService(stateService); var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService); var cryptoService = new CryptoService(stateService, cryptoFunctionService); var passwordRepromptService = new MobilePasswordRepromptService(platformUtilsService, cryptoService); diff --git a/src/Android/Services/BiometricService.cs b/src/Android/Services/BiometricService.cs index e14ae24ed..7a41b0319 100644 --- a/src/Android/Services/BiometricService.cs +++ b/src/Android/Services/BiometricService.cs @@ -4,7 +4,6 @@ using Android.OS; using Android.Security.Keystore; using Bit.Core.Abstractions; using Bit.Core.Services; -using Bit.Core.Utilities; using Java.Security; using Javax.Crypto; @@ -12,6 +11,8 @@ namespace Bit.Droid.Services { public class BiometricService : IBiometricService { + private readonly IStateService _stateService; + private const string KeyName = "com.8bit.bitwarden.biometric_integrity"; private const string KeyStoreName = "AndroidKeyStore"; @@ -23,28 +24,28 @@ namespace Bit.Droid.Services private readonly KeyStore _keystore; - public BiometricService() + public BiometricService(IStateService stateService) { + _stateService = stateService; _keystore = KeyStore.GetInstance(KeyStoreName); _keystore.Load(null); } - public Task SetupBiometricAsync(string bioIntegrityKey = null) + public async Task SetupBiometricAsync(string bioIntegritySrcKey = null) { - // bioIntegrityKey used in iOS only if (Build.VERSION.SdkInt >= BuildVersionCodes.M) { - CreateKey(); + await CreateKeyAsync(bioIntegritySrcKey); } - return Task.FromResult(true); + return true; } - public Task ValidateIntegrityAsync(string bioIntegrityKey = null) + public async Task IsSystemBiometricIntegrityValidAsync(string bioIntegritySrcKey = null) { if (Build.VERSION.SdkInt < BuildVersionCodes.M) { - return Task.FromResult(true); + return true; } try @@ -55,7 +56,7 @@ namespace Bit.Droid.Services if (key == null || cipher == null) { - return Task.FromResult(true); + return true; } cipher.Init(CipherMode.EncryptMode, key); @@ -63,25 +64,32 @@ namespace Bit.Droid.Services catch (KeyPermanentlyInvalidatedException e) { // Biometric has changed - return Task.FromResult(false); + await ClearStateAsync(bioIntegritySrcKey); + return false; } catch (UnrecoverableKeyException e) { // Biometric was disabled and re-enabled - return Task.FromResult(false); + await ClearStateAsync(bioIntegritySrcKey); + return false; } catch (InvalidKeyException e) { // Fallback for old bitwarden users without a key LoggerHelper.LogEvenIfCantBeResolved(e); - CreateKey(); + await CreateKeyAsync(bioIntegritySrcKey); } - return Task.FromResult(true); + return true; } - private void CreateKey() + private async Task CreateKeyAsync(string bioIntegritySrcKey = null) { + bioIntegritySrcKey ??= Core.Constants.BiometricIntegritySourceKey; + await _stateService.SetSystemBiometricIntegrityState(bioIntegritySrcKey, + await GetStateAsync(bioIntegritySrcKey)); + await _stateService.SetAccountBiometricIntegrityValidAsync(bioIntegritySrcKey); + try { var keyGen = KeyGenerator.GetInstance(KeyAlgorithm, KeyStoreName); @@ -101,5 +109,16 @@ namespace Bit.Droid.Services LoggerHelper.LogEvenIfCantBeResolved(e); } } + + private async Task GetStateAsync(string bioIntegritySrcKey) + { + return await _stateService.GetSystemBiometricIntegrityState(bioIntegritySrcKey) ?? + Guid.NewGuid().ToString(); + } + + private async Task ClearStateAsync(string bioIntegritySrcKey) + { + await _stateService.SetSystemBiometricIntegrityState(bioIntegritySrcKey, null); + } } } diff --git a/src/App/Pages/Accounts/LockPage.xaml b/src/App/Pages/Accounts/LockPage.xaml index 5c269ea1e..18d2f8b9c 100644 --- a/src/App/Pages/Accounts/LockPage.xaml +++ b/src/App/Pages/Accounts/LockPage.xaml @@ -137,7 +137,7 @@