adds the config command

This commit is contained in:
Fabian Kaczmarczyck
2021-01-07 18:17:21 +01:00
parent 32d5ff91d4
commit f4eb6c938e
9 changed files with 796 additions and 335 deletions

View File

@@ -14,10 +14,10 @@
use super::data_formats::{
extract_array, extract_bool, extract_byte_string, extract_map, extract_text_string,
extract_unsigned, ok_or_missing, ClientPinSubCommand, CoseKey, GetAssertionExtensions,
GetAssertionOptions, MakeCredentialExtensions, MakeCredentialOptions,
PublicKeyCredentialDescriptor, PublicKeyCredentialParameter, PublicKeyCredentialRpEntity,
PublicKeyCredentialUserEntity,
extract_unsigned, ok_or_missing, ClientPinSubCommand, ConfigSubCommand, ConfigSubCommandParams,
CoseKey, GetAssertionExtensions, GetAssertionOptions, MakeCredentialExtensions,
MakeCredentialOptions, PublicKeyCredentialDescriptor, PublicKeyCredentialParameter,
PublicKeyCredentialRpEntity, PublicKeyCredentialUserEntity, SetMinPinLengthParams,
};
use super::key_material;
use super::status_code::Ctap2StatusCode;
@@ -42,6 +42,7 @@ pub enum Command {
AuthenticatorReset,
AuthenticatorGetNextAssertion,
AuthenticatorSelection,
AuthenticatorConfig(AuthenticatorConfigParameters),
// TODO(kaczmarczyck) implement FIDO 2.1 commands (see below consts)
// Vendor specific commands
AuthenticatorVendorConfigure(AuthenticatorVendorConfigureParameters),
@@ -114,6 +115,12 @@ impl Command {
// Parameters are ignored.
Ok(Command::AuthenticatorSelection)
}
Command::AUTHENTICATOR_CONFIG => {
let decoded_cbor = cbor::read(&bytes[1..])?;
Ok(Command::AuthenticatorConfig(
AuthenticatorConfigParameters::try_from(decoded_cbor)?,
))
}
Command::AUTHENTICATOR_VENDOR_CONFIGURE => {
let decoded_cbor = cbor::read(&bytes[1..])?;
Ok(Command::AuthenticatorVendorConfigure(
@@ -290,8 +297,6 @@ pub struct AuthenticatorClientPinParameters {
pub pin_auth: Option<Vec<u8>>,
pub new_pin_enc: Option<Vec<u8>>,
pub pin_hash_enc: Option<Vec<u8>>,
pub min_pin_length: Option<u8>,
pub min_pin_length_rp_ids: Option<Vec<String>>,
pub permissions: Option<u8>,
pub permissions_rp_id: Option<String>,
}
@@ -308,8 +313,6 @@ impl TryFrom<cbor::Value> for AuthenticatorClientPinParameters {
4 => pin_auth,
5 => new_pin_enc,
6 => pin_hash_enc,
7 => min_pin_length,
8 => min_pin_length_rp_ids,
9 => permissions,
10 => permissions_rp_id,
} = extract_map(cbor_value)?;
@@ -321,21 +324,6 @@ impl TryFrom<cbor::Value> for AuthenticatorClientPinParameters {
let pin_auth = pin_auth.map(extract_byte_string).transpose()?;
let new_pin_enc = new_pin_enc.map(extract_byte_string).transpose()?;
let pin_hash_enc = pin_hash_enc.map(extract_byte_string).transpose()?;
let min_pin_length = min_pin_length
.map(extract_unsigned)
.transpose()?
.map(u8::try_from)
.transpose()
.map_err(|_| Ctap2StatusCode::CTAP2_ERR_PIN_POLICY_VIOLATION)?;
let min_pin_length_rp_ids = match min_pin_length_rp_ids {
Some(entry) => Some(
extract_array(entry)?
.into_iter()
.map(extract_text_string)
.collect::<Result<Vec<String>, Ctap2StatusCode>>()?,
),
None => None,
};
// We expect a bit field of 8 bits, and drop everything else.
// This means we ignore extensions in future versions.
let permissions = permissions
@@ -351,14 +339,52 @@ impl TryFrom<cbor::Value> for AuthenticatorClientPinParameters {
pin_auth,
new_pin_enc,
pin_hash_enc,
min_pin_length,
min_pin_length_rp_ids,
permissions,
permissions_rp_id,
})
}
}
#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))]
pub struct AuthenticatorConfigParameters {
pub sub_command: ConfigSubCommand,
pub sub_command_params: Option<ConfigSubCommandParams>,
pub pin_uv_auth_param: Option<Vec<u8>>,
pub pin_uv_auth_protocol: Option<u64>,
}
impl TryFrom<cbor::Value> for AuthenticatorConfigParameters {
type Error = Ctap2StatusCode;
fn try_from(cbor_value: cbor::Value) -> Result<Self, Ctap2StatusCode> {
destructure_cbor_map! {
let {
0x01 => sub_command,
0x02 => sub_command_params,
0x03 => pin_uv_auth_param,
0x04 => pin_uv_auth_protocol,
} = extract_map(cbor_value)?;
}
let sub_command = ConfigSubCommand::try_from(ok_or_missing(sub_command)?)?;
let sub_command_params = match sub_command {
ConfigSubCommand::SetMinPinLength => Some(ConfigSubCommandParams::SetMinPinLength(
SetMinPinLengthParams::try_from(ok_or_missing(sub_command_params)?)?,
)),
_ => None,
};
let pin_uv_auth_param = pin_uv_auth_param.map(extract_byte_string).transpose()?;
let pin_uv_auth_protocol = pin_uv_auth_protocol.map(extract_unsigned).transpose()?;
Ok(AuthenticatorConfigParameters {
sub_command,
sub_command_params,
pin_uv_auth_param,
pin_uv_auth_protocol,
})
}
}
#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))]
pub struct AuthenticatorAttestationMaterial {
pub certificate: Vec<u8>,
@@ -541,8 +567,6 @@ mod test {
4 => vec! [0xBB],
5 => vec! [0xCC],
6 => vec! [0xDD],
7 => 4,
8 => cbor_array!["example.com"],
9 => 0x03,
10 => "example.com",
};
@@ -556,8 +580,6 @@ mod test {
pin_auth: Some(vec![0xBB]),
new_pin_enc: Some(vec![0xCC]),
pin_hash_enc: Some(vec![0xDD]),
min_pin_length: Some(4),
min_pin_length_rp_ids: Some(vec!["example.com".to_string()]),
permissions: Some(0x03),
permissions_rp_id: Some("example.com".to_string()),
};