Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions libwebauthn/src/ops/u2f.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,7 @@ impl UpgradableResponse<GetAssertionResponse, SignRequest> for SignResponse {
credentials_count: None,
user_selected: None,
large_blob_key: None,
enterprise_attestation: None,
attestation_statement: None,
unsigned_extension_outputs: None,
};

// This isn't great, but we have no access to the original request, and need to construct
Expand Down
8 changes: 2 additions & 6 deletions libwebauthn/src/ops/webauthn/get_assertion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use crate::{
},
pin::PinUvAuthProtocol,
proto::ctap2::{
Ctap2AttestationStatement, Ctap2GetAssertionResponseExtensions,
Ctap2PublicKeyCredentialDescriptor, Ctap2PublicKeyCredentialUserEntity,
Ctap2GetAssertionResponseExtensions, Ctap2PublicKeyCredentialDescriptor,
Ctap2PublicKeyCredentialUserEntity,
},
webauthn::CtapError,
};
Expand Down Expand Up @@ -452,8 +452,6 @@ pub struct Assertion {
pub credentials_count: Option<u32>,
pub user_selected: Option<bool>,
pub unsigned_extensions_output: Option<GetAssertionResponseUnsignedExtensions>,
pub enterprise_attestation: Option<bool>,
pub attestation_statement: Option<Ctap2AttestationStatement>,
}

impl WebAuthnIDLResponse for Assertion {
Expand Down Expand Up @@ -1229,8 +1227,6 @@ mod tests {
credentials_count: None,
user_selected: None,
unsigned_extensions_output: None,
enterprise_attestation: None,
attestation_statement: None,
}
}

Expand Down
35 changes: 26 additions & 9 deletions libwebauthn/src/proto/ctap2/model/get_assertion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,11 +370,7 @@ pub struct Ctap2GetAssertionResponse {

#[serde(skip_serializing_if = "Option::is_none")]
#[serde(index = 0x08)]
pub enterprise_attestation: Option<bool>,

#[serde(skip_serializing_if = "Option::is_none")]
#[serde(index = 0x09)]
pub attestation_statement: Option<Ctap2AttestationStatement>,
pub unsigned_extension_outputs: Option<BTreeMap<Value, Value>>,
}

impl Ctap2UserVerifiableRequest for Ctap2GetAssertionRequest {
Expand Down Expand Up @@ -462,8 +458,6 @@ impl Ctap2GetAssertionResponse {
credentials_count: self.credentials_count,
user_selected: self.user_selected,
unsigned_extensions_output,
enterprise_attestation: self.enterprise_attestation,
attestation_statement: self.attestation_statement,
}
}
}
Expand Down Expand Up @@ -575,8 +569,7 @@ mod tests {
credentials_count: None,
user_selected: None,
large_blob_key: None,
enterprise_attestation: None,
attestation_statement: None,
unsigned_extension_outputs: None,
}
}

Expand Down Expand Up @@ -660,4 +653,28 @@ mod tests {

assert!(large_blob.blob.is_none());
}

#[test]
fn decodes_unsigned_extension_outputs_at_index_0x08() {
// 0x08 is unsignedExtensionOutputs (a CBOR map), not enterprise attestation.
let mut auth_data = vec![0u8; 37];
auth_data[32] = AuthenticatorDataFlags::USER_PRESENT.bits();

let mut ueo = BTreeMap::new();
ueo.insert(
Value::Text("thirdPartyPayment".to_string()),
Value::Bool(true),
);

let mut response: BTreeMap<u64, Value> = BTreeMap::new();
response.insert(0x02, Value::Bytes(auth_data));
response.insert(0x03, Value::Bytes(vec![0xAAu8; 64]));
response.insert(0x08, Value::Map(ueo.clone()));

let bytes = crate::proto::ctap2::cbor::to_vec(&response).unwrap();
let parsed: Ctap2GetAssertionResponse =
crate::proto::ctap2::cbor::from_slice(&bytes).unwrap();

assert_eq!(parsed.unsigned_extension_outputs, Some(ueo));
}
}
Loading