introduces a default level for credProtect
This commit is contained in:
@@ -99,6 +99,9 @@ a few things you can personalize:
|
||||
4. Depending on your available flash storage, choose an appropriate maximum
|
||||
number of supported residential keys and number of pages in
|
||||
`ctap/storage.rs`.
|
||||
5. Change the default level for the credProtect extension. Resident credentials
|
||||
become undiscoverable without user verification. This helps privacy, but
|
||||
can make usage less comfortable for less important credentials.
|
||||
|
||||
### 3D printed enclosure
|
||||
|
||||
|
||||
@@ -440,7 +440,7 @@ impl TryFrom<&cbor::Value> for SignatureAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
#[derive(Clone, PartialEq, PartialOrd)]
|
||||
#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))]
|
||||
pub enum CredentialProtectionPolicy {
|
||||
UserVerificationOptional = 0x01,
|
||||
|
||||
@@ -32,9 +32,10 @@ use self::command::{
|
||||
#[cfg(feature = "with_ctap2_1")]
|
||||
use self::data_formats::AuthenticatorTransport;
|
||||
use self::data_formats::{
|
||||
ClientPinSubCommand, CoseKey, GetAssertionHmacSecretInput, PackedAttestationStatement,
|
||||
PublicKeyCredentialDescriptor, PublicKeyCredentialParameter, PublicKeyCredentialSource,
|
||||
PublicKeyCredentialType, PublicKeyCredentialUserEntity, SignatureAlgorithm,
|
||||
ClientPinSubCommand, CoseKey, CredentialProtectionPolicy, GetAssertionHmacSecretInput,
|
||||
PackedAttestationStatement, PublicKeyCredentialDescriptor, PublicKeyCredentialParameter,
|
||||
PublicKeyCredentialSource, PublicKeyCredentialType, PublicKeyCredentialUserEntity,
|
||||
SignatureAlgorithm,
|
||||
};
|
||||
use self::hid::ChannelID;
|
||||
use self::key_material::{AAGUID, ATTESTATION_CERTIFICATE, ATTESTATION_PRIVATE_KEY};
|
||||
@@ -109,6 +110,10 @@ pub const ES256_CRED_PARAM: PublicKeyCredentialParameter = PublicKeyCredentialPa
|
||||
cred_type: PublicKeyCredentialType::PublicKey,
|
||||
alg: SignatureAlgorithm::ES256,
|
||||
};
|
||||
// You can change this value to one of the following for more privacy.
|
||||
// - Some(CredentialProtectionPolicy::UserVerificationOptionalWithCredentialIdList)
|
||||
// - Some(CredentialProtectionPolicy::UserVerificationRequired)
|
||||
const DEFAULT_CRED_PROTECT: Option<CredentialProtectionPolicy> = None;
|
||||
|
||||
fn check_pin_auth(hmac_key: &[u8], hmac_contents: &[u8], pin_auth: &[u8]) -> bool {
|
||||
if pin_auth.len() != PIN_AUTH_LENGTH {
|
||||
@@ -430,12 +435,19 @@ where
|
||||
}
|
||||
|
||||
let (use_hmac_extension, cred_protect_policy) = if let Some(extensions) = extensions {
|
||||
(
|
||||
extensions.has_make_credential_hmac_secret()?,
|
||||
extensions
|
||||
.make_credential_cred_protect_policy()
|
||||
.transpose()?,
|
||||
)
|
||||
let mut cred_protect = extensions
|
||||
.make_credential_cred_protect_policy()
|
||||
.transpose()?;
|
||||
if cred_protect
|
||||
.as_ref()
|
||||
.unwrap_or(&CredentialProtectionPolicy::UserVerificationOptional)
|
||||
> DEFAULT_CRED_PROTECT
|
||||
.as_ref()
|
||||
.unwrap_or(&CredentialProtectionPolicy::UserVerificationOptional)
|
||||
{
|
||||
cred_protect = DEFAULT_CRED_PROTECT;
|
||||
}
|
||||
(extensions.has_make_credential_hmac_secret()?, cred_protect)
|
||||
} else {
|
||||
(false, None)
|
||||
};
|
||||
@@ -812,6 +824,7 @@ where
|
||||
transports: Some(vec![AuthenticatorTransport::Usb]),
|
||||
#[cfg(feature = "with_ctap2_1")]
|
||||
algorithms: Some(vec![ES256_CRED_PARAM]),
|
||||
default_cred_protect: DEFAULT_CRED_PROTECT,
|
||||
#[cfg(feature = "with_ctap2_1")]
|
||||
firmware_version: None,
|
||||
},
|
||||
@@ -1116,8 +1129,8 @@ where
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::data_formats::{
|
||||
CredentialProtectionPolicy, Extensions, GetAssertionOptions, MakeCredentialOptions,
|
||||
PublicKeyCredentialRpEntity, PublicKeyCredentialUserEntity,
|
||||
Extensions, GetAssertionOptions, MakeCredentialOptions, PublicKeyCredentialRpEntity,
|
||||
PublicKeyCredentialUserEntity,
|
||||
};
|
||||
use super::*;
|
||||
use crypto::rng256::ThreadRng256;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#[cfg(feature = "with_ctap2_1")]
|
||||
use super::data_formats::{AuthenticatorTransport, PublicKeyCredentialParameter};
|
||||
use super::data_formats::{
|
||||
CoseKey, PackedAttestationStatement, PublicKeyCredentialDescriptor,
|
||||
CoseKey, CredentialProtectionPolicy, PackedAttestationStatement, PublicKeyCredentialDescriptor,
|
||||
PublicKeyCredentialUserEntity,
|
||||
};
|
||||
use alloc::collections::BTreeMap;
|
||||
@@ -119,6 +119,7 @@ pub struct AuthenticatorGetInfoResponse {
|
||||
pub transports: Option<Vec<AuthenticatorTransport>>,
|
||||
#[cfg(feature = "with_ctap2_1")]
|
||||
pub algorithms: Option<Vec<PublicKeyCredentialParameter>>,
|
||||
pub default_cred_protect: Option<CredentialProtectionPolicy>,
|
||||
#[cfg(feature = "with_ctap2_1")]
|
||||
pub firmware_version: Option<u64>,
|
||||
}
|
||||
@@ -137,6 +138,7 @@ impl From<AuthenticatorGetInfoResponse> for cbor::Value {
|
||||
max_credential_id_length,
|
||||
transports,
|
||||
algorithms,
|
||||
default_cred_protect,
|
||||
firmware_version,
|
||||
} = get_info_response;
|
||||
|
||||
@@ -159,6 +161,7 @@ impl From<AuthenticatorGetInfoResponse> for cbor::Value {
|
||||
0x08 => max_credential_id_length,
|
||||
0x09 => transports.map(|vec| cbor_array_vec!(vec)),
|
||||
0x0A => algorithms.map(|vec| cbor_array_vec!(vec)),
|
||||
0x0C => default_cred_protect.map(|p| p as u64),
|
||||
0x0E => firmware_version,
|
||||
}
|
||||
}
|
||||
@@ -172,6 +175,7 @@ impl From<AuthenticatorGetInfoResponse> for cbor::Value {
|
||||
options,
|
||||
max_msg_size,
|
||||
pin_protocols,
|
||||
default_cred_protect,
|
||||
} = get_info_response;
|
||||
|
||||
let options_cbor: Option<cbor::Value> = options.map(|options| {
|
||||
@@ -189,6 +193,7 @@ impl From<AuthenticatorGetInfoResponse> for cbor::Value {
|
||||
0x04 => options_cbor,
|
||||
0x05 => max_msg_size,
|
||||
0x06 => pin_protocols.map(|vec| cbor_array_vec!(vec)),
|
||||
0x0C => default_cred_protect.map(|p| p as u64),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,6 +295,7 @@ mod test {
|
||||
transports: None,
|
||||
#[cfg(feature = "with_ctap2_1")]
|
||||
algorithms: None,
|
||||
default_cred_protect: None,
|
||||
#[cfg(feature = "with_ctap2_1")]
|
||||
firmware_version: None,
|
||||
};
|
||||
@@ -318,6 +324,7 @@ mod test {
|
||||
max_credential_id_length: Some(256),
|
||||
transports: Some(vec![AuthenticatorTransport::Usb]),
|
||||
algorithms: Some(vec![ES256_CRED_PARAM]),
|
||||
default_cred_protect: Some(CredentialProtectionPolicy::UserVerificationRequired),
|
||||
firmware_version: Some(0),
|
||||
};
|
||||
let response_cbor: Option<cbor::Value> =
|
||||
@@ -333,6 +340,7 @@ mod test {
|
||||
0x08 => 256,
|
||||
0x09 => cbor_array_vec![vec!["usb"]],
|
||||
0x0A => cbor_array_vec![vec![ES256_CRED_PARAM]],
|
||||
0x0C => CredentialProtectionPolicy::UserVerificationRequired as u64,
|
||||
0x0E => 0,
|
||||
};
|
||||
assert_eq!(response_cbor, Some(expected_cbor));
|
||||
|
||||
Reference in New Issue
Block a user