renames PIN protocol related variables to prepare PIN protocol v2 (#291)
This commit is contained in:
@@ -166,7 +166,7 @@ pub enum PinPermission {
|
||||
AuthenticatorConfiguration = 0x20,
|
||||
}
|
||||
|
||||
pub struct PinProtocolV1 {
|
||||
pub struct ClientPin {
|
||||
key_agreement_key: crypto::ecdh::SecKey,
|
||||
pin_uv_auth_token: [u8; PIN_TOKEN_LENGTH],
|
||||
consecutive_pin_mismatches: u8,
|
||||
@@ -174,11 +174,11 @@ pub struct PinProtocolV1 {
|
||||
permissions_rp_id: Option<String>,
|
||||
}
|
||||
|
||||
impl PinProtocolV1 {
|
||||
pub fn new(rng: &mut impl Rng256) -> PinProtocolV1 {
|
||||
impl ClientPin {
|
||||
pub fn new(rng: &mut impl Rng256) -> ClientPin {
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(rng);
|
||||
let pin_uv_auth_token = rng.gen_uniform_u8x32();
|
||||
PinProtocolV1 {
|
||||
ClientPin {
|
||||
key_agreement_key,
|
||||
pin_uv_auth_token,
|
||||
consecutive_pin_mismatches: 0,
|
||||
@@ -395,14 +395,14 @@ impl PinProtocolV1 {
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
pub fn process_subcommand(
|
||||
pub fn process_command(
|
||||
&mut self,
|
||||
rng: &mut impl Rng256,
|
||||
persistent_store: &mut PersistentStore,
|
||||
client_pin_params: AuthenticatorClientPinParameters,
|
||||
) -> Result<ResponseData, Ctap2StatusCode> {
|
||||
let AuthenticatorClientPinParameters {
|
||||
pin_protocol,
|
||||
pin_uv_auth_protocol,
|
||||
sub_command,
|
||||
key_agreement,
|
||||
pin_auth,
|
||||
@@ -412,7 +412,7 @@ impl PinProtocolV1 {
|
||||
permissions_rp_id,
|
||||
} = client_pin_params;
|
||||
|
||||
if pin_protocol != 1 {
|
||||
if pin_uv_auth_protocol != 1 {
|
||||
return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@@ -558,8 +558,8 @@ impl PinProtocolV1 {
|
||||
pub fn new_test(
|
||||
key_agreement_key: crypto::ecdh::SecKey,
|
||||
pin_uv_auth_token: [u8; PIN_TOKEN_LENGTH],
|
||||
) -> PinProtocolV1 {
|
||||
PinProtocolV1 {
|
||||
) -> ClientPin {
|
||||
ClientPin {
|
||||
key_agreement_key,
|
||||
pin_uv_auth_token,
|
||||
consecutive_pin_mismatches: 0,
|
||||
@@ -647,13 +647,13 @@ mod test {
|
||||
let aes_enc_key = crypto::aes256::EncryptionKey::new(&shared_secret);
|
||||
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![
|
||||
0x8D, 0x7A, 0xA3, 0x9F, 0x7F, 0xC6, 0x08, 0x13, 0x9A, 0xC8, 0x56, 0x97, 0x70, 0x74,
|
||||
0x99, 0x66,
|
||||
];
|
||||
assert_eq!(
|
||||
pin_protocol_v1.verify_pin_hash_enc(
|
||||
client_pin.verify_pin_hash_enc(
|
||||
&mut rng,
|
||||
&mut persistent_store,
|
||||
&aes_dec_key,
|
||||
@@ -664,7 +664,7 @@ mod test {
|
||||
|
||||
let pin_hash_enc = vec![0xEE; 16];
|
||||
assert_eq!(
|
||||
pin_protocol_v1.verify_pin_hash_enc(
|
||||
client_pin.verify_pin_hash_enc(
|
||||
&mut rng,
|
||||
&mut persistent_store,
|
||||
&aes_dec_key,
|
||||
@@ -677,9 +677,9 @@ mod test {
|
||||
0x8D, 0x7A, 0xA3, 0x9F, 0x7F, 0xC6, 0x08, 0x13, 0x9A, 0xC8, 0x56, 0x97, 0x70, 0x74,
|
||||
0x99, 0x66,
|
||||
];
|
||||
pin_protocol_v1.consecutive_pin_mismatches = 3;
|
||||
client_pin.consecutive_pin_mismatches = 3;
|
||||
assert_eq!(
|
||||
pin_protocol_v1.verify_pin_hash_enc(
|
||||
client_pin.verify_pin_hash_enc(
|
||||
&mut rng,
|
||||
&mut persistent_store,
|
||||
&aes_dec_key,
|
||||
@@ -687,11 +687,11 @@ mod test {
|
||||
),
|
||||
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];
|
||||
assert_eq!(
|
||||
pin_protocol_v1.verify_pin_hash_enc(
|
||||
client_pin.verify_pin_hash_enc(
|
||||
&mut rng,
|
||||
&mut persistent_store,
|
||||
&aes_dec_key,
|
||||
@@ -702,7 +702,7 @@ mod test {
|
||||
|
||||
let pin_hash_enc = vec![0x77; PIN_AUTH_LENGTH + 1];
|
||||
assert_eq!(
|
||||
pin_protocol_v1.verify_pin_hash_enc(
|
||||
client_pin.verify_pin_hash_enc(
|
||||
&mut rng,
|
||||
&mut persistent_store,
|
||||
&aes_dec_key,
|
||||
@@ -716,14 +716,14 @@ mod test {
|
||||
fn test_process_get_pin_retries() {
|
||||
let mut rng = ThreadRng256 {};
|
||||
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 {
|
||||
key_agreement: None,
|
||||
pin_token: None,
|
||||
retries: Some(persistent_store.pin_retries().unwrap() as u64),
|
||||
});
|
||||
assert_eq!(
|
||||
pin_protocol_v1.process_get_pin_retries(&persistent_store),
|
||||
client_pin.process_get_pin_retries(&persistent_store),
|
||||
expected_response
|
||||
);
|
||||
}
|
||||
@@ -731,36 +731,28 @@ mod test {
|
||||
#[test]
|
||||
fn test_process_get_key_agreement() {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let pin_protocol_v1 = PinProtocolV1::new(&mut rng);
|
||||
let pk = pin_protocol_v1.key_agreement_key.genpk();
|
||||
let client_pin = ClientPin::new(&mut rng);
|
||||
let pk = client_pin.key_agreement_key.genpk();
|
||||
let expected_response = Ok(AuthenticatorClientPinResponse {
|
||||
key_agreement: Some(CoseKey::from(pk)),
|
||||
pin_token: None,
|
||||
retries: None,
|
||||
});
|
||||
assert_eq!(
|
||||
pin_protocol_v1.process_get_key_agreement(),
|
||||
expected_response
|
||||
);
|
||||
assert_eq!(client_pin.process_get_key_agreement(), expected_response);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_process_set_pin() {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng);
|
||||
let pk = pin_protocol_v1.key_agreement_key.genpk();
|
||||
let shared_secret = pin_protocol_v1.key_agreement_key.exchange_x_sha256(&pk);
|
||||
let mut client_pin = ClientPin::new(&mut rng);
|
||||
let pk = client_pin.key_agreement_key.genpk();
|
||||
let shared_secret = client_pin.key_agreement_key.exchange_x_sha256(&pk);
|
||||
let key_agreement = CoseKey::from(pk);
|
||||
let new_pin_enc = encrypt_standard_pin(&shared_secret);
|
||||
let pin_auth = hmac_256::<Sha256>(&shared_secret, &new_pin_enc[..])[..16].to_vec();
|
||||
assert_eq!(
|
||||
pin_protocol_v1.process_set_pin(
|
||||
&mut persistent_store,
|
||||
key_agreement,
|
||||
pin_auth,
|
||||
new_pin_enc
|
||||
),
|
||||
client_pin.process_set_pin(&mut persistent_store, key_agreement, pin_auth, new_pin_enc),
|
||||
Ok(())
|
||||
);
|
||||
}
|
||||
@@ -770,9 +762,9 @@ mod test {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
set_standard_pin(&mut persistent_store);
|
||||
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng);
|
||||
let pk = pin_protocol_v1.key_agreement_key.genpk();
|
||||
let shared_secret = pin_protocol_v1.key_agreement_key.exchange_x_sha256(&pk);
|
||||
let mut client_pin = ClientPin::new(&mut rng);
|
||||
let pk = client_pin.key_agreement_key.genpk();
|
||||
let shared_secret = client_pin.key_agreement_key.exchange_x_sha256(&pk);
|
||||
let key_agreement = CoseKey::from(pk);
|
||||
let new_pin_enc = encrypt_standard_pin(&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);
|
||||
let pin_auth = hmac_256::<Sha256>(&shared_secret, &auth_param_data[..])[..16].to_vec();
|
||||
assert_eq!(
|
||||
pin_protocol_v1.process_change_pin(
|
||||
client_pin.process_change_pin(
|
||||
&mut rng,
|
||||
&mut persistent_store,
|
||||
key_agreement.clone(),
|
||||
@@ -793,7 +785,7 @@ mod test {
|
||||
|
||||
let bad_pin_hash_enc = vec![0xEE; 16];
|
||||
assert_eq!(
|
||||
pin_protocol_v1.process_change_pin(
|
||||
client_pin.process_change_pin(
|
||||
&mut rng,
|
||||
&mut persistent_store,
|
||||
key_agreement.clone(),
|
||||
@@ -808,7 +800,7 @@ mod test {
|
||||
persistent_store.decr_pin_retries().unwrap();
|
||||
}
|
||||
assert_eq!(
|
||||
pin_protocol_v1.process_change_pin(
|
||||
client_pin.process_change_pin(
|
||||
&mut rng,
|
||||
&mut persistent_store,
|
||||
key_agreement,
|
||||
@@ -825,12 +817,12 @@ mod test {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
set_standard_pin(&mut persistent_store);
|
||||
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng);
|
||||
let pk = pin_protocol_v1.key_agreement_key.genpk();
|
||||
let shared_secret = pin_protocol_v1.key_agreement_key.exchange_x_sha256(&pk);
|
||||
let mut client_pin = ClientPin::new(&mut rng);
|
||||
let pk = client_pin.key_agreement_key.genpk();
|
||||
let shared_secret = client_pin.key_agreement_key.exchange_x_sha256(&pk);
|
||||
let key_agreement = CoseKey::from(pk);
|
||||
let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret);
|
||||
assert!(pin_protocol_v1
|
||||
assert!(client_pin
|
||||
.process_get_pin_token(
|
||||
&mut rng,
|
||||
&mut persistent_store,
|
||||
@@ -841,7 +833,7 @@ mod test {
|
||||
|
||||
let pin_hash_enc = vec![0xEE; 16];
|
||||
assert_eq!(
|
||||
pin_protocol_v1.process_get_pin_token(
|
||||
client_pin.process_get_pin_token(
|
||||
&mut rng,
|
||||
&mut persistent_store,
|
||||
key_agreement,
|
||||
@@ -857,13 +849,13 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
set_standard_pin(&mut persistent_store);
|
||||
assert_eq!(persistent_store.force_pin_change(), Ok(()));
|
||||
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng);
|
||||
let pk = pin_protocol_v1.key_agreement_key.genpk();
|
||||
let shared_secret = pin_protocol_v1.key_agreement_key.exchange_x_sha256(&pk);
|
||||
let mut client_pin = ClientPin::new(&mut rng);
|
||||
let pk = client_pin.key_agreement_key.genpk();
|
||||
let shared_secret = client_pin.key_agreement_key.exchange_x_sha256(&pk);
|
||||
let key_agreement = CoseKey::from(pk);
|
||||
let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret);
|
||||
assert_eq!(
|
||||
pin_protocol_v1.process_get_pin_token(
|
||||
client_pin.process_get_pin_token(
|
||||
&mut rng,
|
||||
&mut persistent_store,
|
||||
key_agreement,
|
||||
@@ -878,12 +870,12 @@ mod test {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
set_standard_pin(&mut persistent_store);
|
||||
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng);
|
||||
let pk = pin_protocol_v1.key_agreement_key.genpk();
|
||||
let shared_secret = pin_protocol_v1.key_agreement_key.exchange_x_sha256(&pk);
|
||||
let mut client_pin = ClientPin::new(&mut rng);
|
||||
let pk = client_pin.key_agreement_key.genpk();
|
||||
let shared_secret = client_pin.key_agreement_key.exchange_x_sha256(&pk);
|
||||
let key_agreement = CoseKey::from(pk);
|
||||
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(
|
||||
&mut rng,
|
||||
&mut persistent_store,
|
||||
@@ -893,14 +885,14 @@ mod test {
|
||||
Some(String::from("example.com")),
|
||||
)
|
||||
.is_ok());
|
||||
assert_eq!(pin_protocol_v1.permissions, 0x03);
|
||||
assert_eq!(client_pin.permissions, 0x03);
|
||||
assert_eq!(
|
||||
pin_protocol_v1.permissions_rp_id,
|
||||
client_pin.permissions_rp_id,
|
||||
Some(String::from("example.com"))
|
||||
);
|
||||
|
||||
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 persistent_store,
|
||||
key_agreement.clone(),
|
||||
@@ -912,7 +904,7 @@ mod test {
|
||||
);
|
||||
|
||||
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 persistent_store,
|
||||
key_agreement.clone(),
|
||||
@@ -925,7 +917,7 @@ mod test {
|
||||
|
||||
let pin_hash_enc = vec![0xEE; 16];
|
||||
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 persistent_store,
|
||||
key_agreement,
|
||||
@@ -943,13 +935,13 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
set_standard_pin(&mut persistent_store);
|
||||
assert_eq!(persistent_store.force_pin_change(), Ok(()));
|
||||
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng);
|
||||
let pk = pin_protocol_v1.key_agreement_key.genpk();
|
||||
let shared_secret = pin_protocol_v1.key_agreement_key.exchange_x_sha256(&pk);
|
||||
let mut client_pin = ClientPin::new(&mut rng);
|
||||
let pk = client_pin.key_agreement_key.genpk();
|
||||
let shared_secret = client_pin.key_agreement_key.exchange_x_sha256(&pk);
|
||||
let key_agreement = CoseKey::from(pk);
|
||||
let pin_hash_enc = encrypt_standard_pin_hash(&shared_secret);
|
||||
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 persistent_store,
|
||||
key_agreement,
|
||||
@@ -965,9 +957,9 @@ mod test {
|
||||
fn test_process() {
|
||||
let mut rng = ThreadRng256 {};
|
||||
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 {
|
||||
pin_protocol: 1,
|
||||
pin_uv_auth_protocol: 1,
|
||||
sub_command: ClientPinSubCommand::GetPinRetries,
|
||||
key_agreement: None,
|
||||
pin_auth: None,
|
||||
@@ -976,12 +968,12 @@ mod test {
|
||||
permissions: None,
|
||||
permissions_rp_id: None,
|
||||
};
|
||||
assert!(pin_protocol_v1
|
||||
.process_subcommand(&mut rng, &mut persistent_store, client_pin_params)
|
||||
assert!(client_pin
|
||||
.process_command(&mut rng, &mut persistent_store, client_pin_params)
|
||||
.is_ok());
|
||||
|
||||
let client_pin_params = AuthenticatorClientPinParameters {
|
||||
pin_protocol: 2,
|
||||
pin_uv_auth_protocol: 2,
|
||||
sub_command: ClientPinSubCommand::GetPinRetries,
|
||||
key_agreement: None,
|
||||
pin_auth: None,
|
||||
@@ -992,7 +984,7 @@ mod test {
|
||||
};
|
||||
let error_code = Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER;
|
||||
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)
|
||||
);
|
||||
}
|
||||
@@ -1161,15 +1153,15 @@ mod test {
|
||||
#[test]
|
||||
fn test_has_permission() {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng);
|
||||
pin_protocol_v1.permissions = 0x7F;
|
||||
let mut client_pin = ClientPin::new(&mut rng);
|
||||
client_pin.permissions = 0x7F;
|
||||
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() {
|
||||
assert_eq!(
|
||||
pin_protocol_v1.has_permission(permission),
|
||||
client_pin.has_permission(permission),
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
|
||||
);
|
||||
}
|
||||
@@ -1178,12 +1170,12 @@ mod test {
|
||||
#[test]
|
||||
fn test_has_no_rp_id_permission() {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng);
|
||||
assert_eq!(pin_protocol_v1.has_no_rp_id_permission(), Ok(()));
|
||||
assert_eq!(pin_protocol_v1.permissions_rp_id, None);
|
||||
pin_protocol_v1.permissions_rp_id = Some("example.com".to_string());
|
||||
let mut client_pin = ClientPin::new(&mut rng);
|
||||
assert_eq!(client_pin.has_no_rp_id_permission(), Ok(()));
|
||||
assert_eq!(client_pin.permissions_rp_id, None);
|
||||
client_pin.permissions_rp_id = Some("example.com".to_string());
|
||||
assert_eq!(
|
||||
pin_protocol_v1.has_no_rp_id_permission(),
|
||||
client_pin.has_no_rp_id_permission(),
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
|
||||
);
|
||||
}
|
||||
@@ -1191,19 +1183,13 @@ mod test {
|
||||
#[test]
|
||||
fn test_has_no_or_rp_id_permission() {
|
||||
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!(
|
||||
pin_protocol_v1.has_no_or_rp_id_permission("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"),
|
||||
client_pin.has_no_or_rp_id_permission("another.example.com"),
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
|
||||
);
|
||||
}
|
||||
@@ -1211,20 +1197,20 @@ mod test {
|
||||
#[test]
|
||||
fn test_has_no_or_rp_id_hash_permission() {
|
||||
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");
|
||||
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(())
|
||||
);
|
||||
assert_eq!(pin_protocol_v1.permissions_rp_id, None);
|
||||
pin_protocol_v1.permissions_rp_id = Some("example.com".to_string());
|
||||
assert_eq!(client_pin.permissions_rp_id, None);
|
||||
client_pin.permissions_rp_id = Some("example.com".to_string());
|
||||
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(())
|
||||
);
|
||||
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)
|
||||
);
|
||||
}
|
||||
@@ -1232,21 +1218,15 @@ mod test {
|
||||
#[test]
|
||||
fn test_ensure_rp_id_permission() {
|
||||
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!(
|
||||
pin_protocol_v1.ensure_rp_id_permission("example.com"),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(
|
||||
pin_protocol_v1.permissions_rp_id,
|
||||
client_pin.permissions_rp_id,
|
||||
Some(String::from("example.com"))
|
||||
);
|
||||
assert_eq!(client_pin.ensure_rp_id_permission("example.com"), Ok(()));
|
||||
assert_eq!(
|
||||
pin_protocol_v1.ensure_rp_id_permission("example.com"),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(
|
||||
pin_protocol_v1.ensure_rp_id_permission("counter-example.com"),
|
||||
client_pin.ensure_rp_id_permission("counter-example.com"),
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
|
||||
);
|
||||
}
|
||||
@@ -304,7 +304,7 @@ impl TryFrom<cbor::Value> for AuthenticatorGetAssertionParameters {
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct AuthenticatorClientPinParameters {
|
||||
pub pin_protocol: u64,
|
||||
pub pin_uv_auth_protocol: u64,
|
||||
pub sub_command: ClientPinSubCommand,
|
||||
pub key_agreement: Option<CoseKey>,
|
||||
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> {
|
||||
destructure_cbor_map! {
|
||||
let {
|
||||
0x01 => pin_protocol,
|
||||
0x01 => pin_uv_auth_protocol,
|
||||
0x02 => sub_command,
|
||||
0x03 => key_agreement,
|
||||
0x04 => pin_auth,
|
||||
@@ -331,7 +331,7 @@ impl TryFrom<cbor::Value> for AuthenticatorClientPinParameters {
|
||||
} = 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 key_agreement = key_agreement.map(CoseKey::try_from).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()?;
|
||||
|
||||
Ok(AuthenticatorClientPinParameters {
|
||||
pin_protocol,
|
||||
pin_uv_auth_protocol,
|
||||
sub_command,
|
||||
key_agreement,
|
||||
pin_auth,
|
||||
@@ -506,7 +506,7 @@ impl TryFrom<cbor::Value> for AuthenticatorAttestationMaterial {
|
||||
pub struct AuthenticatorCredentialManagementParameters {
|
||||
pub sub_command: CredentialManagementSubCommand,
|
||||
pub sub_command_params: Option<CredentialManagementSubCommandParameters>,
|
||||
pub pin_protocol: Option<u64>,
|
||||
pub pin_uv_auth_protocol: Option<u64>,
|
||||
pub pin_auth: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
@@ -518,7 +518,7 @@ impl TryFrom<cbor::Value> for AuthenticatorCredentialManagementParameters {
|
||||
let {
|
||||
0x01 => sub_command,
|
||||
0x02 => sub_command_params,
|
||||
0x03 => pin_protocol,
|
||||
0x03 => pin_uv_auth_protocol,
|
||||
0x04 => pin_auth,
|
||||
} = extract_map(cbor_value)?;
|
||||
}
|
||||
@@ -527,13 +527,13 @@ impl TryFrom<cbor::Value> for AuthenticatorCredentialManagementParameters {
|
||||
let sub_command_params = sub_command_params
|
||||
.map(CredentialManagementSubCommandParameters::try_from)
|
||||
.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()?;
|
||||
|
||||
Ok(AuthenticatorCredentialManagementParameters {
|
||||
sub_command,
|
||||
sub_command_params,
|
||||
pin_protocol,
|
||||
pin_uv_auth_protocol,
|
||||
pin_auth,
|
||||
})
|
||||
}
|
||||
@@ -706,7 +706,7 @@ mod test {
|
||||
AuthenticatorClientPinParameters::try_from(cbor_value).unwrap();
|
||||
|
||||
let expected_client_pin_parameters = AuthenticatorClientPinParameters {
|
||||
pin_protocol: 1,
|
||||
pin_uv_auth_protocol: 1,
|
||||
sub_command: ClientPinSubCommand::GetPinRetries,
|
||||
key_agreement: Some(cose_key),
|
||||
pin_auth: Some(vec![0xBB]),
|
||||
@@ -765,7 +765,7 @@ mod test {
|
||||
let expected_cred_management_parameters = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::EnumerateCredentialsBegin,
|
||||
sub_command_params: Some(params),
|
||||
pin_protocol: Some(1),
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
pin_auth: Some(vec![0x9A; 16]),
|
||||
};
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::client_pin::ClientPin;
|
||||
use super::command::AuthenticatorConfigParameters;
|
||||
use super::data_formats::{ConfigSubCommand, ConfigSubCommandParams, SetMinPinLengthParams};
|
||||
use super::pin_protocol_v1::PinProtocolV1;
|
||||
use super::response::ResponseData;
|
||||
use super::status_code::Ctap2StatusCode;
|
||||
use super::storage::PersistentStore;
|
||||
@@ -76,7 +76,7 @@ fn process_set_min_pin_length(
|
||||
/// Processes the AuthenticatorConfig command.
|
||||
pub fn process_config(
|
||||
persistent_store: &mut PersistentStore,
|
||||
pin_protocol_v1: &mut PinProtocolV1,
|
||||
client_pin: &mut ClientPin,
|
||||
params: AuthenticatorConfigParameters,
|
||||
) -> Result<ResponseData, Ctap2StatusCode> {
|
||||
let AuthenticatorConfigParameters {
|
||||
@@ -103,7 +103,7 @@ pub fn process_config(
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -136,7 +136,7 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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 {
|
||||
sub_command: ConfigSubCommand::EnableEnterpriseAttestation,
|
||||
@@ -144,8 +144,7 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
|
||||
if ENTERPRISE_ATTESTATION_MODE.is_some() {
|
||||
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
|
||||
@@ -164,7 +163,7 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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 {
|
||||
sub_command: ConfigSubCommand::ToggleAlwaysUv,
|
||||
@@ -172,8 +171,7 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
|
||||
assert!(persistent_store.has_always_uv().unwrap());
|
||||
|
||||
@@ -183,8 +181,7 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
if ENFORCE_ALWAYS_UV {
|
||||
assert_eq!(
|
||||
config_response,
|
||||
@@ -202,7 +199,7 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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();
|
||||
|
||||
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_protocol: Some(1),
|
||||
};
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
if ENFORCE_ALWAYS_UV {
|
||||
assert_eq!(
|
||||
config_response,
|
||||
@@ -233,8 +229,7 @@ mod test {
|
||||
pin_uv_auth_param,
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
};
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
|
||||
assert!(!persistent_store.has_always_uv().unwrap());
|
||||
}
|
||||
@@ -264,13 +259,12 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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.
|
||||
let min_pin_length = 6;
|
||||
let config_params = create_min_pin_config_params(min_pin_length, None);
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
|
||||
assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length));
|
||||
|
||||
@@ -284,8 +278,7 @@ mod test {
|
||||
0xB2, 0xDE,
|
||||
];
|
||||
config_params.pin_uv_auth_param = Some(pin_auth);
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
|
||||
assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length));
|
||||
|
||||
@@ -296,8 +289,7 @@ mod test {
|
||||
0xA7, 0x71,
|
||||
];
|
||||
config_params.pin_uv_auth_param = Some(pin_auth);
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
assert_eq!(
|
||||
config_response,
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_PIN_POLICY_VIOLATION)
|
||||
@@ -311,15 +303,14 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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.
|
||||
let min_pin_length = 6;
|
||||
let min_pin_length_rp_ids = vec!["example.com".to_string()];
|
||||
let config_params =
|
||||
create_min_pin_config_params(min_pin_length, Some(min_pin_length_rp_ids.clone()));
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
|
||||
assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length));
|
||||
assert_eq!(
|
||||
@@ -339,8 +330,7 @@ mod test {
|
||||
0xD6, 0xDA,
|
||||
];
|
||||
config_params.pin_uv_auth_param = Some(pin_auth.clone());
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
|
||||
assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length));
|
||||
assert_eq!(
|
||||
@@ -353,8 +343,7 @@ mod test {
|
||||
let mut config_params =
|
||||
create_min_pin_config_params(9, Some(min_pin_length_rp_ids.clone()));
|
||||
config_params.pin_uv_auth_param = Some(pin_auth.clone());
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
assert_eq!(
|
||||
config_response,
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
|
||||
@@ -372,8 +361,7 @@ mod test {
|
||||
Some(vec!["counter.example.com".to_string()]),
|
||||
);
|
||||
config_params.pin_uv_auth_param = Some(pin_auth);
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
assert_eq!(
|
||||
config_response,
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
|
||||
@@ -391,7 +379,7 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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();
|
||||
// Increase min PIN, force PIN change.
|
||||
@@ -402,8 +390,7 @@ mod test {
|
||||
0xA8, 0xC8,
|
||||
]);
|
||||
config_params.pin_uv_auth_param = pin_uv_auth_param;
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
|
||||
assert_eq!(persistent_store.min_pin_length(), Ok(min_pin_length));
|
||||
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 key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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();
|
||||
let pin_uv_auth_param = Some(vec![
|
||||
@@ -435,8 +422,7 @@ mod test {
|
||||
pin_uv_auth_param,
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
};
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
|
||||
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 key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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 {
|
||||
sub_command: ConfigSubCommand::VendorPrototype,
|
||||
@@ -455,8 +441,7 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let config_response =
|
||||
process_config(&mut persistent_store, &mut pin_protocol_v1, config_params);
|
||||
let config_response = process_config(&mut persistent_store, &mut client_pin, config_params);
|
||||
assert_eq!(
|
||||
config_response,
|
||||
Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER)
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::client_pin::{ClientPin, PinPermission};
|
||||
use super::command::AuthenticatorCredentialManagementParameters;
|
||||
use super::data_formats::{
|
||||
CoseKey, CredentialManagementSubCommand, CredentialManagementSubCommandParameters,
|
||||
PublicKeyCredentialDescriptor, PublicKeyCredentialRpEntity, PublicKeyCredentialSource,
|
||||
PublicKeyCredentialUserEntity,
|
||||
};
|
||||
use super::pin_protocol_v1::{PinPermission, PinProtocolV1};
|
||||
use super::response::{AuthenticatorCredentialManagementResponse, ResponseData};
|
||||
use super::status_code::Ctap2StatusCode;
|
||||
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.
|
||||
fn check_rp_id_permissions(
|
||||
persistent_store: &mut PersistentStore,
|
||||
pin_protocol_v1: &mut PinProtocolV1,
|
||||
client_pin: &mut ClientPin,
|
||||
credential_id: &[u8],
|
||||
) -> Result<(), Ctap2StatusCode> {
|
||||
// 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(());
|
||||
}
|
||||
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.
|
||||
@@ -173,14 +173,14 @@ fn process_enumerate_rps_get_next_rp(
|
||||
fn process_enumerate_credentials_begin(
|
||||
persistent_store: &PersistentStore,
|
||||
stateful_command_permission: &mut StatefulPermission,
|
||||
pin_protocol_v1: &mut PinProtocolV1,
|
||||
client_pin: &mut ClientPin,
|
||||
sub_command_params: CredentialManagementSubCommandParameters,
|
||||
now: ClockValue,
|
||||
) -> Result<AuthenticatorCredentialManagementResponse, Ctap2StatusCode> {
|
||||
let rp_id_hash = sub_command_params
|
||||
.rp_id_hash
|
||||
.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 iter = persistent_store.iter_credentials(&mut iter_result)?;
|
||||
let mut rp_credentials: Vec<usize> = iter
|
||||
@@ -219,21 +219,21 @@ fn process_enumerate_credentials_get_next_credential(
|
||||
/// Processes the subcommand deleteCredential for CredentialManagement.
|
||||
fn process_delete_credential(
|
||||
persistent_store: &mut PersistentStore,
|
||||
pin_protocol_v1: &mut PinProtocolV1,
|
||||
client_pin: &mut ClientPin,
|
||||
sub_command_params: CredentialManagementSubCommandParameters,
|
||||
) -> Result<(), Ctap2StatusCode> {
|
||||
let credential_id = sub_command_params
|
||||
.credential_id
|
||||
.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?
|
||||
.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)
|
||||
}
|
||||
|
||||
/// Processes the subcommand updateUserInformation for CredentialManagement.
|
||||
fn process_update_user_information(
|
||||
persistent_store: &mut PersistentStore,
|
||||
pin_protocol_v1: &mut PinProtocolV1,
|
||||
client_pin: &mut ClientPin,
|
||||
sub_command_params: CredentialManagementSubCommandParameters,
|
||||
) -> Result<(), Ctap2StatusCode> {
|
||||
let credential_id = sub_command_params
|
||||
@@ -243,7 +243,7 @@ fn process_update_user_information(
|
||||
let user = sub_command_params
|
||||
.user
|
||||
.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)
|
||||
}
|
||||
|
||||
@@ -251,14 +251,14 @@ fn process_update_user_information(
|
||||
pub fn process_credential_management(
|
||||
persistent_store: &mut PersistentStore,
|
||||
stateful_command_permission: &mut StatefulPermission,
|
||||
pin_protocol_v1: &mut PinProtocolV1,
|
||||
client_pin: &mut ClientPin,
|
||||
cred_management_params: AuthenticatorCredentialManagementParameters,
|
||||
now: ClockValue,
|
||||
) -> Result<ResponseData, Ctap2StatusCode> {
|
||||
let AuthenticatorCredentialManagementParameters {
|
||||
sub_command,
|
||||
sub_command_params,
|
||||
pin_protocol,
|
||||
pin_uv_auth_protocol,
|
||||
pin_auth,
|
||||
} = cred_management_params;
|
||||
|
||||
@@ -282,7 +282,7 @@ pub fn process_credential_management(
|
||||
| CredentialManagementSubCommand::EnumerateCredentialsBegin
|
||||
| CredentialManagementSubCommand::DeleteCredential
|
||||
| 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 mut management_data = vec![sub_command as u8];
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
// 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::EnumerateCredentialsGetNextCredential => {}
|
||||
@@ -302,11 +302,11 @@ pub fn process_credential_management(
|
||||
|
||||
let response = match sub_command {
|
||||
CredentialManagementSubCommand::GetCredsMetadata => {
|
||||
pin_protocol_v1.has_no_rp_id_permission()?;
|
||||
client_pin.has_no_rp_id_permission()?;
|
||||
Some(process_get_creds_metadata(persistent_store)?)
|
||||
}
|
||||
CredentialManagementSubCommand::EnumerateRpsBegin => {
|
||||
pin_protocol_v1.has_no_rp_id_permission()?;
|
||||
client_pin.has_no_rp_id_permission()?;
|
||||
Some(process_enumerate_rps_begin(
|
||||
persistent_store,
|
||||
stateful_command_permission,
|
||||
@@ -320,7 +320,7 @@ pub fn process_credential_management(
|
||||
Some(process_enumerate_credentials_begin(
|
||||
persistent_store,
|
||||
stateful_command_permission,
|
||||
pin_protocol_v1,
|
||||
client_pin,
|
||||
sub_command_params.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?,
|
||||
now,
|
||||
)?)
|
||||
@@ -334,7 +334,7 @@ pub fn process_credential_management(
|
||||
CredentialManagementSubCommand::DeleteCredential => {
|
||||
process_delete_credential(
|
||||
persistent_store,
|
||||
pin_protocol_v1,
|
||||
client_pin,
|
||||
sub_command_params.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?,
|
||||
)?;
|
||||
None
|
||||
@@ -342,7 +342,7 @@ pub fn process_credential_management(
|
||||
CredentialManagementSubCommand::UpdateUserInformation => {
|
||||
process_update_user_information(
|
||||
persistent_store,
|
||||
pin_protocol_v1,
|
||||
client_pin,
|
||||
sub_command_params.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?,
|
||||
)?;
|
||||
None
|
||||
@@ -384,12 +384,12 @@ mod test {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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 user_immediately_present = |_| Ok(());
|
||||
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();
|
||||
let pin_auth = Some(vec![
|
||||
@@ -400,13 +400,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::GetCredsMetadata,
|
||||
sub_command_params: None,
|
||||
pin_protocol: Some(1),
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
pin_auth: pin_auth.clone(),
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -428,13 +428,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::GetCredsMetadata,
|
||||
sub_command_params: None,
|
||||
pin_protocol: Some(1),
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
pin_auth,
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -455,14 +455,14 @@ mod test {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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 mut credential_source2 = create_credential_source(&mut rng);
|
||||
credential_source2.rp_id = "another.example.com".to_string();
|
||||
|
||||
let user_immediately_present = |_| Ok(());
|
||||
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
|
||||
@@ -482,13 +482,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::EnumerateRpsBegin,
|
||||
sub_command_params: None,
|
||||
pin_protocol: Some(1),
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
pin_auth,
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -506,13 +506,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::EnumerateRpsGetNextRp,
|
||||
sub_command_params: None,
|
||||
pin_protocol: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
pin_auth: None,
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -531,13 +531,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::EnumerateRpsGetNextRp,
|
||||
sub_command_params: None,
|
||||
pin_protocol: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
pin_auth: None,
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -552,12 +552,12 @@ mod test {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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 user_immediately_present = |_| Ok(());
|
||||
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;
|
||||
for i in 0..NUM_CREDENTIALS {
|
||||
@@ -581,7 +581,7 @@ mod test {
|
||||
let mut cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::EnumerateRpsBegin,
|
||||
sub_command_params: None,
|
||||
pin_protocol: Some(1),
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
pin_auth,
|
||||
};
|
||||
|
||||
@@ -589,7 +589,7 @@ mod test {
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -611,7 +611,7 @@ mod test {
|
||||
cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::EnumerateRpsGetNextRp,
|
||||
sub_command_params: None,
|
||||
pin_protocol: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
pin_auth: None,
|
||||
};
|
||||
}
|
||||
@@ -619,7 +619,7 @@ mod test {
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -634,7 +634,7 @@ mod test {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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 mut credential_source2 = create_credential_source(&mut rng);
|
||||
credential_source2.user_handle = vec![0x02];
|
||||
@@ -644,7 +644,7 @@ mod test {
|
||||
|
||||
let user_immediately_present = |_| Ok(());
|
||||
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
|
||||
@@ -671,13 +671,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::EnumerateCredentialsBegin,
|
||||
sub_command_params: Some(sub_command_params),
|
||||
pin_protocol: Some(1),
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
pin_auth,
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -694,13 +694,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::EnumerateCredentialsGetNextCredential,
|
||||
sub_command_params: None,
|
||||
pin_protocol: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
pin_auth: None,
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -718,13 +718,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::EnumerateCredentialsGetNextCredential,
|
||||
sub_command_params: None,
|
||||
pin_protocol: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
pin_auth: None,
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -739,13 +739,13 @@ mod test {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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);
|
||||
credential_source.credential_id = vec![0x1D; 32];
|
||||
|
||||
let user_immediately_present = |_| Ok(());
|
||||
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
|
||||
@@ -771,13 +771,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::DeleteCredential,
|
||||
sub_command_params: Some(sub_command_params.clone()),
|
||||
pin_protocol: Some(1),
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
pin_auth: pin_auth.clone(),
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -789,13 +789,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::DeleteCredential,
|
||||
sub_command_params: Some(sub_command_params),
|
||||
pin_protocol: Some(1),
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
pin_auth,
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -810,13 +810,13 @@ mod test {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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);
|
||||
credential_source.credential_id = vec![0x1D; 32];
|
||||
|
||||
let user_immediately_present = |_| Ok(());
|
||||
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
|
||||
@@ -848,13 +848,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::UpdateUserInformation,
|
||||
sub_command_params: Some(sub_command_params),
|
||||
pin_protocol: Some(1),
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
pin_auth,
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -878,15 +878,15 @@ mod 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 key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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 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();
|
||||
let pin_auth = Some(vec![
|
||||
@@ -897,13 +897,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::GetCredsMetadata,
|
||||
sub_command_params: None,
|
||||
pin_protocol: Some(123456),
|
||||
pin_uv_auth_protocol: Some(123456),
|
||||
pin_auth,
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
@@ -924,13 +924,13 @@ mod test {
|
||||
let cred_management_params = AuthenticatorCredentialManagementParameters {
|
||||
sub_command: CredentialManagementSubCommand::GetCredsMetadata,
|
||||
sub_command_params: None,
|
||||
pin_protocol: Some(1),
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
pin_auth: Some(vec![0u8; 16]),
|
||||
};
|
||||
let cred_management_response = process_credential_management(
|
||||
&mut ctap_state.persistent_store,
|
||||
&mut ctap_state.stateful_command_permission,
|
||||
&mut ctap_state.pin_protocol_v1,
|
||||
&mut ctap_state.client_pin,
|
||||
cred_management_params,
|
||||
DUMMY_CLOCK_VALUE,
|
||||
);
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
// limitations under the License.
|
||||
|
||||
use super::check_pin_uv_auth_protocol;
|
||||
use super::client_pin::{ClientPin, PinPermission};
|
||||
use super::command::AuthenticatorLargeBlobsParameters;
|
||||
use super::pin_protocol_v1::{PinPermission, PinProtocolV1};
|
||||
use super::response::{AuthenticatorLargeBlobsResponse, ResponseData};
|
||||
use super::status_code::Ctap2StatusCode;
|
||||
use super::storage::PersistentStore;
|
||||
@@ -51,7 +51,7 @@ impl LargeBlobs {
|
||||
pub fn process_command(
|
||||
&mut self,
|
||||
persistent_store: &mut PersistentStore,
|
||||
pin_protocol_v1: &mut PinProtocolV1,
|
||||
client_pin: &mut ClientPin,
|
||||
large_blobs_params: AuthenticatorLargeBlobsParameters,
|
||||
) -> Result<ResponseData, Ctap2StatusCode> {
|
||||
let AuthenticatorLargeBlobsParameters {
|
||||
@@ -94,14 +94,14 @@ impl LargeBlobs {
|
||||
// TODO(kaczmarczyck) Error codes for PIN protocol differ across commands.
|
||||
// Change to Ctap2StatusCode::CTAP2_ERR_PUAT_REQUIRED for None?
|
||||
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];
|
||||
message.extend(&[0x0C, 0x00]);
|
||||
let mut offset_bytes = [0u8; 4];
|
||||
LittleEndian::write_u32(&mut offset_bytes, offset as u32);
|
||||
message.extend(&offset_bytes);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -146,7 +146,7 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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 large_blob = vec![
|
||||
@@ -161,11 +161,8 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let large_blobs_response = large_blobs.process_command(
|
||||
&mut persistent_store,
|
||||
&mut pin_protocol_v1,
|
||||
large_blobs_params,
|
||||
);
|
||||
let large_blobs_response =
|
||||
large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
|
||||
match large_blobs_response.unwrap() {
|
||||
ResponseData::AuthenticatorLargeBlobs(Some(response)) => {
|
||||
assert_eq!(response.config, large_blob);
|
||||
@@ -180,7 +177,7 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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();
|
||||
|
||||
const BLOB_LEN: usize = 200;
|
||||
@@ -196,11 +193,8 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let large_blobs_response = large_blobs.process_command(
|
||||
&mut persistent_store,
|
||||
&mut pin_protocol_v1,
|
||||
large_blobs_params,
|
||||
);
|
||||
let large_blobs_response =
|
||||
large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
|
||||
assert_eq!(
|
||||
large_blobs_response,
|
||||
Ok(ResponseData::AuthenticatorLargeBlobs(None))
|
||||
@@ -214,11 +208,8 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let large_blobs_response = large_blobs.process_command(
|
||||
&mut persistent_store,
|
||||
&mut pin_protocol_v1,
|
||||
large_blobs_params,
|
||||
);
|
||||
let large_blobs_response =
|
||||
large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
|
||||
assert_eq!(
|
||||
large_blobs_response,
|
||||
Ok(ResponseData::AuthenticatorLargeBlobs(None))
|
||||
@@ -232,11 +223,8 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let large_blobs_response = large_blobs.process_command(
|
||||
&mut persistent_store,
|
||||
&mut pin_protocol_v1,
|
||||
large_blobs_params,
|
||||
);
|
||||
let large_blobs_response =
|
||||
large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
|
||||
match large_blobs_response.unwrap() {
|
||||
ResponseData::AuthenticatorLargeBlobs(Some(response)) => {
|
||||
assert_eq!(response.config, large_blob);
|
||||
@@ -251,7 +239,7 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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();
|
||||
|
||||
const BLOB_LEN: usize = 200;
|
||||
@@ -267,11 +255,8 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let large_blobs_response = large_blobs.process_command(
|
||||
&mut persistent_store,
|
||||
&mut pin_protocol_v1,
|
||||
large_blobs_params,
|
||||
);
|
||||
let large_blobs_response =
|
||||
large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
|
||||
assert_eq!(
|
||||
large_blobs_response,
|
||||
Ok(ResponseData::AuthenticatorLargeBlobs(None))
|
||||
@@ -286,11 +271,8 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let large_blobs_response = large_blobs.process_command(
|
||||
&mut persistent_store,
|
||||
&mut pin_protocol_v1,
|
||||
large_blobs_params,
|
||||
);
|
||||
let large_blobs_response =
|
||||
large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
|
||||
assert_eq!(
|
||||
large_blobs_response,
|
||||
Err(Ctap2StatusCode::CTAP1_ERR_INVALID_SEQ),
|
||||
@@ -303,7 +285,7 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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();
|
||||
|
||||
const BLOB_LEN: usize = 200;
|
||||
@@ -320,11 +302,8 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let large_blobs_response = large_blobs.process_command(
|
||||
&mut persistent_store,
|
||||
&mut pin_protocol_v1,
|
||||
large_blobs_params,
|
||||
);
|
||||
let large_blobs_response =
|
||||
large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
|
||||
assert_eq!(
|
||||
large_blobs_response,
|
||||
Ok(ResponseData::AuthenticatorLargeBlobs(None))
|
||||
@@ -338,11 +317,8 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let large_blobs_response = large_blobs.process_command(
|
||||
&mut persistent_store,
|
||||
&mut pin_protocol_v1,
|
||||
large_blobs_params,
|
||||
);
|
||||
let large_blobs_response =
|
||||
large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
|
||||
assert_eq!(
|
||||
large_blobs_response,
|
||||
Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER),
|
||||
@@ -355,7 +331,7 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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();
|
||||
|
||||
const BLOB_LEN: usize = 20;
|
||||
@@ -370,11 +346,8 @@ mod test {
|
||||
pin_uv_auth_param: None,
|
||||
pin_uv_auth_protocol: None,
|
||||
};
|
||||
let large_blobs_response = large_blobs.process_command(
|
||||
&mut persistent_store,
|
||||
&mut pin_protocol_v1,
|
||||
large_blobs_params,
|
||||
);
|
||||
let large_blobs_response =
|
||||
large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
|
||||
assert_eq!(
|
||||
large_blobs_response,
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_INTEGRITY_FAILURE),
|
||||
@@ -387,7 +360,7 @@ mod test {
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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();
|
||||
|
||||
const BLOB_LEN: usize = 20;
|
||||
@@ -409,11 +382,8 @@ mod test {
|
||||
pin_uv_auth_param,
|
||||
pin_uv_auth_protocol: Some(1),
|
||||
};
|
||||
let large_blobs_response = large_blobs.process_command(
|
||||
&mut persistent_store,
|
||||
&mut pin_protocol_v1,
|
||||
large_blobs_params,
|
||||
);
|
||||
let large_blobs_response =
|
||||
large_blobs.process_command(&mut persistent_store, &mut client_pin, large_blobs_params);
|
||||
assert_eq!(
|
||||
large_blobs_response,
|
||||
Ok(ResponseData::AuthenticatorLargeBlobs(None))
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
pub mod apdu;
|
||||
mod client_pin;
|
||||
pub mod command;
|
||||
mod config_command;
|
||||
mod credential_management;
|
||||
@@ -23,15 +24,15 @@ pub mod data_formats;
|
||||
pub mod hid;
|
||||
mod key_material;
|
||||
mod large_blobs;
|
||||
mod pin_protocol_v1;
|
||||
pub mod response;
|
||||
pub mod status_code;
|
||||
mod storage;
|
||||
mod timed_permission;
|
||||
|
||||
use self::client_pin::{ClientPin, PinPermission};
|
||||
use self::command::{
|
||||
AuthenticatorClientPinParameters, AuthenticatorGetAssertionParameters,
|
||||
AuthenticatorMakeCredentialParameters, AuthenticatorVendorConfigureParameters, Command,
|
||||
AuthenticatorGetAssertionParameters, AuthenticatorMakeCredentialParameters,
|
||||
AuthenticatorVendorConfigureParameters, Command,
|
||||
};
|
||||
use self::config_command::process_config;
|
||||
use self::credential_management::process_credential_management;
|
||||
@@ -48,7 +49,6 @@ use self::data_formats::{
|
||||
};
|
||||
use self::hid::ChannelID;
|
||||
use self::large_blobs::{LargeBlobs, MAX_MSG_SIZE};
|
||||
use self::pin_protocol_v1::{PinPermission, PinProtocolV1};
|
||||
use self::response::{
|
||||
AuthenticatorGetAssertionResponse, AuthenticatorGetInfoResponse,
|
||||
AuthenticatorMakeCredentialResponse, AuthenticatorVendorResponse, ResponseData,
|
||||
@@ -278,7 +278,7 @@ pub struct CtapState<'a, R: Rng256, CheckUserPresence: Fn(ChannelID) -> Result<(
|
||||
// false otherwise.
|
||||
check_user_presence: CheckUserPresence,
|
||||
persistent_store: PersistentStore,
|
||||
pin_protocol_v1: PinProtocolV1,
|
||||
client_pin: ClientPin,
|
||||
#[cfg(feature = "with_ctap1")]
|
||||
pub u2f_up_state: U2fUserPresenceState,
|
||||
// The state initializes to Reset and its timeout, and never goes back to Reset.
|
||||
@@ -297,12 +297,12 @@ where
|
||||
now: ClockValue,
|
||||
) -> CtapState<'a, R, CheckUserPresence> {
|
||||
let persistent_store = PersistentStore::new(rng);
|
||||
let pin_protocol_v1 = PinProtocolV1::new(rng);
|
||||
let client_pin = ClientPin::new(rng);
|
||||
CtapState {
|
||||
rng,
|
||||
check_user_presence,
|
||||
persistent_store,
|
||||
pin_protocol_v1,
|
||||
client_pin,
|
||||
#[cfg(feature = "with_ctap1")]
|
||||
u2f_up_state: U2fUserPresenceState::new(
|
||||
U2F_UP_PROMPT_TIMEOUT,
|
||||
@@ -473,13 +473,17 @@ where
|
||||
}
|
||||
Command::AuthenticatorGetNextAssertion => self.process_get_next_assertion(now),
|
||||
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::AuthenticatorCredentialManagement(params) => {
|
||||
process_credential_management(
|
||||
&mut self.persistent_store,
|
||||
&mut self.stateful_command_permission,
|
||||
&mut self.pin_protocol_v1,
|
||||
&mut self.client_pin,
|
||||
params,
|
||||
now,
|
||||
)
|
||||
@@ -487,14 +491,12 @@ where
|
||||
Command::AuthenticatorSelection => self.process_selection(cid),
|
||||
Command::AuthenticatorLargeBlobs(params) => self.large_blobs.process_command(
|
||||
&mut self.persistent_store,
|
||||
&mut self.pin_protocol_v1,
|
||||
params,
|
||||
),
|
||||
Command::AuthenticatorConfig(params) => process_config(
|
||||
&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.client_pin, params)
|
||||
}
|
||||
// Vendor specific commands
|
||||
Command::AuthenticatorVendorConfigure(params) => {
|
||||
self.process_vendor_configure(params, cid)
|
||||
@@ -647,14 +649,14 @@ where
|
||||
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_NOT_SET);
|
||||
}
|
||||
if !self
|
||||
.pin_protocol_v1
|
||||
.client_pin
|
||||
.verify_pin_auth_token(&client_data_hash, &pin_auth)
|
||||
{
|
||||
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID);
|
||||
}
|
||||
self.pin_protocol_v1
|
||||
self.client_pin
|
||||
.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
|
||||
}
|
||||
None => {
|
||||
@@ -815,7 +817,7 @@ where
|
||||
let encrypted_output = if let Some(hmac_secret_input) = extensions.hmac_secret {
|
||||
let cred_random = self.generate_cred_random(&credential.private_key, has_uv)?;
|
||||
Some(
|
||||
self.pin_protocol_v1
|
||||
self.client_pin
|
||||
.process_hmac_secret(hmac_secret_input, &cred_random)?,
|
||||
)
|
||||
} else {
|
||||
@@ -938,14 +940,14 @@ where
|
||||
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_NOT_SET);
|
||||
}
|
||||
if !self
|
||||
.pin_protocol_v1
|
||||
.client_pin
|
||||
.verify_pin_auth_token(&client_data_hash, &pin_auth)
|
||||
{
|
||||
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID);
|
||||
}
|
||||
self.pin_protocol_v1
|
||||
self.client_pin
|
||||
.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
|
||||
}
|
||||
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(
|
||||
&mut self,
|
||||
cid: ChannelID,
|
||||
@@ -1129,7 +1120,7 @@ where
|
||||
(self.check_user_presence)(cid)?;
|
||||
|
||||
self.persistent_store.reset(self.rng)?;
|
||||
self.pin_protocol_v1.reset(self.rng);
|
||||
self.client_pin.reset(self.rng);
|
||||
#[cfg(feature = "with_ctap1")]
|
||||
{
|
||||
self.u2f_up_state = U2fUserPresenceState::new(
|
||||
@@ -2332,11 +2323,11 @@ mod test {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let key_agreement_key = crypto::ecdh::SecKey::gensk(&mut rng);
|
||||
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 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 user1 = PublicKeyCredentialUserEntity {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
mod key;
|
||||
|
||||
use crate::ctap::client_pin::PIN_AUTH_LENGTH;
|
||||
use crate::ctap::customization::{
|
||||
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,
|
||||
@@ -24,7 +25,6 @@ use crate::ctap::data_formats::{
|
||||
PublicKeyCredentialUserEntity,
|
||||
};
|
||||
use crate::ctap::key_material;
|
||||
use crate::ctap::pin_protocol_v1::PIN_AUTH_LENGTH;
|
||||
use crate::ctap::status_code::Ctap2StatusCode;
|
||||
use crate::ctap::INITIAL_SIGNATURE_COUNTER;
|
||||
use crate::embedded_flash::{new_storage, Storage};
|
||||
|
||||
Reference in New Issue
Block a user