Consolidate PIN and UV parameters in FIDO commands
This commit is contained in:
@@ -858,10 +858,14 @@ class CredentialProviderActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
// Compute pinUvAuthParam if needed
|
||||
var pinUvAuthParam: ByteArray? = null
|
||||
if (pinProtocol != null) {
|
||||
pinUvAuthParam = pinProtocol.computeAuthParam(clientData.hash)
|
||||
// Build UV mode
|
||||
val uvMode = if (pinProtocol != null && pinProtocol.hasPinToken()) {
|
||||
FidoCommands.UvMode.AuthToken(
|
||||
pinProtocol.computeAuthParam(clientData.hash),
|
||||
protocol = 1
|
||||
)
|
||||
} else {
|
||||
FidoCommands.UvMode.None
|
||||
}
|
||||
|
||||
// Build and send command
|
||||
@@ -873,12 +877,10 @@ class CredentialProviderActivity : AppCompatActivity() {
|
||||
userName = userName,
|
||||
userDisplayName = userDisplayName,
|
||||
pubKeyCredParams = pubKeyCredParams,
|
||||
excludeList = if (excludeList.isNotEmpty()) excludeList else null,
|
||||
excludeList = excludeList.ifEmpty { null },
|
||||
requireResidentKey = residentKey.requiresResidentKey(),
|
||||
requireUserVerification = false, // UV is provided by pinUvAuthParam
|
||||
extensions = if (ctapExtensions.isNotEmpty()) ctapExtensions else null,
|
||||
pinUvAuthParam = pinUvAuthParam,
|
||||
pinUvAuthProtocol = if (pinProtocol != null) 1 else null
|
||||
uvMode = uvMode,
|
||||
extensions = ctapExtensions.ifEmpty { null },
|
||||
)
|
||||
|
||||
runOnUiThread {
|
||||
@@ -1085,21 +1087,23 @@ class CredentialProviderActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
// Compute pinUvAuthParam if needed
|
||||
var pinUvAuthParam: ByteArray? = null
|
||||
if (effectiveProtocol != null && effectiveProtocol.hasPinToken()) {
|
||||
pinUvAuthParam = effectiveProtocol.computeAuthParam(clientData.hash)
|
||||
// Build UV mode
|
||||
val uvMode = if (effectiveProtocol != null && effectiveProtocol.hasPinToken()) {
|
||||
FidoCommands.UvMode.AuthToken(
|
||||
effectiveProtocol.computeAuthParam(clientData.hash),
|
||||
protocol = 1
|
||||
)
|
||||
} else {
|
||||
FidoCommands.UvMode.None
|
||||
}
|
||||
|
||||
// Build and send command
|
||||
val command = FidoCommands.buildGetAssertion(
|
||||
rpId = rpId,
|
||||
clientDataHash = clientData.hash,
|
||||
allowList = if (allowList.isNotEmpty()) allowList else null,
|
||||
requireUserVerification = false, // UV is provided by pinUvAuthParam
|
||||
allowList = allowList.ifEmpty { null },
|
||||
uvMode = uvMode,
|
||||
extensions = hmacSecretExtensions,
|
||||
pinUvAuthParam = pinUvAuthParam,
|
||||
pinUvAuthProtocol = if (effectiveProtocol != null && effectiveProtocol.hasPinToken()) 1 else null
|
||||
)
|
||||
|
||||
runOnUiThread {
|
||||
|
||||
@@ -4,6 +4,15 @@ import java.security.MessageDigest
|
||||
|
||||
object FidoCommands {
|
||||
|
||||
sealed class UvMode {
|
||||
/** No user verification requested. */
|
||||
object None : UvMode()
|
||||
/** Ask the authenticator to perform UV itself. */
|
||||
object BuiltIn : UvMode()
|
||||
/** UV via a pinUvAuth token. */
|
||||
data class AuthToken(val param: ByteArray, val protocol: Int) : UvMode()
|
||||
}
|
||||
|
||||
fun buildMakeCredential(
|
||||
clientDataHash: ByteArray,
|
||||
rpId: String,
|
||||
@@ -14,10 +23,8 @@ object FidoCommands {
|
||||
pubKeyCredParams: List<Pair<String, Int>>,
|
||||
excludeList: List<ByteArray>? = null,
|
||||
requireResidentKey: Boolean = true,
|
||||
requireUserVerification: Boolean = true,
|
||||
uvMode: UvMode = UvMode.None,
|
||||
extensions: Map<String, Any>? = null,
|
||||
pinUvAuthParam: ByteArray? = null,
|
||||
pinUvAuthProtocol: Int? = null
|
||||
): ByteArray {
|
||||
val payload = cbor {
|
||||
map {
|
||||
@@ -62,14 +69,14 @@ object FidoCommands {
|
||||
}
|
||||
}
|
||||
|
||||
7 to map { "rk" to requireResidentKey }
|
||||
|
||||
if (pinUvAuthParam != null) {
|
||||
8 to bytes(pinUvAuthParam)
|
||||
7 to map {
|
||||
"rk" to requireResidentKey
|
||||
if (uvMode is UvMode.BuiltIn) "uv" to true
|
||||
}
|
||||
|
||||
if (pinUvAuthProtocol != null) {
|
||||
9 to pinUvAuthProtocol
|
||||
if (uvMode is UvMode.AuthToken) {
|
||||
8 to bytes(uvMode.param)
|
||||
9 to uvMode.protocol
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,10 +88,8 @@ object FidoCommands {
|
||||
rpId: String,
|
||||
clientDataHash: ByteArray,
|
||||
allowList: List<ByteArray>? = null,
|
||||
requireUserVerification: Boolean = true,
|
||||
uvMode: UvMode = UvMode.None,
|
||||
extensions: CborRaw? = null,
|
||||
pinUvAuthParam: ByteArray? = null,
|
||||
pinUvAuthProtocol: Int? = null
|
||||
): ByteArray {
|
||||
val payload = cbor {
|
||||
map {
|
||||
@@ -106,14 +111,14 @@ object FidoCommands {
|
||||
4 to extensions
|
||||
}
|
||||
|
||||
5 to map { "up" to true }
|
||||
|
||||
if (pinUvAuthParam != null) {
|
||||
6 to bytes(pinUvAuthParam)
|
||||
5 to map {
|
||||
"up" to true
|
||||
if (uvMode is UvMode.BuiltIn) "uv" to true
|
||||
}
|
||||
|
||||
if (pinUvAuthProtocol != null) {
|
||||
7 to pinUvAuthProtocol
|
||||
if (uvMode is UvMode.AuthToken) {
|
||||
6 to bytes(uvMode.param)
|
||||
7 to uvMode.protocol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,17 +329,13 @@ class PinProtocol(private val transport: FidoTransport) {
|
||||
val isInitialized: Boolean
|
||||
get() = sharedSecret != null && platformPublicKey != null
|
||||
|
||||
fun computeAuthParam(message: ByteArray): ByteArray? {
|
||||
val token = pinToken ?: return null
|
||||
fun computeAuthParam(message: ByteArray): ByteArray {
|
||||
val token = pinToken ?: throw IllegalStateException("No pin token")
|
||||
|
||||
try {
|
||||
val mac = Mac.getInstance("HmacSHA256")
|
||||
mac.init(SecretKeySpec(token, "HmacSHA256"))
|
||||
val hmacResult = mac.doFinal(message)
|
||||
return hmacResult.copyOf(16)
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
}
|
||||
val mac = Mac.getInstance("HmacSHA256")
|
||||
mac.init(SecretKeySpec(token, "HmacSHA256"))
|
||||
val hmacResult = mac.doFinal(message)
|
||||
return hmacResult.copyOf(16)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user