Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/bouncy castle support #375

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.android.identity.android.securearea.AndroidKeystoreSecureArea
import com.android.identity.securearea.BouncyCastleSecureArea
import com.android.identity.securearea.SecureArea.ALGORITHM_ES256
import com.android.mdl.app.R
import com.android.mdl.app.authprompt.UserAuthPromptBuilder
Expand All @@ -37,6 +38,7 @@ class AuthConfirmationFragment : BottomSheetDialogFragment() {
private val passphraseViewModel: PassphrasePromptViewModel by activityViewModels()
private val arguments by navArgs<AuthConfirmationFragmentArgs>()
private var isSendingInProgress = mutableStateOf(false)
private var androidKeyUnlockData: AndroidKeystoreSecureArea.KeyUnlockData? = null

override fun onCreateView(
inflater: LayoutInflater,
Expand Down Expand Up @@ -72,7 +74,7 @@ class AuthConfirmationFragment : BottomSheetDialogFragment() {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED) {
passphraseViewModel.authorizationState.collect { value ->
if (value is PassphraseAuthResult.Success) {
authenticationSucceeded(value.userPassphrase)
onPassphraseProvided(value.userPassphrase)
passphraseViewModel.reset()
}
}
Expand Down Expand Up @@ -144,8 +146,6 @@ class AuthConfirmationFragment : BottomSheetDialogFragment() {
userAuthRequest.build().authenticate(cryptoObject)
}

private var androidKeyUnlockData: AndroidKeystoreSecureArea.KeyUnlockData? = null

private fun getSubtitle(): String {
val readerCommonName = arguments.readerCommonName
val readerIsTrusted = arguments.readerIsTrusted
Expand All @@ -160,9 +160,10 @@ class AuthConfirmationFragment : BottomSheetDialogFragment() {
}
}

private fun authenticationSucceeded(passphrase: String) {
viewModel.sendResponseForSelection()
findNavController().navigateUp()
private fun onPassphraseProvided(passphrase: String) {
val unlockData = BouncyCastleSecureArea.KeyUnlockData(passphrase)
val result = viewModel.sendResponseForSelection(unlockData)
onSendResponseResult(result)
}

private fun authenticationSucceeded() {
Expand All @@ -179,16 +180,15 @@ class AuthConfirmationFragment : BottomSheetDialogFragment() {
private fun onSendResponseResult(result: AddDocumentToResponseResult) {
when (result) {
is AddDocumentToResponseResult.UserAuthRequired -> {
val keyUnlockData = AndroidKeystoreSecureArea.KeyUnlockData(result.keyAlias)
androidKeyUnlockData = keyUnlockData
androidKeyUnlockData = AndroidKeystoreSecureArea.KeyUnlockData(result.keyAlias)
requestUserAuth(
result.allowLSKFUnlocking,
result.allowBiometricUnlocking
)
}

is AddDocumentToResponseResult.PassphraseRequired -> {
requestPassphrase()
requestPassphrase(result.attemptedWithIncorrectPassword)
}

is AddDocumentToResponseResult.DocumentAdded -> {
Expand All @@ -210,10 +210,13 @@ class AuthConfirmationFragment : BottomSheetDialogFragment() {
viewModel.closeConnection()
}

private fun requestPassphrase() {
val destination = AuthConfirmationFragmentDirections
.openPassphrasePrompt()
findNavController().navigate(destination)
private fun requestPassphrase(attemptedWithIncorrectPassword: Boolean) {
val destination = AuthConfirmationFragmentDirections.openPassphrasePrompt(
showIncorrectPassword = attemptedWithIncorrectPassword
)
val runnable = { findNavController().navigate(destination) }
// The system needs a little time to get back to this screen
Handler(Looper.getMainLooper()).postDelayed(runnable, 500)
}

private fun toast(message: String, duration: Int = Toast.LENGTH_SHORT) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme
Expand All @@ -23,17 +24,21 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.android.mdl.app.R
import com.android.mdl.app.composables.PreviewLightDark
import com.android.mdl.app.theme.HolderAppTheme

class PassphrasePrompt : DialogFragment() {

private val args by navArgs<PassphrasePromptArgs>()
private val viewModel by activityViewModels<PassphrasePromptViewModel>()

override fun onCreateView(
Expand All @@ -45,6 +50,7 @@ class PassphrasePrompt : DialogFragment() {
setContent {
HolderAppTheme {
PassphrasePromptUI(
showIncorrectPassword = args.showIncorrectPassword,
onDone = { passphrase ->
viewModel.authorize(userPassphrase = passphrase)
findNavController().navigateUp()
Expand All @@ -58,6 +64,7 @@ class PassphrasePrompt : DialogFragment() {

@Composable
private fun PassphrasePromptUI(
showIncorrectPassword: Boolean,
onDone: (passphrase: String) -> Unit
) {
var value by remember { mutableStateOf("") }
Expand All @@ -82,8 +89,23 @@ private fun PassphrasePromptUI(
modifier = Modifier.fillMaxWidth(),
value = value,
onValueChange = { value = it },
textStyle = MaterialTheme.typography.bodyMedium
textStyle = MaterialTheme.typography.bodyMedium,
visualTransformation = PasswordVisualTransformation(),
placeholder = {
Text(
text = stringResource(id = R.string.passphrase_prompt_hint),
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = .5f)
)
}
)
if (showIncorrectPassword) {
Text(
text = stringResource(id = R.string.passphrase_prompt_incorrect_passphrase),
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.error
)
}
TextButton(
modifier = Modifier
.align(Alignment.End),
Expand All @@ -95,9 +117,23 @@ private fun PassphrasePromptUI(
}

@Composable
@Preview
@PreviewLightDark
private fun PreviewPassphrasePrompt() {
HolderAppTheme {
PassphrasePromptUI(onDone = {})
PassphrasePromptUI(
showIncorrectPassword = false,
onDone = {}
)
}
}

@Composable
@PreviewLightDark
private fun PreviewPassphrasePromptWithIncorrectPassword() {
HolderAppTheme {
PassphrasePromptUI(
showIncorrectPassword = true,
onDone = {}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ data class DocumentInformation(
val maxUsagesPerKey: Int,
val lastTimeUsed: String,
val mDocAuthOption: String,
val secureAreaImplementationState: SecureAreaImplementationState,
val authKeys: List<KeyData>
) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class DocumentInfoViewModel(
documentType = documentInformation.docType,
documentColor = documentInformation.documentColor.toCardArt(),
provisioningDate = documentInformation.dateProvisioned,
secureAreaImplementationState = documentInformation.secureAreaImplementationState,
isSelfSigned = documentInformation.selfSigned,
lastTimeUsedDate = documentInformation.lastTimeUsed,
authKeys = documentInformation.authKeys.asScreenStateKeys()
Expand Down
Loading
Loading