Find the next free key in a linear way
This commit is contained in:
@@ -23,7 +23,6 @@ use crate::ctap::status_code::Ctap2StatusCode;
|
|||||||
use crate::ctap::INITIAL_SIGNATURE_COUNTER;
|
use crate::ctap::INITIAL_SIGNATURE_COUNTER;
|
||||||
#[cfg(feature = "with_ctap2_1")]
|
#[cfg(feature = "with_ctap2_1")]
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
#[cfg(any(test, feature = "ram_storage", feature = "with_ctap2_1"))]
|
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use arrayref::array_ref;
|
use arrayref::array_ref;
|
||||||
@@ -206,12 +205,19 @@ impl PersistentStore {
|
|||||||
) -> Result<(), Ctap2StatusCode> {
|
) -> Result<(), Ctap2StatusCode> {
|
||||||
// Holds the key of the existing credential if this is an update.
|
// Holds the key of the existing credential if this is an update.
|
||||||
let mut old_key = None;
|
let mut old_key = None;
|
||||||
// Holds the unordered list of used keys.
|
let min_key = key::CREDENTIALS.start;
|
||||||
let mut keys = Vec::new();
|
// Holds whether a key is used (indices are shifted by min_key).
|
||||||
|
let mut keys = vec![false; MAX_SUPPORTED_RESIDENTIAL_KEYS];
|
||||||
let mut iter_result = Ok(());
|
let mut iter_result = Ok(());
|
||||||
let iter = self.iter_credentials(&mut iter_result)?;
|
let iter = self.iter_credentials(&mut iter_result)?;
|
||||||
for (key, credential) in iter {
|
for (key, credential) in iter {
|
||||||
keys.push(key);
|
if key < min_key
|
||||||
|
|| key - min_key >= MAX_SUPPORTED_RESIDENTIAL_KEYS
|
||||||
|
|| keys[key - min_key]
|
||||||
|
{
|
||||||
|
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
||||||
|
}
|
||||||
|
keys[key - min_key] = true;
|
||||||
if credential.rp_id == new_credential.rp_id
|
if credential.rp_id == new_credential.rp_id
|
||||||
&& credential.user_handle == new_credential.user_handle
|
&& credential.user_handle == new_credential.user_handle
|
||||||
{
|
{
|
||||||
@@ -222,15 +228,17 @@ impl PersistentStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
iter_result?;
|
iter_result?;
|
||||||
if old_key.is_none() && keys.len() >= MAX_SUPPORTED_RESIDENTIAL_KEYS {
|
if old_key.is_none()
|
||||||
|
&& keys.iter().filter(|&&x| x).count() >= MAX_SUPPORTED_RESIDENTIAL_KEYS
|
||||||
|
{
|
||||||
return Err(Ctap2StatusCode::CTAP2_ERR_KEY_STORE_FULL);
|
return Err(Ctap2StatusCode::CTAP2_ERR_KEY_STORE_FULL);
|
||||||
}
|
}
|
||||||
let key = match old_key {
|
let key = match old_key {
|
||||||
// This is a new credential being added, we need to allocate a free key. We choose the
|
// This is a new credential being added, we need to allocate a free key. We choose the
|
||||||
// first available key. This is quadratic in the number of existing keys.
|
// first available key.
|
||||||
None => key::CREDENTIALS
|
None => key::CREDENTIALS
|
||||||
.take(MAX_SUPPORTED_RESIDENTIAL_KEYS)
|
.take(MAX_SUPPORTED_RESIDENTIAL_KEYS)
|
||||||
.find(|key| !keys.contains(key))
|
.find(|key| !keys[key - min_key])
|
||||||
.ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?,
|
.ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?,
|
||||||
// This is an existing credential being updated, we reuse its key.
|
// This is an existing credential being updated, we reuse its key.
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
|
|||||||
Reference in New Issue
Block a user