From bf5736b750930c14d978dc34ab12798747be4337 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Mon, 17 Jun 2024 22:53:02 +0200 Subject: [PATCH 1/2] get_info: Put uncommon fields behind feature flag --- .github/workflows/ci.yml | 1 + CHANGELOG.md | 1 + Cargo.toml | 2 ++ src/ctap2/get_info.rs | 22 ++++++++++++++++++++++ 4 files changed, 26 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b850ddc..d69e649 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,7 @@ jobs: - name: Check library run: | cargo check + cargo check --features get-info-full cargo check --features large-blobs cargo check --all-features diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c2e338..1208f3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Mark `get_assertion::{ExtensionsInput, ExtensionsOutput}` and `make_credential::Extensions` as non-exhaustive and implement `Default` - Mark CTAP2 request and response types as non-exhaustive where possible - Use references where possible +- Put uncommon fields in `get_info` behind `get-info-full` feature flag [#8]: https://github.com/trussed-dev/ctap-types/pull/8 [#9]: https://github.com/solokeys/ctap-types/issues/9 diff --git a/Cargo.toml b/Cargo.toml index 87e09e0..ff969b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,8 @@ serde_bytes = { version = "0.11.12", default-features = false } serde_repr = "0.1" [features] +# enables all fields for ctap2::get_info::CtapOptions +get-info-full = [] # enables support for implementing the large-blobs extension, see src/sizes.rs large-blobs = [] diff --git a/src/ctap2/get_info.rs b/src/ctap2/get_info.rs index 056e33c..096be8b 100644 --- a/src/ctap2/get_info.rs +++ b/src/ctap2/get_info.rs @@ -108,6 +108,7 @@ impl ResponseBuilder { #[non_exhaustive] #[serde(rename_all = "camelCase")] pub struct CtapOptions { + #[cfg(feature = "get-info-full")] #[serde(skip_serializing_if = "Option::is_none")] pub ep: Option, // default false pub rk: bool, @@ -119,32 +120,42 @@ pub struct CtapOptions { pub uv: Option, // default not capable #[serde(skip_serializing_if = "Option::is_none")] pub plat: Option, // default false + #[cfg(feature = "get-info-full")] #[serde(skip_serializing_if = "Option::is_none")] pub uv_acfg: Option, // default false + #[cfg(feature = "get-info-full")] #[serde(skip_serializing_if = "Option::is_none")] pub always_uv: Option, #[serde(skip_serializing_if = "Option::is_none")] pub cred_mgmt: Option, + #[cfg(feature = "get-info-full")] #[serde(skip_serializing_if = "Option::is_none")] pub authnr_cfg: Option, + #[cfg(feature = "get-info-full")] #[serde(skip_serializing_if = "Option::is_none")] pub bio_enroll: Option, // default false #[serde(skip_serializing_if = "Option::is_none")] pub client_pin: Option, #[serde(skip_serializing_if = "Option::is_none")] pub large_blobs: Option, + #[cfg(feature = "get-info-full")] #[serde(skip_serializing_if = "Option::is_none")] pub uv_bio_enroll: Option, + #[cfg(feature = "get-info-full")] #[serde(rename = "setMinPINLength", skip_serializing_if = "Option::is_none")] pub set_min_pin_length: Option, // default false #[serde(skip_serializing_if = "Option::is_none")] pub pin_uv_auth_token: Option, + #[cfg(feature = "get-info-full")] #[serde(skip_serializing_if = "Option::is_none")] pub make_cred_uv_not_rqd: Option, + #[cfg(feature = "get-info-full")] #[serde(skip_serializing_if = "Option::is_none")] pub credential_mgmt_preview: Option, + #[cfg(feature = "get-info-full")] #[serde(skip_serializing_if = "Option::is_none")] pub user_verification_mgmt_preview: Option, + #[cfg(feature = "get-info-full")] #[serde(skip_serializing_if = "Option::is_none")] pub no_mc_ga_permissions_with_client_pin: Option, } @@ -152,24 +163,35 @@ pub struct CtapOptions { impl Default for CtapOptions { fn default() -> Self { Self { + #[cfg(feature = "get-info-full")] ep: None, rk: false, up: true, uv: None, plat: None, + #[cfg(feature = "get-info-full")] uv_acfg: None, + #[cfg(feature = "get-info-full")] always_uv: None, cred_mgmt: None, + #[cfg(feature = "get-info-full")] authnr_cfg: None, + #[cfg(feature = "get-info-full")] bio_enroll: None, client_pin: None, large_blobs: None, + #[cfg(feature = "get-info-full")] uv_bio_enroll: None, pin_uv_auth_token: None, + #[cfg(feature = "get-info-full")] set_min_pin_length: None, + #[cfg(feature = "get-info-full")] make_cred_uv_not_rqd: None, + #[cfg(feature = "get-info-full")] credential_mgmt_preview: None, + #[cfg(feature = "get-info-full")] user_verification_mgmt_preview: None, + #[cfg(feature = "get-info-full")] no_mc_ga_permissions_with_client_pin: None, } } From cd854a815ba454c367e184d1ca8f1b88b9dd073e Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Thu, 20 Jun 2024 22:48:18 +0200 Subject: [PATCH 2/2] get_info: Add fields for CTAP 2.1 --- CHANGELOG.md | 2 +- Cargo.toml | 2 +- src/ctap2/get_info.rs | 125 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 116 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1208f3b..dc575b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Mark `get_assertion::{ExtensionsInput, ExtensionsOutput}` and `make_credential::Extensions` as non-exhaustive and implement `Default` - Mark CTAP2 request and response types as non-exhaustive where possible - Use references where possible -- Put uncommon fields in `get_info` behind `get-info-full` feature flag +- Put uncommon fields in `get_info` behind `get-info-full` feature flag and add fields for CTAP 2.1 [#8]: https://github.com/trussed-dev/ctap-types/pull/8 [#9]: https://github.com/solokeys/ctap-types/issues/9 diff --git a/Cargo.toml b/Cargo.toml index ff969b4..c5054ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ serde_bytes = { version = "0.11.12", default-features = false } serde_repr = "0.1" [features] -# enables all fields for ctap2::get_info::CtapOptions +# enables all fields for ctap2::get_info get-info-full = [] # enables support for implementing the large-blobs extension, see src/sizes.rs large-blobs = [] diff --git a/src/ctap2/get_info.rs b/src/ctap2/get_info.rs index 096be8b..2b999f4 100644 --- a/src/ctap2/get_info.rs +++ b/src/ctap2/get_info.rs @@ -55,6 +55,66 @@ pub struct Response { // FIDO_2_1 #[serde(skip_serializing_if = "Option::is_none")] pub max_serialized_large_blob_array: Option, + + // 0x0C + // FIDO_2_1 + #[cfg(feature = "get-info-full")] + #[serde(skip_serializing_if = "Option::is_none")] + pub force_pin_change: Option, + + // 0x0D + // FIDO_2_1 + #[cfg(feature = "get-info-full")] + #[serde(skip_serializing_if = "Option::is_none")] + pub min_pin_length: Option, + + // 0x0E + // FIDO_2_1 + #[cfg(feature = "get-info-full")] + #[serde(skip_serializing_if = "Option::is_none")] + pub firmware_version: Option, + + // 0x0F + // FIDO_2_1 + #[cfg(feature = "get-info-full")] + #[serde(skip_serializing_if = "Option::is_none")] + pub max_cred_blob_length: Option, + + // 0x10 + // FIDO_2_1 + #[cfg(feature = "get-info-full")] + #[serde(skip_serializing_if = "Option::is_none")] + pub max_rpids_for_set_min_pin_length: Option, + + // 0x11 + // FIDO_2_1 + #[cfg(feature = "get-info-full")] + #[serde(skip_serializing_if = "Option::is_none")] + pub preferred_platform_uv_attempts: Option, + + // 0x12 + // FIDO_2_1 + #[cfg(feature = "get-info-full")] + #[serde(skip_serializing_if = "Option::is_none")] + pub uv_modality: Option, + + // 0x13 + // FIDO_2_1 + #[cfg(feature = "get-info-full")] + #[serde(skip_serializing_if = "Option::is_none")] + pub certifications: Option, + + // 0x14 + // FIDO_2_1 + #[cfg(feature = "get-info-full")] + #[serde(skip_serializing_if = "Option::is_none")] + pub remaining_discoverable_credentials: Option, + + // 0x15 + // FIDO_2_1 + #[cfg(feature = "get-info-full")] + #[serde(skip_serializing_if = "Option::is_none")] + pub vendor_prototype_config_commands: Option, } impl Default for Response { @@ -63,19 +123,13 @@ impl Default for Response { zero_aaguid.resize_default(16).unwrap(); let aaguid = Bytes::<16>::from(zero_aaguid); - Self { - versions: Vec::new(), - extensions: None, + let mut response = ResponseBuilder { aaguid, - options: Some(CtapOptions::default()), - max_msg_size: None, //Some(MESSAGE_SIZE), - pin_protocols: None, - max_creds_in_list: None, - max_cred_id_length: None, - transports: None, - algorithms: None, - max_serialized_large_blob_array: None, + versions: Vec::new(), } + .build(); + response.options = Some(CtapOptions::default()); + response } } @@ -100,6 +154,26 @@ impl ResponseBuilder { transports: None, algorithms: None, max_serialized_large_blob_array: None, + #[cfg(feature = "get-info-full")] + force_pin_change: None, + #[cfg(feature = "get-info-full")] + min_pin_length: None, + #[cfg(feature = "get-info-full")] + firmware_version: None, + #[cfg(feature = "get-info-full")] + max_cred_blob_length: None, + #[cfg(feature = "get-info-full")] + max_rpids_for_set_min_pin_length: None, + #[cfg(feature = "get-info-full")] + preferred_platform_uv_attempts: None, + #[cfg(feature = "get-info-full")] + uv_modality: None, + #[cfg(feature = "get-info-full")] + certifications: None, + #[cfg(feature = "get-info-full")] + remaining_discoverable_credentials: None, + #[cfg(feature = "get-info-full")] + vendor_prototype_config_commands: None, } } } @@ -196,3 +270,32 @@ impl Default for CtapOptions { } } } + +#[cfg(feature = "get-info-full")] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[non_exhaustive] +pub struct Certifications { + #[serde(rename = "FIPS-CMVP-2")] + #[serde(skip_serializing_if = "Option::is_none")] + pub fips_cmpv2: Option, + + #[serde(rename = "FIPS-CMVP-3")] + #[serde(skip_serializing_if = "Option::is_none")] + pub fips_cmpv3: Option, + + #[serde(rename = "FIPS-CMVP-2-PHY")] + #[serde(skip_serializing_if = "Option::is_none")] + pub fips_cmpv2_phy: Option, + + #[serde(rename = "FIPS-CMVP-3-PHY")] + #[serde(skip_serializing_if = "Option::is_none")] + pub fips_cmpv3_phy: Option, + + #[serde(rename = "CC-EAL")] + #[serde(skip_serializing_if = "Option::is_none")] + pub cc_eal: Option, + + #[serde(rename = "FIDO")] + #[serde(skip_serializing_if = "Option::is_none")] + pub fido: Option, +}