diff --git a/src/credential.rs b/src/credential.rs index a21a00a..ceb568e 100644 --- a/src/credential.rs +++ b/src/credential.rs @@ -89,7 +89,9 @@ pub struct CredentialData { pub key: Key, // extensions + #[serde(skip_serializing_if = "Option::is_none")] pub hmac_secret: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub cred_protect: Option, // TODO: add `sig_counter: Option`, diff --git a/src/lib.rs b/src/lib.rs index ed3aeae..2973231 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,10 @@ use ctap_types::{ Result as U2fResult, Error as U2fError, }, + webauthn::{ + PublicKeyCredentialRpEntity, + PublicKeyCredentialUserEntity + } }; use littlefs2::path::{Path, PathBuf}; @@ -1835,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, - ¶meters.rp, - ¶meters.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, + ¶meters.rp, + ¶meters.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();