memory stored pinProtectedKey

This commit is contained in:
Kyle Spearrin 2019-09-20 16:43:03 -04:00
parent 23b1373f80
commit ced9d33d2e
8 changed files with 75 additions and 55 deletions

View file

@ -239,7 +239,6 @@ namespace Bit.App
_passwordGenerationService.ClearAsync(), _passwordGenerationService.ClearAsync(),
_lockService.ClearAsync(), _lockService.ClearAsync(),
_stateService.PurgeAsync()); _stateService.PurgeAsync());
_lockService.PinLocked = false;
_lockService.FingerprintLocked = true; _lockService.FingerprintLocked = true;
_searchService.ClearIndex(); _searchService.ClearIndex();
_authService.LogOut(() => _authService.LogOut(() =>

View file

@ -25,7 +25,6 @@ namespace Bit.App.Pages
private readonly IEnvironmentService _environmentService; private readonly IEnvironmentService _environmentService;
private readonly IStateService _stateService; private readonly IStateService _stateService;
private bool _hasKey;
private string _email; private string _email;
private bool _showPassword; private bool _showPassword;
private bool _pinLock; private bool _pinLock;
@ -104,8 +103,7 @@ namespace Bit.App.Pages
public async Task InitAsync(bool autoPromptFingerprint) public async Task InitAsync(bool autoPromptFingerprint)
{ {
_pinSet = await _lockService.IsPinLockSetAsync(); _pinSet = await _lockService.IsPinLockSetAsync();
_hasKey = await _cryptoService.HasKeyAsync(); PinLock = (_pinSet.Item1 && _lockService.PinProtectedKey != null) || _pinSet.Item2;
PinLock = (_pinSet.Item1 && _hasKey) || _pinSet.Item2;
FingerprintLock = await _lockService.IsFingerprintLockSetAsync(); FingerprintLock = await _lockService.IsFingerprintLockSetAsync();
_email = await _userService.GetEmailAsync(); _email = await _userService.GetEmailAsync();
var webVault = _environmentService.GetWebVaultUrl(); var webVault = _environmentService.GetWebVaultUrl();
@ -169,14 +167,17 @@ namespace Bit.App.Pages
{ {
if(_pinSet.Item1) if(_pinSet.Item1)
{ {
var key = await _cryptoService.MakeKeyFromPinAsync(Pin, _email,
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000),
_lockService.PinProtectedKey);
var encKey = await _cryptoService.GetEncKeyAsync(key);
var protectedPin = await _storageService.GetAsync<string>(Constants.ProtectedPin); var protectedPin = await _storageService.GetAsync<string>(Constants.ProtectedPin);
var decPin = await _cryptoService.DecryptToUtf8Async(new CipherString(protectedPin)); var decPin = await _cryptoService.DecryptToUtf8Async(new CipherString(protectedPin), encKey);
failed = decPin != Pin; failed = decPin != Pin;
_lockService.PinLocked = failed;
if(!failed) if(!failed)
{ {
Pin = string.Empty; Pin = string.Empty;
await DoContinueAsync(); await SetKeyAndContinueAsync(key);
} }
} }
else else
@ -221,6 +222,15 @@ namespace Bit.App.Pages
} }
if(storedKeyHash != null && keyHash != null && storedKeyHash == keyHash) if(storedKeyHash != null && keyHash != null && storedKeyHash == keyHash)
{ {
if(_pinSet.Item1)
{
var protectedPin = await _storageService.GetAsync<string>(Constants.ProtectedPin);
var encKey = await _cryptoService.GetEncKeyAsync(key);
var decPin = await _cryptoService.DecryptToUtf8Async(new CipherString(protectedPin), encKey);
var pinKey = await _cryptoService.MakePinKeyAysnc(decPin, _email,
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000));
_lockService.PinProtectedKey = await _cryptoService.EncryptAsync(key.Key, pinKey);
}
MasterPassword = string.Empty; MasterPassword = string.Empty;
await SetKeyAndContinueAsync(key); await SetKeyAndContinueAsync(key);
} }
@ -278,7 +288,8 @@ namespace Bit.App.Pages
private async Task SetKeyAndContinueAsync(SymmetricCryptoKey key) private async Task SetKeyAndContinueAsync(SymmetricCryptoKey key)
{ {
if(!_hasKey) var hasKey = await _cryptoService.HasKeyAsync();
if(!hasKey)
{ {
await _cryptoService.SetKeyAsync(key); await _cryptoService.SetKeyAsync(key);
} }
@ -287,7 +298,6 @@ namespace Bit.App.Pages
private async Task DoContinueAsync() private async Task DoContinueAsync()
{ {
_lockService.PinLocked = false;
_lockService.FingerprintLocked = false; _lockService.FingerprintLocked = false;
var disableFavicon = await _storageService.GetAsync<bool?>(Constants.DisableFaviconKey); var disableFavicon = await _storageService.GetAsync<bool?>(Constants.DisableFaviconKey);
await _stateService.SaveAsync(Constants.DisableFaviconKey, disableFavicon.GetValueOrDefault()); await _stateService.SaveAsync(Constants.DisableFaviconKey, disableFavicon.GetValueOrDefault());

View file

@ -214,21 +214,24 @@ namespace Bit.App.Pages
var masterPassOnRestart = await _platformUtilsService.ShowDialogAsync( var masterPassOnRestart = await _platformUtilsService.ShowDialogAsync(
AppResources.PINRequireMasterPasswordRestart, AppResources.UnlockWithPIN, AppResources.PINRequireMasterPasswordRestart, AppResources.UnlockWithPIN,
AppResources.Yes, AppResources.No); AppResources.Yes, AppResources.No);
var kdf = await _userService.GetKdfAsync();
var kdfIterations = await _userService.GetKdfIterationsAsync();
var email = await _userService.GetEmailAsync();
var pinKey = await _cryptoService.MakePinKeyAysnc(pin, email,
kdf.GetValueOrDefault(Core.Enums.KdfType.PBKDF2_SHA256),
kdfIterations.GetValueOrDefault(5000));
var key = await _cryptoService.GetKeyAsync();
var pinProtectedKey = await _cryptoService.EncryptAsync(key.Key, pinKey);
if(masterPassOnRestart) if(masterPassOnRestart)
{ {
var encPin = await _cryptoService.EncryptAsync(pin); var encPin = await _cryptoService.EncryptAsync(pin);
await _storageService.SaveAsync(Constants.ProtectedPin, encPin.EncryptedString); await _storageService.SaveAsync(Constants.ProtectedPin, encPin.EncryptedString);
_lockService.PinProtectedKey = pinProtectedKey;
} }
else else
{ {
var kdf = await _userService.GetKdfAsync();
var kdfIterations = await _userService.GetKdfIterationsAsync();
var email = await _userService.GetEmailAsync();
var pinKey = await _cryptoService.MakePinKeyAysnc(pin, email,
kdf.GetValueOrDefault(Core.Enums.KdfType.PBKDF2_SHA256),
kdfIterations.GetValueOrDefault(5000));
var key = await _cryptoService.GetKeyAsync();
var pinProtectedKey = await _cryptoService.EncryptAsync(key.Key, pinKey);
await _storageService.SaveAsync(Constants.PinProtectedKey, pinProtectedKey.EncryptedString); await _storageService.SaveAsync(Constants.PinProtectedKey, pinProtectedKey.EncryptedString);
} }
} }
@ -239,8 +242,8 @@ namespace Bit.App.Pages
} }
if(!_pin) if(!_pin)
{ {
await _storageService.RemoveAsync(Constants.PinProtectedKey); await _cryptoService.ClearPinProtectedKeyAsync();
await _storageService.RemoveAsync(Constants.ProtectedPin); await _lockService.ClearAsync();
} }
BuildList(); BuildList();
} }

