fido_authenticator/dispatch/
apdu.rs1use apdu_app::Interface;
2use ctap_types::{serde::error::Error as SerdeError, Error};
3use heapless::VecView;
4use iso7816::{command::CommandView, Status};
5
6use crate::{Authenticator, TrussedRequirements, UserPresence};
7
8pub enum CtapMappingError {
9 InvalidCommand(u8),
10 ParsingError(SerdeError),
11}
12
13impl From<CtapMappingError> for Error {
14 fn from(mapping_error: CtapMappingError) -> Error {
15 match mapping_error {
16 CtapMappingError::InvalidCommand(_cmd) => Error::InvalidCommand,
17 CtapMappingError::ParsingError(cbor_error) => match cbor_error {
18 SerdeError::SerdeMissingField => Error::MissingParameter,
19 _ => Error::InvalidCbor,
20 },
21 }
22 }
23}
24
25impl<UP, T> apdu_app::App for Authenticator<UP, T>
26where
27 UP: UserPresence,
28 T: TrussedRequirements,
29{
30 fn select(
31 &mut self,
32 interface: Interface,
33 _: CommandView<'_>,
34 reply: &mut VecView<u8>,
35 ) -> apdu_app::Result {
36 if interface != Interface::Contactless {
39 return Err(Status::ConditionsOfUseNotSatisfied);
40 }
41
42 reply.extend_from_slice(b"U2F_V2").unwrap();
43 Ok(())
44 }
45
46 fn deselect(&mut self) {}
47
48 fn call(
49 &mut self,
50 interface: Interface,
51 apdu: CommandView<'_>,
52 response: &mut VecView<u8>,
53 ) -> apdu_app::Result {
54 if interface != Interface::Contactless {
57 return Err(Status::ConditionsOfUseNotSatisfied);
58 }
59
60 let instruction: u8 = apdu.instruction().into();
61
62 match instruction {
70 0x00..=0x02 => super::try_handle_ctap1(self, apdu, response)?, _ => {
75 match ctaphid_app::Command::try_from(instruction) {
76 Ok(ctaphid_app::Command::Cbor) => {
78 super::handle_ctap2(self, apdu.data(), response)
79 }
80 Ok(ctaphid_app::Command::Msg) => super::try_handle_ctap1(self, apdu, response)?,
81 Ok(ctaphid_app::Command::Deselect) => apdu_app::App::deselect(self),
82 _ => {
83 info!("Unsupported ins for fido app {:02x}", instruction);
84 return Err(iso7816::Status::InstructionNotSupportedOrInvalid);
85 }
86 }
87 }
88 };
89 Ok(())
90 }
91}