Skip to content

Commit

Permalink
AndroidSecureArea keys creation enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
mitrejcevski committed Sep 13, 2023
1 parent 0289a71 commit fba0cc7
Show file tree
Hide file tree
Showing 24 changed files with 1,081 additions and 244 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class DocumentAdapter : ListAdapter<DocumentInformation, RecyclerView.ViewHolder
}

private fun navigateToDetail(document: DocumentInformation, view: View) {
val direction = SelectDocumentFragmentDirections.toDocumentDetail(document.userVisibleName)
val direction = SelectDocumentFragmentDirections.toDocumentDetail(document.docName)
if (view.findNavController().currentDestination?.id == R.id.wallet) {
view.findNavController().navigate(direction)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import androidx.lifecycle.lifecycleScope
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.SecureArea.ALGORITHM_ES256
import com.android.mdl.app.R
import com.android.mdl.app.authprompt.UserAuthPromptBuilder
import com.android.mdl.app.theme.HolderAppTheme
Expand Down Expand Up @@ -112,26 +114,38 @@ class AuthConfirmationFragment : BottomSheetDialogFragment() {

private fun sendResponse() {
isSendingInProgress.value = true
when (viewModel.sendResponseForSelection()) {
is AddDocumentToResponseResult.UserAuthRequired -> requestUserAuth(false)
is AddDocumentToResponseResult.PassphraseRequired -> requestPassphrase()
else -> findNavController().navigateUp()
}
val result = viewModel.sendResponseForSelection()
onSendResponseResult(result)
}

private fun requestUserAuth(forceLskf: Boolean) {
private fun requestUserAuth(
allowLskfUnlock: Boolean,
allowBiometricUnlock: Boolean,
forceLskf: Boolean = !allowBiometricUnlock
) {
val userAuthRequest = UserAuthPromptBuilder.requestUserAuth(this)
.withTitle(getString(R.string.bio_auth_title))
.withNegativeButton(getString(R.string.bio_auth_use_pin))
.withSuccessCallback { authenticationSucceeded() }
.withCancelledCallback { retryForcingPinUse() }
.withCancelledCallback {
if (allowLskfUnlock) {
retryForcingPinUse(allowLskfUnlock, allowBiometricUnlock)
} else {
cancelAuthorization()
}
}
.withFailureCallback { authenticationFailed() }
.setForceLskf(forceLskf)
.build()
val cryptoObject = viewModel.getCryptoObject()
userAuthRequest.authenticate(cryptoObject)
if (allowLskfUnlock) {
userAuthRequest.withNegativeButton(getString(R.string.bio_auth_use_pin))
} else {
userAuthRequest.withNegativeButton("Cancel")
}
val cryptoObject = androidKeyUnlockData?.getCryptoObjectForSigning(ALGORITHM_ES256)
userAuthRequest.build().authenticate(cryptoObject)
}

private var androidKeyUnlockData: AndroidKeystoreSecureArea.KeyUnlockData? = null

private fun getSubtitle(): String {
val readerCommonName = arguments.readerCommonName
val readerIsTrusted = arguments.readerIsTrusted
Expand All @@ -147,23 +161,48 @@ class AuthConfirmationFragment : BottomSheetDialogFragment() {
}

private fun authenticationSucceeded(passphrase: String) {
viewModel.sendResponseForSelection(true, passphrase)
viewModel.sendResponseForSelection()
findNavController().navigateUp()
}

private fun authenticationSucceeded() {
try {
viewModel.sendResponseForSelection(true)
val result = viewModel.sendResponseForSelection(keyUnlockData = androidKeyUnlockData)
onSendResponseResult(result)
findNavController().navigateUp()
} catch (e: Exception) {
val message = "Send response error: ${e.message}"
log(message, e)
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
toast(message)
}
}

private fun retryForcingPinUse() {
val runnable = { requestUserAuth(true) }
private fun onSendResponseResult(result: AddDocumentToResponseResult) {
when (result) {
is AddDocumentToResponseResult.UserAuthRequired -> {
val keyUnlockData = AndroidKeystoreSecureArea.KeyUnlockData(result.keyAlias)
androidKeyUnlockData = keyUnlockData
requestUserAuth(
result.allowLSKFUnlocking,
result.allowBiometricUnlocking
)
}

is AddDocumentToResponseResult.PassphraseRequired -> {
requestPassphrase()
}

is AddDocumentToResponseResult.DocumentAdded -> {
if (result.signingKeyUsageLimitPassed) {
toast("Using previously used Auth Key")
}
findNavController().navigateUp()
}
}
}

private fun retryForcingPinUse(allowLsfk: Boolean, allowBiometric: Boolean) {
val runnable = { requestUserAuth(allowLsfk, allowBiometric, true) }
// Without this delay, the prompt won't reshow
Handler(Looper.getMainLooper()).postDelayed(runnable, 100)
}
Expand All @@ -177,4 +216,8 @@ class AuthConfirmationFragment : BottomSheetDialogFragment() {
.openPassphrasePrompt()
findNavController().navigate(destination)
}

private fun toast(message: String, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(requireContext(), message, duration).show()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import com.android.identity.mdoc.request.DeviceRequestParser
data class RequestedDocumentData(
val userReadableName: String,
val identityCredentialName: String,
val needsAuth: Boolean,
val requestedElements: ArrayList<RequestedElement>,
val requestedDocument: DeviceRequestParser.DocumentRequest
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ class SignedDocumentData(
private val signedElements: List<RequestedElement>,
val identityCredentialName: String,
val documentType: String,
val readerAuth: ByteArray?,
val itemsRequest: ByteArray
) {

fun issuerSignedEntries(): MutableMap<String, Collection<String>> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ class SignedElementsCollection {
return requestedDocuments.keys.map { namespace ->
val document = requestedDocuments.getValue(namespace)
SignedDocumentData(
signedElements,
document.userReadableName,
document.requestedDocument.docType,
document.requestedDocument.readerAuth,
document.requestedDocument.itemsRequest
signedElements = signedElements,
identityCredentialName = document.identityCredentialName,
documentType = document.requestedDocument.docType,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.android.mdl.app.composables

import android.content.res.Configuration
import androidx.compose.ui.tooling.preview.Preview

@Preview(name = "Light", uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark", uiMode = Configuration.UI_MODE_NIGHT_YES)
annotation class PreviewLightDark
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package com.android.mdl.app.document

data class DocumentInformation(
val userVisibleName: String,
val docName: String,
val docType: String,
val dateProvisioned: String,
val selfSigned: Boolean,
val documentColor: Int,
val maxUsagesPerKey: Int,
val lastTimeUsed: String,
val authKeys: List<KeyData>
) {

Expand All @@ -15,7 +17,10 @@ data class DocumentInformation(
val validFrom: String,
val validUntil: String,
val issuerDataBytesCount: Int,
val usagesCount: Int
val usagesCount: Int,
val keyPurposes: Int,
val ecCurve: Int,
val isHardwareBacked: Boolean
)
}

Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import com.android.identity.*
import com.android.identity.android.legacy.*
import com.android.identity.credential.Credential
import com.android.identity.credential.NameSpacedData
import com.android.mdl.app.keystore.CredentialUtil
import com.android.mdl.app.keystore.CredentialUtil.Companion.toDocumentInformation
import com.android.mdl.app.util.CredentialUtil
import com.android.mdl.app.util.CredentialUtil.Companion.toDocumentInformation
import com.android.mdl.app.selfsigned.SelfSignedDocumentData
import com.android.mdl.app.util.DocumentData
import com.android.mdl.app.util.DocumentData.EU_PID_DOCTYPE
Expand Down
Loading

0 comments on commit fba0cc7

Please sign in to comment.