components/
ctap.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Component for CTAP HID over USB support.
6//!
7//! This provides a component for using the CTAP driver. This allows for
8//! Client to Authenticator Protocol Authentication.
9//!
10//! Usage
11//! -----
12//! ```rust
13//! static STRINGS: &'static [&str; 3] = &[
14//!     "XYZ Corp.",     // Manufacturer
15//!     "FIDO Key",      // Product
16//!     "Serial No. 5",  // Serial number
17//! ];
18//!
19//!     let (ctap, ctap_driver) = components::ctap::CtapComponent::new(
20//!         &earlgrey::usbdev::USB,
21//!         0x1337, // My important company
22//!         0x0DEC, // My device name
23//!         strings,
24//!         board_kernel,
25//!         ctap_send_buffer,
26//!         ctap_recv_buffer,
27//!     )
28//!     .finalize(components::ctap_component_static!(lowrisc::usbdev::Usb));
29//!
30//!     ctap.enable();
31//!     ctap.attach();
32//! ```
33
34use core::mem::MaybeUninit;
35use kernel::capabilities;
36use kernel::component::Component;
37use kernel::create_capability;
38use kernel::hil;
39
40// Setup static space for the objects.
41#[macro_export]
42macro_rules! ctap_component_static {
43    ($U:ty $(,)?) => {{
44        let hid = kernel::static_buf!(capsules_extra::usb::ctap::CtapHid<'static, $U>);
45        let driver = kernel::static_buf!(
46            capsules_extra::usb_hid_driver::UsbHidDriver<
47                'static,
48                capsules_extra::usb::usb_hid_driver::UsbHidDriver<'static, $U>,
49            >
50        );
51        let send_buffer = kernel::static_buf!([u8; 64]);
52        let recv_buffer = kernel::static_buf!([u8; 64]);
53
54        (hid, driver, send_buffer, recv_buffer)
55    };};
56}
57
58pub struct CtapComponent<U: 'static + hil::usb::UsbController<'static>> {
59    board_kernel: &'static kernel::Kernel,
60    driver_num: usize,
61    usb: &'static U,
62    vendor_id: u16,
63    product_id: u16,
64    strings: &'static [&'static str; 3],
65}
66
67impl<U: 'static + hil::usb::UsbController<'static>> CtapComponent<U> {
68    pub fn new(
69        board_kernel: &'static kernel::Kernel,
70        driver_num: usize,
71        usb: &'static U,
72        vendor_id: u16,
73        product_id: u16,
74        strings: &'static [&'static str; 3],
75    ) -> CtapComponent<U> {
76        CtapComponent {
77            board_kernel,
78            driver_num,
79            usb,
80            vendor_id,
81            product_id,
82            strings,
83        }
84    }
85}
86
87impl<U: 'static + hil::usb::UsbController<'static>> Component for CtapComponent<U> {
88    type StaticInput = (
89        &'static mut MaybeUninit<capsules_extra::usb::ctap::CtapHid<'static, U>>,
90        &'static mut MaybeUninit<
91            capsules_extra::usb_hid_driver::UsbHidDriver<
92                'static,
93                capsules_extra::usb::ctap::CtapHid<'static, U>,
94            >,
95        >,
96        &'static mut MaybeUninit<[u8; 64]>,
97        &'static mut MaybeUninit<[u8; 64]>,
98    );
99    type Output = (
100        &'static capsules_extra::usb::ctap::CtapHid<'static, U>,
101        &'static capsules_extra::usb_hid_driver::UsbHidDriver<
102            'static,
103            capsules_extra::usb::ctap::CtapHid<'static, U>,
104        >,
105    );
106
107    fn finalize(self, s: Self::StaticInput) -> Self::Output {
108        let ctap = s.0.write(capsules_extra::usb::ctap::CtapHid::new(
109            self.usb,
110            self.vendor_id,
111            self.product_id,
112            self.strings,
113        ));
114        self.usb.set_client(ctap);
115
116        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
117
118        let send_buffer = s.2.write([0; 64]);
119        let recv_buffer = s.3.write([0; 64]);
120
121        let ctap_driver = s.1.write(capsules_extra::usb_hid_driver::UsbHidDriver::new(
122            ctap,
123            send_buffer,
124            recv_buffer,
125            self.board_kernel.create_grant(self.driver_num, &grant_cap),
126        ));
127
128        ctap.set_client(ctap_driver);
129
130        (ctap, ctap_driver)
131    }
132}