mirror of
https://github.com/bitwarden/android.git
synced 2025-12-11 04:39:19 -06:00
[PM-26420] Add flight recorder logs for vault unlock method and PIN migration (#6052)
This commit is contained in:
parent
9874aad65a
commit
9f4bd70c8d
@ -16,6 +16,7 @@ import com.x8bit.bitwarden.data.auth.repository.util.toUserStateJsonKdfUpdatedMi
|
|||||||
import com.x8bit.bitwarden.data.auth.util.KdfParamsConstants.DEFAULT_PBKDF2_ITERATIONS
|
import com.x8bit.bitwarden.data.auth.util.KdfParamsConstants.DEFAULT_PBKDF2_ITERATIONS
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
|
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
|
||||||
|
import timber.log.Timber
|
||||||
import kotlin.collections.get
|
import kotlin.collections.get
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,6 +72,7 @@ class KdfManagerImpl(
|
|||||||
onSuccess = {
|
onSuccess = {
|
||||||
authDiskSource.userState = authDiskSource.userState
|
authDiskSource.userState = authDiskSource.userState
|
||||||
?.toUserStateJsonKdfUpdatedMinimums()
|
?.toUserStateJsonKdfUpdatedMinimums()
|
||||||
|
Timber.d("[Auth] Upgraded user's KDF to minimums")
|
||||||
UpdateKdfMinimumsResult.Success
|
UpdateKdfMinimumsResult.Success
|
||||||
},
|
},
|
||||||
onFailure = { UpdateKdfMinimumsResult.Error(error = it) },
|
onFailure = { UpdateKdfMinimumsResult.Error(error = it) },
|
||||||
|
|||||||
@ -39,6 +39,7 @@ import com.x8bit.bitwarden.data.vault.datasource.sdk.model.InitializeCryptoResul
|
|||||||
import com.x8bit.bitwarden.data.vault.manager.model.VaultStateEvent
|
import com.x8bit.bitwarden.data.vault.manager.model.VaultStateEvent
|
||||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockData
|
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockData
|
||||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
|
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
|
||||||
|
import com.x8bit.bitwarden.data.vault.repository.util.logTag
|
||||||
import com.x8bit.bitwarden.data.vault.repository.util.statusFor
|
import com.x8bit.bitwarden.data.vault.repository.util.statusFor
|
||||||
import com.x8bit.bitwarden.data.vault.repository.util.toVaultUnlockResult
|
import com.x8bit.bitwarden.data.vault.repository.util.toVaultUnlockResult
|
||||||
import com.x8bit.bitwarden.data.vault.repository.util.update
|
import com.x8bit.bitwarden.data.vault.repository.util.update
|
||||||
@ -239,7 +240,10 @@ class VaultLockManagerImpl(
|
|||||||
trustedDeviceManager
|
trustedDeviceManager
|
||||||
.trustThisDeviceIfNecessary(userId = userId)
|
.trustThisDeviceIfNecessary(userId = userId)
|
||||||
updateKdfIfNeeded(initUserCryptoMethod)
|
updateKdfIfNeeded(initUserCryptoMethod)
|
||||||
migratePinProtectedUserKeyIfNeeded(userId = userId)
|
migratePinProtectedUserKeyIfNeeded(
|
||||||
|
userId = userId,
|
||||||
|
initUserCryptoMethod = initUserCryptoMethod,
|
||||||
|
)
|
||||||
setVaultToUnlocked(userId = userId)
|
setVaultToUnlocked(userId = userId)
|
||||||
} else {
|
} else {
|
||||||
incrementInvalidUnlockCount(userId = userId)
|
incrementInvalidUnlockCount(userId = userId)
|
||||||
@ -284,12 +288,19 @@ class VaultLockManagerImpl(
|
|||||||
* Optionally marks the envelope as in-memory only if the PIN-protected user key is not present.
|
* Optionally marks the envelope as in-memory only if the PIN-protected user key is not present.
|
||||||
*
|
*
|
||||||
* @param userId The ID of the user for whom to migrate the PIN-protected user key.
|
* @param userId The ID of the user for whom to migrate the PIN-protected user key.
|
||||||
|
* @param initUserCryptoMethod The method used to initialize the user's crypto.
|
||||||
*/
|
*/
|
||||||
private suspend fun migratePinProtectedUserKeyIfNeeded(userId: String) {
|
private suspend fun migratePinProtectedUserKeyIfNeeded(
|
||||||
|
userId: String,
|
||||||
|
initUserCryptoMethod: InitUserCryptoMethod,
|
||||||
|
) {
|
||||||
val encryptedPin = authDiskSource.getEncryptedPin(userId) ?: return
|
val encryptedPin = authDiskSource.getEncryptedPin(userId) ?: return
|
||||||
if (authDiskSource.getPinProtectedUserKeyEnvelope(userId) != null) return
|
if (authDiskSource.getPinProtectedUserKeyEnvelope(userId) != null) return
|
||||||
|
|
||||||
val inMemoryOnly = authDiskSource.getPinProtectedUserKey(userId) == null
|
val inMemoryOnly = authDiskSource.getPinProtectedUserKey(userId) == null
|
||||||
|
|
||||||
|
Timber.d("[Auth] Vault unlocked, method: ${initUserCryptoMethod.logTag}")
|
||||||
|
|
||||||
vaultSdkSource.enrollPinWithEncryptedPin(userId, encryptedPin)
|
vaultSdkSource.enrollPinWithEncryptedPin(userId, encryptedPin)
|
||||||
.onSuccess { enrollPinResponse ->
|
.onSuccess { enrollPinResponse ->
|
||||||
authDiskSource.storeEncryptedPin(
|
authDiskSource.storeEncryptedPin(
|
||||||
@ -306,6 +317,11 @@ class VaultLockManagerImpl(
|
|||||||
pinProtectedUserKey = null,
|
pinProtectedUserKey = null,
|
||||||
inMemoryOnly = inMemoryOnly,
|
inMemoryOnly = inMemoryOnly,
|
||||||
)
|
)
|
||||||
|
if (inMemoryOnly) {
|
||||||
|
Timber.d("[Auth] Set PIN-protected user key in memory")
|
||||||
|
} else {
|
||||||
|
Timber.d("[Auth] Migrated from legacy PIN to PIN-protected user key envelope")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import com.x8bit.bitwarden.data.vault.repository.model.GenerateTotpResult
|
|||||||
import com.x8bit.bitwarden.data.vault.repository.model.ImportCredentialsResult
|
import com.x8bit.bitwarden.data.vault.repository.model.ImportCredentialsResult
|
||||||
import com.x8bit.bitwarden.data.vault.repository.model.TotpCodeResult
|
import com.x8bit.bitwarden.data.vault.repository.model.TotpCodeResult
|
||||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
|
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
|
||||||
|
import com.x8bit.bitwarden.data.vault.repository.util.logTag
|
||||||
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkCipher
|
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkCipher
|
||||||
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkFolder
|
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkFolder
|
||||||
import com.x8bit.bitwarden.data.vault.repository.util.toSdkAccount
|
import com.x8bit.bitwarden.data.vault.repository.util.toSdkAccount
|
||||||
@ -326,7 +327,12 @@ class VaultRepositoryImpl(
|
|||||||
)
|
)
|
||||||
authDiskSource.storeUserBiometricInitVector(userId = userId, iv = cipher.iv)
|
authDiskSource.storeUserBiometricInitVector(userId = userId, iv = cipher.iv)
|
||||||
}
|
}
|
||||||
deriveTemporaryPinProtectedUserKeyIfNecessary(userId = userId)
|
deriveTemporaryPinProtectedUserKeyIfNecessary(
|
||||||
|
userId = userId,
|
||||||
|
initUserCryptoMethod = InitUserCryptoMethod.DecryptedKey(
|
||||||
|
decryptedUserKey = decryptedUserKey,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,7 +356,13 @@ class VaultRepositoryImpl(
|
|||||||
)
|
)
|
||||||
.also {
|
.also {
|
||||||
if (it is VaultUnlockResult.Success) {
|
if (it is VaultUnlockResult.Success) {
|
||||||
deriveTemporaryPinProtectedUserKeyIfNecessary(userId = userId)
|
deriveTemporaryPinProtectedUserKeyIfNecessary(
|
||||||
|
userId = userId,
|
||||||
|
initUserCryptoMethod = InitUserCryptoMethod.Password(
|
||||||
|
password = masterPassword,
|
||||||
|
userKey = userKey,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -516,14 +528,23 @@ class VaultRepositoryImpl(
|
|||||||
* unlocks during this current app session.
|
* unlocks during this current app session.
|
||||||
*
|
*
|
||||||
* If the user's vault has not yet been unlocked, this call will do nothing.
|
* If the user's vault has not yet been unlocked, this call will do nothing.
|
||||||
|
*
|
||||||
|
* @param userId The ID of the user to check.
|
||||||
|
* @param initUserCryptoMethod The method used to initialize the user's crypto.
|
||||||
*/
|
*/
|
||||||
private suspend fun deriveTemporaryPinProtectedUserKeyIfNecessary(userId: String) {
|
private suspend fun deriveTemporaryPinProtectedUserKeyIfNecessary(
|
||||||
|
userId: String,
|
||||||
|
initUserCryptoMethod: InitUserCryptoMethod,
|
||||||
|
) {
|
||||||
val encryptedPin = authDiskSource.getEncryptedPin(userId = userId) ?: return
|
val encryptedPin = authDiskSource.getEncryptedPin(userId = userId) ?: return
|
||||||
val existingPinProtectedUserKeyEnvelope = authDiskSource
|
val existingPinProtectedUserKeyEnvelope = authDiskSource
|
||||||
.getPinProtectedUserKeyEnvelope(
|
.getPinProtectedUserKeyEnvelope(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
)
|
)
|
||||||
if (existingPinProtectedUserKeyEnvelope != null) return
|
if (existingPinProtectedUserKeyEnvelope != null) return
|
||||||
|
|
||||||
|
Timber.d("[Auth] Vault unlocked, method: ${initUserCryptoMethod.logTag}")
|
||||||
|
|
||||||
vaultSdkSource
|
vaultSdkSource
|
||||||
.enrollPinWithEncryptedPin(
|
.enrollPinWithEncryptedPin(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
@ -544,6 +565,7 @@ class VaultRepositoryImpl(
|
|||||||
pinProtectedUserKey = null,
|
pinProtectedUserKey = null,
|
||||||
inMemoryOnly = true,
|
inMemoryOnly = true,
|
||||||
)
|
)
|
||||||
|
Timber.d("[Auth] Set PIN-protected user key in memory")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.x8bit.bitwarden.data.vault.repository.util
|
||||||
|
|
||||||
|
import com.bitwarden.core.InitUserCryptoMethod
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the label for the given [InitUserCryptoMethod].
|
||||||
|
* This will be only used for logging purposes, therefore it is not localized.
|
||||||
|
*/
|
||||||
|
val InitUserCryptoMethod.logTag: String
|
||||||
|
get() = when (this) {
|
||||||
|
is InitUserCryptoMethod.AuthRequest -> "Auth Request"
|
||||||
|
is InitUserCryptoMethod.DecryptedKey -> "Decrypted Key (Never Lock/Biometrics)"
|
||||||
|
is InitUserCryptoMethod.DeviceKey -> "Device Key"
|
||||||
|
is InitUserCryptoMethod.KeyConnector -> "Key Connector"
|
||||||
|
is InitUserCryptoMethod.Password -> "Password"
|
||||||
|
is InitUserCryptoMethod.Pin -> "Pin"
|
||||||
|
is InitUserCryptoMethod.PinEnvelope -> "Pin Envelope"
|
||||||
|
is InitUserCryptoMethod.MasterPasswordUnlock -> "Master Password Unlock"
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user