webauthn_rp

WebAuthn Level 3 RP library.
git clone https://git.philomathiclife.com/repos/webauthn_rp
Log | Files | Refs | README

bin.rs (31335B)


      1 use super::{
      2     super::super::bin::{
      3         Decode, DecodeBuffer, EncDecErr, Encode, EncodeBuffer, EncodeBufferFallible as _,
      4     },
      5     Aaguid, Attestation, AuthenticationExtensionsPrfOutputs, AuthenticatorAttachment,
      6     AuthenticatorExtensionOutputMetadata, AuthenticatorExtensionOutputStaticState, Backup,
      7     ClientExtensionsOutputsMetadata, ClientExtensionsOutputsStaticState, CompressedP256PubKey,
      8     CompressedP384PubKey, CompressedPubKeyOwned, CredentialPropertiesOutput,
      9     CredentialProtectionPolicy, DynamicState, Ed25519PubKey, FourToSixtyThree, Metadata,
     10     MlDsa44PubKey, MlDsa65PubKey, MlDsa87PubKey, ResidentKeyRequirement, RsaPubKey, StaticState,
     11     UncompressedP256PubKey, UncompressedP384PubKey, UncompressedPubKey,
     12 };
     13 use core::{
     14     convert::Infallible,
     15     error::Error,
     16     fmt::{self, Display, Formatter},
     17 };
     18 use p256::{
     19     NistP256,
     20     elliptic_curve::{Curve, common::typenum::ToInt as _},
     21 };
     22 use p384::NistP384;
     23 impl EncodeBuffer for CredentialProtectionPolicy {
     24     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     25         match *self {
     26             Self::None => 0u8,
     27             Self::UserVerificationOptional => 1,
     28             Self::UserVerificationOptionalWithCredentialIdList => 2,
     29             Self::UserVerificationRequired => 3,
     30         }
     31         .encode_into_buffer(buffer);
     32     }
     33 }
     34 impl<'a> DecodeBuffer<'a> for CredentialProtectionPolicy {
     35     type Err = EncDecErr;
     36     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     37         u8::decode_from_buffer(data).and_then(|val| match val {
     38             0 => Ok(Self::None),
     39             1 => Ok(Self::UserVerificationOptional),
     40             2 => Ok(Self::UserVerificationOptionalWithCredentialIdList),
     41             3 => Ok(Self::UserVerificationRequired),
     42             _ => Err(EncDecErr),
     43         })
     44     }
     45 }
     46 impl EncodeBuffer for ResidentKeyRequirement {
     47     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     48         match *self {
     49             Self::Required => 0u8,
     50             Self::Discouraged => 1,
     51             Self::Preferred => 2,
     52         }
     53         .encode_into_buffer(buffer);
     54     }
     55 }
     56 impl<'a> DecodeBuffer<'a> for ResidentKeyRequirement {
     57     type Err = EncDecErr;
     58     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     59         u8::decode_from_buffer(data).and_then(|val| match val {
     60             0 => Ok(Self::Required),
     61             1 => Ok(Self::Discouraged),
     62             2 => Ok(Self::Preferred),
     63             _ => Err(EncDecErr),
     64         })
     65     }
     66 }
     67 impl EncodeBuffer for MlDsa87PubKey<&[u8]> {
     68     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     69         // We don't rely on `[u8]::encode_into_buffer` since
     70         // we always know the `slice` has length 2592; thus
     71         // we want to "pretend" this is an array (i.e., don't encode the length).
     72         buffer.extend_from_slice(self.0);
     73     }
     74 }
     75 impl<'a> DecodeBuffer<'a> for MlDsa87PubKey<Box<[u8]>> {
     76     type Err = EncDecErr;
     77     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     78         // Only `array`s that implement `Default` implement `DecodeBuffer`;
     79         // thus we must manually implement it.
     80         let mut key = vec![0; 2592];
     81         data.split_at_checked(key.len())
     82             .ok_or(EncDecErr)
     83             .map(|(key_slice, rem)| {
     84                 *data = rem;
     85                 key.copy_from_slice(key_slice);
     86                 Self(key.into_boxed_slice())
     87             })
     88     }
     89 }
     90 impl EncodeBuffer for MlDsa65PubKey<&[u8]> {
     91     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     92         // We don't rely on `[u8]::encode_into_buffer` since
     93         // we always know the `slice` has length 1952; thus
     94         // we want to "pretend" this is an array (i.e., don't encode the length).
     95         buffer.extend_from_slice(self.0);
     96     }
     97 }
     98 impl<'a> DecodeBuffer<'a> for MlDsa65PubKey<Box<[u8]>> {
     99     type Err = EncDecErr;
    100     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    101         // Only `array`s that implement `Default` implement `DecodeBuffer`;
    102         // thus we must manually implement it.
    103         let mut key = vec![0; 1952];
    104         data.split_at_checked(key.len())
    105             .ok_or(EncDecErr)
    106             .map(|(key_slice, rem)| {
    107                 *data = rem;
    108                 key.copy_from_slice(key_slice);
    109                 Self(key.into_boxed_slice())
    110             })
    111     }
    112 }
    113 impl EncodeBuffer for MlDsa44PubKey<&[u8]> {
    114     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    115         // We don't rely on `[u8]::encode_into_buffer` since
    116         // we always know the `slice` has length 1312; thus
    117         // we want to "pretend" this is an array (i.e., don't encode the length).
    118         buffer.extend_from_slice(self.0);
    119     }
    120 }
    121 impl<'a> DecodeBuffer<'a> for MlDsa44PubKey<Box<[u8]>> {
    122     type Err = EncDecErr;
    123     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    124         // Only `array`s that implement `Default` implement `DecodeBuffer`;
    125         // thus we must manually implement it.
    126         let mut key = vec![0; 1312];
    127         data.split_at_checked(key.len())
    128             .ok_or(EncDecErr)
    129             .map(|(key_slice, rem)| {
    130                 *data = rem;
    131                 key.copy_from_slice(key_slice);
    132                 Self(key.into_boxed_slice())
    133             })
    134     }
    135 }
    136 impl EncodeBuffer for Ed25519PubKey<&[u8]> {
    137     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    138         // We don't rely on `[u8]::encode_into_buffer` since
    139         // we always know the `slice` has length 32; thus
    140         // we want to "pretend" this is an array (i.e., don't encode the length).
    141         buffer.extend_from_slice(self.0);
    142     }
    143 }
    144 impl<'a> DecodeBuffer<'a> for Ed25519PubKey<[u8; ed25519_dalek::PUBLIC_KEY_LENGTH]> {
    145     type Err = EncDecErr;
    146     // We don't verify `Self` is in fact "valid" (i.e., we don't call
    147     // [`Self::validate`]) since that's expensive and an error will
    148     // happen later during authentication anyway. Note even if we did,
    149     // that wouldn't detect a public key that was altered in persistent
    150     // storage in such a way that it's still valid; thus there is no
    151     // benefit in performing "expensive" validation checks.
    152     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    153         <[u8; ed25519_dalek::PUBLIC_KEY_LENGTH]>::decode_from_buffer(data).map(Self)
    154     }
    155 }
    156 impl EncodeBuffer for UncompressedP256PubKey<'_> {
    157     #[expect(clippy::indexing_slicing, reason = "comment justifies its correctness")]
    158     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    159         /// Number of bytes the y-coordinate takes.
    160         const Y_LEN: usize = <NistP256 as Curve>::FieldBytesSize::INT;
    161         /// The index of the least significant byte of the y-coordinate.
    162         const ODD_BYTE_INDEX: usize = Y_LEN - 1;
    163         // We don't rely on `[u8]::encode_into_buffer` since
    164         // we always know the `slice` has length 32; thus
    165         // we want to "pretend" this is an array (i.e., don't encode the length).
    166         buffer.extend_from_slice(self.0);
    167         // `self.1.len() == 32` and `ODD_BYTE_INDEX == 31`, so indexing is fine.
    168         (self.1[ODD_BYTE_INDEX] & 1 == 1).encode_into_buffer(buffer);
    169     }
    170 }
    171 impl<'a> DecodeBuffer<'a> for CompressedP256PubKey<[u8; <NistP256 as Curve>::FieldBytesSize::INT]> {
    172     type Err = EncDecErr;
    173     // We don't verify `Self` is in fact "valid" (i.e., we don't call
    174     // [`Self::validate`]) since that's expensive and an error will
    175     // happen later during authentication anyway. Note even if we did,
    176     // that wouldn't detect a public key that was altered in persistent
    177     // storage in such a way that it's still valid; thus there is no
    178     // benefit in performing "expensive" validation checks.
    179     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    180         <[u8; <NistP256 as Curve>::FieldBytesSize::INT]>::decode_from_buffer(data)
    181             .and_then(|x| bool::decode_from_buffer(data).map(|y_is_odd| Self { x, y_is_odd }))
    182     }
    183 }
    184 impl EncodeBuffer for UncompressedP384PubKey<'_> {
    185     #[expect(clippy::indexing_slicing, reason = "comment justifies its correctness")]
    186     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    187         /// Number of bytes the y-coordinate takes.
    188         const Y_LEN: usize = <NistP384 as Curve>::FieldBytesSize::INT;
    189         /// The index of the least significant byte of the y-coordinate.
    190         const ODD_BYTE_INDEX: usize = Y_LEN - 1;
    191         // We don't rely on `[u8]::encode_into_buffer` since
    192         // we always know the `slice` has length 48; thus
    193         // we want to "pretend" this is an array (i.e., don't encode the length).
    194         buffer.extend_from_slice(self.0);
    195         // `self.1.len() == 48` and `ODD_BYTE_INDEX == 47`, so indexing is fine.
    196         (self.1[ODD_BYTE_INDEX] & 1 == 1).encode_into_buffer(buffer);
    197     }
    198 }
    199 impl<'a> DecodeBuffer<'a> for CompressedP384PubKey<[u8; <NistP384 as Curve>::FieldBytesSize::INT]> {
    200     type Err = EncDecErr;
    201     // We don't verify `Self` is in fact "valid" (i.e., we don't call
    202     // [`Self::validate`]) since that's expensive and an error will
    203     // happen later during authentication anyway. Note even if we did,
    204     // that wouldn't detect a public key that was altered in persistent
    205     // storage in such a way that it's still valid; thus there is no
    206     // benefit in performing "expensive" validation checks.
    207     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    208         // Only `array`s that implement `Default` implement `DecodeBuffer`;
    209         // thus we must manually implement it.
    210         let mut x = [0; <NistP384 as Curve>::FieldBytesSize::INT];
    211         data.split_at_checked(x.len())
    212             .ok_or(EncDecErr)
    213             .and_then(|(x_slice, rem)| {
    214                 *data = rem;
    215                 bool::decode_from_buffer(data).map(|y_is_odd| {
    216                     x.copy_from_slice(x_slice);
    217                     Self { x, y_is_odd }
    218                 })
    219             })
    220     }
    221 }
    222 impl EncodeBuffer for RsaPubKey<&[u8]> {
    223     #[expect(clippy::unreachable, reason = "we want to crash when there is a bug")]
    224     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    225         // Max length is 2048, so this won't error.
    226         self.0
    227             .encode_into_buffer(buffer)
    228             .unwrap_or_else(|_e| unreachable!("there is a bug in [u8]::encode_into_buffer"));
    229         self.1.encode_into_buffer(buffer);
    230     }
    231 }
    232 impl<'a> DecodeBuffer<'a> for RsaPubKey<Box<[u8]>> {
    233     type Err = EncDecErr;
    234     // We don't verify `Self` is in fact "valid" (i.e., we don't call
    235     // [`Self::validate`]) since that's expensive and an error will
    236     // happen later during authentication anyway. Note even if we did,
    237     // that wouldn't detect a public key that was altered in persistent
    238     // storage in such a way that it's still valid; thus there is no
    239     // benefit in performing "expensive" validation checks.
    240     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    241         Box::decode_from_buffer(data).and_then(|n| {
    242             u32::decode_from_buffer(data)
    243                 .and_then(|e| Self::try_from((n, e)).map_err(|_e| EncDecErr))
    244         })
    245     }
    246 }
    247 impl EncodeBuffer for UncompressedPubKey<'_> {
    248     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    249         match *self {
    250             Self::MlDsa87(key) => {
    251                 0u8.encode_into_buffer(buffer);
    252                 key.encode_into_buffer(buffer);
    253             }
    254             Self::MlDsa65(key) => {
    255                 1u8.encode_into_buffer(buffer);
    256                 key.encode_into_buffer(buffer);
    257             }
    258             Self::MlDsa44(key) => {
    259                 2u8.encode_into_buffer(buffer);
    260                 key.encode_into_buffer(buffer);
    261             }
    262             Self::Ed25519(key) => {
    263                 3u8.encode_into_buffer(buffer);
    264                 key.encode_into_buffer(buffer);
    265             }
    266             Self::P256(key) => {
    267                 4u8.encode_into_buffer(buffer);
    268                 key.encode_into_buffer(buffer);
    269             }
    270             Self::P384(key) => {
    271                 5u8.encode_into_buffer(buffer);
    272                 key.encode_into_buffer(buffer);
    273             }
    274             Self::Rsa(key) => {
    275                 6u8.encode_into_buffer(buffer);
    276                 key.encode_into_buffer(buffer);
    277             }
    278         }
    279     }
    280 }
    281 impl<'a> DecodeBuffer<'a> for CompressedPubKeyOwned {
    282     type Err = EncDecErr;
    283     // We don't verify `Self` is in fact "valid" (i.e., we don't call
    284     // [`Self::validate`]) since that's expensive and an error will
    285     // happen later during authentication anyway. Note even if we did,
    286     // that wouldn't detect a public key that was altered in persistent
    287     // storage in such a way that it's still valid; thus there is no
    288     // benefit in performing "expensive" validation checks.
    289     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    290         u8::decode_from_buffer(data).and_then(|val| match val {
    291             0 => MlDsa87PubKey::decode_from_buffer(data).map(Self::MlDsa87),
    292             1 => MlDsa65PubKey::decode_from_buffer(data).map(Self::MlDsa65),
    293             2 => MlDsa44PubKey::decode_from_buffer(data).map(Self::MlDsa44),
    294             3 => Ed25519PubKey::decode_from_buffer(data).map(Self::Ed25519),
    295             4 => CompressedP256PubKey::decode_from_buffer(data).map(Self::P256),
    296             5 => CompressedP384PubKey::decode_from_buffer(data).map(Self::P384),
    297             6 => RsaPubKey::decode_from_buffer(data).map(Self::Rsa),
    298             _ => Err(EncDecErr),
    299         })
    300     }
    301 }
    302 impl EncodeBuffer for AuthenticatorExtensionOutputStaticState {
    303     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    304         self.cred_protect.encode_into_buffer(buffer);
    305         self.hmac_secret.encode_into_buffer(buffer);
    306     }
    307 }
    308 impl<'a> DecodeBuffer<'a> for AuthenticatorExtensionOutputStaticState {
    309     type Err = EncDecErr;
    310     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    311         CredentialProtectionPolicy::decode_from_buffer(data).and_then(|cred_protect| {
    312             Option::decode_from_buffer(data).map(|hmac_secret| Self {
    313                 cred_protect,
    314                 hmac_secret,
    315             })
    316         })
    317     }
    318 }
    319 impl EncodeBuffer for Attestation {
    320     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    321         match *self {
    322             Self::None => 0u8,
    323             Self::Surrogate => 1,
    324         }
    325         .encode_into_buffer(buffer);
    326     }
    327 }
    328 impl<'a> DecodeBuffer<'a> for Attestation {
    329     type Err = EncDecErr;
    330     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    331         u8::decode_from_buffer(data).and_then(|val| match val {
    332             0 => Ok(Self::None),
    333             1 => Ok(Self::Surrogate),
    334             _ => Err(EncDecErr),
    335         })
    336     }
    337 }
    338 impl EncodeBuffer for Aaguid<'_> {
    339     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    340         buffer.extend_from_slice(self.0);
    341     }
    342 }
    343 /// Owned version of [`Aaguid`] that exists for [`MetadataOwned::aaguid`].
    344 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    345 pub struct AaguidOwned(pub [u8; super::AAGUID_LEN]);
    346 impl<'a: 'b, 'b> From<&'a AaguidOwned> for Aaguid<'b> {
    347     #[inline]
    348     fn from(value: &'a AaguidOwned) -> Self {
    349         Self(value.0.as_slice())
    350     }
    351 }
    352 impl<'a> DecodeBuffer<'a> for AaguidOwned {
    353     type Err = EncDecErr;
    354     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    355         <[u8; super::AAGUID_LEN]>::decode_from_buffer(data).map(Self)
    356     }
    357 }
    358 impl EncodeBuffer for FourToSixtyThree {
    359     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    360         self.into_u8().encode_into_buffer(buffer);
    361     }
    362 }
    363 impl EncodeBuffer for AuthenticatorExtensionOutputMetadata {
    364     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    365         self.min_pin_length.encode_into_buffer(buffer);
    366     }
    367 }
    368 impl<'a> DecodeBuffer<'a> for FourToSixtyThree {
    369     type Err = EncDecErr;
    370     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    371         u8::decode_from_buffer(data).and_then(|val| Self::from_u8(val).ok_or(EncDecErr))
    372     }
    373 }
    374 impl<'a> DecodeBuffer<'a> for AuthenticatorExtensionOutputMetadata {
    375     type Err = EncDecErr;
    376     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    377         Option::decode_from_buffer(data).map(|min_pin_length| Self { min_pin_length })
    378     }
    379 }
    380 impl EncodeBuffer for CredentialPropertiesOutput {
    381     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    382         self.rk.encode_into_buffer(buffer);
    383     }
    384 }
    385 impl<'a> DecodeBuffer<'a> for CredentialPropertiesOutput {
    386     type Err = EncDecErr;
    387     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    388         Option::decode_from_buffer(data).map(|rk| Self { rk })
    389     }
    390 }
    391 impl EncodeBuffer for AuthenticationExtensionsPrfOutputs {
    392     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    393         self.enabled.encode_into_buffer(buffer);
    394     }
    395 }
    396 impl<'a> DecodeBuffer<'a> for AuthenticationExtensionsPrfOutputs {
    397     type Err = EncDecErr;
    398     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    399         bool::decode_from_buffer(data).map(|enabled| Self { enabled })
    400     }
    401 }
    402 impl EncodeBuffer for ClientExtensionsOutputsMetadata {
    403     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    404         self.cred_props.encode_into_buffer(buffer);
    405     }
    406 }
    407 impl EncodeBuffer for ClientExtensionsOutputsStaticState {
    408     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    409         self.prf.encode_into_buffer(buffer);
    410     }
    411 }
    412 impl<'a> DecodeBuffer<'a> for ClientExtensionsOutputsMetadata {
    413     type Err = EncDecErr;
    414     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    415         Option::decode_from_buffer(data).map(|cred_props| Self { cred_props })
    416     }
    417 }
    418 impl<'a> DecodeBuffer<'a> for ClientExtensionsOutputsStaticState {
    419     type Err = EncDecErr;
    420     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    421         Option::decode_from_buffer(data).map(|prf| Self { prf })
    422     }
    423 }
    424 impl Encode for Metadata<'_> {
    425     type Output<'a>
    426         = Vec<u8>
    427     where
    428         Self: 'a;
    429     type Err = Infallible;
    430     #[inline]
    431     fn encode(&self) -> Result<Self::Output<'_>, Self::Err> {
    432         // Length of the anticipated most common output:
    433         // * 1 for `Attestation`
    434         // * 16 for `Aaguid`.
    435         // * 1 or 2 for `AuthenticatorExtensionOutputMetadata` where we assume 1 is the most common
    436         // * 1–3 for `ClientExtensionsOutputsMetadata` where we assume 1 is the most common
    437         // * 1 for `ResidentKeyRequirement`
    438         let mut buffer = Vec::with_capacity(1 + 16 + 1 + 1 + 1);
    439         self.attestation.encode_into_buffer(&mut buffer);
    440         self.aaguid.encode_into_buffer(&mut buffer);
    441         self.extensions.encode_into_buffer(&mut buffer);
    442         self.client_extension_results
    443             .encode_into_buffer(&mut buffer);
    444         self.resident_key.encode_into_buffer(&mut buffer);
    445         Ok(buffer)
    446     }
    447 }
    448 /// Owned version of [`Metadata`] that exists to [`Self::decode`] the output of [`Metadata::encode`].
    449 #[derive(Clone, Copy, Debug)]
    450 pub struct MetadataOwned {
    451     /// [`Metadata::attestation`].
    452     pub attestation: Attestation,
    453     /// [`Metadata::aaguid`].
    454     pub aaguid: AaguidOwned,
    455     /// [`Metadata::extensions`].
    456     pub extensions: AuthenticatorExtensionOutputMetadata,
    457     /// [`Metadata::client_extension_results`].
    458     pub client_extension_results: ClientExtensionsOutputsMetadata,
    459     /// [`Metadata::resident_key`].
    460     pub resident_key: ResidentKeyRequirement,
    461 }
    462 impl<'a: 'b, 'b> From<&'a MetadataOwned> for Metadata<'b> {
    463     #[inline]
    464     fn from(value: &'a MetadataOwned) -> Self {
    465         Self {
    466             attestation: value.attestation,
    467             aaguid: (&value.aaguid).into(),
    468             extensions: value.extensions,
    469             client_extension_results: value.client_extension_results,
    470             resident_key: value.resident_key,
    471         }
    472     }
    473 }
    474 /// Error returned from [`MetadataOwned::decode`].
    475 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    476 pub enum DecodeMetadataOwnedErr {
    477     /// Variant returned when [`MetadataOwned::attestation`] could not be decoded.
    478     Attestation,
    479     /// Variant returned when [`MetadataOwned::aaguid`] could not be decoded.
    480     Aaguid,
    481     /// Variant returned when [`MetadataOwned::extensions`] could not be decoded.
    482     Extensions,
    483     /// Variant returned when [`MetadataOwned::client_extension_results`] could not be decoded.
    484     ClientExtensionResults,
    485     /// Variant returned when [`MetadataOwned::resident_key`] could not be decoded.
    486     ResidentKey,
    487     /// Variant returned when [`MetadataOwned`] was decoded with trailing data.
    488     TrailingData,
    489 }
    490 impl Display for DecodeMetadataOwnedErr {
    491     #[inline]
    492     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    493         f.write_str(match *self {
    494             Self::Attestation => "attestation could not be decoded",
    495             Self::Aaguid => "aaguid could not be decoded",
    496             Self::Extensions => "extensions could not be decoded",
    497             Self::ClientExtensionResults => "client_extension_results could not be decoded",
    498             Self::ResidentKey => "resident_key could not be decoded",
    499             Self::TrailingData => "trailing data existed after decoding MetadataOwned",
    500         })
    501     }
    502 }
    503 impl Error for DecodeMetadataOwnedErr {}
    504 impl Decode for MetadataOwned {
    505     type Input<'a> = &'a [u8];
    506     type Err = DecodeMetadataOwnedErr;
    507     #[inline]
    508     fn decode(mut input: Self::Input<'_>) -> Result<Self, Self::Err> {
    509         Attestation::decode_from_buffer(&mut input)
    510             .map_err(|_e| DecodeMetadataOwnedErr::Attestation)
    511             .and_then(|attestation| {
    512                 AaguidOwned::decode_from_buffer(&mut input)
    513                     .map_err(|_e| DecodeMetadataOwnedErr::Aaguid)
    514                     .and_then(|aaguid| {
    515                         AuthenticatorExtensionOutputMetadata::decode_from_buffer(&mut input)
    516                             .map_err(|_e| DecodeMetadataOwnedErr::Extensions)
    517                             .and_then(|extensions| {
    518                                 ClientExtensionsOutputsMetadata::decode_from_buffer(&mut input)
    519                                     .map_err(|_e| DecodeMetadataOwnedErr::ClientExtensionResults)
    520                                     .and_then(|client_extension_results| {
    521                                         ResidentKeyRequirement::decode_from_buffer(&mut input)
    522                                             .map_err(|_e| DecodeMetadataOwnedErr::ResidentKey)
    523                                             .and_then(|resident_key| {
    524                                                 if input.is_empty() {
    525                                                     Ok(Self {
    526                                                         attestation,
    527                                                         aaguid,
    528                                                         extensions,
    529                                                         client_extension_results,
    530                                                         resident_key,
    531                                                     })
    532                                                 } else {
    533                                                     Err(DecodeMetadataOwnedErr::TrailingData)
    534                                                 }
    535                                             })
    536                                     })
    537                             })
    538                     })
    539             })
    540     }
    541 }
    542 impl Encode for StaticState<UncompressedPubKey<'_>> {
    543     type Output<'a>
    544         = Vec<u8>
    545     where
    546         Self: 'a;
    547     type Err = Infallible;
    548     /// Transforms `self` into a `Vec` that can subsequently be [`StaticState::decode`]d into a [`StaticState`] of
    549     /// [`CompressedPubKeyOwned`].
    550     #[expect(
    551         clippy::arithmetic_side_effects,
    552         reason = "comment justifies its correctness"
    553     )]
    554     #[inline]
    555     fn encode(&self) -> Result<Self::Output<'_>, Self::Err> {
    556         let mut buffer = Vec::with_capacity(
    557             // The maximum value is 2593 so overflow cannot happen.
    558             // `key.0.len() <= MAX_RSA_N_BYTES` which is 2048.
    559             match self.credential_public_key {
    560                 UncompressedPubKey::MlDsa87(_) => 2593,
    561                 UncompressedPubKey::MlDsa65(_) => 1953,
    562                 UncompressedPubKey::MlDsa44(_) => 1313,
    563                 UncompressedPubKey::Ed25519(_) => 33,
    564                 UncompressedPubKey::P256(_) => 34,
    565                 UncompressedPubKey::P384(_) => 50,
    566                 UncompressedPubKey::Rsa(key) => 1 + 2 + key.0.len() + 4,
    567             } + 1
    568                 + 1
    569                 + usize::from(self.extensions.hmac_secret.is_some())
    570                 + 1
    571                 + usize::from(self.client_extension_results.prf.is_some()),
    572         );
    573         self.credential_public_key.encode_into_buffer(&mut buffer);
    574         self.extensions.encode_into_buffer(&mut buffer);
    575         self.client_extension_results
    576             .encode_into_buffer(&mut buffer);
    577         Ok(buffer)
    578     }
    579 }
    580 /// Error returned from [`StaticState::decode`].
    581 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    582 pub enum DecodeStaticStateErr {
    583     /// Variant returned when [`StaticState::credential_public_key`] could not be decoded.
    584     CredentialPublicKey,
    585     /// Variant returned when [`StaticState::extensions`] could not be decoded.
    586     Extensions,
    587     /// Variant returned when [`StaticState::client_extension_results`] could not be decoded.
    588     ClientExtensionResults,
    589     /// Variant returned when there was trailing data after decoding a [`StaticState`].
    590     TrailingData,
    591 }
    592 impl Display for DecodeStaticStateErr {
    593     #[inline]
    594     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    595         f.write_str(match *self {
    596             Self::CredentialPublicKey => "credential_public_key could not be decoded",
    597             Self::Extensions => "extensions could not be decoded",
    598             Self::ClientExtensionResults => "client_extension_results could not be decoded",
    599             Self::TrailingData => "there was trailing data after decoding a StaticState",
    600         })
    601     }
    602 }
    603 impl Error for DecodeStaticStateErr {}
    604 impl Decode for StaticState<CompressedPubKeyOwned> {
    605     type Input<'a> = &'a [u8];
    606     type Err = DecodeStaticStateErr;
    607     /// Interprets `input` as the [`StaticState::Output`] of [`StaticState::encode`].
    608     #[inline]
    609     fn decode(mut input: Self::Input<'_>) -> Result<Self, Self::Err> {
    610         CompressedPubKeyOwned::decode_from_buffer(&mut input)
    611             .map_err(|_e| DecodeStaticStateErr::CredentialPublicKey)
    612             .and_then(|credential_public_key| {
    613                 AuthenticatorExtensionOutputStaticState::decode_from_buffer(&mut input)
    614                     .map_err(|_e| DecodeStaticStateErr::Extensions)
    615                     .and_then(|extensions| {
    616                         ClientExtensionsOutputsStaticState::decode_from_buffer(&mut input)
    617                             .map_err(|_e| DecodeStaticStateErr::ClientExtensionResults)
    618                             .and_then(|client_extension_results| {
    619                                 if input.is_empty() {
    620                                     Ok(Self {
    621                                         credential_public_key,
    622                                         extensions,
    623                                         client_extension_results,
    624                                     })
    625                                 } else {
    626                                     Err(DecodeStaticStateErr::TrailingData)
    627                                 }
    628                             })
    629                     })
    630             })
    631     }
    632 }
    633 impl Encode for DynamicState {
    634     type Output<'a>
    635         = [u8; 7]
    636     where
    637         Self: 'a;
    638     type Err = Infallible;
    639     #[expect(
    640         clippy::little_endian_bytes,
    641         reason = "need cross-platform correctness"
    642     )]
    643     #[inline]
    644     fn encode(&self) -> Result<Self::Output<'_>, Self::Err> {
    645         let mut buffer = [
    646             u8::from(self.user_verified),
    647             match self.backup {
    648                 Backup::NotEligible => 0,
    649                 Backup::Eligible => 1,
    650                 Backup::Exists => 2,
    651             },
    652             0,
    653             0,
    654             0,
    655             0,
    656             match self.authenticator_attachment {
    657                 AuthenticatorAttachment::None => 0,
    658                 AuthenticatorAttachment::Platform => 1,
    659                 AuthenticatorAttachment::CrossPlatform => 2,
    660             },
    661         ];
    662         buffer[2..6].copy_from_slice(self.sign_count.to_le_bytes().as_slice());
    663         Ok(buffer)
    664     }
    665 }
    666 /// Error returned from [`DynamicState::decode`].
    667 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    668 pub enum DecodeDynamicStateErr {
    669     /// Variant returned when [`DynamicState::user_verified`] could not be decoded.
    670     UserVerified,
    671     /// Variant returned when [`DynamicState::backup`] could not be decoded.
    672     Backup,
    673     /// Variant returned when [`DynamicState::sign_count`] could not be decoded.
    674     SignCount,
    675     /// Variant returned when [`DynamicState::authenticator_attachment`] could not be decoded.
    676     AuthenticatorAttachment,
    677 }
    678 impl Display for DecodeDynamicStateErr {
    679     #[inline]
    680     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    681         f.write_str(match *self {
    682             Self::UserVerified => "user_verified could not be decoded",
    683             Self::Backup => "backup could not be decoded",
    684             Self::SignCount => "sign_count could not be decoded",
    685             Self::AuthenticatorAttachment => "authenticator_attachment could not be decoded",
    686         })
    687     }
    688 }
    689 impl Error for DecodeDynamicStateErr {}
    690 impl Decode for DynamicState {
    691     type Input<'a> = [u8; 7];
    692     type Err = DecodeDynamicStateErr;
    693     #[expect(
    694         clippy::panic_in_result_fn,
    695         reason = "want to crash when there is a bug"
    696     )]
    697     #[inline]
    698     fn decode(input: Self::Input<'_>) -> Result<Self, Self::Err> {
    699         let mut buffer = input.as_slice();
    700         bool::decode_from_buffer(&mut buffer)
    701             .map_err(|_e| DecodeDynamicStateErr::UserVerified)
    702             .and_then(|user_verified| {
    703                 Backup::decode_from_buffer(&mut buffer)
    704                     .map_err(|_e| DecodeDynamicStateErr::Backup)
    705                     .and_then(|backup| {
    706                         u32::decode_from_buffer(&mut buffer)
    707                             .map_err(|_e| DecodeDynamicStateErr::SignCount)
    708                             .and_then(|sign_count| {
    709                                 AuthenticatorAttachment::decode_from_buffer(&mut buffer)
    710                                     .map_err(|_e| DecodeDynamicStateErr::AuthenticatorAttachment)
    711                                     .map(|authenticator_attachment| {
    712                                         assert!(
    713                                             buffer.is_empty(),
    714                                             "there is a bug in DynamicState::decode"
    715                                         );
    716                                         Self {
    717                                             user_verified,
    718                                             backup,
    719                                             sign_count,
    720                                             authenticator_attachment,
    721                                         }
    722                                     })
    723                             })
    724                     })
    725             })
    726     }
    727 }