1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-15 15:53:44 +00:00

[PM-2713] PR feedback

This commit is contained in:
Jacob Fink
2023-07-31 15:31:46 -04:00
parent c793260689
commit e323e196c0
5 changed files with 71 additions and 69 deletions

View File

@@ -36,7 +36,7 @@ namespace Bit.Core.Abstractions
Task<OrgKey> GetOrgKeyAsync(string orgId); Task<OrgKey> GetOrgKeyAsync(string orgId);
Task<Dictionary<string, OrgKey>> GetOrgKeysAsync(); Task<Dictionary<string, OrgKey>> GetOrgKeysAsync();
Task ClearOrgKeysAsync(bool memoryOnly = false, string userId = null); Task ClearOrgKeysAsync(bool memoryOnly = false, string userId = null);
Task<byte[]> GetPublicKeyAsync(); Task<byte[]> GetUserPublicKeyAsync();
Task SetUserPrivateKeyAsync(string encPrivateKey); Task SetUserPrivateKeyAsync(string encPrivateKey);
Task<byte[]> GetUserPrivateKeyAsync(); Task<byte[]> GetUserPrivateKeyAsync();
Task<List<string>> GetFingerprintAsync(string userId, byte[] publicKey = null); Task<List<string>> GetFingerprintAsync(string userId, byte[] publicKey = null);

View File

