diff --git a/reproducible/binaries.sha256sum b/reproducible/binaries.sha256sum deleted file mode 100644 index 6858153..0000000 --- a/reproducible/binaries.sha256sum +++ /dev/null @@ -1,9 +0,0 @@ -c182bb4902fff51b2f56810fc2a27df3646cd66ba21359162354d53445623ab8 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -2c2879a0263ebaa6e841db4b352346cc5b4cef5084ce85525cf49669d3b0b41d target/nrf52840dk_merged.hex -0a9929ba8fa57e8a502a49fc7c53177397202e1b11f4c7c3cb6ed68b2b99dd46 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -652824a90674dc3199070f2f46a791ab4951e367982ecae6f65fc41338a5a856 target/nrf52840_dongle_merged.hex -cca9086c9149c607589b23ffa599a5e4c26db7c20bd3700b79528bd3a5df991d third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -a030505f5576129954a3977f97957b8b4e023b2b51a29d45d4511566458666ac target/nrf52840_dongle_dfu_merged.hex -8857488ba6a69e366f0da229bbfc012a2ad291d3a88d9494247d600c10bb19b7 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -82ac4290967ae67a78c986444fd6c2a2aa5668ac254a2af642c98be4a064f913 target/nrf52840_mdk_dfu_merged.hex -c3e901a80fd779b15a6f266e48dcef5140b318f5f62b23a96547498572ac1666 target/tab/ctap2.tab diff --git a/reproducible/reproduced.tar b/reproducible/reproduced.tar deleted file mode 100644 index 96616b5..0000000 Binary files a/reproducible/reproduced.tar and /dev/null differ diff --git a/src/ctap/command.rs b/src/ctap/command.rs index 19132bc..21ac767 100644 --- a/src/ctap/command.rs +++ b/src/ctap/command.rs @@ -13,10 +13,10 @@ // limitations under the License. use super::data_formats::{ - ok_or_missing, read_array, read_byte_string, read_map, read_text_string, read_unsigned, - ClientPinSubCommand, CoseKey, Extensions, GetAssertionOptions, MakeCredentialOptions, - PublicKeyCredentialDescriptor, PublicKeyCredentialParameter, PublicKeyCredentialRpEntity, - PublicKeyCredentialUserEntity, + extract_array, extract_byte_string, extract_map, extract_text_string, extract_unsigned, + ok_or_missing, ClientPinSubCommand, CoseKey, Extensions, GetAssertionOptions, + MakeCredentialOptions, PublicKeyCredentialDescriptor, PublicKeyCredentialParameter, + PublicKeyCredentialRpEntity, PublicKeyCredentialUserEntity, }; use super::status_code::Ctap2StatusCode; use alloc::string::String; @@ -124,30 +124,32 @@ impl TryFrom for AuthenticatorMakeCredentialParameters { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let param_map = read_map(&cbor_value)?; + let mut param_map = extract_map(cbor_value)?; - let client_data_hash = read_byte_string(ok_or_missing(param_map.get(&cbor_unsigned!(1)))?)?; + let client_data_hash = + extract_byte_string(ok_or_missing(param_map.remove(&cbor_unsigned!(1)))?)?; let rp = PublicKeyCredentialRpEntity::try_from(ok_or_missing( - param_map.get(&cbor_unsigned!(2)), + param_map.remove(&cbor_unsigned!(2)), )?)?; let user = PublicKeyCredentialUserEntity::try_from(ok_or_missing( - param_map.get(&cbor_unsigned!(3)), + param_map.remove(&cbor_unsigned!(3)), )?)?; - let cred_param_vec = read_array(ok_or_missing(param_map.get(&cbor_unsigned!(4)))?)?; + let cred_param_vec = extract_array(ok_or_missing(param_map.remove(&cbor_unsigned!(4)))?)?; let pub_key_cred_params = cred_param_vec - .iter() + .into_iter() .map(PublicKeyCredentialParameter::try_from) .collect::, Ctap2StatusCode>>()?; - let exclude_list = match param_map.get(&cbor_unsigned!(5)) { + let exclude_list = match param_map.remove(&cbor_unsigned!(5)) { Some(entry) => { - let exclude_list_vec = read_array(entry)?; + let exclude_list_vec = extract_array(entry)?; + let list_len = MAX_CREDENTIAL_COUNT_IN_LIST.unwrap_or(exclude_list_vec.len()); let exclude_list = exclude_list_vec - .iter() - .take(MAX_CREDENTIAL_COUNT_IN_LIST.unwrap_or(exclude_list_vec.len())) + .into_iter() + .take(list_len) .map(PublicKeyCredentialDescriptor::try_from) .collect::, Ctap2StatusCode>>()?; Some(exclude_list) @@ -156,11 +158,11 @@ impl TryFrom for AuthenticatorMakeCredentialParameters { }; let extensions = param_map - .get(&cbor_unsigned!(6)) + .remove(&cbor_unsigned!(6)) .map(Extensions::try_from) .transpose()?; - let options = match param_map.get(&cbor_unsigned!(7)) { + let options = match param_map.remove(&cbor_unsigned!(7)) { Some(entry) => MakeCredentialOptions::try_from(entry)?, None => MakeCredentialOptions { rk: false, @@ -169,13 +171,13 @@ impl TryFrom for AuthenticatorMakeCredentialParameters { }; let pin_uv_auth_param = param_map - .get(&cbor_unsigned!(8)) - .map(read_byte_string) + .remove(&cbor_unsigned!(8)) + .map(extract_byte_string) .transpose()?; let pin_uv_auth_protocol = param_map - .get(&cbor_unsigned!(9)) - .map(read_unsigned) + .remove(&cbor_unsigned!(9)) + .map(extract_unsigned) .transpose()?; Ok(AuthenticatorMakeCredentialParameters { @@ -208,18 +210,20 @@ impl TryFrom for AuthenticatorGetAssertionParameters { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let param_map = read_map(&cbor_value)?; + let mut param_map = extract_map(cbor_value)?; - let rp_id = read_text_string(ok_or_missing(param_map.get(&cbor_unsigned!(1)))?)?; + let rp_id = extract_text_string(ok_or_missing(param_map.remove(&cbor_unsigned!(1)))?)?; - let client_data_hash = read_byte_string(ok_or_missing(param_map.get(&cbor_unsigned!(2)))?)?; + let client_data_hash = + extract_byte_string(ok_or_missing(param_map.remove(&cbor_unsigned!(2)))?)?; - let allow_list = match param_map.get(&cbor_unsigned!(3)) { + let allow_list = match param_map.remove(&cbor_unsigned!(3)) { Some(entry) => { - let allow_list_vec = read_array(entry)?; + let allow_list_vec = extract_array(entry)?; + let list_len = MAX_CREDENTIAL_COUNT_IN_LIST.unwrap_or(allow_list_vec.len()); let allow_list = allow_list_vec - .iter() - .take(MAX_CREDENTIAL_COUNT_IN_LIST.unwrap_or(allow_list_vec.len())) + .into_iter() + .take(list_len) .map(PublicKeyCredentialDescriptor::try_from) .collect::, Ctap2StatusCode>>()?; Some(allow_list) @@ -228,11 +232,11 @@ impl TryFrom for AuthenticatorGetAssertionParameters { }; let extensions = param_map - .get(&cbor_unsigned!(4)) + .remove(&cbor_unsigned!(4)) .map(Extensions::try_from) .transpose()?; - let options = match param_map.get(&cbor_unsigned!(5)) { + let options = match param_map.remove(&cbor_unsigned!(5)) { Some(entry) => GetAssertionOptions::try_from(entry)?, None => GetAssertionOptions { up: true, @@ -241,13 +245,13 @@ impl TryFrom for AuthenticatorGetAssertionParameters { }; let pin_uv_auth_param = param_map - .get(&cbor_unsigned!(6)) - .map(read_byte_string) + .remove(&cbor_unsigned!(6)) + .map(extract_byte_string) .transpose()?; let pin_uv_auth_protocol = param_map - .get(&cbor_unsigned!(7)) - .map(read_unsigned) + .remove(&cbor_unsigned!(7)) + .map(extract_unsigned) .transpose()?; Ok(AuthenticatorGetAssertionParameters { @@ -276,32 +280,32 @@ impl TryFrom for AuthenticatorClientPinParameters { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let param_map = read_map(&cbor_value)?; + let mut param_map = extract_map(cbor_value)?; - let pin_protocol = read_unsigned(ok_or_missing(param_map.get(&cbor_unsigned!(1)))?)?; + let pin_protocol = extract_unsigned(ok_or_missing(param_map.remove(&cbor_unsigned!(1)))?)?; let sub_command = - ClientPinSubCommand::try_from(ok_or_missing(param_map.get(&cbor_unsigned!(2)))?)?; + ClientPinSubCommand::try_from(ok_or_missing(param_map.remove(&cbor_unsigned!(2)))?)?; let key_agreement = param_map - .get(&cbor_unsigned!(3)) - .map(read_map) + .remove(&cbor_unsigned!(3)) + .map(extract_map) .transpose()? - .map(|x| CoseKey(x.clone())); + .map(|x| CoseKey(x)); let pin_auth = param_map - .get(&cbor_unsigned!(4)) - .map(read_byte_string) + .remove(&cbor_unsigned!(4)) + .map(extract_byte_string) .transpose()?; let new_pin_enc = param_map - .get(&cbor_unsigned!(5)) - .map(read_byte_string) + .remove(&cbor_unsigned!(5)) + .map(extract_byte_string) .transpose()?; let pin_hash_enc = param_map - .get(&cbor_unsigned!(6)) - .map(read_byte_string) + .remove(&cbor_unsigned!(6)) + .map(extract_byte_string) .transpose()?; Ok(AuthenticatorClientPinParameters { diff --git a/src/ctap/data_formats.rs b/src/ctap/data_formats.rs index d226fca..e838c2c 100644 --- a/src/ctap/data_formats.rs +++ b/src/ctap/data_formats.rs @@ -27,19 +27,19 @@ pub struct PublicKeyCredentialRpEntity { pub rp_icon: Option, } -impl TryFrom<&cbor::Value> for PublicKeyCredentialRpEntity { +impl TryFrom for PublicKeyCredentialRpEntity { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { - let rp_map = read_map(cbor_value)?; - let rp_id = read_text_string(ok_or_missing(rp_map.get(&cbor_text!("id")))?)?; + fn try_from(cbor_value: cbor::Value) -> Result { + let mut rp_map = extract_map(cbor_value)?; + let rp_id = extract_text_string(ok_or_missing(rp_map.remove(&cbor_text!("id")))?)?; let rp_name = rp_map - .get(&cbor_text!("name")) - .map(read_text_string) + .remove(&cbor_text!("name")) + .map(extract_text_string) .transpose()?; let rp_icon = rp_map - .get(&cbor_text!("icon")) - .map(read_text_string) + .remove(&cbor_text!("icon")) + .map(extract_text_string) .transpose()?; Ok(Self { rp_id, @@ -58,23 +58,23 @@ pub struct PublicKeyCredentialUserEntity { pub user_icon: Option, } -impl TryFrom<&cbor::Value> for PublicKeyCredentialUserEntity { +impl TryFrom for PublicKeyCredentialUserEntity { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { - let user_map = read_map(cbor_value)?; - let user_id = read_byte_string(ok_or_missing(user_map.get(&cbor_text!("id")))?)?; + fn try_from(cbor_value: cbor::Value) -> Result { + let mut user_map = extract_map(cbor_value)?; + let user_id = extract_byte_string(ok_or_missing(user_map.remove(&cbor_text!("id")))?)?; let user_name = user_map - .get(&cbor_text!("name")) - .map(read_text_string) + .remove(&cbor_text!("name")) + .map(extract_text_string) .transpose()?; let user_display_name = user_map - .get(&cbor_text!("displayName")) - .map(read_text_string) + .remove(&cbor_text!("displayName")) + .map(extract_text_string) .transpose()?; let user_icon = user_map - .get(&cbor_text!("icon")) - .map(read_text_string) + .remove(&cbor_text!("icon")) + .map(extract_text_string) .transpose()?; Ok(Self { user_id, @@ -117,11 +117,11 @@ impl From for cbor::Value { } } -impl TryFrom<&cbor::Value> for PublicKeyCredentialType { +impl TryFrom for PublicKeyCredentialType { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { - let cred_type_string = read_text_string(cbor_value)?; + fn try_from(cbor_value: cbor::Value) -> Result { + let cred_type_string = extract_text_string(cbor_value)?; match &cred_type_string[..] { "public-key" => Ok(PublicKeyCredentialType::PublicKey), _ => Ok(PublicKeyCredentialType::Unknown), @@ -137,16 +137,17 @@ pub struct PublicKeyCredentialParameter { pub alg: SignatureAlgorithm, } -impl TryFrom<&cbor::Value> for PublicKeyCredentialParameter { +impl TryFrom for PublicKeyCredentialParameter { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { - let cred_param_map = read_map(cbor_value)?; + fn try_from(cbor_value: cbor::Value) -> Result { + let mut cred_param_map = extract_map(cbor_value)?; let cred_type = PublicKeyCredentialType::try_from(ok_or_missing( - cred_param_map.get(&cbor_text!("type")), + cred_param_map.remove(&cbor_text!("type")), + )?)?; + let alg = SignatureAlgorithm::try_from(ok_or_missing( + cred_param_map.remove(&cbor_text!("alg")), )?)?; - let alg = - SignatureAlgorithm::try_from(ok_or_missing(cred_param_map.get(&cbor_text!("alg")))?)?; Ok(Self { cred_type, alg }) } } @@ -181,11 +182,11 @@ impl From for cbor::Value { } } -impl TryFrom<&cbor::Value> for AuthenticatorTransport { +impl TryFrom for AuthenticatorTransport { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { - let transport_string = read_text_string(cbor_value)?; + fn try_from(cbor_value: cbor::Value) -> Result { + let transport_string = extract_text_string(cbor_value)?; match &transport_string[..] { "usb" => Ok(AuthenticatorTransport::Usb), "nfc" => Ok(AuthenticatorTransport::Nfc), @@ -204,23 +205,22 @@ pub struct PublicKeyCredentialDescriptor { pub transports: Option>, } -impl TryFrom<&cbor::Value> for PublicKeyCredentialDescriptor { +impl TryFrom for PublicKeyCredentialDescriptor { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { - let cred_desc_map = read_map(cbor_value)?; + fn try_from(cbor_value: cbor::Value) -> Result { + let mut cred_desc_map = extract_map(cbor_value)?; let key_type = PublicKeyCredentialType::try_from(ok_or_missing( - cred_desc_map.get(&cbor_text!("type")), + cred_desc_map.remove(&cbor_text!("type")), )?)?; - let key_id = read_byte_string(ok_or_missing(cred_desc_map.get(&cbor_text!("id")))?)?; - let transports = match cred_desc_map.get(&cbor_text!("transports")) { + let key_id = extract_byte_string(ok_or_missing(cred_desc_map.remove(&cbor_text!("id")))?)?; + let transports = match cred_desc_map.remove(&cbor_text!("transports")) { Some(exclude_entry) => { - let transport_vec = read_array(exclude_entry)?; + let transport_vec = extract_array(exclude_entry)?; let transports = transport_vec - .iter() + .into_iter() .map(AuthenticatorTransport::try_from) - .collect::, Ctap2StatusCode>>( - )?; + .collect::, Ctap2StatusCode>>()?; Some(transports) } None => None, @@ -246,12 +246,12 @@ impl From for cbor::Value { #[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] pub struct Extensions(BTreeMap); -impl TryFrom<&cbor::Value> for Extensions { +impl TryFrom for Extensions { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { + fn try_from(cbor_value: cbor::Value) -> Result { let mut extensions = BTreeMap::new(); - for (extension_key, extension_value) in read_map(cbor_value)? { + for (extension_key, extension_value) in extract_map(cbor_value)? { if let cbor::KeyType::TextString(extension_key_string) = extension_key { extensions.insert(extension_key_string.to_string(), extension_value.clone()); } else { @@ -281,23 +281,23 @@ impl Extensions { pub fn has_make_credential_hmac_secret(&self) -> Result { self.0 .get("hmac-secret") - .map(read_bool) + .map(|b| extract_bool(b.clone())) .unwrap_or(Ok(false)) } pub fn get_assertion_hmac_secret( - &self, + mut self, ) -> Option> { self.0 - .get("hmac-secret") + .remove("hmac-secret") .map(GetAssertionHmacSecretInput::try_from) } pub fn make_credential_cred_protect_policy( - &self, + mut self, ) -> Option> { self.0 - .get("credProtect") + .remove("credProtect") .map(CredentialProtectionPolicy::try_from) } } @@ -309,14 +309,14 @@ pub struct GetAssertionHmacSecretInput { pub salt_auth: Vec, } -impl TryFrom<&cbor::Value> for GetAssertionHmacSecretInput { +impl TryFrom for GetAssertionHmacSecretInput { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { - let input_map = read_map(cbor_value)?; - let cose_key = read_map(ok_or_missing(input_map.get(&cbor_unsigned!(1)))?)?; - let salt_enc = read_byte_string(ok_or_missing(input_map.get(&cbor_unsigned!(2)))?)?; - let salt_auth = read_byte_string(ok_or_missing(input_map.get(&cbor_unsigned!(3)))?)?; + fn try_from(cbor_value: cbor::Value) -> Result { + let mut input_map = extract_map(cbor_value)?; + let cose_key = extract_map(ok_or_missing(input_map.remove(&cbor_unsigned!(1)))?)?; + let salt_enc = extract_byte_string(ok_or_missing(input_map.remove(&cbor_unsigned!(2)))?)?; + let salt_auth = extract_byte_string(ok_or_missing(input_map.remove(&cbor_unsigned!(3)))?)?; Ok(Self { key_agreement: CoseKey(cose_key.clone()), salt_enc, @@ -334,11 +334,13 @@ impl From for cbor::Value { } } -impl TryFrom<&cbor::Value> for GetAssertionHmacSecretOutput { +impl TryFrom for GetAssertionHmacSecretOutput { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { - Ok(GetAssertionHmacSecretOutput(read_byte_string(cbor_value)?)) + fn try_from(cbor_value: cbor::Value) -> Result { + Ok(GetAssertionHmacSecretOutput(extract_byte_string( + cbor_value, + )?)) } } @@ -349,22 +351,22 @@ pub struct MakeCredentialOptions { pub uv: bool, } -impl TryFrom<&cbor::Value> for MakeCredentialOptions { +impl TryFrom for MakeCredentialOptions { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { - let options_map = read_map(cbor_value)?; - let rk = match options_map.get(&cbor_text!("rk")) { - Some(options_entry) => read_bool(options_entry)?, + fn try_from(cbor_value: cbor::Value) -> Result { + let mut options_map = extract_map(cbor_value)?; + let rk = match options_map.remove(&cbor_text!("rk")) { + Some(options_entry) => extract_bool(options_entry)?, None => false, }; - if let Some(options_entry) = options_map.get(&cbor_text!("up")) { - if !read_bool(options_entry)? { + if let Some(options_entry) = options_map.remove(&cbor_text!("up")) { + if !extract_bool(options_entry)? { return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_OPTION); } } - let uv = match options_map.get(&cbor_text!("uv")) { - Some(options_entry) => read_bool(options_entry)?, + let uv = match options_map.remove(&cbor_text!("uv")) { + Some(options_entry) => extract_bool(options_entry)?, None => false, }; Ok(Self { rk, uv }) @@ -377,22 +379,22 @@ pub struct GetAssertionOptions { pub uv: bool, } -impl TryFrom<&cbor::Value> for GetAssertionOptions { +impl TryFrom for GetAssertionOptions { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { - let options_map = read_map(cbor_value)?; - if let Some(options_entry) = options_map.get(&cbor_text!("rk")) { + fn try_from(cbor_value: cbor::Value) -> Result { + let mut options_map = extract_map(cbor_value)?; + if let Some(options_entry) = options_map.remove(&cbor_text!("rk")) { // This is only for returning the correct status code. - read_bool(options_entry)?; + extract_bool(options_entry)?; return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_OPTION); } - let up = match options_map.get(&cbor_text!("up")) { - Some(options_entry) => read_bool(options_entry)?, + let up = match options_map.remove(&cbor_text!("up")) { + Some(options_entry) => extract_bool(options_entry)?, None => true, }; - let uv = match options_map.get(&cbor_text!("uv")) { - Some(options_entry) => read_bool(options_entry)?, + let uv = match options_map.remove(&cbor_text!("uv")) { + Some(options_entry) => extract_bool(options_entry)?, None => false, }; Ok(Self { up, uv }) @@ -435,11 +437,11 @@ impl From for cbor::Value { } } -impl TryFrom<&cbor::Value> for SignatureAlgorithm { +impl TryFrom for SignatureAlgorithm { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { - match read_integer(cbor_value)? { + fn try_from(cbor_value: cbor::Value) -> Result { + match extract_integer(cbor_value)? { ecdsa::PubKey::ES256_ALGORITHM => Ok(SignatureAlgorithm::ES256), _ => Ok(SignatureAlgorithm::Unknown), } @@ -473,19 +475,6 @@ impl TryFrom for CredentialProtectionPolicy { } } -impl TryFrom<&cbor::Value> for CredentialProtectionPolicy { - type Error = Ctap2StatusCode; - - fn try_from(cbor_value: &cbor::Value) -> Result { - match read_integer(cbor_value)? { - 0x01 => Ok(CredentialProtectionPolicy::UserVerificationOptional), - 0x02 => Ok(CredentialProtectionPolicy::UserVerificationOptionalWithCredentialIdList), - 0x03 => Ok(CredentialProtectionPolicy::UserVerificationRequired), - _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), - } - } -} - // https://www.w3.org/TR/webauthn/#public-key-credential-source // // Note that we only use the WebAuthn definition as an example. This data-structure is not specified @@ -645,23 +634,24 @@ impl TryFrom for ecdh::PubKey { type Error = Ctap2StatusCode; fn try_from(cose_key: CoseKey) -> Result { - let key_type = read_integer(ok_or_missing(cose_key.0.get(&cbor_int!(1)))?)?; + let mut cose_map = cose_key.0; + let key_type = extract_integer(ok_or_missing(cose_map.remove(&cbor_int!(1)))?)?; if key_type != EC2_KEY_TYPE { return Err(Ctap2StatusCode::CTAP2_ERR_UNSUPPORTED_ALGORITHM); } - let algorithm = read_integer(ok_or_missing(cose_key.0.get(&cbor_int!(3)))?)?; + let algorithm = extract_integer(ok_or_missing(cose_map.remove(&cbor_int!(3)))?)?; if algorithm != ECDH_ALGORITHM && algorithm != ES256_ALGORITHM { return Err(Ctap2StatusCode::CTAP2_ERR_UNSUPPORTED_ALGORITHM); } - let curve = read_integer(ok_or_missing(cose_key.0.get(&cbor_int!(-1)))?)?; + let curve = extract_integer(ok_or_missing(cose_map.remove(&cbor_int!(-1)))?)?; if curve != P_256_CURVE { return Err(Ctap2StatusCode::CTAP2_ERR_UNSUPPORTED_ALGORITHM); } - let x_bytes = read_byte_string(ok_or_missing(cose_key.0.get(&cbor_int!(-2)))?)?; + let x_bytes = extract_byte_string(ok_or_missing(cose_map.remove(&cbor_int!(-2)))?)?; if x_bytes.len() != ecdh::NBYTES { return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER); } - let y_bytes = read_byte_string(ok_or_missing(cose_key.0.get(&cbor_int!(-3)))?)?; + let y_bytes = extract_byte_string(ok_or_missing(cose_map.remove(&cbor_int!(-3)))?)?; if y_bytes.len() != ecdh::NBYTES { return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER); } @@ -698,11 +688,11 @@ impl From for cbor::Value { } } -impl TryFrom<&cbor::Value> for ClientPinSubCommand { +impl TryFrom for ClientPinSubCommand { type Error = Ctap2StatusCode; - fn try_from(cbor_value: &cbor::Value) -> Result { - let subcommand_int = read_unsigned(cbor_value)?; + fn try_from(cbor_value: cbor::Value) -> Result { + let subcommand_int = extract_unsigned(cbor_value)?; match subcommand_int { 0x01 => Ok(ClientPinSubCommand::GetPinRetries), 0x02 => Ok(ClientPinSubCommand::GetKeyAgreement), @@ -717,28 +707,14 @@ impl TryFrom<&cbor::Value> for ClientPinSubCommand { } } -pub(super) fn read_unsigned(cbor_value: &cbor::Value) -> Result { +pub(super) fn extract_unsigned(cbor_value: cbor::Value) -> Result { match cbor_value { - cbor::Value::KeyValue(cbor::KeyType::Unsigned(unsigned)) => Ok(*unsigned), + cbor::Value::KeyValue(cbor::KeyType::Unsigned(unsigned)) => Ok(unsigned), _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), } } -pub(super) fn read_integer(cbor_value: &cbor::Value) -> Result { - match cbor_value { - cbor::Value::KeyValue(cbor::KeyType::Unsigned(unsigned)) => { - if *unsigned <= core::i64::MAX as u64 { - Ok(*unsigned as i64) - } else { - Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE) - } - } - cbor::Value::KeyValue(cbor::KeyType::Negative(signed)) => Ok(*signed), - _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), - } -} - -fn extract_integer(cbor_value: cbor::Value) -> Result { +pub(super) fn extract_integer(cbor_value: cbor::Value) -> Result { match cbor_value { cbor::Value::KeyValue(cbor::KeyType::Unsigned(unsigned)) => { if unsigned <= core::i64::MAX as u64 { @@ -752,53 +728,28 @@ fn extract_integer(cbor_value: cbor::Value) -> Result { } } -pub fn read_byte_string(cbor_value: &cbor::Value) -> Result, Ctap2StatusCode> { - match cbor_value { - cbor::Value::KeyValue(cbor::KeyType::ByteString(byte_string)) => Ok(byte_string.to_vec()), - _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), - } -} - -fn extract_byte_string(cbor_value: cbor::Value) -> Result, Ctap2StatusCode> { +pub fn extract_byte_string(cbor_value: cbor::Value) -> Result, Ctap2StatusCode> { match cbor_value { cbor::Value::KeyValue(cbor::KeyType::ByteString(byte_string)) => Ok(byte_string), _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), } } -pub(super) fn read_text_string(cbor_value: &cbor::Value) -> Result { - match cbor_value { - cbor::Value::KeyValue(cbor::KeyType::TextString(text_string)) => { - Ok(text_string.to_string()) - } - _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), - } -} - -fn extract_text_string(cbor_value: cbor::Value) -> Result { +pub(super) fn extract_text_string(cbor_value: cbor::Value) -> Result { match cbor_value { cbor::Value::KeyValue(cbor::KeyType::TextString(text_string)) => Ok(text_string), _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), } } -pub(super) fn read_array(cbor_value: &cbor::Value) -> Result<&Vec, Ctap2StatusCode> { +pub(super) fn extract_array(cbor_value: cbor::Value) -> Result, Ctap2StatusCode> { match cbor_value { cbor::Value::Array(array) => Ok(array), _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), } } -pub(super) fn read_map( - cbor_value: &cbor::Value, -) -> Result<&BTreeMap, Ctap2StatusCode> { - match cbor_value { - cbor::Value::Map(map) => Ok(map), - _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), - } -} - -fn extract_map( +pub(super) fn extract_map( cbor_value: cbor::Value, ) -> Result, Ctap2StatusCode> { match cbor_value { @@ -807,7 +758,7 @@ fn extract_map( } } -pub(super) fn read_bool(cbor_value: &cbor::Value) -> Result { +pub(super) fn extract_bool(cbor_value: cbor::Value) -> Result { match cbor_value { cbor::Value::Simple(cbor::SimpleValue::FalseValue) => Ok(false), cbor::Value::Simple(cbor::SimpleValue::TrueValue) => Ok(true), @@ -827,192 +778,192 @@ mod test { use crypto::rng256::{Rng256, ThreadRng256}; #[test] - fn test_read_unsigned() { - assert_eq!(read_unsigned(&cbor_int!(123)), Ok(123)); + fn test_extract_unsigned() { + assert_eq!(extract_unsigned(cbor_int!(123)), Ok(123)); assert_eq!( - read_unsigned(&cbor_bool!(true)), + extract_unsigned(cbor_bool!(true)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_unsigned(&cbor_text!("foo")), + extract_unsigned(cbor_text!("foo")), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_unsigned(&cbor_bytes_lit!(b"bar")), + extract_unsigned(cbor_bytes_lit!(b"bar")), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_unsigned(&cbor_array![]), + extract_unsigned(cbor_array![]), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_unsigned(&cbor_map! {}), + extract_unsigned(cbor_map! {}), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); } #[test] - fn test_read_unsigned_limits() { + fn test_extract_unsigned_limits() { assert_eq!( - read_unsigned(&cbor_unsigned!(std::u64::MAX)), + extract_unsigned(cbor_unsigned!(std::u64::MAX)), Ok(std::u64::MAX) ); assert_eq!( - read_unsigned(&cbor_unsigned!((std::i64::MAX as u64) + 1)), + extract_unsigned(cbor_unsigned!((std::i64::MAX as u64) + 1)), Ok((std::i64::MAX as u64) + 1) ); assert_eq!( - read_unsigned(&cbor_int!(std::i64::MAX)), + extract_unsigned(cbor_int!(std::i64::MAX)), Ok(std::i64::MAX as u64) ); - assert_eq!(read_unsigned(&cbor_int!(123)), Ok(123)); - assert_eq!(read_unsigned(&cbor_int!(1)), Ok(1)); - assert_eq!(read_unsigned(&cbor_int!(0)), Ok(0)); + assert_eq!(extract_unsigned(cbor_int!(123)), Ok(123)); + assert_eq!(extract_unsigned(cbor_int!(1)), Ok(1)); + assert_eq!(extract_unsigned(cbor_int!(0)), Ok(0)); assert_eq!( - read_unsigned(&cbor_int!(-1)), + extract_unsigned(cbor_int!(-1)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_unsigned(&cbor_int!(-123)), + extract_unsigned(cbor_int!(-123)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_unsigned(&cbor_int!(std::i64::MIN)), + extract_unsigned(cbor_int!(std::i64::MIN)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); } #[test] - fn test_read_integer() { - assert_eq!(read_integer(&cbor_int!(123)), Ok(123)); - assert_eq!(read_integer(&cbor_int!(-123)), Ok(-123)); + fn test_extract_integer() { + assert_eq!(extract_integer(cbor_int!(123)), Ok(123)); + assert_eq!(extract_integer(cbor_int!(-123)), Ok(-123)); assert_eq!( - read_integer(&cbor_bool!(true)), + extract_integer(cbor_bool!(true)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_integer(&cbor_text!("foo")), + extract_integer(cbor_text!("foo")), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_integer(&cbor_bytes_lit!(b"bar")), + extract_integer(cbor_bytes_lit!(b"bar")), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_integer(&cbor_array![]), + extract_integer(cbor_array![]), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_integer(&cbor_map! {}), + extract_integer(cbor_map! {}), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); } #[test] - fn test_read_integer_limits() { + fn test_extract_integer_limits() { assert_eq!( - read_integer(&cbor_unsigned!(std::u64::MAX)), + extract_integer(cbor_unsigned!(std::u64::MAX)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_integer(&cbor_unsigned!((std::i64::MAX as u64) + 1)), + extract_integer(cbor_unsigned!((std::i64::MAX as u64) + 1)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); - assert_eq!(read_integer(&cbor_int!(std::i64::MAX)), Ok(std::i64::MAX)); - assert_eq!(read_integer(&cbor_int!(123)), Ok(123)); - assert_eq!(read_integer(&cbor_int!(1)), Ok(1)); - assert_eq!(read_integer(&cbor_int!(0)), Ok(0)); - assert_eq!(read_integer(&cbor_int!(-1)), Ok(-1)); - assert_eq!(read_integer(&cbor_int!(-123)), Ok(-123)); - assert_eq!(read_integer(&cbor_int!(std::i64::MIN)), Ok(std::i64::MIN)); + assert_eq!(extract_integer(cbor_int!(std::i64::MAX)), Ok(std::i64::MAX)); + assert_eq!(extract_integer(cbor_int!(123)), Ok(123)); + assert_eq!(extract_integer(cbor_int!(1)), Ok(1)); + assert_eq!(extract_integer(cbor_int!(0)), Ok(0)); + assert_eq!(extract_integer(cbor_int!(-1)), Ok(-1)); + assert_eq!(extract_integer(cbor_int!(-123)), Ok(-123)); + assert_eq!(extract_integer(cbor_int!(std::i64::MIN)), Ok(std::i64::MIN)); } #[test] - fn test_read_byte_string() { + fn test_extract_byte_string() { assert_eq!( - read_byte_string(&cbor_int!(123)), + extract_byte_string(cbor_int!(123)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_byte_string(&cbor_bool!(true)), + extract_byte_string(cbor_bool!(true)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_byte_string(&cbor_text!("foo")), + extract_byte_string(cbor_text!("foo")), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); - assert_eq!(read_byte_string(&cbor_bytes_lit!(b"")), Ok(Vec::new())); + assert_eq!(extract_byte_string(cbor_bytes_lit!(b"")), Ok(Vec::new())); assert_eq!( - read_byte_string(&cbor_bytes_lit!(b"bar")), + extract_byte_string(cbor_bytes_lit!(b"bar")), Ok(b"bar".to_vec()) ); assert_eq!( - read_byte_string(&cbor_array![]), + extract_byte_string(cbor_array![]), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_byte_string(&cbor_map! {}), + extract_byte_string(cbor_map! {}), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); } #[test] - fn test_read_text_string() { + fn test_extract_text_string() { assert_eq!( - read_text_string(&cbor_int!(123)), + extract_text_string(cbor_int!(123)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_text_string(&cbor_bool!(true)), + extract_text_string(cbor_bool!(true)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); - assert_eq!(read_text_string(&cbor_text!("")), Ok(String::new())); + assert_eq!(extract_text_string(cbor_text!("")), Ok(String::new())); assert_eq!( - read_text_string(&cbor_text!("foo")), + extract_text_string(cbor_text!("foo")), Ok(String::from("foo")) ); assert_eq!( - read_text_string(&cbor_bytes_lit!(b"bar")), + extract_text_string(cbor_bytes_lit!(b"bar")), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_text_string(&cbor_array![]), + extract_text_string(cbor_array![]), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_text_string(&cbor_map! {}), + extract_text_string(cbor_map! {}), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); } #[test] - fn test_read_array() { + fn test_extract_array() { assert_eq!( - read_array(&cbor_int!(123)), + extract_array(cbor_int!(123)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_array(&cbor_bool!(true)), + extract_array(cbor_bool!(true)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_array(&cbor_text!("foo")), + extract_array(cbor_text!("foo")), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_array(&cbor_bytes_lit!(b"bar")), + extract_array(cbor_bytes_lit!(b"bar")), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); - assert_eq!(read_array(&cbor_array![]), Ok(&Vec::new())); + assert_eq!(extract_array(cbor_array![]), Ok(Vec::new())); assert_eq!( - read_array(&cbor_array![ + extract_array(cbor_array![ 123, cbor_null!(), "foo", cbor_array![], cbor_map! {}, ]), - Ok(&vec![ + Ok(vec![ cbor_int!(123), cbor_null!(), cbor_text!("foo"), @@ -1021,41 +972,41 @@ mod test { ]) ); assert_eq!( - read_array(&cbor_map! {}), + extract_array(cbor_map! {}), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); } #[test] - fn test_read_map() { + fn test_extract_map() { assert_eq!( - read_map(&cbor_int!(123)), + extract_map(cbor_int!(123)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_map(&cbor_bool!(true)), + extract_map(cbor_bool!(true)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_map(&cbor_text!("foo")), + extract_map(cbor_text!("foo")), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_map(&cbor_bytes_lit!(b"bar")), + extract_map(cbor_bytes_lit!(b"bar")), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_map(&cbor_array![]), + extract_map(cbor_array![]), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); - assert_eq!(read_map(&cbor_map! {}), Ok(&BTreeMap::new())); + assert_eq!(extract_map(cbor_map! {}), Ok(BTreeMap::new())); assert_eq!( - read_map(&cbor_map! { + extract_map(cbor_map! { 1 => cbor_false!(), "foo" => b"bar", b"bin" => -42, }), - Ok(&[ + Ok([ (cbor_unsigned!(1), cbor_false!()), (cbor_text!("foo"), cbor_bytes_lit!(b"bar")), (cbor_bytes_lit!(b"bin"), cbor_int!(-42)), @@ -1067,27 +1018,27 @@ mod test { } #[test] - fn test_read_bool() { + fn test_extract_bool() { assert_eq!( - read_bool(&cbor_int!(123)), + extract_bool(cbor_int!(123)), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); - assert_eq!(read_bool(&cbor_bool!(true)), Ok(true)); - assert_eq!(read_bool(&cbor_bool!(false)), Ok(false)); + assert_eq!(extract_bool(cbor_bool!(true)), Ok(true)); + assert_eq!(extract_bool(cbor_bool!(false)), Ok(false)); assert_eq!( - read_bool(&cbor_text!("foo")), + extract_bool(cbor_text!("foo")), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_bool(&cbor_bytes_lit!(b"bar")), + extract_bool(cbor_bytes_lit!(b"bar")), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_bool(&cbor_array![]), + extract_bool(cbor_array![]), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); assert_eq!( - read_bool(&cbor_map! {}), + extract_bool(cbor_map! {}), Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) ); } @@ -1099,7 +1050,7 @@ mod test { "name" => "Example", "icon" => "example.com/icon.png", }; - let rp_entity = PublicKeyCredentialRpEntity::try_from(&cbor_rp_entity); + let rp_entity = PublicKeyCredentialRpEntity::try_from(cbor_rp_entity); let expected_rp_entity = PublicKeyCredentialRpEntity { rp_id: "example.com".to_string(), rp_name: Some("Example".to_string()), @@ -1116,7 +1067,7 @@ mod test { "displayName" => "bar", "icon" => "example.com/foo/icon.png", }; - let user_entity = PublicKeyCredentialUserEntity::try_from(&cbor_user_entity); + let user_entity = PublicKeyCredentialUserEntity::try_from(cbor_user_entity.clone()); let expected_user_entity = PublicKeyCredentialUserEntity { user_id: vec![0x1D, 0x1D, 0x1D, 0x1D], user_name: Some("foo".to_string()), @@ -1130,30 +1081,30 @@ mod test { #[test] fn test_from_into_public_key_credential_type() { - let cbor_credential_type = cbor_text!("public-key"); - let credential_type = PublicKeyCredentialType::try_from(&cbor_credential_type); + let cbor_credential_type: cbor::Value = cbor_text!("public-key"); + let credential_type = PublicKeyCredentialType::try_from(cbor_credential_type.clone()); let expected_credential_type = PublicKeyCredentialType::PublicKey; assert_eq!(credential_type, Ok(expected_credential_type)); let created_cbor: cbor::Value = credential_type.unwrap().into(); assert_eq!(created_cbor, cbor_credential_type); - let cbor_unknown_type = cbor_text!("unknown-type"); - let unknown_type = PublicKeyCredentialType::try_from(&cbor_unknown_type); + let cbor_unknown_type: cbor::Value = cbor_text!("unknown-type"); + let unknown_type = PublicKeyCredentialType::try_from(cbor_unknown_type); let expected_unknown_type = PublicKeyCredentialType::Unknown; assert_eq!(unknown_type, Ok(expected_unknown_type)); } #[test] fn test_from_into_signature_algorithm() { - let cbor_signature_algorithm = cbor_int!(ecdsa::PubKey::ES256_ALGORITHM); - let signature_algorithm = SignatureAlgorithm::try_from(&cbor_signature_algorithm); + let cbor_signature_algorithm: cbor::Value = cbor_int!(ecdsa::PubKey::ES256_ALGORITHM); + let signature_algorithm = SignatureAlgorithm::try_from(cbor_signature_algorithm.clone()); let expected_signature_algorithm = SignatureAlgorithm::ES256; assert_eq!(signature_algorithm, Ok(expected_signature_algorithm)); let created_cbor = cbor::Value::from(signature_algorithm.unwrap()); assert_eq!(created_cbor, cbor_signature_algorithm); - let cbor_unknown_algorithm = cbor_int!(-1); - let unknown_algorithm = SignatureAlgorithm::try_from(&cbor_unknown_algorithm); + let cbor_unknown_algorithm: cbor::Value = cbor_int!(-1); + let unknown_algorithm = SignatureAlgorithm::try_from(cbor_unknown_algorithm); let expected_unknown_algorithm = SignatureAlgorithm::Unknown; assert_eq!(unknown_algorithm, Ok(expected_unknown_algorithm)); } @@ -1177,23 +1128,23 @@ mod test { #[test] fn test_from_into_cred_protection_policy() { let cbor_policy = cbor::Value::from(CredentialProtectionPolicy::UserVerificationOptional); - let policy = CredentialProtectionPolicy::try_from(&cbor_policy); + let policy = CredentialProtectionPolicy::try_from(cbor_policy.clone()); let expected_policy = CredentialProtectionPolicy::UserVerificationOptional; assert_eq!(policy, Ok(expected_policy)); let created_cbor = cbor::Value::from(policy.unwrap()); assert_eq!(created_cbor, cbor_policy); - let cbor_policy_error = cbor_int!(-1); - let policy_error = CredentialProtectionPolicy::try_from(&cbor_policy_error); + let cbor_policy_error: cbor::Value = cbor_int!(-1); + let policy_error = CredentialProtectionPolicy::try_from(cbor_policy_error); let expected_error = Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE); assert_eq!(policy_error, expected_error); } #[test] fn test_from_into_authenticator_transport() { - let cbor_authenticator_transport = cbor_text!("usb"); + let cbor_authenticator_transport: cbor::Value = cbor_text!("usb"); let authenticator_transport = - AuthenticatorTransport::try_from(&cbor_authenticator_transport); + AuthenticatorTransport::try_from(cbor_authenticator_transport.clone()); let expected_authenticator_transport = AuthenticatorTransport::Usb; assert_eq!( authenticator_transport, @@ -1210,7 +1161,7 @@ mod test { "alg" => ecdsa::PubKey::ES256_ALGORITHM, }; let credential_parameter = - PublicKeyCredentialParameter::try_from(&cbor_credential_parameter); + PublicKeyCredentialParameter::try_from(cbor_credential_parameter.clone()); let expected_credential_parameter = PublicKeyCredentialParameter { cred_type: PublicKeyCredentialType::PublicKey, alg: SignatureAlgorithm::ES256, @@ -1228,7 +1179,7 @@ mod test { "transports" => cbor_array!["usb"], }; let credential_descriptor = - PublicKeyCredentialDescriptor::try_from(&cbor_credential_descriptor); + PublicKeyCredentialDescriptor::try_from(cbor_credential_descriptor.clone()); let expected_credential_descriptor = PublicKeyCredentialDescriptor { key_type: PublicKeyCredentialType::PublicKey, key_id: vec![0x2D, 0x2D, 0x2D, 0x2D], @@ -1244,7 +1195,7 @@ mod test { let cbor_extensions = cbor_map! { "the_answer" => 42, }; - let extensions = Extensions::try_from(&cbor_extensions); + let extensions = Extensions::try_from(cbor_extensions.clone()); let mut expected_extensions = Extensions(BTreeMap::new()); expected_extensions .0 @@ -1256,8 +1207,8 @@ mod test { #[test] fn test_from_into_get_assertion_hmac_secret_output() { - let cbor_output = cbor_bytes![vec![0xC0; 32]]; - let output = GetAssertionHmacSecretOutput::try_from(&cbor_output); + let cbor_output: cbor::Value = cbor_bytes![vec![0xC0; 32]]; + let output = GetAssertionHmacSecretOutput::try_from(cbor_output.clone()); let expected_output = GetAssertionHmacSecretOutput(vec![0xC0; 32]); assert_eq!(output, Ok(expected_output)); let created_cbor: cbor::Value = output.unwrap().into(); @@ -1269,13 +1220,13 @@ mod test { let cbor_extensions = cbor_map! { "hmac-secret" => true, }; - let extensions = Extensions::try_from(&cbor_extensions).unwrap(); + let extensions = Extensions::try_from(cbor_extensions).unwrap(); assert!(extensions.has_make_credential_hmac_secret().unwrap()); let cbor_extensions = cbor_map! { "hmac-secret" => false, }; - let extensions = Extensions::try_from(&cbor_extensions).unwrap(); + let extensions = Extensions::try_from(cbor_extensions).unwrap(); assert!(!extensions.has_make_credential_hmac_secret().unwrap()); let mut rng = ThreadRng256 {}; @@ -1289,7 +1240,7 @@ mod test { 3 => vec![0x03; 32], }, }; - let extensions = Extensions::try_from(&cbor_extensions).unwrap(); + let extensions = Extensions::try_from(cbor_extensions).unwrap(); let get_assertion_input = extensions.get_assertion_hmac_secret(); let expected_input = GetAssertionHmacSecretInput { key_agreement: cose_key, @@ -1304,7 +1255,7 @@ mod test { let cbor_extensions = cbor_map! { "credProtect" => CredentialProtectionPolicy::UserVerificationRequired, }; - let extensions = Extensions::try_from(&cbor_extensions).unwrap(); + let extensions = Extensions::try_from(cbor_extensions).unwrap(); assert_eq!( extensions.make_credential_cred_protect_policy(), Some(Ok(CredentialProtectionPolicy::UserVerificationRequired)) @@ -1317,7 +1268,7 @@ mod test { "rk" => true, "uv" => false, }; - let make_options = MakeCredentialOptions::try_from(&cbor_make_options); + let make_options = MakeCredentialOptions::try_from(cbor_make_options); let expected_make_options = MakeCredentialOptions { rk: true, uv: false, @@ -1331,7 +1282,7 @@ mod test { "up" => true, "uv" => false, }; - let get_assertion = GetAssertionOptions::try_from(&cbor_get_assertion); + let get_assertion = GetAssertionOptions::try_from(cbor_get_assertion); let expected_get_assertion = GetAssertionOptions { up: true, uv: false, @@ -1370,8 +1321,8 @@ mod test { #[test] fn test_from_into_client_pin_sub_command() { - let cbor_sub_command = cbor_int!(0x01); - let sub_command = ClientPinSubCommand::try_from(&cbor_sub_command); + let cbor_sub_command: cbor::Value = cbor_int!(0x01); + let sub_command = ClientPinSubCommand::try_from(cbor_sub_command.clone()); let expected_sub_command = ClientPinSubCommand::GetPinRetries; assert_eq!(sub_command, Ok(expected_sub_command)); let created_cbor: cbor::Value = sub_command.unwrap().into(); diff --git a/src/ctap/mod.rs b/src/ctap/mod.rs index 5514fea..8c78fe8 100644 --- a/src/ctap/mod.rs +++ b/src/ctap/mod.rs @@ -435,6 +435,7 @@ where } let (use_hmac_extension, cred_protect_policy) = if let Some(extensions) = extensions { + let has_hmac_secret = extensions.has_make_credential_hmac_secret()?; let mut cred_protect = extensions .make_credential_cred_protect_policy() .transpose()?; @@ -444,7 +445,7 @@ where { cred_protect = DEFAULT_CRED_PROTECT; } - (extensions.has_make_credential_hmac_secret()?, cred_protect) + (has_hmac_secret, cred_protect) } else { (false, None) };