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
This commit is contained in:
Matt Portune 2020-10-07 12:18:36 -04:00 committed by GitHub
parent 8f533bc576
commit 37e19d9a60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 35 additions and 12 deletions

View File

@ -30,8 +30,9 @@ namespace Bit.Droid.Services
_keystore.Load(null);
}
public Task<bool> SetupBiometricAsync()
public Task<bool> 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<bool> ValidateIntegrityAsync()
public Task<bool> ValidateIntegrityAsync(string bioIntegrityKey = null)
{
// bioIntegrityKey used in iOS only
if (Build.VERSION.SdkInt < BuildVersionCodes.M)
{
return Task.FromResult(true);

View File

@ -4,7 +4,7 @@ namespace Bit.Core.Abstractions
{
public interface IBiometricService
{
Task<bool> SetupBiometricAsync();
Task<bool> ValidateIntegrityAsync();
Task<bool> SetupBiometricAsync(string bioIntegrityKey = null);
Task<bool> ValidateIntegrityAsync(string bioIntegrityKey = null);
}
}

View File

@ -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;

View File

@ -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
{

View File

@ -14,24 +14,32 @@ namespace Bit.iOS.Core.Services
_storageService = storageService;
}
public async Task<bool> SetupBiometricAsync()
public async Task<bool> 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<bool> ValidateIntegrityAsync()
public async Task<bool> ValidateIntegrityAsync(string bioIntegrityKey = null)
{
var oldState = await _storageService.GetAsync<string>("biometricState");
if (bioIntegrityKey == null)
{
bioIntegrityKey = "biometricState";
}
var oldState = await _storageService.GetAsync<string>(bioIntegrityKey);
if (oldState == null)
{
// Fallback for upgraded devices
await SetupBiometricAsync();
await SetupBiometricAsync(bioIntegrityKey);
return true;
}

View File

@ -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;