webauthn_rp

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

ser_server_state.rs (11545B)


      1 use super::{
      2     super::super::bin::{
      3         Decode, DecodeBuffer, EncDecErr, Encode, EncodeBuffer, EncodeBufferFallible as _,
      4     },
      5     AuthenticatorAttachment, AuthenticatorSelectionCriteria, CoseAlgorithmIdentifiers, CredProtect,
      6     CredentialMediationRequirement, ExtensionInfo, RegistrationServerState, ResidentKeyRequirement,
      7     SentChallenge, ServerExtensionInfo, ServerPrfInfo, UserHandle, UserVerificationRequirement,
      8 };
      9 use core::{
     10     error::Error,
     11     fmt::{self, Display, Formatter},
     12 };
     13 use std::time::{SystemTime, SystemTimeError};
     14 impl EncodeBuffer for CoseAlgorithmIdentifiers {
     15     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     16         self.0.encode_into_buffer(buffer);
     17     }
     18 }
     19 impl<'a> DecodeBuffer<'a> for CoseAlgorithmIdentifiers {
     20     type Err = EncDecErr;
     21     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     22         u8::decode_from_buffer(data).and_then(|val| {
     23             if val | Self::ALL.0 == Self::ALL.0 {
     24                 Ok(Self(val))
     25             } else {
     26                 Err(EncDecErr)
     27             }
     28         })
     29     }
     30 }
     31 impl EncodeBuffer for AuthenticatorSelectionCriteria {
     32     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     33         self.authenticator_attachment.encode_into_buffer(buffer);
     34         self.resident_key.encode_into_buffer(buffer);
     35         self.user_verification.encode_into_buffer(buffer);
     36     }
     37 }
     38 impl<'a> DecodeBuffer<'a> for AuthenticatorSelectionCriteria {
     39     type Err = EncDecErr;
     40     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     41         AuthenticatorAttachment::decode_from_buffer(data).and_then(|authenticator_attachment| {
     42             ResidentKeyRequirement::decode_from_buffer(data).and_then(|resident_key| {
     43                 UserVerificationRequirement::decode_from_buffer(data).map(|user_verification| {
     44                     Self {
     45                         authenticator_attachment,
     46                         resident_key,
     47                         user_verification,
     48                     }
     49                 })
     50             })
     51         })
     52     }
     53 }
     54 impl EncodeBuffer for CredProtect {
     55     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     56         match *self {
     57             Self::None => 0u8.encode_into_buffer(buffer),
     58             Self::UserVerificationOptional(enforce, info) => {
     59                 1u8.encode_into_buffer(buffer);
     60                 enforce.encode_into_buffer(buffer);
     61                 info.encode_into_buffer(buffer);
     62             }
     63             Self::UserVerificationOptionalWithCredentialIdList(enforce, info) => {
     64                 2u8.encode_into_buffer(buffer);
     65                 enforce.encode_into_buffer(buffer);
     66                 info.encode_into_buffer(buffer);
     67             }
     68             Self::UserVerificationRequired(enforce, info) => {
     69                 3u8.encode_into_buffer(buffer);
     70                 enforce.encode_into_buffer(buffer);
     71                 info.encode_into_buffer(buffer);
     72             }
     73         }
     74     }
     75 }
     76 impl<'a> DecodeBuffer<'a> for CredProtect {
     77     type Err = EncDecErr;
     78     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     79         u8::decode_from_buffer(data).and_then(|val| match val {
     80             0 => Ok(Self::None),
     81             1 => bool::decode_from_buffer(data).and_then(|enforce| {
     82                 ExtensionInfo::decode_from_buffer(data)
     83                     .map(|info| Self::UserVerificationOptional(enforce, info))
     84             }),
     85             2 => bool::decode_from_buffer(data).and_then(|enforce| {
     86                 ExtensionInfo::decode_from_buffer(data)
     87                     .map(|info| Self::UserVerificationOptionalWithCredentialIdList(enforce, info))
     88             }),
     89             3 => bool::decode_from_buffer(data).and_then(|enforce| {
     90                 ExtensionInfo::decode_from_buffer(data)
     91                     .map(|info| Self::UserVerificationRequired(enforce, info))
     92             }),
     93             _ => Err(EncDecErr),
     94         })
     95     }
     96 }
     97 impl EncodeBuffer for ServerPrfInfo {
     98     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     99         match *self {
    100             Self::None => 0u8.encode_into_buffer(buffer),
    101             Self::One(info) => {
    102                 1u8.encode_into_buffer(buffer);
    103                 info.encode_into_buffer(buffer);
    104             }
    105             Self::Two(info) => {
    106                 2u8.encode_into_buffer(buffer);
    107                 info.encode_into_buffer(buffer);
    108             }
    109         }
    110     }
    111 }
    112 impl<'a> DecodeBuffer<'a> for ServerPrfInfo {
    113     type Err = EncDecErr;
    114     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    115         u8::decode_from_buffer(data).and_then(|val| match val {
    116             0 => Ok(Self::None),
    117             1 => ExtensionInfo::decode_from_buffer(data).map(Self::One),
    118             2 => ExtensionInfo::decode_from_buffer(data).map(Self::Two),
    119             _ => Err(EncDecErr),
    120         })
    121     }
    122 }
    123 impl EncodeBuffer for ServerExtensionInfo {
    124     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    125         self.cred_props.encode_into_buffer(buffer);
    126         self.cred_protect.encode_into_buffer(buffer);
    127         self.min_pin_length.encode_into_buffer(buffer);
    128         self.prf.encode_into_buffer(buffer);
    129     }
    130 }
    131 impl<'a> DecodeBuffer<'a> for ServerExtensionInfo {
    132     type Err = EncDecErr;
    133     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    134         Option::decode_from_buffer(data).and_then(|cred_props| {
    135             CredProtect::decode_from_buffer(data).and_then(|cred_protect| {
    136                 Option::decode_from_buffer(data).and_then(|min_pin_length| {
    137                     ServerPrfInfo::decode_from_buffer(data).map(|prf| Self {
    138                         cred_props,
    139                         cred_protect,
    140                         min_pin_length,
    141                         prf,
    142                     })
    143                 })
    144             })
    145         })
    146     }
    147 }
    148 impl<const LEN: usize> EncodeBuffer for UserHandle<LEN> {
    149     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    150         buffer.extend_from_slice(self.0.as_slice());
    151     }
    152 }
    153 impl<'a, const LEN: usize> DecodeBuffer<'a> for UserHandle<LEN>
    154 where
    155     Self: Default,
    156 {
    157     type Err = EncDecErr;
    158     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    159         data.split_at_checked(LEN)
    160             .ok_or(EncDecErr)
    161             .map(|(val_slice, rem)| {
    162                 *data = rem;
    163                 let mut val = Self::default();
    164                 val.0.copy_from_slice(val_slice);
    165                 val
    166             })
    167     }
    168 }
    169 impl<const USER_LEN: usize> Encode for RegistrationServerState<USER_LEN> {
    170     type Output<'a>
    171         = Vec<u8>
    172     where
    173         Self: 'a;
    174     type Err = SystemTimeError;
    175     #[expect(
    176         clippy::arithmetic_side_effects,
    177         reason = "comment justifies correctness"
    178     )]
    179     #[inline]
    180     fn encode(&self) -> Result<Self::Output<'_>, Self::Err> {
    181         // Length of the anticipated most common output:
    182         // * 1 for `CredentialMediationRequirement`
    183         // * 16 for `SentChallenge`
    184         // * 1 for `CoseAlgorithmIdentifiers`
    185         // * 3 for `AuthenticatorSelectionCriteria`
    186         // * 4–10 for `Extension`
    187         // * 12 for `SystemTime`
    188         // * 1–64 for `UserHandle<USER_LEN>`
    189         // Overflow cannot occur since `self.user_id` has max length of 64.
    190         let mut buffer = Vec::with_capacity(
    191             1 + 16
    192                 + 1
    193                 + 3
    194                 + (1 + usize::from(self.extensions.cred_props.is_some())
    195                     + if matches!(self.extensions.cred_protect, CredProtect::None) {
    196                         1
    197                     } else {
    198                         3
    199                     }
    200                     + if self.extensions.min_pin_length.is_none() {
    201                         1
    202                     } else {
    203                         3
    204                     }
    205                     + 1
    206                     + usize::from(!matches!(self.extensions.prf, ServerPrfInfo::None)))
    207                 + 12
    208                 + self.user_id.0.len(),
    209         );
    210         self.mediation.encode_into_buffer(&mut buffer);
    211         self.challenge.encode_into_buffer(&mut buffer);
    212         self.pub_key_cred_params.encode_into_buffer(&mut buffer);
    213         self.authenticator_selection.encode_into_buffer(&mut buffer);
    214         self.extensions.encode_into_buffer(&mut buffer);
    215         self.expiration.encode_into_buffer(&mut buffer).map(|()| {
    216             self.user_id.encode_into_buffer(&mut buffer);
    217             buffer
    218         })
    219     }
    220 }
    221 /// Error returned from [`RegistrationServerState::decode`].
    222 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    223 pub enum DecodeRegistrationServerStateErr {
    224     /// Variant returned when there was trailing data after decoding a [`RegistrationServerState`].
    225     TrailingData,
    226     /// Variant returned for all other errors.
    227     Other,
    228 }
    229 impl Display for DecodeRegistrationServerStateErr {
    230     #[inline]
    231     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    232         f.write_str(match *self {
    233             Self::TrailingData => "trailing data existed after decoding a RegistrationServerState",
    234             Self::Other => "RegistrationServerState could not be decoded",
    235         })
    236     }
    237 }
    238 impl Error for DecodeRegistrationServerStateErr {}
    239 impl<const USER_LEN: usize> Decode for RegistrationServerState<USER_LEN>
    240 where
    241     UserHandle<USER_LEN>: Default,
    242 {
    243     type Input<'a> = &'a [u8];
    244     type Err = DecodeRegistrationServerStateErr;
    245     #[inline]
    246     fn decode(mut input: Self::Input<'_>) -> Result<Self, Self::Err> {
    247         CredentialMediationRequirement::decode_from_buffer(&mut input).map_err(|_e| DecodeRegistrationServerStateErr::Other).and_then(|mediation| {
    248             SentChallenge::decode_from_buffer(&mut input).map_err(|_e| DecodeRegistrationServerStateErr::Other).and_then(|challenge| {
    249                 CoseAlgorithmIdentifiers::decode_from_buffer(&mut input).map_err(|_e| DecodeRegistrationServerStateErr::Other).and_then(|pub_key_cred_params| {
    250                     AuthenticatorSelectionCriteria::decode_from_buffer(&mut input).map_err(|_e| DecodeRegistrationServerStateErr::Other).and_then(
    251                         |authenticator_selection| {
    252                             ServerExtensionInfo::decode_from_buffer(&mut input).map_err(|_e| DecodeRegistrationServerStateErr::Other).and_then(|extensions| {
    253                                 super::validate_options_helper(authenticator_selection, extensions)
    254                                     .map_err(|_e| DecodeRegistrationServerStateErr::Other)
    255                                     .and_then(|()| {
    256                                         SystemTime::decode_from_buffer(&mut input).map_err(|_e| DecodeRegistrationServerStateErr::Other).and_then(|expiration| {
    257                                             UserHandle::decode_from_buffer(&mut input).map_err(|_e| DecodeRegistrationServerStateErr::Other).and_then(|user_id| {
    258                                                 if input.is_empty() {
    259                                                     Ok(Self { mediation, challenge, pub_key_cred_params, authenticator_selection, extensions, expiration, user_id, })
    260                                                 } else {
    261                                                     Err(DecodeRegistrationServerStateErr::TrailingData)
    262                                                 }
    263                                             })
    264                                         })
    265                                     })
    266                             })
    267                         },
    268                     )
    269                 })
    270             })
    271         })
    272     }
    273 }