Skip to content

Commit

Permalink
Merge branch 'sz-smaller-keyhandle-length'
Browse files Browse the repository at this point in the history
Remove some fields from credential data serialization while making
credential ID. Reduces key handle size by around 30% (from ~320 to
~220). Tested on Gitlab, and this patch makes it working correctly
(both registering and signing, as opposed to 500 error code returned
otherwise). Presumably the hidden limit is 255 bytes, which would be
compatible with CTAP1.

Related: trussed-dev#8
  • Loading branch information
szszszsz committed Jan 15, 2022
2 parents 297114a + c9c70c3 commit 5862c89
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 18 deletions.
2 changes: 2 additions & 0 deletions src/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ pub struct CredentialData {
pub key: Key,

// extensions
#[serde(skip_serializing_if = "Option::is_none")]
pub hmac_secret: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cred_protect: Option<CredentialProtectionPolicy>,

// TODO: add `sig_counter: Option<CounterId>`,
Expand Down
66 changes: 48 additions & 18 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ use ctap_types::{
Result as U2fResult,
Error as U2fError,
},
webauthn::{
PublicKeyCredentialRpEntity,
PublicKeyCredentialUserEntity
}
};

use littlefs2::path::{Path, PathBuf};
Expand Down Expand Up @@ -477,7 +481,7 @@ where UP: UserPresence,
return Err(Error::InvalidParameter);
}

Ok(match parameters.sub_command {
Ok( match parameters.sub_command {

Subcommand::GetRetries => {
debug!("processing CP.GR");
Expand Down Expand Up @@ -660,6 +664,10 @@ where UP: UserPresence,
}
}

_ => {
// todo!("not implemented yet")
return Err(Error::InvalidParameter);
}
})
}

Expand Down Expand Up @@ -1831,31 +1839,53 @@ where UP: UserPresence,
let nonce = syscall!(self.trussed.random_bytes(12)).bytes.as_slice().try_into().unwrap();
info!("nonce = {:?}", &nonce);

let credential = Credential::new(
credential::CtapVersion::Fido21Pre,
&parameters.rp,
&parameters.user,
algorithm as i32,
key_parameter,
self.state.persistent.timestamp(&mut self.trussed)?,
hmac_secret_requested.clone(),
cred_protect_requested,
nonce,
);

// info!("made credential {:?}", &credential);

// 12.b generate credential ID { = AEAD(Serialize(Credential)) }
let kek = self.state.persistent.key_encryption_key(&mut self.trussed)?;
let credential_id = credential.id_using_hash(&mut self.trussed, kek, &rp_id_hash)?;

// store it.
// TODO: overwrite, error handling with KeyStoreFull

let serialized_credential = credential.serialize()?;
// Introduce smaller Credential struct for ID, with extra metadata removed. This ensures
// ID will stay below 255 bytes.
let credential_thin = Credential::new(
credential::CtapVersion::Fido21Pre,
&PublicKeyCredentialRpEntity{
id: parameters.rp.id.clone(),
name: None,
url: None
},
&PublicKeyCredentialUserEntity {
id: parameters.user.id.clone(),
icon: None,
name: None,
display_name: None
},
algorithm as i32,
key_parameter.clone(),
self.state.persistent.timestamp(&mut self.trussed)?,
None,
None,
nonce,
);

let credential_id = credential_thin.id_using_hash(&mut self.trussed, kek, &rp_id_hash)?;

if rk_requested {
// Create full credential for the Resident Key usage, and store it in local memory.
let credential = Credential::new(
credential::CtapVersion::Fido21Pre,
&parameters.rp,
&parameters.user,
algorithm as i32,
key_parameter,
self.state.persistent.timestamp(&mut self.trussed)?,
hmac_secret_requested.clone(),
cred_protect_requested,
nonce,
);
// info!("made credential {:?}", &credential);
let serialized_credential = credential.serialize()?;

// first delete any other RK cred with same RP + UserId if there is one.
self.delete_resident_key_by_user_id(&rp_id_hash, &credential.user.id).ok();

Expand Down Expand Up @@ -2069,7 +2099,7 @@ where UP: UserPresence,
fn get_info(&mut self) -> ctap2::get_info::Response {

use core::str::FromStr;
let mut versions = Vec::<String<12>, 3>::new();
let mut versions = Vec::<String<12>, 4>::new();
versions.push(String::from_str("U2F_V2").unwrap()).unwrap();
versions.push(String::from_str("FIDO_2_0").unwrap()).unwrap();
// #[cfg(feature = "enable-fido-pre")]
Expand Down

0 comments on commit 5862c89

Please sign in to comment.