Add write to the environment

This commit is contained in:
Julien Cretin
2022-03-04 15:09:44 +01:00
parent dcc053c6cb
commit f09e5a77e8
6 changed files with 152 additions and 88 deletions

11
src/env/mod.rs vendored
View File

@@ -13,7 +13,7 @@ pub trait UserPresence {
/// Blocks for user presence.
///
/// Returns an error in case of timeout or keepalive error.
fn check(&self, cid: ChannelID) -> Result<(), Ctap2StatusCode>;
fn check(&mut self, cid: ChannelID) -> Result<(), Ctap2StatusCode>;
}
/// Describes what CTAP needs to function.
@@ -23,6 +23,7 @@ pub trait Env {
type Storage: Storage;
type UpgradeStorage: UpgradeStorage;
type FirmwareProtection: FirmwareProtection;
type Write: core::fmt::Write;
fn rng(&mut self) -> &mut Self::Rng;
fn user_presence(&mut self) -> &mut Self::UserPresence;
@@ -38,4 +39,12 @@ pub trait Env {
fn upgrade_storage(&mut self) -> StorageResult<Self::UpgradeStorage>;
fn firmware_protection(&mut self) -> &mut Self::FirmwareProtection;
/// Creates a write instance for debugging.
///
/// This API doesn't return a reference such that drop may flush. This matches the Tock
/// environment. Non-Tock embedded environments should use the defmt feature (to be implemented
/// using the defmt crate) and ignore this API. Non-embedded environments may either use this
/// API or use the log feature (to be implemented using the log crate).
fn write(&mut self) -> Self::Write;
}

15
src/env/test/mod.rs vendored
View File

@@ -17,6 +17,14 @@ pub struct TestUserPresence {
check: Box<dyn Fn(ChannelID) -> Result<(), Ctap2StatusCode>>,
}
pub struct TestWrite;
impl core::fmt::Write for TestWrite {
fn write_str(&mut self, _: &str) -> core::fmt::Result {
Ok(())
}
}
impl TestEnv {
pub fn new() -> Self {
let rng = ThreadRng256 {};
@@ -34,7 +42,7 @@ impl TestUserPresence {
}
impl UserPresence for TestUserPresence {
fn check(&self, cid: ChannelID) -> Result<(), Ctap2StatusCode> {
fn check(&mut self, cid: ChannelID) -> Result<(), Ctap2StatusCode> {
(self.check)(cid)
}
}
@@ -51,6 +59,7 @@ impl Env for TestEnv {
type Storage = BufferStorage;
type UpgradeStorage = BufferUpgradeStorage;
type FirmwareProtection = Self;
type Write = TestWrite;
fn rng(&mut self) -> &mut Self::Rng {
&mut self.rng
@@ -82,4 +91,8 @@ impl Env for TestEnv {
fn firmware_protection(&mut self) -> &mut Self::FirmwareProtection {
self
}
fn write(&mut self) -> Self::Write {
TestWrite
}
}

19
src/env/tock/mod.rs vendored
View File

@@ -10,7 +10,6 @@ use core::sync::atomic::{AtomicBool, Ordering};
use crypto::rng256::TockRng256;
use libtock_core::result::{CommandError, EALREADY};
use libtock_drivers::buttons::{self, ButtonState};
#[cfg(feature = "debug_ctap")]
use libtock_drivers::console::Console;
use libtock_drivers::result::{FlexUnwrap, TockError};
use libtock_drivers::timer::Duration;
@@ -58,8 +57,8 @@ pub unsafe fn steal_storage() -> StorageResult<SyscallStorage> {
}
impl UserPresence for TockEnv {
fn check(&self, cid: ChannelID) -> Result<(), Ctap2StatusCode> {
check_user_presence(cid)
fn check(&mut self, cid: ChannelID) -> Result<(), Ctap2StatusCode> {
check_user_presence(self, cid)
}
}
@@ -82,6 +81,7 @@ impl Env for TockEnv {
type Storage = SyscallStorage;
type UpgradeStorage = SyscallUpgradeStorage;
type FirmwareProtection = Self;
type Write = Console;
fn rng(&mut self) -> &mut Self::Rng {
&mut self.rng
@@ -104,6 +104,10 @@ impl Env for TockEnv {
fn firmware_protection(&mut self) -> &mut Self::FirmwareProtection {
self
}
fn write(&mut self) -> Self::Write {
Console::new()
}
}
/// Asserts a boolean is false and sets it to true.
@@ -114,10 +118,11 @@ fn assert_once(b: &mut bool) {
// Returns whether the keepalive was sent, or false if cancelled.
fn send_keepalive_up_needed(
env: &mut TockEnv,
cid: ChannelID,
timeout: Duration<isize>,
) -> Result<(), Ctap2StatusCode> {
let keepalive_msg = CtapHid::keepalive(cid, KeepaliveStatus::UpNeeded);
let keepalive_msg = CtapHid::keepalive(env, cid, KeepaliveStatus::UpNeeded);
for mut pkt in keepalive_msg {
let status = usb_ctap_hid::send_or_recv_with_timeout(&mut pkt, timeout);
match status {
@@ -228,13 +233,13 @@ pub fn switch_off_leds() {
const KEEPALIVE_DELAY_MS: isize = 100;
pub const KEEPALIVE_DELAY: Duration<isize> = Duration::from_ms(KEEPALIVE_DELAY_MS);
fn check_user_presence(cid: ChannelID) -> Result<(), Ctap2StatusCode> {
fn check_user_presence(env: &mut TockEnv, cid: ChannelID) -> Result<(), Ctap2StatusCode> {
// The timeout is N times the keepalive delay.
const TIMEOUT_ITERATIONS: usize =
crate::ctap::TOUCH_TIMEOUT_MS as usize / KEEPALIVE_DELAY_MS as usize;
// First, send a keep-alive packet to notify that the keep-alive status has changed.
send_keepalive_up_needed(cid, KEEPALIVE_DELAY)?;
send_keepalive_up_needed(env, cid, KEEPALIVE_DELAY)?;
// Listen to the button presses.
let button_touched = Cell::new(false);
@@ -284,7 +289,7 @@ fn check_user_presence(cid: ChannelID) -> Result<(), Ctap2StatusCode> {
// so that LEDs blink with a consistent pattern.
if keepalive_expired.get() {
// Do not return immediately, because we must clean up still.
keepalive_response = send_keepalive_up_needed(cid, KEEPALIVE_DELAY);
keepalive_response = send_keepalive_up_needed(env, cid, KEEPALIVE_DELAY);
}
if button_touched.get() || keepalive_response.is_err() {