Skip to content

Commit 660fdc9

Browse files
chore(api): mark growable public response and spec types non_exhaustive
Add #[non_exhaustive] to CTAP2 command, transport, attestation and biometric enums plus the get-info, make-credential, get-assertion, bio-enrollment, credential-management, client-pin and large-blobs response structs so adding fields or variants stays backward compatible. Seal the test-only dummy() constructors out of the public API.
1 parent 537aca1 commit 660fdc9

10 files changed

Lines changed: 39 additions & 4 deletions

File tree

libwebauthn/src/ops/webauthn/make_credential.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,8 @@ pub struct MakeCredentialsRequestExtensions {
652652
pub type MakeCredentialsResponseExtensions = Ctap2MakeCredentialsResponseExtensions;
653653

654654
impl MakeCredentialRequest {
655-
pub fn dummy() -> Self {
655+
#[cfg(test)]
656+
pub(crate) fn dummy() -> Self {
656657
Self {
657658
challenge: Vec::new(),
658659
origin: "example.org".to_owned(),

libwebauthn/src/proto/ctap1/model.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl Ctap1RegisterRequest {
8686
}
8787
}
8888

89-
pub fn dummy(timeout: Duration) -> Self {
89+
pub(crate) fn dummy(timeout: Duration) -> Self {
9090
Ctap1RegisterRequest {
9191
version: Ctap1Version::U2fV2,
9292
app_id_hash: vec![0; 32],

libwebauthn/src/proto/ctap2/model.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,29 @@ pub use credential_management::{
5050
mod large_blobs;
5151
pub use large_blobs::{Ctap2LargeBlobsRequest, Ctap2LargeBlobsResponse};
5252

53+
/// CTAP2 command codes; `#[non_exhaustive]` so consumers handle unknown variants.
54+
///
55+
/// ```compile_fail
56+
/// use libwebauthn::proto::ctap2::Ctap2CommandCode;
57+
/// let code = Ctap2CommandCode::AuthenticatorGetInfo;
58+
/// let _value: u8 = match code {
59+
/// Ctap2CommandCode::AuthenticatorMakeCredential => 0x01,
60+
/// Ctap2CommandCode::AuthenticatorGetAssertion => 0x02,
61+
/// Ctap2CommandCode::AuthenticatorGetInfo => 0x04,
62+
/// Ctap2CommandCode::AuthenticatorClientPin => 0x06,
63+
/// Ctap2CommandCode::AuthenticatorGetNextAssertion => 0x08,
64+
/// Ctap2CommandCode::AuthenticatorBioEnrollment => 0x09,
65+
/// Ctap2CommandCode::AuthenticatorBioEnrollmentPreview => 0x40,
66+
/// Ctap2CommandCode::AuthenticatorCredentialManagement => 0x0A,
67+
/// Ctap2CommandCode::AuthenticatorCredentialManagementPreview => 0x41,
68+
/// Ctap2CommandCode::AuthenticatorSelection => 0x0B,
69+
/// Ctap2CommandCode::AuthenticatorLargeBlobs => 0x0C,
70+
/// Ctap2CommandCode::AuthenticatorConfig => 0x0D,
71+
/// };
72+
/// ```
5373
#[derive(Debug, IntoPrimitive, TryFromPrimitive, Copy, Clone, PartialEq, Serialize_repr)]
5474
#[repr(u8)]
75+
#[non_exhaustive]
5576
pub enum Ctap2CommandCode {
5677
AuthenticatorMakeCredential = 0x01,
5778
AuthenticatorGetAssertion = 0x02,
@@ -78,7 +99,7 @@ pub struct Ctap2PublicKeyCredentialRpEntity {
7899
}
79100

80101
impl Ctap2PublicKeyCredentialRpEntity {
81-
pub fn dummy() -> Self {
102+
pub(crate) fn dummy() -> Self {
82103
Self {
83104
id: String::from(".dummy"),
84105
name: Some(String::from(".dummy")),
@@ -109,7 +130,7 @@ pub struct Ctap2PublicKeyCredentialUserEntity {
109130
}
110131

111132
impl Ctap2PublicKeyCredentialUserEntity {
112-
pub fn dummy() -> Self {
133+
pub(crate) fn dummy() -> Self {
113134
Self {
114135
id: ByteBuf::from([1]),
115136
name: Some(String::from("dummy")),
@@ -150,6 +171,7 @@ pub enum Ctap2PublicKeyCredentialType {
150171
/// AuthenticatorTransport from a credential descriptor. Unknown values are kept in `Other` so they pass through unchanged.
151172
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
152173
#[serde(from = "String", into = "String")]
174+
#[non_exhaustive]
153175
pub enum Ctap2Transport {
154176
Ble,
155177
Nfc,

libwebauthn/src/proto/ctap2/model/bio_enrollment.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ pub struct Ctap2BioEnrollmentParams {
6868
}
6969

7070
#[derive(Debug, Default, Clone, DeserializeIndexed)]
71+
#[non_exhaustive]
7172
pub struct Ctap2BioEnrollmentResponse {
7273
// modality (0x01) Unsigned Integer Optional The user verification modality.
7374
#[serde(skip_serializing_if = "Option::is_none")]
@@ -145,12 +146,14 @@ pub enum Ctap2LastEnrollmentSampleStatus {
145146

146147
#[repr(u64)]
147148
#[derive(Debug, Clone, FromPrimitive, PartialEq, Serialize_repr, Deserialize_repr)]
149+
#[non_exhaustive]
148150
pub enum Ctap2BioEnrollmentModality {
149151
Fingerprint = 0x01, // Fingerprint was too high.
150152
}
151153

152154
#[repr(u64)]
153155
#[derive(Debug, Clone, FromPrimitive, PartialEq, Serialize_repr, Deserialize_repr)]
156+
#[non_exhaustive]
154157
pub enum Ctap2BioEnrollmentFingerprintKind {
155158
Touch = 0x01,
156159
Swipe = 0x02,

libwebauthn/src/proto/ctap2/model/client_pin.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ pub enum Ctap2PinUvAuthProtocolCommand {
224224

225225
#[cfg_attr(test, derive(SerializeIndexed))]
226226
#[derive(Debug, Clone, Default, DeserializeIndexed)]
227+
#[non_exhaustive]
227228
pub struct Ctap2ClientPinResponse {
228229
/// keyAgreement (0x01)
229230
#[serde(skip_serializing_if = "Option::is_none")]

libwebauthn/src/proto/ctap2/model/credential_management.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ pub struct Ctap2CredentialManagementParams {
8989
}
9090

9191
#[derive(Debug, Default, Clone, DeserializeIndexed)]
92+
#[non_exhaustive]
9293
pub struct Ctap2CredentialManagementResponse {
9394
// existingResidentCredentialsCount (0x01) Unsigned Integer Number of existing discoverable credentials present on the authenticator.
9495
#[serde(skip_serializing_if = "Option::is_none")]

libwebauthn/src/proto/ctap2/model/get_assertion.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ pub struct AppleAnonymousAttestationStmt {
9292

9393
#[derive(Debug, Clone, Deserialize, Serialize)]
9494
#[serde(untagged)]
95+
#[non_exhaustive]
9596
pub enum Ctap2AttestationStatement {
9697
PackedOrAndroid(PackedAttestationStmt),
9798
Tpm(TpmAttestationStmt),
@@ -512,6 +513,7 @@ pub struct CalculatedHMACGetSecretInput {
512513
}
513514

514515
#[derive(Debug, Clone, DeserializeIndexed)]
516+
#[non_exhaustive]
515517
pub struct Ctap2GetAssertionResponse {
516518
#[serde(skip_serializing_if = "Option::is_none")]
517519
#[serde(index = 0x01)]
@@ -687,6 +689,7 @@ impl Ctap2GetAssertionResponse {
687689

688690
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
689691
#[serde(rename_all = "camelCase")]
692+
#[non_exhaustive]
690693
pub struct Ctap2GetAssertionResponseExtensions {
691694
// Stored credBlob
692695
#[serde(default, skip_serializing_if = "Option::is_none", with = "serde_bytes")]

libwebauthn/src/proto/ctap2/model/get_info.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use super::{Ctap2CredentialType, Ctap2UserVerificationOperation};
1010

1111
#[cfg_attr(test, derive(SerializeIndexed))]
1212
#[derive(Debug, Clone, DeserializeIndexed, Default)]
13+
#[non_exhaustive]
1314
pub struct Ctap2GetInfoResponse {
1415
/// versions (0x01)
1516
#[serde(index = 0x01)]

libwebauthn/src/proto/ctap2/model/large_blobs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ impl Ctap2LargeBlobsRequest {
8888

8989
#[cfg_attr(test, derive(SerializeIndexed))]
9090
#[derive(Debug, Default, Clone, DeserializeIndexed)]
91+
#[non_exhaustive]
9192
pub struct Ctap2LargeBlobsResponse {
9293
#[serde(skip_serializing_if = "Option::is_none")]
9394
#[serde(index = 0x01)]

libwebauthn/src/proto/ctap2/model/make_credential.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ impl Ctap2MakeCredentialsRequestExtensions {
357357
}
358358

359359
#[derive(Debug, Clone, DeserializeIndexed)]
360+
#[non_exhaustive]
360361
pub struct Ctap2MakeCredentialResponse {
361362
#[serde(index = 0x01)]
362363
pub format: String,
@@ -469,6 +470,7 @@ impl Ctap2UserVerifiableRequest for Ctap2MakeCredentialRequest {
469470

470471
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
471472
#[serde(rename_all = "camelCase")]
473+
#[non_exhaustive]
472474
pub struct Ctap2MakeCredentialsResponseExtensions {
473475
// If storing credBlob was successful
474476
#[serde(default, skip_serializing_if = "Option::is_none")]

0 commit comments

Comments
 (0)