From 50d966a247a88d92ba2bf5621cf4e151bde68ba8 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Fri, 9 May 2025 11:16:14 +0200 Subject: [PATCH] ctap2::client_pin: Make pin_protocol optional in Request Since CTAP 2.1, the pin_protocol argument is optional for client_pin requests, see: https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#authnrClientPin-cmd-dfn --- CHANGELOG.md | 2 +- src/ctap2/client_pin.rs | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af899e5..02f8f88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [Unreleased]: https://github.com/trussed-dev/ctap-types/compare/0.3.2...HEAD -- +- Make `pin_protocol` optional in `ctap2::client_pin::Request` for compliance with CTAP 2.1. ## [0.3.2] 2024-10-24 diff --git a/src/ctap2/client_pin.rs b/src/ctap2/client_pin.rs index 048f375..50b4dae 100644 --- a/src/ctap2/client_pin.rs +++ b/src/ctap2/client_pin.rs @@ -41,8 +41,8 @@ bitflags! { pub struct Request<'a> { // 0x01 // PIN protocol version chosen by the client. - // For this version of the spec, this SHALL be the number 1. - pub pin_protocol: u8, + #[serde(skip_serializing_if = "Option::is_none")] + pub pin_protocol: Option, // 0x02 // The authenticator Client PIN sub command currently being requested @@ -119,7 +119,7 @@ pub struct Response { mod tests { use super::*; use hex_literal::hex; - use serde_test::{assert_de_tokens, assert_ser_tokens, assert_tokens, Token}; + use serde_test::{assert_de_tokens, assert_ser_tokens, Token}; const KEY_AGREEMENT: &[u8] = &hex!("b174bc49c7ca254b70d2e5c207cee9cf174820ebd77ea3c65508c26da51b657c1cc6b952f8621697936482da0a6d3d3826a59095daf6cd7c03e2e60385d2f6d9"); const NEW_PIN_ENC: &[u8] = &[0xde; 64]; @@ -130,7 +130,7 @@ mod tests { #[test] fn test_de_request_get_retries() { let request = Request { - pin_protocol: 1, + pin_protocol: Some(1), sub_command: PinV1Subcommand::GetRetries, key_agreement: None, pin_auth: None, @@ -141,7 +141,7 @@ mod tests { permissions: None, rp_id: None, }; - assert_tokens( + assert_de_tokens( &request, &[ Token::Map { len: Some(2) }, @@ -159,7 +159,7 @@ mod tests { #[test] fn test_de_request_get_key_agreement() { let request = Request { - pin_protocol: 1, + pin_protocol: Some(1), sub_command: PinV1Subcommand::GetKeyAgreement, key_agreement: None, pin_auth: None, @@ -170,7 +170,7 @@ mod tests { permissions: None, rp_id: None, }; - assert_tokens( + assert_de_tokens( &request, &[ Token::Map { len: Some(2) }, @@ -192,7 +192,7 @@ mod tests { y: Bytes::from_slice(&KEY_AGREEMENT[32..]).unwrap(), }; let request = Request { - pin_protocol: 1, + pin_protocol: Some(1), sub_command: PinV1Subcommand::SetPin, key_agreement: Some(key_agreement), pin_auth: Some(serde_bytes::Bytes::new(PIN_AUTH)), @@ -250,7 +250,7 @@ mod tests { y: Bytes::from_slice(&KEY_AGREEMENT[32..]).unwrap(), }; let request = Request { - pin_protocol: 1, + pin_protocol: Some(1), sub_command: PinV1Subcommand::ChangePin, key_agreement: Some(key_agreement), pin_auth: Some(serde_bytes::Bytes::new(PIN_AUTH)), @@ -311,7 +311,7 @@ mod tests { y: Bytes::from_slice(&KEY_AGREEMENT[32..]).unwrap(), }; let request = Request { - pin_protocol: 1, + pin_protocol: Some(1), sub_command: PinV1Subcommand::GetPinToken, key_agreement: Some(key_agreement), pin_auth: None, @@ -366,7 +366,7 @@ mod tests { y: Bytes::from_slice(&KEY_AGREEMENT[32..]).unwrap(), }; let request = Request { - pin_protocol: 1, + pin_protocol: Some(1), sub_command: PinV1Subcommand::GetPinUvAuthTokenUsingPinWithPermissions, key_agreement: Some(key_agreement), pin_auth: None,