mozilla/authenticator-rs

[ctap2] Missing Parameter Error with CTAP2.0 Security Key

andreydanil opened this issue · 9 comments

I'm getting errors in running the CTAP2 example with a CTAP2.0 token. Seems like it is due to this TODO: https://github.com/mozilla/authenticator-rs/blob/ctap2-2021/src/ctap2/commands/make_credentials.rs#L57. Any ideas why CTAP2.0 throws a missing parameter error?

Impact: CTAP2.0 tokens are not able to be registered and authenticated. CTAP2.1 tokens work.

Run Command:

RUST_LOG=debug  cargo run --example ctap2

Output:

Asking a security key to register now...
[2023-03-04T01:18:18Z DEBUG authenticator::authenticatorservice] register called with 1 transports, iterable is 1
[2023-03-04T01:18:18Z DEBUG authenticator::authenticatorservice] register transports_to_cancel 0
[2023-03-04T01:18:18Z DEBUG authenticator::transport::device_selector] Device added event: IOHIDDeviceRef(0x122a04390)
[2023-03-04T01:18:18Z DEBUG authenticator::transport] sending GetInfo to Device { cid: [74, 159, 196, 34] }
[2023-03-04T01:18:18Z DEBUG authenticator::transport] got from Device IOHIDDeviceRef(0x122a04390) status=Cbor: [0, 166, 1, 129, 104, 70, 73, 68, 79, 95, 50, 95, 48, 2, 129, 107, 104, 109, 97, 99, 45, 115, 101, 99, 114, 101, 116, 3, 80, 202, 183, 253, 129, 131, 98, 206, 157, 44, 169, 189, 235, 199, 214, 28, 76, 4, 162, 98, 114, 107, 245, 105, 99, 108, 105, 101, 110, 116, 80, 105, 110, 245, 5, 25, 8, 152, 6, 129, 1]
[2023-03-04T01:18:18Z DEBUG authenticator::transport] IOHIDDeviceRef(0x122a04390) infos: AuthenticatorInfo { versions: ["FIDO_2_0"], extensions: ["hmac-secret"], aaguid: AAGuid(cab7fd81-8362-ce9d-2ca9-bdebc7d61c4c), options: AuthenticatorOptions { platform_device: false, resident_key: true, client_pin: Some(true), user_presence: true, user_verification: None }, max_msg_size: Some(2200), pin_protocols: [1], max_credential_count_in_list: None, max_credential_id_length: None, transports: None, algorithms: None, max_ser_large_blob_array: None, force_pin_change: None, min_pin_length: None, firmware_version: None, max_cred_blob_length: None, max_rpids_for_set_min_pin_length: None, preferred_platform_uv_attempts: None, uv_modality: None, certifications: None, remaining_discoverable_credentials: None, vendor_prototype_config_commands: None }
[2023-03-04T01:18:18Z INFO  authenticator::statemachine] Device IOHIDDeviceRef(0x122a04390) continues with the register process
[2023-03-04T01:18:18Z DEBUG authenticator::transport] sending GetKeyAgreement { pin_protocol: 1 } to Device { cid: [74, 159, 196, 34] }
STATUS: device available: Vendor: X, Device: X, Interface: 2, Firmware: v1.1.0, Capabilities: 0d
STATUS: Continuing with device: Vendor: X, Device: X, Interface: 2, Firmware: v1.1.0, Capabilities: 0d
[2023-03-04T01:18:18Z DEBUG authenticator::transport] got from Device IOHIDDeviceRef(0x122a04390) status=Cbor: [0, 161, 1, 165, 1, 2, 3, 56, 24, 32, 1, 33, 88, 32, 59, 143, 218, 70, 14, 197, 121, 75, 75, 197, 188, 107, 84, 239, 177, 240, 163, 73, 9, 144, 241, 111, 184, 101, 63, 28, 196, 5, 140, 128, 237, 192, 34, 88, 32, 184, 82, 81, 145, 7, 188, 103, 234, 36, 37, 98, 37, 107, 148, 237, 249, 247, 44, 66, 70, 155, 17, 1, 113, 67, 119, 83, 37, 200, 107, 126, 244]
[2023-03-04T01:18:18Z DEBUG authenticator::ctap2::commands::client_pin] response status code: OK
[2023-03-04T01:18:18Z DEBUG authenticator::ctap2::commands::client_pin] GetKeyAgreement::parse_response_payload Map({Integer(1): Map({Integer(1): Integer(2), Integer(3): Integer(-25), Integer(-1): Integer(1), Integer(-2): Bytes([59, 143, 218, 70, 14, 197, 121, 75, 75, 197, 188, 107, 84, 239, 177, 240, 163, 73, 9, 144, 241, 111, 184, 101, 63, 28, 196, 5, 140, 128, 237, 192]), Integer(-3): Bytes([184, 82, 81, 145, 7, 188, 103, 234, 36, 37, 98, 37, 107, 148, 237, 249, 247, 44, 66, 70, 155, 17, 1, 113, 67, 119, 83, 37, 200, 107, 126, 244])})})
[2023-03-04T01:18:18Z INFO  authenticator::statemachine] PIN Error that requires user interaction detected. Sending it back and waiting for a reply
Enter PIN: 12341234
[2023-03-04T01:18:21Z DEBUG authenticator::transport] sending GetKeyAgreement { pin_protocol: 1 } to Device { cid: [74, 159, 196, 34] }
[2023-03-04T01:18:21Z DEBUG authenticator::transport] got from Device IOHIDDeviceRef(0x122a04390) status=Cbor: [0, 161, 1, 165, 1, 2, 3, 56, 24, 32, 1, 33, 88, 32, 59, 143, 218, 70, 14, 197, 121, 75, 75, 197, 188, 107, 84, 239, 177, 240, 163, 73, 9, 144, 241, 111, 184, 101, 63, 28, 196, 5, 140, 128, 237, 192, 34, 88, 32, 184, 82, 81, 145, 7, 188, 103, 234, 36, 37, 98, 37, 107, 148, 237, 249, 247, 44, 66, 70, 155, 17, 1, 113, 67, 119, 83, 37, 200, 107, 126, 244]
[2023-03-04T01:18:21Z DEBUG authenticator::ctap2::commands::client_pin] response status code: OK
[2023-03-04T01:18:21Z DEBUG authenticator::ctap2::commands::client_pin] GetKeyAgreement::parse_response_payload Map({Integer(1): Map({Integer(1): Integer(2), Integer(3): Integer(-25), Integer(-1): Integer(1), Integer(-2): Bytes([59, 143, 218, 70, 14, 197, 121, 75, 75, 197, 188, 107, 84, 239, 177, 240, 163, 73, 9, 144, 241, 111, 184, 101, 63, 28, 196, 5, 140, 128, 237, 192]), Integer(-3): Bytes([184, 82, 81, 145, 7, 188, 103, 234, 36, 37, 98, 37, 107, 148, 237, 249, 247, 44, 66, 70, 155, 17, 1, 113, 67, 119, 83, 37, 200, 107, 126, 244])})})
[2023-03-04T01:18:21Z DEBUG authenticator::transport] sending GetPinToken { pin_protocol: 1, shared_secret: ECDHSecret(remote: COSEKey { alg: ECDH_ES_HKDF256, key: EC2(COSEEC2Key { curve: SECP256R1, x: [59, 143, 218, 70, 14, 197, 121, 75, 75, 197, 188, 107, 84, 239, 177, 240, 163, 73, 9, 144, 241, 111, 184, 101, 63, 28, 196, 5, 140, 128, 237, 192], y: [184, 82, 81, 145, 7, 188, 103, 234, 36, 37, 98, 37, 107, 148, 237, 249, 247, 44, 66, 70, 155, 17, 1, 113, 67, 119, 83, 37, 200, 107, 126, 244] }) }, my: COSEKey { alg: ECDH_ES_HKDF256, key: EC2(COSEEC2Key { curve: SECP256R1, x: [218, 59, 201, 207, 176, 161, 194, 43, 177, 11, 94, 96, 205, 195, 37, 217, 24, 33, 155, 25, 189, 204, 112, 106, 113, 34, 25, 59, 119, 76, 123, 8], y: [10, 175, 193, 165, 195, 143, 126, 198, 41, 8, 98, 57, 51, 181, 135, 143, 92, 133, 128, 207, 253, 36, 66, 0, 249, 135, 51, 199, 100, 16, 252, 232] }) }), pin: Pin(redacted) } to Device { cid: [74, 159, 196, 34] }
[2023-03-04T01:18:21Z DEBUG authenticator::transport] got from Device IOHIDDeviceRef(0x122a04390) status=Cbor: [0, 161, 2, 88, 32, 95, 1, 210, 168, 100, 207, 212, 57, 180, 191, 64, 162, 94, 37, 53, 107, 59, 252, 253, 53, 97, 68, 175, 244, 209, 189, 82, 252, 179, 255, 238, 254]
[2023-03-04T01:18:21Z DEBUG authenticator::ctap2::commands::client_pin] response status code: OK
[2023-03-04T01:18:21Z DEBUG authenticator::ctap2::commands::client_pin] GetKeyAgreement::parse_response_payload Map({Integer(2): Bytes([95, 1, 210, 168, 100, 207, 212, 57, 180, 191, 64, 162, 94, 37, 53, 107, 59, 252, 253, 53, 97, 68, 175, 244, 209, 189, 82, 252, 179, 255, 238, 254])})
[2023-03-04T01:18:21Z DEBUG authenticator::statemachine] ------------------------------------------------------------------
[2023-03-04T01:18:21Z DEBUG authenticator::statemachine] MakeCredentials { client_data_wrapper: CollectedClientDataWrapper { client_data: CollectedClientData { webauthn_type: Create, challenge: Challenge("6li3x1exZaV52irnWtTcgw7S-H-61tnI3-T1oVobep0"), origin: "https://example.com", cross_origin: false, token_binding: None }, serialized_data: [123, 34, 116, 121, 112, 101, 34, 58, 34, 119, 101, 98, 97, 117, 116, 104, 110, 46, 99, 114, 101, 97, 116, 101, 34, 44, 34, 99, 104, 97, 108, 108, 101, 110, 103, 101, 34, 58, 34, 54, 108, 105, 51, 120, 49, 101, 120, 90, 97, 86, 53, 50, 105, 114, 110, 87, 116, 84, 99, 103, 119, 55, 83, 45, 72, 45, 54, 49, 116, 110, 73, 51, 45, 84, 49, 111, 86, 111, 98, 101, 112, 48, 34, 44, 34, 111, 114, 105, 103, 105, 110, 34, 58, 34, 104, 116, 116, 112, 115, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 34, 44, 34, 99, 114, 111, 115, 115, 79, 114, 105, 103, 105, 110, 34, 58, 102, 97, 108, 115, 101, 125] }, rp: Data(RelyingParty { id: "example.com", name: None, icon: None }), user: Some(User { id: [117, 115, 101, 114, 95, 105, 100], icon: None, name: Some("A. User"), display_name: None }), pub_cred_params: [PublicKeyCredentialParameters { alg: ES256 }, PublicKeyCredentialParameters { alg: RS256 }], exclude_list: [PublicKeyCredentialDescriptor { id: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], transports: [USB, NFC] }], extensions: MakeCredentialsExtensions { pin_min_length: None, hmac_secret: None }, options: MakeCredentialsOptions { resident_key: None, user_verification: None }, pin: Some(Pin(redacted)), pin_auth: Some(PinAuth([36, 79, 19, 75, 95, 59, 123, 129, 134, 117, 159, 205, 2, 77, 65, 136])), pin_auth_protocol: Some(1), enterprise_attestation: None }
[2023-03-04T01:18:21Z DEBUG authenticator::statemachine] ------------------------------------------------------------------
[2023-03-04T01:18:21Z DEBUG authenticator::transport] sending MakeCredentials { client_data_wrapper: CollectedClientDataWrapper { client_data: CollectedClientData { webauthn_type: Create, challenge: Challenge("6li3x1exZaV52irnWtTcgw7S-H-61tnI3-T1oVobep0"), origin: "https://example.com", cross_origin: false, token_binding: None }, serialized_data: [123, 34, 116, 121, 112, 101, 34, 58, 34, 119, 101, 98, 97, 117, 116, 104, 110, 46, 99, 114, 101, 97, 116, 101, 34, 44, 34, 99, 104, 97, 108, 108, 101, 110, 103, 101, 34, 58, 34, 54, 108, 105, 51, 120, 49, 101, 120, 90, 97, 86, 53, 50, 105, 114, 110, 87, 116, 84, 99, 103, 119, 55, 83, 45, 72, 45, 54, 49, 116, 110, 73, 51, 45, 84, 49, 111, 86, 111, 98, 101, 112, 48, 34, 44, 34, 111, 114, 105, 103, 105, 110, 34, 58, 34, 104, 116, 116, 112, 115, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 34, 44, 34, 99, 114, 111, 115, 115, 79, 114, 105, 103, 105, 110, 34, 58, 102, 97, 108, 115, 101, 125] }, rp: Data(RelyingParty { id: "example.com", name: None, icon: None }), user: Some(User { id: [117, 115, 101, 114, 95, 105, 100], icon: None, name: Some("A. User"), display_name: None }), pub_cred_params: [PublicKeyCredentialParameters { alg: ES256 }, PublicKeyCredentialParameters { alg: RS256 }], exclude_list: [PublicKeyCredentialDescriptor { id: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], transports: [USB, NFC] }], extensions: MakeCredentialsExtensions { pin_min_length: None, hmac_secret: None }, options: MakeCredentialsOptions { resident_key: None, user_verification: None }, pin: Some(Pin(redacted)), pin_auth: Some(PinAuth([36, 79, 19, 75, 95, 59, 123, 129, 134, 117, 159, 205, 2, 77, 65, 136])), pin_auth_protocol: Some(1), enterprise_attestation: None } to Device { cid: [74, 159, 196, 34] }
[2023-03-04T01:18:21Z DEBUG authenticator::ctap2::commands::make_credentials] Serialize MakeCredentials
[2023-03-04T01:18:21Z DEBUG authenticator::transport] got from Device IOHIDDeviceRef(0x122a04390) status=Cbor: [20]
[2023-03-04T01:18:21Z DEBUG authenticator::ctap2::commands::make_credentials] response status code: MissingParameter
[2023-03-04T01:18:21Z WARN  authenticator::statemachine] error happened: Error: Error issuing command: CommandError: Unexpected code: MissingParameter (None)
[2023-03-04T01:18:21Z DEBUG authenticator::authenticatorservice] Callback observer is running, cancelling 0 unchosen transports...
thread 'main' panicked at 'Registration failed: HIDError(Command(StatusCode(MissingParameter, None)))', examples/ctap2.rs:214:23

