* Fixes an issue where Lc bytes would be included when Nc = 0 (zero command data length). This is incorrect in ISO 7816-4:2005 (which FIDO v1.1 and v1.2 correctly describe).
This affected the `GetVersion` command; and tests have been updated accordingly.
* Renames `U2FAPDUHeader` to `CTAP1RequestAPDU`.
Using the name "CTAP1" rather than "U2F" follows the convention put forward in FIDO v2.x specs, which avoids confusion like "U2Fv2" = "CTAP1".
The previous implementation wasn't just "a header", but rather the complete APDU.
* Renames `RequestCtap1::apdu_format` to `RequestCtap1::ctap1_format` and `FidoDevice::send_apdu` to `FidoDevice::send_ctap1`. This makes it more like `RequestCtap2`, and avoids confusion later on when adding support for CTAP2 over NFC (which still uses ISO 7816-4 APDUs).
* Documents and add tests for `CTAP1RequestAPDU`, explaining the confusing state of affairs.
* Corrects comments for sample CTAP1 requests in tests.
* Do not error out if the token returns options unknown to us
This might happen, if the token is very new and supports a newer CTAP-specification.
In that case, we simply don't support it, but shouldn't error out.
* Device selection (#163)
* Add cancel-function to HIDs, which can cancel blocking reads
* Add function to clone a (Linux) device in write-only mode
* First implementation of DeviceSelector
For selecting multiple devices, if those are present.
A few lints need to be fixed and it doesn't work with PIN-tokens yet.
* Fix stupid typo in function name
* Move PIN into StatusUpdate as a callback (discoverable_creds not yet working)
* Move workaround for unsetting uv to accomodate the new PIN-retrieval process
* Fix warnings
* Send DeviceSelectionNotice on Status channel, when devices blink
Also remove the unneccessary Mutex around the status-sender, since
we have to clone it anyways into Transaction. Then we can just clone
and hand it into each device-thread.
* Trying to add latest features to mac and win
Untested, so compilation might be broken.
netbsd is only partly done and broken anyways at the moment
* Simplify HIDDevice vs. FidoDevice traits
Instead of implementing FidoDevice for each HIDDevice and implementing a bunch
of duplicate functions, that call through to HIDDevice, just extend HIDDevice
with FidoDevice.
This _might_ become a problem once we introduce NFC or such, but it is unclear
at the moment, how this is going to look like, anyways.
* Add impl FidoDevice for Windows and Mac
* Reduce number of arguments to new-device callback function
Also move functions needed by statemachine or device_selector into the
HIDDevice trait
* Make tests compile again
* Add authenticatorSelection command (CTAP2.1 only)
* Blink only when at least one token has a PIN (or UV)
With this, we can skip the "blinking"-phase if multiple tokens are there,
because we only need to blink, if at least one of them has a PIN (otherwise
we get a PIN-prompt, even though no token has been selected yet).
For tokens with no PIN (or CTAP1 tokens) we can send the normal request right
away. That will blink anyways.
* Make only tokens with some UV blink
Only let tokens with some UV (e.g. Password) blink, the others
can get the request straight away. This way, they will also blink,
but execute the request right away and cancel all other devices.
Only UV-devices would trigger callbacks, so they have to be sent a
selection-command.
* Make the is_u2f-function part of the HIDDevice trait as every device needs to have that function currently
* Move the TestDevice into its own platform and implement tests for DeviceSelector
Mostly copy&paste, plus minor adjustments to existing tests.
For the DeviceSelector-Tests, some extensions to the device have been made
(adding Sender and Receiver, giving it a function for it).
* Some AuthenticatorOptions need a default value according to spec
* Revert f3718a3: Blink for all devices, not just those with PIN
We can't let the non-UV devices continue with the regular request, because in the error-case
we can't differentiate if it is due to a bad request or something the user did (e.g. pull the
token out, or decline the request on the token, etc.).
Some errors should lead to cancelling the request altogether, the other just means "not with
this device". With our own Blink-command, we know that it works in principle. If there is an
error then it must be because of user-actions and should lead to skipping that device.
* Add status callbacks to C-API (for ctap2)
* Don't just borrow the status result, but 'forget' it on the Rust side
If we don't do this, the callback-function on C++ side can't keep a
reference to the result, which it needs for later sending a Pin back.
* Add "DeviceSelected" status update plus tests
Also moved the "DeviceUnavailable" to DeviceSelector (and send it upon removal of the token)
* First test of multi-platform CI (excluding crypto)
* Fix builds on Mac and Windows
* Add option for PinError-callback to 'say' the error is not recoverable
We use the property of channel() here, that recv will error out if the Sender is dropped.
So the status-callback can now drop the Sender without replying first, to trigger
the code to error out the 'normal' way.
This helps us to show a popup-dialog, but also cancel the current transaction cleanly.
For this, NSS-errors needed to be made cloneable, so we replaced them with their String-representation.
* Fix typo
* Implement serializing of crypto backend errors
* Add 2 more CI pipelines for building with all crypto-backends on Linux
* Change status update C-API to combined buffer+length-interface
* Revert "Change status update C-API to combined buffer+length-interface"
This reverts commit b4342e90b6.
Co-authored-by: Martin Sirringhaus <>
* Simplify C-API by serializing AttestationObject in webauthn-format
Co-authored-by: Martin Sirringhaus <>
* Add riscv64 support (#152)
Thanks!
* Fix panic msg is not a string literal warning (#149)
Fixes the non_fmt_panic warning.
* Update rand. (#164)
* Use memoffset instead of homebrew offset_of (#171)
Co-authored-by: R. Martinho Fernandes <bugs@rmf.io>
* Remove base64 from dev-dependencies, as it is now a normal dependency
* Bump application-services to the version currently vendored in mozilla-central
Co-authored-by: Makoto Kato <m_kato@ga2.so-net.ne.jp>
Co-authored-by: est31 <est31@users.noreply.github.com>
Co-authored-by: Emilio Cobos Álvarez <emilio@crisal.io>
Co-authored-by: R. Martinho Fernandes <rmf@rmf.io>
Co-authored-by: R. Martinho Fernandes <bugs@rmf.io>
Co-authored-by: Martin Sirringhaus <>
* Do not error out if the token returns options unknown to us
This might happen, if the token is very new and supports a newer CTAP-specification.
In that case, we simply don't support it, but shouldn't error out.
* Device selection (#163)
* Add cancel-function to HIDs, which can cancel blocking reads
* Add function to clone a (Linux) device in write-only mode
* First implementation of DeviceSelector
For selecting multiple devices, if those are present.
A few lints need to be fixed and it doesn't work with PIN-tokens yet.
* Fix stupid typo in function name
* Move PIN into StatusUpdate as a callback (discoverable_creds not yet working)
* Move workaround for unsetting uv to accomodate the new PIN-retrieval process
* Fix warnings
* Send DeviceSelectionNotice on Status channel, when devices blink
Also remove the unneccessary Mutex around the status-sender, since
we have to clone it anyways into Transaction. Then we can just clone
and hand it into each device-thread.
* Trying to add latest features to mac and win
Untested, so compilation might be broken.
netbsd is only partly done and broken anyways at the moment
* Simplify HIDDevice vs. FidoDevice traits
Instead of implementing FidoDevice for each HIDDevice and implementing a bunch
of duplicate functions, that call through to HIDDevice, just extend HIDDevice
with FidoDevice.
This _might_ become a problem once we introduce NFC or such, but it is unclear
at the moment, how this is going to look like, anyways.
* Add impl FidoDevice for Windows and Mac
* Reduce number of arguments to new-device callback function
Also move functions needed by statemachine or device_selector into the
HIDDevice trait
* Make tests compile again
* Add authenticatorSelection command (CTAP2.1 only)
* Blink only when at least one token has a PIN (or UV)
With this, we can skip the "blinking"-phase if multiple tokens are there,
because we only need to blink, if at least one of them has a PIN (otherwise
we get a PIN-prompt, even though no token has been selected yet).
For tokens with no PIN (or CTAP1 tokens) we can send the normal request right
away. That will blink anyways.
* Make only tokens with some UV blink
Only let tokens with some UV (e.g. Password) blink, the others
can get the request straight away. This way, they will also blink,
but execute the request right away and cancel all other devices.
Only UV-devices would trigger callbacks, so they have to be sent a
selection-command.
* Make the is_u2f-function part of the HIDDevice trait as every device needs to have that function currently
* Move the TestDevice into its own platform and implement tests for DeviceSelector
Mostly copy&paste, plus minor adjustments to existing tests.
For the DeviceSelector-Tests, some extensions to the device have been made
(adding Sender and Receiver, giving it a function for it).
* Some AuthenticatorOptions need a default value according to spec
* Revert f3718a3: Blink for all devices, not just those with PIN
We can't let the non-UV devices continue with the regular request, because in the error-case
we can't differentiate if it is due to a bad request or something the user did (e.g. pull the
token out, or decline the request on the token, etc.).
Some errors should lead to cancelling the request altogether, the other just means "not with
this device". With our own Blink-command, we know that it works in principle. If there is an
error then it must be because of user-actions and should lead to skipping that device.
* Add status callbacks to C-API (for ctap2)
* Don't just borrow the status result, but 'forget' it on the Rust side
If we don't do this, the callback-function on C++ side can't keep a
reference to the result, which it needs for later sending a Pin back.
* Add "DeviceSelected" status update plus tests
Also moved the "DeviceUnavailable" to DeviceSelector (and send it upon removal of the token)
* First test of multi-platform CI (excluding crypto)
* Fix builds on Mac and Windows
* Add option for PinError-callback to 'say' the error is not recoverable
We use the property of channel() here, that recv will error out if the Sender is dropped.
So the status-callback can now drop the Sender without replying first, to trigger
the code to error out the 'normal' way.
This helps us to show a popup-dialog, but also cancel the current transaction cleanly.
For this, NSS-errors needed to be made cloneable, so we replaced them with their String-representation.
* Fix typo
* Implement serializing of crypto backend errors
* Add 2 more CI pipelines for building with all crypto-backends on Linux
* Change status update C-API to combined buffer+length-interface
* Revert "Change status update C-API to combined buffer+length-interface"
This reverts commit b4342e90b6.
Co-authored-by: Martin Sirringhaus <>
* Make stub compile again
* Make NSS compile on 32bit systems
* Silence unused-warnings when building the stub
Co-authored-by: Martin Sirringhaus <>
* Add functions and example binary for Reset
* NSS should use CBC and not ECB encryption alg
* Add functions and example for set/change pin
Co-authored-by: Martin Sirringhaus <>
This might happen, if the token is very new and supports a newer CTAP-specification.
In that case, we simply don't support it, but shouldn't error out.
Co-authored-by: Martin Sirringhaus <>
* Add cancel-function to HIDs, which can cancel blocking reads
* Add function to clone a (Linux) device in write-only mode
* First implementation of DeviceSelector
For selecting multiple devices, if those are present.
A few lints need to be fixed and it doesn't work with PIN-tokens yet.
* Fix stupid typo in function name
* Move PIN into StatusUpdate as a callback (discoverable_creds not yet working)
* Move workaround for unsetting uv to accomodate the new PIN-retrieval process
* Fix warnings
* Send DeviceSelectionNotice on Status channel, when devices blink
Also remove the unneccessary Mutex around the status-sender, since
we have to clone it anyways into Transaction. Then we can just clone
and hand it into each device-thread.
* Trying to add latest features to mac and win
Untested, so compilation might be broken.
netbsd is only partly done and broken anyways at the moment
* Simplify HIDDevice vs. FidoDevice traits
Instead of implementing FidoDevice for each HIDDevice and implementing a bunch
of duplicate functions, that call through to HIDDevice, just extend HIDDevice
with FidoDevice.
This _might_ become a problem once we introduce NFC or such, but it is unclear
at the moment, how this is going to look like, anyways.
* Add impl FidoDevice for Windows and Mac
* Reduce number of arguments to new-device callback function
Also move functions needed by statemachine or device_selector into the
HIDDevice trait
* Make tests compile again
* Add authenticatorSelection command (CTAP2.1 only)
* Blink only when at least one token has a PIN (or UV)
With this, we can skip the "blinking"-phase if multiple tokens are there,
because we only need to blink, if at least one of them has a PIN (otherwise
we get a PIN-prompt, even though no token has been selected yet).
For tokens with no PIN (or CTAP1 tokens) we can send the normal request right
away. That will blink anyways.
* Make only tokens with some UV blink
Only let tokens with some UV (e.g. Password) blink, the others
can get the request straight away. This way, they will also blink,
but execute the request right away and cancel all other devices.
Only UV-devices would trigger callbacks, so they have to be sent a
selection-command.
* Make the is_u2f-function part of the HIDDevice trait as every device needs to have that function currently
* Move the TestDevice into its own platform and implement tests for DeviceSelector
Mostly copy&paste, plus minor adjustments to existing tests.
For the DeviceSelector-Tests, some extensions to the device have been made
(adding Sender and Receiver, giving it a function for it).
* Some AuthenticatorOptions need a default value according to spec
* Revert f3718a3: Blink for all devices, not just those with PIN
We can't let the non-UV devices continue with the regular request, because in the error-case
we can't differentiate if it is due to a bad request or something the user did (e.g. pull the
token out, or decline the request on the token, etc.).
Some errors should lead to cancelling the request altogether, the other just means "not with
this device". With our own Blink-command, we know that it works in principle. If there is an
error then it must be because of user-actions and should lead to skipping that device.
* Add status callbacks to C-API (for ctap2)
* Don't just borrow the status result, but 'forget' it on the Rust side
If we don't do this, the callback-function on C++ side can't keep a
reference to the result, which it needs for later sending a Pin back.
* Add "DeviceSelected" status update plus tests
Also moved the "DeviceUnavailable" to DeviceSelector (and send it upon removal of the token)
* First test of multi-platform CI (excluding crypto)
* Fix builds on Mac and Windows
* Add option for PinError-callback to 'say' the error is not recoverable
We use the property of channel() here, that recv will error out if the Sender is dropped.
So the status-callback can now drop the Sender without replying first, to trigger
the code to error out the 'normal' way.
This helps us to show a popup-dialog, but also cancel the current transaction cleanly.
For this, NSS-errors needed to be made cloneable, so we replaced them with their String-representation.
* Fix typo
* Implement serializing of crypto backend errors
* Add 2 more CI pipelines for building with all crypto-backends on Linux
* Change status update C-API to combined buffer+length-interface
* Revert "Change status update C-API to combined buffer+length-interface"
This reverts commit b4342e90b6.
Co-authored-by: Martin Sirringhaus <>
* Moving platform specific modules into new module 'transport'
* Replace capability-defines with bitflags (and add ctap2 capabilities)
* Make HID commands its own type
* Run cargo fmt and clippy
* Add test for U2F_VERSION
* CTAP2: Implement first ctap2-command GetInfo as well as ctap1-fallback GetVersion, plus tests
* WIP: Add part MakeCredentials
* Add test for (and do some fixes) for MakeCredential CTAP1 mapping
* Adjust tests with RelyingParty and name-field
* Fix serialization of MakeCredentialOptions (individually serialize members)
* Temporarily parse credential_public_key just as a byte-vector, until COSE-crate is added and able to actually parse it
* Add Option Unparsed to AttestationStatement, to currently skip parsing it (which would need a DER-parser)
* Add commands GetAssertion and GetAssertionNext. Still missing tests.
* WIP: Add clientpin command with all the crypto functionality commented out
* Remove duplicate Pin-definition
* MakeCredentials and GetAssertion now do not store Pin but PinAuth, which has to be calculated before hand
* Sort CTAPHID const values according to value
* WIP: New Manager and StateMachine-slots for CTAP2. A lot of functions are still missing.
* MakeCredentials: Remove pointless alias for HIDError
* GetInfo: Fix wrong parsing of response. Forgot to strip away the status-byte
* Linux/Device: Fix bug where file was not saved and prematurely closed, leaving a dangling filedescriptor
* WIP: Add seperate statemachine for ctap2, add example which can already call MakeCredential
* Prepare for sign-functions: Make SignResult CTAP2-aware (similar to RegisterResult)
* Add some (not all) CTAP2.1 info options to GetInfo for testing.
* Implement generic Request marker trait for GetAssertion
* Fix non-conformance with spec for GetAssertion: Only RelyingParty-ID should be send, not the entire rp
* First draft implementation of manager.sign()
- SignArgs now enum for ctap1/2 like RegisterArgs
- Same for SignResult
- Add exclude_list and allow_list to RegisterArgs and SignArgs resp.
* Remove transports-option of PublicKeyCredentialDescriptor for now as older tokens dont understand it and return an error
* Fix wrongly used default of GetAssertionOptions (which has its own Default-implementation)
* Fix test for PublicKeyCredentialDescriptor because of removed transport-serialization
* Remove some unneeded dead_code cfgs
* Remove outdated TODO-comments
* Add some comments/hints/todos
* Expose Pin at a higher level to be easily found and used by users
* First draft of the framework of crypto-module, with some dummy-content for testing
* GetInfo: When deserializing key algorithms don't abort when an unknown alg is encountered. Just mark it as unknown
* Activate openssl crypto backend for PIN usage in MakeCredentials
Moved src/ctap2/crypto.rs to src/crypto/mod.rs
Fleshed out authenticate, encrypt, decrypt, etc. functions in openssl
Use them in client_pin.rs
* openssl: Clarify IV comments. Spec says IV=0 for all use cases
* GetAssertion: Implement pin_auth and use it to get user_verification in GetAssertionResponse
* PIN: Implement automated GetRetires if pin was wrong. Re-wrap several other pin-related Errors
* Implement Ring backend as far as possible for now (ring doesn't support AES-CBC yet)
* Redirect PinRequired error and update some comments
* Implement first draft of NSS backend
* Add one more testcase: Hash and encrypt PIN
* Fix GetAssertion for CTAP1-only devices
- Defaults of GetAssertionOptions were wrong
- Skip PIN-related function for CTAP1
* Fix downward compatiblity (to use CTAP2-Manager for CTAP1 requests on CTAP1 tokens)
- Repackage CTAP1 requests for "register()" and "sign()" into CTAP2 data structure
- Repackage MakeCredential result only for CTAP2 requests into CTAP2 result values
- Repackage GetAssertion result into CTAP1-result if needed
- Add "is_ctap2_request()" function and only send cbor-messages if Request AND Device are CTAP2
- Introduce RelyingPartyWrapper (CTAP1 requests provide the RpIdHash only, not the complete rp)
- Copy existing ctap1-example (main.rs), but use new CTAP2 Manager
* Fix build with feature webdriver
* Fix parsing of GetAssertionResponse: Parse PublicKeyCredentialDescriptor instead of serde::Value
* First draft of capi-additions: sign-result repackaging not yet done
* For testing purposes, switch to own repo of rc_crypto (to test vendoring)
* Undo last change, switch to application-services directly
* Expose rust_ctap2_mgr_new()
* Fix various CTAP1-only bugs
- When doing CTAP1 only, use challenge directly in the requests (not hashing the whole client data)
- Package GetAssertionResult similar to MakeCredential in CTAP1 and CTAP2
- Append flags and counter before AssertionObject.u2f_sign_data() to make it identical to the CTAP1 response
* openssl: Add incomplete verify()-function to test if signature is valid. Add some commented out code on how to eventually use it
* Make Challenge a base64-encoded String
* Make RegisterResult-matching agnostic wrt number of result arguments
* Add to_vec() function to AuthenticatorData, to be able to easily serialize it again for the answer back to the RelyingParty
* Add function to serialize Alg for passing the answer to C
* Add rust_u2f_resbuf_contains to capi, to check whether certain keys are set in the result-hashmap or not (for determining if its a ctap2 or ctap1 response)
* Expose ctap2-register function to C and repackage the result accordingly
* Remove User from Ctap2-SignArgs, as it is not needed
* Expose rust_ctap2_mgr_sign() to C
* Fix bug: sign() should use WebauthnType::Get, not Create
* C-API: Introduce CTAP2.0 indicator to check whether a response is CTAP1 or 2 (used 2.0, as 2.1 will be coming soon)
* Make ctap2-sign() work
- Add client-data to CTAP2 result
- C-API: Set CTAP2 indicator in the sign-result
- C-API: Add logic to determine credential-id (if none is returned from the token, but allow_list is length 1, use that)
* Also remap PinRequired-error
* GetInfo: Remove double definition of AAGuid
* Implement Deserialize for CollectedClientData
- Implement Deserialize for WebauthnType
- Implement Deserialize for TokenBinding
- Make TokenBinding contain String, not Vec<u8> (as we get it base64-encoded from the server)
- Add some tests for it
- Fix remaining test by fixing the client_hash (reference calculated via commandline)
* Make crossOrigin not an Option anymore, as we need it when serializing. Set a default for deserializing instead.
* test: implement tests for ctap2 get_assertion
This also fixes an issue in the test frame work. Due to the drop
implementation for the test client, a panic-while-panic could occur
which prevents the developer from seeing the actual error
* Update test_get_assertion_ctap2() to new codebase
* Start to add macos support for ctap2
* Expose PIN-related errors via C-api
* Move PinErrors to toplevel error. Enhance example to ask for pin, if required.
* Avoid multiple remapping of PinErrors and map them once directly to AuthenticatorError
* Define (most) C-API constants like hashmap-IDs only once, to avoid possible mismatch between C and Rust.
* Finish up macos
* Revert "Define (most) C-API constants like hashmap-IDs only once, to avoid possible mismatch between C and Rust."
With this change, it is not possible to use the const-values in switch-case statements in C/C++.
This reverts commit d5b400252b.
* Implement HIDDevice trait for device stub / dummy, so it (hopefully) compiles on non-supported archs
* Add some explanatory comments to the HIDDevice trait
* Rename user_validation to user_verification, which is the correct term
* Wrap various RegisterArgs in structs for smaller function API and also expose MakeCredentialOptions
* Also shrink C-API for GetAssertion and expose GetAssertionOptions. Fix bug where PIN+user verification could be provided, which is not allowed
* Make User.name optional, as it is no longer required by Webauthn
* Use correct credential-id for return-value in GetAssertion. Use the old path as a Fallback in case nothing is found
* Fix broken prev. commit.
* Fix tests because User.name is now an option
* Make naming of CommandError variants consistent and remove redundant 'Parsing'-variant
* Replace custom error with invalid_length (even though the usage is a bit weird)
* Use From<CommandError>-trait of HIDError to avoid verbose map_err-calls, by using the shorter .into()
* Add another test with discoverable credentials
* Splitting c-api into u2f and ctap2-parts
- Add a bunch of functions to access ctap2 results
- Attestation statement is now returned as "raw cbor data", instead of individual pieces, that are re-assembled
- Including possibility to have multiple credentials upon signing in ("discoverable creds" might return more, which the user has to choose from)
* Fix bug in parsing ctap1-response (wrongly set flags), which was not according to spec
* Fix missing credential_ids in GetAssertion responses (most notably when using a CTAP1-only token)
* Only try to determine PIN-Auth, if the request is actually CTAP2
* Return the actual Adpu-Error instead of generic DeviceError
* Adjust MakeCredentialsOptions::default, as uv=true is problematic for ctap1. Let the webauthn-server specify it
* Rework crypto module, with better COSE defintions and being able to parse keys as structs instead of Vec<u8>
* Follow-up to 'Only try to determine PIN-Auth, if the request is actually CTAP2': Same for GetAssertion
* Fix bug where Challenge for CTAP1 requests was base64-encoded, which is wrong
* Challenge only has to be 32 bytes in case of CTAP1-mapping, not in general
* C-API: Add functions to copy username from GetAssertions
* Implement hmac-secret extension
* Remove old, commented out code
Co-authored-by: Martin Sirringhaus <>
Co-authored-by: Dominik Süß <dominik@suess.wtf>
Co-authored-by: William Brown <william@blackhats.net.au>
* WIP: Add part MakeCredentials
* Add test for (and do some fixes) for MakeCredential CTAP1 mapping
* Adjust tests with RelyingParty and name-field
* Fix serialization of MakeCredentialOptions (individually serialize members)
* Temporarily parse credential_public_key just as a byte-vector, until COSE-crate is added and able to actually parse it
* Add Option Unparsed to AttestationStatement, to currently skip parsing it (which would need a DER-parser)
* Add commands GetAssertion and GetAssertionNext. Still missing tests.
* WIP: Add clientpin command with all the crypto functionality commented out
* Remove duplicate Pin-definition
* MakeCredentials and GetAssertion now do not store Pin but PinAuth, which has to be calculated before hand
* MakeCredentials: Remove pointless alias for HIDError
* GetInfo: Fix wrong parsing of response. Forgot to strip away the status-byte
* Make naming of CommandError variants consistent and remove redundant 'Parsing'-variant
* Replace custom error with invalid_length (even though the usage is a bit weird)
* Use From<CommandError>-trait of HIDError to avoid verbose map_err-calls, by using the shorter .into()
Co-authored-by: Martin Sirringhaus <>
* Moving platform specific modules into new module 'transport'
* Replace capability-defines with bitflags (and add ctap2 capabilities)
* Make HID commands its own type
* Run cargo fmt and clippy
* Add test for U2F_VERSION
* CTAP2: Implement first ctap2-command GetInfo as well as ctap1-fallback GetVersion, plus tests
* Sort CTAPHID const values according to value
Co-authored-by: Martin Sirringhaus <>
The U2F/CTAP specifications for the HID transport allow arbitrary
sizes for the HID input/output reports, not just the standard 64 bytes.
This commit adds the general logic needed to deal with varying report
sizes and implements the relevant descriptor parsing for Linux.
The `break` only caused the inner loop to break, so the Transaction would
continue until the StateMachine itself is cancelled by the U2FManager,
which only happens when it is dropped.
This means that there would be a period in which the sign request is fully
done, but the manager is not yet dropped in which one or more other sign
requests can execute.
This implementation uses OpenBSD's fido(4) interface which provides
restricted USB HID access to FIDO/U2F security keys. fido(4) is a new
driver in OpenBSD 6.7 (6.6-current at the time of this writing);
running this code on older releases will simply not find the security
keys which is OK as full backwards compatibility is not desired.
See also: http://man.openbsd.org/fido.4
Earlier versions of core-foundation lacked runloop support, among other things,
prompting us to use core-foundation-sys. >0.6 supports everything needed out of
-sys, so let's retire direct use of core-foundation-sys.
`extern "stdcall"` really only has meaning on x86 Windows; I'm not even sure what calling `extern "stdcall"` functions on x86-64 Windows does (probably bad things?). `extern "system"` carries the correct meaning on x86 and x86-64 (and other architectures such as AArch64), so let's use that. (FWIW, `winapi` also uses `extern "system"` for these functions.)
Summary:
Add support for PublicKeyCredentialRequestOptions.userVerification. For now
this basically means that we'll abort the operation with NotAllowed, as we
don't support user verification yet.
Pass PublicKeyCredentialDescriptor.transports through to the token manager
implementations. The softoken will ignore those and pretend to support all
transports defined by the spec. The USB HID token will check for the "usb"
transport and either ignore credentials accordingly, or abort the operation.
Note: The `UserVerificationRequirement` in WebIDL is defined at https://w3c.github.io/webauthn/#assertion-options
Reviewers: jcj, smaug
Reviewed By: jcj, smaug
Bug #: 1406467
Differential Revision: https://phabricator.services.mozilla.com/D338
One cannot use #[cfg(target_os)] checks in build.rs.
Build scripts can be used to generate code so the target
is set to the host platform when they are compiled.
Having this setting exported an unconditional link
depencency whenever the host was macOS, which broke
cross-compiling, in particular for fennec builds
targetting Android.
Instead, declare the IOKit dependency on the `extern`
block which imports the symbol inside macOS-specific
code. That way final link still works, but the extra
dependency is only enabled when appropriate for the
final target, like the other platform-dependent code.
- from_u8_array is dangerous; it can cast improper arrays into structures.
Note that this change leaves it still dangerous for buffer underruns, where
it might walk onto someting else on the stack.
- The byte layouts for the structures were marked packed, which as of Rust 1.0
has undefined behavior. So switch to repr(C), which is what we want anyway.[1]
[1] https://doc.rust-lang.org/nomicon/other-reprs.html#reprc
Pull in the log crate and move all the OSX println statements to be at appropriate
log levels.
This also pulls in `env_logger`, an implementation of a logger, that obeys an
environment variable RUST_LOG. I added some notes to README.md as to how to
use it.
Optimally, we don't need `env_logger` except for tests and the binary, but
we can't eliminate it from the library form until [this PR for cargo completes](https://github.com/rust-lang/cargo/issues/1982), so we might need to refactor it out of main.rs when this becomes a Gecko lib.
But maybe not? Anyway, it's easy to change down the line.
This patch changes the OSX runloop so that, before attempting to access a
device, it should peek and see if there are any pending Add/Remove events
from the Monitor, which runs in a different thread.
Another option, which might be safer, is to use an AtomicBoolean shared between
the Monitor and the OSX platform, named something like `events_waiting`. If I'm
understanding the channel properly though, this patch's method should be OK,
and doesn't push OSX's requirements out to other platforms.
Note that the way I'm doing this - using the TryIter.size_hint - is probably
somewhat inefficient, but this already has lots of milliseconds of sleep in it,
so I'm not overly worried.
When the state machine demands we call register() to cause blinks during a sign(),
this patch sets the challenge and application parameters to all zeroes. While
not necessary for security, it's what other implementations do.
The `init_device` and `ping_device` methods both need a random of some sort,
and since we want to test those methods, it seems reasonable to - like the
challenge parameters - make the randomness be supplied by the platform. This
also lets us potentially use different random sources per platform - which is
probably not a good idea, but ... maybe?
Anyway, this unbreaks the tests.