Enterprise attestation testing (#465)

* fix enterprise attestation check

* returns storage errors
This commit is contained in:
kaczmarczyck
2022-04-26 12:24:43 +02:00
committed by GitHub
parent 2b6424360c
commit 8dc6dab450
4 changed files with 163 additions and 9 deletions

View File

@@ -230,6 +230,7 @@ impl TryFrom<cbor::Value> for AuthenticatorMakeCredentialParameters {
let pin_uv_auth_protocol = pin_uv_auth_protocol
.map(PinUvAuthProtocol::try_from)
.transpose()?;
// We don't convert into EnterpriseAttestationMode to maintain the correct order of errors.
let enterprise_attestation = enterprise_attestation.map(extract_unsigned).transpose()?;
Ok(AuthenticatorMakeCredentialParameters {

View File

@@ -697,8 +697,8 @@ impl CtapState {
(
EnterpriseAttestationMode::PlatformManaged,
EnterpriseAttestationMode::PlatformManaged,
) => env.customization().is_enterprise_rp_id(&rp_id),
_ => true,
) => true,
_ => env.customization().is_enterprise_rp_id(&rp_id),
}
} else {
false
@@ -2048,6 +2048,138 @@ mod test {
);
}
fn check_ep(make_credential_response: Result<ResponseData, Ctap2StatusCode>, has_ep: bool) {
let ep_att = if has_ep { Some(true) } else { None };
match make_credential_response.unwrap() {
ResponseData::AuthenticatorMakeCredential(make_credential_response) => {
assert_eq!(make_credential_response.ep_att, ep_att);
}
_ => panic!("Invalid response type"),
}
}
#[test]
fn test_process_make_credential_with_enterprise_attestation_vendor_facilitated() {
let mut env = TestEnv::new();
env.customization_mut().enterprise_attestation_mode =
Some(EnterpriseAttestationMode::VendorFacilitated);
env.customization_mut().enterprise_rp_id_list = vec!["example.com".to_string()];
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
let mut key_bytes = [0; 32];
let private_key = crypto::ecdsa::SecKey::gensk(env.rng());
private_key.to_bytes(array_mut_ref!(key_bytes, 0, 32));
storage::set_attestation_certificate(&mut env, &[0xCC]).unwrap();
storage::set_attestation_private_key(&mut env, &key_bytes).unwrap();
storage::enable_enterprise_attestation(&mut env).unwrap();
let mut make_credential_params = create_minimal_make_credential_parameters();
make_credential_params.enterprise_attestation = Some(1);
make_credential_params.rp = PublicKeyCredentialRpEntity {
rp_id: "counter-example.com".to_string(),
rp_name: None,
rp_icon: None,
};
let make_credential_response =
ctap_state.process_make_credential(&mut env, make_credential_params, DUMMY_CHANNEL);
check_ep(make_credential_response, false);
let mut make_credential_params = create_minimal_make_credential_parameters();
make_credential_params.enterprise_attestation = Some(2);
make_credential_params.rp = PublicKeyCredentialRpEntity {
rp_id: "counter-example.com".to_string(),
rp_name: None,
rp_icon: None,
};
let make_credential_response =
ctap_state.process_make_credential(&mut env, make_credential_params, DUMMY_CHANNEL);
check_ep(make_credential_response, false);
let mut make_credential_params = create_minimal_make_credential_parameters();
make_credential_params.enterprise_attestation = Some(1);
let make_credential_response =
ctap_state.process_make_credential(&mut env, make_credential_params, DUMMY_CHANNEL);
check_ep(make_credential_response, true);
let mut make_credential_params = create_minimal_make_credential_parameters();
make_credential_params.enterprise_attestation = Some(2);
let make_credential_response =
ctap_state.process_make_credential(&mut env, make_credential_params, DUMMY_CHANNEL);
check_ep(make_credential_response, true);
}
#[test]
fn test_process_make_credential_with_enterprise_attestation_platform_managed() {
let mut env = TestEnv::new();
env.customization_mut().enterprise_attestation_mode =
Some(EnterpriseAttestationMode::PlatformManaged);
env.customization_mut().enterprise_rp_id_list = vec!["example.com".to_string()];
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
let mut key_bytes = [0; 32];
let private_key = crypto::ecdsa::SecKey::gensk(env.rng());
private_key.to_bytes(array_mut_ref!(key_bytes, 0, 32));
storage::set_attestation_certificate(&mut env, &[0xCC]).unwrap();
storage::set_attestation_private_key(&mut env, &key_bytes).unwrap();
storage::enable_enterprise_attestation(&mut env).unwrap();
let mut make_credential_params = create_minimal_make_credential_parameters();
make_credential_params.enterprise_attestation = Some(1);
make_credential_params.rp = PublicKeyCredentialRpEntity {
rp_id: "counter-example.com".to_string(),
rp_name: None,
rp_icon: None,
};
let make_credential_response =
ctap_state.process_make_credential(&mut env, make_credential_params, DUMMY_CHANNEL);
check_ep(make_credential_response, false);
let mut make_credential_params = create_minimal_make_credential_parameters();
make_credential_params.enterprise_attestation = Some(1);
let make_credential_response =
ctap_state.process_make_credential(&mut env, make_credential_params, DUMMY_CHANNEL);
check_ep(make_credential_response, true);
let mut make_credential_params = create_minimal_make_credential_parameters();
make_credential_params.enterprise_attestation = Some(2);
let make_credential_response =
ctap_state.process_make_credential(&mut env, make_credential_params, DUMMY_CHANNEL);
check_ep(make_credential_response, true);
}
#[test]
fn test_process_make_credential_with_enterprise_attestation_invalid() {
let mut env = TestEnv::new();
env.customization_mut().enterprise_attestation_mode =
Some(EnterpriseAttestationMode::PlatformManaged);
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
let mut make_credential_params = create_minimal_make_credential_parameters();
make_credential_params.enterprise_attestation = Some(2);
let make_credential_response =
ctap_state.process_make_credential(&mut env, make_credential_params, DUMMY_CHANNEL);
assert_eq!(
make_credential_response,
Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER)
);
let mut key_bytes = [0; 32];
let private_key = crypto::ecdsa::SecKey::gensk(env.rng());
private_key.to_bytes(array_mut_ref!(key_bytes, 0, 32));
storage::set_attestation_certificate(&mut env, &[0xCC]).unwrap();
storage::set_attestation_private_key(&mut env, &key_bytes).unwrap();
storage::enable_enterprise_attestation(&mut env).unwrap();
let mut make_credential_params = create_minimal_make_credential_parameters();
make_credential_params.enterprise_attestation = Some(3);
let make_credential_response =
ctap_state.process_make_credential(&mut env, make_credential_params, DUMMY_CHANNEL);
assert_eq!(
make_credential_response,
Err(Ctap2StatusCode::CTAP2_ERR_INVALID_OPTION)
);
}
#[test]
fn test_process_make_credential_cancelled() {
let mut env = TestEnv::new();

View File

@@ -577,6 +577,9 @@ pub fn enterprise_attestation(env: &mut impl Env) -> Result<bool, Ctap2StatusCod
/// Marks enterprise attestation as enabled.
pub fn enable_enterprise_attestation(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
if attestation_private_key(env)?.is_none() || attestation_certificate(env)?.is_none() {
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
}
if !enterprise_attestation(env)? {
env.store().insert(key::ENTERPRISE_ATTESTATION, &[])?;
}
@@ -1079,8 +1082,8 @@ mod test {
init(&mut env).unwrap();
// Make sure the attestation are absent. There is no batch attestation in tests.
assert!(attestation_private_key(&mut env,).unwrap().is_none());
assert!(attestation_certificate(&mut env,).unwrap().is_none());
assert!(attestation_private_key(&mut env).unwrap().is_none());
assert!(attestation_certificate(&mut env).unwrap().is_none());
// Make sure the persistent keys are initialized to dummy values.
let dummy_key = [0x41u8; key_material::ATTESTATION_PRIVATE_KEY_LENGTH];
@@ -1233,6 +1236,18 @@ mod test {
fn test_enterprise_attestation() {
let mut env = TestEnv::new();
assert!(!enterprise_attestation(&mut env).unwrap());
assert_eq!(
enable_enterprise_attestation(&mut env),
Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)
);
assert!(!enterprise_attestation(&mut env).unwrap());
let dummy_key = [0x41u8; key_material::ATTESTATION_PRIVATE_KEY_LENGTH];
let dummy_cert = [0xddu8; 20];
set_attestation_private_key(&mut env, &dummy_key).unwrap();
set_attestation_certificate(&mut env, &dummy_cert).unwrap();
assert!(!enterprise_attestation(&mut env).unwrap());
assert_eq!(enable_enterprise_attestation(&mut env), Ok(()));
assert!(enterprise_attestation(&mut env).unwrap());