From c55a062bbab43828e6c9c7c4957c95020ce996e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Guti=C3=A9rrez=20Restrepo?= Date: Mon, 14 Oct 2024 14:41:31 -0500 Subject: [PATCH] change(pass-webauthn): fix impls and work towards registration verification. --- pass-webauthn/src/impls.rs | 49 ++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/pass-webauthn/src/impls.rs b/pass-webauthn/src/impls.rs index 45260bb..15499c0 100644 --- a/pass-webauthn/src/impls.rs +++ b/pass-webauthn/src/impls.rs @@ -15,7 +15,7 @@ where Cx: Parameter, { fn challenge(&self) -> Challenge { - || -> Result { + || -> Result { let client_data_json = serde_json::from_slice::(&self.client_data).map_err(|_| ())?; @@ -33,14 +33,11 @@ impl DeviceChallengeResponse for Attestation where Cx: Parameter + Copy + 'static, { + // TODO: @pandres95, considering that DeviceChallengeResponse is used for creating a new + // authentication device, webauth_verify wouldn't work here. We need to implement a new + // verification method exclusively for credential creation. fn is_valid(&self) -> bool { - webauthn_verify( - self.authenticator_data.as_ref(), - &self.client_data, - &self.signature, - &self.public_key, - ) - .is_ok() + true } fn used_challenge(&self) -> (Cx, Challenge) { @@ -105,7 +102,17 @@ where Cx: Parameter, { fn challenge(&self) -> Challenge { - todo!("Extract `challenge`, format into `Challenge` format (that is, [u8; 32])"); + || -> Result { + let client_data_json = + serde_json::from_slice::(&self.client_data).map_err(|_| ())?; + + let challenge_str = + base64::decode(client_data_json["challenge"].as_str().ok_or(())?.as_bytes()) + .map_err(|_| ())?; + + Decode::decode(&mut TrailingZeroInput::new(challenge_str.as_bytes())).map_err(|_| ())? + }() + .unwrap_or_default() } } @@ -114,9 +121,14 @@ impl UserChallengeResponse for Credential where Cx: Parameter + Copy + 'static, { - // TODO: @jgutierrezre please check if there are necessary validations involved here. fn is_valid(&self) -> bool { - true + webauthn_verify( + self.authenticator_data.as_ref(), + &self.client_data, + &self.signature, + &self.public_key, + ) + .is_ok() } fn used_challenge(&self) -> (Cx, Challenge) { @@ -124,10 +136,21 @@ where } fn authority(&self) -> AuthorityId { - todo!("Extract `rp_id`, format into `AuthorityId` format (that is, [u8; 32])"); + || -> Result { + let client_data_json = + serde_json::from_slice::(&self.client_data).map_err(|_| ())?; + + let origin = client_data_json["origin"].as_str().ok_or(())?; + let (_, domain) = origin.split_once("//").ok_or(())?; + let (rp_id_subdomain, _) = domain.split_once(".").ok_or(())?; + + Decode::decode(&mut TrailingZeroInput::new(rp_id_subdomain.as_bytes())) + .map_err(|_| ())? + }() + .unwrap_or_default() } fn user_id(&self) -> HashedUserId { - todo!("Extract `user_id`, format into `HashedUserId` format (that is, [u8; 32])"); + &self.user_id } }