1use crate::error::{Error, Result};
4
5use soft_fido2_ctap::types::{RelyingParty, User};
6
7use alloc::string::String;
8use alloc::vec::Vec;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct ClientDataHash([u8; 32]);
16
17impl ClientDataHash {
18 pub fn new(hash: [u8; 32]) -> Self {
20 Self(hash)
21 }
22
23 pub fn from_slice(slice: &[u8]) -> Result<Self> {
29 if slice.len() != 32 {
30 return Err(Error::InvalidClientDataHash);
31 }
32 let mut hash = [0u8; 32];
33 hash.copy_from_slice(slice);
34 Ok(Self(hash))
35 }
36
37 pub fn as_bytes(&self) -> &[u8; 32] {
39 &self.0
40 }
41
42 pub fn as_slice(&self) -> &[u8] {
44 &self.0
45 }
46}
47
48impl AsRef<[u8]> for ClientDataHash {
49 fn as_ref(&self) -> &[u8] {
50 &self.0
51 }
52}
53
54impl From<[u8; 32]> for ClientDataHash {
55 fn from(hash: [u8; 32]) -> Self {
56 Self::new(hash)
57 }
58}
59
60#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
62pub enum CredentialType {
63 #[default]
65 PublicKey,
66}
67
68impl CredentialType {
69 pub fn as_str(&self) -> &'static str {
71 match self {
72 CredentialType::PublicKey => "public-key",
73 }
74 }
75}
76
77#[derive(Debug, Clone, PartialEq, Eq)]
81pub struct CredentialDescriptor {
82 pub id: Vec<u8>,
84 pub credential_type: CredentialType,
86}
87
88impl CredentialDescriptor {
89 pub fn new(id: Vec<u8>, credential_type: CredentialType) -> Self {
91 Self {
92 id,
93 credential_type,
94 }
95 }
96
97 pub fn public_key(id: Vec<u8>) -> Self {
99 Self {
100 id,
101 credential_type: CredentialType::PublicKey,
102 }
103 }
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
108#[repr(u8)]
109pub enum PinUvAuthProtocol {
110 V1 = 1,
112 V2 = 2,
114}
115
116impl PinUvAuthProtocol {
117 pub fn as_u8(self) -> u8 {
119 self as u8
120 }
121}
122
123impl From<PinUvAuthProtocol> for u8 {
124 fn from(protocol: PinUvAuthProtocol) -> u8 {
125 protocol.as_u8()
126 }
127}
128
129#[derive(Debug, Clone)]
133pub struct PinUvAuth {
134 param: Vec<u8>,
135 protocol: PinUvAuthProtocol,
136}
137
138impl PinUvAuth {
139 pub fn new(param: Vec<u8>, protocol: PinUvAuthProtocol) -> Self {
146 Self { param, protocol }
147 }
148
149 pub fn param(&self) -> &[u8] {
151 &self.param
152 }
153
154 pub fn protocol(&self) -> PinUvAuthProtocol {
156 self.protocol
157 }
158
159 pub fn protocol_u8(&self) -> u8 {
161 self.protocol.as_u8()
162 }
163}
164
165#[derive(Debug)]
169pub struct MakeCredentialRequest {
170 pub(crate) client_data_hash: ClientDataHash,
171 pub(crate) rp: RelyingParty,
172 pub(crate) user: User,
173 pub(crate) pin_uv_auth: Option<PinUvAuth>,
174 pub(crate) timeout_ms: i32,
175 pub(crate) resident_key: Option<bool>,
176 pub(crate) user_verification: Option<bool>,
177}
178
179impl MakeCredentialRequest {
180 pub fn new(client_data_hash: ClientDataHash, rp: RelyingParty, user: User) -> Self {
188 Self {
189 client_data_hash,
190 rp,
191 user,
192 pin_uv_auth: None,
193 timeout_ms: 30000, resident_key: None,
195 user_verification: None,
196 }
197 }
198
199 pub fn with_pin_uv_auth(mut self, auth: PinUvAuth) -> Self {
201 self.pin_uv_auth = Some(auth);
202 self
203 }
204
205 pub fn with_timeout(mut self, timeout_ms: i32) -> Self {
207 self.timeout_ms = timeout_ms;
208 self
209 }
210
211 pub fn with_resident_key(mut self, resident_key: bool) -> Self {
213 self.resident_key = Some(resident_key);
214 self
215 }
216
217 pub fn with_user_verification(mut self, user_verification: bool) -> Self {
219 self.user_verification = Some(user_verification);
220 self
221 }
222
223 pub fn client_data_hash(&self) -> &ClientDataHash {
225 &self.client_data_hash
226 }
227
228 pub fn rp(&self) -> &RelyingParty {
230 &self.rp
231 }
232
233 pub fn user(&self) -> &User {
235 &self.user
236 }
237
238 pub fn pin_uv_auth(&self) -> Option<&PinUvAuth> {
240 self.pin_uv_auth.as_ref()
241 }
242
243 pub fn timeout_ms(&self) -> i32 {
245 self.timeout_ms
246 }
247}
248
249#[derive(Debug)]
253pub struct GetAssertionRequest {
254 pub(crate) client_data_hash: ClientDataHash,
255 pub(crate) rp_id: String,
256 pub(crate) allow_list: Vec<CredentialDescriptor>,
257 pub(crate) pin_uv_auth: Option<PinUvAuth>,
258 pub(crate) timeout_ms: i32,
259 pub(crate) user_verification: Option<bool>,
260}
261
262impl GetAssertionRequest {
263 pub fn new(client_data_hash: ClientDataHash, rp_id: impl Into<String>) -> Self {
270 Self {
271 client_data_hash,
272 rp_id: rp_id.into(),
273 allow_list: Vec::new(),
274 pin_uv_auth: None,
275 timeout_ms: 30000, user_verification: None,
277 }
278 }
279
280 pub fn with_credential(mut self, credential: CredentialDescriptor) -> Self {
282 self.allow_list.push(credential);
283 self
284 }
285
286 pub fn with_credentials(mut self, credentials: Vec<CredentialDescriptor>) -> Self {
288 self.allow_list = credentials;
289 self
290 }
291
292 pub fn with_pin_uv_auth(mut self, auth: PinUvAuth) -> Self {
294 self.pin_uv_auth = Some(auth);
295 self
296 }
297
298 pub fn with_timeout(mut self, timeout_ms: i32) -> Self {
300 self.timeout_ms = timeout_ms;
301 self
302 }
303
304 pub fn with_user_verification(mut self, user_verification: bool) -> Self {
306 self.user_verification = Some(user_verification);
307 self
308 }
309
310 pub fn client_data_hash(&self) -> &ClientDataHash {
312 &self.client_data_hash
313 }
314
315 pub fn rp_id(&self) -> &str {
317 &self.rp_id
318 }
319
320 pub fn allow_list(&self) -> &[CredentialDescriptor] {
322 &self.allow_list
323 }
324
325 pub fn pin_uv_auth(&self) -> Option<&PinUvAuth> {
327 self.pin_uv_auth.as_ref()
328 }
329
330 pub fn timeout_ms(&self) -> i32 {
332 self.timeout_ms
333 }
334}
335
336#[derive(Debug, Clone, Copy, PartialEq, Eq)]
340#[repr(u8)]
341pub enum Permission {
342 MakeCredential = 0x01,
344 GetAssertion = 0x02,
346 CredentialManagement = 0x04,
348 BioEnrollment = 0x08,
350 LargeBlobWrite = 0x10,
352 AuthenticatorConfiguration = 0x20,
354}
355
356impl Permission {
357 pub fn to_u8(self) -> u8 {
359 self as u8
360 }
361}
362
363#[derive(Debug, Clone)]
365pub struct CredentialManagementRequest {
366 pin_uv_auth: Option<PinUvAuth>,
367}
368
369impl CredentialManagementRequest {
370 pub fn new(pin_uv_auth: Option<PinUvAuth>) -> Self {
379 Self { pin_uv_auth }
380 }
381
382 pub fn pin_uv_auth(&self) -> Option<&PinUvAuth> {
384 self.pin_uv_auth.as_ref()
385 }
386}
387
388#[derive(Debug, Clone)]
390pub struct EnumerateCredentialsRequest {
391 pin_uv_auth: Option<PinUvAuth>,
392 rp_id_hash: [u8; 32],
393}
394
395impl EnumerateCredentialsRequest {
396 pub fn new(pin_uv_auth: Option<PinUvAuth>, rp_id_hash: [u8; 32]) -> Self {
402 Self {
403 pin_uv_auth,
404 rp_id_hash,
405 }
406 }
407
408 pub fn pin_uv_auth(&self) -> Option<&PinUvAuth> {
410 self.pin_uv_auth.as_ref()
411 }
412
413 pub fn rp_id_hash(&self) -> &[u8; 32] {
415 &self.rp_id_hash
416 }
417}
418
419#[derive(Debug, Clone)]
421pub struct DeleteCredentialRequest {
422 pin_uv_auth: Option<PinUvAuth>,
423 credential_id: Vec<u8>,
424}
425
426impl DeleteCredentialRequest {
427 pub fn new(pin_uv_auth: Option<PinUvAuth>, credential_id: Vec<u8>) -> Self {
436 Self {
437 pin_uv_auth,
438 credential_id,
439 }
440 }
441
442 pub fn pin_uv_auth(&self) -> Option<&PinUvAuth> {
444 self.pin_uv_auth.as_ref()
445 }
446
447 pub fn credential_id(&self) -> &[u8] {
449 &self.credential_id
450 }
451}
452
453#[derive(Debug, Clone)]
455pub struct UpdateUserRequest {
456 pin_uv_auth: Option<PinUvAuth>,
457 credential_id: Vec<u8>,
458 user: User,
459}
460
461impl UpdateUserRequest {
462 pub fn new(pin_uv_auth: Option<PinUvAuth>, credential_id: Vec<u8>, user: User) -> Self {
474 Self {
475 pin_uv_auth,
476 credential_id,
477 user,
478 }
479 }
480
481 pub fn pin_uv_auth(&self) -> Option<&PinUvAuth> {
483 self.pin_uv_auth.as_ref()
484 }
485
486 pub fn credential_id(&self) -> &[u8] {
488 &self.credential_id
489 }
490
491 pub fn user(&self) -> &User {
493 &self.user
494 }
495}