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