diff --git a/src/api/firmware_protection.rs b/src/api/firmware_protection.rs new file mode 100644 index 0000000..9f73b3c --- /dev/null +++ b/src/api/firmware_protection.rs @@ -0,0 +1,6 @@ +pub trait FirmwareProtection { + /// Locks the firmware. + /// + /// Returns whether the operation was successful. + fn lock(&mut self) -> bool; +} diff --git a/src/api/mod.rs b/src/api/mod.rs index b8c5bcb..6738124 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -3,4 +3,5 @@ //! The [environment](crate::env::Env) is split into components. Each component has an API described //! by a trait. This module gathers the API of those components. +pub mod firmware_protection; pub mod upgrade_storage; diff --git a/src/ctap/mod.rs b/src/ctap/mod.rs index eed20f9..f78aaf1 100644 --- a/src/ctap/mod.rs +++ b/src/ctap/mod.rs @@ -63,6 +63,7 @@ use self::status_code::Ctap2StatusCode; use self::timed_permission::TimedPermission; #[cfg(feature = "with_ctap1")] use self::timed_permission::U2fUserPresenceState; +use crate::api::firmware_protection::FirmwareProtection; use crate::api::upgrade_storage::UpgradeStorage; use crate::env::{Env, UserPresence}; use alloc::boxed::Box; @@ -81,7 +82,6 @@ use crypto::sha256::Sha256; use crypto::Hash256; #[cfg(feature = "debug_ctap")] use libtock_drivers::console::Console; -use libtock_drivers::crp; use libtock_drivers::timer::{ClockValue, Duration}; use sk_cbor as cbor; use sk_cbor::cbor_map_options; @@ -1234,7 +1234,7 @@ impl CtapState { let need_certificate = USE_BATCH_ATTESTATION; if (need_certificate && !(response.pkey_programmed && response.cert_programmed)) - || crp::set_protection(crp::ProtectionLevel::FullyLocked).is_err() + || !env.firmware_protection().lock() { return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR); } diff --git a/src/env/mod.rs b/src/env/mod.rs index ba8f75b..9db1b70 100644 --- a/src/env/mod.rs +++ b/src/env/mod.rs @@ -1,3 +1,4 @@ +use crate::api::firmware_protection::FirmwareProtection; use crate::api::upgrade_storage::UpgradeStorage; use crate::ctap::hid::ChannelID; use crate::ctap::status_code::Ctap2StatusCode; @@ -21,6 +22,7 @@ pub trait Env { type UserPresence: UserPresence; type Storage: Storage; type UpgradeStorage: UpgradeStorage; + type FirmwareProtection: FirmwareProtection; fn rng(&mut self) -> &mut Self::Rng; fn user_presence(&mut self) -> &mut Self::UserPresence; @@ -31,4 +33,6 @@ pub trait Env { /// Upgrade storage is optional, so implementations may return `None`. However, implementations /// should either always return `None` or always return `Some`. fn upgrade_storage(&mut self) -> Option<&mut Self::UpgradeStorage>; + + fn firmware_protection(&mut self) -> &mut Self::FirmwareProtection; } diff --git a/src/env/test/mod.rs b/src/env/test/mod.rs index cf1f506..66eb031 100644 --- a/src/env/test/mod.rs +++ b/src/env/test/mod.rs @@ -1,4 +1,5 @@ use self::upgrade_storage::BufferUpgradeStorage; +use crate::api::firmware_protection::FirmwareProtection; use crate::ctap::hid::ChannelID; use crate::ctap::status_code::Ctap2StatusCode; use crate::env::{Env, UserPresence}; @@ -67,11 +68,18 @@ impl UserPresence for TestUserPresence { } } +impl FirmwareProtection for TestEnv { + fn lock(&mut self) -> bool { + true + } +} + impl Env for TestEnv { type Rng = ThreadRng256; type UserPresence = TestUserPresence; type Storage = BufferStorage; type UpgradeStorage = BufferUpgradeStorage; + type FirmwareProtection = Self; fn rng(&mut self) -> &mut Self::Rng { &mut self.rng @@ -88,4 +96,8 @@ impl Env for TestEnv { fn upgrade_storage(&mut self) -> Option<&mut Self::UpgradeStorage> { self.upgrade_storage.as_mut() } + + fn firmware_protection(&mut self) -> &mut Self::FirmwareProtection { + self + } } diff --git a/src/env/tock/mod.rs b/src/env/tock/mod.rs index 257ac1c..8b249cb 100644 --- a/src/env/tock/mod.rs +++ b/src/env/tock/mod.rs @@ -1,4 +1,5 @@ pub use self::storage::{TockStorage, TockUpgradeStorage}; +use crate::api::firmware_protection::FirmwareProtection; use crate::ctap::hid::{ChannelID, CtapHid, CtapHidCommand, KeepaliveStatus, ProcessedPacket}; use crate::ctap::status_code::Ctap2StatusCode; use crate::env::{Env, UserPresence}; @@ -13,7 +14,7 @@ use libtock_drivers::buttons::{self, ButtonState}; use libtock_drivers::console::Console; use libtock_drivers::result::{FlexUnwrap, TockError}; use libtock_drivers::timer::Duration; -use libtock_drivers::{led, timer, usb_ctap_hid}; +use libtock_drivers::{crp, led, timer, usb_ctap_hid}; use persistent_store::{StorageResult, Store}; mod storage; @@ -61,11 +62,25 @@ impl UserPresence for TockEnv { } } +impl FirmwareProtection for TockEnv { + fn lock(&mut self) -> bool { + matches!( + crp::set_protection(crp::ProtectionLevel::FullyLocked), + Ok(()) + | Err(TockError::Command(CommandError { + return_code: EALREADY, + .. + })) + ) + } +} + impl Env for TockEnv { type Rng = TockRng256; type UserPresence = Self; type Storage = TockStorage; type UpgradeStorage = TockUpgradeStorage; + type FirmwareProtection = Self; fn rng(&mut self) -> &mut Self::Rng { &mut self.rng @@ -82,6 +97,10 @@ impl Env for TockEnv { fn upgrade_storage(&mut self) -> Option<&mut Self::UpgradeStorage> { self.upgrade_storage.as_mut() } + + fn firmware_protection(&mut self) -> &mut Self::FirmwareProtection { + self + } } // Returns whether the keepalive was sent, or false if cancelled.