Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2018 Yubico AB. All rights reserved. |
3 | | * Use of this source code is governed by a BSD-style |
4 | | * license that can be found in the LICENSE file. |
5 | | */ |
6 | | |
7 | | |
8 | | #include <openssl/sha.h> |
9 | | |
10 | | #include <stdint.h> |
11 | | #include <stdlib.h> |
12 | | #include <string.h> |
13 | | |
14 | | #include "fido.h" |
15 | | |
16 | | #ifndef TLS |
17 | | #define TLS |
18 | | #endif |
19 | | |
20 | | typedef struct dev_manifest_func_node { |
21 | | dev_manifest_func_t manifest_func; |
22 | | struct dev_manifest_func_node *next; |
23 | | } dev_manifest_func_node_t; |
24 | | |
25 | | static TLS dev_manifest_func_node_t *manifest_funcs = NULL; |
26 | | |
27 | | static void |
28 | | find_manifest_func_node(dev_manifest_func_t f, dev_manifest_func_node_t **curr, |
29 | | dev_manifest_func_node_t **prev) |
30 | 0 | { |
31 | 0 | *prev = NULL; |
32 | 0 | *curr = manifest_funcs; |
33 | 0 |
|
34 | 0 | while (*curr != NULL && (*curr)->manifest_func != f) { |
35 | 0 | *prev = *curr; |
36 | 0 | *curr = (*curr)->next; |
37 | 0 | } |
38 | 0 | } |
39 | | |
40 | | #ifdef FIDO_FUZZ |
41 | | static void |
42 | | set_random_report_len(fido_dev_t *dev) |
43 | 27.6k | { |
44 | 27.6k | dev->rx_len = CTAP_MIN_REPORT_LEN + |
45 | 27.6k | uniform_random(CTAP_MAX_REPORT_LEN - CTAP_MIN_REPORT_LEN + 1); |
46 | 27.6k | dev->tx_len = CTAP_MIN_REPORT_LEN + |
47 | 27.6k | uniform_random(CTAP_MAX_REPORT_LEN - CTAP_MIN_REPORT_LEN + 1); |
48 | 27.6k | } |
49 | | #endif |
50 | | |
51 | | static void |
52 | | fido_dev_set_flags(fido_dev_t *dev, const fido_cbor_info_t *info) |
53 | 3.70k | { |
54 | 3.70k | char * const *ptr; |
55 | 3.70k | const bool *val; |
56 | 3.70k | size_t len; |
57 | 3.70k | |
58 | 3.70k | ptr = fido_cbor_info_extensions_ptr(info); |
59 | 3.70k | len = fido_cbor_info_extensions_len(info); |
60 | 3.70k | |
61 | 10.8k | for (size_t i = 0; i < len; i++) |
62 | 7.11k | if (strcmp(ptr[i], "credProtect") == 0) |
63 | 2.01k | dev->flags |= FIDO_DEV_CRED_PROT; |
64 | 3.70k | |
65 | 3.70k | ptr = fido_cbor_info_options_name_ptr(info); |
66 | 3.70k | val = fido_cbor_info_options_value_ptr(info); |
67 | 3.70k | len = fido_cbor_info_options_len(info); |
68 | 3.70k | |
69 | 20.1k | for (size_t i = 0; i < len; i++) |
70 | 16.4k | if (strcmp(ptr[i], "clientPin") == 0) { |
71 | 2.22k | if (val[i] == true) |
72 | 2.22k | dev->flags |= FIDO_DEV_PIN_SET; |
73 | 2.22k | else |
74 | 2.22k | dev->flags |= FIDO_DEV_PIN_UNSET; |
75 | 14.2k | } else if (strcmp(ptr[i], "credMgmt") == 0 || |
76 | 14.2k | strcmp(ptr[i], "credentialMgmtPreview") == 0) { |
77 | 1.74k | if (val[i] == true) |
78 | 1.74k | dev->flags |= FIDO_DEV_CREDMAN; |
79 | 1.74k | } |
80 | 3.70k | } |
81 | | |
82 | | static int |
83 | | fido_dev_open_tx(fido_dev_t *dev, const char *path) |
84 | 27.6k | { |
85 | 27.6k | const uint8_t cmd = CTAP_CMD_INIT; |
86 | 27.6k | int r; |
87 | 27.6k | |
88 | 27.6k | if (dev->io_handle != NULL) { |
89 | 0 | fido_log_debug("%s: handle=%p", __func__, dev->io_handle); |
90 | 0 | return (FIDO_ERR_INVALID_ARGUMENT); |
91 | 0 | } |
92 | 27.6k | |
93 | 27.6k | if (dev->io.open == NULL || dev->io.close == NULL) { |
94 | 0 | fido_log_debug("%s: NULL open/close", __func__); |
95 | 0 | return (FIDO_ERR_INVALID_ARGUMENT); |
96 | 0 | } |
97 | 27.6k | |
98 | 27.6k | if (dev->cid != CTAP_CID_BROADCAST) { |
99 | 0 | fido_log_debug("%s: cid=0x%x", __func__, dev->cid); |
100 | 0 | return (FIDO_ERR_INVALID_ARGUMENT); |
101 | 0 | } |
102 | 27.6k | |
103 | 27.6k | if (fido_get_random(&dev->nonce, sizeof(dev->nonce)) < 0) { |
104 | 0 | fido_log_debug("%s: fido_get_random", __func__); |
105 | 0 | return (FIDO_ERR_INTERNAL); |
106 | 0 | } |
107 | 27.6k | |
108 | 27.6k | if ((dev->io_handle = dev->io.open(path)) == NULL) { |
109 | 0 | fido_log_debug("%s: dev->io.open", __func__); |
110 | 0 | return (FIDO_ERR_INTERNAL); |
111 | 0 | } |
112 | 27.6k | |
113 | 27.6k | if (dev->io_own) { |
114 | 27.6k | dev->rx_len = CTAP_MAX_REPORT_LEN; |
115 | 27.6k | dev->tx_len = CTAP_MAX_REPORT_LEN; |
116 | 27.6k | } else { |
117 | 0 | dev->rx_len = fido_hid_report_in_len(dev->io_handle); |
118 | 0 | dev->tx_len = fido_hid_report_out_len(dev->io_handle); |
119 | 0 | } |
120 | 27.6k | |
121 | 27.6k | #ifdef FIDO_FUZZ |
122 | 27.6k | set_random_report_len(dev); |
123 | 27.6k | #endif |
124 | 27.6k | |
125 | 27.6k | if (dev->rx_len < CTAP_MIN_REPORT_LEN || |
126 | 27.6k | dev->rx_len > CTAP_MAX_REPORT_LEN) { |
127 | 0 | fido_log_debug("%s: invalid rx_len %zu", __func__, dev->rx_len); |
128 | 0 | r = FIDO_ERR_RX; |
129 | 0 | goto fail; |
130 | 0 | } |
131 | 27.6k | |
132 | 27.6k | if (dev->tx_len < CTAP_MIN_REPORT_LEN || |
133 | 27.6k | dev->tx_len > CTAP_MAX_REPORT_LEN) { |
134 | 0 | fido_log_debug("%s: invalid tx_len %zu", __func__, dev->tx_len); |
135 | 0 | r = FIDO_ERR_TX; |
136 | 0 | goto fail; |
137 | 0 | } |
138 | 27.6k | |
139 | 27.6k | if (fido_tx(dev, cmd, &dev->nonce, sizeof(dev->nonce)) < 0) { |
140 | 198 | fido_log_debug("%s: fido_tx", __func__); |
141 | 198 | r = FIDO_ERR_TX; |
142 | 198 | goto fail; |
143 | 198 | } |
144 | 27.4k | |
145 | 27.4k | return (FIDO_OK); |
146 | 198 | fail: |
147 | 198 | dev->io.close(dev->io_handle); |
148 | 198 | dev->io_handle = NULL; |
149 | 198 | |
150 | 198 | return (r); |
151 | 27.4k | } |
152 | | |
153 | | static int |
154 | | fido_dev_open_rx(fido_dev_t *dev, int ms) |
155 | 27.4k | { |
156 | 27.4k | fido_cbor_info_t *info = NULL; |
157 | 27.4k | int reply_len; |
158 | 27.4k | int r; |
159 | 27.4k | |
160 | 27.4k | if ((reply_len = fido_rx(dev, CTAP_CMD_INIT, &dev->attr, |
161 | 27.4k | sizeof(dev->attr), ms)) < 0) { |
162 | 17.0k | fido_log_debug("%s: fido_rx", __func__); |
163 | 17.0k | r = FIDO_ERR_RX; |
164 | 17.0k | goto fail; |
165 | 17.0k | } |
166 | 10.3k | |
167 | 10.3k | #ifdef FIDO_FUZZ |
168 | 10.3k | dev->attr.nonce = dev->nonce; |
169 | 10.3k | #endif |
170 | 10.3k | |
171 | 10.3k | if ((size_t)reply_len != sizeof(dev->attr) || |
172 | 10.3k | dev->attr.nonce != dev->nonce) { |
173 | 131 | fido_log_debug("%s: invalid nonce", __func__); |
174 | 131 | r = FIDO_ERR_RX; |
175 | 131 | goto fail; |
176 | 131 | } |
177 | 10.2k | |
178 | 10.2k | dev->flags = 0; |
179 | 10.2k | dev->cid = dev->attr.cid; |
180 | 10.2k | |
181 | 10.2k | if (fido_dev_is_fido2(dev)) { |
182 | 7.72k | if ((info = fido_cbor_info_new()) == NULL) { |
183 | 38 | fido_log_debug("%s: fido_cbor_info_new", __func__); |
184 | 38 | r = FIDO_ERR_INTERNAL; |
185 | 38 | goto fail; |
186 | 38 | } |
187 | 7.68k | if (fido_dev_get_cbor_info_wait(dev, info, ms) != FIDO_OK) { |
188 | 3.98k | fido_log_debug("%s: falling back to u2f", __func__); |
189 | 3.98k | fido_dev_force_u2f(dev); |
190 | 3.98k | } else { |
191 | 3.70k | fido_dev_set_flags(dev, info); |
192 | 3.70k | } |
193 | 7.68k | } |
194 | 10.2k | |
195 | 10.2k | if (fido_dev_is_fido2(dev) && info != NULL) { |
196 | 3.70k | fido_log_debug("%s: FIDO_MAXMSG=%d, maxmsgsiz=%lu", __func__, |
197 | 3.70k | FIDO_MAXMSG, (unsigned long)fido_cbor_info_maxmsgsiz(info)); |
198 | 3.70k | } |
199 | 10.1k | |
200 | 10.1k | r = FIDO_OK; |
201 | 27.4k | fail: |
202 | 27.4k | fido_cbor_info_free(&info); |
203 | 27.4k | |
204 | 27.4k | if (r != FIDO_OK) { |
205 | 17.2k | dev->io.close(dev->io_handle); |
206 | 17.2k | dev->io_handle = NULL; |
207 | 17.2k | } |
208 | 27.4k | |
209 | 27.4k | return (r); |
210 | 10.1k | } |
211 | | |
212 | | static int |
213 | | fido_dev_open_wait(fido_dev_t *dev, const char *path, int ms) |
214 | 27.6k | { |
215 | 27.6k | int r; |
216 | 27.6k | |
217 | 27.6k | if ((r = fido_dev_open_tx(dev, path)) != FIDO_OK || |
218 | 27.6k | (r = fido_dev_open_rx(dev, ms)) != FIDO_OK) |
219 | 27.6k | return (r); |
220 | 10.1k | |
221 | 10.1k | return (FIDO_OK); |
222 | 10.1k | } |
223 | | |
224 | | int |
225 | | fido_dev_register_manifest_func(const dev_manifest_func_t f) |
226 | 0 | { |
227 | 0 | dev_manifest_func_node_t *prev, *curr, *n; |
228 | 0 |
|
229 | 0 | find_manifest_func_node(f, &curr, &prev); |
230 | 0 | if (curr != NULL) |
231 | 0 | return (FIDO_OK); |
232 | 0 |
|
233 | 0 | if ((n = calloc(1, sizeof(*n))) == NULL) { |
234 | 0 | fido_log_debug("%s: calloc", __func__); |
235 | 0 | return (FIDO_ERR_INTERNAL); |
236 | 0 | } |
237 | 0 |
|
238 | 0 | n->manifest_func = f; |
239 | 0 | n->next = manifest_funcs; |
240 | 0 | manifest_funcs = n; |
241 | 0 |
|
242 | 0 | return (FIDO_OK); |
243 | 0 | } |
244 | | |
245 | | void |
246 | | fido_dev_unregister_manifest_func(const dev_manifest_func_t f) |
247 | 0 | { |
248 | 0 | dev_manifest_func_node_t *prev, *curr; |
249 | 0 |
|
250 | 0 | find_manifest_func_node(f, &curr, &prev); |
251 | 0 | if (curr == NULL) |
252 | 0 | return; |
253 | 0 | if (prev != NULL) |
254 | 0 | prev->next = curr->next; |
255 | 0 | else |
256 | 0 | manifest_funcs = curr->next; |
257 | 0 |
|
258 | 0 | free(curr); |
259 | 0 | } |
260 | | |
261 | | int |
262 | | fido_dev_info_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) |
263 | 0 | { |
264 | 0 | dev_manifest_func_node_t *curr = NULL; |
265 | 0 | dev_manifest_func_t m_func; |
266 | 0 | size_t curr_olen; |
267 | 0 | int r; |
268 | 0 |
|
269 | 0 | *olen = 0; |
270 | 0 |
|
271 | 0 | if (fido_dev_register_manifest_func(fido_hid_manifest) != FIDO_OK) |
272 | 0 | return (FIDO_ERR_INTERNAL); |
273 | 0 |
|
274 | 0 | for (curr = manifest_funcs; curr != NULL; curr = curr->next) { |
275 | 0 | curr_olen = 0; |
276 | 0 | m_func = curr->manifest_func; |
277 | 0 | r = m_func(devlist + *olen, ilen - *olen, &curr_olen); |
278 | 0 | if (r != FIDO_OK) |
279 | 0 | return (r); |
280 | 0 | *olen += curr_olen; |
281 | 0 | if (*olen == ilen) |
282 | 0 | break; |
283 | 0 | } |
284 | 0 |
|
285 | 0 | return (FIDO_OK); |
286 | 0 | } |
287 | | |
288 | | int |
289 | | fido_dev_open_with_info(fido_dev_t *dev) |
290 | 0 | { |
291 | 0 | if (dev->path == NULL) |
292 | 0 | return (FIDO_ERR_INVALID_ARGUMENT); |
293 | 0 |
|
294 | 0 | return (fido_dev_open_wait(dev, dev->path, -1)); |
295 | 0 | } |
296 | | |
297 | | int |
298 | | fido_dev_open(fido_dev_t *dev, const char *path) |
299 | 27.6k | { |
300 | 27.6k | return (fido_dev_open_wait(dev, path, -1)); |
301 | 27.6k | } |
302 | | |
303 | | int |
304 | | fido_dev_close(fido_dev_t *dev) |
305 | 10.1k | { |
306 | 10.1k | if (dev->io_handle == NULL || dev->io.close == NULL) |
307 | 10.1k | return (FIDO_ERR_INVALID_ARGUMENT); |
308 | 10.1k | |
309 | 10.1k | dev->io.close(dev->io_handle); |
310 | 10.1k | dev->io_handle = NULL; |
311 | 10.1k | dev->cid = CTAP_CID_BROADCAST; |
312 | 10.1k | |
313 | 10.1k | return (FIDO_OK); |
314 | 10.1k | } |
315 | | |
316 | | int |
317 | | fido_dev_cancel(fido_dev_t *dev) |
318 | 4.34k | { |
319 | 4.34k | if (fido_dev_is_fido2(dev) == false) |
320 | 4.34k | return (FIDO_ERR_INVALID_ARGUMENT); |
321 | 1.70k | |
322 | 1.70k | if (fido_tx(dev, CTAP_CMD_CANCEL, NULL, 0) < 0) |
323 | 18 | return (FIDO_ERR_TX); |
324 | 1.68k | |
325 | 1.68k | return (FIDO_OK); |
326 | 1.68k | } |
327 | | |
328 | | int |
329 | | fido_dev_get_touch_begin(fido_dev_t *dev) |
330 | 1.44k | { |
331 | 1.44k | fido_blob_t f; |
332 | 1.44k | cbor_item_t *argv[9]; |
333 | 1.44k | const char *clientdata = FIDO_DUMMY_CLIENTDATA; |
334 | 1.44k | const uint8_t user_id = FIDO_DUMMY_USER_ID; |
335 | 1.44k | unsigned char cdh[SHA256_DIGEST_LENGTH]; |
336 | 1.44k | fido_rp_t rp; |
337 | 1.44k | fido_user_t user; |
338 | 1.44k | int r = FIDO_ERR_INTERNAL; |
339 | 1.44k | |
340 | 1.44k | memset(&f, 0, sizeof(f)); |
341 | 1.44k | memset(argv, 0, sizeof(argv)); |
342 | 1.44k | memset(cdh, 0, sizeof(cdh)); |
343 | 1.44k | memset(&rp, 0, sizeof(rp)); |
344 | 1.44k | memset(&user, 0, sizeof(user)); |
345 | 1.44k | |
346 | 1.44k | if (fido_dev_is_fido2(dev) == false) |
347 | 1.44k | return (u2f_get_touch_begin(dev)); |
348 | 127 | |
349 | 127 | if (SHA256((const void *)clientdata, strlen(clientdata), cdh) != cdh) { |
350 | 1 | fido_log_debug("%s: sha256", __func__); |
351 | 1 | return (FIDO_ERR_INTERNAL); |
352 | 1 | } |
353 | 126 | |
354 | 126 | if ((rp.id = strdup(FIDO_DUMMY_RP_ID)) == NULL || |
355 | 126 | (user.name = strdup(FIDO_DUMMY_USER_NAME)) == NULL) { |
356 | 6 | fido_log_debug("%s: strdup", __func__); |
357 | 6 | goto fail; |
358 | 6 | } |
359 | 120 | |
360 | 120 | if (fido_blob_set(&user.id, &user_id, sizeof(user_id)) < 0) { |
361 | 1 | fido_log_debug("%s: fido_blob_set", __func__); |
362 | 1 | goto fail; |
363 | 1 | } |
364 | 119 | |
365 | 119 | if ((argv[0] = cbor_build_bytestring(cdh, sizeof(cdh))) == NULL || |
366 | 119 | (argv[1] = cbor_encode_rp_entity(&rp)) == NULL || |
367 | 119 | (argv[2] = cbor_encode_user_entity(&user)) == NULL || |
368 | 119 | (argv[3] = cbor_encode_pubkey_param(COSE_ES256)) == NULL) { |
369 | 25 | fido_log_debug("%s: cbor encode", __func__); |
370 | 25 | goto fail; |
371 | 25 | } |
372 | 94 | |
373 | 94 | if (fido_dev_supports_pin(dev)) { |
374 | 91 | if ((argv[7] = cbor_new_definite_bytestring()) == NULL || |
375 | 91 | (argv[8] = cbor_encode_pin_opt()) == NULL) { |
376 | 5 | fido_log_debug("%s: cbor encode", __func__); |
377 | 5 | goto fail; |
378 | 5 | } |
379 | 89 | } |
380 | 89 | |
381 | 89 | if (cbor_build_frame(CTAP_CBOR_MAKECRED, argv, nitems(argv), &f) < 0 || |
382 | 89 | fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) { |
383 | 7 | fido_log_debug("%s: fido_tx", __func__); |
384 | 7 | r = FIDO_ERR_TX; |
385 | 7 | goto fail; |
386 | 7 | } |
387 | 82 | |
388 | 82 | r = FIDO_OK; |
389 | 126 | fail: |
390 | 126 | cbor_vector_free(argv, nitems(argv)); |
391 | 126 | free(f.ptr); |
392 | 126 | free(rp.id); |
393 | 126 | free(user.name); |
394 | 126 | free(user.id.ptr); |
395 | 126 | |
396 | 126 | return (r); |
397 | 82 | } |
398 | | |
399 | | int |
400 | | fido_dev_get_touch_status(fido_dev_t *dev, int *touched, int ms) |
401 | 1.44k | { |
402 | 1.44k | int r; |
403 | 1.44k | |
404 | 1.44k | *touched = 0; |
405 | 1.44k | |
406 | 1.44k | if (fido_dev_is_fido2(dev) == false) |
407 | 1.44k | return (u2f_get_touch_status(dev, touched, ms)); |
408 | 127 | |
409 | 127 | switch ((r = fido_rx_cbor_status(dev, ms))) { |
410 | 41 | case FIDO_ERR_PIN_AUTH_INVALID: |
411 | 41 | case FIDO_ERR_PIN_INVALID: |
412 | 41 | case FIDO_ERR_PIN_NOT_SET: |
413 | 41 | case FIDO_ERR_SUCCESS: |
414 | 41 | *touched = 1; |
415 | 41 | break; |
416 | 41 | case FIDO_ERR_RX: |
417 | 34 | /* ignore */ |
418 | 34 | break; |
419 | 52 | default: |
420 | 52 | fido_log_debug("%s: fido_rx_cbor_status", __func__); |
421 | 52 | return (r); |
422 | 75 | } |
423 | 75 | |
424 | 75 | return (FIDO_OK); |
425 | 75 | } |
426 | | |
427 | | int |
428 | | fido_dev_set_io_functions(fido_dev_t *dev, const fido_dev_io_t *io) |
429 | 27.6k | { |
430 | 27.6k | if (dev->io_handle != NULL) { |
431 | 0 | fido_log_debug("%s: non-NULL handle", __func__); |
432 | 0 | return (FIDO_ERR_INVALID_ARGUMENT); |
433 | 0 | } |
434 | 27.6k | |
435 | 27.6k | if (io == NULL || io->open == NULL || io->close == NULL || |
436 | 27.6k | io->read == NULL || io->write == NULL) { |
437 | 0 | fido_log_debug("%s: NULL function", __func__); |
438 | 0 | return (FIDO_ERR_INVALID_ARGUMENT); |
439 | 0 | } |
440 | 27.6k | |
441 | 27.6k | dev->io = *io; |
442 | 27.6k | dev->io_own = true; |
443 | 27.6k | |
444 | 27.6k | return (FIDO_OK); |
445 | 27.6k | } |
446 | | |
447 | | int |
448 | | fido_dev_set_transport_functions(fido_dev_t *dev, const fido_dev_transport_t *t) |
449 | 0 | { |
450 | 0 | if (dev->io_handle != NULL) { |
451 | 0 | fido_log_debug("%s: non-NULL handle", __func__); |
452 | 0 | return (FIDO_ERR_INVALID_ARGUMENT); |
453 | 0 | } |
454 | 0 |
|
455 | 0 | dev->transport = *t; |
456 | 0 | dev->io_own = true; |
457 | 0 |
|
458 | 0 | return (FIDO_OK); |
459 | 0 | } |
460 | | |
461 | | void |
462 | | fido_init(int flags) |
463 | 8.34k | { |
464 | 8.34k | if (flags & FIDO_DEBUG || getenv("FIDO_DEBUG") != NULL) |
465 | 8.34k | fido_log_init(); |
466 | 8.34k | } |
467 | | |
468 | | fido_dev_t * |
469 | | fido_dev_new(void) |
470 | 27.7k | { |
471 | 27.7k | fido_dev_t *dev; |
472 | 27.7k | |
473 | 27.7k | if ((dev = calloc(1, sizeof(*dev))) == NULL) |
474 | 27.7k | return (NULL); |
475 | 27.6k | |
476 | 27.6k | dev->cid = CTAP_CID_BROADCAST; |
477 | 27.6k | dev->io = (fido_dev_io_t) { |
478 | 27.6k | &fido_hid_open, |
479 | 27.6k | &fido_hid_close, |
480 | 27.6k | &fido_hid_read, |
481 | 27.6k | &fido_hid_write, |
482 | 27.6k | }; |
483 | 27.6k | |
484 | 27.6k | return (dev); |
485 | 27.6k | } |
486 | | |
487 | | fido_dev_t * |
488 | | fido_dev_new_with_info(const fido_dev_info_t *di) |
489 | 0 | { |
490 | 0 | fido_dev_t *dev; |
491 | 0 |
|
492 | 0 | if ((dev = calloc(1, sizeof(*dev))) == NULL) |
493 | 0 | return (NULL); |
494 | 0 | |
495 | 0 | if (di->io.open == NULL || di->io.close == NULL || |
496 | 0 | di->io.read == NULL || di->io.write == NULL) { |
497 | 0 | fido_log_debug("%s: NULL function", __func__); |
498 | 0 | fido_dev_free(&dev); |
499 | 0 | return (NULL); |
500 | 0 | } |
501 | 0 | |
502 | 0 | dev->io = di->io; |
503 | 0 | dev->io_own = di->transport.tx != NULL || di->transport.rx != NULL; |
504 | 0 | dev->transport = di->transport; |
505 | 0 | dev->cid = CTAP_CID_BROADCAST; |
506 | 0 |
|
507 | 0 | if ((dev->path = strdup(di->path)) == NULL) { |
508 | 0 | fido_log_debug("%s: strdup", __func__); |
509 | 0 | fido_dev_free(&dev); |
510 | 0 | return (NULL); |
511 | 0 | } |
512 | 0 | |
513 | 0 | return (dev); |
514 | 0 | } |
515 | | |
516 | | void |
517 | | fido_dev_free(fido_dev_t **dev_p) |
518 | 34.1k | { |
519 | 34.1k | fido_dev_t *dev; |
520 | 34.1k | |
521 | 34.1k | if (dev_p == NULL || (dev = *dev_p) == NULL) |
522 | 34.1k | return; |
523 | 27.6k | |
524 | 27.6k | free(dev->path); |
525 | 27.6k | free(dev); |
526 | 27.6k | |
527 | 27.6k | *dev_p = NULL; |
528 | 27.6k | } |
529 | | |
530 | | uint8_t |
531 | | fido_dev_protocol(const fido_dev_t *dev) |
532 | 267 | { |
533 | 267 | return (dev->attr.protocol); |
534 | 267 | } |
535 | | |
536 | | uint8_t |
537 | | fido_dev_major(const fido_dev_t *dev) |
538 | 267 | { |
539 | 267 | return (dev->attr.major); |
540 | 267 | } |
541 | | |
542 | | uint8_t |
543 | | fido_dev_minor(const fido_dev_t *dev) |
544 | 267 | { |
545 | 267 | return (dev->attr.minor); |
546 | 267 | } |
547 | | |
548 | | uint8_t |
549 | | fido_dev_build(const fido_dev_t *dev) |
550 | 267 | { |
551 | 267 | return (dev->attr.build); |
552 | 267 | } |
553 | | |
554 | | uint8_t |
555 | | fido_dev_flags(const fido_dev_t *dev) |
556 | 267 | { |
557 | 267 | return (dev->attr.flags); |
558 | 267 | } |
559 | | |
560 | | bool |
561 | | fido_dev_is_fido2(const fido_dev_t *dev) |
562 | 37.0k | { |
563 | 37.0k | return (dev->attr.flags & FIDO_CAP_CBOR); |
564 | 37.0k | } |
565 | | |
566 | | bool |
567 | | fido_dev_supports_pin(const fido_dev_t *dev) |
568 | 2.31k | { |
569 | 2.31k | return (dev->flags & (FIDO_DEV_PIN_SET|FIDO_DEV_PIN_UNSET)); |
570 | 2.31k | } |
571 | | |
572 | | bool |
573 | | fido_dev_has_pin(const fido_dev_t *dev) |
574 | 2.22k | { |
575 | 2.22k | return (dev->flags & FIDO_DEV_PIN_SET); |
576 | 2.22k | } |
577 | | |
578 | | bool |
579 | | fido_dev_supports_cred_prot(const fido_dev_t *dev) |
580 | 2.15k | { |
581 | 2.15k | return (dev->flags & FIDO_DEV_CRED_PROT); |
582 | 2.15k | } |
583 | | |
584 | | bool |
585 | | fido_dev_supports_credman(const fido_dev_t *dev) |
586 | 2.15k | { |
587 | 2.15k | return (dev->flags & FIDO_DEV_CREDMAN); |
588 | 2.15k | } |
589 | | |
590 | | void |
591 | | fido_dev_force_u2f(fido_dev_t *dev) |
592 | 4.98k | { |
593 | 4.98k | dev->attr.flags &= (uint8_t)~FIDO_CAP_CBOR; |
594 | 4.98k | dev->flags = 0; |
595 | 4.98k | } |
596 | | |
597 | | void |
598 | | fido_dev_force_fido2(fido_dev_t *dev) |
599 | 0 | { |
600 | 0 | dev->attr.flags |= FIDO_CAP_CBOR; |
601 | 0 | } |