webauthn_rp

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

ser_server_state.rs (13088B)


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