introduces customization for PIN protcol v1 (#559)

This commit is contained in:
kaczmarczyck
2022-10-13 16:13:07 +02:00
committed by GitHub
parent 3c28ff49ee
commit 44cafb9566
4 changed files with 65 additions and 4 deletions

View File

@@ -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
} }

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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,