webauthn_authenticator_rs/ctap2/commands/
config.rs1use serde::Serialize;
2use serde_cbor_2::Value;
3
4use self::CBORCommand;
5use super::*;
6
7#[derive(Serialize, Debug, Clone, Default, PartialEq, Eq)]
16#[serde(into = "BTreeMap<u32, Value>")]
17pub struct ConfigRequest {
18 sub_command: u8,
20 sub_command_params: Option<BTreeMap<Value, Value>>,
21 pin_uv_protocol: Option<u32>,
23 pin_uv_auth_param: Option<Vec<u8>>,
25}
26
27impl CBORCommand for ConfigRequest {
28 const CMD: u8 = 0x0d;
29 type Response = NoResponse;
30}
31
32#[derive(Debug, Clone, PartialEq, Eq, Default)]
34pub enum ConfigSubCommand {
35 #[default]
36 Unknown,
37 EnableEnterpriseAttestation,
41 ToggleAlwaysUv,
45 SetMinPinLength(SetMinPinLengthParams),
51 }
53
54#[derive(Serialize, Debug, Clone, Default, PartialEq, Eq)]
56#[serde(into = "BTreeMap<Value, Value>")]
57pub struct SetMinPinLengthParams {
58 pub new_min_pin_length: Option<u32>,
60 pub min_pin_length_rpids: Vec<String>,
63 pub force_change_pin: Option<bool>,
66}
67
68impl From<&ConfigSubCommand> for u8 {
69 fn from(c: &ConfigSubCommand) -> Self {
70 use ConfigSubCommand::*;
71 match c {
72 Unknown => 0x00,
73 EnableEnterpriseAttestation => 0x01,
74 ToggleAlwaysUv => 0x02,
75 SetMinPinLength(_) => 0x03,
76 }
78 }
79}
80
81impl From<ConfigSubCommand> for Option<BTreeMap<Value, Value>> {
82 fn from(c: ConfigSubCommand) -> Self {
83 use ConfigSubCommand::*;
84 match c {
85 SetMinPinLength(p) => Some(p.into()),
86 Unknown => None,
87 EnableEnterpriseAttestation => None,
88 ToggleAlwaysUv => None,
89 }
91 }
92}
93
94impl ConfigSubCommand {
95 pub fn prf(&self) -> Vec<u8> {
96 let sub_command = self.into();
98 let sub_command_params: Option<BTreeMap<Value, Value>> = self.to_owned().into();
99
100 let mut o = vec![0xff; 32];
101 o.push(ConfigRequest::CMD);
102 o.push(sub_command);
103 if let Some(p) = sub_command_params
104 .as_ref()
105 .and_then(|p| serde_cbor_2::to_vec(p).ok())
106 {
107 o.extend_from_slice(p.as_slice())
108 }
109
110 o
111 }
112}
113
114impl ConfigRequest {
115 pub fn new(
116 s: ConfigSubCommand,
117 pin_uv_protocol: Option<u32>,
118 pin_uv_auth_param: Option<Vec<u8>>,
119 ) -> Self {
120 let sub_command = (&s).into();
121 let sub_command_params = s.into();
122
123 Self {
124 sub_command,
125 sub_command_params,
126 pin_uv_protocol,
127 pin_uv_auth_param,
128 }
129 }
130}
131
132impl From<ConfigRequest> for BTreeMap<u32, Value> {
133 fn from(value: ConfigRequest) -> Self {
134 let ConfigRequest {
135 sub_command,
136 sub_command_params,
137 pin_uv_protocol,
138 pin_uv_auth_param,
139 } = value;
140
141 let mut keys = BTreeMap::new();
142 keys.insert(0x01, Value::Integer(sub_command.into()));
143
144 if let Some(v) = sub_command_params {
145 keys.insert(0x02, Value::Map(v));
146 }
147
148 if let Some(v) = pin_uv_protocol {
149 keys.insert(0x03, Value::Integer(v.to_owned().into()));
150 }
151 if let Some(v) = pin_uv_auth_param {
152 keys.insert(0x04, Value::Bytes(v));
153 }
154
155 keys
156 }
157}
158
159impl From<SetMinPinLengthParams> for BTreeMap<Value, Value> {
160 fn from(value: SetMinPinLengthParams) -> Self {
161 let SetMinPinLengthParams {
162 new_min_pin_length,
163 min_pin_length_rpids,
164 force_change_pin,
165 } = value;
166
167 let mut keys = BTreeMap::new();
168
169 if let Some(v) = new_min_pin_length {
170 keys.insert(Value::Integer(0x01), Value::Integer(v.to_owned().into()));
171 }
172
173 if !min_pin_length_rpids.is_empty() {
174 keys.insert(
175 Value::Integer(0x02),
176 Value::Array(
177 min_pin_length_rpids
178 .iter()
179 .map(|v| Value::Text(v.clone()))
180 .collect(),
181 ),
182 );
183 }
184
185 if let Some(v) = force_change_pin {
186 keys.insert(Value::Integer(0x03), Value::Bool(v.to_owned()));
187 }
188
189 keys
190 }
191}