Thanks for the help!

Hm... The request coupled with the AuthenticatorInfo looks fine to me. I don't think it has anything to do with the TODO you mentioned. Since those are for CTAP2.1, and your token only supports CTAP2.0.
Can you share what kind of token you are using?

I have several security keys which I'm testing with Firefox - Yubikey (CTAP2.1) and ThinC (CTAP2.0).

Looks like the pinUvAuthParam is set for FIDO2.1 spec.

Note: Use of this "uv" option key is deprecated in CTAP2.1. Instead, platforms SHOULD create a pinUvAuthParam by obtaining pinUvAuthToken via getPinUvAuthTokenUsingUvWithPermissions or getPinUvAuthTokenUsingPinWithPermissions, as appropriate.

I suspect the issue now is around user verification: https://github.com/mozilla/authenticator-rs/blob/ctap2-2021/src/ctap2/commands/make_credentials.rs#L57

MakeCredential spec:

For backwards compatibility, platforms must be aware that FIDO_2_0 (aka CTAP2.0) authenticators always require some form of user verification for authenticatorMakeCredential operations. If a platform attempts to create a non-discoverable credential on a CTAP2.0 authenticator without including the "uv" option key or the pinUvAuthToken parameter that authenticator will return an error.

What's interesting is that the CTAP2.0 keys DO work in Chrome, Edge, Opera, and Safari just fine. I was able to register and authenticate using https://webauthn.io/.

