Merge pull request #433 from ia0/firmware_protection

Add firmware protection to the environment
This commit is contained in:
Julien Cretin
2022-03-08 16:47:39 +01:00
committed by GitHub
6 changed files with 45 additions and 3 deletions

View File

@@ -0,0 +1,6 @@
pub trait FirmwareProtection {
/// Locks the firmware.
///
/// Returns whether the operation was successful.
fn lock(&mut self) -> bool;
}

View File

@@ -3,4 +3,5 @@
//! The [environment](crate::env::Env) is split into components. Each component has an API described //! 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. //! by a trait. This module gathers the API of those components.
pub mod firmware_protection;
pub mod upgrade_storage; pub mod upgrade_storage;

View File

@@ -63,6 +63,7 @@ use self::status_code::Ctap2StatusCode;
use self::timed_permission::TimedPermission; use self::timed_permission::TimedPermission;
#[cfg(feature = "with_ctap1")] #[cfg(feature = "with_ctap1")]
use self::timed_permission::U2fUserPresenceState; use self::timed_permission::U2fUserPresenceState;
use crate::api::firmware_protection::FirmwareProtection;
use crate::api::upgrade_storage::UpgradeStorage; use crate::api::upgrade_storage::UpgradeStorage;
use crate::env::{Env, UserPresence}; use crate::env::{Env, UserPresence};
use alloc::boxed::Box; use alloc::boxed::Box;
@@ -81,7 +82,6 @@ use crypto::sha256::Sha256;
use crypto::Hash256; use crypto::Hash256;
#[cfg(feature = "debug_ctap")] #[cfg(feature = "debug_ctap")]
use libtock_drivers::console::Console; use libtock_drivers::console::Console;
use libtock_drivers::crp;
use libtock_drivers::timer::{ClockValue, Duration}; use libtock_drivers::timer::{ClockValue, Duration};
use sk_cbor as cbor; use sk_cbor as cbor;
use sk_cbor::cbor_map_options; use sk_cbor::cbor_map_options;
@@ -1234,7 +1234,7 @@ impl CtapState {
let need_certificate = USE_BATCH_ATTESTATION; let need_certificate = USE_BATCH_ATTESTATION;
if (need_certificate && !(response.pkey_programmed && response.cert_programmed)) 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); return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
} }

4
src/env/mod.rs vendored
View File

@@ -1,3 +1,4 @@
use crate::api::firmware_protection::FirmwareProtection;
use crate::api::upgrade_storage::UpgradeStorage; use crate::api::upgrade_storage::UpgradeStorage;
use crate::ctap::hid::ChannelID; use crate::ctap::hid::ChannelID;
use crate::ctap::status_code::Ctap2StatusCode; use crate::ctap::status_code::Ctap2StatusCode;
@@ -21,6 +22,7 @@ pub trait Env {
type UserPresence: UserPresence; type UserPresence: UserPresence;
type Storage: Storage; type Storage: Storage;
type UpgradeStorage: UpgradeStorage; type UpgradeStorage: UpgradeStorage;
type FirmwareProtection: FirmwareProtection;
fn rng(&mut self) -> &mut Self::Rng; fn rng(&mut self) -> &mut Self::Rng;
fn user_presence(&mut self) -> &mut Self::UserPresence; 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 /// Upgrade storage is optional, so implementations may return `None`. However, implementations
/// should either always return `None` or always return `Some`. /// should either always return `None` or always return `Some`.
fn upgrade_storage(&mut self) -> Option<&mut Self::UpgradeStorage>; fn upgrade_storage(&mut self) -> Option<&mut Self::UpgradeStorage>;
fn firmware_protection(&mut self) -> &mut Self::FirmwareProtection;
} }

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

@@ -1,4 +1,5 @@
use self::upgrade_storage::BufferUpgradeStorage; use self::upgrade_storage::BufferUpgradeStorage;
use crate::api::firmware_protection::FirmwareProtection;
use crate::ctap::hid::ChannelID; use crate::ctap::hid::ChannelID;
use crate::ctap::status_code::Ctap2StatusCode; use crate::ctap::status_code::Ctap2StatusCode;
use crate::env::{Env, UserPresence}; 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 { impl Env for TestEnv {
type Rng = ThreadRng256; type Rng = ThreadRng256;
type UserPresence = TestUserPresence; type UserPresence = TestUserPresence;
type Storage = BufferStorage; type Storage = BufferStorage;
type UpgradeStorage = BufferUpgradeStorage; type UpgradeStorage = BufferUpgradeStorage;
type FirmwareProtection = Self;
fn rng(&mut self) -> &mut Self::Rng { fn rng(&mut self) -> &mut Self::Rng {
&mut self.rng &mut self.rng
@@ -88,4 +96,8 @@ impl Env for TestEnv {
fn upgrade_storage(&mut self) -> Option<&mut Self::UpgradeStorage> { fn upgrade_storage(&mut self) -> Option<&mut Self::UpgradeStorage> {
self.upgrade_storage.as_mut() self.upgrade_storage.as_mut()
} }
fn firmware_protection(&mut self) -> &mut Self::FirmwareProtection {
self
}
} }

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

@@ -1,4 +1,5 @@
pub use self::storage::{TockStorage, TockUpgradeStorage}; pub use self::storage::{TockStorage, TockUpgradeStorage};
use crate::api::firmware_protection::FirmwareProtection;
use crate::ctap::hid::{ChannelID, CtapHid, CtapHidCommand, KeepaliveStatus, ProcessedPacket}; use crate::ctap::hid::{ChannelID, CtapHid, CtapHidCommand, KeepaliveStatus, ProcessedPacket};
use crate::ctap::status_code::Ctap2StatusCode; use crate::ctap::status_code::Ctap2StatusCode;
use crate::env::{Env, UserPresence}; use crate::env::{Env, UserPresence};
@@ -13,7 +14,7 @@ use libtock_drivers::buttons::{self, ButtonState};
use libtock_drivers::console::Console; use libtock_drivers::console::Console;
use libtock_drivers::result::{FlexUnwrap, TockError}; use libtock_drivers::result::{FlexUnwrap, TockError};
use libtock_drivers::timer::Duration; 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}; use persistent_store::{StorageResult, Store};
mod storage; 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 { impl Env for TockEnv {
type Rng = TockRng256; type Rng = TockRng256;
type UserPresence = Self; type UserPresence = Self;
type Storage = TockStorage; type Storage = TockStorage;
type UpgradeStorage = TockUpgradeStorage; type UpgradeStorage = TockUpgradeStorage;
type FirmwareProtection = Self;
fn rng(&mut self) -> &mut Self::Rng { fn rng(&mut self) -> &mut Self::Rng {
&mut self.rng &mut self.rng
@@ -82,6 +97,10 @@ impl Env for TockEnv {
fn upgrade_storage(&mut self) -> Option<&mut Self::UpgradeStorage> { fn upgrade_storage(&mut self) -> Option<&mut Self::UpgradeStorage> {
self.upgrade_storage.as_mut() self.upgrade_storage.as_mut()
} }
fn firmware_protection(&mut self) -> &mut Self::FirmwareProtection {
self
}
} }
// Returns whether the keepalive was sent, or false if cancelled. // Returns whether the keepalive was sent, or false if cancelled.