webauthn_rp

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

ser_server_state.rs (11284B)


      1 use super::{
      2     super::bin::{DecodeBuffer, EncDecErr, Encode, EncodeBuffer, EncodeBufferFallible},
      3     CredentialMediationRequirement, ExtensionInfo, ExtensionReq, Hint, 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 /// [`Hint::None`] tag.
     63 const HINT_NONE: u8 = 0;
     64 /// [`Hint::SecurityKey`] tag.
     65 const HINT_SEC_KEY: u8 = 1;
     66 /// [`Hint::ClientDevice`] tag.
     67 const HINT_CLIENT_DEV: u8 = 2;
     68 /// [`Hint::Hybrid`] tag.
     69 const HINT_HYBRID: u8 = 3;
     70 /// [`Hint::SecurityKeyClientDevice`] tag.
     71 const HINT_SEC_KEY_CLIENT_DEV: u8 = 4;
     72 /// [`Hint::ClientDeviceSecurityKey`] tag.
     73 const HINT_CLIENT_DEV_SEC_KEY: u8 = 5;
     74 /// [`Hint::SecurityKeyHybrid`] tag.
     75 const HINT_SEC_KEY_HYBRID: u8 = 6;
     76 /// [`Hint::HybridSecurityKey`] tag.
     77 const HINT_HYBRID_SEC_KEY: u8 = 7;
     78 /// [`Hint::ClientDeviceHybrid`] tag.
     79 const HINT_CLIENT_DEV_HYBRID: u8 = 8;
     80 /// [`Hint::HybridClientDevice`] tag.
     81 const HINT_HYBRID_CLIENT_DEV: u8 = 9;
     82 /// [`Hint::SecurityKeyClientDeviceHybrid`] tag.
     83 const HINT_SEC_KEY_CLIENT_DEV_HYBRID: u8 = 10;
     84 /// [`Hint::SecurityKeyHybridClientDevice`] tag.
     85 const HINT_SEC_KEY_HYBRID_CLIENT_DEV: u8 = 11;
     86 /// [`Hint::ClientDeviceSecurityKeyHybrid`] tag.
     87 const HINT_CLIENT_DEV_SEC_KEY_HYBRID: u8 = 12;
     88 /// [`Hint::ClientDeviceHybridSecurityKey`] tag.
     89 const HINT_CLIENT_DEV_HYBRID_SEC_KEY: u8 = 13;
     90 /// [`Hint::HybridSecurityKeyClientDevice`] tag.
     91 const HINT_HYBRID_SEC_KEY_CLIENT_DEV: u8 = 14;
     92 /// [`Hint::HybridClientDeviceSecurityKey`] tag.
     93 const HINT_HYBRID_CLIENT_DEV_SEC_KEY: u8 = 15;
     94 impl EncodeBuffer for Hint {
     95     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     96         match *self {
     97             Self::None => HINT_NONE,
     98             Self::SecurityKey => HINT_SEC_KEY,
     99             Self::ClientDevice => HINT_CLIENT_DEV,
    100             Self::Hybrid => HINT_HYBRID,
    101             Self::SecurityKeyClientDevice => HINT_SEC_KEY_CLIENT_DEV,
    102             Self::ClientDeviceSecurityKey => HINT_CLIENT_DEV_SEC_KEY,
    103             Self::SecurityKeyHybrid => HINT_SEC_KEY_HYBRID,
    104             Self::HybridSecurityKey => HINT_HYBRID_SEC_KEY,
    105             Self::ClientDeviceHybrid => HINT_CLIENT_DEV_HYBRID,
    106             Self::HybridClientDevice => HINT_HYBRID_CLIENT_DEV,
    107             Self::SecurityKeyClientDeviceHybrid => HINT_SEC_KEY_CLIENT_DEV_HYBRID,
    108             Self::SecurityKeyHybridClientDevice => HINT_SEC_KEY_HYBRID_CLIENT_DEV,
    109             Self::ClientDeviceSecurityKeyHybrid => HINT_CLIENT_DEV_SEC_KEY_HYBRID,
    110             Self::ClientDeviceHybridSecurityKey => HINT_CLIENT_DEV_HYBRID_SEC_KEY,
    111             Self::HybridSecurityKeyClientDevice => HINT_HYBRID_SEC_KEY_CLIENT_DEV,
    112             Self::HybridClientDeviceSecurityKey => HINT_HYBRID_CLIENT_DEV_SEC_KEY,
    113         }
    114         .encode_into_buffer(buffer);
    115     }
    116 }
    117 impl<'a> DecodeBuffer<'a> for Hint {
    118     type Err = EncDecErr;
    119     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    120         u8::decode_from_buffer(data).and_then(|val| match val {
    121             HINT_NONE => Ok(Self::None),
    122             HINT_SEC_KEY => Ok(Self::SecurityKey),
    123             HINT_CLIENT_DEV => Ok(Self::ClientDevice),
    124             HINT_HYBRID => Ok(Self::Hybrid),
    125             HINT_SEC_KEY_CLIENT_DEV => Ok(Self::SecurityKeyClientDevice),
    126             HINT_CLIENT_DEV_SEC_KEY => Ok(Self::ClientDeviceSecurityKey),
    127             HINT_SEC_KEY_HYBRID => Ok(Self::SecurityKeyHybrid),
    128             HINT_HYBRID_SEC_KEY => Ok(Self::HybridSecurityKey),
    129             HINT_CLIENT_DEV_HYBRID => Ok(Self::ClientDeviceHybrid),
    130             HINT_HYBRID_CLIENT_DEV => Ok(Self::HybridClientDevice),
    131             HINT_SEC_KEY_CLIENT_DEV_HYBRID => Ok(Self::SecurityKeyClientDeviceHybrid),
    132             HINT_SEC_KEY_HYBRID_CLIENT_DEV => Ok(Self::SecurityKeyHybridClientDevice),
    133             HINT_CLIENT_DEV_SEC_KEY_HYBRID => Ok(Self::ClientDeviceSecurityKeyHybrid),
    134             HINT_CLIENT_DEV_HYBRID_SEC_KEY => Ok(Self::ClientDeviceHybridSecurityKey),
    135             HINT_HYBRID_SEC_KEY_CLIENT_DEV => Ok(Self::HybridSecurityKeyClientDevice),
    136             HINT_HYBRID_CLIENT_DEV_SEC_KEY => Ok(Self::HybridClientDeviceSecurityKey),
    137             _ => Err(EncDecErr),
    138         })
    139     }
    140 }
    141 impl EncodeBuffer for SentChallenge {
    142     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    143         self.0.encode_into_buffer(buffer);
    144     }
    145 }
    146 impl<'a> DecodeBuffer<'a> for SentChallenge {
    147     type Err = EncDecErr;
    148     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    149         u128::decode_from_buffer(data).map(Self)
    150     }
    151 }
    152 impl Encode for SentChallenge {
    153     type Output<'a>
    154         = u128
    155     where
    156         Self: 'a;
    157     type Err = Infallible;
    158     #[inline]
    159     fn encode(&self) -> Result<Self::Output<'_>, Self::Err> {
    160         Ok(self.0)
    161     }
    162 }
    163 /// [`UserVerificationRequirement::Required`] tag.
    164 const USER_VER_REQ_REQUIRED: u8 = 0;
    165 /// [`UserVerificationRequirement::Discouraged`] tag.
    166 const USER_VER_REQ_DISCOURAGED: u8 = 1;
    167 /// [`UserVerificationRequirement::Preferred`] tag.
    168 const USER_VER_REQ_PREFERRED: u8 = 2;
    169 impl EncodeBuffer for UserVerificationRequirement {
    170     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    171         match *self {
    172             Self::Required => USER_VER_REQ_REQUIRED,
    173             Self::Discouraged => USER_VER_REQ_DISCOURAGED,
    174             Self::Preferred => USER_VER_REQ_PREFERRED,
    175         }
    176         .encode_into_buffer(buffer);
    177     }
    178 }
    179 impl<'a> DecodeBuffer<'a> for UserVerificationRequirement {
    180     type Err = EncDecErr;
    181     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    182         u8::decode_from_buffer(data).and_then(|val| match val {
    183             USER_VER_REQ_REQUIRED => Ok(Self::Required),
    184             USER_VER_REQ_DISCOURAGED => Ok(Self::Discouraged),
    185             USER_VER_REQ_PREFERRED => Ok(Self::Preferred),
    186             _ => Err(EncDecErr),
    187         })
    188     }
    189 }
    190 /// [`CredentialMediationRequirement::Required`] tag.
    191 const CRED_MED_REQ_REQUIRED: u8 = 0;
    192 /// [`CredentialMediationRequirement::Conditional`] tag.
    193 const CRED_MED_REQ_CONDITIONAL: u8 = 1;
    194 impl EncodeBuffer for CredentialMediationRequirement {
    195     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    196         match *self {
    197             Self::Required => CRED_MED_REQ_REQUIRED,
    198             Self::Conditional => CRED_MED_REQ_CONDITIONAL,
    199         }
    200         .encode_into_buffer(buffer);
    201     }
    202 }
    203 impl<'a> DecodeBuffer<'a> for CredentialMediationRequirement {
    204     type Err = EncDecErr;
    205     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    206         u8::decode_from_buffer(data).and_then(|val| match val {
    207             CRED_MED_REQ_REQUIRED => Ok(Self::Required),
    208             CRED_MED_REQ_CONDITIONAL => Ok(Self::Conditional),
    209             _ => Err(EncDecErr),
    210         })
    211     }
    212 }
    213 impl EncodeBufferFallible for SystemTime {
    214     type Err = SystemTimeError;
    215     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), Self::Err> {
    216         self.duration_since(UNIX_EPOCH).map(|dur| {
    217             dur.as_secs().encode_into_buffer(buffer);
    218             dur.subsec_nanos().encode_into_buffer(buffer);
    219         })
    220     }
    221 }
    222 impl<'a> DecodeBuffer<'a> for SystemTime {
    223     type Err = EncDecErr;
    224     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    225         /// Maximum duration possible for a timeout which is around 49.7 days.
    226         #[expect(
    227             clippy::as_conversions,
    228             reason = "u32 as u64 is always OK, and we can't use u64::from in const contexts"
    229         )]
    230         const MAX_TIMEOUT: Duration = Duration::from_millis(NonZeroU32::MAX.get() as u64);
    231         u64::decode_from_buffer(data).and_then(|secs| {
    232             u32::decode_from_buffer(data).and_then(|nanos| {
    233                 if nanos < 1_000_000_000 {
    234                     UNIX_EPOCH
    235                         .checked_add(Duration::new(secs, nanos))
    236                         .ok_or(EncDecErr)
    237                         .and_then(|exp| {
    238                             // The latest we could have started the ceremony is now which means the maximum
    239                             // expiry is now plus the maximum timeout.
    240                             if let Some(max_exp) = Self::now().checked_add(MAX_TIMEOUT)
    241                                 && max_exp < exp
    242                             {
    243                                 Err(EncDecErr)
    244                             } else {
    245                                 // Note even when `SystemTime::now().checked_add(MAX_TIMEOUT)` is `None`,
    246                                 // this is valid since the ceremony could have very recently been started.
    247                                 // While this is highly unlikely seeing how `MAX_TIMEOUT` is less than 50 days;
    248                                 // it is _technically_ possible if `SystemTime::now` is within 50 days
    249                                 // of the maximum representable `SystemTime`. It is _far_ more likely that
    250                                 // this branch is taken since `max_exp >= exp`.
    251                                 Ok(exp)
    252                             }
    253                         })
    254                 } else {
    255                     Err(EncDecErr)
    256                 }
    257             })
    258         })
    259     }
    260 }