From c43da04a260f40b31302b413706eca2fe505b5bf Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Mon, 20 Nov 2023 14:02:05 +0100 Subject: [PATCH] Add largeBlobKey support to make_credential This patch adds support for the largeBlobKey extension to make_credential. This means that we have to generate a 32-bit key and store it together with the credential if requested by the platform. --- src/credential.rs | 4 ++++ src/ctap2.rs | 25 ++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/credential.rs b/src/credential.rs index 32cd94a..b67ea62 100644 --- a/src/credential.rs +++ b/src/credential.rs @@ -226,6 +226,8 @@ pub struct CredentialData { pub hmac_secret: Option, #[serde(skip_serializing_if = "Option::is_none")] pub cred_protect: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub large_blob_key: Option>, // TODO: add `sig_counter: Option`, // and grant RKs a per-credential sig-counter. @@ -327,6 +329,7 @@ impl FullCredential { timestamp: u32, hmac_secret: Option, cred_protect: Option, + large_blob_key: Option>, nonce: [u8; 12], ) -> Self { info!("credential for algorithm {}", algorithm); @@ -341,6 +344,7 @@ impl FullCredential { hmac_secret, cred_protect, + large_blob_key, use_short_id: Some(true), }; diff --git a/src/ctap2.rs b/src/ctap2.rs index 1a66bc1..502e268 100644 --- a/src/ctap2.rs +++ b/src/ctap2.rs @@ -234,6 +234,7 @@ impl Authenticator for crate::Authenti let mut hmac_secret_requested = None; // let mut cred_protect_requested = CredentialProtectionPolicy::Optional; let mut cred_protect_requested = None; + let mut large_blob_key_requested = false; if let Some(extensions) = ¶meters.extensions { hmac_secret_requested = extensions.hmac_secret; @@ -241,6 +242,21 @@ impl Authenticator for crate::Authenti cred_protect_requested = Some(credential::CredentialProtectionPolicy::try_from(*policy)?); } + + if self.config.supports_large_blobs() { + if let Some(large_blob_key) = extensions.large_blob_key { + if large_blob_key { + if !rk_requested { + // the largeBlobKey extension is only available for resident keys + return Err(Error::InvalidOption); + } + large_blob_key_requested = true; + } else { + // large_blob_key must be Some(true) or omitted, Some(false) is invalid + return Err(Error::InvalidOption); + } + } + } } // debug_now!("hmac-secret = {:?}, credProtect = {:?}", hmac_secret_requested, cred_protect_requested); @@ -343,6 +359,12 @@ impl Authenticator for crate::Authenti // store it. // TODO: overwrite, error handling with KeyStoreFull + let large_blob_key = if large_blob_key_requested { + Some(Bytes::from_slice(&syscall!(self.trussed.random_bytes(32)).bytes).unwrap()) + } else { + None + }; + let credential = FullCredential::new( credential::CtapVersion::Fido21Pre, ¶meters.rp, @@ -352,6 +374,7 @@ impl Authenticator for crate::Authenti self.state.persistent.timestamp(&mut self.trussed)?, hmac_secret_requested, cred_protect_requested, + large_blob_key.clone(), nonce, ); @@ -559,7 +582,7 @@ impl Authenticator for crate::Authenti auth_data: serialized_auth_data, att_stmt, ep_att: None, - large_blob_key: None, + large_blob_key, }; Ok(attestation_object)