Replaced Libtock driver clock with embedded_time::Clock (#422)
* Replaced Libtock driver clock with embedded_time::Clock * Add unittest and address some comments * Add unittest and address some comments
This commit is contained in:
192
src/ctap/mod.rs
192
src/ctap/mod.rs
@@ -65,6 +65,7 @@ use self::timed_permission::TimedPermission;
|
||||
use self::timed_permission::U2fUserPresenceState;
|
||||
use crate::api::firmware_protection::FirmwareProtection;
|
||||
use crate::api::upgrade_storage::UpgradeStorage;
|
||||
use crate::clock::{ClockInt, CtapInstant};
|
||||
use crate::env::{Env, UserPresence};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::{String, ToString};
|
||||
@@ -78,7 +79,7 @@ use crypto::hmac::{hmac_256, verify_hmac_256};
|
||||
use crypto::rng256::Rng256;
|
||||
use crypto::sha256::Sha256;
|
||||
use crypto::Hash256;
|
||||
use libtock_drivers::timer::{ClockValue, Duration};
|
||||
use embedded_time::duration::Milliseconds;
|
||||
use sk_cbor as cbor;
|
||||
use sk_cbor::cbor_map_options;
|
||||
|
||||
@@ -101,12 +102,14 @@ const ED_FLAG: u8 = 0x80;
|
||||
// CTAP2 specification section 6 requires that the depth of nested CBOR structures be limited to at most four levels.
|
||||
const MAX_CBOR_NESTING_DEPTH: i8 = 4;
|
||||
|
||||
pub const TOUCH_TIMEOUT_MS: isize = 30000;
|
||||
pub const TOUCH_TIMEOUT_MS: ClockInt = 30000;
|
||||
#[cfg(feature = "with_ctap1")]
|
||||
const U2F_UP_PROMPT_TIMEOUT: Duration<isize> = Duration::from_ms(10000);
|
||||
pub const TOUCH_TIMEOUT: Milliseconds<ClockInt> = Milliseconds(TOUCH_TIMEOUT_MS);
|
||||
#[cfg(feature = "with_ctap1")]
|
||||
const U2F_UP_PROMPT_TIMEOUT: Milliseconds<ClockInt> = Milliseconds(10000 as ClockInt);
|
||||
// TODO(kaczmarczyck) 2.1 allows Reset after Reset and 15 seconds?
|
||||
const RESET_TIMEOUT_DURATION: Duration<isize> = Duration::from_ms(10000);
|
||||
const STATEFUL_COMMAND_TIMEOUT_DURATION: Duration<isize> = Duration::from_ms(30000);
|
||||
const RESET_TIMEOUT_DURATION: Milliseconds<ClockInt> = Milliseconds(10000 as ClockInt);
|
||||
const STATEFUL_COMMAND_TIMEOUT_DURATION: Milliseconds<ClockInt> = Milliseconds(30000 as ClockInt);
|
||||
|
||||
pub const FIDO2_VERSION_STRING: &str = "FIDO_2_0";
|
||||
#[cfg(feature = "with_ctap1")]
|
||||
@@ -239,7 +242,7 @@ impl StatefulPermission {
|
||||
///
|
||||
/// Resets are only possible after a power cycle. Therefore, initialization
|
||||
/// means allowing Reset, and Reset cannot be granted later.
|
||||
pub fn new_reset(now: ClockValue) -> StatefulPermission {
|
||||
pub fn new_reset(now: CtapInstant) -> StatefulPermission {
|
||||
StatefulPermission {
|
||||
permission: TimedPermission::granted(now, RESET_TIMEOUT_DURATION),
|
||||
command_type: Some(StatefulCommand::Reset),
|
||||
@@ -253,7 +256,7 @@ impl StatefulPermission {
|
||||
}
|
||||
|
||||
/// Checks the permission timeout.
|
||||
pub fn check_command_permission(&mut self, now: ClockValue) -> Result<(), Ctap2StatusCode> {
|
||||
pub fn check_command_permission(&mut self, now: CtapInstant) -> Result<(), Ctap2StatusCode> {
|
||||
if self.permission.is_granted(now) {
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -270,7 +273,7 @@ impl StatefulPermission {
|
||||
}
|
||||
|
||||
/// Sets a new command state, and starts a new clock for timeouts.
|
||||
pub fn set_command(&mut self, now: ClockValue, new_command_type: StatefulCommand) {
|
||||
pub fn set_command(&mut self, now: CtapInstant, new_command_type: StatefulCommand) {
|
||||
match &new_command_type {
|
||||
// Reset is only allowed after a power cycle.
|
||||
StatefulCommand::Reset => unreachable!(),
|
||||
@@ -335,22 +338,19 @@ pub struct CtapState {
|
||||
}
|
||||
|
||||
impl CtapState {
|
||||
pub fn new(env: &mut impl Env, now: ClockValue) -> Self {
|
||||
pub fn new(env: &mut impl Env, now: CtapInstant) -> Self {
|
||||
storage::init(env).ok().unwrap();
|
||||
let client_pin = ClientPin::new(env.rng());
|
||||
CtapState {
|
||||
client_pin,
|
||||
#[cfg(feature = "with_ctap1")]
|
||||
u2f_up_state: U2fUserPresenceState::new(
|
||||
U2F_UP_PROMPT_TIMEOUT,
|
||||
Duration::from_ms(TOUCH_TIMEOUT_MS),
|
||||
),
|
||||
u2f_up_state: U2fUserPresenceState::new(U2F_UP_PROMPT_TIMEOUT, TOUCH_TIMEOUT),
|
||||
stateful_command_permission: StatefulPermission::new_reset(now),
|
||||
large_blobs: LargeBlobs::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_timeouts(&mut self, now: ClockValue) {
|
||||
pub fn update_timeouts(&mut self, now: CtapInstant) {
|
||||
// Ignore the result, just update.
|
||||
let _ = self
|
||||
.stateful_command_permission
|
||||
@@ -448,7 +448,7 @@ impl CtapState {
|
||||
env: &mut impl Env,
|
||||
command_cbor: &[u8],
|
||||
cid: ChannelID,
|
||||
now: ClockValue,
|
||||
now: CtapInstant,
|
||||
) -> Vec<u8> {
|
||||
let cmd = Command::deserialize(command_cbor);
|
||||
debug_ctap!(env, "Received command: {:#?}", cmd);
|
||||
@@ -457,10 +457,8 @@ impl CtapState {
|
||||
// Correct behavior between CTAP1 and CTAP2 isn't defined yet. Just a guess.
|
||||
#[cfg(feature = "with_ctap1")]
|
||||
{
|
||||
self.u2f_up_state = U2fUserPresenceState::new(
|
||||
U2F_UP_PROMPT_TIMEOUT,
|
||||
Duration::from_ms(TOUCH_TIMEOUT_MS),
|
||||
);
|
||||
self.u2f_up_state =
|
||||
U2fUserPresenceState::new(U2F_UP_PROMPT_TIMEOUT, TOUCH_TIMEOUT);
|
||||
}
|
||||
match (&command, self.stateful_command_permission.get_command()) {
|
||||
(Command::AuthenticatorGetNextAssertion, Ok(StatefulCommand::GetAssertion(_)))
|
||||
@@ -925,7 +923,7 @@ impl CtapState {
|
||||
env: &mut impl Env,
|
||||
get_assertion_params: AuthenticatorGetAssertionParameters,
|
||||
cid: ChannelID,
|
||||
now: ClockValue,
|
||||
now: CtapInstant,
|
||||
) -> Result<ResponseData, Ctap2StatusCode> {
|
||||
let AuthenticatorGetAssertionParameters {
|
||||
rp_id,
|
||||
@@ -1055,7 +1053,7 @@ impl CtapState {
|
||||
fn process_get_next_assertion(
|
||||
&mut self,
|
||||
env: &mut impl Env,
|
||||
now: ClockValue,
|
||||
now: CtapInstant,
|
||||
) -> Result<ResponseData, Ctap2StatusCode> {
|
||||
self.stateful_command_permission
|
||||
.check_command_permission(now)?;
|
||||
@@ -1136,7 +1134,7 @@ impl CtapState {
|
||||
&mut self,
|
||||
env: &mut impl Env,
|
||||
cid: ChannelID,
|
||||
now: ClockValue,
|
||||
now: CtapInstant,
|
||||
) -> Result<ResponseData, Ctap2StatusCode> {
|
||||
self.stateful_command_permission
|
||||
.check_command_permission(now)?;
|
||||
@@ -1150,10 +1148,7 @@ impl CtapState {
|
||||
self.client_pin.reset(env.rng());
|
||||
#[cfg(feature = "with_ctap1")]
|
||||
{
|
||||
self.u2f_up_state = U2fUserPresenceState::new(
|
||||
U2F_UP_PROMPT_TIMEOUT,
|
||||
Duration::from_ms(TOUCH_TIMEOUT_MS),
|
||||
);
|
||||
self.u2f_up_state = U2fUserPresenceState::new(U2F_UP_PROMPT_TIMEOUT, TOUCH_TIMEOUT);
|
||||
}
|
||||
Ok(ResponseData::AuthenticatorReset)
|
||||
}
|
||||
@@ -1312,12 +1307,12 @@ impl CtapState {
|
||||
}
|
||||
|
||||
#[cfg(feature = "with_ctap1")]
|
||||
pub fn u2f_grant_user_presence(&mut self, now: ClockValue) {
|
||||
pub fn u2f_grant_user_presence(&mut self, now: CtapInstant) {
|
||||
self.u2f_up_state.grant_up(now)
|
||||
}
|
||||
|
||||
#[cfg(feature = "with_ctap1")]
|
||||
pub fn u2f_needs_user_presence(&mut self, now: ClockValue) -> bool {
|
||||
pub fn u2f_needs_user_presence(&mut self, now: CtapInstant) -> bool {
|
||||
self.u2f_up_state.is_up_needed(now)
|
||||
}
|
||||
}
|
||||
@@ -1336,8 +1331,6 @@ mod test {
|
||||
use crate::env::test::TestEnv;
|
||||
use cbor::{cbor_array, cbor_array_vec, cbor_map};
|
||||
|
||||
const CLOCK_FREQUENCY_HZ: usize = 32768;
|
||||
const DUMMY_CLOCK_VALUE: ClockValue = ClockValue::new(0, CLOCK_FREQUENCY_HZ);
|
||||
// The keep-alive logic in the processing of some commands needs a channel ID to send
|
||||
// keep-alive packets to.
|
||||
// In tests where we define a dummy user-presence check that immediately returns, the channel
|
||||
@@ -1389,9 +1382,9 @@ mod test {
|
||||
#[test]
|
||||
fn test_get_info() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
let info_reponse =
|
||||
ctap_state.process_command(&mut env, &[0x04], DUMMY_CHANNEL_ID, DUMMY_CLOCK_VALUE);
|
||||
ctap_state.process_command(&mut env, &[0x04], DUMMY_CHANNEL_ID, CtapInstant::new(0));
|
||||
|
||||
let expected_cbor = cbor_map_options! {
|
||||
0x01 => cbor_array_vec![vec![
|
||||
@@ -1501,7 +1494,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_resident_process_make_credential() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let make_credential_params = create_minimal_make_credential_parameters();
|
||||
let make_credential_response =
|
||||
@@ -1519,7 +1512,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_non_resident_process_make_credential() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let mut make_credential_params = create_minimal_make_credential_parameters();
|
||||
make_credential_params.options.rk = false;
|
||||
@@ -1538,7 +1531,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_make_credential_unsupported_algorithm() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let mut make_credential_params = create_minimal_make_credential_parameters();
|
||||
make_credential_params.pub_key_cred_params = vec![];
|
||||
@@ -1555,7 +1548,7 @@ mod test {
|
||||
fn test_process_make_credential_credential_excluded() {
|
||||
let mut env = TestEnv::new();
|
||||
let excluded_private_key = crypto::ecdsa::SecKey::gensk(env.rng());
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let excluded_credential_id = vec![0x01, 0x23, 0x45, 0x67];
|
||||
let make_credential_params =
|
||||
@@ -1587,7 +1580,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_make_credential_credential_with_cred_protect() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let test_policy = CredentialProtectionPolicy::UserVerificationOptionalWithCredentialIdList;
|
||||
let make_credential_params =
|
||||
@@ -1638,7 +1631,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_make_credential_hmac_secret() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let extensions = MakeCredentialExtensions {
|
||||
hmac_secret: true,
|
||||
@@ -1665,7 +1658,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_make_credential_hmac_secret_resident_key() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let extensions = MakeCredentialExtensions {
|
||||
hmac_secret: true,
|
||||
@@ -1691,7 +1684,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_make_credential_min_pin_length() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
// First part: The extension is ignored, since the RP ID is not on the list.
|
||||
let extensions = MakeCredentialExtensions {
|
||||
@@ -1740,7 +1733,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_make_credential_cred_blob_ok() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let extensions = MakeCredentialExtensions {
|
||||
cred_blob: Some(vec![0xCB]),
|
||||
@@ -1772,7 +1765,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_make_credential_cred_blob_too_big() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let extensions = MakeCredentialExtensions {
|
||||
cred_blob: Some(vec![0xCB; MAX_CRED_BLOB_LENGTH + 1]),
|
||||
@@ -1804,7 +1797,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_make_credential_large_blob_key() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let extensions = MakeCredentialExtensions {
|
||||
large_blob_key: Some(true),
|
||||
@@ -1839,7 +1832,7 @@ mod test {
|
||||
let client_pin =
|
||||
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, pin_uv_auth_protocol);
|
||||
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
ctap_state.client_pin = client_pin;
|
||||
storage::set_pin(&mut env, &[0x88; 16], 4).unwrap();
|
||||
|
||||
@@ -1888,7 +1881,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_non_resident_process_make_credential_with_pin() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
storage::set_pin(&mut env, &[0x88; 16], 4).unwrap();
|
||||
|
||||
let mut make_credential_params = create_minimal_make_credential_parameters();
|
||||
@@ -1908,7 +1901,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_resident_process_make_credential_with_pin() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
storage::set_pin(&mut env, &[0x88; 16], 4).unwrap();
|
||||
|
||||
let make_credential_params = create_minimal_make_credential_parameters();
|
||||
@@ -1923,7 +1916,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_make_credential_with_pin_always_uv() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
storage::toggle_always_uv(&mut env).unwrap();
|
||||
let make_credential_params = create_minimal_make_credential_parameters();
|
||||
@@ -1951,7 +1944,7 @@ mod test {
|
||||
let mut env = TestEnv::new();
|
||||
env.user_presence()
|
||||
.set(|_| Err(Ctap2StatusCode::CTAP2_ERR_KEEPALIVE_CANCEL));
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let make_credential_params = create_minimal_make_credential_parameters();
|
||||
let make_credential_response =
|
||||
@@ -2046,7 +2039,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_resident_process_get_assertion() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let make_credential_params = create_minimal_make_credential_parameters();
|
||||
assert!(ctap_state
|
||||
@@ -2069,7 +2062,7 @@ mod test {
|
||||
&mut env,
|
||||
get_assertion_params,
|
||||
DUMMY_CHANNEL_ID,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
let signature_counter = storage::global_signature_counter(&mut env).unwrap();
|
||||
check_assertion_response(get_assertion_response, vec![0x1D], signature_counter, None);
|
||||
@@ -2131,7 +2124,7 @@ mod test {
|
||||
fn test_helper_process_get_assertion_hmac_secret(pin_uv_auth_protocol: PinUvAuthProtocol) {
|
||||
let mut env = TestEnv::new();
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let make_extensions = MakeCredentialExtensions {
|
||||
hmac_secret: true,
|
||||
@@ -2167,7 +2160,7 @@ mod test {
|
||||
let key_agreement_response =
|
||||
ctap_state
|
||||
.client_pin
|
||||
.process_command(&mut env, client_pin_params, DUMMY_CLOCK_VALUE);
|
||||
.process_command(&mut env, client_pin_params, CtapInstant::new(0));
|
||||
let get_assertion_params = get_assertion_hmac_secret_params(
|
||||
key_agreement_key,
|
||||
key_agreement_response.unwrap(),
|
||||
@@ -2178,7 +2171,7 @@ mod test {
|
||||
&mut env,
|
||||
get_assertion_params,
|
||||
DUMMY_CHANNEL_ID,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
assert!(get_assertion_response.is_ok());
|
||||
}
|
||||
@@ -2198,7 +2191,7 @@ mod test {
|
||||
) {
|
||||
let mut env = TestEnv::new();
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let make_extensions = MakeCredentialExtensions {
|
||||
hmac_secret: true,
|
||||
@@ -2223,7 +2216,7 @@ mod test {
|
||||
let key_agreement_response =
|
||||
ctap_state
|
||||
.client_pin
|
||||
.process_command(&mut env, client_pin_params, DUMMY_CLOCK_VALUE);
|
||||
.process_command(&mut env, client_pin_params, CtapInstant::new(0));
|
||||
let get_assertion_params = get_assertion_hmac_secret_params(
|
||||
key_agreement_key,
|
||||
key_agreement_response.unwrap(),
|
||||
@@ -2234,7 +2227,7 @@ mod test {
|
||||
&mut env,
|
||||
get_assertion_params,
|
||||
DUMMY_CHANNEL_ID,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
assert!(get_assertion_response.is_ok());
|
||||
}
|
||||
@@ -2254,7 +2247,7 @@ mod test {
|
||||
let mut env = TestEnv::new();
|
||||
let private_key = crypto::ecdsa::SecKey::gensk(env.rng());
|
||||
let credential_id = env.rng().gen_uniform_u8x32().to_vec();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let cred_desc = PublicKeyCredentialDescriptor {
|
||||
key_type: PublicKeyCredentialType::PublicKey,
|
||||
@@ -2295,7 +2288,7 @@ mod test {
|
||||
&mut env,
|
||||
get_assertion_params,
|
||||
DUMMY_CHANNEL_ID,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
assert_eq!(
|
||||
get_assertion_response,
|
||||
@@ -2318,7 +2311,7 @@ mod test {
|
||||
&mut env,
|
||||
get_assertion_params,
|
||||
DUMMY_CHANNEL_ID,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
let signature_counter = storage::global_signature_counter(&mut env).unwrap();
|
||||
check_assertion_response(get_assertion_response, vec![0x1D], signature_counter, None);
|
||||
@@ -2355,7 +2348,7 @@ mod test {
|
||||
&mut env,
|
||||
get_assertion_params,
|
||||
DUMMY_CHANNEL_ID,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
assert_eq!(
|
||||
get_assertion_response,
|
||||
@@ -2368,7 +2361,7 @@ mod test {
|
||||
let mut env = TestEnv::new();
|
||||
let private_key = crypto::ecdsa::SecKey::gensk(env.rng());
|
||||
let credential_id = env.rng().gen_uniform_u8x32().to_vec();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let credential = PublicKeyCredentialSource {
|
||||
key_type: PublicKeyCredentialType::PublicKey,
|
||||
@@ -2406,7 +2399,7 @@ mod test {
|
||||
&mut env,
|
||||
get_assertion_params,
|
||||
DUMMY_CHANNEL_ID,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
let signature_counter = storage::global_signature_counter(&mut env).unwrap();
|
||||
let expected_extension_cbor = [
|
||||
@@ -2426,7 +2419,7 @@ mod test {
|
||||
let mut env = TestEnv::new();
|
||||
let private_key = crypto::ecdsa::SecKey::gensk(env.rng());
|
||||
let credential_id = env.rng().gen_uniform_u8x32().to_vec();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let credential = PublicKeyCredentialSource {
|
||||
key_type: PublicKeyCredentialType::PublicKey,
|
||||
@@ -2464,7 +2457,7 @@ mod test {
|
||||
&mut env,
|
||||
get_assertion_params,
|
||||
DUMMY_CHANNEL_ID,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
let large_blob_key = match get_assertion_response.unwrap() {
|
||||
ResponseData::AuthenticatorGetAssertion(get_assertion_response) => {
|
||||
@@ -2484,7 +2477,7 @@ mod test {
|
||||
let client_pin =
|
||||
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, pin_uv_auth_protocol);
|
||||
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let mut make_credential_params = create_minimal_make_credential_parameters();
|
||||
let user1 = PublicKeyCredentialUserEntity {
|
||||
@@ -2535,7 +2528,7 @@ mod test {
|
||||
&mut env,
|
||||
get_assertion_params,
|
||||
DUMMY_CHANNEL_ID,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
let signature_counter = storage::global_signature_counter(&mut env).unwrap();
|
||||
check_assertion_response_with_user(
|
||||
@@ -2548,7 +2541,7 @@ mod test {
|
||||
);
|
||||
|
||||
let get_assertion_response =
|
||||
ctap_state.process_get_next_assertion(&mut env, DUMMY_CLOCK_VALUE);
|
||||
ctap_state.process_get_next_assertion(&mut env, CtapInstant::new(0));
|
||||
check_assertion_response_with_user(
|
||||
get_assertion_response,
|
||||
user1,
|
||||
@@ -2559,7 +2552,7 @@ mod test {
|
||||
);
|
||||
|
||||
let get_assertion_response =
|
||||
ctap_state.process_get_next_assertion(&mut env, DUMMY_CLOCK_VALUE);
|
||||
ctap_state.process_get_next_assertion(&mut env, CtapInstant::new(0));
|
||||
assert_eq!(
|
||||
get_assertion_response,
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_NOT_ALLOWED)
|
||||
@@ -2579,7 +2572,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_get_next_assertion_three_credentials_no_uv() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let mut make_credential_params = create_minimal_make_credential_parameters();
|
||||
make_credential_params.user.user_id = vec![0x01];
|
||||
@@ -2622,7 +2615,7 @@ mod test {
|
||||
&mut env,
|
||||
get_assertion_params,
|
||||
DUMMY_CHANNEL_ID,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
let signature_counter = storage::global_signature_counter(&mut env).unwrap();
|
||||
check_assertion_response(
|
||||
@@ -2633,15 +2626,15 @@ mod test {
|
||||
);
|
||||
|
||||
let get_assertion_response =
|
||||
ctap_state.process_get_next_assertion(&mut env, DUMMY_CLOCK_VALUE);
|
||||
ctap_state.process_get_next_assertion(&mut env, CtapInstant::new(0));
|
||||
check_assertion_response(get_assertion_response, vec![0x02], signature_counter, None);
|
||||
|
||||
let get_assertion_response =
|
||||
ctap_state.process_get_next_assertion(&mut env, DUMMY_CLOCK_VALUE);
|
||||
ctap_state.process_get_next_assertion(&mut env, CtapInstant::new(0));
|
||||
check_assertion_response(get_assertion_response, vec![0x01], signature_counter, None);
|
||||
|
||||
let get_assertion_response =
|
||||
ctap_state.process_get_next_assertion(&mut env, DUMMY_CLOCK_VALUE);
|
||||
ctap_state.process_get_next_assertion(&mut env, CtapInstant::new(0));
|
||||
assert_eq!(
|
||||
get_assertion_response,
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_NOT_ALLOWED)
|
||||
@@ -2651,10 +2644,10 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_get_next_assertion_not_allowed() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let get_assertion_response =
|
||||
ctap_state.process_get_next_assertion(&mut env, DUMMY_CLOCK_VALUE);
|
||||
ctap_state.process_get_next_assertion(&mut env, CtapInstant::new(0));
|
||||
assert_eq!(
|
||||
get_assertion_response,
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_NOT_ALLOWED)
|
||||
@@ -2687,7 +2680,7 @@ mod test {
|
||||
&mut env,
|
||||
get_assertion_params,
|
||||
DUMMY_CHANNEL_ID,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
assert!(get_assertion_response.is_ok());
|
||||
|
||||
@@ -2704,10 +2697,15 @@ mod test {
|
||||
4 => cbor_array![ES256_CRED_PARAM],
|
||||
};
|
||||
assert!(cbor_write(cbor_value, &mut command_cbor).is_ok());
|
||||
ctap_state.process_command(&mut env, &command_cbor, DUMMY_CHANNEL_ID, DUMMY_CLOCK_VALUE);
|
||||
ctap_state.process_command(
|
||||
&mut env,
|
||||
&command_cbor,
|
||||
DUMMY_CHANNEL_ID,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
|
||||
let get_assertion_response =
|
||||
ctap_state.process_get_next_assertion(&mut env, DUMMY_CLOCK_VALUE);
|
||||
ctap_state.process_get_next_assertion(&mut env, CtapInstant::new(0));
|
||||
assert_eq!(
|
||||
get_assertion_response,
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_NOT_ALLOWED)
|
||||
@@ -2718,7 +2716,7 @@ mod test {
|
||||
fn test_process_reset() {
|
||||
let mut env = TestEnv::new();
|
||||
let private_key = crypto::ecdsa::SecKey::gensk(env.rng());
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let credential_id = vec![0x01, 0x23, 0x45, 0x67];
|
||||
let credential_source = PublicKeyCredentialSource {
|
||||
@@ -2739,7 +2737,7 @@ mod test {
|
||||
assert!(storage::count_credentials(&mut env).unwrap() > 0);
|
||||
|
||||
let reset_reponse =
|
||||
ctap_state.process_command(&mut env, &[0x07], DUMMY_CHANNEL_ID, DUMMY_CLOCK_VALUE);
|
||||
ctap_state.process_command(&mut env, &[0x07], DUMMY_CHANNEL_ID, CtapInstant::new(0));
|
||||
let expected_response = vec![0x00];
|
||||
assert_eq!(reset_reponse, expected_response);
|
||||
assert!(storage::count_credentials(&mut env).unwrap() == 0);
|
||||
@@ -2750,9 +2748,10 @@ mod test {
|
||||
let mut env = TestEnv::new();
|
||||
env.user_presence()
|
||||
.set(|_| Err(Ctap2StatusCode::CTAP2_ERR_KEEPALIVE_CANCEL));
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let reset_reponse = ctap_state.process_reset(&mut env, DUMMY_CHANNEL_ID, DUMMY_CLOCK_VALUE);
|
||||
let reset_reponse =
|
||||
ctap_state.process_reset(&mut env, DUMMY_CHANNEL_ID, CtapInstant::new(0));
|
||||
|
||||
assert_eq!(
|
||||
reset_reponse,
|
||||
@@ -2763,26 +2762,27 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_reset_not_first() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
// This is a GetNextAssertion command.
|
||||
ctap_state.process_command(&mut env, &[0x08], DUMMY_CHANNEL_ID, DUMMY_CLOCK_VALUE);
|
||||
ctap_state.process_command(&mut env, &[0x08], DUMMY_CHANNEL_ID, CtapInstant::new(0));
|
||||
|
||||
let reset_reponse = ctap_state.process_reset(&mut env, DUMMY_CHANNEL_ID, DUMMY_CLOCK_VALUE);
|
||||
let reset_reponse =
|
||||
ctap_state.process_reset(&mut env, DUMMY_CHANNEL_ID, CtapInstant::new(0));
|
||||
assert_eq!(reset_reponse, Err(Ctap2StatusCode::CTAP2_ERR_NOT_ALLOWED));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_process_credential_management_unknown_subcommand() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
// The subcommand 0xEE does not exist.
|
||||
let reponse = ctap_state.process_command(
|
||||
&mut env,
|
||||
&[0x0A, 0xA1, 0x01, 0x18, 0xEE],
|
||||
DUMMY_CHANNEL_ID,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
CtapInstant::new(0),
|
||||
);
|
||||
let expected_response = vec![Ctap2StatusCode::CTAP2_ERR_INVALID_SUBCOMMAND as u8];
|
||||
assert_eq!(reponse, expected_response);
|
||||
@@ -2791,11 +2791,11 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_unknown_command() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
// This command does not exist.
|
||||
let reponse =
|
||||
ctap_state.process_command(&mut env, &[0xDF], DUMMY_CHANNEL_ID, DUMMY_CLOCK_VALUE);
|
||||
ctap_state.process_command(&mut env, &[0xDF], DUMMY_CHANNEL_ID, CtapInstant::new(0));
|
||||
let expected_response = vec![Ctap2StatusCode::CTAP1_ERR_INVALID_COMMAND as u8];
|
||||
assert_eq!(reponse, expected_response);
|
||||
}
|
||||
@@ -2804,7 +2804,7 @@ mod test {
|
||||
fn test_encrypt_decrypt_credential() {
|
||||
let mut env = TestEnv::new();
|
||||
let private_key = crypto::ecdsa::SecKey::gensk(env.rng());
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
// Usually, the relying party ID or its hash is provided by the client.
|
||||
// We are not testing the correctness of our SHA256 here, only if it is checked.
|
||||
@@ -2824,7 +2824,7 @@ mod test {
|
||||
fn test_encrypt_decrypt_bad_hmac() {
|
||||
let mut env = TestEnv::new();
|
||||
let private_key = crypto::ecdsa::SecKey::gensk(env.rng());
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
// Same as above.
|
||||
let rp_id_hash = [0x55; 32];
|
||||
@@ -2844,7 +2844,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_signature_counter() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let mut last_counter = storage::global_signature_counter(&mut env).unwrap();
|
||||
assert!(last_counter > 0);
|
||||
@@ -2861,7 +2861,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_vendor_configure() {
|
||||
let mut env = TestEnv::new();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
// Nothing should be configured at the beginning
|
||||
let response = ctap_state.process_vendor_configure(
|
||||
@@ -3066,7 +3066,7 @@ mod test {
|
||||
// The test identifier matches partition B.
|
||||
let mut env = TestEnv::new();
|
||||
let private_key = crypto::ecdsa::SecKey::gensk(env.rng());
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
const METADATA_LEN: usize = 40;
|
||||
|
||||
let data = vec![0xFF; 0x1000];
|
||||
@@ -3157,7 +3157,7 @@ mod test {
|
||||
fn test_vendor_upgrade_no_second_partition() {
|
||||
let mut env = TestEnv::new();
|
||||
env.disable_upgrade_storage();
|
||||
let mut ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
|
||||
let data = vec![0xFF; 0x1000];
|
||||
let hash = Sha256::hash(&data).to_vec();
|
||||
@@ -3176,7 +3176,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_vendor_upgrade_info() {
|
||||
let mut env = TestEnv::new();
|
||||
let ctap_state = CtapState::new(&mut env, DUMMY_CLOCK_VALUE);
|
||||
let ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||
let partition_address = env.upgrade_storage().unwrap().partition_address();
|
||||
|
||||
let upgrade_info_reponse = ctap_state.process_vendor_upgrade_info(&mut env);
|
||||
|
||||
Reference in New Issue
Block a user