renames PIN protocol related variables to prepare PIN protocol v2 (#291)

This commit is contained in:
kaczmarczyck
2021-03-04 10:37:19 +01:00
committed by GitHub
parent 5e9c32dff5
commit 351e6c12c6
7 changed files with 246 additions and 320 deletions

View File

@@ -166,7 +166,7 @@ pub enum PinPermission {
AuthenticatorConfiguration = 0x20, AuthenticatorConfiguration = 0x20,
} }
pub struct PinProtocolV1 { pub struct ClientPin {
key_agreement_key: crypto::ecdh::SecKey, key_agreement_key: crypto::ecdh::SecKey,
pin_uv_auth_token: [u8; PIN_TOKEN_LENGTH], pin_uv_auth_token: [u8; PIN_TOKEN_LENGTH],
consecutive_pin_mismatches: u8, consecutive_pin_mismatches: u8,
@@ -174,11 +174,11 @@ pub struct PinProtocolV1 {
permissions_rp_id: Option<String>, permissions_rp_id: Option<String>,
} }
impl PinProtocolV1 { impl ClientPin {
pub fn new(rng: &mut impl Rng256) -> PinProtocolV1 { pub fn new(rng: &mut impl Rng256) -> ClientPin {
let key_agreement_key = crypto::ecdh::SecKey::gensk(rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(rng);
let pin_uv_auth_token = rng.gen_uniform_u8x32(); let pin_uv_auth_token = rng.gen_uniform_u8x32();
PinProtocolV1 { ClientPin {
key_agreement_key, key_agreement_key,
pin_uv_auth_token, pin_uv_auth_token,
consecutive_pin_mismatches: 0, consecutive_pin_mismatches: 0,
@@ -395,14 +395,14 @@ impl PinProtocolV1 {
Ok(response) Ok(response)
} }
pub fn process_subcommand( pub fn process_command(
&mut self, &mut self,
rng: &mut impl Rng256, rng: &mut impl Rng256,
persistent_store: &mut PersistentStore, persistent_store: &mut PersistentStore,
client_pin_params: AuthenticatorClientPinParameters, client_pin_params: AuthenticatorClientPinParameters,
) -> Result<ResponseData, Ctap2StatusCode> { ) -> Result<ResponseData, Ctap2StatusCode> {
let AuthenticatorClientPinParameters { let AuthenticatorClientPinParameters {
pin_protocol, pin_uv_auth_protocol,
sub_command, sub_command,
key_agreement, key_agreement,
pin_auth, pin_auth,
@@ -412,7 +412,7 @@ impl PinProtocolV1 {
permissions_rp_id, permissions_rp_id,
} = client_pin_params; } = client_pin_params;
if pin_protocol != 1 { if pin_uv_auth_protocol != 1 {
return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER); return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER);
} }
@@ -558,8 +558,8 @@ impl PinProtocolV1 {
pub fn new_test( pub fn new_test(
key_agreement_key: crypto::ecdh::SecKey, key_agreement_key: crypto::ecdh::SecKey,
pin_uv_auth_token: [u8; PIN_TOKEN_LENGTH], pin_uv_auth_token: [u8; PIN_TOKEN_LENGTH],
) -> PinProtocolV1 { ) -> ClientPin {
PinProtocolV1 { ClientPin {
key_agreement_key, key_agreement_key,
pin_uv_auth_token, pin_uv_auth_token,
consecutive_pin_mismatches: 0, consecutive_pin_mismatches: 0,
@@ -647,13 +647,13 @@ mod test {
let aes_enc_key = crypto::aes256::EncryptionKey::new(&shared_secret); let aes_enc_key = crypto::aes256::EncryptionKey::new(&shared_secret);
let aes_dec_key = crypto::aes256::DecryptionKey::new(&aes_enc_key); let aes_dec_key = crypto::aes256::DecryptionKey::new(&aes_enc_key);
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
let pin_hash_enc = vec![ let pin_hash_enc = vec![
0x8D, 0x7A, 0xA3, 0x9F, 0x7F, 0xC6, 0x08, 0x13, 0x9A, 0xC8, 0x56, 0x97, 0x70, 0x74, 0x8D, 0x7A, 0xA3, 0x9F, 0x7F, 0xC6, 0x08, 0x13, 0x9A, 0xC8, 0x56, 0x97, 0x70, 0x74,
0x99, 0x66, 0x99, 0x66,
]; ];
assert_eq!( assert_eq!(
pin_protocol_v1.verify_pin_hash_enc( client_pin.verify_pin_hash_enc(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
&aes_dec_key, &aes_dec_key,
@@ -664,7 +664,7 @@ mod test {
let pin_hash_enc = vec![0xEE; 16]; let pin_hash_enc = vec![0xEE; 16];
assert_eq!( assert_eq!(
pin_protocol_v1.verify_pin_hash_enc( client_pin.verify_pin_hash_enc(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
&aes_dec_key, &aes_dec_key,
@@ -677,9 +677,9 @@ mod test {
0x8D, 0x7A, 0xA3, 0x9F, 0x7F, 0xC6, 0x08, 0x13, 0x9A, 0xC8, 0x56, 0x97, 0x70, 0x74, 0x8D, 0x7A, 0xA3, 0x9F, 0x7F, 0xC6, 0x08, 0x13, 0x9A, 0xC8, 0x56, 0x97, 0x70, 0x74,
0x99, 0x66, 0x99, 0x66,
]; ];
pin_protocol_v1.consecutive_pin_mismatches = 3; client_pin.consecutive_pin_mismatches = 3;
assert_eq!( assert_eq!(
pin_protocol_v1.verify_pin_hash_enc( client_pin.verify_pin_hash_enc(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
&aes_dec_key, &aes_dec_key,
@@ -687,11 +687,11 @@ mod test {
), ),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_BLOCKED) Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_BLOCKED)
); );
pin_protocol_v1.consecutive_pin_mismatches = 0; client_pin.consecutive_pin_mismatches = 0;
let pin_hash_enc = vec![0x77; PIN_AUTH_LENGTH - 1]; let pin_hash_enc = vec![0x77; PIN_AUTH_LENGTH - 1];
assert_eq!( assert_eq!(
pin_protocol_v1.verify_pin_hash_enc( client_pin.verify_pin_hash_enc(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
&aes_dec_key, &aes_dec_key,
@@ -702,7 +702,7 @@ mod test {
let pin_hash_enc = vec![0x77; PIN_AUTH_LENGTH + 1]; let pin_hash_enc = vec![0x77; PIN_AUTH_LENGTH + 1];
assert_eq!( assert_eq!(
pin_protocol_v1.verify_pin_hash_enc( client_pin.verify_pin_hash_enc(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
&aes_dec_key, &aes_dec_key,
@@ -716,14 +716,14 @@ mod test {
fn test_process_get_pin_retries() { fn test_process_get_pin_retries() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let persistent_store = PersistentStore::new(&mut rng); let persistent_store = PersistentStore::new(&mut rng);
let pin_protocol_v1 = PinProtocolV1::new(&mut rng); let client_pin = ClientPin::new(&mut rng);
let expected_response = Ok(AuthenticatorClientPinResponse { let expected_response = Ok(AuthenticatorClientPinResponse {
key_agreement: None, key_agreement: None,
pin_token: None, pin_token: None,
retries: Some(persistent_store.pin_retries().unwrap() as u64), retries: Some(persistent_store.pin_retries().unwrap() as u64),
}); });
assert_eq!( assert_eq!(
pin_protocol_v1.process_get_pin_retries(&persistent_store), client_pin.process_get_pin_retries(&persistent_store),
expected_response expected_response
); );
} }
@@ -731,36 +731,28 @@ mod test {
#[test] #[test]
fn test_process_get_key_agreement() { fn test_process_get_key_agreement() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let pin_protocol_v1 = PinProtocolV1::new(&mut rng); let client_pin = ClientPin::new(&mut rng);
let pk = pin_protocol_v1.key_agreement_key.genpk(); let pk = client_pin.key_agreement_key.genpk();
let expected_response = Ok(AuthenticatorClientPinResponse { let expected_response = Ok(AuthenticatorClientPinResponse {
key_agreement: Some(CoseKey::from(pk)), key_agreement: Some(CoseKey::from(pk)),
pin_token: None, pin_token: None,
retries: None, retries: None,
}); });
assert_eq!( assert_eq!(client_pin.process_get_key_agreement(), expected_response);
pin_protocol_v1.process_get_key_agreement(),
expected_response
);
} }
#[test] #[test]
fn test_process_set_pin() { fn test_process_set_pin() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
let pk = pin_protocol_v1.key_agreement_key.genpk(); let pk = client_pin.key_agreement_key.genpk();
let shared_secret = pin_protocol_v1.key_agreement_key.exchange_x_sha256(&pk); let shared_secret = client_pin.key_agreement_key.exchange_x_sha256(&pk);
let key_agreement = CoseKey::from(pk); let key_agreement = CoseKey::from(pk);
let new_pin_enc = encrypt_standard_pin(&shared_secret); let new_pin_enc = encrypt_standard_pin(&shared_secret);
let pin_auth = hmac_256::<Sha256>(&shared_secret, &new_pin_enc[..])[..16].to_vec(); let pin_auth = hmac_256::<Sha256>(&shared_secret, &new_pin_enc[..])[..16].to_vec();
assert_eq!( assert_eq!(
pin_protocol_v1.process_set_pin( client_pin.process_set_pin(&mut persistent_store, key_agreement, pin_auth, new_pin_enc),
&mut persistent_store,
key_agreement,
pin_auth,
new_pin_enc
),
Ok(()) Ok(())
); );
} }
@@ -770,9 +762,9 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
set_standard_pin(&mut persistent_store); set_standard_pin(&mut persistent_store);
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
let pk = pin_protocol_v1.key_agreement_key.genpk(); let pk = client_pin.key_agreement_key.genpk();
let shared_secret = pin_protocol_v1.key_agreement_key.exchange_x_sha256(&pk); let shared_secret = client_pin.key_agreement_key.exchange_x_sha256(&pk);
let key_agreement = CoseKey::from(pk); let key_agreement = CoseKey::from(pk);
let new_pin_enc = encrypt_standard_pin(&shared_secret); let new_pin_enc = encrypt_standard_pin(&shared_secret);
let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret); let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret);
@@ -780,7 +772,7 @@ mod test {
auth_param_data.extend(&pin_hash_enc); auth_param_data.extend(&pin_hash_enc);
let pin_auth = hmac_256::<Sha256>(&shared_secret, &auth_param_data[..])[..16].to_vec(); let pin_auth = hmac_256::<Sha256>(&shared_secret, &auth_param_data[..])[..16].to_vec();
assert_eq!( assert_eq!(
pin_protocol_v1.process_change_pin( client_pin.process_change_pin(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
key_agreement.clone(), key_agreement.clone(),
@@ -793,7 +785,7 @@ mod test {
let bad_pin_hash_enc = vec![0xEE; 16]; let bad_pin_hash_enc = vec![0xEE; 16];
assert_eq!( assert_eq!(
pin_protocol_v1.process_change_pin( client_pin.process_change_pin(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
key_agreement.clone(), key_agreement.clone(),
@@ -808,7 +800,7 @@ mod test {
persistent_store.decr_pin_retries().unwrap(); persistent_store.decr_pin_retries().unwrap();
} }
assert_eq!( assert_eq!(
pin_protocol_v1.process_change_pin( client_pin.process_change_pin(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
key_agreement, key_agreement,
@@ -825,12 +817,12 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
set_standard_pin(&mut persistent_store); set_standard_pin(&mut persistent_store);
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
let pk = pin_protocol_v1.key_agreement_key.genpk(); let pk = client_pin.key_agreement_key.genpk();
let shared_secret = pin_protocol_v1.key_agreement_key.exchange_x_sha256(&pk); let shared_secret = client_pin.key_agreement_key.exchange_x_sha256(&pk);
let key_agreement = CoseKey::from(pk); let key_agreement = CoseKey::from(pk);
let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret); let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret);
assert!(pin_protocol_v1 assert!(client_pin
.process_get_pin_token( .process_get_pin_token(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
@@ -841,7 +833,7 @@ mod test {
let pin_hash_enc = vec![0xEE; 16]; let pin_hash_enc = vec![0xEE; 16];
assert_eq!( assert_eq!(
pin_protocol_v1.process_get_pin_token( client_pin.process_get_pin_token(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
key_agreement, key_agreement,
@@ -857,13 +849,13 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
set_standard_pin(&mut persistent_store); set_standard_pin(&mut persistent_store);
assert_eq!(persistent_store.force_pin_change(), Ok(())); assert_eq!(persistent_store.force_pin_change(), Ok(()));
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
let pk = pin_protocol_v1.key_agreement_key.genpk(); let pk = client_pin.key_agreement_key.genpk();
let shared_secret = pin_protocol_v1.key_agreement_key.exchange_x_sha256(&pk); let shared_secret = client_pin.key_agreement_key.exchange_x_sha256(&pk);
let key_agreement = CoseKey::from(pk); let key_agreement = CoseKey::from(pk);
let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret); let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret);
assert_eq!( assert_eq!(
pin_protocol_v1.process_get_pin_token( client_pin.process_get_pin_token(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
key_agreement, key_agreement,
@@ -878,12 +870,12 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
set_standard_pin(&mut persistent_store); set_standard_pin(&mut persistent_store);
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
let pk = pin_protocol_v1.key_agreement_key.genpk(); let pk = client_pin.key_agreement_key.genpk();
let shared_secret = pin_protocol_v1.key_agreement_key.exchange_x_sha256(&pk); let shared_secret = client_pin.key_agreement_key.exchange_x_sha256(&pk);
let key_agreement = CoseKey::from(pk); let key_agreement = CoseKey::from(pk);
let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret); let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret);
assert!(pin_protocol_v1 assert!(client_pin
.process_get_pin_uv_auth_token_using_pin_with_permissions( .process_get_pin_uv_auth_token_using_pin_with_permissions(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
@@ -893,14 +885,14 @@ mod test {
Some(String::from("example.com")), Some(String::from("example.com")),
) )
.is_ok()); .is_ok());
assert_eq!(pin_protocol_v1.permissions, 0x03); assert_eq!(client_pin.permissions, 0x03);
assert_eq!( assert_eq!(
pin_protocol_v1.permissions_rp_id, client_pin.permissions_rp_id,
Some(String::from("example.com")) Some(String::from("example.com"))
); );
assert_eq!( assert_eq!(
pin_protocol_v1.process_get_pin_uv_auth_token_using_pin_with_permissions( client_pin.process_get_pin_uv_auth_token_using_pin_with_permissions(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
key_agreement.clone(), key_agreement.clone(),
@@ -912,7 +904,7 @@ mod test {
); );
assert_eq!( assert_eq!(
pin_protocol_v1.process_get_pin_uv_auth_token_using_pin_with_permissions( client_pin.process_get_pin_uv_auth_token_using_pin_with_permissions(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
key_agreement.clone(), key_agreement.clone(),
@@ -925,7 +917,7 @@ mod test {
let pin_hash_enc = vec![0xEE; 16]; let pin_hash_enc = vec![0xEE; 16];
assert_eq!( assert_eq!(
pin_protocol_v1.process_get_pin_uv_auth_token_using_pin_with_permissions( client_pin.process_get_pin_uv_auth_token_using_pin_with_permissions(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
key_agreement, key_agreement,
@@ -943,13 +935,13 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
set_standard_pin(&mut persistent_store); set_standard_pin(&mut persistent_store);
assert_eq!(persistent_store.force_pin_change(), Ok(())); assert_eq!(persistent_store.force_pin_change(), Ok(()));
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
let pk = pin_protocol_v1.key_agreement_key.genpk(); let pk = client_pin.key_agreement_key.genpk();
let shared_secret = pin_protocol_v1.key_agreement_key.exchange_x_sha256(&pk); let shared_secret = client_pin.key_agreement_key.exchange_x_sha256(&pk);
let key_agreement = CoseKey::from(pk); let key_agreement = CoseKey::from(pk);
let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret); let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret);
assert_eq!( assert_eq!(
pin_protocol_v1.process_get_pin_uv_auth_token_using_pin_with_permissions( client_pin.process_get_pin_uv_auth_token_using_pin_with_permissions(
&mut rng, &mut rng,
&mut persistent_store, &mut persistent_store,
key_agreement, key_agreement,
@@ -965,9 +957,9 @@ mod test {
fn test_process() { fn test_process() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
let client_pin_params = AuthenticatorClientPinParameters { let client_pin_params = AuthenticatorClientPinParameters {
pin_protocol: 1, pin_uv_auth_protocol: 1,
sub_command: ClientPinSubCommand::GetPinRetries, sub_command: ClientPinSubCommand::GetPinRetries,
key_agreement: None, key_agreement: None,
pin_auth: None, pin_auth: None,
@@ -976,12 +968,12 @@ mod test {
permissions: None, permissions: None,
permissions_rp_id: None, permissions_rp_id: None,
}; };
assert!(pin_protocol_v1 assert!(client_pin
.process_subcommand(&mut rng, &mut persistent_store, client_pin_params) .process_command(&mut rng, &mut persistent_store, client_pin_params)
.is_ok()); .is_ok());
let client_pin_params = AuthenticatorClientPinParameters { let client_pin_params = AuthenticatorClientPinParameters {
pin_protocol: 2, pin_uv_auth_protocol: 2,
sub_command: ClientPinSubCommand::GetPinRetries, sub_command: ClientPinSubCommand::GetPinRetries,
key_agreement: None, key_agreement: None,
pin_auth: None, pin_auth: None,
@@ -992,7 +984,7 @@ mod test {
}; };
let error_code = Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER; let error_code = Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER;
assert_eq!( assert_eq!(
pin_protocol_v1.process_subcommand(&mut rng, &mut persistent_store, client_pin_params), client_pin.process_command(&mut rng, &mut persistent_store, client_pin_params),
Err(error_code) Err(error_code)
); );
} }
@@ -1161,15 +1153,15 @@ mod test {
#[test] #[test]
fn test_has_permission() { fn test_has_permission() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
pin_protocol_v1.permissions = 0x7F; client_pin.permissions = 0x7F;
for permission in PinPermission::into_enum_iter() { for permission in PinPermission::into_enum_iter() {
assert_eq!(pin_protocol_v1.has_permission(permission), Ok(())); assert_eq!(client_pin.has_permission(permission), Ok(()));
} }
pin_protocol_v1.permissions = 0x00; client_pin.permissions = 0x00;
for permission in PinPermission::into_enum_iter() { for permission in PinPermission::into_enum_iter() {
assert_eq!( assert_eq!(
pin_protocol_v1.has_permission(permission), client_pin.has_permission(permission),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID) Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
); );
} }
@@ -1178,12 +1170,12 @@ mod test {
#[test] #[test]
fn test_has_no_rp_id_permission() { fn test_has_no_rp_id_permission() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
assert_eq!(pin_protocol_v1.has_no_rp_id_permission(), Ok(())); assert_eq!(client_pin.has_no_rp_id_permission(), Ok(()));
assert_eq!(pin_protocol_v1.permissions_rp_id, None); assert_eq!(client_pin.permissions_rp_id, None);
pin_protocol_v1.permissions_rp_id = Some("example.com".to_string()); client_pin.permissions_rp_id = Some("example.com".to_string());
assert_eq!( assert_eq!(
pin_protocol_v1.has_no_rp_id_permission(), client_pin.has_no_rp_id_permission(),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID) Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
); );
} }
@@ -1191,19 +1183,13 @@ mod test {
#[test] #[test]
fn test_has_no_or_rp_id_permission() { fn test_has_no_or_rp_id_permission() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
assert_eq!(client_pin.has_no_or_rp_id_permission("example.com"), Ok(()));
assert_eq!(client_pin.permissions_rp_id, None);
client_pin.permissions_rp_id = Some("example.com".to_string());
assert_eq!(client_pin.has_no_or_rp_id_permission("example.com"), Ok(()));
assert_eq!( assert_eq!(
pin_protocol_v1.has_no_or_rp_id_permission("example.com"), client_pin.has_no_or_rp_id_permission("another.example.com"),
Ok(())
);
assert_eq!(pin_protocol_v1.permissions_rp_id, None);
pin_protocol_v1.permissions_rp_id = Some("example.com".to_string());
assert_eq!(
pin_protocol_v1.has_no_or_rp_id_permission("example.com"),
Ok(())
);
assert_eq!(
pin_protocol_v1.has_no_or_rp_id_permission("another.example.com"),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID) Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
); );
} }
@@ -1211,20 +1197,20 @@ mod test {
#[test] #[test]
fn test_has_no_or_rp_id_hash_permission() { fn test_has_no_or_rp_id_hash_permission() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
let rp_id_hash = Sha256::hash(b"example.com"); let rp_id_hash = Sha256::hash(b"example.com");
assert_eq!( assert_eq!(
pin_protocol_v1.has_no_or_rp_id_hash_permission(&rp_id_hash), client_pin.has_no_or_rp_id_hash_permission(&rp_id_hash),
Ok(()) Ok(())
); );
assert_eq!(pin_protocol_v1.permissions_rp_id, None); assert_eq!(client_pin.permissions_rp_id, None);
pin_protocol_v1.permissions_rp_id = Some("example.com".to_string()); client_pin.permissions_rp_id = Some("example.com".to_string());
assert_eq!( assert_eq!(
pin_protocol_v1.has_no_or_rp_id_hash_permission(&rp_id_hash), client_pin.has_no_or_rp_id_hash_permission(&rp_id_hash),
Ok(()) Ok(())
); );
assert_eq!( assert_eq!(
pin_protocol_v1.has_no_or_rp_id_hash_permission(&[0x4A; 32]), client_pin.has_no_or_rp_id_hash_permission(&[0x4A; 32]),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID) Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
); );
} }
@@ -1232,21 +1218,15 @@ mod test {
#[test] #[test]
fn test_ensure_rp_id_permission() { fn test_ensure_rp_id_permission() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng); let mut client_pin = ClientPin::new(&mut rng);
assert_eq!(client_pin.ensure_rp_id_permission("example.com"), Ok(()));
assert_eq!( assert_eq!(
pin_protocol_v1.ensure_rp_id_permission("example.com"), client_pin.permissions_rp_id,
Ok(())
);
assert_eq!(
pin_protocol_v1.permissions_rp_id,
Some(String::from("example.com")) Some(String::from("example.com"))
); );
assert_eq!(client_pin.ensure_rp_id_permission("example.com"), Ok(()));
assert_eq!( assert_eq!(
pin_protocol_v1.ensure_rp_id_permission("example.com"), client_pin.ensure_rp_id_permission("counter-example.com"),
Ok(())
);
assert_eq!(
pin_protocol_v1.ensure_rp_id_permission("counter-example.com"),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID) Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
); );
} }

View File

@@ -304,7 +304,7 @@ impl TryFrom<cbor::Value> for AuthenticatorGetAssertionParameters {
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct AuthenticatorClientPinParameters { pub struct AuthenticatorClientPinParameters {
pub pin_protocol: u64, pub pin_uv_auth_protocol: u64,
pub sub_command: ClientPinSubCommand, pub sub_command: ClientPinSubCommand,
pub key_agreement: Option<CoseKey>, pub key_agreement: Option<CoseKey>,
pub pin_auth: Option<Vec<u8>>, pub pin_auth: Option<Vec<u8>>,
@@ -320,7 +320,7 @@ impl TryFrom<cbor::Value> for AuthenticatorClientPinParameters {
fn try_from(cbor_value: cbor::Value) -> Result<Self, Ctap2StatusCode> { fn try_from(cbor_value: cbor::Value) -> Result<Self, Ctap2StatusCode> {
destructure_cbor_map! { destructure_cbor_map! {
let { let {
0x01 => pin_protocol, 0x01 => pin_uv_auth_protocol,
0x02 => sub_command, 0x02 => sub_command,
0x03 => key_agreement, 0x03 => key_agreement,
0x04 => pin_auth, 0x04 => pin_auth,
@@ -331,7 +331,7 @@ impl TryFrom<cbor::Value> for AuthenticatorClientPinParameters {
} = extract_map(cbor_value)?; } = extract_map(cbor_value)?;
} }
let pin_protocol = extract_unsigned(ok_or_missing(pin_protocol)?)?; let pin_uv_auth_protocol = extract_unsigned(ok_or_missing(pin_uv_auth_protocol)?)?;
let sub_command = ClientPinSubCommand::try_from(ok_or_missing(sub_command)?)?; let sub_command = ClientPinSubCommand::try_from(ok_or_missing(sub_command)?)?;
let key_agreement = key_agreement.map(CoseKey::try_from).transpose()?; let key_agreement = key_agreement.map(CoseKey::try_from).transpose()?;
let pin_auth = pin_auth.map(extract_byte_string).transpose()?; let pin_auth = pin_auth.map(extract_byte_string).transpose()?;
@@ -346,7 +346,7 @@ impl TryFrom<cbor::Value> for AuthenticatorClientPinParameters {
let permissions_rp_id = permissions_rp_id.map(extract_text_string).transpose()?; let permissions_rp_id = permissions_rp_id.map(extract_text_string).transpose()?;
Ok(AuthenticatorClientPinParameters { Ok(AuthenticatorClientPinParameters {
pin_protocol, pin_uv_auth_protocol,
sub_command, sub_command,
key_agreement, key_agreement,
pin_auth, pin_auth,
@@ -506,7 +506,7 @@ impl TryFrom<cbor::Value> for AuthenticatorAttestationMaterial {
pub struct AuthenticatorCredentialManagementParameters { pub struct AuthenticatorCredentialManagementParameters {
pub sub_command: CredentialManagementSubCommand, pub sub_command: CredentialManagementSubCommand,
pub sub_command_params: Option<CredentialManagementSubCommandParameters>, pub sub_command_params: Option<CredentialManagementSubCommandParameters>,
pub pin_protocol: Option<u64>, pub pin_uv_auth_protocol: Option<u64>,
pub pin_auth: Option<Vec<u8>>, pub pin_auth: Option<Vec<u8>>,
} }
@@ -518,7 +518,7 @@ impl TryFrom<cbor::Value> for AuthenticatorCredentialManagementParameters {
let { let {
0x01 => sub_command, 0x01 => sub_command,
0x02 => sub_command_params, 0x02 => sub_command_params,
0x03 => pin_protocol, 0x03 => pin_uv_auth_protocol,
0x04 => pin_auth, 0x04 => pin_auth,
} = extract_map(cbor_value)?; } = extract_map(cbor_value)?;
} }
@@ -527,13 +527,13 @@ impl TryFrom<cbor::Value> for AuthenticatorCredentialManagementParameters {
let sub_command_params = sub_command_params let sub_command_params = sub_command_params
.map(CredentialManagementSubCommandParameters::try_from) .map(CredentialManagementSubCommandParameters::try_from)
.transpose()?; .transpose()?;
let pin_protocol = pin_protocol.map(extract_unsigned).transpose()?; let pin_uv_auth_protocol = pin_uv_auth_protocol.map(extract_unsigned).transpose()?;
let pin_auth = pin_auth.map(extract_byte_string).transpose()?; let pin_auth = pin_auth.map(extract_byte_string).transpose()?;
Ok(AuthenticatorCredentialManagementParameters { Ok(AuthenticatorCredentialManagementParameters {
sub_command, sub_command,
sub_command_params, sub_command_params,
pin_protocol, pin_uv_auth_protocol,
pin_auth, pin_auth,
}) })
} }
@@ -706,7 +706,7 @@ mod test {
AuthenticatorClientPinParameters::try_from(cbor_value).unwrap(); AuthenticatorClientPinParameters::try_from(cbor_value).unwrap();
let expected_client_pin_parameters = AuthenticatorClientPinParameters { let expected_client_pin_parameters = AuthenticatorClientPinParameters {
pin_protocol: 1, pin_uv_auth_protocol: 1,
sub_command: ClientPinSubCommand::GetPinRetries, sub_command: ClientPinSubCommand::GetPinRetries,
key_agreement: Some(cose_key), key_agreement: Some(cose_key),
pin_auth: Some(vec![0xBB]), pin_auth: Some(vec![0xBB]),
@@ -765,7 +765,7 @@ mod test {
let expected_cred_management_parameters = AuthenticatorCredentialManagementParameters { let expected_cred_management_parameters = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::EnumerateCredentialsBegin, sub_command: CredentialManagementSubCommand::EnumerateCredentialsBegin,
sub_command_params: Some(params), sub_command_params: Some(params),
pin_protocol: Some(1), pin_uv_auth_protocol: Some(1),
pin_auth: Some(vec![0x9A; 16]), pin_auth: Some(vec![0x9A; 16]),
}; };

View File

@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::client_pin::ClientPin;
use super::command::AuthenticatorConfigParameters; use super::command::AuthenticatorConfigParameters;
use super::data_formats::{ConfigSubCommand, ConfigSubCommandParams, SetMinPinLengthParams}; use super::data_formats::{ConfigSubCommand, ConfigSubCommandParams, SetMinPinLengthParams};
use super::pin_protocol_v1::PinProtocolV1;
use super::response::ResponseData; use super::response::ResponseData;
use super::status_code::Ctap2StatusCode; use super::status_code::Ctap2StatusCode;
use super::storage::PersistentStore; use super::storage::PersistentStore;
@@ -76,7 +76,7 @@ fn process_set_min_pin_length(
/// Processes the AuthenticatorConfig command. /// Processes the AuthenticatorConfig command.
pub fn process_config( pub fn process_config(
persistent_store: &mut PersistentStore, persistent_store: &mut PersistentStore,
pin_protocol_v1: &mut PinProtocolV1, client_pin: &mut ClientPin,
params: AuthenticatorConfigParameters, params: AuthenticatorConfigParameters,
) -> Result<ResponseData, Ctap2StatusCode> { ) -> Result<ResponseData, Ctap2StatusCode> {
let AuthenticatorConfigParameters { let AuthenticatorConfigParameters {
@@ -103,7 +103,7 @@ pub fn process_config(
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR); return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
} }
} }
if !pin_protocol_v1.verify_pin_auth_token(&config_data, &auth_param) { if !client_pin.verify_pin_auth_token(&config_data, &auth_param) {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID);
} }
} }
@@ -136,7 +136,7 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let config_params = AuthenticatorConfigParameters { let config_params = AuthenticatorConfigParameters {
sub_command: ConfigSubCommand::EnableEnterpriseAttestation, sub_command: ConfigSubCommand::EnableEnterpriseAttestation,
@@ -144,8 +144,7 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
if ENTERPRISE_ATTESTATION_MODE.is_some() { if ENTERPRISE_ATTESTATION_MODE.is_some() {
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig)); assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
@@ -164,7 +163,7 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let config_params = AuthenticatorConfigParameters { let config_params = AuthenticatorConfigParameters {
sub_command: ConfigSubCommand::ToggleAlwaysUv, sub_command: ConfigSubCommand::ToggleAlwaysUv,
@@ -172,8 +171,7 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig)); assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
assert!(persistent_store.has_always_uv().unwrap()); assert!(persistent_store.has_always_uv().unwrap());
@@ -183,8 +181,7 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
if ENFORCE_ALWAYS_UV { if ENFORCE_ALWAYS_UV {
assert_eq!( assert_eq!(
config_response, config_response,
@@ -202,7 +199,7 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
persistent_store.set_pin(&[0x88; 16], 4).unwrap(); persistent_store.set_pin(&[0x88; 16], 4).unwrap();
let pin_uv_auth_param = Some(vec![ let pin_uv_auth_param = Some(vec![
@@ -215,8 +212,7 @@ mod test {
pin_uv_auth_param: pin_uv_auth_param.clone(), pin_uv_auth_param: pin_uv_auth_param.clone(),
pin_uv_auth_protocol: Some(1), pin_uv_auth_protocol: Some(1),
}; };
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
if ENFORCE_ALWAYS_UV { if ENFORCE_ALWAYS_UV {
assert_eq!( assert_eq!(
config_response, config_response,
@@ -233,8 +229,7 @@ mod test {
pin_uv_auth_param, pin_uv_auth_param,
pin_uv_auth_protocol: Some(1), pin_uv_auth_protocol: Some(1),
}; };
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig)); assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
assert!(!persistent_store.has_always_uv().unwrap()); assert!(!persistent_store.has_always_uv().unwrap());
} }
@@ -264,13 +259,12 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
// First, increase minimum PIN length from 4 to 6 without PIN auth. // First, increase minimum PIN length from 4 to 6 without PIN auth.
let min_pin_length = 6; let min_pin_length = 6;
let config_params = create_min_pin_config_params(min_pin_length, None); let config_params = create_min_pin_config_params(min_pin_length, None);
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig)); assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length)); assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length));
@@ -284,8 +278,7 @@ mod test {
0xB2, 0xDE, 0xB2, 0xDE,
]; ];
config_params.pin_uv_auth_param = Some(pin_auth); config_params.pin_uv_auth_param = Some(pin_auth);
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig)); assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length)); assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length));
@@ -296,8 +289,7 @@ mod test {
0xA7, 0x71, 0xA7, 0x71,
]; ];
config_params.pin_uv_auth_param = Some(pin_auth); config_params.pin_uv_auth_param = Some(pin_auth);
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
assert_eq!( assert_eq!(
config_response, config_response,
Err(Ctap2StatusCode::CTAP2_ERR_PIN_POLICY_VIOLATION) Err(Ctap2StatusCode::CTAP2_ERR_PIN_POLICY_VIOLATION)
@@ -311,15 +303,14 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
// First, set RP IDs without PIN auth. // First, set RP IDs without PIN auth.
let min_pin_length = 6; let min_pin_length = 6;
let min_pin_length_rp_ids = vec!["example.com".to_string()]; let min_pin_length_rp_ids = vec!["example.com".to_string()];
let config_params = let config_params =
create_min_pin_config_params(min_pin_length, Some(min_pin_length_rp_ids.clone())); create_min_pin_config_params(min_pin_length, Some(min_pin_length_rp_ids.clone()));
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig)); assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length)); assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length));
assert_eq!( assert_eq!(
@@ -339,8 +330,7 @@ mod test {
0xD6, 0xDA, 0xD6, 0xDA,
]; ];
config_params.pin_uv_auth_param = Some(pin_auth.clone()); config_params.pin_uv_auth_param = Some(pin_auth.clone());
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig)); assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length)); assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length));
assert_eq!( assert_eq!(
@@ -353,8 +343,7 @@ mod test {
let mut config_params = let mut config_params =
create_min_pin_config_params(9, Some(min_pin_length_rp_ids.clone())); create_min_pin_config_params(9, Some(min_pin_length_rp_ids.clone()));
config_params.pin_uv_auth_param = Some(pin_auth.clone()); config_params.pin_uv_auth_param = Some(pin_auth.clone());
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
assert_eq!( assert_eq!(
config_response, config_response,
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID) Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
@@ -372,8 +361,7 @@ mod test {
Some(vec!["counter.example.com".to_string()]), Some(vec!["counter.example.com".to_string()]),
); );
config_params.pin_uv_auth_param = Some(pin_auth); config_params.pin_uv_auth_param = Some(pin_auth);
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
assert_eq!( assert_eq!(
config_response, config_response,
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID) Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
@@ -391,7 +379,7 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
persistent_store.set_pin(&[0x88; 16], 4).unwrap(); persistent_store.set_pin(&[0x88; 16], 4).unwrap();
// Increase min PIN, force PIN change. // Increase min PIN, force PIN change.
@@ -402,8 +390,7 @@ mod test {
0xA8, 0xC8, 0xA8, 0xC8,
]); ]);
config_params.pin_uv_auth_param = pin_uv_auth_param; config_params.pin_uv_auth_param = pin_uv_auth_param;
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig)); assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length)); assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length));
assert_eq!(persistent_store.has_force_pin_change(), Ok(true)); assert_eq!(persistent_store.has_force_pin_change(), Ok(true));
@@ -415,7 +402,7 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
persistent_store.set_pin(&[0x88; 16], 4).unwrap(); persistent_store.set_pin(&[0x88; 16], 4).unwrap();
let pin_uv_auth_param = Some(vec![ let pin_uv_auth_param = Some(vec![
@@ -435,8 +422,7 @@ mod test {
pin_uv_auth_param, pin_uv_auth_param,
pin_uv_auth_protocol: Some(1), pin_uv_auth_protocol: Some(1),
}; };
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig)); assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
assert_eq!(persistent_store.has_force_pin_change(), Ok(true)); assert_eq!(persistent_store.has_force_pin_change(), Ok(true));
} }
@@ -447,7 +433,7 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let config_params = AuthenticatorConfigParameters { let config_params = AuthenticatorConfigParameters {
sub_command: ConfigSubCommand::VendorPrototype, sub_command: ConfigSubCommand::VendorPrototype,
@@ -455,8 +441,7 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let config_response = let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
assert_eq!( assert_eq!(
config_response, config_response,
Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER) Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER)

View File

@@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::client_pin::{ClientPin, PinPermission};
use super::command::AuthenticatorCredentialManagementParameters; use super::command::AuthenticatorCredentialManagementParameters;
use super::data_formats::{ use super::data_formats::{
CoseKey, CredentialManagementSubCommand, CredentialManagementSubCommandParameters, CoseKey, CredentialManagementSubCommand, CredentialManagementSubCommandParameters,
PublicKeyCredentialDescriptor, PublicKeyCredentialRpEntity, PublicKeyCredentialSource, PublicKeyCredentialDescriptor, PublicKeyCredentialRpEntity, PublicKeyCredentialSource,
PublicKeyCredentialUserEntity, PublicKeyCredentialUserEntity,
}; };
use super::pin_protocol_v1::{PinPermission, PinProtocolV1};
use super::response::{AuthenticatorCredentialManagementResponse, ResponseData}; use super::response::{AuthenticatorCredentialManagementResponse, ResponseData};
use super::status_code::Ctap2StatusCode; use super::status_code::Ctap2StatusCode;
use super::storage::PersistentStore; use super::storage::PersistentStore;
@@ -110,15 +110,15 @@ fn enumerate_credentials_response(
/// Either no RP ID is associated, or the RP ID matches the stored credential. /// Either no RP ID is associated, or the RP ID matches the stored credential.
fn check_rp_id_permissions( fn check_rp_id_permissions(
persistent_store: &mut PersistentStore, persistent_store: &mut PersistentStore,
pin_protocol_v1: &mut PinProtocolV1, client_pin: &mut ClientPin,
credential_id: &[u8], credential_id: &[u8],
) -> Result<(), Ctap2StatusCode> { ) -> Result<(), Ctap2StatusCode> {
// Pre-check a sufficient condition before calling the store. // Pre-check a sufficient condition before calling the store.
if pin_protocol_v1.has_no_rp_id_permission().is_ok() { if client_pin.has_no_rp_id_permission().is_ok() {
return Ok(()); return Ok(());
} }
let (_, credential) = persistent_store.find_credential_item(credential_id)?; let (_, credential) = persistent_store.find_credential_item(credential_id)?;
pin_protocol_v1.has_no_or_rp_id_permission(&credential.rp_id) client_pin.has_no_or_rp_id_permission(&credential.rp_id)
} }
/// Processes the subcommand getCredsMetadata for CredentialManagement. /// Processes the subcommand getCredsMetadata for CredentialManagement.
@@ -173,14 +173,14 @@ fn process_enumerate_rps_get_next_rp(
fn process_enumerate_credentials_begin( fn process_enumerate_credentials_begin(
persistent_store: &PersistentStore, persistent_store: &PersistentStore,
stateful_command_permission: &mut StatefulPermission, stateful_command_permission: &mut StatefulPermission,
pin_protocol_v1: &mut PinProtocolV1, client_pin: &mut ClientPin,
sub_command_params: CredentialManagementSubCommandParameters, sub_command_params: CredentialManagementSubCommandParameters,
now: ClockValue, now: ClockValue,
) -> Result<AuthenticatorCredentialManagementResponse, Ctap2StatusCode> { ) -> Result<AuthenticatorCredentialManagementResponse, Ctap2StatusCode> {
let rp_id_hash = sub_command_params let rp_id_hash = sub_command_params
.rp_id_hash .rp_id_hash
.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?; .ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?;
pin_protocol_v1.has_no_or_rp_id_hash_permission(&rp_id_hash[..])?; client_pin.has_no_or_rp_id_hash_permission(&rp_id_hash[..])?;
let mut iter_result = Ok(()); let mut iter_result = Ok(());
let iter = persistent_store.iter_credentials(&mut iter_result)?; let iter = persistent_store.iter_credentials(&mut iter_result)?;
let mut rp_credentials: Vec<usize> = iter let mut rp_credentials: Vec<usize> = iter
@@ -219,21 +219,21 @@ fn process_enumerate_credentials_get_next_credential(
/// Processes the subcommand deleteCredential for CredentialManagement. /// Processes the subcommand deleteCredential for CredentialManagement.
fn process_delete_credential( fn process_delete_credential(
persistent_store: &mut PersistentStore, persistent_store: &mut PersistentStore,
pin_protocol_v1: &mut PinProtocolV1, client_pin: &mut ClientPin,
sub_command_params: CredentialManagementSubCommandParameters, sub_command_params: CredentialManagementSubCommandParameters,
) -> Result<(), Ctap2StatusCode> { ) -> Result<(), Ctap2StatusCode> {
let credential_id = sub_command_params let credential_id = sub_command_params
.credential_id .credential_id
.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)? .ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?
.key_id; .key_id;
check_rp_id_permissions(persistent_store, pin_protocol_v1, &credential_id)?; check_rp_id_permissions(persistent_store, client_pin, &credential_id)?;
persistent_store.delete_credential(&credential_id) persistent_store.delete_credential(&credential_id)
} }
/// Processes the subcommand updateUserInformation for CredentialManagement. /// Processes the subcommand updateUserInformation for CredentialManagement.
fn process_update_user_information( fn process_update_user_information(
persistent_store: &mut PersistentStore, persistent_store: &mut PersistentStore,
pin_protocol_v1: &mut PinProtocolV1, client_pin: &mut ClientPin,
sub_command_params: CredentialManagementSubCommandParameters, sub_command_params: CredentialManagementSubCommandParameters,
) -> Result<(), Ctap2StatusCode> { ) -> Result<(), Ctap2StatusCode> {
let credential_id = sub_command_params let credential_id = sub_command_params
@@ -243,7 +243,7 @@ fn process_update_user_information(
let user = sub_command_params let user = sub_command_params
.user .user
.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?; .ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?;
check_rp_id_permissions(persistent_store, pin_protocol_v1, &credential_id)?; check_rp_id_permissions(persistent_store, client_pin, &credential_id)?;
persistent_store.update_credential(&credential_id, user) persistent_store.update_credential(&credential_id, user)
} }
@@ -251,14 +251,14 @@ fn process_update_user_information(
pub fn process_credential_management( pub fn process_credential_management(
persistent_store: &mut PersistentStore, persistent_store: &mut PersistentStore,
stateful_command_permission: &mut StatefulPermission, stateful_command_permission: &mut StatefulPermission,
pin_protocol_v1: &mut PinProtocolV1, client_pin: &mut ClientPin,
cred_management_params: AuthenticatorCredentialManagementParameters, cred_management_params: AuthenticatorCredentialManagementParameters,
now: ClockValue, now: ClockValue,
) -> Result<ResponseData, Ctap2StatusCode> { ) -> Result<ResponseData, Ctap2StatusCode> {
let AuthenticatorCredentialManagementParameters { let AuthenticatorCredentialManagementParameters {
sub_command, sub_command,
sub_command_params, sub_command_params,
pin_protocol, pin_uv_auth_protocol,
pin_auth, pin_auth,
} = cred_management_params; } = cred_management_params;
@@ -282,7 +282,7 @@ pub fn process_credential_management(
| CredentialManagementSubCommand::EnumerateCredentialsBegin | CredentialManagementSubCommand::EnumerateCredentialsBegin
| CredentialManagementSubCommand::DeleteCredential | CredentialManagementSubCommand::DeleteCredential
| CredentialManagementSubCommand::UpdateUserInformation => { | CredentialManagementSubCommand::UpdateUserInformation => {
check_pin_uv_auth_protocol(pin_protocol)?; check_pin_uv_auth_protocol(pin_uv_auth_protocol)?;
let pin_auth = pin_auth.ok_or(Ctap2StatusCode::CTAP2_ERR_PUAT_REQUIRED)?; let pin_auth = pin_auth.ok_or(Ctap2StatusCode::CTAP2_ERR_PUAT_REQUIRED)?;
let mut management_data = vec![sub_command as u8]; let mut management_data = vec![sub_command as u8];
if let Some(sub_command_params) = sub_command_params.clone() { if let Some(sub_command_params) = sub_command_params.clone() {
@@ -290,11 +290,11 @@ pub fn process_credential_management(
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR); return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
} }
} }
if !pin_protocol_v1.verify_pin_auth_token(&management_data, &pin_auth) { if !client_pin.verify_pin_auth_token(&management_data, &pin_auth) {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID);
} }
// The RP ID permission is handled differently per subcommand below. // The RP ID permission is handled differently per subcommand below.
pin_protocol_v1.has_permission(PinPermission::CredentialManagement)?; client_pin.has_permission(PinPermission::CredentialManagement)?;
} }
CredentialManagementSubCommand::EnumerateRpsGetNextRp CredentialManagementSubCommand::EnumerateRpsGetNextRp
| CredentialManagementSubCommand::EnumerateCredentialsGetNextCredential => {} | CredentialManagementSubCommand::EnumerateCredentialsGetNextCredential => {}
@@ -302,11 +302,11 @@ pub fn process_credential_management(
let response = match sub_command { let response = match sub_command {
CredentialManagementSubCommand::GetCredsMetadata => { CredentialManagementSubCommand::GetCredsMetadata => {
pin_protocol_v1.has_no_rp_id_permission()?; client_pin.has_no_rp_id_permission()?;
Some(process_get_creds_metadata(persistent_store)?) Some(process_get_creds_metadata(persistent_store)?)
} }
CredentialManagementSubCommand::EnumerateRpsBegin => { CredentialManagementSubCommand::EnumerateRpsBegin => {
pin_protocol_v1.has_no_rp_id_permission()?; client_pin.has_no_rp_id_permission()?;
Some(process_enumerate_rps_begin( Some(process_enumerate_rps_begin(
persistent_store, persistent_store,
stateful_command_permission, stateful_command_permission,
@@ -320,7 +320,7 @@ pub fn process_credential_management(
Some(process_enumerate_credentials_begin( Some(process_enumerate_credentials_begin(
persistent_store, persistent_store,
stateful_command_permission, stateful_command_permission,
pin_protocol_v1, client_pin,
sub_command_params.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, sub_command_params.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?,
now, now,
)?) )?)
@@ -334,7 +334,7 @@ pub fn process_credential_management(
CredentialManagementSubCommand::DeleteCredential => { CredentialManagementSubCommand::DeleteCredential => {
process_delete_credential( process_delete_credential(
persistent_store, persistent_store,
pin_protocol_v1, client_pin,
sub_command_params.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, sub_command_params.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?,
)?; )?;
None None
@@ -342,7 +342,7 @@ pub fn process_credential_management(
CredentialManagementSubCommand::UpdateUserInformation => { CredentialManagementSubCommand::UpdateUserInformation => {
process_update_user_information( process_update_user_information(
persistent_store, persistent_store,
pin_protocol_v1, client_pin,
sub_command_params.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, sub_command_params.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?,
)?; )?;
None None
@@ -384,12 +384,12 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let credential_source = create_credential_source(&mut rng); let credential_source = create_credential_source(&mut rng);
let user_immediately_present = |_| Ok(()); let user_immediately_present = |_| Ok(());
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
ctap_state.pin_protocol_v1 = pin_protocol_v1; ctap_state.client_pin = client_pin;
ctap_state.persistent_store.set_pin(&[0u8; 16], 4).unwrap(); ctap_state.persistent_store.set_pin(&[0u8; 16], 4).unwrap();
let pin_auth = Some(vec![ let pin_auth = Some(vec![
@@ -400,13 +400,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::GetCredsMetadata, sub_command: CredentialManagementSubCommand::GetCredsMetadata,
sub_command_params: None, sub_command_params: None,
pin_protocol: Some(1), pin_uv_auth_protocol: Some(1),
pin_auth: pin_auth.clone(), pin_auth: pin_auth.clone(),
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -428,13 +428,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::GetCredsMetadata, sub_command: CredentialManagementSubCommand::GetCredsMetadata,
sub_command_params: None, sub_command_params: None,
pin_protocol: Some(1), pin_uv_auth_protocol: Some(1),
pin_auth, pin_auth,
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -455,14 +455,14 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let credential_source1 = create_credential_source(&mut rng); let credential_source1 = create_credential_source(&mut rng);
let mut credential_source2 = create_credential_source(&mut rng); let mut credential_source2 = create_credential_source(&mut rng);
credential_source2.rp_id = "another.example.com".to_string(); credential_source2.rp_id = "another.example.com".to_string();
let user_immediately_present = |_| Ok(()); let user_immediately_present = |_| Ok(());
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
ctap_state.pin_protocol_v1 = pin_protocol_v1; ctap_state.client_pin = client_pin;
ctap_state ctap_state
.persistent_store .persistent_store
@@ -482,13 +482,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::EnumerateRpsBegin, sub_command: CredentialManagementSubCommand::EnumerateRpsBegin,
sub_command_params: None, sub_command_params: None,
pin_protocol: Some(1), pin_uv_auth_protocol: Some(1),
pin_auth, pin_auth,
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -506,13 +506,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::EnumerateRpsGetNextRp, sub_command: CredentialManagementSubCommand::EnumerateRpsGetNextRp,
sub_command_params: None, sub_command_params: None,
pin_protocol: None, pin_uv_auth_protocol: None,
pin_auth: None, pin_auth: None,
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -531,13 +531,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::EnumerateRpsGetNextRp, sub_command: CredentialManagementSubCommand::EnumerateRpsGetNextRp,
sub_command_params: None, sub_command_params: None,
pin_protocol: None, pin_uv_auth_protocol: None,
pin_auth: None, pin_auth: None,
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -552,12 +552,12 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let credential_source = create_credential_source(&mut rng); let credential_source = create_credential_source(&mut rng);
let user_immediately_present = |_| Ok(()); let user_immediately_present = |_| Ok(());
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
ctap_state.pin_protocol_v1 = pin_protocol_v1; ctap_state.client_pin = client_pin;
const NUM_CREDENTIALS: usize = 20; const NUM_CREDENTIALS: usize = 20;
for i in 0..NUM_CREDENTIALS { for i in 0..NUM_CREDENTIALS {
@@ -581,7 +581,7 @@ mod test {
let mut cred_management_params = AuthenticatorCredentialManagementParameters { let mut cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::EnumerateRpsBegin, sub_command: CredentialManagementSubCommand::EnumerateRpsBegin,
sub_command_params: None, sub_command_params: None,
pin_protocol: Some(1), pin_uv_auth_protocol: Some(1),
pin_auth, pin_auth,
}; };
@@ -589,7 +589,7 @@ mod test {
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -611,7 +611,7 @@ mod test {
cred_management_params = AuthenticatorCredentialManagementParameters { cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::EnumerateRpsGetNextRp, sub_command: CredentialManagementSubCommand::EnumerateRpsGetNextRp,
sub_command_params: None, sub_command_params: None,
pin_protocol: None, pin_uv_auth_protocol: None,
pin_auth: None, pin_auth: None,
}; };
} }
@@ -619,7 +619,7 @@ mod test {
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -634,7 +634,7 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let credential_source1 = create_credential_source(&mut rng); let credential_source1 = create_credential_source(&mut rng);
let mut credential_source2 = create_credential_source(&mut rng); let mut credential_source2 = create_credential_source(&mut rng);
credential_source2.user_handle = vec![0x02]; credential_source2.user_handle = vec![0x02];
@@ -644,7 +644,7 @@ mod test {
let user_immediately_present = |_| Ok(()); let user_immediately_present = |_| Ok(());
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
ctap_state.pin_protocol_v1 = pin_protocol_v1; ctap_state.client_pin = client_pin;
ctap_state ctap_state
.persistent_store .persistent_store
@@ -671,13 +671,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::EnumerateCredentialsBegin, sub_command: CredentialManagementSubCommand::EnumerateCredentialsBegin,
sub_command_params: Some(sub_command_params), sub_command_params: Some(sub_command_params),
pin_protocol: Some(1), pin_uv_auth_protocol: Some(1),
pin_auth, pin_auth,
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -694,13 +694,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::EnumerateCredentialsGetNextCredential, sub_command: CredentialManagementSubCommand::EnumerateCredentialsGetNextCredential,
sub_command_params: None, sub_command_params: None,
pin_protocol: None, pin_uv_auth_protocol: None,
pin_auth: None, pin_auth: None,
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -718,13 +718,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::EnumerateCredentialsGetNextCredential, sub_command: CredentialManagementSubCommand::EnumerateCredentialsGetNextCredential,
sub_command_params: None, sub_command_params: None,
pin_protocol: None, pin_uv_auth_protocol: None,
pin_auth: None, pin_auth: None,
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -739,13 +739,13 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let mut credential_source = create_credential_source(&mut rng); let mut credential_source = create_credential_source(&mut rng);
credential_source.credential_id = vec![0x1D; 32]; credential_source.credential_id = vec![0x1D; 32];
let user_immediately_present = |_| Ok(()); let user_immediately_present = |_| Ok(());
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
ctap_state.pin_protocol_v1 = pin_protocol_v1; ctap_state.client_pin = client_pin;
ctap_state ctap_state
.persistent_store .persistent_store
@@ -771,13 +771,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::DeleteCredential, sub_command: CredentialManagementSubCommand::DeleteCredential,
sub_command_params: Some(sub_command_params.clone()), sub_command_params: Some(sub_command_params.clone()),
pin_protocol: Some(1), pin_uv_auth_protocol: Some(1),
pin_auth: pin_auth.clone(), pin_auth: pin_auth.clone(),
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -789,13 +789,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::DeleteCredential, sub_command: CredentialManagementSubCommand::DeleteCredential,
sub_command_params: Some(sub_command_params), sub_command_params: Some(sub_command_params),
pin_protocol: Some(1), pin_uv_auth_protocol: Some(1),
pin_auth, pin_auth,
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -810,13 +810,13 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let mut credential_source = create_credential_source(&mut rng); let mut credential_source = create_credential_source(&mut rng);
credential_source.credential_id = vec![0x1D; 32]; credential_source.credential_id = vec![0x1D; 32];
let user_immediately_present = |_| Ok(()); let user_immediately_present = |_| Ok(());
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
ctap_state.pin_protocol_v1 = pin_protocol_v1; ctap_state.client_pin = client_pin;
ctap_state ctap_state
.persistent_store .persistent_store
@@ -848,13 +848,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::UpdateUserInformation, sub_command: CredentialManagementSubCommand::UpdateUserInformation,
sub_command_params: Some(sub_command_params), sub_command_params: Some(sub_command_params),
pin_protocol: Some(1), pin_uv_auth_protocol: Some(1),
pin_auth, pin_auth,
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -878,15 +878,15 @@ mod test {
} }
#[test] #[test]
fn test_process_credential_management_invalid_pin_protocol() { fn test_process_credential_management_invalid_pin_uv_auth_protocol() {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let user_immediately_present = |_| Ok(()); let user_immediately_present = |_| Ok(());
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
ctap_state.pin_protocol_v1 = pin_protocol_v1; ctap_state.client_pin = client_pin;
ctap_state.persistent_store.set_pin(&[0u8; 16], 4).unwrap(); ctap_state.persistent_store.set_pin(&[0u8; 16], 4).unwrap();
let pin_auth = Some(vec![ let pin_auth = Some(vec![
@@ -897,13 +897,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::GetCredsMetadata, sub_command: CredentialManagementSubCommand::GetCredsMetadata,
sub_command_params: None, sub_command_params: None,
pin_protocol: Some(123456), pin_uv_auth_protocol: Some(123456),
pin_auth, pin_auth,
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );
@@ -924,13 +924,13 @@ mod test {
let cred_management_params = AuthenticatorCredentialManagementParameters { let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::GetCredsMetadata, sub_command: CredentialManagementSubCommand::GetCredsMetadata,
sub_command_params: None, sub_command_params: None,
pin_protocol: Some(1), pin_uv_auth_protocol: Some(1),
pin_auth: Some(vec![0u8; 16]), pin_auth: Some(vec![0u8; 16]),
}; };
let cred_management_response = process_credential_management( let cred_management_response = process_credential_management(
&mut ctap_state.persistent_store, &mut ctap_state.persistent_store,
&mut ctap_state.stateful_command_permission, &mut ctap_state.stateful_command_permission,
&mut ctap_state.pin_protocol_v1, &mut ctap_state.client_pin,
cred_management_params, cred_management_params,
DUMMY_CLOCK_VALUE, DUMMY_CLOCK_VALUE,
); );

View File

@@ -13,8 +13,8 @@
// limitations under the License. // limitations under the License.
use super::check_pin_uv_auth_protocol; use super::check_pin_uv_auth_protocol;
use super::client_pin::{ClientPin, PinPermission};
use super::command::AuthenticatorLargeBlobsParameters; use super::command::AuthenticatorLargeBlobsParameters;
use super::pin_protocol_v1::{PinPermission, PinProtocolV1};
use super::response::{AuthenticatorLargeBlobsResponse, ResponseData}; use super::response::{AuthenticatorLargeBlobsResponse, ResponseData};
use super::status_code::Ctap2StatusCode; use super::status_code::Ctap2StatusCode;
use super::storage::PersistentStore; use super::storage::PersistentStore;
@@ -51,7 +51,7 @@ impl LargeBlobs {
pub fn process_command( pub fn process_command(
&mut self, &mut self,
persistent_store: &mut PersistentStore, persistent_store: &mut PersistentStore,
pin_protocol_v1: &mut PinProtocolV1, client_pin: &mut ClientPin,
large_blobs_params: AuthenticatorLargeBlobsParameters, large_blobs_params: AuthenticatorLargeBlobsParameters,
) -> Result<ResponseData, Ctap2StatusCode> { ) -> Result<ResponseData, Ctap2StatusCode> {
let AuthenticatorLargeBlobsParameters { let AuthenticatorLargeBlobsParameters {
@@ -94,14 +94,14 @@ impl LargeBlobs {
// TODO(kaczmarczyck) Error codes for PIN protocol differ across commands. // TODO(kaczmarczyck) Error codes for PIN protocol differ across commands.
// Change to Ctap2StatusCode::CTAP2_ERR_PUAT_REQUIRED for None? // Change to Ctap2StatusCode::CTAP2_ERR_PUAT_REQUIRED for None?
check_pin_uv_auth_protocol(pin_uv_auth_protocol)?; check_pin_uv_auth_protocol(pin_uv_auth_protocol)?;
pin_protocol_v1.has_permission(PinPermission::LargeBlobWrite)?; client_pin.has_permission(PinPermission::LargeBlobWrite)?;
let mut message = vec![0xFF; 32]; let mut message = vec![0xFF; 32];
message.extend(&[0x0C, 0x00]); message.extend(&[0x0C, 0x00]);
let mut offset_bytes = [0u8; 4]; let mut offset_bytes = [0u8; 4];
LittleEndian::write_u32(&mut offset_bytes, offset as u32); LittleEndian::write_u32(&mut offset_bytes, offset as u32);
message.extend(&offset_bytes); message.extend(&offset_bytes);
message.extend(&Sha256::hash(set.as_slice())); message.extend(&Sha256::hash(set.as_slice()));
if !pin_protocol_v1.verify_pin_auth_token(&message, &pin_uv_auth_param) { if !client_pin.verify_pin_auth_token(&message, &pin_uv_auth_param) {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID);
} }
} }
@@ -146,7 +146,7 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let mut large_blobs = LargeBlobs::new(); let mut large_blobs = LargeBlobs::new();
let large_blob = vec![ let large_blob = vec![
@@ -161,11 +161,8 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let large_blobs_response = large_blobs.process_command( let large_blobs_response =
&mut persistent_store, large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
&mut pin_protocol_v1,
large_blobs_params,
);
match large_blobs_response.unwrap() { match large_blobs_response.unwrap() {
ResponseData::AuthenticatorLargeBlobs(Some(response)) => { ResponseData::AuthenticatorLargeBlobs(Some(response)) => {
assert_eq!(response.config, large_blob); assert_eq!(response.config, large_blob);
@@ -180,7 +177,7 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let mut large_blobs = LargeBlobs::new(); let mut large_blobs = LargeBlobs::new();
const BLOB_LEN: usize = 200; const BLOB_LEN: usize = 200;
@@ -196,11 +193,8 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let large_blobs_response = large_blobs.process_command( let large_blobs_response =
&mut persistent_store, large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
&mut pin_protocol_v1,
large_blobs_params,
);
assert_eq!( assert_eq!(
large_blobs_response, large_blobs_response,
Ok(ResponseData::AuthenticatorLargeBlobs(None)) Ok(ResponseData::AuthenticatorLargeBlobs(None))
@@ -214,11 +208,8 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let large_blobs_response = large_blobs.process_command( let large_blobs_response =
&mut persistent_store, large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
&mut pin_protocol_v1,
large_blobs_params,
);
assert_eq!( assert_eq!(
large_blobs_response, large_blobs_response,
Ok(ResponseData::AuthenticatorLargeBlobs(None)) Ok(ResponseData::AuthenticatorLargeBlobs(None))
@@ -232,11 +223,8 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let large_blobs_response = large_blobs.process_command( let large_blobs_response =
&mut persistent_store, large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
&mut pin_protocol_v1,
large_blobs_params,
);
match large_blobs_response.unwrap() { match large_blobs_response.unwrap() {
ResponseData::AuthenticatorLargeBlobs(Some(response)) => { ResponseData::AuthenticatorLargeBlobs(Some(response)) => {
assert_eq!(response.config, large_blob); assert_eq!(response.config, large_blob);
@@ -251,7 +239,7 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let mut large_blobs = LargeBlobs::new(); let mut large_blobs = LargeBlobs::new();
const BLOB_LEN: usize = 200; const BLOB_LEN: usize = 200;
@@ -267,11 +255,8 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let large_blobs_response = large_blobs.process_command( let large_blobs_response =
&mut persistent_store, large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
&mut pin_protocol_v1,
large_blobs_params,
);
assert_eq!( assert_eq!(
large_blobs_response, large_blobs_response,
Ok(ResponseData::AuthenticatorLargeBlobs(None)) Ok(ResponseData::AuthenticatorLargeBlobs(None))
@@ -286,11 +271,8 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let large_blobs_response = large_blobs.process_command( let large_blobs_response =
&mut persistent_store, large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
&mut pin_protocol_v1,
large_blobs_params,
);
assert_eq!( assert_eq!(
large_blobs_response, large_blobs_response,
Err(Ctap2StatusCode::CTAP1_ERR_INVALID_SEQ), Err(Ctap2StatusCode::CTAP1_ERR_INVALID_SEQ),
@@ -303,7 +285,7 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let mut large_blobs = LargeBlobs::new(); let mut large_blobs = LargeBlobs::new();
const BLOB_LEN: usize = 200; const BLOB_LEN: usize = 200;
@@ -320,11 +302,8 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let large_blobs_response = large_blobs.process_command( let large_blobs_response =
&mut persistent_store, large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
&mut pin_protocol_v1,
large_blobs_params,
);
assert_eq!( assert_eq!(
large_blobs_response, large_blobs_response,
Ok(ResponseData::AuthenticatorLargeBlobs(None)) Ok(ResponseData::AuthenticatorLargeBlobs(None))
@@ -338,11 +317,8 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let large_blobs_response = large_blobs.process_command( let large_blobs_response =
&mut persistent_store, large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
&mut pin_protocol_v1,
large_blobs_params,
);
assert_eq!( assert_eq!(
large_blobs_response, large_blobs_response,
Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER), Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER),
@@ -355,7 +331,7 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let mut large_blobs = LargeBlobs::new(); let mut large_blobs = LargeBlobs::new();
const BLOB_LEN: usize = 20; const BLOB_LEN: usize = 20;
@@ -370,11 +346,8 @@ mod test {
pin_uv_auth_param: None, pin_uv_auth_param: None,
pin_uv_auth_protocol: None, pin_uv_auth_protocol: None,
}; };
let large_blobs_response = large_blobs.process_command( let large_blobs_response =
&mut persistent_store, large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
&mut pin_protocol_v1,
large_blobs_params,
);
assert_eq!( assert_eq!(
large_blobs_response, large_blobs_response,
Err(Ctap2StatusCode::CTAP2_ERR_INTEGRITY_FAILURE), Err(Ctap2StatusCode::CTAP2_ERR_INTEGRITY_FAILURE),
@@ -387,7 +360,7 @@ mod test {
let mut persistent_store = PersistentStore::new(&mut rng); let mut persistent_store = PersistentStore::new(&mut rng);
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x55; 32]; let pin_uv_auth_token = [0x55; 32];
let mut pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let mut client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let mut large_blobs = LargeBlobs::new(); let mut large_blobs = LargeBlobs::new();
const BLOB_LEN: usize = 20; const BLOB_LEN: usize = 20;
@@ -409,11 +382,8 @@ mod test {
pin_uv_auth_param, pin_uv_auth_param,
pin_uv_auth_protocol: Some(1), pin_uv_auth_protocol: Some(1),
}; };
let large_blobs_response = large_blobs.process_command( let large_blobs_response =
&mut persistent_store, large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
&mut pin_protocol_v1,
large_blobs_params,
);
assert_eq!( assert_eq!(
large_blobs_response, large_blobs_response,
Ok(ResponseData::AuthenticatorLargeBlobs(None)) Ok(ResponseData::AuthenticatorLargeBlobs(None))

View File

@@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
pub mod apdu; pub mod apdu;
mod client_pin;
pub mod command; pub mod command;
mod config_command; mod config_command;
mod credential_management; mod credential_management;
@@ -23,15 +24,15 @@ pub mod data_formats;
pub mod hid; pub mod hid;
mod key_material; mod key_material;
mod large_blobs; mod large_blobs;
mod pin_protocol_v1;
pub mod response; pub mod response;
pub mod status_code; pub mod status_code;
mod storage; mod storage;
mod timed_permission; mod timed_permission;
use self::client_pin::{ClientPin, PinPermission};
use self::command::{ use self::command::{
AuthenticatorClientPinParameters, AuthenticatorGetAssertionParameters, AuthenticatorGetAssertionParameters, AuthenticatorMakeCredentialParameters,
AuthenticatorMakeCredentialParameters, AuthenticatorVendorConfigureParameters, Command, AuthenticatorVendorConfigureParameters, Command,
}; };
use self::config_command::process_config; use self::config_command::process_config;
use self::credential_management::process_credential_management; use self::credential_management::process_credential_management;
@@ -48,7 +49,6 @@ use self::data_formats::{
}; };
use self::hid::ChannelID; use self::hid::ChannelID;
use self::large_blobs::{LargeBlobs, MAX_MSG_SIZE}; use self::large_blobs::{LargeBlobs, MAX_MSG_SIZE};
use self::pin_protocol_v1::{PinPermission, PinProtocolV1};
use self::response::{ use self::response::{
AuthenticatorGetAssertionResponse, AuthenticatorGetInfoResponse, AuthenticatorGetAssertionResponse, AuthenticatorGetInfoResponse,
AuthenticatorMakeCredentialResponse, AuthenticatorVendorResponse, ResponseData, AuthenticatorMakeCredentialResponse, AuthenticatorVendorResponse, ResponseData,
@@ -278,7 +278,7 @@ pub struct CtapState<'a, R: Rng256, CheckUserPresence: Fn(ChannelID) -> Result<(
// false otherwise. // false otherwise.
check_user_presence: CheckUserPresence, check_user_presence: CheckUserPresence,
persistent_store: PersistentStore, persistent_store: PersistentStore,
pin_protocol_v1: PinProtocolV1, client_pin: ClientPin,
#[cfg(feature = "with_ctap1")] #[cfg(feature = "with_ctap1")]
pub u2f_up_state: U2fUserPresenceState, pub u2f_up_state: U2fUserPresenceState,
// The state initializes to Reset and its timeout, and never goes back to Reset. // The state initializes to Reset and its timeout, and never goes back to Reset.
@@ -297,12 +297,12 @@ where
now: ClockValue, now: ClockValue,
) -> CtapState<'a, R, CheckUserPresence> { ) -> CtapState<'a, R, CheckUserPresence> {
let persistent_store = PersistentStore::new(rng); let persistent_store = PersistentStore::new(rng);
let pin_protocol_v1 = PinProtocolV1::new(rng); let client_pin = ClientPin::new(rng);
CtapState { CtapState {
rng, rng,
check_user_presence, check_user_presence,
persistent_store, persistent_store,
pin_protocol_v1, client_pin,
#[cfg(feature = "with_ctap1")] #[cfg(feature = "with_ctap1")]
u2f_up_state: U2fUserPresenceState::new( u2f_up_state: U2fUserPresenceState::new(
U2F_UP_PROMPT_TIMEOUT, U2F_UP_PROMPT_TIMEOUT,
@@ -473,13 +473,17 @@ where
} }
Command::AuthenticatorGetNextAssertion => self.process_get_next_assertion(now), Command::AuthenticatorGetNextAssertion => self.process_get_next_assertion(now),
Command::AuthenticatorGetInfo => self.process_get_info(), Command::AuthenticatorGetInfo => self.process_get_info(),
Command::AuthenticatorClientPin(params) => self.process_client_pin(params), Command::AuthenticatorClientPin(params) => self.client_pin.process_command(
self.rng,
&mut self.persistent_store,
params,
),
Command::AuthenticatorReset => self.process_reset(cid, now), Command::AuthenticatorReset => self.process_reset(cid, now),
Command::AuthenticatorCredentialManagement(params) => { Command::AuthenticatorCredentialManagement(params) => {
process_credential_management( process_credential_management(
&mut self.persistent_store, &mut self.persistent_store,
&mut self.stateful_command_permission, &mut self.stateful_command_permission,
&mut self.pin_protocol_v1, &mut self.client_pin,
params, params,
now, now,
) )
@@ -487,14 +491,12 @@ where
Command::AuthenticatorSelection => self.process_selection(cid), Command::AuthenticatorSelection => self.process_selection(cid),
Command::AuthenticatorLargeBlobs(params) => self.large_blobs.process_command( Command::AuthenticatorLargeBlobs(params) => self.large_blobs.process_command(
&mut self.persistent_store, &mut self.persistent_store,
&mut self.pin_protocol_v1, &mut self.client_pin,
params,
),
Command::AuthenticatorConfig(params) => process_config(
&mut self.persistent_store,
&mut self.pin_protocol_v1,
params, params,
), ),
Command::AuthenticatorConfig(params) => {
process_config(&mut self.persistent_store, &mut self.client_pin, params)
}
// Vendor specific commands // Vendor specific commands
Command::AuthenticatorVendorConfigure(params) => { Command::AuthenticatorVendorConfigure(params) => {
self.process_vendor_configure(params, cid) self.process_vendor_configure(params, cid)
@@ -647,14 +649,14 @@ where
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_NOT_SET); return Err(Ctap2StatusCode::CTAP2_ERR_PIN_NOT_SET);
} }
if !self if !self
.pin_protocol_v1 .client_pin
.verify_pin_auth_token(&client_data_hash, &pin_auth) .verify_pin_auth_token(&client_data_hash, &pin_auth)
{ {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID);
} }
self.pin_protocol_v1 self.client_pin
.has_permission(PinPermission::MakeCredential)?; .has_permission(PinPermission::MakeCredential)?;
self.pin_protocol_v1.ensure_rp_id_permission(&rp_id)?; self.client_pin.ensure_rp_id_permission(&rp_id)?;
UP_FLAG | UV_FLAG | AT_FLAG | ed_flag UP_FLAG | UV_FLAG | AT_FLAG | ed_flag
} }
None => { None => {
@@ -815,7 +817,7 @@ where
let encrypted_output = if let Some(hmac_secret_input) = extensions.hmac_secret { let encrypted_output = if let Some(hmac_secret_input) = extensions.hmac_secret {
let cred_random = self.generate_cred_random(&credential.private_key, has_uv)?; let cred_random = self.generate_cred_random(&credential.private_key, has_uv)?;
Some( Some(
self.pin_protocol_v1 self.client_pin
.process_hmac_secret(hmac_secret_input, &cred_random)?, .process_hmac_secret(hmac_secret_input, &cred_random)?,
) )
} else { } else {
@@ -938,14 +940,14 @@ where
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_NOT_SET); return Err(Ctap2StatusCode::CTAP2_ERR_PIN_NOT_SET);
} }
if !self if !self
.pin_protocol_v1 .client_pin
.verify_pin_auth_token(&client_data_hash, &pin_auth) .verify_pin_auth_token(&client_data_hash, &pin_auth)
{ {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID);
} }
self.pin_protocol_v1 self.client_pin
.has_permission(PinPermission::GetAssertion)?; .has_permission(PinPermission::GetAssertion)?;
self.pin_protocol_v1.ensure_rp_id_permission(&rp_id)?; self.client_pin.ensure_rp_id_permission(&rp_id)?;
UV_FLAG UV_FLAG
} }
None => { None => {
@@ -1104,17 +1106,6 @@ where
)) ))
} }
fn process_client_pin(
&mut self,
client_pin_params: AuthenticatorClientPinParameters,
) -> Result<ResponseData, Ctap2StatusCode> {
self.pin_protocol_v1.process_subcommand(
self.rng,
&mut self.persistent_store,
client_pin_params,
)
}
fn process_reset( fn process_reset(
&mut self, &mut self,
cid: ChannelID, cid: ChannelID,
@@ -1129,7 +1120,7 @@ where
(self.check_user_presence)(cid)?; (self.check_user_presence)(cid)?;
self.persistent_store.reset(self.rng)?; self.persistent_store.reset(self.rng)?;
self.pin_protocol_v1.reset(self.rng); self.client_pin.reset(self.rng);
#[cfg(feature = "with_ctap1")] #[cfg(feature = "with_ctap1")]
{ {
self.u2f_up_state = U2fUserPresenceState::new( self.u2f_up_state = U2fUserPresenceState::new(
@@ -2332,11 +2323,11 @@ mod test {
let mut rng = ThreadRng256 {}; let mut rng = ThreadRng256 {};
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng); let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
let pin_uv_auth_token = [0x88; 32]; let pin_uv_auth_token = [0x88; 32];
let pin_protocol_v1 = PinProtocolV1::new_test(key_agreement_key, pin_uv_auth_token); let client_pin = ClientPin::new_test(key_agreement_key, pin_uv_auth_token);
let user_immediately_present = |_| Ok(()); let user_immediately_present = |_| Ok(());
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
ctap_state.pin_protocol_v1 = pin_protocol_v1; ctap_state.client_pin = client_pin;
let mut make_credential_params = create_minimal_make_credential_parameters(); let mut make_credential_params = create_minimal_make_credential_parameters();
let user1 = PublicKeyCredentialUserEntity { let user1 = PublicKeyCredentialUserEntity {

View File

@@ -14,6 +14,7 @@
mod key; mod key;
use crate::ctap::client_pin::PIN_AUTH_LENGTH;
use crate::ctap::customization::{ use crate::ctap::customization::{
DEFAULT_MIN_PIN_LENGTH, DEFAULT_MIN_PIN_LENGTH_RP_IDS, ENFORCE_ALWAYS_UV, DEFAULT_MIN_PIN_LENGTH, DEFAULT_MIN_PIN_LENGTH_RP_IDS, ENFORCE_ALWAYS_UV,
MAX_LARGE_BLOB_ARRAY_SIZE, MAX_PIN_RETRIES, MAX_RP_IDS_LENGTH, MAX_SUPPORTED_RESIDENT_KEYS, MAX_LARGE_BLOB_ARRAY_SIZE, MAX_PIN_RETRIES, MAX_RP_IDS_LENGTH, MAX_SUPPORTED_RESIDENT_KEYS,
@@ -24,7 +25,6 @@ use crate::ctap::data_formats::{
PublicKeyCredentialUserEntity, PublicKeyCredentialUserEntity,
}; };
use crate::ctap::key_material; use crate::ctap::key_material;
use crate::ctap::pin_protocol_v1::PIN_AUTH_LENGTH;
use crate::ctap::status_code::Ctap2StatusCode; use crate::ctap::status_code::Ctap2StatusCode;
use crate::ctap::INITIAL_SIGNATURE_COUNTER; use crate::ctap::INITIAL_SIGNATURE_COUNTER;
use crate::embedded_flash::{new_storage, Storage}; use crate::embedded_flash::{new_storage, Storage};