Add CBOR credential ID type (#512)

* Add CBOR credential ID type

Update the format of the credential ID we generated to extend the
encrypted portion from only private_key + rp_id_hash to a flexible CBOR
map. This way we can persist more data into the key handle in the future
without need of a new version.

We add credProtectPolicy to the persisted data in this commit too, so we
can correctly check the credProtectPolicy for non-discoverable
credentials in follow-up commits.

* Fixed some style problems.

* Fix cargo clippy warning

* Check credProtectPolicy for non-discoverable credentials.

* Remove support of old v1, v2 key handles

- And changed some style problems

* Style changes

* Add missing `alloc` use
This commit is contained in:
hcyang
2022-07-14 14:17:12 +08:00
committed by GitHub
parent aee7d7c9b3
commit 4736cc63c4
4 changed files with 517 additions and 332 deletions

View File

@@ -16,6 +16,7 @@ pub mod apdu;
mod client_pin;
pub mod command;
mod config_command;
mod credential_id;
mod credential_management;
mod crypto_wrapper;
#[cfg(feature = "with_ctap1")]
@@ -40,10 +41,11 @@ use self::command::{
AuthenticatorVendorConfigureParameters, AuthenticatorVendorUpgradeParameters, Command,
};
use self::config_command::process_config;
use self::credential_management::process_credential_management;
use self::crypto_wrapper::{
decrypt_credential_source, encrypt_key_handle, PrivateKey, MAX_CREDENTIAL_ID_SIZE,
use self::credential_id::{
decrypt_credential_id, encrypt_to_credential_id, MAX_CREDENTIAL_ID_SIZE,
};
use self::credential_management::process_credential_management;
use self::crypto_wrapper::PrivateKey;
use self::data_formats::{
AuthenticatorTransport, CoseKey, CoseSignature, CredentialProtectionPolicy,
EnterpriseAttestationMode, GetAssertionExtensions, PackedAttestationStatement,
@@ -807,7 +809,7 @@ impl CtapState {
if let Some(exclude_list) = exclude_list {
for cred_desc in exclude_list {
if storage::find_credential(env, &rp_id, &cred_desc.key_id, !has_uv)?.is_some()
|| decrypt_credential_source(env, cred_desc.key_id, &rp_id_hash)?.is_some()
|| decrypt_credential_id(env, cred_desc.key_id, &rp_id_hash, !has_uv)?.is_some()
{
// Perform this check, so bad actors can't brute force exclude_list
// without user interaction.
@@ -881,7 +883,7 @@ impl CtapState {
storage::store_credential(env, credential_source)?;
random_id
} else {
encrypt_key_handle(env, &private_key, &rp_id_hash)?
encrypt_to_credential_id(env, &private_key, &rp_id_hash, cred_protect_policy)?
};
let mut auth_data = self.generate_auth_data(env, &rp_id_hash, flags)?;
@@ -1070,7 +1072,8 @@ impl CtapState {
if credential.is_some() {
return Ok(credential);
}
let credential = decrypt_credential_source(env, allowed_credential.key_id, rp_id_hash)?;
let credential =
decrypt_credential_id(env, allowed_credential.key_id, rp_id_hash, !has_uv)?;
if credential.is_some() {
return Ok(credential);
}
@@ -1491,7 +1494,7 @@ mod test {
AuthenticatorAttestationMaterial, AuthenticatorClientPinParameters,
AuthenticatorCredentialManagementParameters,
};
use super::crypto_wrapper::ECDSA_CREDENTIAL_ID_SIZE;
use super::credential_id::CBOR_CREDENTIAL_ID_SIZE;
use super::data_formats::{
ClientPinSubCommand, CoseKey, CredentialManagementSubCommand, GetAssertionHmacSecretInput,
GetAssertionOptions, MakeCredentialExtensions, MakeCredentialOptions, PinUvAuthProtocol,
@@ -1698,7 +1701,7 @@ mod test {
make_credential_response,
0x41,
&storage::aaguid(&mut env).unwrap(),
ECDSA_CREDENTIAL_ID_SIZE as u8,
CBOR_CREDENTIAL_ID_SIZE as u8,
&[],
);
}
@@ -1825,7 +1828,7 @@ mod test {
make_credential_response,
0xC1,
&storage::aaguid(&mut env).unwrap(),
ECDSA_CREDENTIAL_ID_SIZE as u8,
CBOR_CREDENTIAL_ID_SIZE as u8,
&expected_extension_cbor,
);
}
@@ -2068,7 +2071,7 @@ mod test {
make_credential_response,
0x41,
&storage::aaguid(&mut env).unwrap(),
ECDSA_CREDENTIAL_ID_SIZE as u8,
CBOR_CREDENTIAL_ID_SIZE as u8,
&[],
);
}
@@ -2436,8 +2439,8 @@ mod test {
let auth_data = make_credential_response.auth_data;
let offset = 37 + storage::aaguid(&mut env).unwrap().len();
assert_eq!(auth_data[offset], 0x00);
assert_eq!(auth_data[offset + 1] as usize, ECDSA_CREDENTIAL_ID_SIZE);
auth_data[offset + 2..offset + 2 + ECDSA_CREDENTIAL_ID_SIZE].to_vec()
assert_eq!(auth_data[offset + 1] as usize, CBOR_CREDENTIAL_ID_SIZE);
auth_data[offset + 2..offset + 2 + CBOR_CREDENTIAL_ID_SIZE].to_vec()
}
_ => panic!("Invalid response type"),
};