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,
|
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)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -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]),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|||||||
Reference in New Issue
Block a user