webauthn_rp

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

ser_server_state.rs (9319B)


      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, ExtensionReq, SentChallenge,
     11     ServerCredSpecificExtensionInfo, ServerExtensionInfo, ServerPrfInfo,
     12     SignatureCounterEnforcement, UserVerificationRequirement,
     13 };
     14 #[cfg(doc)]
     15 use super::{AllowedCredential, PublicKeyCredentialRequestOptions};
     16 use core::{
     17     error::Error,
     18     fmt::{self, Display, Formatter},
     19 };
     20 #[cfg(doc)]
     21 use std::time::UNIX_EPOCH;
     22 use std::time::{SystemTime, SystemTimeError};
     23 impl EncodeBuffer for ServerPrfInfo {
     24     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     25         match *self {
     26             Self::One(req) => {
     27                 0u8.encode_into_buffer(buffer);
     28                 req
     29             }
     30             Self::Two(req) => {
     31                 1u8.encode_into_buffer(buffer);
     32                 req
     33             }
     34         }
     35         .encode_into_buffer(buffer);
     36     }
     37 }
     38 impl<'a> DecodeBuffer<'a> for ServerPrfInfo {
     39     type Err = EncDecErr;
     40     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     41         u8::decode_from_buffer(data).and_then(|val| match val {
     42             0 => ExtensionReq::decode_from_buffer(data).map(Self::One),
     43             1 => ExtensionReq::decode_from_buffer(data).map(Self::Two),
     44             _ => Err(EncDecErr),
     45         })
     46     }
     47 }
     48 impl EncodeBuffer for ServerCredSpecificExtensionInfo {
     49     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     50         self.prf.encode_into_buffer(buffer);
     51     }
     52 }
     53 impl<'a> DecodeBuffer<'a> for ServerCredSpecificExtensionInfo {
     54     type Err = EncDecErr;
     55     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     56         Option::decode_from_buffer(data).map(|prf| Self { prf })
     57     }
     58 }
     59 impl EncodeBuffer for CredInfo {
     60     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     61         CredentialId::<&[u8]>::from(&self.id).encode_into_buffer(buffer);
     62         self.ext.encode_into_buffer(buffer);
     63     }
     64 }
     65 impl<'a> DecodeBuffer<'a> for CredInfo {
     66     type Err = EncDecErr;
     67     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     68         CredentialId::<Vec<u8>>::decode_from_buffer(data).and_then(|id| {
     69             ServerCredSpecificExtensionInfo::decode_from_buffer(data).map(|ext| Self { id, ext })
     70         })
     71     }
     72 }
     73 impl EncodeBuffer for ServerExtensionInfo {
     74     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     75         self.prf.encode_into_buffer(buffer);
     76     }
     77 }
     78 impl<'a> DecodeBuffer<'a> for ServerExtensionInfo {
     79     type Err = EncDecErr;
     80     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     81         Option::decode_from_buffer(data).map(|prf| Self { prf })
     82     }
     83 }
     84 impl EncodeBuffer for SignatureCounterEnforcement {
     85     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     86         match *self {
     87             Self::Fail => 0u8,
     88             Self::Update => 1,
     89             Self::Ignore => 2,
     90         }
     91         .encode_into_buffer(buffer);
     92     }
     93 }
     94 impl<'a> DecodeBuffer<'a> for SignatureCounterEnforcement {
     95     type Err = EncDecErr;
     96     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     97         u8::decode_from_buffer(data).and_then(|val| match val {
     98             0 => Ok(Self::Fail),
     99             1 => Ok(Self::Update),
    100             2 => Ok(Self::Ignore),
    101             _ => Err(EncDecErr),
    102         })
    103     }
    104 }
    105 impl EncodeBufferFallible for &[CredInfo] {
    106     type Err = EncDecErr;
    107     /// # Errors
    108     ///
    109     /// Errors iff `self.len() > usize::from(u16::MAX)`.
    110     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), EncDecErr> {
    111         u16::try_from(self.len())
    112             .map_err(|_e| EncDecErr)
    113             .map(|len| {
    114                 len.encode_into_buffer(buffer);
    115                 self.iter().fold((), |(), val| {
    116                     val.encode_into_buffer(buffer);
    117                 });
    118             })
    119     }
    120 }
    121 impl<'a> DecodeBuffer<'a> for Vec<CredInfo> {
    122     type Err = EncDecErr;
    123     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    124         u16::decode_from_buffer(data).and_then(|len| {
    125             let l = usize::from(len);
    126             let mut creds = Self::with_capacity(l);
    127             while creds.len() < l {
    128                 creds.push(CredInfo::decode_from_buffer(data)?);
    129             }
    130             Ok(creds)
    131         })
    132     }
    133 }
    134 /// Error returned from [`AuthenticationServerState::encode`].
    135 #[derive(Debug)]
    136 pub enum EncodeAuthenticationServerStateErr {
    137     /// Variant returned when
    138     /// [`AuthenticationServerState::expiration`](../struct.AuthenticationServerState.html#method.expiration-1)
    139     /// is before [`UNIX_EPOCH`].
    140     SystemTime(SystemTimeError),
    141     /// Variant returned when the corresponding [`PublicKeyCredentialRequestOptions::allow_credentials`] has more
    142     /// than [`u16::MAX`] [`AllowedCredential`]s.
    143     AllowedCredentialsCount,
    144 }
    145 impl Display for EncodeAuthenticationServerStateErr {
    146     #[inline]
    147     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    148         match *self {
    149             Self::SystemTime(ref err) => err.fmt(f),
    150             Self::AllowedCredentialsCount => {
    151                 f.write_str("there were more than 65,535 AllowedCredentials")
    152             }
    153         }
    154     }
    155 }
    156 impl Error for EncodeAuthenticationServerStateErr {}
    157 impl Encode for AuthenticationServerState {
    158     type Output<'a> = Vec<u8> where Self: 'a;
    159     type Err = EncodeAuthenticationServerStateErr;
    160     #[inline]
    161     fn encode(&self) -> Result<Self::Output<'_>, Self::Err> {
    162         // Length of the anticipated most common output:
    163         // * 16 for `SentChallenge`
    164         // * 2 + large range for `[CredInfo]` where we assume [`CredInfo`] being
    165         //   empty is the most common
    166         // * 1 for `UserVerificationRequirement`
    167         // * 1 or 3 for `ServerExtensionInfo` where we assume 1 is the most common
    168         // * 12 for `SystemTime`
    169         let mut buffer = Vec::with_capacity(16 + 2 + 1 + 1 + 12);
    170         self.challenge.encode_into_buffer(&mut buffer);
    171         self.allow_credentials
    172             .as_slice()
    173             .encode_into_buffer(&mut buffer)
    174             .map_err(|_e| EncodeAuthenticationServerStateErr::AllowedCredentialsCount)
    175             .and_then(|()| {
    176                 self.user_verification.encode_into_buffer(&mut buffer);
    177                 self.extensions.encode_into_buffer(&mut buffer);
    178                 self.expiration
    179                     .encode_into_buffer(&mut buffer)
    180                     .map_err(EncodeAuthenticationServerStateErr::SystemTime)
    181                     .map(|()| buffer)
    182             })
    183     }
    184 }
    185 /// Error returned from [`AuthenticationServerState::decode`].
    186 #[derive(Clone, Copy, Debug)]
    187 pub enum DecodeAuthenticationServerStateErr {
    188     /// Variant returned when there was trailing data after decoding an [`AuthenticationServerState`].
    189     TrailingData,
    190     /// Variant returned for all other errors.
    191     Other,
    192 }
    193 impl Display for DecodeAuthenticationServerStateErr {
    194     #[inline]
    195     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    196         f.write_str(match *self {
    197             Self::TrailingData => "trailing data after decoding AuthenticationServerState",
    198             Self::Other => "AuthenticationServerState could not be decoded",
    199         })
    200     }
    201 }
    202 impl Error for DecodeAuthenticationServerStateErr {}
    203 impl Decode for AuthenticationServerState {
    204     type Input<'a> = &'a [u8];
    205     type Err = DecodeAuthenticationServerStateErr;
    206     #[inline]
    207     fn decode(mut input: Self::Input<'_>) -> Result<Self, Self::Err> {
    208         SentChallenge::decode_from_buffer(&mut input).map_err(|_e| DecodeAuthenticationServerStateErr::Other).and_then(|challenge| {
    209             Vec::decode_from_buffer(&mut input).map_err(|_e| DecodeAuthenticationServerStateErr::Other).and_then(|allow_credentials| {
    210                 UserVerificationRequirement::decode_from_buffer(&mut input).map_err(|_e| DecodeAuthenticationServerStateErr::Other).and_then(|user_verification| {
    211                     ServerExtensionInfo::decode_from_buffer(&mut input).map_err(|_e| DecodeAuthenticationServerStateErr::Other).and_then(|extensions| {
    212                         super::validate_options_helper(extensions, user_verification, &allow_credentials).map_err(|_e| DecodeAuthenticationServerStateErr::Other).and_then(|()| {
    213                             SystemTime::decode_from_buffer(&mut input).map_err(|_e| DecodeAuthenticationServerStateErr::Other).and_then(|expiration| {
    214                                 if input.is_empty() {
    215                                     Ok(Self {
    216                                         challenge,
    217                                         allow_credentials,
    218                                         user_verification,
    219                                         extensions,
    220                                         expiration,
    221                                     })
    222                                 } else {
    223                                     Err(DecodeAuthenticationServerStateErr::TrailingData)
    224                                 }
    225                             })
    226                         })
    227                     })
    228                 })
    229             })
    230         })
    231     }
    232 }