My CTAP2.0 security keys do not work with Firefox properly, but CTAP2.1 from Yubico do work.

I have 2 Yubikeys, one full "FIDO_2_1" support, one only having "FIDO_2_1_PRE". Both work fine.
I'll get back my other key soon, which has plain "FIDO_2_0" to test. But last time I tried it, it also worked fine.

Note that the TODO you link to speaks about "user_presence" (up) not "user_verification" (uv).
Meaning: CTAP2.1 introduced up for MakeCredentialsOptions, thus supporting rk, uv and up. While CTAP2.0 only supports rk and uv.
Our code does not yet do CTAP2.1, so we are never sending up, so no token can (should) error out because of that.

But I'm guessing, you are correct that it is probably related to user verification in some way. Can you try with a FIDO_2_0-device without a PIN set?

Without the device PIN set, the CTAP2 example still fails for me for a CTAP2.0 token. Debug output:

[2023-03-06T16:29:29Z INFO  authenticator::statemachine] Device IOHIDDeviceRef(0x13c604850) continues with the register process
[2023-03-06T16:29:29Z DEBUG authenticator::transport] sending GetKeyAgreement { pin_protocol: 1 } to Device { cid: [73, 140, 3, 171] }
[2023-03-06T16:29:29Z DEBUG authenticator::transport] got from Device IOHIDDeviceRef(0x13c604850) status=Cbor: [0, 161, 1, 165, 1, 2, 3, 56, 24, 32, 1, 33, 88, 32, 52, 51, 189, 205, 203, 34, 97, 174, 187, 148, 210, 88, 153, 98, 225, 243, 94, 164, 161, 88, 152, 207, 206, 75, 74, 23, 226, 57, 72, 28, 82, 148, 34, 88, 32, 79, 67, 253, 37, 139, 196, 255, 57, 107, 249, 121, 181, 154, 81, 194, 182, 244, 177, 159, 117, 78, 58, 212, 53, 169, 241, 244, 39, 5, 118, 207, 164]
[2023-03-06T16:29:29Z DEBUG authenticator::ctap2::commands::client_pin] response status code: OK
[2023-03-06T16:29:29Z DEBUG authenticator::ctap2::commands::client_pin] GetKeyAgreement::parse_response_payload Map({Integer(1): Map({Integer(1): Integer(2), Integer(3): Integer(-25), Integer(-1): Integer(1), Integer(-2): Bytes([52, 51, 189, 205, 203, 34, 97, 174, 187, 148, 210, 88, 153, 98, 225, 243, 94, 164, 161, 88, 152, 207, 206, 75, 74, 23, 226, 57, 72, 28, 82, 148]), Integer(-3): Bytes([79, 67, 253, 37, 139, 196, 255, 57, 107, 249, 121, 181, 154, 81, 194, 182, 244, 177, 159, 117, 78, 58, 212, 53, 169, 241, 244, 39, 5, 118, 207, 164])})})
[2023-03-06T16:29:29Z DEBUG authenticator::statemachine] ------------------------------------------------------------------
[2023-03-06T16:29:29Z DEBUG authenticator::statemachine] MakeCredentials { client_data_wrapper: CollectedClientDataWrapper { client_data: CollectedClientData { webauthn_type: Create, challenge: Challenge("6li3x1exZaV52irnWtTcgw7S-H-61tnI3-T1oVobep0"), origin: "https://example.com", cross_origin: false, token_binding: None }, serialized_data: [123, 34, 116, 121, 112, 101, 34, 58, 34, 119, 101, 98, 97, 117, 116, 104, 110, 46, 99, 114, 101, 97, 116, 101, 34, 44, 34, 99, 104, 97, 108, 108, 101, 110, 103, 101, 34, 58, 34, 54, 108, 105, 51, 120, 49, 101, 120, 90, 97, 86, 53, 50, 105, 114, 110, 87, 116, 84, 99, 103, 119, 55, 83, 45, 72, 45, 54, 49, 116, 110, 73, 51, 45, 84, 49, 111, 86, 111, 98, 101, 112, 48, 34, 44, 34, 111, 114, 105, 103, 105, 110, 34, 58, 34, 104, 116, 116, 112, 115, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 34, 44, 34, 99, 114, 111, 115, 115, 79, 114, 105, 103, 105, 110, 34, 58, 102, 97, 108, 115, 101, 125] }, rp: Data(RelyingParty { id: "example.com", name: None, icon: None }), user: Some(User { id: [117, 115, 101, 114, 95, 105, 100], icon: None, name: Some("A. User"), display_name: None }), pub_cred_params: [PublicKeyCredentialParameters { alg: ES256 }, PublicKeyCredentialParameters { alg: RS256 }], exclude_list: [PublicKeyCredentialDescriptor { id: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], transports: [USB, NFC] }], extensions: MakeCredentialsExtensions { pin_min_length: None, hmac_secret: None }, options: MakeCredentialsOptions { resident_key: None, user_verification: None }, pin: None, pin_auth: None, pin_auth_protocol: None, enterprise_attestation: None }
[2023-03-06T16:29:29Z DEBUG authenticator::statemachine] ------------------------------------------------------------------
[2023-03-06T16:29:29Z DEBUG authenticator::transport] sending MakeCredentials { client_data_wrapper: CollectedClientDataWrapper { client_data: CollectedClientData { webauthn_type: Create, challenge: Challenge("6li3x1exZaV52irnWtTcgw7S-H-61tnI3-T1oVobep0"), origin: "https://example.com", cross_origin: false, token_binding: None }, serialized_data: [123, 34, 116, 121, 112, 101, 34, 58, 34, 119, 101, 98, 97, 117, 116, 104, 110, 46, 99, 114, 101, 97, 116, 101, 34, 44, 34, 99, 104, 97, 108, 108, 101, 110, 103, 101, 34, 58, 34, 54, 108, 105, 51, 120, 49, 101, 120, 90, 97, 86, 53, 50, 105, 114, 110, 87, 116, 84, 99, 103, 119, 55, 83, 45, 72, 45, 54, 49, 116, 110, 73, 51, 45, 84, 49, 111, 86, 111, 98, 101, 112, 48, 34, 44, 34, 111, 114, 105, 103, 105, 110, 34, 58, 34, 104, 116, 116, 112, 115, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 34, 44, 34, 99, 114, 111, 115, 115, 79, 114, 105, 103, 105, 110, 34, 58, 102, 97, 108, 115, 101, 125] }, rp: Data(RelyingParty { id: "example.com", name: None, icon: None }), user: Some(User { id: [117, 115, 101, 114, 95, 105, 100], icon: None, name: Some("A. User"), display_name: None }), pub_cred_params: [PublicKeyCredentialParameters { alg: ES256 }, PublicKeyCredentialParameters { alg: RS256 }], exclude_list: [PublicKeyCredentialDescriptor { id: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], transports: [USB, NFC] }], extensions: MakeCredentialsExtensions { pin_min_length: None, hmac_secret: None }, options: MakeCredentialsOptions { resident_key: None, user_verification: None }, pin: None, pin_auth: None, pin_auth_protocol: None, enterprise_attestation: None } to Device { cid: [73, 140, 3, 171] }
[2023-03-06T16:29:29Z DEBUG authenticator::ctap2::commands::make_credentials] Serialize MakeCredentials
[2023-03-06T16:29:29Z DEBUG authenticator::transport] got from Device IOHIDDeviceRef(0x13c604850) status=Cbor: [20]
[2023-03-06T16:29:29Z DEBUG authenticator::ctap2::commands::make_credentials] response status code: MissingParameter
[2023-03-06T16:29:29Z WARN  authenticator::statemachine] error happened: Error: Error issuing command: CommandError: Unexpected code: MissingParameter (None)
[2023-03-06T16:29:29Z DEBUG authenticator::authenticatorservice] Callback observer is running, cancelling 0 unchosen transports...
thread 'main' panicked at 'Registration failed: HIDError(Command(StatusCode(MissingParameter, None)))', examples/ctap2.rs:214:23

