bin.rs (28095B)
1 use super::{ 2 super::super::bin::{ 3 Decode, DecodeBuffer, EncDecErr, Encode, EncodeBuffer, EncodeBufferFallible as _, 4 }, 5 Aaguid, Attestation, AuthenticationExtensionsPrfOutputs, AuthenticatorAttachment, 6 AuthenticatorExtensionOutputMetadata, AuthenticatorExtensionOutputStaticState, Backup, 7 ClientExtensionsOutputsMetadata, ClientExtensionsOutputsStaticState, CompressedP256PubKey, 8 CompressedP384PubKey, CompressedPubKey, CredentialPropertiesOutput, CredentialProtectionPolicy, 9 DynamicState, Ed25519PubKey, FourToSixtyThree, Metadata, ResidentKeyRequirement, RsaPubKey, 10 StaticState, UncompressedP256PubKey, UncompressedP384PubKey, UncompressedPubKey, 11 }; 12 use core::{ 13 convert::Infallible, 14 error::Error, 15 fmt::{self, Display, Formatter}, 16 }; 17 use p256::{ 18 NistP256, 19 elliptic_curve::{Curve, generic_array::typenum::ToInt as _}, 20 }; 21 use p384::NistP384; 22 impl EncodeBuffer for CredentialProtectionPolicy { 23 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 24 match *self { 25 Self::None => 0u8, 26 Self::UserVerificationOptional => 1, 27 Self::UserVerificationOptionalWithCredentialIdList => 2, 28 Self::UserVerificationRequired => 3, 29 } 30 .encode_into_buffer(buffer); 31 } 32 } 33 impl<'a> DecodeBuffer<'a> for CredentialProtectionPolicy { 34 type Err = EncDecErr; 35 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 36 u8::decode_from_buffer(data).and_then(|val| match val { 37 0 => Ok(Self::None), 38 1 => Ok(Self::UserVerificationOptional), 39 2 => Ok(Self::UserVerificationOptionalWithCredentialIdList), 40 3 => Ok(Self::UserVerificationRequired), 41 _ => Err(EncDecErr), 42 }) 43 } 44 } 45 impl EncodeBuffer for ResidentKeyRequirement { 46 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 47 match *self { 48 Self::Required => 0u8, 49 Self::Discouraged => 1, 50 Self::Preferred => 2, 51 } 52 .encode_into_buffer(buffer); 53 } 54 } 55 impl<'a> DecodeBuffer<'a> for ResidentKeyRequirement { 56 type Err = EncDecErr; 57 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 58 u8::decode_from_buffer(data).and_then(|val| match val { 59 0 => Ok(Self::Required), 60 1 => Ok(Self::Discouraged), 61 2 => Ok(Self::Preferred), 62 _ => Err(EncDecErr), 63 }) 64 } 65 } 66 impl EncodeBuffer for Ed25519PubKey<&[u8]> { 67 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 68 // We don't rely on `[u8]::encode_into_buffer` since 69 // we always know the `slice` has length 32; thus 70 // we want to "pretend" this is an array (i.e., don't encode the length). 71 buffer.extend_from_slice(self.0); 72 } 73 } 74 impl<'a> DecodeBuffer<'a> for Ed25519PubKey<[u8; ed25519_dalek::PUBLIC_KEY_LENGTH]> { 75 type Err = EncDecErr; 76 // We don't verify `Self` is in fact "valid" (i.e., we don't call 77 // [`Self::validate`]) since that's expensive and an error will 78 // happen later during authentication anyway. Note even if we did, 79 // that wouldn't detect a public key that was altered in persistent 80 // storage in such a way that it's still valid; thus there is no 81 // benefit in performing "expensive" validation checks. 82 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 83 <[u8; ed25519_dalek::PUBLIC_KEY_LENGTH]>::decode_from_buffer(data).map(Self) 84 } 85 } 86 impl EncodeBuffer for UncompressedP256PubKey<'_> { 87 #[expect(clippy::indexing_slicing, reason = "comment justifies its correctness")] 88 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 89 /// Number of bytes the y-coordinate takes. 90 const Y_LEN: usize = <NistP256 as Curve>::FieldBytesSize::INT; 91 /// The index of the least significant byte of the y-coordinate. 92 const ODD_BYTE_INDEX: usize = Y_LEN - 1; 93 // We don't rely on `[u8]::encode_into_buffer` since 94 // we always know the `slice` has length 32; thus 95 // we want to "pretend" this is an array (i.e., don't encode the length). 96 buffer.extend_from_slice(self.0); 97 // `self.1.len() == 32` and `ODD_BYTE_INDEX == 31`, so indexing is fine. 98 (self.1[ODD_BYTE_INDEX] & 1 == 1).encode_into_buffer(buffer); 99 } 100 } 101 impl<'a> DecodeBuffer<'a> for CompressedP256PubKey<[u8; <NistP256 as Curve>::FieldBytesSize::INT]> { 102 type Err = EncDecErr; 103 // We don't verify `Self` is in fact "valid" (i.e., we don't call 104 // [`Self::validate`]) since that's expensive and an error will 105 // happen later during authentication anyway. Note even if we did, 106 // that wouldn't detect a public key that was altered in persistent 107 // storage in such a way that it's still valid; thus there is no 108 // benefit in performing "expensive" validation checks. 109 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 110 <[u8; <NistP256 as Curve>::FieldBytesSize::INT]>::decode_from_buffer(data) 111 .and_then(|x| bool::decode_from_buffer(data).map(|y_is_odd| Self { x, y_is_odd })) 112 } 113 } 114 impl EncodeBuffer for UncompressedP384PubKey<'_> { 115 #[expect(clippy::indexing_slicing, reason = "comment justifies its correctness")] 116 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 117 /// Number of bytes the y-coordinate takes. 118 const Y_LEN: usize = <NistP384 as Curve>::FieldBytesSize::INT; 119 /// The index of the least significant byte of the y-coordinate. 120 const ODD_BYTE_INDEX: usize = Y_LEN - 1; 121 // We don't rely on `[u8]::encode_into_buffer` since 122 // we always know the `slice` has length 48; thus 123 // we want to "pretend" this is an array (i.e., don't encode the length). 124 buffer.extend_from_slice(self.0); 125 // `self.1.len() == 48` and `ODD_BYTE_INDEX == 47`, so indexing is fine. 126 (self.1[ODD_BYTE_INDEX] & 1 == 1).encode_into_buffer(buffer); 127 } 128 } 129 impl<'a> DecodeBuffer<'a> for CompressedP384PubKey<[u8; <NistP384 as Curve>::FieldBytesSize::INT]> { 130 type Err = EncDecErr; 131 // We don't verify `Self` is in fact "valid" (i.e., we don't call 132 // [`Self::validate`]) since that's expensive and an error will 133 // happen later during authentication anyway. Note even if we did, 134 // that wouldn't detect a public key that was altered in persistent 135 // storage in such a way that it's still valid; thus there is no 136 // benefit in performing "expensive" validation checks. 137 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 138 // Only `array`s that implement `Default` implement `DecodeBuffer`; 139 // thus we must manually implement it. 140 let mut x = [0; <NistP384 as Curve>::FieldBytesSize::INT]; 141 data.split_at_checked(x.len()) 142 .ok_or(EncDecErr) 143 .and_then(|(x_slice, rem)| { 144 *data = rem; 145 bool::decode_from_buffer(data).map(|y_is_odd| { 146 x.copy_from_slice(x_slice); 147 Self { x, y_is_odd } 148 }) 149 }) 150 } 151 } 152 impl EncodeBuffer for RsaPubKey<&[u8]> { 153 #[expect(clippy::unreachable, reason = "we want to crash when there is a bug")] 154 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 155 // Max length is 2048, so this won't error. 156 self.0 157 .encode_into_buffer(buffer) 158 .unwrap_or_else(|_e| unreachable!("there is a bug in [u8]::encode_into_buffer")); 159 self.1.encode_into_buffer(buffer); 160 } 161 } 162 impl<'a> DecodeBuffer<'a> for RsaPubKey<Vec<u8>> { 163 type Err = EncDecErr; 164 // We don't verify `Self` is in fact "valid" (i.e., we don't call 165 // [`Self::validate`]) since that's expensive and an error will 166 // happen later during authentication anyway. Note even if we did, 167 // that wouldn't detect a public key that was altered in persistent 168 // storage in such a way that it's still valid; thus there is no 169 // benefit in performing "expensive" validation checks. 170 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 171 Vec::decode_from_buffer(data).and_then(|n| { 172 u32::decode_from_buffer(data) 173 .and_then(|e| Self::try_from((n, e)).map_err(|_e| EncDecErr)) 174 }) 175 } 176 } 177 impl EncodeBuffer for UncompressedPubKey<'_> { 178 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 179 match *self { 180 Self::Ed25519(key) => { 181 0u8.encode_into_buffer(buffer); 182 key.encode_into_buffer(buffer); 183 } 184 Self::P256(key) => { 185 1u8.encode_into_buffer(buffer); 186 key.encode_into_buffer(buffer); 187 } 188 Self::P384(key) => { 189 2u8.encode_into_buffer(buffer); 190 key.encode_into_buffer(buffer); 191 } 192 Self::Rsa(key) => { 193 3u8.encode_into_buffer(buffer); 194 key.encode_into_buffer(buffer); 195 } 196 } 197 } 198 } 199 impl<'a> DecodeBuffer<'a> 200 for CompressedPubKey< 201 [u8; ed25519_dalek::PUBLIC_KEY_LENGTH], 202 [u8; <NistP256 as Curve>::FieldBytesSize::INT], 203 [u8; <NistP384 as Curve>::FieldBytesSize::INT], 204 Vec<u8>, 205 > 206 { 207 type Err = EncDecErr; 208 // We don't verify `Self` is in fact "valid" (i.e., we don't call 209 // [`Self::validate`]) since that's expensive and an error will 210 // happen later during authentication anyway. Note even if we did, 211 // that wouldn't detect a public key that was altered in persistent 212 // storage in such a way that it's still valid; thus there is no 213 // benefit in performing "expensive" validation checks. 214 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 215 u8::decode_from_buffer(data).and_then(|val| match val { 216 0 => Ed25519PubKey::decode_from_buffer(data).map(Self::Ed25519), 217 1 => CompressedP256PubKey::decode_from_buffer(data).map(Self::P256), 218 2 => CompressedP384PubKey::decode_from_buffer(data).map(Self::P384), 219 3 => RsaPubKey::decode_from_buffer(data).map(Self::Rsa), 220 _ => Err(EncDecErr), 221 }) 222 } 223 } 224 impl EncodeBuffer for AuthenticatorExtensionOutputStaticState { 225 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 226 self.cred_protect.encode_into_buffer(buffer); 227 self.hmac_secret.encode_into_buffer(buffer); 228 } 229 } 230 impl<'a> DecodeBuffer<'a> for AuthenticatorExtensionOutputStaticState { 231 type Err = EncDecErr; 232 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 233 CredentialProtectionPolicy::decode_from_buffer(data).and_then(|cred_protect| { 234 Option::decode_from_buffer(data).map(|hmac_secret| Self { 235 cred_protect, 236 hmac_secret, 237 }) 238 }) 239 } 240 } 241 impl EncodeBuffer for Attestation { 242 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 243 match *self { 244 Self::None => 0u8, 245 Self::Surrogate => 1, 246 } 247 .encode_into_buffer(buffer); 248 } 249 } 250 impl<'a> DecodeBuffer<'a> for Attestation { 251 type Err = EncDecErr; 252 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 253 u8::decode_from_buffer(data).and_then(|val| match val { 254 0 => Ok(Self::None), 255 1 => Ok(Self::Surrogate), 256 _ => Err(EncDecErr), 257 }) 258 } 259 } 260 impl EncodeBuffer for Aaguid<'_> { 261 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 262 buffer.extend_from_slice(self.0); 263 } 264 } 265 /// Owned version of [`Aaguid`] that exists for [`MetadataOwned::aaguid`]. 266 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 267 pub struct AaguidOwned(pub [u8; super::AAGUID_LEN]); 268 impl<'a: 'b, 'b> From<&'a AaguidOwned> for Aaguid<'b> { 269 #[inline] 270 fn from(value: &'a AaguidOwned) -> Self { 271 Self(value.0.as_slice()) 272 } 273 } 274 impl<'a> DecodeBuffer<'a> for AaguidOwned { 275 type Err = EncDecErr; 276 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 277 <[u8; super::AAGUID_LEN]>::decode_from_buffer(data).map(Self) 278 } 279 } 280 impl EncodeBuffer for FourToSixtyThree { 281 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 282 self.into_u8().encode_into_buffer(buffer); 283 } 284 } 285 impl EncodeBuffer for AuthenticatorExtensionOutputMetadata { 286 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 287 self.min_pin_length.encode_into_buffer(buffer); 288 } 289 } 290 impl<'a> DecodeBuffer<'a> for FourToSixtyThree { 291 type Err = EncDecErr; 292 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 293 u8::decode_from_buffer(data).and_then(|val| Self::from_u8(val).ok_or(EncDecErr)) 294 } 295 } 296 impl<'a> DecodeBuffer<'a> for AuthenticatorExtensionOutputMetadata { 297 type Err = EncDecErr; 298 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 299 Option::decode_from_buffer(data).map(|min_pin_length| Self { min_pin_length }) 300 } 301 } 302 impl EncodeBuffer for CredentialPropertiesOutput { 303 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 304 self.rk.encode_into_buffer(buffer); 305 } 306 } 307 impl<'a> DecodeBuffer<'a> for CredentialPropertiesOutput { 308 type Err = EncDecErr; 309 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 310 Option::decode_from_buffer(data).map(|rk| Self { rk }) 311 } 312 } 313 impl EncodeBuffer for AuthenticationExtensionsPrfOutputs { 314 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 315 self.enabled.encode_into_buffer(buffer); 316 } 317 } 318 impl<'a> DecodeBuffer<'a> for AuthenticationExtensionsPrfOutputs { 319 type Err = EncDecErr; 320 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 321 bool::decode_from_buffer(data).map(|enabled| Self { enabled }) 322 } 323 } 324 impl EncodeBuffer for ClientExtensionsOutputsMetadata { 325 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 326 self.cred_props.encode_into_buffer(buffer); 327 } 328 } 329 impl EncodeBuffer for ClientExtensionsOutputsStaticState { 330 fn encode_into_buffer(&self, buffer: &mut Vec<u8>) { 331 self.prf.encode_into_buffer(buffer); 332 } 333 } 334 impl<'a> DecodeBuffer<'a> for ClientExtensionsOutputsMetadata { 335 type Err = EncDecErr; 336 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 337 Option::decode_from_buffer(data).map(|cred_props| Self { cred_props }) 338 } 339 } 340 impl<'a> DecodeBuffer<'a> for ClientExtensionsOutputsStaticState { 341 type Err = EncDecErr; 342 fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> { 343 Option::decode_from_buffer(data).map(|prf| Self { prf }) 344 } 345 } 346 impl Encode for Metadata<'_> { 347 type Output<'a> 348 = Vec<u8> 349 where 350 Self: 'a; 351 type Err = Infallible; 352 #[inline] 353 fn encode(&self) -> Result<Self::Output<'_>, Self::Err> { 354 // Length of the anticipated most common output: 355 // * 1 for `Attestation` 356 // * 16 for `Aaguid`. 357 // * 1 or 2 for `AuthenticatorExtensionOutputMetadata` where we assume 1 is the most common 358 // * 1–3 for `ClientExtensionsOutputsMetadata` where we assume 1 is the most common 359 // * 1 for `ResidentKeyRequirement` 360 let mut buffer = Vec::with_capacity(1 + 16 + 1 + 1 + 1); 361 self.attestation.encode_into_buffer(&mut buffer); 362 self.aaguid.encode_into_buffer(&mut buffer); 363 self.extensions.encode_into_buffer(&mut buffer); 364 self.client_extension_results 365 .encode_into_buffer(&mut buffer); 366 self.resident_key.encode_into_buffer(&mut buffer); 367 Ok(buffer) 368 } 369 } 370 /// Owned version of [`Metadata`] that exists to [`Self::decode`] the output of [`Metadata::encode`]. 371 #[derive(Clone, Copy, Debug)] 372 pub struct MetadataOwned { 373 /// [`Metadata::attestation`]. 374 pub attestation: Attestation, 375 /// [`Metadata::aaguid`]. 376 pub aaguid: AaguidOwned, 377 /// [`Metadata::extensions`]. 378 pub extensions: AuthenticatorExtensionOutputMetadata, 379 /// [`Metadata::client_extension_results`]. 380 pub client_extension_results: ClientExtensionsOutputsMetadata, 381 /// [`Metadata::resident_key`]. 382 pub resident_key: ResidentKeyRequirement, 383 } 384 impl<'a: 'b, 'b> From<&'a MetadataOwned> for Metadata<'b> { 385 #[inline] 386 fn from(value: &'a MetadataOwned) -> Self { 387 Self { 388 attestation: value.attestation, 389 aaguid: (&value.aaguid).into(), 390 extensions: value.extensions, 391 client_extension_results: value.client_extension_results, 392 resident_key: value.resident_key, 393 } 394 } 395 } 396 /// Error returned from [`MetadataOwned::decode`]. 397 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 398 pub enum DecodeMetadataOwnedErr { 399 /// Variant returned when [`MetadataOwned::attestation`] could not be decoded. 400 Attestation, 401 /// Variant returned when [`MetadataOwned::aaguid`] could not be decoded. 402 Aaguid, 403 /// Variant returned when [`MetadataOwned::extensions`] could not be decoded. 404 Extensions, 405 /// Variant returned when [`MetadataOwned::client_extension_results`] could not be decoded. 406 ClientExtensionResults, 407 /// Variant returned when [`MetadataOwned::resident_key`] could not be decoded. 408 ResidentKey, 409 /// Variant returned when [`MetadataOwned`] was decoded with trailing data. 410 TrailingData, 411 } 412 impl Display for DecodeMetadataOwnedErr { 413 #[inline] 414 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 415 f.write_str(match *self { 416 Self::Attestation => "attestation could not be decoded", 417 Self::Aaguid => "aaguid could not be decoded", 418 Self::Extensions => "extensions could not be decoded", 419 Self::ClientExtensionResults => "client_extension_results could not be decoded", 420 Self::ResidentKey => "resident_key could not be decoded", 421 Self::TrailingData => "trailing data existed after decoding MetadataOwned", 422 }) 423 } 424 } 425 impl Error for DecodeMetadataOwnedErr {} 426 impl Decode for MetadataOwned { 427 type Input<'a> = &'a [u8]; 428 type Err = DecodeMetadataOwnedErr; 429 #[inline] 430 fn decode(mut input: Self::Input<'_>) -> Result<Self, Self::Err> { 431 Attestation::decode_from_buffer(&mut input) 432 .map_err(|_e| DecodeMetadataOwnedErr::Attestation) 433 .and_then(|attestation| { 434 AaguidOwned::decode_from_buffer(&mut input) 435 .map_err(|_e| DecodeMetadataOwnedErr::Aaguid) 436 .and_then(|aaguid| { 437 AuthenticatorExtensionOutputMetadata::decode_from_buffer(&mut input) 438 .map_err(|_e| DecodeMetadataOwnedErr::Extensions) 439 .and_then(|extensions| { 440 ClientExtensionsOutputsMetadata::decode_from_buffer(&mut input) 441 .map_err(|_e| DecodeMetadataOwnedErr::ClientExtensionResults) 442 .and_then(|client_extension_results| { 443 ResidentKeyRequirement::decode_from_buffer(&mut input) 444 .map_err(|_e| DecodeMetadataOwnedErr::ResidentKey) 445 .and_then(|resident_key| { 446 if input.is_empty() { 447 Ok(Self { 448 attestation, 449 aaguid, 450 extensions, 451 client_extension_results, 452 resident_key, 453 }) 454 } else { 455 Err(DecodeMetadataOwnedErr::TrailingData) 456 } 457 }) 458 }) 459 }) 460 }) 461 }) 462 } 463 } 464 impl Encode for StaticState<UncompressedPubKey<'_>> { 465 type Output<'a> 466 = Vec<u8> 467 where 468 Self: 'a; 469 type Err = Infallible; 470 /// Transforms `self` into a `Vec` that can subsequently be [`StaticState::decode`]d into a [`StaticState`] of 471 /// [`CompressedPubKey`]. 472 #[expect( 473 clippy::arithmetic_side_effects, 474 reason = "comment justifies its correctness" 475 )] 476 #[inline] 477 fn encode(&self) -> Result<Self::Output<'_>, Self::Err> { 478 let mut buffer = Vec::with_capacity( 479 // The maximum value is 1 + 2 + 2048 + 4 + 1 + 1 + 1 + 1 + 1 = 2060 so overflow cannot happen. 480 // `key.0.len() <= MAX_RSA_N_BYTES` which is 2048. 481 match self.credential_public_key { 482 UncompressedPubKey::Ed25519(_) => 33, 483 UncompressedPubKey::P256(_) => 34, 484 UncompressedPubKey::P384(_) => 50, 485 UncompressedPubKey::Rsa(key) => 1 + 2 + key.0.len() + 4, 486 } + 1 487 + 1 488 + usize::from(self.extensions.hmac_secret.is_some()) 489 + 1 490 + usize::from(self.client_extension_results.prf.is_some()), 491 ); 492 self.credential_public_key.encode_into_buffer(&mut buffer); 493 self.extensions.encode_into_buffer(&mut buffer); 494 self.client_extension_results 495 .encode_into_buffer(&mut buffer); 496 Ok(buffer) 497 } 498 } 499 /// Error returned from [`StaticState::decode`]. 500 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 501 pub enum DecodeStaticStateErr { 502 /// Variant returned when [`StaticState::credential_public_key`] could not be decoded. 503 CredentialPublicKey, 504 /// Variant returned when [`StaticState::extensions`] could not be decoded. 505 Extensions, 506 /// Variant returned when [`StaticState::client_extension_results`] could not be decoded. 507 ClientExtensionResults, 508 /// Variant returned when there was trailing data after decoding a [`StaticState`]. 509 TrailingData, 510 } 511 impl Display for DecodeStaticStateErr { 512 #[inline] 513 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 514 f.write_str(match *self { 515 Self::CredentialPublicKey => "credential_public_key could not be decoded", 516 Self::Extensions => "extensions could not be decoded", 517 Self::ClientExtensionResults => "client_extension_results could not be decoded", 518 Self::TrailingData => "there was trailing data after decoding a StaticState", 519 }) 520 } 521 } 522 impl Error for DecodeStaticStateErr {} 523 impl Decode 524 for StaticState< 525 CompressedPubKey< 526 [u8; ed25519_dalek::PUBLIC_KEY_LENGTH], 527 [u8; <NistP256 as Curve>::FieldBytesSize::INT], 528 [u8; <NistP384 as Curve>::FieldBytesSize::INT], 529 Vec<u8>, 530 >, 531 > 532 { 533 type Input<'a> = &'a [u8]; 534 type Err = DecodeStaticStateErr; 535 /// Interprets `input` as the [`StaticState::Output`] of [`StaticState::encode`]. 536 #[inline] 537 fn decode(mut input: Self::Input<'_>) -> Result<Self, Self::Err> { 538 CompressedPubKey::decode_from_buffer(&mut input) 539 .map_err(|_e| DecodeStaticStateErr::CredentialPublicKey) 540 .and_then(|credential_public_key| { 541 AuthenticatorExtensionOutputStaticState::decode_from_buffer(&mut input) 542 .map_err(|_e| DecodeStaticStateErr::Extensions) 543 .and_then(|extensions| { 544 ClientExtensionsOutputsStaticState::decode_from_buffer(&mut input) 545 .map_err(|_e| DecodeStaticStateErr::ClientExtensionResults) 546 .and_then(|client_extension_results| { 547 if input.is_empty() { 548 Ok(Self { 549 credential_public_key, 550 extensions, 551 client_extension_results, 552 }) 553 } else { 554 Err(DecodeStaticStateErr::TrailingData) 555 } 556 }) 557 }) 558 }) 559 } 560 } 561 impl Encode for DynamicState { 562 type Output<'a> 563 = [u8; 7] 564 where 565 Self: 'a; 566 type Err = Infallible; 567 #[expect( 568 clippy::little_endian_bytes, 569 reason = "need cross-platform correctness" 570 )] 571 #[inline] 572 fn encode(&self) -> Result<Self::Output<'_>, Self::Err> { 573 let mut buffer = [ 574 u8::from(self.user_verified), 575 match self.backup { 576 Backup::NotEligible => 0, 577 Backup::Eligible => 1, 578 Backup::Exists => 2, 579 }, 580 0, 581 0, 582 0, 583 0, 584 match self.authenticator_attachment { 585 AuthenticatorAttachment::None => 0, 586 AuthenticatorAttachment::Platform => 1, 587 AuthenticatorAttachment::CrossPlatform => 2, 588 }, 589 ]; 590 buffer[2..6].copy_from_slice(self.sign_count.to_le_bytes().as_slice()); 591 Ok(buffer) 592 } 593 } 594 /// Error returned from [`DynamicState::decode`]. 595 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 596 pub enum DecodeDynamicStateErr { 597 /// Variant returned when [`DynamicState::user_verified`] could not be decoded. 598 UserVerified, 599 /// Variant returned when [`DynamicState::backup`] could not be decoded. 600 Backup, 601 /// Variant returned when [`DynamicState::sign_count`] could not be decoded. 602 SignCount, 603 /// Variant returned when [`DynamicState::authenticator_attachment`] could not be decoded. 604 AuthenticatorAttachment, 605 } 606 impl Display for DecodeDynamicStateErr { 607 #[inline] 608 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 609 f.write_str(match *self { 610 Self::UserVerified => "user_verified could not be decoded", 611 Self::Backup => "backup could not be decoded", 612 Self::SignCount => "sign_count could not be decoded", 613 Self::AuthenticatorAttachment => "authenticator_attachment could not be decoded", 614 }) 615 } 616 } 617 impl Error for DecodeDynamicStateErr {} 618 impl Decode for DynamicState { 619 type Input<'a> = [u8; 7]; 620 type Err = DecodeDynamicStateErr; 621 #[expect( 622 clippy::panic_in_result_fn, 623 reason = "want to crash when there is a bug" 624 )] 625 #[inline] 626 fn decode(input: Self::Input<'_>) -> Result<Self, Self::Err> { 627 let mut buffer = input.as_slice(); 628 bool::decode_from_buffer(&mut buffer) 629 .map_err(|_e| DecodeDynamicStateErr::UserVerified) 630 .and_then(|user_verified| { 631 Backup::decode_from_buffer(&mut buffer) 632 .map_err(|_e| DecodeDynamicStateErr::Backup) 633 .and_then(|backup| { 634 u32::decode_from_buffer(&mut buffer) 635 .map_err(|_e| DecodeDynamicStateErr::SignCount) 636 .and_then(|sign_count| { 637 AuthenticatorAttachment::decode_from_buffer(&mut buffer) 638 .map_err(|_e| DecodeDynamicStateErr::AuthenticatorAttachment) 639 .map(|authenticator_attachment| { 640 assert!( 641 buffer.is_empty(), 642 "there is a bug in DynamicState::decode" 643 ); 644 Self { 645 user_verified, 646 backup, 647 sign_count, 648 authenticator_attachment, 649 } 650 }) 651 }) 652 }) 653 }) 654 } 655 }