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

@@ -14,7 +14,8 @@
use super::super::clock::CtapInstant;
use super::apdu::{Apdu, ApduStatusCode};
use super::crypto_wrapper::{decrypt_credential_source, encrypt_key_handle, PrivateKey};
use super::credential_id::{decrypt_credential_id, encrypt_to_credential_id};
use super::crypto_wrapper::PrivateKey;
use super::CtapState;
use crate::ctap::storage;
use crate::env::Env;
@@ -250,7 +251,7 @@ impl Ctap1Command {
.ecdsa_key(env)
.map_err(|_| Ctap1StatusCode::SW_INTERNAL_EXCEPTION)?;
let pk = sk.genpk();
let key_handle = encrypt_key_handle(env, &private_key, &application)
let key_handle = encrypt_to_credential_id(env, &private_key, &application, None)
.map_err(|_| Ctap1StatusCode::SW_INTERNAL_EXCEPTION)?;
if key_handle.len() > 0xFF {
// This is just being defensive with unreachable code.
@@ -309,7 +310,7 @@ impl Ctap1Command {
flags: Ctap1Flags,
ctap_state: &mut CtapState,
) -> Result<Vec<u8>, Ctap1StatusCode> {
let credential_source = decrypt_credential_source(env, key_handle, &application)
let credential_source = decrypt_credential_id(env, key_handle, &application, false)
.map_err(|_| Ctap1StatusCode::SW_WRONG_DATA)?;
if let Some(credential_source) = credential_source {
let ecdsa_key = credential_source
@@ -343,7 +344,7 @@ impl Ctap1Command {
#[cfg(test)]
mod test {
use super::super::crypto_wrapper::ECDSA_CREDENTIAL_ID_SIZE;
use super::super::credential_id::CBOR_CREDENTIAL_ID_SIZE;
use super::super::data_formats::SignatureAlgorithm;
use super::super::key_material;
use super::*;
@@ -379,13 +380,12 @@ mod test {
flags.into(),
0x00,
0x00,
0x00,
65 + ECDSA_CREDENTIAL_ID_SIZE as u8,
];
message.extend(&(65 + CBOR_CREDENTIAL_ID_SIZE as u16).to_be_bytes());
let challenge = [0x0C; 32];
message.extend(&challenge);
message.extend(application);
message.push(ECDSA_CREDENTIAL_ID_SIZE as u8);
message.push(CBOR_CREDENTIAL_ID_SIZE as u8);
message.extend(key_handle);
message
}
@@ -444,15 +444,16 @@ mod test {
Ctap1Command::process_command(&mut env, &message, &mut ctap_state, CtapInstant::new(0))
.unwrap();
assert_eq!(response[0], Ctap1Command::LEGACY_BYTE);
assert_eq!(response[66], ECDSA_CREDENTIAL_ID_SIZE as u8);
assert!(decrypt_credential_source(
assert_eq!(response[66], CBOR_CREDENTIAL_ID_SIZE as u8);
assert!(decrypt_credential_id(
&mut env,
response[67..67 + ECDSA_CREDENTIAL_ID_SIZE].to_vec(),
&application
response[67..67 + CBOR_CREDENTIAL_ID_SIZE].to_vec(),
&application,
false
)
.unwrap()
.is_some());
const CERT_START: usize = 67 + ECDSA_CREDENTIAL_ID_SIZE;
const CERT_START: usize = 67 + CBOR_CREDENTIAL_ID_SIZE;
assert_eq!(
&response[CERT_START..CERT_START + fake_cert.len()],
&fake_cert[..]
@@ -507,7 +508,7 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_key_handle(&mut env, &sk, &application).unwrap();
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None).unwrap();
let message = create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle);
let response =
@@ -525,7 +526,7 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_key_handle(&mut env, &sk, &application).unwrap();
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None).unwrap();
let application = [0x55; 32];
let message = create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle);
@@ -544,7 +545,7 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_key_handle(&mut env, &sk, &application).unwrap();
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None).unwrap();
let mut message = create_authenticate_message(
&application,
Ctap1Flags::DontEnforceUpAndSign,
@@ -582,7 +583,7 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_key_handle(&mut env, &sk, &application).unwrap();
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None).unwrap();
let mut message =
create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle);
message[0] = 0xEE;
@@ -602,7 +603,7 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_key_handle(&mut env, &sk, &application).unwrap();
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None).unwrap();
let mut message =
create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle);
message[1] = 0xEE;
@@ -622,7 +623,7 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_key_handle(&mut env, &sk, &application).unwrap();
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None).unwrap();
let mut message =
create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle);
message[2] = 0xEE;
@@ -650,7 +651,7 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_key_handle(&mut env, &sk, &application).unwrap();
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None).unwrap();
let message =
create_authenticate_message(&application, Ctap1Flags::EnforceUpAndSign, &key_handle);
@@ -678,7 +679,7 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_key_handle(&mut env, &sk, &application).unwrap();
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None).unwrap();
let message = create_authenticate_message(
&application,
Ctap1Flags::DontEnforceUpAndSign,
@@ -704,7 +705,7 @@ mod test {
#[test]
fn test_process_authenticate_bad_key_handle() {
let application = [0x0A; 32];
let key_handle = vec![0x00; ECDSA_CREDENTIAL_ID_SIZE];
let key_handle = vec![0x00; CBOR_CREDENTIAL_ID_SIZE];
let message =
create_authenticate_message(&application, Ctap1Flags::EnforceUpAndSign, &key_handle);
@@ -723,7 +724,7 @@ mod test {
#[test]
fn test_process_authenticate_without_up() {
let application = [0x0A; 32];
let key_handle = vec![0x00; ECDSA_CREDENTIAL_ID_SIZE];
let key_handle = vec![0x00; CBOR_CREDENTIAL_ID_SIZE];
let message =
create_authenticate_message(&application, Ctap1Flags::EnforceUpAndSign, &key_handle);