libwebauthn/proto/ctap2/model/
bio_enrollment.rs

1use super::Ctap2PinUvAuthProtocol;
2use serde_bytes::ByteBuf;
3use serde_indexed::{DeserializeIndexed, SerializeIndexed};
4use serde_repr::{Deserialize_repr, Serialize_repr};
5use std::time::Duration;
6
7#[derive(Debug, Clone, SerializeIndexed)]
8pub struct Ctap2BioEnrollmentRequest {
9    // modality (0x01) 	Unsigned Integer 	Optional 	The user verification modality being requested
10    #[serde(skip_serializing_if = "Option::is_none")]
11    #[serde(index = 0x01)]
12    pub modality: Option<Ctap2BioEnrollmentModality>,
13
14    // subCommand (0x02) 	Unsigned Integer 	Optional 	The authenticator user verification sub command currently being requested
15    #[serde(skip_serializing_if = "Option::is_none")]
16    #[serde(index = 0x02)]
17    pub subcommand: Option<Ctap2BioEnrollmentSubcommand>,
18
19    // subCommandParams (0x03) 	CBOR Map 	Optional 	Map of subCommands parameters. This parameter MAY be omitted when the subCommand does not take any arguments.
20    #[serde(skip_serializing_if = "Option::is_none")]
21    #[serde(index = 0x03)]
22    pub subcommand_params: Option<Ctap2BioEnrollmentParams>,
23
24    // pinUvAuthProtocol (0x04) 	Unsigned Integer 	Optional 	PIN/UV protocol version chosen by the platform.
25    #[serde(skip_serializing_if = "Option::is_none")]
26    #[serde(index = 0x04)]
27    pub protocol: Option<Ctap2PinUvAuthProtocol>,
28
29    // pinUvAuthParam (0x05) 	Byte String 	Optional 	First 16 bytes of HMAC-SHA-256 of contents using pinUvAuthToken.
30    #[serde(skip_serializing_if = "Option::is_none")]
31    #[serde(index = 0x05)]
32    pub uv_auth_param: Option<ByteBuf>,
33
34    // getModality (0x06) 	Boolean 	Optional 	Get the user verification type modality. This MUST be set to true.
35    #[serde(skip_serializing_if = "Option::is_none")]
36    #[serde(index = 0x06)]
37    pub get_modality: Option<bool>,
38
39    #[serde(skip)]
40    pub use_legacy_preview: bool,
41}
42
43#[repr(u32)]
44#[derive(Debug, Copy, Clone, FromPrimitive, PartialEq, Serialize_repr, Deserialize_repr)]
45pub enum Ctap2BioEnrollmentSubcommand {
46    EnrollBegin = 0x01,
47    EnrollCaptureNextSample = 0x02,
48    CancelCurrentEnrollment = 0x03,
49    EnumerateEnrollments = 0x04,
50    SetFriendlyName = 0x05,
51    RemoveEnrollment = 0x06,
52    GetFingerprintSensorInfo = 0x07,
53}
54
55#[derive(Debug, Clone, SerializeIndexed)]
56pub struct Ctap2BioEnrollmentParams {
57    #[serde(skip_serializing_if = "Option::is_none")]
58    #[serde(index = 0x01)]
59    template_id: Option<ByteBuf>,
60
61    #[serde(skip_serializing_if = "Option::is_none")]
62    #[serde(index = 0x02)]
63    template_friendly_name: Option<String>,
64
65    #[serde(skip_serializing_if = "Option::is_none")]
66    #[serde(index = 0x03)]
67    timeout_milliseconds: Option<u64>,
68}
69
70#[derive(Debug, Default, Clone, DeserializeIndexed)]
71pub struct Ctap2BioEnrollmentResponse {
72    // modality (0x01) 	Unsigned Integer 	Optional 	The user verification modality.
73    #[serde(skip_serializing_if = "Option::is_none")]
74    #[serde(index = 0x01)]
75    pub modality: Option<Ctap2BioEnrollmentModality>,
76
77    // fingerprintKind (0x02) 	Unsigned Integer 	Optional 	Indicates the type of fingerprint sensor. For touch type sensor, its value is 1. For swipe type sensor its value is 2.
78    #[serde(skip_serializing_if = "Option::is_none")]
79    #[serde(index = 0x02)]
80    pub fingerprint_kind: Option<Ctap2BioEnrollmentFingerprintKind>,
81
82    // maxCaptureSamplesRequiredForEnroll (0x03) 	Unsigned Integer 	Optional 	Indicates the maximum good samples required for enrollment.
83    #[serde(skip_serializing_if = "Option::is_none")]
84    #[serde(index = 0x03)]
85    pub max_capture_samples_required_for_enroll: Option<u64>,
86
87    // templateId (0x04) 	Byte String 	Optional 	Template Identifier.
88    #[serde(skip_serializing_if = "Option::is_none")]
89    #[serde(index = 0x04)]
90    pub template_id: Option<ByteBuf>,
91
92    // lastEnrollSampleStatus (0x05) 	Unsigned Integer 	Optional 	Last enrollment sample status.
93    #[serde(skip_serializing_if = "Option::is_none")]
94    #[serde(index = 0x05)]
95    pub last_enroll_sample_status: Option<Ctap2LastEnrollmentSampleStatus>,
96
97    // remainingSamples (0x06) 	Unsigned Integer 	Optional 	Number of more sample required for enrollment to complete
98    #[serde(skip_serializing_if = "Option::is_none")]
99    #[serde(index = 0x06)]
100    pub remaining_samples: Option<u64>,
101
102    // templateInfos (0x07) 	CBOR ARRAY 	Optional 	Array of templateInfo’s
103    #[serde(skip_serializing_if = "Option::is_none")]
104    #[serde(index = 0x07)]
105    pub template_infos: Option<Vec<Ctap2BioEnrollmentTemplateId>>,
106
107    // maxTemplateFriendlyName (0x08) 	Unsigned Integer 	Optional 	Indicates the maximum number of bytes the authenticator will accept as a templateFriendlyName.
108    #[serde(skip_serializing_if = "Option::is_none")]
109    #[serde(index = 0x08)]
110    pub max_template_friendly_name: Option<u64>,
111}
112
113#[derive(Debug, Clone, DeserializeIndexed)]
114pub struct Ctap2BioEnrollmentTemplateId {
115    // templateId (0x01) 	Byte String 	Required 	Template Identifier.
116    #[serde(skip_serializing_if = "Option::is_none")]
117    #[serde(index = 0x01)]
118    pub template_id: Option<ByteBuf>,
119
120    // templateFriendlyName (0x02) 	String 	Optional 	Template Friendly Name.
121    #[serde(skip_serializing_if = "Option::is_none")]
122    #[serde(index = 0x02)]
123    pub template_friendly_name: Option<String>,
124}
125
126#[repr(u64)]
127#[derive(Debug, Clone, Copy, FromPrimitive, PartialEq, Serialize_repr, Deserialize_repr)]
128pub enum Ctap2LastEnrollmentSampleStatus {
129    Ctap2EnrollFeedbackFpGood = 0x00,        // Good fingerprint capture.
130    Ctap2EnrollFeedbackFpTooHigh = 0x01,     // Fingerprint was too high.
131    Ctap2EnrollFeedbackFpTooLow = 0x02,      // Fingerprint was too low.
132    Ctap2EnrollFeedbackFpTooLeft = 0x03,     // Fingerprint was too left.
133    Ctap2EnrollFeedbackFpTooRight = 0x04,    // Fingerprint was too right.
134    Ctap2EnrollFeedbackFpTooFast = 0x05,     // Fingerprint was too fast.
135    Ctap2EnrollFeedbackFpTooSlow = 0x06,     // Fingerprint was too slow.
136    Ctap2EnrollFeedbackFpPoorQuality = 0x07, // Fingerprint was of poor quality.
137    Ctap2EnrollFeedbackFpTooSkewed = 0x08,   // Fingerprint was too skewed.
138    Ctap2EnrollFeedbackFpTooShort = 0x09,    // Fingerprint was too short.
139    Ctap2EnrollFeedbackFpMergeFailure = 0x0A, // Merge failure of the capture.
140    Ctap2EnrollFeedbackFpExists = 0x0B,      // Fingerprint already exists.
141    Unused = 0x0C,                           // (this error number is available)
142    Ctap2EnrollFeedbackNoUserActivity = 0x0D, // User did not touch/swipe the authenticator.
143    Ctap2EnrollFeedbackNoUserPresenceTransition = 0x0E, // User did not lift the finger off the sensor.
144}
145
146#[repr(u64)]
147#[derive(Debug, Clone, FromPrimitive, PartialEq, Serialize_repr, Deserialize_repr)]
148pub enum Ctap2BioEnrollmentModality {
149    Fingerprint = 0x01, // Fingerprint was too high.
150}
151
152#[repr(u64)]
153#[derive(Debug, Clone, FromPrimitive, PartialEq, Serialize_repr, Deserialize_repr)]
154pub enum Ctap2BioEnrollmentFingerprintKind {
155    Touch = 0x01,
156    Swipe = 0x02,
157}
158
159impl Ctap2BioEnrollmentRequest {
160    pub fn new_get_modality() -> Self {
161        Ctap2BioEnrollmentRequest {
162            modality: None,
163            subcommand: None,
164            subcommand_params: None,
165            protocol: None,      // Get's filled in later
166            uv_auth_param: None, // Get's filled in later
167            get_modality: Some(true),
168            use_legacy_preview: false,
169        }
170    }
171
172    pub fn new_fingerprint_sensor_info() -> Self {
173        Ctap2BioEnrollmentRequest {
174            modality: Some(Ctap2BioEnrollmentModality::Fingerprint),
175            subcommand: Some(Ctap2BioEnrollmentSubcommand::GetFingerprintSensorInfo),
176            subcommand_params: None,
177            protocol: None,      // Get's filled in later
178            uv_auth_param: None, // Get's filled in later
179            get_modality: None,
180            use_legacy_preview: false,
181        }
182    }
183
184    pub fn new_enumerate_enrollments() -> Self {
185        Ctap2BioEnrollmentRequest {
186            modality: Some(Ctap2BioEnrollmentModality::Fingerprint),
187            subcommand: Some(Ctap2BioEnrollmentSubcommand::EnumerateEnrollments),
188            subcommand_params: None,
189            protocol: None,      // Get's filled in later
190            uv_auth_param: None, // Get's filled in later
191            get_modality: None,
192            use_legacy_preview: false,
193        }
194    }
195
196    pub fn new_remove_enrollment(template_id: &[u8]) -> Self {
197        Ctap2BioEnrollmentRequest {
198            modality: Some(Ctap2BioEnrollmentModality::Fingerprint),
199            subcommand: Some(Ctap2BioEnrollmentSubcommand::RemoveEnrollment),
200            subcommand_params: Some(Ctap2BioEnrollmentParams {
201                template_id: Some(ByteBuf::from(template_id)),
202                template_friendly_name: None,
203                timeout_milliseconds: None,
204            }),
205            protocol: None,      // Get's filled in later
206            uv_auth_param: None, // Get's filled in later
207            get_modality: None,
208            use_legacy_preview: false,
209        }
210    }
211
212    pub fn new_rename_enrollment(template_id: &[u8], template_friendly_name: &str) -> Self {
213        Ctap2BioEnrollmentRequest {
214            modality: Some(Ctap2BioEnrollmentModality::Fingerprint),
215            subcommand: Some(Ctap2BioEnrollmentSubcommand::SetFriendlyName),
216            subcommand_params: Some(Ctap2BioEnrollmentParams {
217                template_id: Some(ByteBuf::from(template_id)),
218                template_friendly_name: Some(template_friendly_name.to_string()),
219                timeout_milliseconds: None,
220            }),
221            protocol: None,      // Get's filled in later
222            uv_auth_param: None, // Get's filled in later
223            get_modality: None,
224            use_legacy_preview: false,
225        }
226    }
227
228    pub fn new_start_new_enrollment(enrollment_timeout: Option<Duration>) -> Self {
229        let subcommand_params = if let Some(time) = enrollment_timeout {
230            Some(Ctap2BioEnrollmentParams {
231                template_id: None,
232                template_friendly_name: None,
233                timeout_milliseconds: Some(time.as_millis() as u64),
234            })
235        } else {
236            None
237        };
238
239        Ctap2BioEnrollmentRequest {
240            modality: Some(Ctap2BioEnrollmentModality::Fingerprint),
241            subcommand: Some(Ctap2BioEnrollmentSubcommand::EnrollBegin),
242            subcommand_params,
243            protocol: None,      // Get's filled in later
244            uv_auth_param: None, // Get's filled in later
245            get_modality: None,
246            use_legacy_preview: false,
247        }
248    }
249
250    pub fn new_next_enrollment(template_id: &[u8], enrollment_timeout: Option<Duration>) -> Self {
251        let subcommand_params = Some(Ctap2BioEnrollmentParams {
252            template_id: Some(ByteBuf::from(template_id)),
253            template_friendly_name: None,
254            timeout_milliseconds: enrollment_timeout.map(|x| x.as_millis() as u64),
255        });
256
257        Ctap2BioEnrollmentRequest {
258            modality: Some(Ctap2BioEnrollmentModality::Fingerprint),
259            subcommand: Some(Ctap2BioEnrollmentSubcommand::EnrollCaptureNextSample),
260            subcommand_params,
261            protocol: None,
262            uv_auth_param: None,
263            get_modality: None,
264            use_legacy_preview: false,
265        }
266    }
267
268    pub fn new_cancel_current_enrollment() -> Self {
269        Ctap2BioEnrollmentRequest {
270            modality: Some(Ctap2BioEnrollmentModality::Fingerprint),
271            subcommand: Some(Ctap2BioEnrollmentSubcommand::CancelCurrentEnrollment),
272            subcommand_params: None,
273            protocol: None,
274            uv_auth_param: None,
275            get_modality: None,
276            use_legacy_preview: false,
277        }
278    }
279}