View file

@ -22,7 +22,7 @@ namespace Bit.Core.Abstractions
Task<CipherString> EncryptAsync(byte[] plainValue, SymmetricCryptoKey key = null); Task<CipherString> EncryptAsync(byte[] plainValue, SymmetricCryptoKey key = null);
Task<CipherString> EncryptAsync(string plainValue, SymmetricCryptoKey key = null); Task<CipherString> EncryptAsync(string plainValue, SymmetricCryptoKey key = null);
Task<byte[]> EncryptToBytesAsync(byte[] plainValue, SymmetricCryptoKey key = null); Task<byte[]> EncryptToBytesAsync(byte[] plainValue, SymmetricCryptoKey key = null);
Task<SymmetricCryptoKey> GetEncKeyAsync(); Task<SymmetricCryptoKey> GetEncKeyAsync(SymmetricCryptoKey key = null);
Task<List<string>> GetFingerprintAsync(string userId, byte[] publicKey = null); Task<List<string>> GetFingerprintAsync(string userId, byte[] publicKey = null);
Task<SymmetricCryptoKey> GetKeyAsync(); Task<SymmetricCryptoKey> GetKeyAsync();
Task<string> GetKeyHashAsync(); Task<string> GetKeyHashAsync();
@ -35,7 +35,8 @@ namespace Bit.Core.Abstractions
Task<bool> HasKeyAsync(); Task<bool> HasKeyAsync();
Task<Tuple<SymmetricCryptoKey, CipherString>> MakeEncKeyAsync(SymmetricCryptoKey key); Task<Tuple<SymmetricCryptoKey, CipherString>> MakeEncKeyAsync(SymmetricCryptoKey key);
Task<SymmetricCryptoKey> MakeKeyAsync(string password, string salt, KdfType? kdf, int? kdfIterations); Task<SymmetricCryptoKey> MakeKeyAsync(string password, string salt, KdfType? kdf, int? kdfIterations);
Task<SymmetricCryptoKey> MakeKeyFromPinAsync(string pin, string salt, KdfType kdf, int kdfIterations); Task<SymmetricCryptoKey> MakeKeyFromPinAsync(string pin, string salt, KdfType kdf, int kdfIterations,
CipherString protectedKeyCs = null);
Task<Tuple<string, CipherString>> MakeKeyPairAsync(SymmetricCryptoKey key = null); Task<Tuple<string, CipherString>> MakeKeyPairAsync(SymmetricCryptoKey key = null);
Task<SymmetricCryptoKey> MakePinKeyAysnc(string pin, string salt, KdfType kdf, int kdfIterations); Task<SymmetricCryptoKey> MakePinKeyAysnc(string pin, string salt, KdfType kdf, int kdfIterations);
Task<Tuple<CipherString, SymmetricCryptoKey>> MakeShareKeyAsync(); Task<Tuple<CipherString, SymmetricCryptoKey>> MakeShareKeyAsync();

