diff --git a/src/App/Pages/Accounts/LockPageViewModel.cs b/src/App/Pages/Accounts/LockPageViewModel.cs index 10cc3a162..3ef580c9a 100644 --- a/src/App/Pages/Accounts/LockPageViewModel.cs +++ b/src/App/Pages/Accounts/LockPageViewModel.cs @@ -462,7 +462,7 @@ namespace Bit.App.Pages await _stateService.SetBiometricLockedAsync(!success); if (success) { - var userKey = await _stateService.GetUserKeyBiometricUnlockAsync(); + var userKey = await _cryptoService.GetBiometricUnlockKeyAsync(); await SetUserKeyAndContinueAsync(userKey); } } diff --git a/src/Core/Abstractions/ICryptoService.cs b/src/Core/Abstractions/ICryptoService.cs index b7d03df2d..4b9bf570a 100644 --- a/src/Core/Abstractions/ICryptoService.cs +++ b/src/Core/Abstractions/ICryptoService.cs @@ -21,6 +21,7 @@ namespace Bit.Core.Abstractions Task SetMasterKeyEncryptedUserKeyAsync(string value, string userId = null); Task GetAutoUnlockKeyAsync(string userId = null); Task HasAutoUnlockKeyAsync(string userId = null); + Task GetBiometricUnlockKeyAsync(string userId = null); Task SetMasterKeyAsync(MasterKey masterKey, string userId = null); Task GetMasterKeyAsync(string userId = null); Task MakeMasterKeyAsync(string password, string email, KdfConfig kdfConfig); diff --git a/src/Core/Services/AuthService.cs b/src/Core/Services/AuthService.cs index 28ffeef2d..762a51e1e 100644 --- a/src/Core/Services/AuthService.cs +++ b/src/Core/Services/AuthService.cs @@ -46,7 +46,6 @@ namespace Bit.Core.Services II18nService i18nService, IPlatformUtilsService platformUtilsService, IMessagingService messagingService, - IKeyConnectorService keyConnectorService, IPasswordGenerationService passwordGenerationService, IPolicyService policyService, bool setCryptoKeys = true) @@ -60,7 +59,6 @@ namespace Bit.Core.Services _i18nService = i18nService; _platformUtilsService = platformUtilsService; _messagingService = messagingService; - _keyConnectorService = keyConnectorService; _passwordGenerationService = passwordGenerationService; _policyService = policyService; _setCryptoKeys = setCryptoKeys; diff --git a/src/Core/Services/CryptoService.cs b/src/Core/Services/CryptoService.cs index d9c10cb8d..0255e5fe5 100644 --- a/src/Core/Services/CryptoService.cs +++ b/src/Core/Services/CryptoService.cs @@ -101,7 +101,7 @@ namespace Bit.Core.Services public async Task GetAutoUnlockKeyAsync(string userId = null) { - await MigrateAutoUnlockKeyIfNeededAsync(userId); + await MigrateAutoAndBioKeysIfNeededAsync(userId); return await _stateService.GetUserKeyAutoUnlockAsync(userId); } @@ -110,6 +110,12 @@ namespace Bit.Core.Services return await GetAutoUnlockKeyAsync(userId) != null; } + public async Task GetBiometricUnlockKeyAsync(string userId = null) + { + await MigrateAutoAndBioKeysIfNeededAsync(userId); + return await _stateService.GetUserKeyBiometricUnlockAsync(userId); + } + public Task SetMasterKeyAsync(MasterKey masterKey, string userId = null) { return _stateService.SetMasterKeyAsync(masterKey, userId); @@ -982,23 +988,33 @@ namespace Bit.Core.Services // We previously used the master key for additional keys, but now we use the user key. // These methods support migrating the old keys to the new ones. - private async Task MigrateAutoUnlockKeyIfNeededAsync(string userId = null) + private async Task MigrateAutoAndBioKeysIfNeededAsync(string userId = null) { - var oldAutoKey = await _stateService.GetKeyEncryptedAsync(userId); - if (oldAutoKey == null) + var oldKey = await _stateService.GetKeyEncryptedAsync(userId); + if (oldKey == null) { return; } + // Decrypt - var masterKey = new MasterKey(Convert.FromBase64String(oldAutoKey)); + var masterKey = new MasterKey(Convert.FromBase64String(oldKey)); var encryptedUserKey = await _stateService.GetEncKeyEncryptedAsync(userId); var userKey = await DecryptUserKeyWithMasterKeyAsync( masterKey, new EncString(encryptedUserKey), userId); + // Migrate - await _stateService.SetUserKeyAutoUnlockAsync(userKey, userId); + if (await _stateService.GetVaultTimeoutAsync(userId) == null) + { + await _stateService.SetUserKeyAutoUnlockAsync(userKey, userId); + } + if ((await _stateService.GetBiometricUnlockAsync(userId)).GetValueOrDefault()) + { + await _stateService.SetUserKeyBiometricUnlockAsync(userKey, userId); + } await _stateService.SetKeyEncryptedAsync(null, userId); + // Set encrypted user key just in case the user locks without syncing await SetMasterKeyEncryptedUserKeyAsync(encryptedUserKey); } diff --git a/src/Core/Services/StateService.cs b/src/Core/Services/StateService.cs index 9e5fb3a06..3b42c96c0 100644 --- a/src/Core/Services/StateService.cs +++ b/src/Core/Services/StateService.cs @@ -251,7 +251,7 @@ namespace Bit.Core.Services public async Task SetUserKeyBiometricUnlockAsync(UserKey value, string userId = null) { await _storageMediatorService.SaveAsync( - await ComposeKeyAsync(Constants.UserKeyBiometricUnlockKey, userId), value, true); + await ComposeKeyAsync(Constants.UserKeyBiometricUnlockKey, userId), value?.KeyB64, true); } public async Task GetBiometricUnlockAsync(string userId = null) @@ -369,7 +369,7 @@ namespace Bit.Core.Services public async Task SetUserKeyAutoUnlockAsync(UserKey value, string userId = null) { await _storageMediatorService.SaveAsync( - await ComposeKeyAsync(Constants.UserKeyAutoUnlockKey, userId), value.KeyB64, true); + await ComposeKeyAsync(Constants.UserKeyAutoUnlockKey, userId), value?.KeyB64, true); } public async Task CanAccessPremiumAsync(string userId = null) @@ -1478,6 +1478,7 @@ namespace Bit.Core.Services // Non-state storage await Task.WhenAll( SetUserKeyAutoUnlockAsync(null, userId), + SetUserKeyBiometricUnlockAsync(null, userId), SetProtectedPinAsync(null, userId), SetKeyHashAsync(null, userId), SetOrgKeysEncryptedAsync(null, userId), diff --git a/src/Core/Utilities/ServiceContainer.cs b/src/Core/Utilities/ServiceContainer.cs index 9c8b7909f..a040ce3ee 100644 --- a/src/Core/Utilities/ServiceContainer.cs +++ b/src/Core/Utilities/ServiceContainer.cs @@ -79,7 +79,7 @@ namespace Bit.Core.Utilities var totpService = new TotpService(cryptoFunctionService); var authService = new AuthService(cryptoService, cryptoFunctionService, apiService, stateService, tokenService, appIdService, i18nService, platformUtilsService, messagingService, - keyConnectorService, passwordGenerationService, policyService); + passwordGenerationService, policyService); var exportService = new ExportService(folderService, cipherService, cryptoService); var auditService = new AuditService(cryptoFunctionService, apiService); var environmentService = new EnvironmentService(apiService, stateService, conditionedRunner);