@@ -56,7 +56,7 @@ namespace Bit.Core.Services
// Refresh the Pin Key if the user has a Pin set // Refresh the Pin Key if the user has a Pin set
if (await _stateService.GetProtectedPinAsync(userId) != null) if (await _stateService.GetProtectedPinAsync(userId) != null)
{ {
await StorePinKey(userKey, userId); await UpdateUserKeyPinAsync(userKey, userId);
} }
else else
{ {
@@ -174,7 +174,7 @@ namespace Bit.Core.Services
} }
else else
{ {
throw new Exception("Unsupported encKey type."); throw new Exception($"Unsupported encrypted user key type: {encUserKey.EncryptionType}");
} }
if (decUserKey == null) if (decUserKey == null)
@@ -184,40 +184,45 @@ namespace Bit.Core.Services
return new UserKey(decUserKey); return new UserKey(decUserKey);
} }
public async Task<Tuple<SymmetricCryptoKey, EncString>> MakeDataEncKeyAsync(UserKey key) public async Task<Tuple<SymmetricCryptoKey, EncString>> MakeDataEncKeyAsync(UserKey userKey)
{ {
if (key == null) if (userKey is null)
{ {
throw new Exception("No user key provided"); throw new ArgumentNullException(nameof(userKey));
} }
var newSymKey = await _cryptoFunctionService.RandomBytesAsync(64); var newSymKey = await _cryptoFunctionService.RandomBytesAsync(64);
return await BuildProtectedSymmetricKey(key, newSymKey, keyBytes => new SymmetricCryptoKey(keyBytes)); return await BuildProtectedSymmetricKey(userKey, newSymKey, keyBytes => new SymmetricCryptoKey(keyBytes));
} }
public async Task<Tuple<SymmetricCryptoKey, EncString>> MakeDataEncKeyAsync(OrgKey key) public async Task<Tuple<SymmetricCryptoKey, EncString>> MakeDataEncKeyAsync(OrgKey orgKey)
{ {
if (key == null) if (orgKey is null)
{ {
throw new Exception("No org key provided"); throw new ArgumentNullException(nameof(orgKey));
} }
var newSymKey = await _cryptoFunctionService.RandomBytesAsync(64); var newSymKey = await _cryptoFunctionService.RandomBytesAsync(64);
return await BuildProtectedSymmetricKey(key, newSymKey, keyBytes => new SymmetricCryptoKey(keyBytes)); return await BuildProtectedSymmetricKey(orgKey, newSymKey, keyBytes => new SymmetricCryptoKey(keyBytes));
} }
public async Task<string> HashMasterKeyAsync(string password, MasterKey masterKey, HashPurpose hashPurpose = HashPurpose.ServerAuthorization) public async Task<string> HashMasterKeyAsync(string password, MasterKey masterKey, HashPurpose hashPurpose = HashPurpose.ServerAuthorization)
{ {
if (masterKey == null) if (password is null)
{
throw new ArgumentNullException(nameof(password));
}
if (masterKey is null)
{ {
masterKey = await GetMasterKeyAsync(); masterKey = await GetMasterKeyAsync();
if (masterKey is null)
{
throw new ArgumentNullException(nameof(masterKey));
}
} }
if (password == null || masterKey == null) var hash = await _cryptoFunctionService.Pbkdf2Async(masterKey.Key, password, CryptoHashAlgorithm.Sha256, (int)hashPurpose);
{
throw new Exception("Invalid parameters.");
}
var iterations = hashPurpose == HashPurpose.LocalAuthorization ? 2 : 1;
var hash = await _cryptoFunctionService.Pbkdf2Async(masterKey.Key, password, CryptoHashAlgorithm.Sha256, iterations);
return Convert.ToBase64String(hash); return Convert.ToBase64String(hash);
} }
@@ -259,7 +264,7 @@ namespace Bit.Core.Services
} }
var serverPasswordHash = await HashMasterKeyAsync(masterPassword, key, HashPurpose.ServerAuthorization); var serverPasswordHash = await HashMasterKeyAsync(masterPassword, key, HashPurpose.ServerAuthorization);
if (serverPasswordHash != null & storedPasswordHash == serverPasswordHash) if (serverPasswordHash != null && storedPasswordHash == serverPasswordHash)
{ {
await SetMasterKeyHashAsync(localPasswordHash); await SetMasterKeyHashAsync(localPasswordHash);
return true; return true;
@@ -283,11 +288,11 @@ namespace Bit.Core.Services
return null; return null;
} }
var orgKeys = await GetOrgKeysAsync(); var orgKeys = await GetOrgKeysAsync();
if (orgKeys == null || !orgKeys.ContainsKey(orgId)) if (orgKeys?.TryGetValue(orgId, out var orgKey) == true)
{ {
return null; return orgKey;
} }
return orgKeys[orgId]; return null;
} }
public Task<Dictionary<string, OrgKey>> GetOrgKeysAsync() public Task<Dictionary<string, OrgKey>> GetOrgKeysAsync()
@@ -343,7 +348,7 @@ namespace Bit.Core.Services
} }
} }
public async Task<byte[]> GetPublicKeyAsync() public async Task<byte[]> GetUserPublicKeyAsync()
{ {
if (_publicKey != null) if (_publicKey != null)
{ {
@@ -387,7 +392,7 @@ namespace Bit.Core.Services
{ {
if (publicKey == null) if (publicKey == null)
{ {
publicKey = await GetPublicKeyAsync(); publicKey = await GetUserPublicKeyAsync();
} }
if (publicKey == null) if (publicKey == null)
{ {
@@ -427,7 +432,7 @@ namespace Bit.Core.Services
_stateService.SetUserKeyPinAsync(null, userId), _stateService.SetUserKeyPinAsync(null, userId),
_stateService.SetUserKeyPinEphemeralAsync(null, userId), _stateService.SetUserKeyPinEphemeralAsync(null, userId),
_stateService.SetProtectedPinAsync(null, userId), _stateService.SetProtectedPinAsync(null, userId),
clearDeprecatedPinKeysAsync(userId)); ClearDeprecatedPinKeysAsync(userId));
} }
public async Task<UserKey> DecryptUserKeyWithPinAsync(string pin, string salt, KdfConfig kdfConfig, EncString pinProtectedUserKey = null) public async Task<UserKey> DecryptUserKeyWithPinAsync(string pin, string salt, KdfConfig kdfConfig, EncString pinProtectedUserKey = null)
@@ -439,8 +444,8 @@ namespace Bit.Core.Services
throw new Exception("No PIN protected user key found."); throw new Exception("No PIN protected user key found.");
} }
var pinKey = await MakePinKeyAsync(pin, salt, kdfConfig); var pinKey = await MakePinKeyAsync(pin, salt, kdfConfig);
var userKey = await DecryptToBytesAsync(pinProtectedUserKey, pinKey); var userKeyBytes = await DecryptToBytesAsync(pinProtectedUserKey, pinKey);
return new UserKey(userKey); return new UserKey(userKeyBytes);
} }
// Only for migration purposes // Only for migration purposes
@@ -474,7 +479,7 @@ namespace Bit.Core.Services
{ {
if (publicKey == null) if (publicKey == null)
{ {
publicKey = await GetPublicKeyAsync(); publicKey = await GetUserPublicKeyAsync();
} }
if (publicKey == null) if (publicKey == null)
{ {
@@ -668,7 +673,7 @@ namespace Bit.Core.Services
// --HELPER METHODS-- // --HELPER METHODS--
private async Task StorePinKey(UserKey userKey, string userId = null) private async Task UpdateUserKeyPinAsync(UserKey userKey, string userId = null)
{ {
var pin = await DecryptToUtf8Async(new EncString(await _stateService.GetProtectedPinAsync(userId))); var pin = await DecryptToUtf8Async(new EncString(await _stateService.GetProtectedPinAsync(userId)));
var pinKey = await MakePinKeyAsync( var pinKey = await MakePinKeyAsync(
@@ -974,7 +979,7 @@ namespace Bit.Core.Services
return userKey; return userKey;
} }
public Task clearDeprecatedPinKeysAsync(string userId = null) public Task ClearDeprecatedPinKeysAsync(string userId = null)
{ {
return Task.WhenAll( return Task.WhenAll(
_stateService.SetPinProtectedAsync(null, userId), _stateService.SetPinProtectedAsync(null, userId),

View File

@@ -229,22 +229,19 @@ namespace Bit.Core.Services
{ {
// we can't depend on only the protected pin being set because old // we can't depend on only the protected pin being set because old
// versions only used it for MP on Restart // versions only used it for MP on Restart
var pinIsEnabled = await _stateService.GetProtectedPinAsync(userId); var isPinEnabled = await _stateService.GetProtectedPinAsync(userId) != null;
var userKeyPin = await _stateService.GetUserKeyPinAsync(userId); var hasUserKeyPin = await _stateService.GetUserKeyPinAsync(userId) != null;
var oldUserKeyPin = await _stateService.GetPinProtectedAsync(userId); var hasOldUserKeyPin = await _stateService.GetPinProtectedAsync(userId) != null;
if (userKeyPin != null || oldUserKeyPin != null) if (hasUserKeyPin || hasOldUserKeyPin)
{ {
return PinLockType.Persistent; return PinLockType.Persistent;
} }
else if (pinIsEnabled != null && userKeyPin == null && oldUserKeyPin == null) else if (isPinEnabled && !hasUserKeyPin && !hasOldUserKeyPin)
{ {
return PinLockType.Transient; return PinLockType.Transient;
} }
else return PinLockType.Disabled;
{
return PinLockType.Disabled;
}
} }
public async Task<bool> IsBiometricLockSetAsync(string userId = null) public async Task<bool> IsBiometricLockSetAsync(string userId = null)

View File

@@ -30,7 +30,7 @@ namespace Bit.iOS.Core.Controllers
private IBiometricService _biometricService; private IBiometricService _biometricService;
private IKeyConnectorService _keyConnectorService; private IKeyConnectorService _keyConnectorService;
private IAccountsManager _accountManager; private IAccountsManager _accountManager;
private PinLockEnum _pinStatus; private PinLockType _pinStatus;
private bool _pinEnabled; private bool _pinEnabled;
private bool _biometricEnabled; private bool _biometricEnabled;
private bool _biometricIntegrityValid = true; private bool _biometricIntegrityValid = true;
@@ -104,7 +104,7 @@ namespace Bit.iOS.Core.Controllers
if (autofillExtension && await _stateService.GetPasswordRepromptAutofillAsync()) if (autofillExtension && await _stateService.GetPasswordRepromptAutofillAsync())
{ {
_passwordReprompt = true; _passwordReprompt = true;
_pinStatus = PinLockEnum.Disabled; _pinStatus = PinLockType.Disabled;
_pinEnabled = false; _pinEnabled = false;
_biometricEnabled = false; _biometricEnabled = false;
} }
@@ -114,8 +114,8 @@ namespace Bit.iOS.Core.Controllers
var ephemeralPinSet = await _stateService.GetUserKeyPinEphemeralAsync() var ephemeralPinSet = await _stateService.GetUserKeyPinEphemeralAsync()
?? await _stateService.GetPinProtectedKeyAsync(); ?? await _stateService.GetPinProtectedKeyAsync();
_pinEnabled = (_pinStatus == PinLockEnum.Transient && ephemeralPinSet != null) || _pinEnabled = (_pinStatus == PinLockType.Transient && ephemeralPinSet != null) ||
_pinStatus == PinLockEnum.Persistent; _pinStatus == PinLockType.Persistent;
_biometricEnabled = await _vaultTimeoutService.IsBiometricLockSetAsync() _biometricEnabled = await _vaultTimeoutService.IsBiometricLockSetAsync()
&& await _cryptoService.HasEncryptedUserKeyAsync(); && await _cryptoService.HasEncryptedUserKeyAsync();
@@ -257,13 +257,13 @@ namespace Bit.iOS.Core.Controllers
{ {
EncString userKeyPin = null; EncString userKeyPin = null;
EncString oldPinProtected = null; EncString oldPinProtected = null;
if (_pinStatus == PinLockEnum.Persistent) if (_pinStatus == PinLockType.Persistent)
{ {
userKeyPin = await _stateService.GetUserKeyPinAsync(); userKeyPin = await _stateService.GetUserKeyPinAsync();
var oldEncryptedKey = await _stateService.GetPinProtectedAsync(); var oldEncryptedKey = await _stateService.GetPinProtectedAsync();
oldPinProtected = oldEncryptedKey != null ? new EncString(oldEncryptedKey) : null; oldPinProtected = oldEncryptedKey != null ? new EncString(oldEncryptedKey) : null;
} }
else if (_pinStatus == PinLockEnum.Transient) else if (_pinStatus == PinLockType.Transient)
{ {
userKeyPin = await _stateService.GetUserKeyPinEphemeralAsync(); userKeyPin = await _stateService.GetUserKeyPinEphemeralAsync();
oldPinProtected = await _stateService.GetPinProtectedKeyAsync(); oldPinProtected = await _stateService.GetPinProtectedKeyAsync();
@@ -273,7 +273,7 @@ namespace Bit.iOS.Core.Controllers
if (oldPinProtected != null) if (oldPinProtected != null)
{ {
userKey = await _cryptoService.DecryptAndMigrateOldPinKeyAsync( userKey = await _cryptoService.DecryptAndMigrateOldPinKeyAsync(
_pinStatus == PinLockEnum.Transient, _pinStatus == PinLockType.Transient,
inputtedValue, inputtedValue,
email, email,
kdfConfig, kdfConfig,

View File

@@ -1,20 +1,20 @@
using System; using System;
using UIKit;
using Foundation;
using Bit.iOS.Core.Views;
using Bit.App.Resources;
using Bit.iOS.Core.Utilities;
using Bit.App.Abstractions;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.App.Utilities; using Bit.App.Abstractions;
using Bit.Core.Models.Domain;
using Bit.Core.Enums;
using Bit.App.Pages;
using Bit.App.Models; using Bit.App.Models;
using Xamarin.Forms; using Bit.App.Pages;
using Bit.App.Resources;
using Bit.App.Utilities;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Models.Domain;
using Bit.Core.Services; using Bit.Core.Services;
using Bit.Core.Utilities;
using Bit.iOS.Core.Utilities;
using Bit.iOS.Core.Views;
using Foundation;
using UIKit;
using Xamarin.Forms;
namespace Bit.iOS.Core.Controllers namespace Bit.iOS.Core.Controllers
{ {
@@ -30,7 +30,7 @@ namespace Bit.iOS.Core.Controllers
private IPlatformUtilsService _platformUtilsService; private IPlatformUtilsService _platformUtilsService;
private IBiometricService _biometricService; private IBiometricService _biometricService;
private IKeyConnectorService _keyConnectorService; private IKeyConnectorService _keyConnectorService;
private PinLockEnum _pinStatus; private PinLockType _pinStatus;
private bool _pinEnabled; private bool _pinEnabled;
private bool _biometricEnabled; private bool _biometricEnabled;
private bool _biometricIntegrityValid = true; private bool _biometricIntegrityValid = true;
@@ -96,7 +96,7 @@ namespace Bit.iOS.Core.Controllers
if (autofillExtension && await _stateService.GetPasswordRepromptAutofillAsync()) if (autofillExtension && await _stateService.GetPasswordRepromptAutofillAsync())
{ {
_passwordReprompt = true; _passwordReprompt = true;
_pinStatus = PinLockEnum.Disabled; _pinStatus = PinLockType.Disabled;
_pinEnabled = false; _pinEnabled = false;
_biometricEnabled = false; _biometricEnabled = false;
} }
@@ -106,8 +106,8 @@ namespace Bit.iOS.Core.Controllers
var ephemeralPinSet = await _stateService.GetUserKeyPinEphemeralAsync() var ephemeralPinSet = await _stateService.GetUserKeyPinEphemeralAsync()
?? await _stateService.GetPinProtectedKeyAsync(); ?? await _stateService.GetPinProtectedKeyAsync();
_pinEnabled = (_pinStatus == PinLockEnum.Transient && ephemeralPinSet != null) || _pinEnabled = (_pinStatus == PinLockType.Transient && ephemeralPinSet != null) ||
_pinStatus == PinLockEnum.Persistent; _pinStatus == PinLockType.Persistent;
_biometricEnabled = await _vaultTimeoutService.IsBiometricLockSetAsync() _biometricEnabled = await _vaultTimeoutService.IsBiometricLockSetAsync()
&& await _cryptoService.HasEncryptedUserKeyAsync(); && await _cryptoService.HasEncryptedUserKeyAsync();
@@ -129,7 +129,7 @@ namespace Bit.iOS.Core.Controllers
{ {
BaseNavItem.Title = AppResources.VerifyMasterPassword; BaseNavItem.Title = AppResources.VerifyMasterPassword;
} }
BaseCancelButton.Title = AppResources.Cancel; BaseCancelButton.Title = AppResources.Cancel;
if (_biometricUnlockOnly) if (_biometricUnlockOnly)
@@ -224,13 +224,13 @@ namespace Bit.iOS.Core.Controllers
{ {
EncString userKeyPin = null; EncString userKeyPin = null;
EncString oldPinProtected = null; EncString oldPinProtected = null;
if (_pinStatus == PinLockEnum.Persistent) if (_pinStatus == PinLockType.Persistent)
{ {
userKeyPin = await _stateService.GetUserKeyPinAsync(); userKeyPin = await _stateService.GetUserKeyPinAsync();
var oldEncryptedKey = await _stateService.GetPinProtectedAsync(); var oldEncryptedKey = await _stateService.GetPinProtectedAsync();
oldPinProtected = oldEncryptedKey != null ? new EncString(oldEncryptedKey) : null; oldPinProtected = oldEncryptedKey != null ? new EncString(oldEncryptedKey) : null;
} }
else if (_pinStatus == PinLockEnum.Transient) else if (_pinStatus == PinLockType.Transient)
{ {
userKeyPin = await _stateService.GetUserKeyPinEphemeralAsync(); userKeyPin = await _stateService.GetUserKeyPinEphemeralAsync();
oldPinProtected = await _stateService.GetPinProtectedKeyAsync(); oldPinProtected = await _stateService.GetPinProtectedKeyAsync();
@@ -240,7 +240,7 @@ namespace Bit.iOS.Core.Controllers
if (oldPinProtected != null) if (oldPinProtected != null)
{ {
userKey = await _cryptoService.DecryptAndMigrateOldPinKeyAsync( userKey = await _cryptoService.DecryptAndMigrateOldPinKeyAsync(
_pinStatus == PinLockEnum.Transient, _pinStatus == PinLockType.Transient,
inputtedValue, inputtedValue,
email, email,
kdfConfig, kdfConfig,
@@ -284,7 +284,7 @@ namespace Bit.iOS.Core.Controllers
else else
{ {
var masterKey = await _cryptoService.MakeMasterKeyAsync(inputtedValue, email, kdfConfig); var masterKey = await _cryptoService.MakeMasterKeyAsync(inputtedValue, email, kdfConfig);
var storedPasswordHash = await _cryptoService.GetMasterKeyHashAsync(); var storedPasswordHash = await _cryptoService.GetMasterKeyHashAsync();
if (storedPasswordHash == null) if (storedPasswordHash == null)
{ {
@@ -395,7 +395,7 @@ namespace Bit.iOS.Core.Controllers
}); });
PresentViewController(alert, true, null); PresentViewController(alert, true, null);
} }
private async Task LogOutAsync() private async Task LogOutAsync()
{ {
await AppHelpers.LogOutAsync(await _stateService.GetActiveUserIdAsync()); await AppHelpers.LogOutAsync(await _stateService.GetActiveUserIdAsync());