View file

@ -1,11 +1,12 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.Core.Models.Domain;
namespace Bit.Core.Abstractions namespace Bit.Core.Abstractions
{ {
public interface ILockService public interface ILockService
{ {
bool PinLocked { get; set; } CipherString PinProtectedKey { get; set; }
bool FingerprintLocked { get; set; } bool FingerprintLocked { get; set; }
Task CheckLockAsync(); Task CheckLockAsync();

View file

@ -118,7 +118,7 @@ namespace Bit.Core.Services
return _keyHash; return _keyHash;
} }
public Task<SymmetricCryptoKey> GetEncKeyAsync() public Task<SymmetricCryptoKey> GetEncKeyAsync(SymmetricCryptoKey key = null)
{ {
if(_encKey != null) if(_encKey != null)
{ {
@ -138,7 +138,10 @@ namespace Bit.Core.Services
return null; return null;
} }
var key = await GetKeyAsync(); if(key == null)
{
key = await GetKeyAsync();
}
if(key == null) if(key == null)
{ {
return null; return null;
@ -386,14 +389,17 @@ namespace Bit.Core.Services
} }
public async Task<SymmetricCryptoKey> MakeKeyFromPinAsync(string pin, string salt, public async Task<SymmetricCryptoKey> MakeKeyFromPinAsync(string pin, string salt,
KdfType kdf, int kdfIterations) KdfType kdf, int kdfIterations, CipherString protectedKeyCs = null)
{ {
var pinProtectedKey = await _storageService.GetAsync<string>(Constants.PinProtectedKey); if(protectedKeyCs == null)
if(pinProtectedKey == null)
{ {
throw new Exception("No PIN protected key found."); var pinProtectedKey = await _storageService.GetAsync<string>(Constants.PinProtectedKey);
if(pinProtectedKey == null)
{
throw new Exception("No PIN protected key found.");
}
protectedKeyCs = new CipherString(pinProtectedKey);
} }
var protectedKeyCs = new CipherString(pinProtectedKey);
var pinKey = await MakePinKeyAysnc(pin, salt, kdf, kdfIterations); var pinKey = await MakePinKeyAysnc(pin, salt, kdf, kdfIterations);
var decKey = await DecryptToBytesAsync(protectedKeyCs, pinKey); var decKey = await DecryptToBytesAsync(protectedKeyCs, pinKey);
return new SymmetricCryptoKey(decKey); return new SymmetricCryptoKey(decKey);

View file

@ -1,4 +1,5 @@
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Models.Domain;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -41,7 +42,7 @@ namespace Bit.Core.Services
_lockedCallback = lockedCallback; _lockedCallback = lockedCallback;
} }
public bool PinLocked { get; set; } public CipherString PinProtectedKey { get; set; } = null;
public bool FingerprintLocked { get; set; } = true; public bool FingerprintLocked { get; set; } = true;
public async Task<bool> IsLockedAsync() public async Task<bool> IsLockedAsync()
@ -49,18 +50,11 @@ namespace Bit.Core.Services
var hasKey = await _cryptoService.HasKeyAsync(); var hasKey = await _cryptoService.HasKeyAsync();
if(hasKey) if(hasKey)
{ {
if(PinLocked) var fingerprintSet = await IsFingerprintLockSetAsync();
if(fingerprintSet && FingerprintLocked)
{ {
return true; return true;
} }
else
{
var fingerprintSet = await IsFingerprintLockSetAsync();
if(fingerprintSet && FingerprintLocked)
{
return true;
}
}
} }
return !hasKey; return !hasKey;
} }
@ -111,13 +105,8 @@ namespace Bit.Core.Services
} }
if(allowSoftLock) if(allowSoftLock)
{ {
var pinSet = await IsPinLockSetAsync();
if(pinSet.Item1)
{
PinLocked = true;
}
FingerprintLocked = await IsFingerprintLockSetAsync(); FingerprintLocked = await IsFingerprintLockSetAsync();
if(FingerprintLocked || PinLocked) if(FingerprintLocked)
{ {
_messagingService.Send("locked", userInitiated); _messagingService.Send("locked", userInitiated);
_lockedCallback?.Invoke(userInitiated); _lockedCallback?.Invoke(userInitiated);
@ -159,6 +148,7 @@ namespace Bit.Core.Services
public async Task ClearAsync() public async Task ClearAsync()
{ {
PinProtectedKey = null;
await _storageService.RemoveAsync(Constants.ProtectedPin); await _storageService.RemoveAsync(Constants.ProtectedPin);
} }
} }

View file

@ -23,7 +23,6 @@ namespace Bit.iOS.Core.Controllers
private IStorageService _secureStorageService; private IStorageService _secureStorageService;
private IPlatformUtilsService _platformUtilsService; private IPlatformUtilsService _platformUtilsService;
private Tuple<bool, bool> _pinSet; private Tuple<bool, bool> _pinSet;
private bool _hasKey;
private bool _pinLock; private bool _pinLock;
private bool _fingerprintLock; private bool _fingerprintLock;
private int _invalidPinAttempts; private int _invalidPinAttempts;
@ -52,8 +51,7 @@ namespace Bit.iOS.Core.Controllers
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"); _platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
_pinSet = _lockService.IsPinLockSetAsync().GetAwaiter().GetResult(); _pinSet = _lockService.IsPinLockSetAsync().GetAwaiter().GetResult();
_hasKey = _cryptoService.HasKeyAsync().GetAwaiter().GetResult(); _pinLock = (_pinSet.Item1 && _lockService.PinProtectedKey != null) || _pinSet.Item2;
_pinLock = (_pinSet.Item1 && _hasKey) || _pinSet.Item2;
_fingerprintLock = _lockService.IsFingerprintLockSetAsync().GetAwaiter().GetResult(); _fingerprintLock = _lockService.IsFingerprintLockSetAsync().GetAwaiter().GetResult();
BaseNavItem.Title = _pinLock ? AppResources.VerifyPIN : AppResources.VerifyMasterPassword; BaseNavItem.Title = _pinLock ? AppResources.VerifyPIN : AppResources.VerifyMasterPassword;
@ -125,13 +123,16 @@ namespace Bit.iOS.Core.Controllers
{ {
if(_pinSet.Item1) if(_pinSet.Item1)
{ {
var key = await _cryptoService.MakeKeyFromPinAsync(inputtedValue, email,
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000),
_lockService.PinProtectedKey);
var encKey = await _cryptoService.GetEncKeyAsync(key);
var protectedPin = await _storageService.GetAsync<string>(Bit.Core.Constants.ProtectedPin); var protectedPin = await _storageService.GetAsync<string>(Bit.Core.Constants.ProtectedPin);
var decPin = await _cryptoService.DecryptToUtf8Async(new CipherString(protectedPin)); var decPin = await _cryptoService.DecryptToUtf8Async(new CipherString(protectedPin), encKey);
failed = decPin != inputtedValue; failed = decPin != inputtedValue;
_lockService.PinLocked = failed;
if(!failed) if(!failed)
{ {
DoContinue(); await SetKeyAndContinueAsync(key);
} }
} }
else else
@ -174,6 +175,15 @@ namespace Bit.iOS.Core.Controllers
} }
if(storedKeyHash != null && keyHash != null && storedKeyHash == keyHash) if(storedKeyHash != null && keyHash != null && storedKeyHash == keyHash)
{ {
if(_pinSet.Item1)
{
var protectedPin = await _storageService.GetAsync<string>(Bit.Core.Constants.ProtectedPin);
var encKey = await _cryptoService.GetEncKeyAsync(key2);
var decPin = await _cryptoService.DecryptToUtf8Async(new CipherString(protectedPin), encKey);
var pinKey = await _cryptoService.MakePinKeyAysnc(decPin, email,
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000));
_lockService.PinProtectedKey = await _cryptoService.EncryptAsync(key2.Key, pinKey);
}
await SetKeyAndContinueAsync(key2); await SetKeyAndContinueAsync(key2);
} }
else else
@ -185,7 +195,8 @@ namespace Bit.iOS.Core.Controllers
private async Task SetKeyAndContinueAsync(SymmetricCryptoKey key) private async Task SetKeyAndContinueAsync(SymmetricCryptoKey key)
{ {
if(!_hasKey) var hasKey = await _cryptoService.HasKeyAsync();
if(!hasKey)
{ {
await _cryptoService.SetKeyAsync(key); await _cryptoService.SetKeyAsync(key);
} }
@ -194,7 +205,6 @@ namespace Bit.iOS.Core.Controllers
private void DoContinue() private void DoContinue()
{ {
_lockService.PinLocked = false;
_lockService.FingerprintLocked = false; _lockService.FingerprintLocked = false;
MasterPasswordCell.TextField.ResignFirstResponder(); MasterPasswordCell.TextField.ResignFirstResponder();
Success(); Success();