use crate::{Bytes, String, Vec};
use serde::{Deserialize, Serialize};
use serde_indexed::{DeserializeIndexed, SerializeIndexed};
use super::{AuthenticatorOptions, PinAuth};
use crate::ctap2::credential_management::CredentialProtectionPolicy;
use crate::sizes::*;
use crate::webauthn::*;
impl TryFrom<u8> for CredentialProtectionPolicy {
type Error = super::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
Ok(match value {
1 => CredentialProtectionPolicy::Optional,
2 => CredentialProtectionPolicy::OptionalWithCredentialIdList,
3 => CredentialProtectionPolicy::Required,
_ => return Err(Self::Error::InvalidParameter),
})
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct Extensions {
#[serde(rename = "credProtect")]
#[serde(skip_serializing_if = "Option::is_none")]
pub cred_protect: Option<u8>,
#[serde(rename = "hmac-secret")]
#[serde(skip_serializing_if = "Option::is_none")]
pub hmac_secret: Option<bool>,
}
#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)]
#[serde_indexed(offset = 1)]
pub struct Request {
pub client_data_hash: Bytes<32>,
pub rp: PublicKeyCredentialRpEntity,
pub user: PublicKeyCredentialUserEntity,
pub pub_key_cred_params: Vec<PublicKeyCredentialParameters, 12>,
#[serde(skip_serializing_if = "Option::is_none")]
pub exclude_list: Option<Vec<PublicKeyCredentialDescriptor, 16>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub extensions: Option<Extensions>,
#[serde(skip_serializing_if = "Option::is_none")]
pub options: Option<AuthenticatorOptions>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pin_auth: Option<PinAuth>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pin_protocol: Option<u32>,
}
pub type AttestationObject = Response;
pub type AuthenticatorData = super::AuthenticatorData<AttestedCredentialData, Extensions>;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AttestedCredentialData {
pub aaguid: Bytes<16>,
pub credential_id: Bytes<MAX_CREDENTIAL_ID_LENGTH>,
pub credential_public_key: Bytes<COSE_KEY_LENGTH>,
}
impl super::SerializeAttestedCredentialData for AttestedCredentialData {
fn serialize(&self) -> Bytes<ATTESTED_CREDENTIAL_DATA_LENGTH> {
let mut bytes = Vec::<u8, ATTESTED_CREDENTIAL_DATA_LENGTH>::new();
bytes.extend_from_slice(&self.aaguid).unwrap();
bytes
.extend_from_slice(&(self.credential_id.len() as u16).to_be_bytes())
.unwrap();
bytes
.extend_from_slice(&self.credential_id[..self.credential_id.len()])
.unwrap();
bytes
.extend_from_slice(&self.credential_public_key)
.unwrap();
Bytes::from(bytes)
}
}
#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed)]
#[serde_indexed(offset = 1)]
pub struct Response {
pub fmt: String<32>,
pub auth_data: super::SerializedAuthenticatorData,
pub att_stmt: AttestationStatement,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[serde(untagged)]
#[allow(clippy::large_enum_variant)]
pub enum AttestationStatement {
None(NoneAttestationStatement),
Packed(PackedAttestationStatement),
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[serde(untagged)]
pub enum AttestationStatementFormat {
None,
Packed,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct NoneAttestationStatement {}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct PackedAttestationStatement {
pub alg: i32,
pub sig: Bytes<ASN1_SIGNATURE_LENGTH>,
#[serde(skip_serializing_if = "Option::is_none")]
pub x5c: Option<Vec<Bytes<1024>, 1>>,
}