From 37e19d9a60435002f43b38175f9b81f54c6822fc Mon Sep 17 00:00:00 2001 From: Matt Portune <59324545+mportune-bw@users.noreply.github.com> Date: Wed, 7 Oct 2020 12:18:36 -0400 Subject: [PATCH] Support for storing multiple biometric integrity states for iOS (#1110) * support for storing multiple biometric integrity states for iOS * remove unused var & save new extension bio state upon password validation --- src/Android/Services/BiometricService.cs | 6 ++++-- src/Core/Abstractions/IBiometricService.cs | 4 ++-- src/iOS.Autofill/LockPasswordViewController.cs | 4 +++- .../Controllers/LockPasswordViewController.cs | 11 ++++++++++- src/iOS.Core/Services/BiometricService.cs | 18 +++++++++++++----- .../LockPasswordViewController.cs | 4 +++- 6 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/Android/Services/BiometricService.cs b/src/Android/Services/BiometricService.cs index 83b19e5dc..aa23477ba 100644 --- a/src/Android/Services/BiometricService.cs +++ b/src/Android/Services/BiometricService.cs @@ -30,8 +30,9 @@ namespace Bit.Droid.Services _keystore.Load(null); } - public Task SetupBiometricAsync() + public Task SetupBiometricAsync(string bioIntegrityKey = null) { + // bioIntegrityKey used in iOS only if (Build.VERSION.SdkInt >= BuildVersionCodes.M) { CreateKey(); @@ -40,8 +41,9 @@ namespace Bit.Droid.Services return Task.FromResult(true); } - public Task ValidateIntegrityAsync() + public Task ValidateIntegrityAsync(string bioIntegrityKey = null) { + // bioIntegrityKey used in iOS only if (Build.VERSION.SdkInt < BuildVersionCodes.M) { return Task.FromResult(true); diff --git a/src/Core/Abstractions/IBiometricService.cs b/src/Core/Abstractions/IBiometricService.cs index 5e77a6329..29c8773c2 100644 --- a/src/Core/Abstractions/IBiometricService.cs +++ b/src/Core/Abstractions/IBiometricService.cs @@ -4,7 +4,7 @@ namespace Bit.Core.Abstractions { public interface IBiometricService { - Task SetupBiometricAsync(); - Task ValidateIntegrityAsync(); + Task SetupBiometricAsync(string bioIntegrityKey = null); + Task ValidateIntegrityAsync(string bioIntegrityKey = null); } } diff --git a/src/iOS.Autofill/LockPasswordViewController.cs b/src/iOS.Autofill/LockPasswordViewController.cs index 9b975473e..35fa2267f 100644 --- a/src/iOS.Autofill/LockPasswordViewController.cs +++ b/src/iOS.Autofill/LockPasswordViewController.cs @@ -7,7 +7,9 @@ namespace Bit.iOS.Autofill { public LockPasswordViewController(IntPtr handle) : base(handle) - { } + { + BiometricIntegrityKey = "autofillBiometricState"; + } public CredentialProviderViewController CPViewController { get; set; } public override UINavigationItem BaseNavItem => NavItem; diff --git a/src/iOS.Core/Controllers/LockPasswordViewController.cs b/src/iOS.Core/Controllers/LockPasswordViewController.cs index ad6ec4ec0..346d53a90 100644 --- a/src/iOS.Core/Controllers/LockPasswordViewController.cs +++ b/src/iOS.Core/Controllers/LockPasswordViewController.cs @@ -41,6 +41,8 @@ namespace Bit.iOS.Core.Controllers public FormEntryTableViewCell MasterPasswordCell { get; set; } = new FormEntryTableViewCell( AppResources.MasterPassword); + + public string BiometricIntegrityKey { get; set; } public override void ViewDidLoad() { @@ -86,7 +88,8 @@ namespace Bit.iOS.Core.Controllers if (_biometricLock) { - _biometricIntegrityValid = _biometricService.ValidateIntegrityAsync().GetAwaiter().GetResult(); + _biometricIntegrityValid = _biometricService.ValidateIntegrityAsync(BiometricIntegrityKey).GetAwaiter() + .GetResult(); if (!_biometricIntegrityValid) { return; @@ -194,6 +197,12 @@ namespace Bit.iOS.Core.Controllers _vaultTimeoutService.PinProtectedKey = await _cryptoService.EncryptAsync(key2.Key, pinKey); } await SetKeyAndContinueAsync(key2); + + // Re-enable biometrics + if (_biometricLock & !_biometricIntegrityValid) + { + await _biometricService.SetupBiometricAsync(BiometricIntegrityKey); + } } else { diff --git a/src/iOS.Core/Services/BiometricService.cs b/src/iOS.Core/Services/BiometricService.cs index 3126a8c10..8df66c4a1 100644 --- a/src/iOS.Core/Services/BiometricService.cs +++ b/src/iOS.Core/Services/BiometricService.cs @@ -14,24 +14,32 @@ namespace Bit.iOS.Core.Services _storageService = storageService; } - public async Task SetupBiometricAsync() + public async Task SetupBiometricAsync(string bioIntegrityKey = null) { + if (bioIntegrityKey == null) + { + bioIntegrityKey = "biometricState"; + } var state = GetState(); if (state != null) { - await _storageService.SaveAsync("biometricState", ToBase64(state)); + await _storageService.SaveAsync(bioIntegrityKey, ToBase64(state)); } return true; } - public async Task ValidateIntegrityAsync() + public async Task ValidateIntegrityAsync(string bioIntegrityKey = null) { - var oldState = await _storageService.GetAsync("biometricState"); + if (bioIntegrityKey == null) + { + bioIntegrityKey = "biometricState"; + } + var oldState = await _storageService.GetAsync(bioIntegrityKey); if (oldState == null) { // Fallback for upgraded devices - await SetupBiometricAsync(); + await SetupBiometricAsync(bioIntegrityKey); return true; } diff --git a/src/iOS.Extension/LockPasswordViewController.cs b/src/iOS.Extension/LockPasswordViewController.cs index 5f8024453..ae7a400d4 100644 --- a/src/iOS.Extension/LockPasswordViewController.cs +++ b/src/iOS.Extension/LockPasswordViewController.cs @@ -8,7 +8,9 @@ namespace Bit.iOS.Extension { public LockPasswordViewController(IntPtr handle) : base(handle) - { } + { + BiometricIntegrityKey = "extensionBiometricState"; + } public LoadingViewController LoadingController { get; set; } public override UINavigationItem BaseNavItem => NavItem;