Merge develop into command-cred-mgmt

This commit is contained in:
Fabian Kaczmarczyck
2021-01-14 16:02:30 +01:00
19 changed files with 815 additions and 377 deletions

View File

@@ -1,4 +1,4 @@
// Copyright 2020 Google LLC
// Copyright 2020-2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -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(())
}
@@ -363,54 +365,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 +404,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 +451,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,
@@ -584,7 +527,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,
@@ -607,7 +550,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.
@@ -669,7 +612,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);
@@ -942,40 +885,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 {};
@@ -988,8 +897,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,
};
@@ -1004,8 +911,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,
};