From c3f57f01215a02c2e4d153d5af8975fae7a7860c Mon Sep 17 00:00:00 2001 From: Fabian Kaczmarczyck Date: Tue, 9 Jun 2020 12:07:00 +0200 Subject: [PATCH] implements the AuthenticatorSelection command --- src/ctap/command.rs | 15 +++++++++++++++ src/ctap/mod.rs | 14 +++++++++++++- src/ctap/response.rs | 11 +++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/ctap/command.rs b/src/ctap/command.rs index d6dd0fa..ba44147 100644 --- a/src/ctap/command.rs +++ b/src/ctap/command.rs @@ -37,6 +37,8 @@ pub enum Command { AuthenticatorClientPin(AuthenticatorClientPinParameters), AuthenticatorReset, AuthenticatorGetNextAssertion, + #[cfg(feature = "with_ctap2_1")] + AuthenticatorSelection, // TODO(kaczmarczyck) implement FIDO 2.1 commands (see below consts) } @@ -101,6 +103,11 @@ impl Command { // Parameters are ignored. Ok(Command::AuthenticatorGetNextAssertion) } + #[cfg(feature = "with_ctap2_1")] + Command::AUTHENTICATOR_SELECTION => { + // Parameters are ignored. + Ok(Command::AuthenticatorSelection) + } _ => Err(Ctap2StatusCode::CTAP1_ERR_INVALID_COMMAND), } } @@ -484,4 +491,12 @@ mod test { let command = Command::deserialize(&cbor_bytes); assert_eq!(command, Ok(Command::AuthenticatorGetNextAssertion)); } + + #[cfg(feature = "with_ctap2_1")] + #[test] + fn test_deserialize_selection() { + let cbor_bytes = [Command::AUTHENTICATOR_SELECTION]; + let command = Command::deserialize(&cbor_bytes); + assert_eq!(command, Ok(Command::AuthenticatorSelection)); + } } diff --git a/src/ctap/mod.rs b/src/ctap/mod.rs index a52798b..d554994 100644 --- a/src/ctap/mod.rs +++ b/src/ctap/mod.rs @@ -368,8 +368,10 @@ where Command::AuthenticatorGetInfo => self.process_get_info(), Command::AuthenticatorClientPin(params) => self.process_client_pin(params), Command::AuthenticatorReset => self.process_reset(cid), + #[cfg(feature = "with_ctap2_1")] + Command::AuthenticatorSelection => self.process_selection(cid), // TODO(kaczmarczyck) implement GetNextAssertion and FIDO 2.1 commands - _ => unimplemented!(), + _ => self.process_unknown_command(), }; #[cfg(feature = "debug_ctap")] writeln!(&mut Console::new(), "Sending response: {:#?}", response).unwrap(); @@ -1094,6 +1096,16 @@ where Ok(ResponseData::AuthenticatorReset) } + #[cfg(feature = "with_ctap2_1")] + fn process_selection(&self, cid: ChannelID) -> Result { + (self.check_user_presence)(cid)?; + Ok(ResponseData::AuthenticatorSelection) + } + + fn process_unknown_command(&self) -> Result { + Err(Ctap2StatusCode::CTAP1_ERR_INVALID_COMMAND) + } + pub fn generate_auth_data(&self, rp_id_hash: &[u8], flag_byte: u8) -> Vec { let mut auth_data = vec![]; auth_data.extend(rp_id_hash); diff --git a/src/ctap/response.rs b/src/ctap/response.rs index 2a33a6d..0a4548d 100644 --- a/src/ctap/response.rs +++ b/src/ctap/response.rs @@ -31,6 +31,8 @@ pub enum ResponseData { AuthenticatorGetInfo(AuthenticatorGetInfoResponse), AuthenticatorClientPin(Option), AuthenticatorReset, + #[cfg(feature = "with_ctap2_1")] + AuthenticatorSelection, } impl From for Option { @@ -43,6 +45,8 @@ impl From for Option { ResponseData::AuthenticatorClientPin(Some(data)) => Some(data.into()), ResponseData::AuthenticatorClientPin(None) => None, ResponseData::AuthenticatorReset => None, + #[cfg(feature = "with_ctap2_1")] + ResponseData::AuthenticatorSelection => None, } } } @@ -372,4 +376,11 @@ mod test { let response_cbor: Option = ResponseData::AuthenticatorReset.into(); assert_eq!(response_cbor, None); } + + #[cfg(feature = "with_ctap2_1")] + #[test] + fn test_selection_into_cbor() { + let response_cbor: Option = ResponseData::AuthenticatorSelection.into(); + assert_eq!(response_cbor, None); + } }