webauthn_rp

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

ser_server_state.rs (7412B)


      1 use super::{
      2     super::bin::{DecodeBuffer, EncDecErr, Encode, EncodeBuffer, EncodeBufferFallible},
      3     CredentialMediationRequirement, ExtensionInfo, ExtensionReq, SentChallenge,
      4     UserVerificationRequirement,
      5 };
      6 use core::{convert::Infallible, num::NonZeroU32, time::Duration};
      7 use std::time::{SystemTime, SystemTimeError, UNIX_EPOCH};
      8 /// [`ExtensionInfo::RequireEnforceValue`] tag.
      9 const EXT_INFO_REQUIRE_ENFORCE: u8 = 0;
     10 /// [`ExtensionInfo::RequireDontEnforceValue`] tag.
     11 const EXT_INFO_REQUIRE_DONT_ENFORCE: u8 = 1;
     12 /// [`ExtensionInfo::AllowEnforceValue`] tag.
     13 const EXT_INFO_ALLOW_ENFORCE: u8 = 2;
     14 /// [`ExtensionInfo::AllowDontEnforceValue`] tag.
     15 const EXT_INFO_ALLOW_DONT_ENFORCE: u8 = 3;
     16 impl EncodeBuffer for ExtensionInfo {
     17     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     18         match *self {
     19             Self::RequireEnforceValue => EXT_INFO_REQUIRE_ENFORCE,
     20             Self::RequireDontEnforceValue => EXT_INFO_REQUIRE_DONT_ENFORCE,
     21             Self::AllowEnforceValue => EXT_INFO_ALLOW_ENFORCE,
     22             Self::AllowDontEnforceValue => EXT_INFO_ALLOW_DONT_ENFORCE,
     23         }
     24         .encode_into_buffer(buffer);
     25     }
     26 }
     27 impl<'a> DecodeBuffer<'a> for ExtensionInfo {
     28     type Err = EncDecErr;
     29     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     30         u8::decode_from_buffer(data).and_then(|val| match val {
     31             EXT_INFO_REQUIRE_ENFORCE => Ok(Self::RequireEnforceValue),
     32             EXT_INFO_REQUIRE_DONT_ENFORCE => Ok(Self::RequireDontEnforceValue),
     33             EXT_INFO_ALLOW_ENFORCE => Ok(Self::AllowEnforceValue),
     34             EXT_INFO_ALLOW_DONT_ENFORCE => Ok(Self::AllowDontEnforceValue),
     35             _ => Err(EncDecErr),
     36         })
     37     }
     38 }
     39 /// [`ExtensionReq::Require`] tag.
     40 const EXT_REQ_REQUIRE: u8 = 0;
     41 /// [`ExtensionReq::Allow`] tag.
     42 const EXT_REQ_ALLOW: u8 = 1;
     43 impl EncodeBuffer for ExtensionReq {
     44     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     45         match *self {
     46             Self::Require => EXT_REQ_REQUIRE,
     47             Self::Allow => EXT_REQ_ALLOW,
     48         }
     49         .encode_into_buffer(buffer);
     50     }
     51 }
     52 impl<'a> DecodeBuffer<'a> for ExtensionReq {
     53     type Err = EncDecErr;
     54     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     55         u8::decode_from_buffer(data).and_then(|val| match val {
     56             EXT_REQ_REQUIRE => Ok(Self::Require),
     57             EXT_REQ_ALLOW => Ok(Self::Allow),
     58             _ => Err(EncDecErr),
     59         })
     60     }
     61 }
     62 impl EncodeBuffer for SentChallenge {
     63     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     64         self.0.encode_into_buffer(buffer);
     65     }
     66 }
     67 impl<'a> DecodeBuffer<'a> for SentChallenge {
     68     type Err = EncDecErr;
     69     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
     70         u128::decode_from_buffer(data).map(Self)
     71     }
     72 }
     73 impl Encode for SentChallenge {
     74     type Output<'a>
     75         = u128
     76     where
     77         Self: 'a;
     78     type Err = Infallible;
     79     #[inline]
     80     fn encode(&self) -> Result<Self::Output<'_>, Self::Err> {
     81         Ok(self.0)
     82     }
     83 }
     84 /// [`UserVerificationRequirement::Required`] tag.
     85 const USER_VER_REQ_REQUIRED: u8 = 0;
     86 /// [`UserVerificationRequirement::Discouraged`] tag.
     87 const USER_VER_REQ_DISCOURAGED: u8 = 1;
     88 /// [`UserVerificationRequirement::Preferred`] tag.
     89 const USER_VER_REQ_PREFERRED: u8 = 2;
     90 impl EncodeBuffer for UserVerificationRequirement {
     91     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     92         match *self {
     93             Self::Required => USER_VER_REQ_REQUIRED,
     94             Self::Discouraged => USER_VER_REQ_DISCOURAGED,
     95             Self::Preferred => USER_VER_REQ_PREFERRED,
     96         }
     97         .encode_into_buffer(buffer);
     98     }
     99 }
    100 impl<'a> DecodeBuffer<'a> for UserVerificationRequirement {
    101     type Err = EncDecErr;
    102     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    103         u8::decode_from_buffer(data).and_then(|val| match val {
    104             USER_VER_REQ_REQUIRED => Ok(Self::Required),
    105             USER_VER_REQ_DISCOURAGED => Ok(Self::Discouraged),
    106             USER_VER_REQ_PREFERRED => Ok(Self::Preferred),
    107             _ => Err(EncDecErr),
    108         })
    109     }
    110 }
    111 /// [`CredentialMediationRequirement::Required`] tag.
    112 const CRED_MED_REQ_REQUIRED: u8 = 0;
    113 /// [`CredentialMediationRequirement::Conditional`] tag.
    114 const CRED_MED_REQ_CONDITIONAL: u8 = 1;
    115 impl EncodeBuffer for CredentialMediationRequirement {
    116     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    117         match *self {
    118             Self::Required => CRED_MED_REQ_REQUIRED,
    119             Self::Conditional => CRED_MED_REQ_CONDITIONAL,
    120         }
    121         .encode_into_buffer(buffer);
    122     }
    123 }
    124 impl<'a> DecodeBuffer<'a> for CredentialMediationRequirement {
    125     type Err = EncDecErr;
    126     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    127         u8::decode_from_buffer(data).and_then(|val| match val {
    128             CRED_MED_REQ_REQUIRED => Ok(Self::Required),
    129             CRED_MED_REQ_CONDITIONAL => Ok(Self::Conditional),
    130             _ => Err(EncDecErr),
    131         })
    132     }
    133 }
    134 impl EncodeBufferFallible for SystemTime {
    135     type Err = SystemTimeError;
    136     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), Self::Err> {
    137         self.duration_since(UNIX_EPOCH).map(|dur| {
    138             dur.as_secs().encode_into_buffer(buffer);
    139             dur.subsec_nanos().encode_into_buffer(buffer);
    140         })
    141     }
    142 }
    143 impl<'a> DecodeBuffer<'a> for SystemTime {
    144     type Err = EncDecErr;
    145     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    146         /// Maximum duration possible for a timeout which is around 49.7 days.
    147         #[expect(
    148             clippy::as_conversions,
    149             reason = "u32 as u64 is always OK, and we can't use u64::from in const contexts"
    150         )]
    151         const MAX_TIMEOUT: Duration = Duration::from_millis(NonZeroU32::MAX.get() as u64);
    152         u64::decode_from_buffer(data).and_then(|secs| {
    153             u32::decode_from_buffer(data).and_then(|nanos| {
    154                 if nanos < 1_000_000_000 {
    155                     UNIX_EPOCH
    156                         .checked_add(Duration::new(secs, nanos))
    157                         .ok_or(EncDecErr)
    158                         .and_then(|exp| {
    159                             // The latest we could have started the ceremony is now which means the maximum
    160                             // expiry is now plus the maximum timeout.
    161                             if let Some(max_exp) = Self::now().checked_add(MAX_TIMEOUT)
    162                                 && max_exp < exp
    163                             {
    164                                 Err(EncDecErr)
    165                             } else {
    166                                 // Note even when `SystemTime::now().checked_add(MAX_TIMEOUT)` is `None`,
    167                                 // this is valid since the ceremony could have very recently been started.
    168                                 // While this is highly unlikely seeing how `MAX_TIMEOUT` is less than 50 days;
    169                                 // it is _technically_ possible if `SystemTime::now` is within 50 days
    170                                 // of the maximum representable `SystemTime`. It is _far_ more likely that
    171                                 // this branch is taken since `max_exp >= exp`.
    172                                 Ok(exp)
    173                             }
    174                         })
    175                 } else {
    176                     Err(EncDecErr)
    177                 }
    178             })
    179         })
    180     }
    181 }