Add write to the environment

This commit is contained in:
Julien Cretin
2022-03-04 15:09:44 +01:00
parent dcc053c6cb
commit f09e5a77e8
6 changed files with 152 additions and 88 deletions

View File

@@ -26,10 +26,6 @@ use crate::env::Env;
use alloc::vec;
use alloc::vec::Vec;
use arrayref::{array_ref, array_refs};
#[cfg(feature = "debug_ctap")]
use core::fmt::Write;
#[cfg(feature = "debug_ctap")]
use libtock_drivers::console::Console;
use libtock_drivers::timer::{ClockValue, Duration, Timestamp};
// CTAP specification (version 20190130) section 8.1
@@ -159,14 +155,12 @@ impl CtapHid {
.parse_packet(packet, Timestamp::<isize>::from_clock_value(clock_value))
{
Ok(Some(message)) => {
#[cfg(feature = "debug_ctap")]
writeln!(&mut Console::new(), "Received message: {:02x?}", message).unwrap();
debug_ctap!(env, "Received message: {:02x?}", message);
let cid = message.cid;
if !self.has_valid_channel(&message) {
#[cfg(feature = "debug_ctap")]
writeln!(&mut Console::new(), "Invalid channel: {:02x?}", cid).unwrap();
return CtapHid::error_message(cid, CtapHid::ERR_INVALID_CHANNEL);
debug_ctap!(env, "Invalid channel: {:02x?}", cid);
return CtapHid::error_message(env, cid, CtapHid::ERR_INVALID_CHANNEL);
}
// If another command arrives, stop winking to prevent accidential button touches.
self.wink_permission = TimedPermission::waiting();
@@ -176,7 +170,7 @@ impl CtapHid {
CtapHid::COMMAND_MSG => {
// If we don't have CTAP1 backward compatibilty, this command is invalid.
#[cfg(not(feature = "with_ctap1"))]
return CtapHid::error_message(cid, CtapHid::ERR_INVALID_CMD);
return CtapHid::error_message(env, cid, CtapHid::ERR_INVALID_CMD);
#[cfg(feature = "with_ctap1")]
match ctap1::Ctap1Command::process_command(
@@ -185,9 +179,9 @@ impl CtapHid {
ctap_state,
clock_value,
) {
Ok(payload) => CtapHid::ctap1_success_message(cid, &payload),
Ok(payload) => CtapHid::ctap1_success_message(env, cid, &payload),
Err(ctap1_status_code) => {
CtapHid::ctap1_error_message(cid, ctap1_status_code)
CtapHid::ctap1_error_message(env, cid, ctap1_status_code)
}
}
}
@@ -199,11 +193,14 @@ impl CtapHid {
// TODO: Send keep-alive packets in the meantime.
let response =
ctap_state.process_command(env, &message.payload, cid, clock_value);
if let Some(iterator) = CtapHid::split_message(Message {
cid,
cmd: CtapHid::COMMAND_CBOR,
payload: response,
}) {
if let Some(iterator) = CtapHid::split_message(
env,
Message {
cid,
cmd: CtapHid::COMMAND_CBOR,
payload: response,
},
) {
iterator
} else {
// Handle the case of a payload > 7609 bytes.
@@ -213,20 +210,23 @@ impl CtapHid {
//
// The error payload that we send instead is 1 <= 7609 bytes, so it is
// safe to unwrap() the result.
CtapHid::split_message(Message {
cid,
cmd: CtapHid::COMMAND_CBOR,
payload: vec![
Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR as u8,
],
})
CtapHid::split_message(
env,
Message {
cid,
cmd: CtapHid::COMMAND_CBOR,
payload: vec![
Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR as u8,
],
},
)
.unwrap()
}
}
// CTAP specification (version 20190130) section 8.1.9.1.3
CtapHid::COMMAND_INIT => {
if message.payload.len() != 8 {
return CtapHid::error_message(cid, CtapHid::ERR_INVALID_LEN);
return CtapHid::error_message(env, cid, CtapHid::ERR_INVALID_LEN);
}
let new_cid = if cid == CtapHid::CHANNEL_BROADCAST {
@@ -248,11 +248,14 @@ impl CtapHid {
payload[16] = CtapHid::CAPABILITIES;
// This unwrap is safe because the payload length is 17 <= 7609 bytes.
CtapHid::split_message(Message {
cid,
cmd: CtapHid::COMMAND_INIT,
payload,
})
CtapHid::split_message(
env,
Message {
cid,
cmd: CtapHid::COMMAND_INIT,
payload,
},
)
.unwrap()
}
// CTAP specification (version 20190130) section 8.1.9.1.4
@@ -260,7 +263,7 @@ impl CtapHid {
// Pong the same message.
// This unwrap is safe because if we could parse the incoming message, it's
// payload length must be <= 7609 bytes.
CtapHid::split_message(message).unwrap()
CtapHid::split_message(env, message).unwrap()
}
// CTAP specification (version 20190130) section 8.1.9.1.5
CtapHid::COMMAND_CANCEL => {
@@ -272,22 +275,25 @@ impl CtapHid {
// CTAP specification (version 20190130) section 8.1.9.2.1
CtapHid::COMMAND_WINK => {
if !message.payload.is_empty() {
return CtapHid::error_message(cid, CtapHid::ERR_INVALID_LEN);
return CtapHid::error_message(env, cid, CtapHid::ERR_INVALID_LEN);
}
self.wink_permission =
TimedPermission::granted(clock_value, CtapHid::WINK_TIMEOUT_DURATION);
CtapHid::split_message(Message {
cid,
cmd: CtapHid::COMMAND_WINK,
payload: vec![],
})
CtapHid::split_message(
env,
Message {
cid,
cmd: CtapHid::COMMAND_WINK,
payload: vec![],
},
)
.unwrap()
}
// CTAP specification (version 20190130) section 8.1.9.2.2
// TODO: implement LOCK
_ => {
// Unknown or unsupported command.
CtapHid::error_message(cid, CtapHid::ERR_INVALID_CMD)
CtapHid::error_message(env, cid, CtapHid::ERR_INVALID_CMD)
}
}
}
@@ -299,18 +305,18 @@ impl CtapHid {
if !self.is_allocated_channel(cid)
&& error != receive::Error::UnexpectedContinuation
{
CtapHid::error_message(cid, CtapHid::ERR_INVALID_CHANNEL)
CtapHid::error_message(env, cid, CtapHid::ERR_INVALID_CHANNEL)
} else {
match error {
receive::Error::UnexpectedChannel => {
CtapHid::error_message(cid, CtapHid::ERR_CHANNEL_BUSY)
CtapHid::error_message(env, cid, CtapHid::ERR_CHANNEL_BUSY)
}
receive::Error::UnexpectedInit => {
// TODO: Should we send another error code in this case?
// Technically, we were expecting a sequence number and got another
// byte, although the command/seqnum bit has higher-level semantics
// than sequence numbers.
CtapHid::error_message(cid, CtapHid::ERR_INVALID_SEQ)
CtapHid::error_message(env, cid, CtapHid::ERR_INVALID_SEQ)
}
receive::Error::UnexpectedContinuation => {
// CTAP specification (version 20190130) section 8.1.5.4
@@ -318,13 +324,13 @@ impl CtapHid {
HidPacketIterator::none()
}
receive::Error::UnexpectedSeq => {
CtapHid::error_message(cid, CtapHid::ERR_INVALID_SEQ)
CtapHid::error_message(env, cid, CtapHid::ERR_INVALID_SEQ)
}
receive::Error::UnexpectedLen => {
CtapHid::error_message(cid, CtapHid::ERR_INVALID_LEN)
CtapHid::error_message(env, cid, CtapHid::ERR_INVALID_LEN)
}
receive::Error::Timeout => {
CtapHid::error_message(cid, CtapHid::ERR_MSG_TIMEOUT)
CtapHid::error_message(env, cid, CtapHid::ERR_MSG_TIMEOUT)
}
}
}
@@ -345,13 +351,16 @@ impl CtapHid {
cid != CtapHid::CHANNEL_RESERVED && u32::from_be_bytes(cid) as usize <= self.allocated_cids
}
fn error_message(cid: ChannelID, error_code: u8) -> HidPacketIterator {
fn error_message<E: Env>(env: &mut E, cid: ChannelID, error_code: u8) -> HidPacketIterator {
// This unwrap is safe because the payload length is 1 <= 7609 bytes.
CtapHid::split_message(Message {
cid,
cmd: CtapHid::COMMAND_ERROR,
payload: vec![error_code],
})
CtapHid::split_message(
env,
Message {
cid,
cmd: CtapHid::COMMAND_ERROR,
payload: vec![error_code],
},
)
.unwrap()
}
@@ -379,23 +388,29 @@ impl CtapHid {
}
}
fn split_message(message: Message) -> Option<HidPacketIterator> {
#[cfg(feature = "debug_ctap")]
writeln!(&mut Console::new(), "Sending message: {:02x?}", message).unwrap();
fn split_message<E: Env>(env: &mut E, message: Message) -> Option<HidPacketIterator> {
debug_ctap!(env, "Sending message: {:02x?}", message);
HidPacketIterator::new(message)
}
pub fn keepalive(cid: ChannelID, status: KeepaliveStatus) -> HidPacketIterator {
pub fn keepalive<E: Env>(
env: &mut E,
cid: ChannelID,
status: KeepaliveStatus,
) -> HidPacketIterator {
let status_code = match status {
KeepaliveStatus::Processing => 1,
KeepaliveStatus::UpNeeded => 2,
};
// This unwrap is safe because the payload length is 1 <= 7609 bytes.
CtapHid::split_message(Message {
cid,
cmd: CtapHid::COMMAND_KEEPALIVE,
payload: vec![status_code],
})
CtapHid::split_message(
env,
Message {
cid,
cmd: CtapHid::COMMAND_KEEPALIVE,
payload: vec![status_code],
},
)
.unwrap()
}
@@ -404,30 +419,41 @@ impl CtapHid {
}
#[cfg(feature = "with_ctap1")]
fn ctap1_error_message(
fn ctap1_error_message<E: Env>(
env: &mut E,
cid: ChannelID,
error_code: ctap1::Ctap1StatusCode,
) -> HidPacketIterator {
// This unwrap is safe because the payload length is 2 <= 7609 bytes
let code: u16 = error_code.into();
CtapHid::split_message(Message {
cid,
cmd: CtapHid::COMMAND_MSG,
payload: code.to_be_bytes().to_vec(),
})
CtapHid::split_message(
env,
Message {
cid,
cmd: CtapHid::COMMAND_MSG,
payload: code.to_be_bytes().to_vec(),
},
)
.unwrap()
}
#[cfg(feature = "with_ctap1")]
fn ctap1_success_message(cid: ChannelID, payload: &[u8]) -> HidPacketIterator {
fn ctap1_success_message<E: Env>(
env: &mut E,
cid: ChannelID,
payload: &[u8],
) -> HidPacketIterator {
let mut response = payload.to_vec();
let code: u16 = ctap1::Ctap1StatusCode::SW_SUCCESS.into();
response.extend_from_slice(&code.to_be_bytes());
CtapHid::split_message(Message {
cid,
cmd: CtapHid::COMMAND_MSG,
payload: response,
})
CtapHid::split_message(
env,
Message {
cid,
cmd: CtapHid::COMMAND_MSG,
payload: response,
},
)
.unwrap()
}
}

View File

@@ -74,15 +74,11 @@ use alloc::vec::Vec;
use arrayref::array_ref;
use byteorder::{BigEndian, ByteOrder};
use core::convert::TryFrom;
#[cfg(feature = "debug_ctap")]
use core::fmt::Write;
use crypto::ecdsa;
use crypto::hmac::{hmac_256, verify_hmac_256};
use crypto::rng256::Rng256;
use crypto::sha256::Sha256;
use crypto::Hash256;
#[cfg(feature = "debug_ctap")]
use libtock_drivers::console::Console;
use libtock_drivers::timer::{ClockValue, Duration};
use sk_cbor as cbor;
use sk_cbor::cbor_map_options;
@@ -461,8 +457,7 @@ impl<E: Env> CtapState<E> {
now: ClockValue,
) -> Vec<u8> {
let cmd = Command::deserialize(command_cbor);
#[cfg(feature = "debug_ctap")]
writeln!(&mut Console::new(), "Received command: {:#?}", cmd).unwrap();
debug_ctap!(env, "Received command: {:#?}", cmd);
match cmd {
Ok(command) => {
// Correct behavior between CTAP1 and CTAP2 isn't defined yet. Just a guess.
@@ -536,8 +531,7 @@ impl<E: Env> CtapState<E> {
}
Command::AuthenticatorVendorUpgradeInfo => self.process_vendor_upgrade_info(),
};
#[cfg(feature = "debug_ctap")]
writeln!(&mut Console::new(), "Sending response: {:#?}", response).unwrap();
debug_ctap!(env, "Sending response: {:#?}", response);
match response {
Ok(response_data) => {
let mut response_vec = vec![0x00];