webauthn_rp

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

ser_server_state.rs (14098B)


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