You've already forked pc-usbip-runner
mirror of
https://github.com/trussed-dev/pc-usbip-runner.git
synced 2026-06-20 04:16:19 -07:00
Include usbd-ctaphid
Include usbd-ctaphid component as copied from: - https://github.com/Nitrokey/nitrokey-3-firmware/tree/9cb8afe5b6cac1a4ea5cf5001713d4f1415d8394/components/usbd-ctaphid - https://github.com/solokeys/solo2/tree/b43e3f287443fe36a2a4f6ec288d4f703a71d753/components/usbd-ctaphid To be changed, when the proper repository will get the update: - https://github.com/nickray/usbd-ctaphid
This commit is contained in:
+1
-1
@@ -26,7 +26,7 @@ fido-authenticator = { version = "0.1", features = ["dispatch"] }
|
||||
trussed = { version = "0.1", features = ["clients-3"] }
|
||||
|
||||
# components
|
||||
usbd-ctaphid = { path = "../../components/usbd-ctaphid" }
|
||||
usbd-ctaphid = { path = "components/usbd-ctaphid" }
|
||||
|
||||
# storage
|
||||
littlefs2 = "0.3.1"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
APPNAME=usbip-simulation
|
||||
APPPATH=target/debug/usbip-simulation
|
||||
FLAGS=--features=enable-logs
|
||||
|
||||
all: | start-sim attach finish-message
|
||||
|
||||
@@ -11,7 +12,7 @@ finish-message:
|
||||
.PHONY: start-sim
|
||||
start-sim: $(APPNAME)
|
||||
-$(MAKE) stop
|
||||
env RUST_LOG=debug ./$(APPNAME) &
|
||||
env RUST_LOG=debug cargo run $(FLAGS) &
|
||||
sleep 1
|
||||
|
||||
.PHONY: attach
|
||||
@@ -22,16 +23,19 @@ attach:
|
||||
sudo usbip attach -r "localhost" -b "1-1"
|
||||
sleep 5
|
||||
|
||||
.PHONY: ci
|
||||
ci:
|
||||
timeout 10 -k 5 $(MAKE)
|
||||
|
||||
.PHONY: build
|
||||
build: $(APPNAME)
|
||||
cp $(APPPATH) ./$(APPNAME) -v
|
||||
|
||||
.PHONY: build-clean
|
||||
build-clean: | clean build
|
||||
|
||||
.PHONY: $(APPNAME)
|
||||
$(APPNAME):
|
||||
cargo build --features=enable-logs
|
||||
cargo build $(FLAGS)
|
||||
|
||||
.PHONY: stop
|
||||
stop:
|
||||
@@ -54,4 +58,4 @@ build-docker:
|
||||
docker build -t usbip .
|
||||
mkdir -p cargo-cache
|
||||
docker run -it --rm -v $(PWD)/cargo-cache:/root/.cargo -v $(PWD)/../../:/app usbip $(CMD)
|
||||
touch $(APPNAME)
|
||||
touch $(APPNAME)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/target
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
||||
generate-certificate.py
|
||||
@@ -0,0 +1,28 @@
|
||||
[package]
|
||||
name = "usbd-ctaphid"
|
||||
version = "0.0.0-unreleased"
|
||||
authors = ["Nicolas Stalder <n@stalder.io>"]
|
||||
license = "Apache-2.0 OR MIT"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
ctap-types = "0.1.0"
|
||||
ctaphid-dispatch = "0.1.0"
|
||||
embedded-time = "0.12"
|
||||
delog = "0.1.0"
|
||||
heapless = "0.7"
|
||||
heapless-bytes = "0.3"
|
||||
interchange = "0.2.0"
|
||||
serde = { version = "1.0", default-features = false }
|
||||
usb-device = "0.2.3"
|
||||
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
log-all = []
|
||||
log-none = []
|
||||
log-info = []
|
||||
log-debug = []
|
||||
log-warn = []
|
||||
log-error = []
|
||||
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2019-2020 Nicolas Stalder
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,7 @@
|
||||
all-builds:
|
||||
cargo build
|
||||
cargo build --release
|
||||
cargo build --features insecure-ram-authenticator --release
|
||||
# test for actual `no_std`-ness
|
||||
cargo build --target thumbv7em-none-eabi
|
||||
cargo build --target thumbv7em-none-eabi --features insecure-ram-authenticator --release
|
||||
@@ -0,0 +1,7 @@
|
||||
[build]
|
||||
command = "curl https://sh.rustup.rs -sSf | sh -s -- -y && apt-get install llvm arm-none-eabi-gcc && source $HOME/.cargo/env && rustup target add thumbv7em-none-eabi && cargo doc --document-private-items --features insecure-ram-authenticator --target thumbv7em-none-eabi"
|
||||
publish = "target/thumbv7em-none-eabi/doc"
|
||||
|
||||
[[redirects]]
|
||||
from = "/"
|
||||
to = "/usbd-ctaphid"
|
||||
@@ -0,0 +1,32 @@
|
||||
import fido2.attestation
|
||||
import fido2.ctap2
|
||||
import fido2.hid
|
||||
|
||||
dev = fido2.ctap2.CTAP2(next(fido2.hid.CtapHidDevice.list_devices()))
|
||||
|
||||
for alg in (-7, -8):
|
||||
att = dev.make_credential(
|
||||
b"1234567890ABCDEF1234567890ABCDEF",
|
||||
{"id": "https://yamnord.com"},
|
||||
{"id": b"nickray"},
|
||||
[{"type": "public-key", "alg": alg}],
|
||||
)
|
||||
|
||||
# basic sanity check - would raise
|
||||
assert att.fmt == "packed"
|
||||
verifier = fido2.attestation.Attestation.for_type(att.fmt)()
|
||||
verifier.verify(
|
||||
att.att_statement, att.auth_data, b"1234567890ABCDEF1234567890ABCDEF"
|
||||
)
|
||||
|
||||
client_data_hash = b"some_client_data_hash_abcdefghij"
|
||||
assn = dev.get_assertion(
|
||||
"https://yamnord.com",
|
||||
client_data_hash,
|
||||
allow_list=[
|
||||
{"type": "public-key", "id": att.auth_data.credential_data.credential_id}
|
||||
],
|
||||
)
|
||||
|
||||
# basic sanity check - would raise
|
||||
assn.verify(client_data_hash, att.auth_data.credential_data.public_key)
|
||||
@@ -0,0 +1,266 @@
|
||||
// use core::convert::TryInto as _;
|
||||
// use core::convert::TryFrom as _;
|
||||
|
||||
use interchange::Requester;
|
||||
use embedded_time::duration::Extensions;
|
||||
|
||||
use crate::{
|
||||
types::Status,
|
||||
constants::{INTERRUPT_POLL_MILLISECONDS, PACKET_SIZE},
|
||||
pipe::Pipe,
|
||||
};
|
||||
|
||||
use ctaphid_dispatch::types::HidInterchange;
|
||||
|
||||
use usb_device::{
|
||||
bus::{InterfaceNumber, UsbBus, UsbBusAllocator},
|
||||
class::{ControlIn, ControlOut, UsbClass},
|
||||
control,
|
||||
descriptor::{DescriptorWriter},
|
||||
endpoint::{EndpointAddress, EndpointIn, EndpointOut},
|
||||
Result as UsbResult,
|
||||
};
|
||||
|
||||
/// Packet-level implementation of the CTAPHID protocol.
|
||||
pub struct CtapHid<'alloc, Bus: UsbBus> {
|
||||
interface: InterfaceNumber,
|
||||
pipe: Pipe<'alloc, Bus>,
|
||||
}
|
||||
|
||||
impl<'alloc, Bus> CtapHid<'alloc, Bus>
|
||||
where
|
||||
Bus: UsbBus
|
||||
{
|
||||
pub fn new(allocate: &'alloc UsbBusAllocator<Bus>, interchange: Requester<HidInterchange>, initial_milliseconds: u32)
|
||||
-> Self
|
||||
{
|
||||
// 64 bytes, interrupt endpoint polled every 5 milliseconds
|
||||
let read_endpoint: EndpointOut<'alloc, Bus> =
|
||||
allocate.interrupt(PACKET_SIZE as u16, INTERRUPT_POLL_MILLISECONDS);
|
||||
// 64 bytes, interrupt endpoint polled every 5 milliseconds
|
||||
let write_endpoint: EndpointIn<'alloc, Bus> =
|
||||
allocate.interrupt(PACKET_SIZE as u16, INTERRUPT_POLL_MILLISECONDS);
|
||||
|
||||
let pipe = Pipe::new(read_endpoint, write_endpoint, interchange, initial_milliseconds);
|
||||
|
||||
Self {
|
||||
interface: allocate.interface(),
|
||||
pipe,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set versions returned in CTAPHID_INIT
|
||||
pub fn set_version(&mut self, version: crate::Version) {
|
||||
self.pipe.set_version(version);
|
||||
}
|
||||
|
||||
/// Indicate in INIT response that Wink command is implemented.
|
||||
pub fn implements_wink(mut self) -> Self {
|
||||
self.pipe.implements |= 0x01;
|
||||
self
|
||||
}
|
||||
|
||||
/// Indicate in INIT response that RawMsg command is implemented.
|
||||
pub fn implements_ctap1(mut self) -> Self {
|
||||
self.pipe.implements &= !0x80;
|
||||
self
|
||||
}
|
||||
|
||||
/// Indicate in INIT response that Cbor command is implemented.
|
||||
pub fn implements_ctap2(mut self) -> Self {
|
||||
self.pipe.implements |= 0x04;
|
||||
self
|
||||
}
|
||||
|
||||
// implement DerefMut<Target = Pipe> instead
|
||||
pub fn pipe(&mut self) -> &mut Pipe<'alloc, Bus> {
|
||||
&mut self.pipe
|
||||
}
|
||||
|
||||
pub fn check_timeout(&mut self, milliseconds: u32) {
|
||||
self.pipe.check_timeout(milliseconds);
|
||||
}
|
||||
|
||||
/// Read response from application (if any) and start writing it to
|
||||
/// the USB bus. Should be called before managing Bus.
|
||||
pub fn check_for_app_response(&mut self) {
|
||||
self.poll();
|
||||
}
|
||||
|
||||
/// Indicate whether or not a task should be scheduled to send keepalive messages.
|
||||
pub fn did_start_processing(&mut self) -> Status {
|
||||
if self.pipe.did_start_processing() {
|
||||
Status::ReceivedData(250.milliseconds())
|
||||
} else {
|
||||
Status::Idle
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a keep alive message with 1 of 2 possible statuses.
|
||||
pub fn send_keepalive(&mut self, is_waiting_for_user_presence: bool) -> Status {
|
||||
if self.pipe.send_keepalive(is_waiting_for_user_presence) {
|
||||
Status::ReceivedData(250.milliseconds())
|
||||
} else {
|
||||
Status::Idle
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const HID_INTERFACE_CLASS: u8 = 0x03;
|
||||
|
||||
const INTERFACE_SUBCLASS_NONE: u8 = 0x0;
|
||||
// const INTERFACE_SUBCLASS_BOOT: u8 = 0x1;
|
||||
|
||||
const INTERFACE_PROTOCOL_NONE: u8 = 0x0;
|
||||
// const INTERFACE_PROTOCOL_KEYBOARD: u8 = 0x1;
|
||||
// const INTERFACE_PROTOCOL_MOUSE: u8 = 0x2;
|
||||
|
||||
const HID_DESCRIPTOR: u8 = 0x21;
|
||||
const HID_REPORT_DESCRIPTOR: u8 = 0x22;
|
||||
|
||||
// cf. https://git.io/Jebh8
|
||||
// integers are little-endian
|
||||
const FIDO_HID_REPORT_DESCRIPTOR_LENGTH: usize = 34;
|
||||
const FIDO_HID_REPORT_DESCRIPTOR: [u8; FIDO_HID_REPORT_DESCRIPTOR_LENGTH] = [
|
||||
// Usage page (vendor defined): 0xF1D0 (FIDO_USAGE_PAGE)
|
||||
0x06, 0xD0, 0xF1,
|
||||
// Usage ID (vendor defined): 0x1 (FIDO_USAGE_CTAPHID)
|
||||
0x09, 0x01,
|
||||
|
||||
// Collection (application)
|
||||
0xA1, 0x01,
|
||||
|
||||
// The Input report
|
||||
0x09, 0x03, // Usage ID - vendor defined: FIDO_USAGE_DATA_IN
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8 bits)
|
||||
0x95, PACKET_SIZE as u8, // Report Count (64 fields)
|
||||
0x81, 0x08, // Input (Data, Variable, Absolute)
|
||||
|
||||
// The Output report
|
||||
0x09, 0x04, // Usage ID - vendor defined: FIDO_USAGE_DATA_OUT
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8 bits)
|
||||
0x95, PACKET_SIZE as u8, // Report Count (64 fields)
|
||||
0x91, 0x08, // Output (Data, Variable, Absolute)
|
||||
|
||||
// EndCollection
|
||||
0xC0,
|
||||
];
|
||||
|
||||
// see hid1_11.pdf, section 7.2, p. 50
|
||||
#[derive(Copy,Clone,Eq,Debug,PartialEq)]
|
||||
pub enum ClassRequests {
|
||||
/// mandatory, allow host to receive report via control pipe.
|
||||
/// intention: initialization
|
||||
GetReport = 0x1,
|
||||
GetIdle = 0x2,
|
||||
/// only boot subclass
|
||||
GetProtocol = 0x3,
|
||||
SetReport = 0x9,
|
||||
SetIdle = 0xA,
|
||||
/// only boot subclass
|
||||
SetProtocol = 0xB,
|
||||
}
|
||||
|
||||
impl<'alloc, Bus> UsbClass<Bus> for CtapHid<'alloc, Bus>
|
||||
where Bus: UsbBus
|
||||
{
|
||||
fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> UsbResult<()> {
|
||||
|
||||
writer.interface(
|
||||
self.interface,
|
||||
HID_INTERFACE_CLASS,
|
||||
INTERFACE_SUBCLASS_NONE,
|
||||
INTERFACE_PROTOCOL_NONE,
|
||||
)?;
|
||||
|
||||
// little-endian integers
|
||||
writer.write(HID_DESCRIPTOR, &[
|
||||
0x11, 0x01, // bcdHID (le)
|
||||
0x00, // country code: universal
|
||||
0x01, // number of HID report descriptors
|
||||
HID_REPORT_DESCRIPTOR, // 1st HID report descriptor type
|
||||
FIDO_HID_REPORT_DESCRIPTOR_LENGTH as u8, 0x00, // 1st HID report descriptor length in bytes as u16-be
|
||||
])?;
|
||||
|
||||
writer.endpoint(&self.pipe.read_endpoint())?;
|
||||
writer.endpoint(&self.pipe.write_endpoint())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn poll(&mut self) {
|
||||
// debug!("state = {:?}", self.pipe().state);
|
||||
self.pipe.handle_response();
|
||||
self.pipe.maybe_write_packet();
|
||||
}
|
||||
|
||||
// called when endpoint with given address received a packet
|
||||
// TODO: should misbehaving clients be blacklisted?
|
||||
fn endpoint_out(&mut self, addr: EndpointAddress) {
|
||||
if addr == self.pipe.read_address() {
|
||||
self.pipe.read_and_handle_packet();
|
||||
}
|
||||
}
|
||||
|
||||
// called when endpoint with given address sent a packet
|
||||
fn endpoint_in_complete(&mut self, addr: EndpointAddress) {
|
||||
if addr == self.pipe.write_address() {
|
||||
self.pipe.maybe_write_packet();
|
||||
}
|
||||
}
|
||||
|
||||
fn control_out(&mut self, xfer: ControlOut<Bus>) {
|
||||
let req = xfer.request();
|
||||
|
||||
if req.request_type == control::RequestType::Class
|
||||
&& req.recipient == control::Recipient::Interface
|
||||
&& req.index == u8::from(self.interface) as u16
|
||||
{
|
||||
match req.request {
|
||||
// SetIdle (0xA)
|
||||
// duration = upper byte of wValue
|
||||
// repot ID = lower byte of wValue
|
||||
// happens during enumeration with wValue = 0x0000,
|
||||
//
|
||||
// tells device to NAK any polls on interrupt IN
|
||||
// while its current report remains unchanged
|
||||
r if r == ClassRequests::SetIdle as u8 => {
|
||||
xfer.accept().ok();
|
||||
},
|
||||
_ => (),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn control_in(&mut self, xfer: ControlIn<Bus>) {
|
||||
let req = xfer.request();
|
||||
|
||||
if req.request_type == control::RequestType::Standard
|
||||
&& req.recipient == control::Recipient::Interface
|
||||
&& req.index == u8::from(self.interface) as u16
|
||||
{
|
||||
match req.request {
|
||||
// GetDescriptor (0x6),
|
||||
// wValue: 0x2200,
|
||||
// wIndex: 0x0,
|
||||
// wLength: 0x22, (34 bytes)
|
||||
control::Request::GET_DESCRIPTOR => {
|
||||
xfer.accept(|data| {
|
||||
assert!(data.len() >= FIDO_HID_REPORT_DESCRIPTOR_LENGTH);
|
||||
data[..FIDO_HID_REPORT_DESCRIPTOR_LENGTH]
|
||||
.copy_from_slice(&FIDO_HID_REPORT_DESCRIPTOR);
|
||||
Ok(FIDO_HID_REPORT_DESCRIPTOR_LENGTH)
|
||||
}).ok();
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
pub const INTERRUPT_POLL_MILLISECONDS: u8 = 5;
|
||||
|
||||
pub const PACKET_SIZE: usize = 64;
|
||||
|
||||
// 1200
|
||||
// pub const MESSAGE_SIZE: usize = ctap_types::sizes::REALISTIC_MAX_MESSAGE_SIZE;
|
||||
pub const MESSAGE_SIZE: usize = 3072;
|
||||
@@ -0,0 +1,32 @@
|
||||
#![no_std]
|
||||
|
||||
/*!
|
||||
usbd-ctaphid
|
||||
|
||||
See "proposed standard":
|
||||
https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#usb
|
||||
|
||||
*/
|
||||
|
||||
#[macro_use]
|
||||
extern crate delog;
|
||||
generate_macros!();
|
||||
|
||||
// use heapless_bytes as bytes;
|
||||
|
||||
// pub mod authenticator;
|
||||
|
||||
pub mod constants;
|
||||
pub mod class;
|
||||
pub use class::CtapHid;
|
||||
pub mod pipe;
|
||||
pub mod types;
|
||||
|
||||
/// major/minor/build version bytes returned in CTAPHID_INIT
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Version {
|
||||
pub major: u8,
|
||||
pub minor: u8,
|
||||
pub build: u8,
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1 @@
|
||||
Νg�1
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
use embedded_time::duration::Milliseconds;
|
||||
|
||||
// Status to indicate Whether or not to send keepalive messages
|
||||
pub enum Status {
|
||||
// No need
|
||||
Idle,
|
||||
// Should schedule take with given period in miliseconds
|
||||
ReceivedData(Milliseconds),
|
||||
}
|
||||
|
||||
pub enum KeepaliveStatus {
|
||||
Processing = 1,
|
||||
UpNeeded = 2,
|
||||
}
|
||||
Reference in New Issue
Block a user