Secure secrets passed to intent

This commit is contained in:
Valere 2021-02-02 08:59:28 +01:00
parent 76b425ee8a
commit 6c9b16088f
7 changed files with 36 additions and 14 deletions

View file

@ -49,7 +49,8 @@ class ReAuthActivity : SimpleFragmentActivity(), ReAuthViewModel.Factory {
val flowType: String?,
val title: String?,
val session: String?,
val lastErrorCode: String?
val lastErrorCode: String?,
val resultKeyStoreAlias: String
) : Parcelable
// For sso
@ -101,7 +102,7 @@ class ReAuthActivity : SimpleFragmentActivity(), ReAuthViewModel.Factory {
is ReAuthEvents.PasswordFinishSuccess -> {
setResult(RESULT_OK, Intent().apply {
putExtra(RESULT_FLOW_TYPE, LoginFlowTypes.PASSWORD)
putExtra(RESULT_VALUE, it.password)
putExtra(RESULT_VALUE, it.passwordSafeForIntent)
})
finish()
}
@ -197,8 +198,13 @@ class ReAuthActivity : SimpleFragmentActivity(), ReAuthViewModel.Factory {
const val EXTRA_REASON_TITLE = "EXTRA_REASON_TITLE"
const val RESULT_FLOW_TYPE = "RESULT_FLOW_TYPE"
const val RESULT_VALUE = "RESULT_VALUE"
const val DEFAULT_RESULT_KEYSTORE_ALIAS = "ReAuthActivity"
fun newIntent(context: Context, fromError: RegistrationFlowResponse, lastErrorCode: String?, reasonTitle: String?): Intent {
fun newIntent(context: Context,
fromError: RegistrationFlowResponse,
lastErrorCode: String?,
reasonTitle: String?,
resultKeyStoreAlias: String = DEFAULT_RESULT_KEYSTORE_ALIAS): Intent {
val authType = when (fromError.nextUncompletedStage()) {
LoginFlowTypes.PASSWORD -> {
LoginFlowTypes.PASSWORD
@ -212,7 +218,7 @@ class ReAuthActivity : SimpleFragmentActivity(), ReAuthViewModel.Factory {
}
}
return Intent(context, ReAuthActivity::class.java).apply {
putExtra(MvRx.KEY_ARG, Args(authType, reasonTitle, fromError.session, lastErrorCode))
putExtra(MvRx.KEY_ARG, Args(authType, reasonTitle, fromError.session, lastErrorCode, resultKeyStoreAlias))
}
}
}

View file

@ -21,5 +21,5 @@ import im.vector.app.core.platform.VectorViewEvents
sealed class ReAuthEvents : VectorViewEvents {
data class OpenSsoURl(val url: String) : ReAuthEvents()
object Dismiss : ReAuthEvents()
data class PasswordFinishSuccess(val password: String) : ReAuthEvents()
data class PasswordFinishSuccess(val passwordSafeForIntent: String) : ReAuthEvents()
}

View file

@ -24,13 +24,15 @@ data class ReAuthState(
val flowType: String? = null,
val ssoFallbackPageWasShown: Boolean = false,
val passwordVisible: Boolean = false,
val lastErrorCode: String? = null
val lastErrorCode: String? = null,
val resultKeyStoreAlias: String = ""
) : MvRxState {
constructor(args: ReAuthActivity.Args) : this(
args.title,
args.session,
args.flowType,
lastErrorCode = args.lastErrorCode
lastErrorCode = args.lastErrorCode,
resultKeyStoreAlias = args.resultKeyStoreAlias
)
constructor() : this(null, null)

View file

@ -24,14 +24,14 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.platform.VectorViewModel
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
import java.io.ByteArrayOutputStream
class ReAuthViewModel @AssistedInject constructor(
@Assisted val initialState: ReAuthState,
private val session: Session,
private val authenticationService: AuthenticationService
private val session: Session
) : VectorViewModel<ReAuthState, ReAuthActions, ReAuthEvents>(initialState) {
@AssistedFactory
@ -72,7 +72,12 @@ class ReAuthViewModel @AssistedInject constructor(
}
}
is ReAuthActions.ReAuthWithPass -> {
_viewEvents.post(ReAuthEvents.PasswordFinishSuccess(action.password))
val safeForIntentCypher = ByteArrayOutputStream().also {
it.use {
session.securelyStoreObject(action.password, initialState.resultKeyStoreAlias, it)
}
}.toByteArray().toBase64NoPadding()
_viewEvents.post(ReAuthEvents.PasswordFinishSuccess(safeForIntentCypher))
}
}
}

View file

@ -34,6 +34,7 @@ import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.WaitingViewData
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.auth.ReAuthActivity
import im.vector.app.features.login.ReAuthHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -44,6 +45,7 @@ import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
import org.matrix.android.sdk.internal.auth.registration.RegistrationFlowResponse
import org.matrix.android.sdk.internal.auth.registration.nextUncompletedStage
import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
import org.matrix.android.sdk.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey
import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth
@ -269,10 +271,11 @@ class BootstrapSharedViewModel @AssistedInject constructor(
uiaContinuation?.resume(DefaultBaseAuth(session = pendingAuth?.session ?: ""))
}
is BootstrapActions.PasswordAuthDone -> {
val decryptedPass = session.loadSecureSecret<String>(action.password.fromBase64().inputStream(), ReAuthActivity.DEFAULT_RESULT_KEYSTORE_ALIAS)
uiaContinuation?.resume(
UserPasswordAuth(
session = pendingAuth?.session,
password = action.password,
password = decryptedPass,
user = session.myUserId
)
)

View file

@ -26,6 +26,7 @@ import im.vector.app.R
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.auth.ReAuthActivity
import im.vector.app.features.login.ReAuthHelper
import io.reactivex.Observable
import io.reactivex.functions.BiFunction
@ -38,6 +39,7 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.auth.registration.RegistrationFlowResponse
import org.matrix.android.sdk.internal.auth.registration.nextUncompletedStage
import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
import org.matrix.android.sdk.internal.crypto.crosssigning.isVerified
import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
@ -134,10 +136,11 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(
Unit
}
is CrossSigningSettingsAction.PasswordAuthDone -> {
val decryptedPass = session.loadSecureSecret<String>(action.password.fromBase64().inputStream(), ReAuthActivity.DEFAULT_RESULT_KEYSTORE_ALIAS)
uiaContinuation?.resume(
UserPasswordAuth(
session = pendingAuth?.session,
password = action.password,
password = decryptedPass,
user = session.myUserId
)
)

View file

@ -32,6 +32,7 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.auth.ReAuthActivity
import im.vector.app.features.login.ReAuthHelper
import io.reactivex.Observable
import io.reactivex.functions.BiFunction
@ -51,6 +52,7 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxStat
import org.matrix.android.sdk.internal.auth.registration.RegistrationFlowResponse
import org.matrix.android.sdk.internal.auth.registration.nextUncompletedStage
import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel
import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
@ -221,10 +223,11 @@ class DevicesViewModel @AssistedInject constructor(
Unit
}
is DevicesAction.PasswordAuthDone -> {
val decryptedPass = session.loadSecureSecret<String>(action.password.fromBase64().inputStream(), ReAuthActivity.DEFAULT_RESULT_KEYSTORE_ALIAS)
uiaContinuation?.resume(
UserPasswordAuth(
session = pendingAuth?.session,
password = action.password,
password = decryptedPass,
user = session.myUserId
)
)