diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d3de11..c23b2d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Remove unused `REALISTIC_MAX_MESSAGE_SIZE` constant - Handle overlong `icon` values in `PublicKeyCredentialUserEntity` ([#27][]) - Update for compatibility with PIN protocol 2 +- Add support for permissions in `ctap2::client_pin` [#8]: https://github.com/trussed-dev/ctap-types/pull/8 [#9]: https://github.com/solokeys/ctap-types/issues/9 diff --git a/src/ctap2/client_pin.rs b/src/ctap2/client_pin.rs index 1c17548..83eba08 100644 --- a/src/ctap2/client_pin.rs +++ b/src/ctap2/client_pin.rs @@ -1,4 +1,5 @@ -use crate::Bytes; +use crate::{Bytes, String}; +use bitflags::bitflags; use serde_indexed::{DeserializeIndexed, SerializeIndexed}; use serde_repr::{Deserialize_repr, Serialize_repr}; @@ -17,6 +18,18 @@ pub enum PinV1Subcommand { GetPinUvAuthTokenUsingPinWithPermissions = 0x09, } +bitflags! { + #[derive(Default)] + pub struct Permissions: u8 { + const MAKE_CREDENTIAL = 0x01; + const GET_ASSERTION = 0x02; + const CREDENTIAL_MANAGEMENT = 0x04; + const BIO_ENROLLMENT = 0x08; + const LARGE_BLOB_WRITE = 0x10; + const AUTHENTICATOR_CONFIGURATION = 0x20; + } +} + // minimum PIN length: 4 unicode // maximum PIN length: UTF-8 represented by <= 63 bytes // maximum consecutive incorrect PIN attempts: 8 @@ -55,9 +68,27 @@ pub struct Request { // Encrypted first 16 bytes of SHA-256 of PIN using `sharedSecret`. #[serde(skip_serializing_if = "Option::is_none")] pub pin_hash_enc: Option>, + + // 0x07 + #[serde(skip_serializing_if = "Option::is_none")] + _placeholder07: Option<()>, + + // 0x08 + #[serde(skip_serializing_if = "Option::is_none")] + _placeholder08: Option<()>, + + // 0x09 + // Bitfield of permissions + #[serde(skip_serializing_if = "Option::is_none")] + pub permissions: Option, + + // 0x0A + // The RP ID to assign as the permissions RP ID + #[serde(skip_serializing_if = "Option::is_none")] + pub rp_id: Option>, } -#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)] +#[derive(Clone, Debug, Default, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)] #[serde_indexed(offset = 1)] pub struct Response { // 0x01, like ClientPinParameters::key_agreement @@ -71,6 +102,14 @@ pub struct Response { // 0x03, number of PIN attempts remaining before lockout #[serde(skip_serializing_if = "Option::is_none")] pub retries: Option, + + // 0x04, whether a power cycle is required before any future PIN operation + #[serde(skip_serializing_if = "Option::is_none")] + pub power_cycle_state: Option, + + // 0x05, number of uv attempts remaining before lockout + #[serde(skip_serializing_if = "Option::is_none")] + pub uv_retries: Option, } #[cfg(test)]