Move enterprise mode related customizations to new file (#463)

* Move enterprise mode related customizations to new file

* Fix cargo clippy error

* Add is_enterpris_rp_id API to avoid cloning

* Only expose enterprise_rp_id_list API in std
This commit is contained in:
hcyang
2022-04-25 09:45:59 +08:00
committed by GitHub
parent 0f47e99a08
commit 2b6424360c
6 changed files with 153 additions and 82 deletions

View File

@@ -14,10 +14,10 @@
use super::client_pin::{ClientPin, PinPermission};
use super::command::AuthenticatorConfigParameters;
use super::customization::ENTERPRISE_ATTESTATION_MODE;
use super::data_formats::{ConfigSubCommand, ConfigSubCommandParams, SetMinPinLengthParams};
use super::response::ResponseData;
use super::status_code::Ctap2StatusCode;
use crate::api::customization::Customization;
use crate::ctap::storage;
use crate::env::Env;
use alloc::vec;
@@ -26,7 +26,7 @@ use alloc::vec;
fn process_enable_enterprise_attestation(
env: &mut impl Env,
) -> Result<ResponseData, Ctap2StatusCode> {
if ENTERPRISE_ATTESTATION_MODE.is_some() {
if env.customization().enterprise_attestation_mode().is_some() {
storage::enable_enterprise_attestation(env)?;
Ok(ResponseData::AuthenticatorConfig)
} else {
@@ -144,7 +144,7 @@ mod test {
};
let config_response = process_config(&mut env, &mut client_pin, config_params);
if ENTERPRISE_ATTESTATION_MODE.is_some() {
if env.customization().enterprise_attestation_mode().is_some() {
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
assert_eq!(storage::enterprise_attestation(&mut env), Ok(true));
} else {

View File

@@ -17,66 +17,6 @@
//! If you adapt them, make sure to run the tests before flashing the firmware.
//! Our deploy script enforces the invariants.
use crate::ctap::data_formats::EnterpriseAttestationMode;
/// Allows usage of enterprise attestation.
///
/// # Invariant
///
/// - Enterprise and batch attestation can not both be active.
/// - If the mode is VendorFacilitated, ENTERPRISE_RP_ID_LIST must be non-empty.
///
/// For privacy reasons, it is disabled by default. You can choose between:
/// - EnterpriseAttestationMode::VendorFacilitated
/// - EnterpriseAttestationMode::PlatformManaged
///
/// VendorFacilitated
/// Enterprise attestation is restricted to ENTERPRISE_RP_ID_LIST. Add your
/// enterprises domain, e.g. "example.com", to the list below.
///
/// PlatformManaged
/// All relying parties can request an enterprise attestation. The authenticator
/// trusts the platform to filter requests.
///
/// To enable the feature, send the subcommand enableEnterpriseAttestation in
/// AuthenticatorConfig. An enterprise might want to customize the type of
/// attestation that is used. OpenSK defaults to batch attestation. Configuring
/// individual certificates then makes authenticators identifiable.
///
/// OpenSK prevents activating batch and enterprise attestation together. The
/// current implementation uses the same key material at the moment, and these
/// two modes have conflicting privacy guarantees.
/// If you implement your own enterprise attestation mechanism, and you want
/// batch attestation at the same time, proceed carefully and remove the
/// assertion.
pub const ENTERPRISE_ATTESTATION_MODE: Option<EnterpriseAttestationMode> = None;
/// Lists relying party IDs that can perform enterprise attestation.
///
/// # Invariant
///
/// - If the mode is VendorFacilitated, ENTERPRISE_RP_ID_LIST must be non-empty.
///
/// This list is only considered if the enterprise attestation mode is
/// VendorFacilitated.
pub const ENTERPRISE_RP_ID_LIST: &[&str] = &[];
/// Enables or disables basic attestation for FIDO2.
///
/// # Invariant
///
/// - Enterprise and batch attestation can not both be active (see above).
///
/// The basic attestation uses the signing key configured with a vendor command
/// as a batch key. If you turn batch attestation on, be aware that it is your
/// responsibility to safely generate and store the key material. Also, the
/// batches must have size of at least 100k authenticators before using new key
/// material.
/// U2F is unaffected by this setting.
///
/// https://www.w3.org/TR/webauthn/#attestation
pub const USE_BATCH_ATTESTATION: bool = false;
// ###########################################################################
// Constants for performance optimization or adapting to different hardware.
//
@@ -140,12 +80,6 @@ mod test {
// Two invariants are currently tested in different files:
// - storage.rs: if MAX_LARGE_BLOB_ARRAY_SIZE fits the shards
// - storage/key.rs: if MAX_SUPPORTED_RESIDENT_KEYS fits CREDENTIALS
assert!(!USE_BATCH_ATTESTATION || ENTERPRISE_ATTESTATION_MODE.is_none());
if let Some(EnterpriseAttestationMode::VendorFacilitated) = ENTERPRISE_ATTESTATION_MODE {
assert!(!ENTERPRISE_RP_ID_LIST.is_empty());
} else {
assert!(ENTERPRISE_RP_ID_LIST.is_empty());
}
assert!(MAX_CRED_BLOB_LENGTH >= 32);
if let Some(count) = MAX_CREDENTIAL_COUNT_IN_LIST {
assert!(count >= 1);

View File

@@ -1052,7 +1052,7 @@ impl From<SetMinPinLengthParams> for cbor::Value {
}
/// The level of enterprise attestation allowed in MakeCredential.
#[derive(Debug, PartialEq)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EnterpriseAttestationMode {
/// Enterprise attestation is restricted to a list of RP IDs. Add your
/// enterprises domain, e.g. "example.com", to the list below.

View File

@@ -44,8 +44,7 @@ use self::config_command::process_config;
use self::credential_management::process_credential_management;
use self::crypto_wrapper::{aes256_cbc_decrypt, aes256_cbc_encrypt};
use self::customization::{
ENTERPRISE_ATTESTATION_MODE, ENTERPRISE_RP_ID_LIST, MAX_CREDENTIAL_COUNT_IN_LIST,
MAX_CRED_BLOB_LENGTH, MAX_LARGE_BLOB_ARRAY_SIZE, USE_BATCH_ATTESTATION,
MAX_CREDENTIAL_COUNT_IN_LIST, MAX_CRED_BLOB_LENGTH, MAX_LARGE_BLOB_ARRAY_SIZE,
};
use self::data_formats::{
AuthenticatorTransport, CoseKey, CoseSignature, CredentialProtectionPolicy,
@@ -684,8 +683,10 @@ impl CtapState {
let rp_id = rp.rp_id;
let ep_att = if let Some(enterprise_attestation) = enterprise_attestation {
let authenticator_mode =
ENTERPRISE_ATTESTATION_MODE.ok_or(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER)?;
let authenticator_mode = env
.customization()
.enterprise_attestation_mode()
.ok_or(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER)?;
if !storage::enterprise_attestation(env)? {
return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER);
}
@@ -696,7 +697,7 @@ impl CtapState {
(
EnterpriseAttestationMode::PlatformManaged,
EnterpriseAttestationMode::PlatformManaged,
) => ENTERPRISE_RP_ID_LIST.contains(&rp_id.as_str()),
) => env.customization().is_enterprise_rp_id(&rp_id),
_ => true,
}
} else {
@@ -859,7 +860,7 @@ impl CtapState {
let mut signature_data = auth_data.clone();
signature_data.extend(client_data_hash);
let (signature, x5c) = if USE_BATCH_ATTESTATION || ep_att {
let (signature, x5c) = if env.customization().use_batch_attestation() || ep_att {
let attestation_private_key = storage::attestation_private_key(env)?
.ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?;
let attestation_key =
@@ -1180,7 +1181,7 @@ impl CtapState {
versions.insert(0, String::from(U2F_VERSION_STRING))
}
let mut options = vec![];
if ENTERPRISE_ATTESTATION_MODE.is_some() {
if env.customization().enterprise_attestation_mode().is_some() {
options.push((String::from("ep"), storage::enterprise_attestation(env)?));
}
options.append(&mut vec![
@@ -1323,7 +1324,7 @@ impl CtapState {
#[cfg(feature = "with_ctap1")]
let need_certificate = true;
#[cfg(not(feature = "with_ctap1"))]
let need_certificate = USE_BATCH_ATTESTATION;
let need_certificate = env.customization().use_batch_attestation();
if (need_certificate && !(response.pkey_programmed && response.cert_programmed))
|| !env.firmware_protection().lock()
@@ -1510,7 +1511,7 @@ mod test {
],
0x03 => storage::aaguid(&mut env).unwrap(),
0x04 => cbor_map_options! {
"ep" => ENTERPRISE_ATTESTATION_MODE.map(|_| false),
"ep" => env.customization().enterprise_attestation_mode().map(|_| false),
"rk" => true,
"up" => true,
"alwaysUv" => false,