HOWEVER, I am able to register a CTAP2.0 token in Firefox 109.x without setting the token PIN.

FF Nightly (112.0a1 (2023-03-06)), CTAP2.0 behavior via webauthn.io:

Test Result
No PIN set registration PASS
PIN pre-set before registration PASS
Set PIN during registration FAIL, tracked in #223 since FF does not have the UI to set the PIN.
NO PIN set authentication FAIL, error: The authenticator was unable to process the specified options, or could not create a new assertion signature
PIN pre-set authentication FAIL, error: The authenticator was unable to process the specified options, or could not create a new assertion signature

FF Nightly (112.0a1 (2023-03-06)), CTAP2.1 behavior via webauthn.io:

Test Result
No PIN set registration PASS
PIN pre-set registration PASS
Set PIN during registration FAIL, tracked in #223
NO PIN set authentication PASS
PIN pre-set authentication PASS, but - always prompts for the PIN, cannot do UV=discouraged. Issue tracked in #162.

Curious @msirringhaus, can you reproduce this issue with your CTAP2.0 token?

Sorry for the wait.
My CTAP_2_0 token works fine with the ctap2-example.

Right now, my only guess is that it may be related to the fingerprint-capability of the ThinC.
Is this set (= Fingerprints registered)? If it is, can you try it with and without setting it?

Oh, and could you also try ctap2_discoverable_creds? (This only works, if you have a PIN set)

I just tried pulling the latest code and it appears that this commit fixed the issue!
70cd053. Without this commit, I get the Unexpected code: MissingParameter (None) exception.

Now the ctap2 example works with my CTAP2.0 security key.

Thank you jschanck@ and msirringhaus@.

I'll keep this issue open until I verify the fix in FF Nightly.

Ah, perfect.
Thanks for hanging in there!

I just built FF locally and can confirm the issue is fixed. Thanks again!