From 6ef8cee4dec4b530067b2e1c2f9eb0f65475f565 Mon Sep 17 00:00:00 2001 From: Nick Zana Date: Tue, 16 May 2023 16:26:12 -0400 Subject: [PATCH] fido-common: Add attestation::Statement data type Attestation statements are returned as part of the CBOR maps returned by authenticators in response to authenticatorMakeCredential and authenticatorGetAssertion commands. The attestation statements defined by WebAuthn come in various formats. However, the format identifier is not part of the attestation statement field in the CBOR map (0x03 attStmt), but rather as a distinct format field (fmt 0x01). Normally, this could be worked around with an externally tagged enum, but using integer tags is not currently supported by serde. By marking the enum instead as untagged, this should ideally mean that serde can differentiate between the enum variants by the fields of the attestation statement, which is itself a CBOR map. Otherwise, we could always revert to just raw byte sequences for the attestation statements during (de)serialization and push validating these statements onto another part of the code. --- crates/fido-common/src/attestation.rs | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/crates/fido-common/src/attestation.rs b/crates/fido-common/src/attestation.rs index 5b76fe6..5dc3d5f 100644 --- a/crates/fido-common/src/attestation.rs +++ b/crates/fido-common/src/attestation.rs @@ -1,5 +1,10 @@ #[cfg(feature = "serde")] +use crate::credential::public_key::algorithm; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "serde")] +use serde_with::{serde_as, Bytes}; + pub mod enterprise; /// > Attestation statement formats are identified by a string, called an @@ -71,6 +76,31 @@ pub enum FormatIdentifier { None, } +#[cfg_eval] +#[derive(Debug)] +#[cfg_attr( + feature = "serde", + serde_as, + derive(Serialize, Deserialize), + // TODO: Workaround until serde can use integer keys as tag, since "fmt" is CBOR key 0x01. + serde(untagged) +)] +pub enum Statement { + #[cfg_attr(feature = "serde", serde(rename = "packed"))] + Packed { + #[cfg_attr(feature = "serde", serde(rename = "alg", with = "algorithm"))] + algorithm: coset::iana::Algorithm, + #[cfg_attr(feature = "serde", serde_as(as = "Bytes"), serde(rename = "sig"))] + signature: Vec, + #[cfg_attr(feature = "serde", serde_as(as = "Vec"), serde(rename = "x5c"))] + attestation_certificate_chain: Vec>, // TODO: Parse X.509 certs + }, + Unregistered { + identifier: String, + data: Vec, + }, +} + /// > Attested credential data is a variable-length byte array added to the /// > authenticator data when generating an attestation object for a given /// > credential.