Merge pull request #223 from kaczmarczyck/get-next-assertion

GetNextAssertion
This commit is contained in:
kaczmarczyck
2020-11-26 19:48:52 +01:00
committed by GitHub
8 changed files with 580 additions and 186 deletions

View File

@@ -147,7 +147,7 @@ fn process_message<CheckUserPresence>(
pub fn process_ctap_any_type(data: &[u8]) { pub fn process_ctap_any_type(data: &[u8]) {
// Initialize ctap state and hid and get the allocated cid. // Initialize ctap state and hid and get the allocated cid.
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
let mut ctap_hid = CtapHid::new(); let mut ctap_hid = CtapHid::new();
let cid = initialize(&mut ctap_state, &mut ctap_hid); let cid = initialize(&mut ctap_state, &mut ctap_hid);
// Wrap input as message with the allocated cid. // Wrap input as message with the allocated cid.
@@ -165,7 +165,7 @@ pub fn process_ctap_specific_type(data: &[u8], input_type: InputType) {
} }
// Initialize ctap state and hid and get the allocated cid. // Initialize ctap state and hid and get the allocated cid.
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
let mut ctap_hid = CtapHid::new(); let mut ctap_hid = CtapHid::new();
let cid = initialize(&mut ctap_state, &mut ctap_hid); let cid = initialize(&mut ctap_state, &mut ctap_hid);
// Wrap input as message with allocated cid and command type. // Wrap input as message with allocated cid and command type.

View File

@@ -57,8 +57,8 @@ impl Command {
const AUTHENTICATOR_GET_INFO: u8 = 0x04; const AUTHENTICATOR_GET_INFO: u8 = 0x04;
const AUTHENTICATOR_CLIENT_PIN: u8 = 0x06; const AUTHENTICATOR_CLIENT_PIN: u8 = 0x06;
const AUTHENTICATOR_RESET: u8 = 0x07; const AUTHENTICATOR_RESET: u8 = 0x07;
// TODO(kaczmarczyck) use or remove those constants
const AUTHENTICATOR_GET_NEXT_ASSERTION: u8 = 0x08; const AUTHENTICATOR_GET_NEXT_ASSERTION: u8 = 0x08;
// TODO(kaczmarczyck) use or remove those constants
const AUTHENTICATOR_BIO_ENROLLMENT: u8 = 0x09; const AUTHENTICATOR_BIO_ENROLLMENT: u8 = 0x09;
const AUTHENTICATOR_CREDENTIAL_MANAGEMENT: u8 = 0xA0; const AUTHENTICATOR_CREDENTIAL_MANAGEMENT: u8 = 0xA0;
const AUTHENTICATOR_SELECTION: u8 = 0xB0; const AUTHENTICATOR_SELECTION: u8 = 0xB0;

View File

@@ -440,7 +440,7 @@ mod test {
fn test_process_register() { fn test_process_register() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
let application = [0x0A; 32]; let application = [0x0A; 32];
let message = create_register_message(&application); let message = create_register_message(&application);
@@ -490,7 +490,7 @@ mod test {
fn test_process_register_bad_message() { fn test_process_register_bad_message() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
let application = [0x0A; 32]; let application = [0x0A; 32];
let message = create_register_message(&application); let message = create_register_message(&application);
@@ -510,7 +510,7 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
ctap_state.u2f_up_state.consume_up(START_CLOCK_VALUE); ctap_state.u2f_up_state.consume_up(START_CLOCK_VALUE);
ctap_state.u2f_up_state.grant_up(START_CLOCK_VALUE); ctap_state.u2f_up_state.grant_up(START_CLOCK_VALUE);
@@ -524,7 +524,7 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let sk = crypto::ecdsa::SecKey::gensk(&mut rng); let sk = crypto::ecdsa::SecKey::gensk(&mut rng);
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
let rp_id = "example.com"; let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
@@ -542,7 +542,7 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let sk = crypto::ecdsa::SecKey::gensk(&mut rng); let sk = crypto::ecdsa::SecKey::gensk(&mut rng);
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
let rp_id = "example.com"; let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
@@ -561,7 +561,7 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let sk = crypto::ecdsa::SecKey::gensk(&mut rng); let sk = crypto::ecdsa::SecKey::gensk(&mut rng);
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
let rp_id = "example.com"; let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
@@ -587,7 +587,7 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let sk = crypto::ecdsa::SecKey::gensk(&mut rng); let sk = crypto::ecdsa::SecKey::gensk(&mut rng);
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
let rp_id = "example.com"; let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
@@ -607,7 +607,7 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let sk = crypto::ecdsa::SecKey::gensk(&mut rng); let sk = crypto::ecdsa::SecKey::gensk(&mut rng);
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
let rp_id = "example.com"; let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
@@ -627,7 +627,7 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let sk = crypto::ecdsa::SecKey::gensk(&mut rng); let sk = crypto::ecdsa::SecKey::gensk(&mut rng);
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
let rp_id = "example.com"; let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
@@ -647,7 +647,7 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let sk = crypto::ecdsa::SecKey::gensk(&mut rng); let sk = crypto::ecdsa::SecKey::gensk(&mut rng);
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
let rp_id = "example.com"; let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
@@ -674,7 +674,7 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let sk = crypto::ecdsa::SecKey::gensk(&mut rng); let sk = crypto::ecdsa::SecKey::gensk(&mut rng);
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
let rp_id = "example.com"; let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
@@ -706,7 +706,7 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
ctap_state.u2f_up_state.consume_up(START_CLOCK_VALUE); ctap_state.u2f_up_state.consume_up(START_CLOCK_VALUE);
ctap_state.u2f_up_state.grant_up(START_CLOCK_VALUE); ctap_state.u2f_up_state.grant_up(START_CLOCK_VALUE);
@@ -723,7 +723,7 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1");
let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence, START_CLOCK_VALUE);
ctap_state.u2f_up_state.consume_up(START_CLOCK_VALUE); ctap_state.u2f_up_state.consume_up(START_CLOCK_VALUE);
ctap_state.u2f_up_state.grant_up(START_CLOCK_VALUE); ctap_state.u2f_up_state.grant_up(START_CLOCK_VALUE);

View File

@@ -308,7 +308,8 @@ impl TryFrom<cbor::Value> for GetAssertionExtensions {
} }
} }
#[cfg_attr(any(test, feature = "debug_ctap"), derive(Clone, Debug, PartialEq))] #[derive(Clone)]
#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))]
pub struct GetAssertionHmacSecretInput { pub struct GetAssertionHmacSecretInput {
pub key_agreement: CoseKey, pub key_agreement: CoseKey,
pub salt_enc: Vec<u8>, pub salt_enc: Vec<u8>,
@@ -499,6 +500,7 @@ pub struct PublicKeyCredentialSource {
pub other_ui: Option<String>, pub other_ui: Option<String>,
pub cred_random: Option<Vec<u8>>, pub cred_random: Option<Vec<u8>>,
pub cred_protect_policy: Option<CredentialProtectionPolicy>, pub cred_protect_policy: Option<CredentialProtectionPolicy>,
pub creation_order: u64,
} }
// We serialize credentials for the persistent storage using CBOR maps. Each field of a credential // We serialize credentials for the persistent storage using CBOR maps. Each field of a credential
@@ -511,6 +513,7 @@ enum PublicKeyCredentialSourceField {
OtherUi = 4, OtherUi = 4,
CredRandom = 5, CredRandom = 5,
CredProtectPolicy = 6, CredProtectPolicy = 6,
CreationOrder = 7,
// When a field is removed, its tag should be reserved and not used for new fields. We document // When a field is removed, its tag should be reserved and not used for new fields. We document
// those reserved tags below. // those reserved tags below.
// Reserved tags: none. // Reserved tags: none.
@@ -534,6 +537,7 @@ impl From<PublicKeyCredentialSource> for cbor::Value {
PublicKeyCredentialSourceField::OtherUi => credential.other_ui, PublicKeyCredentialSourceField::OtherUi => credential.other_ui,
PublicKeyCredentialSourceField::CredRandom => credential.cred_random, PublicKeyCredentialSourceField::CredRandom => credential.cred_random,
PublicKeyCredentialSourceField::CredProtectPolicy => credential.cred_protect_policy, PublicKeyCredentialSourceField::CredProtectPolicy => credential.cred_protect_policy,
PublicKeyCredentialSourceField::CreationOrder => credential.creation_order,
} }
} }
} }
@@ -551,6 +555,7 @@ impl TryFrom<cbor::Value> for PublicKeyCredentialSource {
PublicKeyCredentialSourceField::OtherUi => other_ui, PublicKeyCredentialSourceField::OtherUi => other_ui,
PublicKeyCredentialSourceField::CredRandom => cred_random, PublicKeyCredentialSourceField::CredRandom => cred_random,
PublicKeyCredentialSourceField::CredProtectPolicy => cred_protect_policy, PublicKeyCredentialSourceField::CredProtectPolicy => cred_protect_policy,
PublicKeyCredentialSourceField::CreationOrder => creation_order,
} = extract_map(cbor_value)?; } = extract_map(cbor_value)?;
} }
@@ -568,6 +573,7 @@ impl TryFrom<cbor::Value> for PublicKeyCredentialSource {
let cred_protect_policy = cred_protect_policy let cred_protect_policy = cred_protect_policy
.map(CredentialProtectionPolicy::try_from) .map(CredentialProtectionPolicy::try_from)
.transpose()?; .transpose()?;
let creation_order = creation_order.map(extract_unsigned).unwrap_or(Ok(0))?;
// We don't return whether there were unknown fields in the CBOR value. This means that // We don't return whether there were unknown fields in the CBOR value. This means that
// deserialization is not injective. In particular deserialization is only an inverse of // deserialization is not injective. In particular deserialization is only an inverse of
// serialization at a given version of OpenSK. This is not a problem because: // serialization at a given version of OpenSK. This is not a problem because:
@@ -587,6 +593,7 @@ impl TryFrom<cbor::Value> for PublicKeyCredentialSource {
other_ui, other_ui,
cred_random, cred_random,
cred_protect_policy, cred_protect_policy,
creation_order,
}) })
} }
} }
@@ -603,7 +610,8 @@ impl PublicKeyCredentialSource {
// TODO(kaczmarczyck) we could decide to split this data type up // TODO(kaczmarczyck) we could decide to split this data type up
// It depends on the algorithm though, I think. // It depends on the algorithm though, I think.
// So before creating a mess, this is my workaround. // So before creating a mess, this is my workaround.
#[cfg_attr(any(test, feature = "debug_ctap"), derive(Clone, Debug, PartialEq))] #[derive(Clone)]
#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))]
pub struct CoseKey(pub BTreeMap<cbor::KeyType, cbor::Value>); pub struct CoseKey(pub BTreeMap<cbor::KeyType, cbor::Value>);
// This is the algorithm specifier that is supposed to be used in a COSE key // This is the algorithm specifier that is supposed to be used in a COSE key
@@ -1355,6 +1363,7 @@ mod test {
other_ui: None, other_ui: None,
cred_random: None, cred_random: None,
cred_protect_policy: None, cred_protect_policy: None,
creation_order: 0,
}; };
assert_eq!( assert_eq!(

View File

@@ -200,7 +200,8 @@ impl CtapHid {
// Each transaction is atomic, so we process the command directly here and // Each transaction is atomic, so we process the command directly here and
// don't handle any other packet in the meantime. // don't handle any other packet in the meantime.
// TODO: Send keep-alive packets in the meantime. // TODO: Send keep-alive packets in the meantime.
let response = ctap_state.process_command(&message.payload, cid); let response =
ctap_state.process_command(&message.payload, cid, clock_value);
if let Some(iterator) = CtapHid::split_message(Message { if let Some(iterator) = CtapHid::split_message(Message {
cid, cid,
cmd: CtapHid::COMMAND_CBOR, cmd: CtapHid::COMMAND_CBOR,
@@ -520,7 +521,7 @@ mod test {
fn test_spurious_continuation_packet() { fn test_spurious_continuation_packet() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let user_immediately_present = |_| Ok(()); let user_immediately_present = |_| Ok(());
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
let mut ctap_hid = CtapHid::new(); let mut ctap_hid = CtapHid::new();
let mut packet = [0x00; 64]; let mut packet = [0x00; 64];
@@ -541,7 +542,7 @@ mod test {
fn test_command_init() { fn test_command_init() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let user_immediately_present = |_| Ok(()); let user_immediately_present = |_| Ok(());
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
let mut ctap_hid = CtapHid::new(); let mut ctap_hid = CtapHid::new();
let reply = process_messages( let reply = process_messages(
@@ -586,7 +587,7 @@ mod test {
fn test_command_init_for_sync() { fn test_command_init_for_sync() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let user_immediately_present = |_| Ok(()); let user_immediately_present = |_| Ok(());
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
let mut ctap_hid = CtapHid::new(); let mut ctap_hid = CtapHid::new();
let cid = cid_from_init(&mut ctap_hid, &mut ctap_state); let cid = cid_from_init(&mut ctap_hid, &mut ctap_state);
@@ -646,7 +647,7 @@ mod test {
fn test_command_ping() { fn test_command_ping() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let user_immediately_present = |_| Ok(()); let user_immediately_present = |_| Ok(());
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
let mut ctap_hid = CtapHid::new(); let mut ctap_hid = CtapHid::new();
let cid = cid_from_init(&mut ctap_hid, &mut ctap_state); let cid = cid_from_init(&mut ctap_hid, &mut ctap_state);

File diff suppressed because it is too large Load Diff

View File

@@ -342,6 +342,26 @@ impl PersistentStore {
.count()) .count())
} }
pub fn new_creation_order(&self) -> Result<u64, Ctap2StatusCode> {
Ok(self
.store
.find_all(&Key::Credential {
rp_id: None,
credential_id: None,
user_handle: None,
})
.filter_map(|(_, entry)| {
debug_assert_eq!(entry.tag, TAG_CREDENTIAL);
let credential = deserialize_credential(entry.data);
debug_assert!(credential.is_some());
credential
})
.map(|c| c.creation_order)
.max()
.unwrap_or(0)
.wrapping_add(1))
}
pub fn global_signature_counter(&self) -> Result<u32, Ctap2StatusCode> { pub fn global_signature_counter(&self) -> Result<u32, Ctap2StatusCode> {
Ok(self Ok(self
.store .store
@@ -702,6 +722,7 @@ mod test {
other_ui: None, other_ui: None,
cred_random: None, cred_random: None,
cred_protect_policy: None, cred_protect_policy: None,
creation_order: 0,
} }
} }
@@ -737,6 +758,21 @@ mod test {
assert!(persistent_store.count_credentials().unwrap() > 0); assert!(persistent_store.count_credentials().unwrap() > 0);
} }
#[test]
fn test_credential_order() {
let mut rng = ThreadRng256 {};
let mut persistent_store = PersistentStore::new(&mut rng);
let credential_source = create_credential_source(&mut rng, "example.com", vec![]);
let current_latest_creation = credential_source.creation_order;
assert!(persistent_store.store_credential(credential_source).is_ok());
let mut credential_source = create_credential_source(&mut rng, "example.com", vec![]);
credential_source.creation_order = persistent_store.new_creation_order().unwrap();
assert!(credential_source.creation_order > current_latest_creation);
let current_latest_creation = credential_source.creation_order;
assert!(persistent_store.store_credential(credential_source).is_ok());
assert!(persistent_store.new_creation_order().unwrap() > current_latest_creation);
}
#[test] #[test]
#[allow(clippy::assertions_on_constants)] #[allow(clippy::assertions_on_constants)]
fn test_fill_store() { fn test_fill_store() {
@@ -865,6 +901,7 @@ mod test {
cred_protect_policy: Some( cred_protect_policy: Some(
CredentialProtectionPolicy::UserVerificationOptionalWithCredentialIdList, CredentialProtectionPolicy::UserVerificationOptionalWithCredentialIdList,
), ),
creation_order: 0,
}; };
assert!(persistent_store.store_credential(credential).is_ok()); assert!(persistent_store.store_credential(credential).is_ok());
@@ -906,6 +943,7 @@ mod test {
other_ui: None, other_ui: None,
cred_random: None, cred_random: None,
cred_protect_policy: None, cred_protect_policy: None,
creation_order: 0,
}; };
assert_eq!(found_credential, Some(expected_credential)); assert_eq!(found_credential, Some(expected_credential));
} }
@@ -925,6 +963,7 @@ mod test {
other_ui: None, other_ui: None,
cred_random: None, cred_random: None,
cred_protect_policy: Some(CredentialProtectionPolicy::UserVerificationRequired), cred_protect_policy: Some(CredentialProtectionPolicy::UserVerificationRequired),
creation_order: 0,
}; };
assert!(persistent_store.store_credential(credential).is_ok()); assert!(persistent_store.store_credential(credential).is_ok());
@@ -1102,6 +1141,7 @@ mod test {
other_ui: None, other_ui: None,
cred_random: None, cred_random: None,
cred_protect_policy: None, cred_protect_policy: None,
creation_order: 0,
}; };
let serialized = serialize_credential(credential.clone()).unwrap(); let serialized = serialize_credential(credential.clone()).unwrap();
let reconstructed = deserialize_credential(&serialized).unwrap(); let reconstructed = deserialize_credential(&serialized).unwrap();

View File

@@ -37,9 +37,11 @@ use libtock_drivers::console::Console;
use libtock_drivers::led; use libtock_drivers::led;
use libtock_drivers::result::{FlexUnwrap, TockError}; use libtock_drivers::result::{FlexUnwrap, TockError};
use libtock_drivers::timer; use libtock_drivers::timer;
use libtock_drivers::timer::Duration;
#[cfg(feature = "debug_ctap")] #[cfg(feature = "debug_ctap")]
use libtock_drivers::timer::Timer; use libtock_drivers::timer::Timer;
use libtock_drivers::timer::{Duration, Timestamp}; #[cfg(feature = "debug_ctap")]
use libtock_drivers::timer::Timestamp;
use libtock_drivers::usb_ctap_hid; use libtock_drivers::usb_ctap_hid;
const KEEPALIVE_DELAY_MS: isize = 100; const KEEPALIVE_DELAY_MS: isize = 100;
@@ -57,12 +59,13 @@ fn main() {
panic!("Cannot setup USB driver"); panic!("Cannot setup USB driver");
} }
let boot_time = timer.get_current_clock().flex_unwrap();
let mut rng = TockRng256 {}; let mut rng = TockRng256 {};
let mut ctap_state = CtapState::new(&mut rng, check_user_presence); let mut ctap_state = CtapState::new(&mut rng, check_user_presence, boot_time);
let mut ctap_hid = CtapHid::new(); let mut ctap_hid = CtapHid::new();
let mut led_counter = 0; let mut led_counter = 0;
let mut last_led_increment = timer.get_current_clock().flex_unwrap(); let mut last_led_increment = boot_time;
// Main loop. If CTAP1 is used, we register button presses for U2F while receiving and waiting. // Main loop. If CTAP1 is used, we register button presses for U2F while receiving and waiting.
// The way TockOS and apps currently interact, callbacks need a yield syscall to execute, // The way TockOS and apps currently interact, callbacks need a yield syscall to execute,
@@ -115,7 +118,7 @@ fn main() {
// These calls are making sure that even for long inactivity, wrapping clock values // These calls are making sure that even for long inactivity, wrapping clock values
// never randomly wink or grant user presence for U2F. // never randomly wink or grant user presence for U2F.
ctap_state.check_disable_reset(Timestamp::<isize>::from_clock_value(now)); ctap_state.update_command_permission(now);
ctap_hid.wink_permission = ctap_hid.wink_permission.check_expiration(now); ctap_hid.wink_permission = ctap_hid.wink_permission.check_expiration(now);
if has_packet { if has_packet {