Introduce Customization struct (#458)
* Introduce Customization trait * Introduce Customization trait including the customization accessors that control various behaviors. * Expose Customization through a getter API in Env, and make the code that directly access the constants currently switch to accessing the customizations via Env. * TockEnv's customization getter implementation directly returns the reference of the global DEFAULT_CUSTOMIZATION constant, so the constant values are still inlined and dead code won't be compiled. * We'll add the customizations from global constants to the struct one-by-one, only MAX_MSG_SIZE in this commit. * Small fixes * Fix deploy script * put is_valid under std gate
This commit is contained in:
@@ -76,7 +76,8 @@ fn initialize(ctap: &mut Ctap<TestEnv>) -> ChannelID {
|
|||||||
for pkt_reply in
|
for pkt_reply in
|
||||||
ctap.process_hid_packet(&pkt_request, Transport::MainHid, CtapInstant::new(0))
|
ctap.process_hid_packet(&pkt_request, Transport::MainHid, CtapInstant::new(0))
|
||||||
{
|
{
|
||||||
if let Ok(Some(result)) = assembler_reply.parse_packet(&pkt_reply, CtapInstant::new(0))
|
if let Ok(Some(result)) =
|
||||||
|
assembler_reply.parse_packet(ctap.env(), &pkt_reply, CtapInstant::new(0))
|
||||||
{
|
{
|
||||||
result_cid.copy_from_slice(&result.payload[8..12]);
|
result_cid.copy_from_slice(&result.payload[8..12]);
|
||||||
}
|
}
|
||||||
@@ -118,7 +119,7 @@ fn process_message(data: &[u8], ctap: &mut Ctap<TestEnv>) {
|
|||||||
ctap.process_hid_packet(&pkt_request, Transport::MainHid, CtapInstant::new(0))
|
ctap.process_hid_packet(&pkt_request, Transport::MainHid, CtapInstant::new(0))
|
||||||
{
|
{
|
||||||
// Only checks for assembling crashes, not for semantics.
|
// Only checks for assembling crashes, not for semantics.
|
||||||
let _ = assembler_reply.parse_packet(&pkt_reply, CtapInstant::new(0));
|
let _ = assembler_reply.parse_packet(ctap.env(), &pkt_reply, CtapInstant::new(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,6 +203,7 @@ pub fn process_ctap_structured(data: &[u8], input_type: InputType) -> arbitrary:
|
|||||||
|
|
||||||
// Splits the given data as HID packets and reassembles it, verifying that the original input message is reconstructed.
|
// Splits the given data as HID packets and reassembles it, verifying that the original input message is reconstructed.
|
||||||
pub fn split_assemble_hid_packets(data: &[u8]) {
|
pub fn split_assemble_hid_packets(data: &[u8]) {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
let message = raw_to_message(data);
|
let message = raw_to_message(data);
|
||||||
if let Some(hid_packet_iterator) = HidPacketIterator::new(message.clone()) {
|
if let Some(hid_packet_iterator) = HidPacketIterator::new(message.clone()) {
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
@@ -209,12 +211,12 @@ pub fn split_assemble_hid_packets(data: &[u8]) {
|
|||||||
if let Some((last_packet, first_packets)) = packets.split_last() {
|
if let Some((last_packet, first_packets)) = packets.split_last() {
|
||||||
for packet in first_packets {
|
for packet in first_packets {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(packet, CtapInstant::new(0)),
|
assembler.parse_packet(&mut env, packet, CtapInstant::new(0)),
|
||||||
Ok(None)
|
Ok(None)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(last_packet, CtapInstant::new(0)),
|
assembler.parse_packet(&mut env, last_packet, CtapInstant::new(0)),
|
||||||
Ok(Some(message))
|
Ok(Some(message))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
62
src/api/customization.rs
Normal file
62
src/api/customization.rs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2022 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
//! This file contains all customizable constants.
|
||||||
|
//!
|
||||||
|
//! If you adapt them, make sure to run the tests before flashing the firmware.
|
||||||
|
//! Our deploy script enforces the invariants.
|
||||||
|
|
||||||
|
pub trait Customization {
|
||||||
|
/// Maximum message size send for CTAP commands.
|
||||||
|
///
|
||||||
|
/// The maximum value is 7609, as HID packets can not encode longer messages.
|
||||||
|
/// 1024 is the default mentioned in the authenticatorLargeBlobs commands.
|
||||||
|
/// Larger values are preferred, as that allows more parameters in commands.
|
||||||
|
/// If long commands are too unreliable on your hardware, consider decreasing
|
||||||
|
/// this value.
|
||||||
|
fn max_msg_size(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CustomizationImpl {
|
||||||
|
pub max_msg_size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const DEFAULT_CUSTOMIZATION: CustomizationImpl = CustomizationImpl { max_msg_size: 7609 };
|
||||||
|
|
||||||
|
impl Customization for CustomizationImpl {
|
||||||
|
fn max_msg_size(&self) -> usize {
|
||||||
|
self.max_msg_size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub fn is_valid(customization: &impl Customization) -> bool {
|
||||||
|
// Max message size must be between 1024 and 7609.
|
||||||
|
if customization.max_msg_size() < 1024 || customization.max_msg_size() > 7609 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(clippy::assertions_on_constants)]
|
||||||
|
fn test_invariants() {
|
||||||
|
assert!(is_valid(&DEFAULT_CUSTOMIZATION));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,5 +3,6 @@
|
|||||||
//! The [environment](crate::env::Env) is split into components. Each component has an API described
|
//! The [environment](crate::env::Env) is split into components. Each component has an API described
|
||||||
//! by a trait. This module gathers the API of those components.
|
//! by a trait. This module gathers the API of those components.
|
||||||
|
|
||||||
|
pub mod customization;
|
||||||
pub mod firmware_protection;
|
pub mod firmware_protection;
|
||||||
pub mod upgrade_storage;
|
pub mod upgrade_storage;
|
||||||
|
|||||||
@@ -119,15 +119,6 @@ pub const ENTERPRISE_ATTESTATION_MODE: Option<EnterpriseAttestationMode> = None;
|
|||||||
/// VendorFacilitated.
|
/// VendorFacilitated.
|
||||||
pub const ENTERPRISE_RP_ID_LIST: &[&str] = &[];
|
pub const ENTERPRISE_RP_ID_LIST: &[&str] = &[];
|
||||||
|
|
||||||
/// Maximum message size send for CTAP commands.
|
|
||||||
///
|
|
||||||
/// The maximum value is 7609, as HID packets can not encode longer messages.
|
|
||||||
/// 1024 is the default mentioned in the authenticatorLargeBlobs commands.
|
|
||||||
/// Larger values are preferred, as that allows more parameters in commands.
|
|
||||||
/// If long commands are too unreliable on your hardware, consider decreasing
|
|
||||||
/// this value.
|
|
||||||
pub const MAX_MSG_SIZE: usize = 7609;
|
|
||||||
|
|
||||||
/// Sets the number of consecutive failed PINs before blocking interaction.
|
/// Sets the number of consecutive failed PINs before blocking interaction.
|
||||||
///
|
///
|
||||||
/// # Invariant
|
/// # Invariant
|
||||||
@@ -252,8 +243,6 @@ mod test {
|
|||||||
} else {
|
} else {
|
||||||
assert!(ENTERPRISE_RP_ID_LIST.is_empty());
|
assert!(ENTERPRISE_RP_ID_LIST.is_empty());
|
||||||
}
|
}
|
||||||
assert!(MAX_MSG_SIZE >= 1024);
|
|
||||||
assert!(MAX_MSG_SIZE <= 7609);
|
|
||||||
assert!(MAX_PIN_RETRIES <= 8);
|
assert!(MAX_PIN_RETRIES <= 8);
|
||||||
assert!(MAX_CRED_BLOB_LENGTH >= 32);
|
assert!(MAX_CRED_BLOB_LENGTH >= 32);
|
||||||
if let Some(count) = MAX_CREDENTIAL_COUNT_IN_LIST {
|
if let Some(count) = MAX_CREDENTIAL_COUNT_IN_LIST {
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ impl CtapHid {
|
|||||||
packet: &HidPacket,
|
packet: &HidPacket,
|
||||||
clock_value: CtapInstant,
|
clock_value: CtapInstant,
|
||||||
) -> Option<Message> {
|
) -> Option<Message> {
|
||||||
match self.assembler.parse_packet(packet, clock_value) {
|
match self.assembler.parse_packet(env, packet, clock_value) {
|
||||||
Ok(Some(message)) => {
|
Ok(Some(message)) => {
|
||||||
debug_ctap!(env, "Received message: {:02x?}", message);
|
debug_ctap!(env, "Received message: {:02x?}", message);
|
||||||
self.preprocess_message(message)
|
self.preprocess_message(message)
|
||||||
@@ -420,6 +420,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_split_assemble() {
|
fn test_split_assemble() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
for payload_len in 0..7609 {
|
for payload_len in 0..7609 {
|
||||||
let message = Message {
|
let message = Message {
|
||||||
cid: [0x12, 0x34, 0x56, 0x78],
|
cid: [0x12, 0x34, 0x56, 0x78],
|
||||||
@@ -430,7 +431,7 @@ mod test {
|
|||||||
let mut messages = Vec::new();
|
let mut messages = Vec::new();
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
for packet in HidPacketIterator::new(message.clone()).unwrap() {
|
for packet in HidPacketIterator::new(message.clone()).unwrap() {
|
||||||
match assembler.parse_packet(&packet, CtapInstant::new(0)) {
|
match assembler.parse_packet(&mut env, &packet, CtapInstant::new(0)) {
|
||||||
Ok(Some(msg)) => messages.push(msg),
|
Ok(Some(msg)) => messages.push(msg),
|
||||||
Ok(None) => (),
|
Ok(None) => (),
|
||||||
Err(_) => panic!("Couldn't assemble packet: {:02x?}", &packet as &[u8]),
|
Err(_) => panic!("Couldn't assemble packet: {:02x?}", &packet as &[u8]),
|
||||||
|
|||||||
@@ -12,12 +12,12 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::clock::CtapInstant;
|
|
||||||
|
|
||||||
use super::super::customization::MAX_MSG_SIZE;
|
|
||||||
use super::{
|
use super::{
|
||||||
ChannelID, CtapHid, CtapHidCommand, CtapHidError, HidPacket, Message, ProcessedPacket,
|
ChannelID, CtapHid, CtapHidCommand, CtapHidError, HidPacket, Message, ProcessedPacket,
|
||||||
};
|
};
|
||||||
|
use crate::api::customization::Customization;
|
||||||
|
use crate::clock::CtapInstant;
|
||||||
|
use crate::env::Env;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::mem::swap;
|
use core::mem::swap;
|
||||||
|
|
||||||
@@ -73,6 +73,7 @@ impl MessageAssembler {
|
|||||||
// packet was received.
|
// packet was received.
|
||||||
pub fn parse_packet(
|
pub fn parse_packet(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
env: &mut impl Env,
|
||||||
packet: &HidPacket,
|
packet: &HidPacket,
|
||||||
timestamp: CtapInstant,
|
timestamp: CtapInstant,
|
||||||
) -> Result<Option<Message>, (ChannelID, CtapHidError)> {
|
) -> Result<Option<Message>, (ChannelID, CtapHidError)> {
|
||||||
@@ -97,7 +98,7 @@ impl MessageAssembler {
|
|||||||
// Expecting an initialization packet.
|
// Expecting an initialization packet.
|
||||||
match processed_packet {
|
match processed_packet {
|
||||||
ProcessedPacket::InitPacket { cmd, len, data } => {
|
ProcessedPacket::InitPacket { cmd, len, data } => {
|
||||||
self.parse_init_packet(*cid, cmd, len, data, timestamp)
|
self.parse_init_packet(env, *cid, cmd, len, data, timestamp)
|
||||||
}
|
}
|
||||||
ProcessedPacket::ContinuationPacket { .. } => {
|
ProcessedPacket::ContinuationPacket { .. } => {
|
||||||
// CTAP specification (version 20190130) section 8.1.5.4
|
// CTAP specification (version 20190130) section 8.1.5.4
|
||||||
@@ -119,7 +120,7 @@ impl MessageAssembler {
|
|||||||
ProcessedPacket::InitPacket { cmd, len, data } => {
|
ProcessedPacket::InitPacket { cmd, len, data } => {
|
||||||
self.reset();
|
self.reset();
|
||||||
if cmd == CtapHidCommand::Init as u8 {
|
if cmd == CtapHidCommand::Init as u8 {
|
||||||
self.parse_init_packet(*cid, cmd, len, data, timestamp)
|
self.parse_init_packet(env, *cid, cmd, len, data, timestamp)
|
||||||
} else {
|
} else {
|
||||||
Err((*cid, CtapHidError::InvalidSeq))
|
Err((*cid, CtapHidError::InvalidSeq))
|
||||||
}
|
}
|
||||||
@@ -143,6 +144,7 @@ impl MessageAssembler {
|
|||||||
|
|
||||||
fn parse_init_packet(
|
fn parse_init_packet(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
env: &mut impl Env,
|
||||||
cid: ChannelID,
|
cid: ChannelID,
|
||||||
cmd: u8,
|
cmd: u8,
|
||||||
len: usize,
|
len: usize,
|
||||||
@@ -151,7 +153,7 @@ impl MessageAssembler {
|
|||||||
) -> Result<Option<Message>, (ChannelID, CtapHidError)> {
|
) -> Result<Option<Message>, (ChannelID, CtapHidError)> {
|
||||||
// Reject invalid lengths early to reduce the risk of running out of memory.
|
// Reject invalid lengths early to reduce the risk of running out of memory.
|
||||||
// TODO: also reject invalid commands early?
|
// TODO: also reject invalid commands early?
|
||||||
if len > MAX_MSG_SIZE {
|
if len > env.customization().max_msg_size() {
|
||||||
return Err((cid, CtapHidError::InvalidLen));
|
return Err((cid, CtapHidError::InvalidLen));
|
||||||
}
|
}
|
||||||
self.cid = cid;
|
self.cid = cid;
|
||||||
@@ -186,6 +188,7 @@ impl MessageAssembler {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::ctap::hid::CtapHid;
|
use crate::ctap::hid::CtapHid;
|
||||||
|
use crate::env::test::TestEnv;
|
||||||
use embedded_time::duration::Milliseconds;
|
use embedded_time::duration::Milliseconds;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -207,11 +210,13 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_empty_payload() {
|
fn test_empty_payload() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
// Except for tests that exercise timeouts, all packets are synchronized at the same dummy
|
// Except for tests that exercise timeouts, all packets are synchronized at the same dummy
|
||||||
// timestamp.
|
// timestamp.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x90]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x90]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -225,9 +230,11 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_one_packet() {
|
fn test_one_packet() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x90, 0x00, 0x10]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x90, 0x00, 0x10]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -241,12 +248,14 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_nonzero_padding() {
|
fn test_nonzero_padding() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
// CTAP specification (version 20190130) section 8.1.4
|
// CTAP specification (version 20190130) section 8.1.4
|
||||||
// It is written that "Unused bytes SHOULD be set to zero", so we test that non-zero
|
// It is written that "Unused bytes SHOULD be set to zero", so we test that non-zero
|
||||||
// padding is accepted as well.
|
// padding is accepted as well.
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x90, 0x00, 0x10], 0xFF),
|
&byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x90, 0x00, 0x10], 0xFF),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -260,9 +269,11 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_two_packets() {
|
fn test_two_packets() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -270,6 +281,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x00]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x00]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -283,9 +295,11 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_three_packets() {
|
fn test_three_packets() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x80]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x80]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -293,6 +307,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x00]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x00]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -300,6 +315,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x01]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x01]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -313,9 +329,11 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_max_packets() {
|
fn test_max_packets() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x1D, 0xB9]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x1D, 0xB9]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -324,6 +342,7 @@ mod test {
|
|||||||
for seq in 0..0x7F {
|
for seq in 0..0x7F {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, seq]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, seq]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -332,6 +351,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x7F]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x7F]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -345,6 +365,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_multiple_messages() {
|
fn test_multiple_messages() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
// Check that after yielding a message, the assembler is ready to process new messages.
|
// Check that after yielding a message, the assembler is ready to process new messages.
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
@@ -354,6 +375,7 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&byte_extend(
|
&byte_extend(
|
||||||
&[0x12, 0x34, 0x56, 0x78, 0x80 | cmd as u8, 0x00, 0x80],
|
&[0x12, 0x34, 0x56, 0x78, 0x80 | cmd as u8, 0x00, 0x80],
|
||||||
byte
|
byte
|
||||||
@@ -364,6 +386,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x00], byte),
|
&byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x00], byte),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -371,6 +394,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x01], byte),
|
&byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x01], byte),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -385,6 +409,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_channel_switch() {
|
fn test_channel_switch() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
// Check that the assembler can process messages from multiple channels, sequentially.
|
// Check that the assembler can process messages from multiple channels, sequentially.
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
@@ -395,6 +420,7 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&byte_extend(&[0x12, 0x34, 0x56, cid, 0x80 | cmd as u8, 0x00, 0x80], byte),
|
&byte_extend(&[0x12, 0x34, 0x56, cid, 0x80 | cmd as u8, 0x00, 0x80], byte),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -402,6 +428,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&byte_extend(&[0x12, 0x34, 0x56, cid, 0x00], byte),
|
&byte_extend(&[0x12, 0x34, 0x56, cid, 0x00], byte),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -409,6 +436,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&byte_extend(&[0x12, 0x34, 0x56, cid, 0x01], byte),
|
&byte_extend(&[0x12, 0x34, 0x56, cid, 0x01], byte),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -423,9 +451,11 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unexpected_channel() {
|
fn test_unexpected_channel() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -438,6 +468,7 @@ mod test {
|
|||||||
for byte in 0..=0xFF {
|
for byte in 0..=0xFF {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&byte_extend(&[0x12, 0x34, 0x56, 0x9A, cmd as u8, 0x00], byte),
|
&byte_extend(&[0x12, 0x34, 0x56, 0x9A, cmd as u8, 0x00], byte),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -448,6 +479,7 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x00]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x00]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -461,6 +493,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_spurious_continuation_packets() {
|
fn test_spurious_continuation_packets() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
// CTAP specification (version 20190130) section 8.1.5.4
|
// CTAP specification (version 20190130) section 8.1.5.4
|
||||||
// Spurious continuation packets appearing without a prior initialization packet will be
|
// Spurious continuation packets appearing without a prior initialization packet will be
|
||||||
// ignored.
|
// ignored.
|
||||||
@@ -470,6 +503,7 @@ mod test {
|
|||||||
let byte = 2 * i;
|
let byte = 2 * i;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x10], byte),
|
&byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x10], byte),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -484,6 +518,7 @@ mod test {
|
|||||||
let seq = i;
|
let seq = i;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, seq]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, seq]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -497,9 +532,11 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unexpected_init() {
|
fn test_unexpected_init() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -507,6 +544,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x80]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x80]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -516,9 +554,11 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unexpected_seq() {
|
fn test_unexpected_seq() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -526,6 +566,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x01]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x01]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -535,9 +576,11 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_timed_out_packet() {
|
fn test_timed_out_packet() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -545,6 +588,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x00]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x00]),
|
||||||
CtapInstant::new(0) + CtapHid::TIMEOUT_DURATION
|
CtapInstant::new(0) + CtapHid::TIMEOUT_DURATION
|
||||||
),
|
),
|
||||||
@@ -554,6 +598,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_just_in_time_packets() {
|
fn test_just_in_time_packets() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
let mut timestamp: CtapInstant = CtapInstant::new(0);
|
let mut timestamp: CtapInstant = CtapInstant::new(0);
|
||||||
// Delay between each packet is just below the threshold.
|
// Delay between each packet is just below the threshold.
|
||||||
let delay = CtapHid::TIMEOUT_DURATION - Milliseconds(1_u32);
|
let delay = CtapHid::TIMEOUT_DURATION - Milliseconds(1_u32);
|
||||||
@@ -561,6 +606,7 @@ mod test {
|
|||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x1D, 0xB9]),
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x1D, 0xB9]),
|
||||||
timestamp
|
timestamp
|
||||||
),
|
),
|
||||||
@@ -569,13 +615,21 @@ mod test {
|
|||||||
for seq in 0..0x7F {
|
for seq in 0..0x7F {
|
||||||
timestamp = timestamp + delay;
|
timestamp = timestamp + delay;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(&zero_extend(&[0x12, 0x34, 0x56, 0x78, seq]), timestamp),
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, seq]),
|
||||||
|
timestamp
|
||||||
|
),
|
||||||
Ok(None)
|
Ok(None)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
timestamp = timestamp + delay;
|
timestamp = timestamp + delay;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x7F]), timestamp),
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
|
&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x7F]),
|
||||||
|
timestamp
|
||||||
|
),
|
||||||
Ok(Some(Message {
|
Ok(Some(Message {
|
||||||
cid: [0x12, 0x34, 0x56, 0x78],
|
cid: [0x12, 0x34, 0x56, 0x78],
|
||||||
cmd: CtapHidCommand::Ping,
|
cmd: CtapHidCommand::Ping,
|
||||||
@@ -586,10 +640,12 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_init_sync() {
|
fn test_init_sync() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
let mut assembler = MessageAssembler::new();
|
let mut assembler = MessageAssembler::new();
|
||||||
// Ping packet with a length longer than one packet.
|
// Ping packet with a length longer than one packet.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x02, 0x00], 0x51),
|
&byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x02, 0x00], 0x51),
|
||||||
CtapInstant::new(0)
|
CtapInstant::new(0)
|
||||||
),
|
),
|
||||||
@@ -598,6 +654,7 @@ mod test {
|
|||||||
// Init packet on the same channel.
|
// Init packet on the same channel.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
assembler.parse_packet(
|
assembler.parse_packet(
|
||||||
|
&mut env,
|
||||||
&zero_extend(&[
|
&zero_extend(&[
|
||||||
0x12, 0x34, 0x56, 0x78, 0x86, 0x00, 0x08, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
|
0x12, 0x34, 0x56, 0x78, 0x86, 0x00, 0x08, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
|
||||||
0xDE, 0xF0
|
0xDE, 0xF0
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
|
|
||||||
use super::client_pin::{ClientPin, PinPermission};
|
use super::client_pin::{ClientPin, PinPermission};
|
||||||
use super::command::AuthenticatorLargeBlobsParameters;
|
use super::command::AuthenticatorLargeBlobsParameters;
|
||||||
use super::customization::MAX_MSG_SIZE;
|
|
||||||
use super::response::{AuthenticatorLargeBlobsResponse, ResponseData};
|
use super::response::{AuthenticatorLargeBlobsResponse, ResponseData};
|
||||||
use super::status_code::Ctap2StatusCode;
|
use super::status_code::Ctap2StatusCode;
|
||||||
|
use crate::api::customization::Customization;
|
||||||
use crate::ctap::storage;
|
use crate::ctap::storage;
|
||||||
use crate::env::Env;
|
use crate::env::Env;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
@@ -60,10 +60,10 @@ impl LargeBlobs {
|
|||||||
pin_uv_auth_protocol,
|
pin_uv_auth_protocol,
|
||||||
} = large_blobs_params;
|
} = large_blobs_params;
|
||||||
|
|
||||||
const MAX_FRAGMENT_LENGTH: usize = MAX_MSG_SIZE - 64;
|
let max_fragment_size = env.customization().max_msg_size() - 64;
|
||||||
|
|
||||||
if let Some(get) = get {
|
if let Some(get) = get {
|
||||||
if get > MAX_FRAGMENT_LENGTH || offset.checked_add(get).is_none() {
|
if get > max_fragment_size || offset.checked_add(get).is_none() {
|
||||||
return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_LENGTH);
|
return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_LENGTH);
|
||||||
}
|
}
|
||||||
let config = storage::get_large_blob_array(env, offset, get)?;
|
let config = storage::get_large_blob_array(env, offset, get)?;
|
||||||
@@ -73,7 +73,7 @@ impl LargeBlobs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut set) = set {
|
if let Some(mut set) = set {
|
||||||
if set.len() > MAX_FRAGMENT_LENGTH {
|
if set.len() > max_fragment_size {
|
||||||
return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_LENGTH);
|
return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_LENGTH);
|
||||||
}
|
}
|
||||||
if offset == 0 {
|
if offset == 0 {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ mod credential_management;
|
|||||||
mod crypto_wrapper;
|
mod crypto_wrapper;
|
||||||
#[cfg(feature = "with_ctap1")]
|
#[cfg(feature = "with_ctap1")]
|
||||||
mod ctap1;
|
mod ctap1;
|
||||||
mod customization;
|
pub mod customization;
|
||||||
pub mod data_formats;
|
pub mod data_formats;
|
||||||
pub mod hid;
|
pub mod hid;
|
||||||
mod key_material;
|
mod key_material;
|
||||||
@@ -45,7 +45,7 @@ use self::credential_management::process_credential_management;
|
|||||||
use self::crypto_wrapper::{aes256_cbc_decrypt, aes256_cbc_encrypt};
|
use self::crypto_wrapper::{aes256_cbc_decrypt, aes256_cbc_encrypt};
|
||||||
use self::customization::{
|
use self::customization::{
|
||||||
DEFAULT_CRED_PROTECT, ENTERPRISE_ATTESTATION_MODE, ENTERPRISE_RP_ID_LIST,
|
DEFAULT_CRED_PROTECT, ENTERPRISE_ATTESTATION_MODE, ENTERPRISE_RP_ID_LIST,
|
||||||
MAX_CREDENTIAL_COUNT_IN_LIST, MAX_CRED_BLOB_LENGTH, MAX_LARGE_BLOB_ARRAY_SIZE, MAX_MSG_SIZE,
|
MAX_CREDENTIAL_COUNT_IN_LIST, MAX_CRED_BLOB_LENGTH, MAX_LARGE_BLOB_ARRAY_SIZE,
|
||||||
MAX_RP_IDS_LENGTH, USE_BATCH_ATTESTATION, USE_SIGNATURE_COUNTER,
|
MAX_RP_IDS_LENGTH, USE_BATCH_ATTESTATION, USE_SIGNATURE_COUNTER,
|
||||||
};
|
};
|
||||||
use self::data_formats::{
|
use self::data_formats::{
|
||||||
@@ -66,6 +66,7 @@ use self::status_code::Ctap2StatusCode;
|
|||||||
use self::timed_permission::TimedPermission;
|
use self::timed_permission::TimedPermission;
|
||||||
#[cfg(feature = "with_ctap1")]
|
#[cfg(feature = "with_ctap1")]
|
||||||
use self::timed_permission::U2fUserPresenceState;
|
use self::timed_permission::U2fUserPresenceState;
|
||||||
|
use crate::api::customization::Customization;
|
||||||
use crate::api::firmware_protection::FirmwareProtection;
|
use crate::api::firmware_protection::FirmwareProtection;
|
||||||
use crate::api::upgrade_storage::UpgradeStorage;
|
use crate::api::upgrade_storage::UpgradeStorage;
|
||||||
use crate::clock::{ClockInt, CtapInstant};
|
use crate::clock::{ClockInt, CtapInstant};
|
||||||
@@ -1207,7 +1208,7 @@ impl CtapState {
|
|||||||
]),
|
]),
|
||||||
aaguid: storage::aaguid(env)?,
|
aaguid: storage::aaguid(env)?,
|
||||||
options: Some(options),
|
options: Some(options),
|
||||||
max_msg_size: Some(MAX_MSG_SIZE as u64),
|
max_msg_size: Some(env.customization().max_msg_size() as u64),
|
||||||
// The order implies preference. We favor the new V2.
|
// The order implies preference. We favor the new V2.
|
||||||
pin_protocols: Some(vec![
|
pin_protocols: Some(vec![
|
||||||
PinUvAuthProtocol::V2 as u64,
|
PinUvAuthProtocol::V2 as u64,
|
||||||
@@ -1519,7 +1520,7 @@ mod test {
|
|||||||
"setMinPINLength" => true,
|
"setMinPINLength" => true,
|
||||||
"makeCredUvNotRqd" => true,
|
"makeCredUvNotRqd" => true,
|
||||||
},
|
},
|
||||||
0x05 => MAX_MSG_SIZE as u64,
|
0x05 => env.customization().max_msg_size() as u64,
|
||||||
0x06 => cbor_array![2, 1],
|
0x06 => cbor_array![2, 1],
|
||||||
0x07 => MAX_CREDENTIAL_COUNT_IN_LIST.map(|c| c as u64),
|
0x07 => MAX_CREDENTIAL_COUNT_IN_LIST.map(|c| c as u64),
|
||||||
0x08 => CREDENTIAL_ID_SIZE as u64,
|
0x08 => CREDENTIAL_ID_SIZE as u64,
|
||||||
|
|||||||
4
src/env/mod.rs
vendored
4
src/env/mod.rs
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::api::customization::Customization;
|
||||||
use crate::api::firmware_protection::FirmwareProtection;
|
use crate::api::firmware_protection::FirmwareProtection;
|
||||||
use crate::api::upgrade_storage::UpgradeStorage;
|
use crate::api::upgrade_storage::UpgradeStorage;
|
||||||
use crate::ctap::status_code::Ctap2StatusCode;
|
use crate::ctap::status_code::Ctap2StatusCode;
|
||||||
@@ -24,6 +25,7 @@ pub trait Env {
|
|||||||
type UpgradeStorage: UpgradeStorage;
|
type UpgradeStorage: UpgradeStorage;
|
||||||
type FirmwareProtection: FirmwareProtection;
|
type FirmwareProtection: FirmwareProtection;
|
||||||
type Write: core::fmt::Write;
|
type Write: core::fmt::Write;
|
||||||
|
type Customization: Customization;
|
||||||
|
|
||||||
fn rng(&mut self) -> &mut Self::Rng;
|
fn rng(&mut self) -> &mut Self::Rng;
|
||||||
fn user_presence(&mut self) -> &mut Self::UserPresence;
|
fn user_presence(&mut self) -> &mut Self::UserPresence;
|
||||||
@@ -44,4 +46,6 @@ pub trait Env {
|
|||||||
/// using the defmt crate) and ignore this API. Non-embedded environments may either use this
|
/// using the defmt crate) and ignore this API. Non-embedded environments may either use this
|
||||||
/// API or use the log feature (to be implemented using the log crate).
|
/// API or use the log feature (to be implemented using the log crate).
|
||||||
fn write(&mut self) -> Self::Write;
|
fn write(&mut self) -> Self::Write;
|
||||||
|
|
||||||
|
fn customization(&self) -> &Self::Customization;
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/env/test/mod.rs
vendored
13
src/env/test/mod.rs
vendored
@@ -1,4 +1,5 @@
|
|||||||
use self::upgrade_storage::BufferUpgradeStorage;
|
use self::upgrade_storage::BufferUpgradeStorage;
|
||||||
|
use crate::api::customization::{CustomizationImpl, DEFAULT_CUSTOMIZATION};
|
||||||
use crate::api::firmware_protection::FirmwareProtection;
|
use crate::api::firmware_protection::FirmwareProtection;
|
||||||
use crate::ctap::status_code::Ctap2StatusCode;
|
use crate::ctap::status_code::Ctap2StatusCode;
|
||||||
use crate::ctap::Channel;
|
use crate::ctap::Channel;
|
||||||
@@ -13,6 +14,7 @@ pub struct TestEnv {
|
|||||||
user_presence: TestUserPresence,
|
user_presence: TestUserPresence,
|
||||||
store: Store<BufferStorage>,
|
store: Store<BufferStorage>,
|
||||||
upgrade_storage: Option<BufferUpgradeStorage>,
|
upgrade_storage: Option<BufferUpgradeStorage>,
|
||||||
|
customization: CustomizationImpl,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TestUserPresence {
|
pub struct TestUserPresence {
|
||||||
@@ -51,17 +53,23 @@ impl TestEnv {
|
|||||||
let storage = new_storage();
|
let storage = new_storage();
|
||||||
let store = Store::new(storage).ok().unwrap();
|
let store = Store::new(storage).ok().unwrap();
|
||||||
let upgrade_storage = Some(BufferUpgradeStorage::new().unwrap());
|
let upgrade_storage = Some(BufferUpgradeStorage::new().unwrap());
|
||||||
|
let customization = DEFAULT_CUSTOMIZATION.clone();
|
||||||
TestEnv {
|
TestEnv {
|
||||||
rng,
|
rng,
|
||||||
user_presence,
|
user_presence,
|
||||||
store,
|
store,
|
||||||
upgrade_storage,
|
upgrade_storage,
|
||||||
|
customization,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_upgrade_storage(&mut self) {
|
pub fn disable_upgrade_storage(&mut self) {
|
||||||
self.upgrade_storage = None;
|
self.upgrade_storage = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn customization_mut(&mut self) -> &mut CustomizationImpl {
|
||||||
|
&mut self.customization
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestUserPresence {
|
impl TestUserPresence {
|
||||||
@@ -89,6 +97,7 @@ impl Env for TestEnv {
|
|||||||
type UpgradeStorage = BufferUpgradeStorage;
|
type UpgradeStorage = BufferUpgradeStorage;
|
||||||
type FirmwareProtection = Self;
|
type FirmwareProtection = Self;
|
||||||
type Write = TestWrite;
|
type Write = TestWrite;
|
||||||
|
type Customization = CustomizationImpl;
|
||||||
|
|
||||||
fn rng(&mut self) -> &mut Self::Rng {
|
fn rng(&mut self) -> &mut Self::Rng {
|
||||||
&mut self.rng
|
&mut self.rng
|
||||||
@@ -113,4 +122,8 @@ impl Env for TestEnv {
|
|||||||
fn write(&mut self) -> Self::Write {
|
fn write(&mut self) -> Self::Write {
|
||||||
TestWrite
|
TestWrite
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn customization(&self) -> &Self::Customization {
|
||||||
|
&self.customization
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
src/env/tock/mod.rs
vendored
6
src/env/tock/mod.rs
vendored
@@ -1,4 +1,5 @@
|
|||||||
pub use self::storage::{TockStorage, TockUpgradeStorage};
|
pub use self::storage::{TockStorage, TockUpgradeStorage};
|
||||||
|
use crate::api::customization::{CustomizationImpl, DEFAULT_CUSTOMIZATION};
|
||||||
use crate::api::firmware_protection::FirmwareProtection;
|
use crate::api::firmware_protection::FirmwareProtection;
|
||||||
use crate::ctap::hid::{CtapHid, CtapHidCommand, KeepaliveStatus, ProcessedPacket};
|
use crate::ctap::hid::{CtapHid, CtapHidCommand, KeepaliveStatus, ProcessedPacket};
|
||||||
use crate::ctap::status_code::Ctap2StatusCode;
|
use crate::ctap::status_code::Ctap2StatusCode;
|
||||||
@@ -80,6 +81,7 @@ impl Env for TockEnv {
|
|||||||
type UpgradeStorage = TockUpgradeStorage;
|
type UpgradeStorage = TockUpgradeStorage;
|
||||||
type FirmwareProtection = Self;
|
type FirmwareProtection = Self;
|
||||||
type Write = Console;
|
type Write = Console;
|
||||||
|
type Customization = CustomizationImpl;
|
||||||
|
|
||||||
fn rng(&mut self) -> &mut Self::Rng {
|
fn rng(&mut self) -> &mut Self::Rng {
|
||||||
&mut self.rng
|
&mut self.rng
|
||||||
@@ -104,6 +106,10 @@ impl Env for TockEnv {
|
|||||||
fn write(&mut self) -> Self::Write {
|
fn write(&mut self) -> Self::Write {
|
||||||
Console::new()
|
Console::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn customization(&self) -> &Self::Customization {
|
||||||
|
&DEFAULT_CUSTOMIZATION
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns whether the keepalive was sent, or false if cancelled.
|
// Returns whether the keepalive was sent, or false if cancelled.
|
||||||
|
|||||||
@@ -88,6 +88,11 @@ impl<E: Env> Ctap<E> {
|
|||||||
&mut self.hid
|
&mut self.hid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub fn env(&mut self) -> &mut E {
|
||||||
|
&mut self.env
|
||||||
|
}
|
||||||
|
|
||||||
pub fn process_hid_packet(
|
pub fn process_hid_packet(
|
||||||
&mut self,
|
&mut self,
|
||||||
packet: &HidPacket,
|
packet: &HidPacket,
|
||||||
|
|||||||
Reference in New Issue
Block a user