introduces customization for PIN protcol v1 (#559)
This commit is contained in:
@@ -26,6 +26,12 @@ pub trait Customization {
|
|||||||
// Constants for adjusting privacy and protection levels.
|
// Constants for adjusting privacy and protection levels.
|
||||||
// ###########################################################################
|
// ###########################################################################
|
||||||
|
|
||||||
|
/// Removes support for PIN protocol v1.
|
||||||
|
///
|
||||||
|
/// We support PIN protocol v2, "intended to aid FIPS certification".
|
||||||
|
/// To certify, you might want to remove support for v1 using this customization.
|
||||||
|
fn allows_pin_protocol_v1(&self) -> bool;
|
||||||
|
|
||||||
/// Changes the default level for the credProtect extension.
|
/// Changes the default level for the credProtect extension.
|
||||||
///
|
///
|
||||||
/// You can change this value to one of the following for more privacy:
|
/// You can change this value to one of the following for more privacy:
|
||||||
@@ -245,6 +251,7 @@ pub trait Customization {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CustomizationImpl {
|
pub struct CustomizationImpl {
|
||||||
|
pub allows_pin_protocol_v1: bool,
|
||||||
pub default_cred_protect: Option<CredentialProtectionPolicy>,
|
pub default_cred_protect: Option<CredentialProtectionPolicy>,
|
||||||
pub default_min_pin_length: u8,
|
pub default_min_pin_length: u8,
|
||||||
pub default_min_pin_length_rp_ids: &'static [&'static str],
|
pub default_min_pin_length_rp_ids: &'static [&'static str],
|
||||||
@@ -263,6 +270,7 @@ pub struct CustomizationImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const DEFAULT_CUSTOMIZATION: CustomizationImpl = CustomizationImpl {
|
pub const DEFAULT_CUSTOMIZATION: CustomizationImpl = CustomizationImpl {
|
||||||
|
allows_pin_protocol_v1: true,
|
||||||
default_cred_protect: None,
|
default_cred_protect: None,
|
||||||
default_min_pin_length: 4,
|
default_min_pin_length: 4,
|
||||||
default_min_pin_length_rp_ids: &[],
|
default_min_pin_length_rp_ids: &[],
|
||||||
@@ -281,6 +289,10 @@ pub const DEFAULT_CUSTOMIZATION: CustomizationImpl = CustomizationImpl {
|
|||||||
};
|
};
|
||||||
|
|
||||||
impl Customization for CustomizationImpl {
|
impl Customization for CustomizationImpl {
|
||||||
|
fn allows_pin_protocol_v1(&self) -> bool {
|
||||||
|
self.allows_pin_protocol_v1
|
||||||
|
}
|
||||||
|
|
||||||
fn default_cred_protect(&self) -> Option<CredentialProtectionPolicy> {
|
fn default_cred_protect(&self) -> Option<CredentialProtectionPolicy> {
|
||||||
self.default_cred_protect
|
self.default_cred_protect
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ use super::pin_protocol::{verify_pin_uv_auth_token, PinProtocol, SharedSecret};
|
|||||||
use super::response::{AuthenticatorClientPinResponse, ResponseData};
|
use super::response::{AuthenticatorClientPinResponse, ResponseData};
|
||||||
use super::status_code::Ctap2StatusCode;
|
use super::status_code::Ctap2StatusCode;
|
||||||
use super::token_state::PinUvAuthTokenState;
|
use super::token_state::PinUvAuthTokenState;
|
||||||
|
use crate::api::customization::Customization;
|
||||||
use crate::ctap::storage;
|
use crate::ctap::storage;
|
||||||
use crate::env::Env;
|
use crate::env::Env;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
@@ -390,6 +391,11 @@ impl ClientPin {
|
|||||||
client_pin_params: AuthenticatorClientPinParameters,
|
client_pin_params: AuthenticatorClientPinParameters,
|
||||||
now: CtapInstant,
|
now: CtapInstant,
|
||||||
) -> Result<ResponseData, Ctap2StatusCode> {
|
) -> Result<ResponseData, Ctap2StatusCode> {
|
||||||
|
if !env.customization().allows_pin_protocol_v1()
|
||||||
|
&& client_pin_params.pin_uv_auth_protocol == PinUvAuthProtocol::V1
|
||||||
|
{
|
||||||
|
return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER);
|
||||||
|
}
|
||||||
let response = match client_pin_params.sub_command {
|
let response = match client_pin_params.sub_command {
|
||||||
ClientPinSubCommand::GetPinRetries => Some(self.process_get_pin_retries(env)?),
|
ClientPinSubCommand::GetPinRetries => Some(self.process_get_pin_retries(env)?),
|
||||||
ClientPinSubCommand::GetKeyAgreement => {
|
ClientPinSubCommand::GetKeyAgreement => {
|
||||||
@@ -872,6 +878,20 @@ mod test {
|
|||||||
test_helper_process_get_key_agreement(PinUvAuthProtocol::V2);
|
test_helper_process_get_key_agreement(PinUvAuthProtocol::V2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_process_get_key_agreement_v1_not_allowed() {
|
||||||
|
let (mut client_pin, params) = create_client_pin_and_parameters(
|
||||||
|
PinUvAuthProtocol::V1,
|
||||||
|
ClientPinSubCommand::GetKeyAgreement,
|
||||||
|
);
|
||||||
|
let mut env = TestEnv::new();
|
||||||
|
env.customization_mut().set_allows_pin_protocol_v1(false);
|
||||||
|
assert_eq!(
|
||||||
|
client_pin.process_command(&mut env, params, CtapInstant::new(0)),
|
||||||
|
Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn test_helper_process_set_pin(pin_uv_auth_protocol: PinUvAuthProtocol) {
|
fn test_helper_process_set_pin(pin_uv_auth_protocol: PinUvAuthProtocol) {
|
||||||
let (mut client_pin, params) =
|
let (mut client_pin, params) =
|
||||||
create_client_pin_and_parameters(pin_uv_auth_protocol, ClientPinSubCommand::SetPin);
|
create_client_pin_and_parameters(pin_uv_auth_protocol, ClientPinSubCommand::SetPin);
|
||||||
|
|||||||
@@ -1264,6 +1264,10 @@ impl CtapState {
|
|||||||
(String::from("setMinPINLength"), true),
|
(String::from("setMinPINLength"), true),
|
||||||
(String::from("makeCredUvNotRqd"), !has_always_uv),
|
(String::from("makeCredUvNotRqd"), !has_always_uv),
|
||||||
]);
|
]);
|
||||||
|
let mut pin_protocols = vec![PinUvAuthProtocol::V2 as u64];
|
||||||
|
if env.customization().allows_pin_protocol_v1() {
|
||||||
|
pin_protocols.push(PinUvAuthProtocol::V1 as u64);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(ResponseData::AuthenticatorGetInfo(
|
Ok(ResponseData::AuthenticatorGetInfo(
|
||||||
AuthenticatorGetInfoResponse {
|
AuthenticatorGetInfoResponse {
|
||||||
@@ -1279,10 +1283,7 @@ impl CtapState {
|
|||||||
options: Some(options),
|
options: Some(options),
|
||||||
max_msg_size: Some(env.customization().max_msg_size() as u64),
|
max_msg_size: Some(env.customization().max_msg_size() as u64),
|
||||||
// The order implies preference. We favor the new V2.
|
// The order implies preference. We favor the new V2.
|
||||||
pin_protocols: Some(vec![
|
pin_protocols: Some(pin_protocols),
|
||||||
PinUvAuthProtocol::V2 as u64,
|
|
||||||
PinUvAuthProtocol::V1 as u64,
|
|
||||||
]),
|
|
||||||
max_credential_count_in_list: env
|
max_credential_count_in_list: env
|
||||||
.customization()
|
.customization()
|
||||||
.max_credential_count_in_list()
|
.max_credential_count_in_list()
|
||||||
@@ -1581,6 +1582,23 @@ mod test {
|
|||||||
assert_eq!(info_reponse, response_cbor);
|
assert_eq!(info_reponse, response_cbor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_info_no_pin_protocol_v1() {
|
||||||
|
let mut env = TestEnv::new();
|
||||||
|
env.customization_mut().set_allows_pin_protocol_v1(false);
|
||||||
|
let ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
|
||||||
|
let info_response = ctap_state.process_get_info(&mut env).unwrap();
|
||||||
|
match info_response {
|
||||||
|
ResponseData::AuthenticatorGetInfo(response) => {
|
||||||
|
assert_eq!(
|
||||||
|
response.pin_protocols,
|
||||||
|
Some(vec![PinUvAuthProtocol::V2 as u64])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => panic!("Invalid response type"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn create_minimal_make_credential_parameters() -> AuthenticatorMakeCredentialParameters {
|
fn create_minimal_make_credential_parameters() -> AuthenticatorMakeCredentialParameters {
|
||||||
let client_data_hash = vec![0xCD];
|
let client_data_hash = vec![0xCD];
|
||||||
let rp = PublicKeyCredentialRpEntity {
|
let rp = PublicKeyCredentialRpEntity {
|
||||||
|
|||||||
11
src/env/test/customization.rs
vendored
11
src/env/test/customization.rs
vendored
@@ -18,6 +18,7 @@ use alloc::string::String;
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
pub struct TestCustomization {
|
pub struct TestCustomization {
|
||||||
|
allows_pin_protocol_v1: bool,
|
||||||
default_cred_protect: Option<CredentialProtectionPolicy>,
|
default_cred_protect: Option<CredentialProtectionPolicy>,
|
||||||
default_min_pin_length: u8,
|
default_min_pin_length: u8,
|
||||||
default_min_pin_length_rp_ids: Vec<String>,
|
default_min_pin_length_rp_ids: Vec<String>,
|
||||||
@@ -36,6 +37,10 @@ pub struct TestCustomization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TestCustomization {
|
impl TestCustomization {
|
||||||
|
pub fn set_allows_pin_protocol_v1(&mut self, is_allowed: bool) {
|
||||||
|
self.allows_pin_protocol_v1 = is_allowed;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn setup_enterprise_attestation(
|
pub fn setup_enterprise_attestation(
|
||||||
&mut self,
|
&mut self,
|
||||||
mode: Option<EnterpriseAttestationMode>,
|
mode: Option<EnterpriseAttestationMode>,
|
||||||
@@ -49,6 +54,10 @@ impl TestCustomization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Customization for TestCustomization {
|
impl Customization for TestCustomization {
|
||||||
|
fn allows_pin_protocol_v1(&self) -> bool {
|
||||||
|
self.allows_pin_protocol_v1
|
||||||
|
}
|
||||||
|
|
||||||
fn default_cred_protect(&self) -> Option<CredentialProtectionPolicy> {
|
fn default_cred_protect(&self) -> Option<CredentialProtectionPolicy> {
|
||||||
self.default_cred_protect
|
self.default_cred_protect
|
||||||
}
|
}
|
||||||
@@ -117,6 +126,7 @@ impl Customization for TestCustomization {
|
|||||||
impl From<CustomizationImpl> for TestCustomization {
|
impl From<CustomizationImpl> for TestCustomization {
|
||||||
fn from(c: CustomizationImpl) -> Self {
|
fn from(c: CustomizationImpl) -> Self {
|
||||||
let CustomizationImpl {
|
let CustomizationImpl {
|
||||||
|
allows_pin_protocol_v1,
|
||||||
default_cred_protect,
|
default_cred_protect,
|
||||||
default_min_pin_length,
|
default_min_pin_length,
|
||||||
default_min_pin_length_rp_ids,
|
default_min_pin_length_rp_ids,
|
||||||
@@ -145,6 +155,7 @@ impl From<CustomizationImpl> for TestCustomization {
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
allows_pin_protocol_v1,
|
||||||
default_cred_protect,
|
default_cred_protect,
|
||||||
default_min_pin_length,
|
default_min_pin_length,
|
||||||
default_min_pin_length_rp_ids,
|
default_min_pin_length_rp_ids,
|
||||||
|
|||||||
Reference in New Issue
Block a user