adds the config command
This commit is contained in:
@@ -17,6 +17,7 @@ use super::data_formats::{ClientPinSubCommand, CoseKey, GetAssertionHmacSecretIn
|
||||
use super::response::{AuthenticatorClientPinResponse, ResponseData};
|
||||
use super::status_code::Ctap2StatusCode;
|
||||
use super::storage::PersistentStore;
|
||||
use alloc::str;
|
||||
use alloc::string::String;
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
@@ -141,13 +142,14 @@ fn check_and_store_new_pin(
|
||||
.ok_or(Ctap2StatusCode::CTAP2_ERR_PIN_POLICY_VIOLATION)?;
|
||||
|
||||
let min_pin_length = persistent_store.min_pin_length()? as usize;
|
||||
if pin.len() < min_pin_length || pin.len() == PIN_PADDED_LENGTH {
|
||||
// TODO(kaczmarczyck) check 4 code point minimum instead
|
||||
let pin_length = str::from_utf8(&pin).unwrap_or("").chars().count();
|
||||
if pin_length < min_pin_length || pin.len() == PIN_PADDED_LENGTH {
|
||||
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_POLICY_VIOLATION);
|
||||
}
|
||||
let mut pin_hash = [0u8; 16];
|
||||
pin_hash.copy_from_slice(&Sha256::hash(&pin[..])[..16]);
|
||||
persistent_store.set_pin_hash(&pin_hash)?;
|
||||
// The PIN length is always < 64.
|
||||
persistent_store.set_pin(&pin_hash, pin_length as u8)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -170,6 +172,7 @@ pub struct PinProtocolV1 {
|
||||
consecutive_pin_mismatches: u8,
|
||||
permissions: u8,
|
||||
permissions_rp_id: Option<String>,
|
||||
pub force_pin_change: bool,
|
||||
}
|
||||
|
||||
impl PinProtocolV1 {
|
||||
@@ -182,6 +185,7 @@ impl PinProtocolV1 {
|
||||
consecutive_pin_mismatches: 0,
|
||||
permissions: 0,
|
||||
permissions_rp_id: None,
|
||||
force_pin_change: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,54 +367,6 @@ impl PinProtocolV1 {
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_INVALID_SUBCOMMAND)
|
||||
}
|
||||
|
||||
fn process_set_min_pin_length(
|
||||
&mut self,
|
||||
persistent_store: &mut PersistentStore,
|
||||
min_pin_length: u8,
|
||||
min_pin_length_rp_ids: Option<Vec<String>>,
|
||||
pin_auth: Option<Vec<u8>>,
|
||||
) -> Result<(), Ctap2StatusCode> {
|
||||
if min_pin_length_rp_ids.is_some() {
|
||||
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
||||
}
|
||||
if persistent_store.pin_hash()?.is_some() {
|
||||
match pin_auth {
|
||||
Some(pin_auth) => {
|
||||
if self.consecutive_pin_mismatches >= 3 {
|
||||
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_BLOCKED);
|
||||
}
|
||||
// TODO(kaczmarczyck) Values are taken from the (not yet public) new revision
|
||||
// of CTAP 2.1. The code should link the specification when published.
|
||||
// From CTAP2.1: "If request contains pinUvAuthParam, the Authenticator calls
|
||||
// verify(pinUvAuthToken, 32×0xff || 0x0608 || uint32LittleEndian(minPINLength)
|
||||
// || minPinLengthRPIDs, pinUvAuthParam)"
|
||||
let mut message = vec![0xFF; 32];
|
||||
message.extend(&[0x06, 0x08]);
|
||||
message.extend(&[min_pin_length as u8, 0x00, 0x00, 0x00]);
|
||||
// TODO(kaczmarczyck) commented code is useful for the extension
|
||||
// https://github.com/google/OpenSK/issues/129
|
||||
// if !cbor::write(cbor_array_vec!(min_pin_length_rp_ids), &mut message) {
|
||||
// return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
||||
// }
|
||||
if !verify_pin_auth(&self.pin_uv_auth_token, &message, &pin_auth) {
|
||||
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID);
|
||||
}
|
||||
}
|
||||
None => return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID),
|
||||
};
|
||||
}
|
||||
if min_pin_length < persistent_store.min_pin_length()? {
|
||||
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_POLICY_VIOLATION);
|
||||
}
|
||||
persistent_store.set_min_pin_length(min_pin_length)?;
|
||||
// TODO(kaczmarczyck) commented code is useful for the extension
|
||||
// https://github.com/google/OpenSK/issues/129
|
||||
// if let Some(min_pin_length_rp_ids) = min_pin_length_rp_ids {
|
||||
// persistent_store.set_min_pin_length_rp_ids(min_pin_length_rp_ids)?;
|
||||
// }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process_get_pin_uv_auth_token_using_pin_with_permissions(
|
||||
&mut self,
|
||||
rng: &mut impl Rng256,
|
||||
@@ -450,8 +406,6 @@ impl PinProtocolV1 {
|
||||
pin_auth,
|
||||
new_pin_enc,
|
||||
pin_hash_enc,
|
||||
min_pin_length,
|
||||
min_pin_length_rp_ids,
|
||||
permissions,
|
||||
permissions_rp_id,
|
||||
} = client_pin_params;
|
||||
@@ -499,15 +453,6 @@ impl PinProtocolV1 {
|
||||
)?,
|
||||
),
|
||||
ClientPinSubCommand::GetUvRetries => Some(self.process_get_uv_retries()?),
|
||||
ClientPinSubCommand::SetMinPinLength => {
|
||||
self.process_set_min_pin_length(
|
||||
persistent_store,
|
||||
min_pin_length.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?,
|
||||
min_pin_length_rp_ids,
|
||||
pin_auth,
|
||||
)?;
|
||||
None
|
||||
}
|
||||
ClientPinSubCommand::GetPinUvAuthTokenUsingPinWithPermissions => Some(
|
||||
self.process_get_pin_uv_auth_token_using_pin_with_permissions(
|
||||
rng,
|
||||
@@ -577,7 +522,7 @@ impl PinProtocolV1 {
|
||||
#[cfg(test)]
|
||||
pub fn new_test(
|
||||
key_agreement_key: crypto::ecdh::SecKey,
|
||||
pin_uv_auth_token: [u8; 32],
|
||||
pin_uv_auth_token: [u8; PIN_TOKEN_LENGTH],
|
||||
) -> PinProtocolV1 {
|
||||
PinProtocolV1 {
|
||||
key_agreement_key,
|
||||
@@ -585,6 +530,7 @@ impl PinProtocolV1 {
|
||||
consecutive_pin_mismatches: 0,
|
||||
permissions: 0xFF,
|
||||
permissions_rp_id: None,
|
||||
force_pin_change: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -600,7 +546,7 @@ mod test {
|
||||
pin[..4].copy_from_slice(b"1234");
|
||||
let mut pin_hash = [0u8; 16];
|
||||
pin_hash.copy_from_slice(&Sha256::hash(&pin[..])[..16]);
|
||||
persistent_store.set_pin_hash(&pin_hash).unwrap();
|
||||
persistent_store.set_pin(&pin_hash, 4).unwrap();
|
||||
}
|
||||
|
||||
// Encrypts the message with a zero IV and key derived from shared_secret.
|
||||
@@ -662,7 +608,7 @@ mod test {
|
||||
0x01, 0xD9, 0x88, 0x40, 0x50, 0xBB, 0xD0, 0x7A, 0x23, 0x1A, 0xEB, 0x69, 0xD8, 0x36,
|
||||
0xC4, 0x12,
|
||||
];
|
||||
persistent_store.set_pin_hash(&pin_hash).unwrap();
|
||||
persistent_store.set_pin(&pin_hash, 4).unwrap();
|
||||
let shared_secret = [0x88; 32];
|
||||
let aes_enc_key = crypto::aes256::EncryptionKey::new(&shared_secret);
|
||||
let aes_dec_key = crypto::aes256::DecryptionKey::new(&aes_enc_key);
|
||||
@@ -935,40 +881,6 @@ mod test {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_process_set_min_pin_length() {
|
||||
let mut rng = ThreadRng256 {};
|
||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng);
|
||||
let min_pin_length = 8;
|
||||
pin_protocol_v1.pin_uv_auth_token = [0x55; PIN_TOKEN_LENGTH];
|
||||
let pin_auth = vec![
|
||||
0x94, 0x86, 0xEF, 0x4C, 0xB3, 0x84, 0x2C, 0x85, 0x72, 0x02, 0xBF, 0xE4, 0x36, 0x22,
|
||||
0xFE, 0xC9,
|
||||
];
|
||||
// TODO(kaczmarczyck) implement test for the min PIN length extension
|
||||
// https://github.com/google/OpenSK/issues/129
|
||||
let response = pin_protocol_v1.process_set_min_pin_length(
|
||||
&mut persistent_store,
|
||||
min_pin_length,
|
||||
None,
|
||||
Some(pin_auth.clone()),
|
||||
);
|
||||
assert_eq!(response, Ok(()));
|
||||
assert_eq!(persistent_store.min_pin_length().unwrap(), min_pin_length);
|
||||
let response = pin_protocol_v1.process_set_min_pin_length(
|
||||
&mut persistent_store,
|
||||
7,
|
||||
None,
|
||||
Some(pin_auth),
|
||||
);
|
||||
assert_eq!(
|
||||
response,
|
||||
Err(Ctap2StatusCode::CTAP2_ERR_PIN_POLICY_VIOLATION)
|
||||
);
|
||||
assert_eq!(persistent_store.min_pin_length().unwrap(), min_pin_length);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_process() {
|
||||
let mut rng = ThreadRng256 {};
|
||||
@@ -981,8 +893,6 @@ mod test {
|
||||
pin_auth: None,
|
||||
new_pin_enc: None,
|
||||
pin_hash_enc: None,
|
||||
min_pin_length: None,
|
||||
min_pin_length_rp_ids: None,
|
||||
permissions: None,
|
||||
permissions_rp_id: None,
|
||||
};
|
||||
@@ -997,8 +907,6 @@ mod test {
|
||||
pin_auth: None,
|
||||
new_pin_enc: None,
|
||||
pin_hash_enc: None,
|
||||
min_pin_length: None,
|
||||
min_pin_length_rp_ids: None,
|
||||
permissions: None,
|
||||
permissions_rp_id: None,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user