mirror of
https://github.com/trussed-dev/fido-authenticator.git
synced 2026-06-20 04:16:16 -07:00
ctap2: refactor make_credential / get_assertion to take &mut Response
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## Unreleased
|
||||
|
||||
-
|
||||
- Update to `ctap-types` v0.6.0-rc.4.
|
||||
|
||||
## [v0.4.0-rc.2](https://github.com/trussed-dev/fido-authenticator/releases/tag/v0.4.0-rc.2) (2026-05-31)
|
||||
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ description = "FIDO authenticator Trussed app"
|
||||
apdu-app = { version = "0.2", optional = true }
|
||||
cbor-smol = "0.5"
|
||||
cosey = "0.4"
|
||||
ctap-types = { version = "=0.6.0-rc.3", features = ["get-info-full", "large-blobs", "third-party-payment"] }
|
||||
ctap-types = { version = "=0.6.0-rc.4", features = ["get-info-full", "large-blobs", "third-party-payment"] }
|
||||
ctaphid-app = { version = "0.2", optional = true }
|
||||
delog = "0.1"
|
||||
heapless = "0.9"
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#![no_main]
|
||||
|
||||
use ctap_types::{authenticator::Request, ctap1::Authenticator as _, ctap2::Authenticator as _};
|
||||
use ctap_types::{
|
||||
authenticator::Request,
|
||||
ctap1::Authenticator as _,
|
||||
ctap2::{Authenticator as _, Response},
|
||||
};
|
||||
use fido_authenticator::{Authenticator, Config, Conforming};
|
||||
use trussed::virt::StoreConfig;
|
||||
use trussed_staging::virt;
|
||||
@@ -30,7 +34,8 @@ fuzz_target!(|requests: Vec<Request<'_>>| {
|
||||
authenticator.call_ctap1(&request).ok();
|
||||
}
|
||||
Request::Ctap2(request) => {
|
||||
authenticator.call_ctap2(&request).ok();
|
||||
let mut response = Response::Reset;
|
||||
authenticator.call_ctap2(&request, &mut response).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-27
@@ -205,14 +205,17 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
|
||||
// 7. reset timer
|
||||
// 8. increment credential counter (not applicable)
|
||||
|
||||
self.assert_with_credential(None, Credential::Full(credential))
|
||||
let mut response = ctap2::get_assertion::Response::empty();
|
||||
self.assert_with_credential(None, &Credential::Full(credential), &mut response)?;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn make_credential(
|
||||
fn make_credential_into(
|
||||
&mut self,
|
||||
parameters: &ctap2::make_credential::Request,
|
||||
) -> Result<ctap2::make_credential::Response> {
|
||||
response: &mut ctap2::make_credential::Response,
|
||||
) -> Result<()> {
|
||||
let rp_id_hash = self.hash(parameters.rp.id.as_ref());
|
||||
|
||||
// 1-4.
|
||||
@@ -614,16 +617,13 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
|
||||
info_now!("deleted private credential key: {}", _success);
|
||||
}
|
||||
|
||||
let mut attestation_object = ctap2::make_credential::ResponseBuilder {
|
||||
fmt: att_stmt_fmt
|
||||
.map(From::from)
|
||||
.unwrap_or(AttestationStatementFormat::None),
|
||||
auth_data: serialized_auth_data,
|
||||
}
|
||||
.build();
|
||||
attestation_object.att_stmt = att_stmt;
|
||||
attestation_object.large_blob_key = large_blob_key;
|
||||
Ok(attestation_object)
|
||||
response.fmt = att_stmt_fmt
|
||||
.map(From::from)
|
||||
.unwrap_or(AttestationStatementFormat::None);
|
||||
response.auth_data = serialized_auth_data;
|
||||
response.att_stmt = att_stmt;
|
||||
response.large_blob_key = large_blob_key;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
@@ -1207,10 +1207,11 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn get_assertion(
|
||||
fn get_assertion_into(
|
||||
&mut self,
|
||||
parameters: &ctap2::get_assertion::Request,
|
||||
) -> Result<ctap2::get_assertion::Response> {
|
||||
response: &mut ctap2::get_assertion::Response,
|
||||
) -> Result<()> {
|
||||
debug_now!("remaining stack size: {} bytes", msp() - 0x2000_0000);
|
||||
|
||||
let rp_id_hash = self.hash(parameters.rp_id.as_ref());
|
||||
@@ -1315,7 +1316,7 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
|
||||
n => Some(n),
|
||||
};
|
||||
|
||||
self.assert_with_credential(num_credentials, credential)
|
||||
self.assert_with_credential(num_credentials, &credential, response)
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
@@ -2044,8 +2045,9 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
|
||||
fn assert_with_credential(
|
||||
&mut self,
|
||||
num_credentials: Option<u32>,
|
||||
credential: Credential,
|
||||
) -> Result<ctap2::get_assertion::Response> {
|
||||
credential: &Credential,
|
||||
response: &mut ctap2::get_assertion::Response,
|
||||
) -> Result<()> {
|
||||
let data = self.state.runtime.active_get_assertion.clone().unwrap();
|
||||
let credential_id_version = self.state.persistent.credential_id_version();
|
||||
let rp_id_hash = &data.rp_id_hash;
|
||||
@@ -2078,7 +2080,7 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
|
||||
}
|
||||
large_blob_key_requested = extensions.large_blob_key == Some(true);
|
||||
}
|
||||
self.process_assertion_extensions(&data, extensions, &credential, key)?
|
||||
self.process_assertion_extensions(&data, extensions, credential, key)?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -2184,18 +2186,15 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
|
||||
syscall!(self.trussed.delete(key));
|
||||
}
|
||||
|
||||
let mut response = ctap2::get_assertion::ResponseBuilder {
|
||||
credential: credential_id.into(),
|
||||
auth_data: serialized_auth_data,
|
||||
signature,
|
||||
}
|
||||
.build();
|
||||
response.credential = credential_id.into();
|
||||
response.auth_data = serialized_auth_data;
|
||||
response.signature = signature;
|
||||
response.number_of_credentials = num_credentials;
|
||||
response.att_stmt = att_stmt;
|
||||
|
||||
// User with empty IDs are ignored for compatibility
|
||||
if is_rk {
|
||||
if let Credential::Full(credential) = &credential {
|
||||
if let Credential::Full(credential) = credential {
|
||||
if !credential.user.id().is_empty() {
|
||||
let mut user: PublicKeyCredentialUserEntity = credential.user.clone().into();
|
||||
// User identifiable information (name, DisplayName, icon) MUST not
|
||||
@@ -2219,7 +2218,7 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(response)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
|
||||
+8
-13
@@ -145,13 +145,11 @@ where
|
||||
msp() - 0x2000_0000
|
||||
);
|
||||
|
||||
// let ctap_request = ctap2::Request::deserialize(data)
|
||||
// .map_err(|error| error as u8)?;
|
||||
// let ctap_response = ctap2::Authenticator::call_ctap2(authenticator, &ctap_request)
|
||||
// .map_err(|error| error as u8)?;
|
||||
|
||||
// Goal of these nested scopes is to keep stack small.
|
||||
let ctap_response = try_get_ctap2_response(authenticator, data)?;
|
||||
// ctap_response lives here (this is the only stack slot for the
|
||||
// ~6 KB ctap2::Response with mldsa44). Inner layers fill it in
|
||||
// place via &mut, avoiding by-value copies.
|
||||
let mut ctap_response = ctap2::Response::Reset;
|
||||
try_get_ctap2_response(authenticator, data, &mut ctap_response)?;
|
||||
ctap_response.serialize(response);
|
||||
Ok(())
|
||||
}
|
||||
@@ -160,7 +158,8 @@ where
|
||||
fn try_get_ctap2_response<T, UP>(
|
||||
authenticator: &mut Authenticator<UP, T>,
|
||||
data: &[u8],
|
||||
) -> Result<ctap2::Response, u8>
|
||||
ctap_response: &mut ctap2::Response,
|
||||
) -> Result<(), u8>
|
||||
where
|
||||
T: TrussedRequirements,
|
||||
UP: UserPresence,
|
||||
@@ -190,11 +189,7 @@ where
|
||||
debug!("2a SP: {:X}", msp());
|
||||
use ctap2::Authenticator;
|
||||
authenticator
|
||||
.call_ctap2(&ctap_request)
|
||||
.inspect(|_response| {
|
||||
info!("Sending CTAP2 response {:?}", response_operation(_response));
|
||||
trace!("CTAP2 response: {:?}", _response);
|
||||
})
|
||||
.call_ctap2(&ctap_request, ctap_response)
|
||||
.map_err(|error| {
|
||||
info!("CTAP2 error: {:?}", error);
|
||||
error as u8
|
||||
|
||||
Reference in New Issue
Block a user