webauthn_rp

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

ser_server_state.rs (12623B)


      1 #![expect(
      2     clippy::question_mark_used,
      3     clippy::unseparated_literal_suffix,
      4     reason = "noisy, opinionated, and likely doesn't prevent bugs or improve APIs"
      5 )]
      6 use super::{
      7     super::super::bin::{
      8         Decode, DecodeBuffer, EncDecErr, Encode, EncodeBuffer, EncodeBufferFallible,
      9     },
     10     AuthenticationServerState, CredInfo, CredentialId, DiscoverableAuthenticationServerState,
     11     ExtensionReq, NonDiscoverableAuthenticationServerState, SentChallenge,
     12     ServerCredSpecificExtensionInfo, ServerExtensionInfo, ServerPrfInfo,
     13     SignatureCounterEnforcement, UserVerificationRequirement,
     14 };
     15 #[cfg(doc)]
     16 use super::{AllowedCredential, NonDiscoverableCredentialRequestOptions};
     17 use core::{
     18     error::Error,
     19     fmt::{self, Display, Formatter},
     20 };
     21 #[cfg(doc)]
     22 use std::time::UNIX_EPOCH;
     23 use std::time::{SystemTime, SystemTimeError};
     24 impl EncodeBuffer for ServerPrfInfo {
     25     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     26         match *self {
     27             Self::One(req) => {
     28                 0u8.encode_into_buffer(buffer);
     29                 req
     30             }
     31             Self::Two(req) => {
     32                 1u8.encode_into_buffer(buffer);
     33                 req
     34             }
     35         }
     36         .encode_into_buffer(buffer);
     37     }
     38 }
     39 impl<'a> DecodeBuffer<'a> for ServerPrfInfo {
     40     type Err = EncDecErr;
     41     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     42         u8::decode_from_buffer(data).and_then(|val| match val {
     43             0 => ExtensionReq::decode_from_buffer(data).map(Self::One),
     44             1 => ExtensionReq::decode_from_buffer(data).map(Self::Two),
     45             _ => Err(EncDecErr),
     46         })
     47     }
     48 }
     49 impl EncodeBuffer for ServerCredSpecificExtensionInfo {
     50     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     51         self.prf.encode_into_buffer(buffer);
     52     }
     53 }
     54 impl<'a> DecodeBuffer<'a> for ServerCredSpecificExtensionInfo {
     55     type Err = EncDecErr;
     56     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     57         Option::decode_from_buffer(data).map(|prf| Self { prf })
     58     }
     59 }
     60 impl EncodeBuffer for CredInfo {
     61     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     62         CredentialId::<&[u8]>::from(&self.id).encode_into_buffer(buffer);
     63         self.ext.encode_into_buffer(buffer);
     64     }
     65 }
     66 impl<'a> DecodeBuffer<'a> for CredInfo {
     67     type Err = EncDecErr;
     68     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     69         CredentialId::<Vec<u8>>::decode_from_buffer(data).and_then(|id| {
     70             ServerCredSpecificExtensionInfo::decode_from_buffer(data).map(|ext| Self { id, ext })
     71         })
     72     }
     73 }
     74 impl EncodeBuffer for ServerExtensionInfo {
     75     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     76         self.prf.encode_into_buffer(buffer);
     77     }
     78 }
     79 impl<'a> DecodeBuffer<'a> for ServerExtensionInfo {
     80     type Err = EncDecErr;
     81     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     82         Option::decode_from_buffer(data).map(|prf| Self { prf })
     83     }
     84 }
     85 impl EncodeBuffer for SignatureCounterEnforcement {
     86     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     87         match *self {
     88             Self::Fail => 0u8,
     89             Self::Update => 1,
     90             Self::Ignore => 2,
     91         }
     92         .encode_into_buffer(buffer);
     93     }
     94 }
     95 impl<'a> DecodeBuffer<'a> for SignatureCounterEnforcement {
     96     type Err = EncDecErr;
     97     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     98         u8::decode_from_buffer(data).and_then(|val| match val {
     99             0 => Ok(Self::Fail),
    100             1 => Ok(Self::Update),
    101             2 => Ok(Self::Ignore),
    102             _ => Err(EncDecErr),
    103         })
    104     }
    105 }
    106 impl EncodeBufferFallible for &[CredInfo] {
    107     type Err = EncDecErr;
    108     /// # Errors
    109     ///
    110     /// Errors iff `self.len() > usize::from(u16::MAX)`.
    111     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), EncDecErr> {
    112         u16::try_from(self.len())
    113             .map_err(|_e| EncDecErr)
    114             .map(|len| {
    115                 len.encode_into_buffer(buffer);
    116                 self.iter().fold((), |(), val| {
    117                     val.encode_into_buffer(buffer);
    118                 });
    119             })
    120     }
    121 }
    122 impl<'a> DecodeBuffer<'a> for Vec<CredInfo> {
    123     type Err = EncDecErr;
    124     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    125         u16::decode_from_buffer(data).and_then(|len| {
    126             let l = usize::from(len);
    127             let mut creds = Self::with_capacity(l);
    128             while creds.len() < l {
    129                 creds.push(CredInfo::decode_from_buffer(data)?);
    130             }
    131             Ok(creds)
    132         })
    133     }
    134 }
    135 impl EncodeBufferFallible for AuthenticationServerState {
    136     type Err = SystemTimeError;
    137     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), Self::Err> {
    138         self.challenge.encode_into_buffer(buffer);
    139         self.user_verification.encode_into_buffer(buffer);
    140         self.extensions.encode_into_buffer(buffer);
    141         self.expiration.encode_into_buffer(buffer)
    142     }
    143 }
    144 impl Encode for DiscoverableAuthenticationServerState {
    145     type Output<'a>
    146         = Vec<u8>
    147     where
    148         Self: 'a;
    149     type Err = SystemTimeError;
    150     #[inline]
    151     fn encode(&self) -> Result<Self::Output<'_>, Self::Err> {
    152         // Length of the anticipated most common output:
    153         // * 16 for `SentChallenge`
    154         // * 1 for `UserVerificationRequirement`
    155         // * 1 or 3 for `ServerExtensionInfo` where we assume 1 is the most common
    156         // * 12 for `SystemTime`
    157         let mut buffer = Vec::with_capacity(16 + 1 + 1 + 12);
    158         self.0.encode_into_buffer(&mut buffer).map(|()| buffer)
    159     }
    160 }
    161 /// Error returned from [`NonDiscoverableAuthenticationServerState::encode`].
    162 #[derive(Debug)]
    163 pub enum EncodeNonDiscoverableAuthenticationServerStateErr {
    164     /// Variant returned when
    165     /// [`NonDiscoverableAuthenticationServerState::expiration`](../struct.AuthenticationServerState.html#method.expiration-1)
    166     /// is before [`UNIX_EPOCH`].
    167     SystemTime(SystemTimeError),
    168     /// Variant returned when the corresponding [`NonDiscoverableCredentialRequestOptions::allow_credentials`] has more
    169     /// than [`u16::MAX`] [`AllowedCredential`]s.
    170     AllowedCredentialsCount,
    171 }
    172 impl Display for EncodeNonDiscoverableAuthenticationServerStateErr {
    173     #[inline]
    174     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    175         match *self {
    176             Self::SystemTime(ref err) => err.fmt(f),
    177             Self::AllowedCredentialsCount => {
    178                 f.write_str("there were more than 65,535 AllowedCredentials")
    179             }
    180         }
    181     }
    182 }
    183 impl Error for EncodeNonDiscoverableAuthenticationServerStateErr {}
    184 impl Encode for NonDiscoverableAuthenticationServerState {
    185     type Output<'a>
    186         = Vec<u8>
    187     where
    188         Self: 'a;
    189     type Err = EncodeNonDiscoverableAuthenticationServerStateErr;
    190     #[inline]
    191     fn encode(&self) -> Result<Self::Output<'_>, Self::Err> {
    192         // Length of the anticipated most common output:
    193         // * 16 for `SentChallenge`
    194         // * 2 + large range for `[CredInfo]` where we assume [`CredInfo`] being
    195         //   empty is the most common
    196         // * 1 for `UserVerificationRequirement`
    197         // * 1 or 3 for `ServerExtensionInfo` where we assume 1 is the most common
    198         // * 12 for `SystemTime`
    199         let mut buffer = Vec::with_capacity(16 + 2 + 1 + 1 + 12);
    200         self.state
    201             .encode_into_buffer(&mut buffer)
    202             .map_err(EncodeNonDiscoverableAuthenticationServerStateErr::SystemTime)
    203             .and_then(|()| {
    204                 self.allow_credentials
    205                     .as_slice()
    206                     .encode_into_buffer(&mut buffer)
    207                     .map_err(|_e| {
    208                         EncodeNonDiscoverableAuthenticationServerStateErr::AllowedCredentialsCount
    209                     })
    210                     .map(|()| buffer)
    211             })
    212     }
    213 }
    214 impl<'a> DecodeBuffer<'a> for AuthenticationServerState {
    215     type Err = EncDecErr;
    216     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    217         SentChallenge::decode_from_buffer(data).and_then(|challenge| {
    218             UserVerificationRequirement::decode_from_buffer(data).and_then(|user_verification| {
    219                 ServerExtensionInfo::decode_from_buffer(data).and_then(|extensions| {
    220                     super::validate_discoverable_options_helper(extensions, user_verification)
    221                         .map_err(|_e| EncDecErr)
    222                         .and_then(|()| {
    223                             SystemTime::decode_from_buffer(data).map(|expiration| Self {
    224                                 challenge,
    225                                 user_verification,
    226                                 extensions,
    227                                 expiration,
    228                             })
    229                         })
    230                 })
    231             })
    232         })
    233     }
    234 }
    235 /// Error returned from [`DiscoverableAuthenticationServerState::decode`].
    236 #[derive(Clone, Copy, Debug)]
    237 pub enum DecodeDiscoverableAuthenticationServerStateErr {
    238     /// Variant returned when there was trailing data after decoding a [`DiscoverableAuthenticationServerState`].
    239     TrailingData,
    240     /// Variant returned for all other errors.
    241     Other,
    242 }
    243 impl Display for DecodeDiscoverableAuthenticationServerStateErr {
    244     #[inline]
    245     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    246         f.write_str(match *self {
    247             Self::TrailingData => {
    248                 "trailing data after decoding DiscoverableAuthenticationServerState"
    249             }
    250             Self::Other => "DiscoverableAuthenticationServerState could not be decoded",
    251         })
    252     }
    253 }
    254 impl Error for DecodeDiscoverableAuthenticationServerStateErr {}
    255 impl Decode for DiscoverableAuthenticationServerState {
    256     type Input<'a> = &'a [u8];
    257     type Err = DecodeDiscoverableAuthenticationServerStateErr;
    258     #[inline]
    259     fn decode(mut input: Self::Input<'_>) -> Result<Self, Self::Err> {
    260         AuthenticationServerState::decode_from_buffer(&mut input)
    261             .map_err(|_e| DecodeDiscoverableAuthenticationServerStateErr::Other)
    262             .and_then(|state| {
    263                 if input.is_empty() {
    264                     Ok(Self(state))
    265                 } else {
    266                     Err(DecodeDiscoverableAuthenticationServerStateErr::TrailingData)
    267                 }
    268             })
    269     }
    270 }
    271 /// Error returned from [`NonDiscoverableAuthenticationServerState::decode`].
    272 #[derive(Clone, Copy, Debug)]
    273 pub enum DecodeNonDiscoverableAuthenticationServerStateErr {
    274     /// Variant returned when there was trailing data after decoding a [`NonDiscoverableAuthenticationServerState`].
    275     TrailingData,
    276     /// Variant returned for all other errors.
    277     Other,
    278 }
    279 impl Display for DecodeNonDiscoverableAuthenticationServerStateErr {
    280     #[inline]
    281     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    282         f.write_str(match *self {
    283             Self::TrailingData => {
    284                 "trailing data after decoding NonDiscoverableAuthenticationServerState"
    285             }
    286             Self::Other => "NonDiscoverableAuthenticationServerState could not be decoded",
    287         })
    288     }
    289 }
    290 impl Error for DecodeNonDiscoverableAuthenticationServerStateErr {}
    291 impl Decode for NonDiscoverableAuthenticationServerState {
    292     type Input<'a> = &'a [u8];
    293     type Err = DecodeNonDiscoverableAuthenticationServerStateErr;
    294     #[inline]
    295     fn decode(mut input: Self::Input<'_>) -> Result<Self, Self::Err> {
    296         AuthenticationServerState::decode_from_buffer(&mut input)
    297             .map_err(|_e| DecodeNonDiscoverableAuthenticationServerStateErr::Other)
    298             .and_then(|state| {
    299                 Vec::decode_from_buffer(&mut input)
    300                     .map_err(|_e| DecodeNonDiscoverableAuthenticationServerStateErr::Other)
    301                     .and_then(|allow_credentials| {
    302                         super::validate_non_discoverable_options_helper(
    303                             state.user_verification,
    304                             allow_credentials.as_slice(),
    305                         )
    306                         .map_err(|_e| DecodeNonDiscoverableAuthenticationServerStateErr::Other)
    307                         .and({
    308                             if input.is_empty() {
    309                                 Ok(Self {
    310                                     state,
    311                                     allow_credentials,
    312                                 })
    313                             } else {
    314                                 Err(DecodeNonDiscoverableAuthenticationServerStateErr::TrailingData)
    315                             }
    316                         })
    317                     })
    318             })
    319     }
    320 }