Configure the number of pages in the board

This permits to have portable apps.
This commit is contained in:
Julien Cretin
2021-08-15 22:39:13 +02:00
committed by Julien Cretin
parent c1f2551d0d
commit 2d5fdd1034
12 changed files with 77 additions and 79 deletions

View File

@@ -219,23 +219,10 @@ pub const MAX_RP_IDS_LENGTH: usize = 8;
///
/// - The storage key CREDENTIALS must fit at least this number of credentials.
///
/// This value has implications on the flash lifetime, please see the
/// documentation for NUM_PAGES below.
pub const MAX_SUPPORTED_RESIDENT_KEYS: usize = 150;
/// Sets the number of pages used for persistent storage.
///
/// The number of pages should be at least 3 and at most what the flash can
/// hold. There should be no reason to put a small number here, except that the
/// latency of flash operations is linear in the number of pages. This may
/// improve in the future. Currently, using 20 pages gives between 20ms and
/// 240ms per operation. The rule of thumb is between 1ms and 12ms per
/// additional page.
///
/// Limiting the number of resident keys permits to ensure a minimum number of
/// counter increments.
/// Let:
/// - P the number of pages (NUM_PAGES)
/// - P the number of pages (NUM_PAGES in the board definition)
/// - K the maximum number of resident keys (MAX_SUPPORTED_RESIDENT_KEYS)
/// - S the maximum size of a resident key (about 500)
/// - C the number of erase cycles (10000)
@@ -245,7 +232,7 @@ pub const MAX_SUPPORTED_RESIDENT_KEYS: usize = 150;
///
/// With P=20 and K=150, we have I=2M which is enough for 500 increments per day
/// for 10 years.
pub const NUM_PAGES: usize = 20;
pub const MAX_SUPPORTED_RESIDENT_KEYS: usize = 150;
#[cfg(test)]
mod test {

View File

@@ -18,7 +18,6 @@ use crate::ctap::client_pin::PIN_AUTH_LENGTH;
use crate::ctap::customization::{
DEFAULT_MIN_PIN_LENGTH, DEFAULT_MIN_PIN_LENGTH_RP_IDS, ENFORCE_ALWAYS_UV,
MAX_LARGE_BLOB_ARRAY_SIZE, MAX_PIN_RETRIES, MAX_RP_IDS_LENGTH, MAX_SUPPORTED_RESIDENT_KEYS,
NUM_PAGES,
};
use crate::ctap::data_formats::{
extract_array, extract_text_string, CredentialProtectionPolicy, PublicKeyCredentialSource,
@@ -68,7 +67,7 @@ impl PersistentStore {
///
/// This should be at most one instance of persistent store per program lifetime.
pub fn new(rng: &mut impl Rng256) -> PersistentStore {
let storage = new_storage(NUM_PAGES);
let storage = new_storage().ok().unwrap();
let mut store = PersistentStore {
store: persistent_store::Store::new(storage).ok().unwrap(),
};

View File

@@ -28,8 +28,8 @@ mod prod {
pub type Storage = SyscallStorage;
pub fn new_storage(num_pages: usize) -> Storage {
Storage::new(num_pages).unwrap()
pub fn new_storage() -> persistent_store::StorageResult<Storage> {
Storage::new()
}
pub type UpgradeLocations = SyscallUpgradeStorage;
@@ -44,9 +44,11 @@ mod test {
pub type Storage = persistent_store::BufferStorage;
pub fn new_storage(num_pages: usize) -> Storage {
pub fn new_storage() -> persistent_store::StorageResult<Storage> {
// Use the Nordic configuration.
const PAGE_SIZE: usize = 0x1000;
let store = vec![0xff; num_pages * PAGE_SIZE].into_boxed_slice();
const NUM_PAGES: usize = 20;
let store = vec![0xff; NUM_PAGES * PAGE_SIZE].into_boxed_slice();
let options = persistent_store::BufferOptions {
word_size: 4,
page_size: PAGE_SIZE,
@@ -54,7 +56,7 @@ mod test {
max_page_erases: 10000,
strict_mode: true,
};
Storage::new(store, options)
Ok(Storage::new(store, options))
}
pub type UpgradeLocations = BufferUpgradeStorage;

View File

@@ -134,13 +134,11 @@ impl SyscallStorage {
/// - The page size is a power of two.
/// - The page size is a multiple of the word size.
/// - The storage is page-aligned.
///
/// Returns `OutOfBounds` the number of pages does not fit in the storage.
pub fn new(mut num_pages: usize) -> StorageResult<SyscallStorage> {
pub fn new() -> StorageResult<SyscallStorage> {
let mut syscall = SyscallStorage {
word_size: get_info(command_nr::get_info_nr::WORD_SIZE, 0)?,
page_size: get_info(command_nr::get_info_nr::PAGE_SIZE, 0)?,
num_pages,
num_pages: 0,
max_word_writes: get_info(command_nr::get_info_nr::MAX_WORD_WRITES, 0)?,
max_page_erases: get_info(command_nr::get_info_nr::MAX_PAGE_ERASES, 0)?,
storage_locations: Vec::new(),
@@ -156,20 +154,15 @@ impl SyscallStorage {
continue;
}
let storage_ptr = memop(memop_nr::STORAGE_PTR, i)?;
let max_storage_len = memop(memop_nr::STORAGE_LEN, i)?;
if !syscall.is_page_aligned(storage_ptr) || !syscall.is_page_aligned(max_storage_len) {
let storage_len = memop(memop_nr::STORAGE_LEN, i)?;
if !syscall.is_page_aligned(storage_ptr) || !syscall.is_page_aligned(storage_len) {
return Err(StorageError::CustomError);
}
let storage_len = core::cmp::min(num_pages * syscall.page_size, max_storage_len);
num_pages -= storage_len / syscall.page_size;
syscall.num_pages += storage_len / syscall.page_size;
syscall
.storage_locations
.push(unsafe { core::slice::from_raw_parts(storage_ptr as *mut u8, storage_len) });
}
if num_pages > 0 {
// The storage locations don't have enough pages.
return Err(StorageError::OutOfBounds);
}
Ok(syscall)
}