Move choice between prod and test storage to embedded_flash module

This way all users of storage can share the logic to choose between flash or RAM
storage depending on the "std" feature. This is needed because the store_latency
example assumes flash storage but is built when running `cargo test
--features=std`.
This commit is contained in:
Julien Cretin
2020-12-10 18:04:25 +01:00
parent ece546a03b
commit 371b8af224
3 changed files with 41 additions and 35 deletions

View File

@@ -19,10 +19,10 @@ extern crate lang_items;
use alloc::vec; use alloc::vec;
use core::fmt::Write; use core::fmt::Write;
use ctap2::embedded_flash::SyscallStorage; use ctap2::embedded_flash::{new_storage, Storage};
use libtock_drivers::console::Console; use libtock_drivers::console::Console;
use libtock_drivers::timer::{self, Duration, Timer, Timestamp}; use libtock_drivers::timer::{self, Duration, Timer, Timestamp};
use persistent_store::{Storage, Store}; use persistent_store::Store;
fn timestamp(timer: &Timer) -> Timestamp<f64> { fn timestamp(timer: &Timer) -> Timestamp<f64> {
Timestamp::<f64>::from_clock_value(timer.get_current_clock().ok().unwrap()) Timestamp::<f64>::from_clock_value(timer.get_current_clock().ok().unwrap())
@@ -36,10 +36,11 @@ fn measure<T>(timer: &Timer, operation: impl FnOnce() -> T) -> (T, Duration<f64>
} }
// Only use one store at a time. // Only use one store at a time.
unsafe fn boot_store(num_pages: usize, erase: bool) -> Store<SyscallStorage> { unsafe fn boot_store(num_pages: usize, erase: bool) -> Store<Storage> {
let mut storage = SyscallStorage::new(num_pages).unwrap(); let mut storage = new_storage(num_pages);
if erase { if erase {
for page in 0..storage.num_pages() { for page in 0..num_pages {
use persistent_store::Storage;
storage.erase_page(page).unwrap(); storage.erase_page(page).unwrap();
} }
} }

View File

@@ -21,6 +21,7 @@ use crate::ctap::key_material;
use crate::ctap::pin_protocol_v1::PIN_AUTH_LENGTH; use crate::ctap::pin_protocol_v1::PIN_AUTH_LENGTH;
use crate::ctap::status_code::Ctap2StatusCode; use crate::ctap::status_code::Ctap2StatusCode;
use crate::ctap::INITIAL_SIGNATURE_COUNTER; use crate::ctap::INITIAL_SIGNATURE_COUNTER;
use crate::embedded_flash::{new_storage, Storage};
#[cfg(feature = "with_ctap2_1")] #[cfg(feature = "with_ctap2_1")]
use alloc::string::String; use alloc::string::String;
use alloc::vec; use alloc::vec;
@@ -31,11 +32,6 @@ use cbor::cbor_array_vec;
use core::convert::TryInto; use core::convert::TryInto;
use crypto::rng256::Rng256; use crypto::rng256::Rng256;
#[cfg(feature = "std")]
type Storage = persistent_store::BufferStorage;
#[cfg(not(feature = "std"))]
type Storage = crate::embedded_flash::SyscallStorage;
// Those constants may be modified before compilation to tune the behavior of the key. // Those constants may be modified before compilation to tune the behavior of the key.
// //
// The number of pages should be at least 3 and at most what the flash can hold. There should be no // The number of pages should be at least 3 and at most what the flash can hold. There should be no
@@ -89,10 +85,7 @@ impl PersistentStore {
/// ///
/// This should be at most one instance of persistent store per program lifetime. /// This should be at most one instance of persistent store per program lifetime.
pub fn new(rng: &mut impl Rng256) -> PersistentStore { pub fn new(rng: &mut impl Rng256) -> PersistentStore {
#[cfg(not(feature = "std"))] let storage = new_storage(NUM_PAGES);
let storage = PersistentStore::new_prod_storage();
#[cfg(feature = "std")]
let storage = PersistentStore::new_test_storage();
let mut store = PersistentStore { let mut store = PersistentStore {
store: persistent_store::Store::new(storage).ok().unwrap(), store: persistent_store::Store::new(storage).ok().unwrap(),
}; };
@@ -100,27 +93,6 @@ impl PersistentStore {
store store
} }
/// Creates a syscall storage in flash.
#[cfg(not(feature = "std"))]
fn new_prod_storage() -> Storage {
Storage::new(NUM_PAGES).unwrap()
}
/// Creates a buffer storage in RAM.
#[cfg(feature = "std")]
fn new_test_storage() -> Storage {
const PAGE_SIZE: usize = 0x1000;
let store = vec![0xff; NUM_PAGES * PAGE_SIZE].into_boxed_slice();
let options = persistent_store::BufferOptions {
word_size: 4,
page_size: PAGE_SIZE,
max_word_writes: 2,
max_page_erases: 10000,
strict_mode: true,
};
Storage::new(store, options)
}
/// Initializes the store by creating missing objects. /// Initializes the store by creating missing objects.
fn init(&mut self, rng: &mut impl Rng256) -> Result<(), Ctap2StatusCode> { fn init(&mut self, rng: &mut impl Rng256) -> Result<(), Ctap2StatusCode> {
// Generate and store the master keys if they are missing. // Generate and store the master keys if they are missing.

View File

@@ -17,3 +17,36 @@ mod syscall;
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
pub use self::syscall::SyscallStorage; pub use self::syscall::SyscallStorage;
/// Storage definition for production.
#[cfg(not(feature = "std"))]
mod prod {
pub type Storage = super::SyscallStorage;
pub fn new_storage(num_pages: usize) -> Storage {
Storage::new(num_pages).unwrap()
}
}
#[cfg(not(feature = "std"))]
pub use self::prod::{new_storage, Storage};
/// Storage definition for testing.
#[cfg(feature = "std")]
mod test {
pub type Storage = persistent_store::BufferStorage;
pub fn new_storage(num_pages: usize) -> Storage {
const PAGE_SIZE: usize = 0x1000;
let store = vec![0xff; num_pages * PAGE_SIZE].into_boxed_slice();
let options = persistent_store::BufferOptions {
word_size: 4,
page_size: PAGE_SIZE,
max_word_writes: 2,
max_page_erases: 10000,
strict_mode: true,
};
Storage::new(store, options)
}
}
#[cfg(feature = "std")]
pub use self::test::{new_storage, Storage};