Coverage Report

Created: 2022-01-17 10:46

/libfido2/src/dev.c
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
#include <openssl/sha.h>
8
#include "fido.h"
9
10
#ifndef TLS
11
#define TLS
12
#endif
13
14
typedef struct dev_manifest_func_node {
15
        dev_manifest_func_t manifest_func;
16
        struct dev_manifest_func_node *next;
17
} dev_manifest_func_node_t;
18
19
static TLS dev_manifest_func_node_t *manifest_funcs = NULL;
20
static TLS bool disable_u2f_fallback;
21
22
static void
23
find_manifest_func_node(dev_manifest_func_t f, dev_manifest_func_node_t **curr,
24
    dev_manifest_func_node_t **prev)
25
2.41k
{
26
2.41k
        *prev = NULL;
27
2.41k
        *curr = manifest_funcs;
28
29
3.62k
        while (*curr != NULL && (*curr)->manifest_func != f) {
30
1.20k
                *prev = *curr;
31
1.20k
                *curr = (*curr)->next;
32
1.20k
        }
33
2.41k
}
34
35
#ifdef FIDO_FUZZ
36
static void
37
set_random_report_len(fido_dev_t *dev)
38
72.2k
{
39
72.2k
        dev->rx_len = CTAP_MIN_REPORT_LEN +
40
72.2k
            uniform_random(CTAP_MAX_REPORT_LEN - CTAP_MIN_REPORT_LEN + 1);
41
72.2k
        dev->tx_len = CTAP_MIN_REPORT_LEN +
42
72.2k
            uniform_random(CTAP_MAX_REPORT_LEN - CTAP_MIN_REPORT_LEN + 1);
43
72.2k
}
44
#endif
45
46
static void
47
fido_dev_set_extension_flags(fido_dev_t *dev, const fido_cbor_info_t *info)
48
8.97k
{
49
8.97k
        char * const    *ptr = fido_cbor_info_extensions_ptr(info);
50
8.97k
        size_t           len = fido_cbor_info_extensions_len(info);
51
52
26.5k
        for (size_t i = 0; i < len; i++)
53
17.5k
                if (strcmp(ptr[i], "credProtect") == 0)
54
3.91k
                        dev->flags |= FIDO_DEV_CRED_PROT;
55
8.97k
}
56
57
static void
58
fido_dev_set_option_flags(fido_dev_t *dev, const fido_cbor_info_t *info)
59
8.97k
{
60
8.97k
        char * const    *ptr = fido_cbor_info_options_name_ptr(info);
61
8.97k
        const bool      *val = fido_cbor_info_options_value_ptr(info);
62
8.97k
        size_t           len = fido_cbor_info_options_len(info);
63
64
51.9k
        for (size_t i = 0; i < len; i++)
65
43.0k
                if (strcmp(ptr[i], "clientPin") == 0) {
66
3.80k
                        dev->flags |= val[i] ? FIDO_DEV_PIN_SET : FIDO_DEV_PIN_UNSET;
67
39.2k
                } else if (strcmp(ptr[i], "credMgmt") == 0 ||
68
39.2k
                           strcmp(ptr[i], "credentialMgmtPreview") == 0) {
69
3.21k
                        if (val[i])
70
3.18k
                                dev->flags |= FIDO_DEV_CREDMAN;
71
36.0k
                } else if (strcmp(ptr[i], "uv") == 0) {
72
590
                        dev->flags |= val[i] ? FIDO_DEV_UV_SET : FIDO_DEV_UV_UNSET;
73
35.4k
                } else if (strcmp(ptr[i], "pinUvAuthToken") == 0) {
74
410
                        if (val[i])
75
396
                                dev->flags |= FIDO_DEV_TOKEN_PERMS;
76
410
                }
77
8.97k
}
78
79
static void
80
fido_dev_set_protocol_flags(fido_dev_t *dev, const fido_cbor_info_t *info)
81
8.97k
{
82
8.97k
        const uint8_t   *ptr = fido_cbor_info_protocols_ptr(info);
83
8.97k
        size_t           len = fido_cbor_info_protocols_len(info);
84
85
19.5k
        for (size_t i = 0; i < len; i++)
86
10.6k
                switch (ptr[i]) {
87
7.85k
                case CTAP_PIN_PROTOCOL1:
88
7.85k
                        dev->flags |= FIDO_DEV_PIN_PROTOCOL1;
89
7.85k
                        break;
90
1.19k
                case CTAP_PIN_PROTOCOL2:
91
1.19k
                        dev->flags |= FIDO_DEV_PIN_PROTOCOL2;
92
1.19k
                        break;
93
1.57k
                default:
94
1.57k
                        fido_log_debug("%s: unknown protocol %u", __func__,
95
1.57k
                            ptr[i]);
96
1.57k
                        break;
97
10.6k
                }
98
8.97k
}
99
100
static void
101
fido_dev_set_flags(fido_dev_t *dev, const fido_cbor_info_t *info)
102
8.97k
{
103
8.97k
        fido_dev_set_extension_flags(dev, info);
104
8.97k
        fido_dev_set_option_flags(dev, info);
105
8.97k
        fido_dev_set_protocol_flags(dev, info);
106
8.97k
}
107
108
static int
109
fido_dev_open_tx(fido_dev_t *dev, const char *path, int *ms)
110
72.2k
{
111
72.2k
        int r;
112
113
72.2k
        if (dev->io_handle != NULL) {
114
0
                fido_log_debug("%s: handle=%p", __func__, dev->io_handle);
115
0
                return (FIDO_ERR_INVALID_ARGUMENT);
116
0
        }
117
118
72.2k
        if (dev->io.open == NULL || dev->io.close == NULL) {
119
0
                fido_log_debug("%s: NULL open/close", __func__);
120
0
                return (FIDO_ERR_INVALID_ARGUMENT);
121
0
        }
122
123
72.2k
        if (dev->cid != CTAP_CID_BROADCAST) {
124
0
                fido_log_debug("%s: cid=0x%x", __func__, dev->cid);
125
0
                return (FIDO_ERR_INVALID_ARGUMENT);
126
0
        }
127
128
72.2k
        if (fido_get_random(&dev->nonce, sizeof(dev->nonce)) < 0) {
129
0
                fido_log_debug("%s: fido_get_random", __func__);
130
0
                return (FIDO_ERR_INTERNAL);
131
0
        }
132
133
72.2k
        if ((dev->io_handle = dev->io.open(path)) == NULL) {
134
0
                fido_log_debug("%s: dev->io.open", __func__);
135
0
                return (FIDO_ERR_INTERNAL);
136
0
        }
137
138
72.2k
        if (dev->io_own) {
139
72.2k
                dev->rx_len = CTAP_MAX_REPORT_LEN;
140
72.2k
                dev->tx_len = CTAP_MAX_REPORT_LEN;
141
72.2k
        } else {
142
0
                dev->rx_len = fido_hid_report_in_len(dev->io_handle);
143
0
                dev->tx_len = fido_hid_report_out_len(dev->io_handle);
144
0
        }
145
146
72.2k
#ifdef FIDO_FUZZ
147
72.2k
        set_random_report_len(dev);
148
72.2k
#endif
149
150
72.2k
        if (dev->rx_len < CTAP_MIN_REPORT_LEN ||
151
72.2k
            dev->rx_len > CTAP_MAX_REPORT_LEN) {
152
0
                fido_log_debug("%s: invalid rx_len %zu", __func__, dev->rx_len);
153
0
                r = FIDO_ERR_RX;
154
0
                goto fail;
155
0
        }
156
157
72.2k
        if (dev->tx_len < CTAP_MIN_REPORT_LEN ||
158
72.2k
            dev->tx_len > CTAP_MAX_REPORT_LEN) {
159
0
                fido_log_debug("%s: invalid tx_len %zu", __func__, dev->tx_len);
160
0
                r = FIDO_ERR_TX;
161
0
                goto fail;
162
0
        }
163
164
72.2k
        if (fido_tx(dev, CTAP_CMD_INIT, &dev->nonce, sizeof(dev->nonce),
165
72.2k
            ms) < 0) {
166
1.52k
                fido_log_debug("%s: fido_tx", __func__);
167
1.52k
                r = FIDO_ERR_TX;
168
1.52k
                goto fail;
169
1.52k
        }
170
171
70.6k
        return (FIDO_OK);
172
1.52k
fail:
173
1.52k
        dev->io.close(dev->io_handle);
174
1.52k
        dev->io_handle = NULL;
175
176
1.52k
        return (r);
177
70.6k
}
178
179
static int
180
fido_dev_open_rx(fido_dev_t *dev, int *ms)
181
70.6k
{
182
70.6k
        fido_cbor_info_t        *info = NULL;
183
70.6k
        int                      reply_len;
184
70.6k
        int                      r;
185
186
70.6k
        if ((reply_len = fido_rx(dev, CTAP_CMD_INIT, &dev->attr,
187
70.6k
            sizeof(dev->attr), ms)) < 0) {
188
43.0k
                fido_log_debug("%s: fido_rx", __func__);
189
43.0k
                r = FIDO_ERR_RX;
190
43.0k
                goto fail;
191
43.0k
        }
192
193
27.6k
#ifdef FIDO_FUZZ
194
27.6k
        dev->attr.nonce = dev->nonce;
195
27.6k
#endif
196
197
27.6k
        if ((size_t)reply_len != sizeof(dev->attr) ||
198
27.6k
            dev->attr.nonce != dev->nonce) {
199
452
                fido_log_debug("%s: invalid nonce", __func__);
200
452
                r = FIDO_ERR_RX;
201
452
                goto fail;
202
452
        }
203
204
27.2k
        dev->flags = 0;
205
27.2k
        dev->cid = dev->attr.cid;
206
207
27.2k
        if (fido_dev_is_fido2(dev)) {
208
22.1k
                if ((info = fido_cbor_info_new()) == NULL) {
209
70
                        fido_log_debug("%s: fido_cbor_info_new", __func__);
210
70
                        r = FIDO_ERR_INTERNAL;
211
70
                        goto fail;
212
70
                }
213
22.0k
                if ((r = fido_dev_get_cbor_info_wait(dev, info,
214
22.0k
                    ms)) != FIDO_OK) {
215
13.1k
                        fido_log_debug("%s: fido_dev_cbor_info_wait: %d",
216
13.1k
                            __func__, r);
217
13.1k
                        if (disable_u2f_fallback)
218
0
                                goto fail;
219
13.1k
                        fido_log_debug("%s: falling back to u2f", __func__);
220
13.1k
                        fido_dev_force_u2f(dev);
221
13.1k
                } else {
222
8.97k
                        fido_dev_set_flags(dev, info);
223
8.97k
                }
224
22.0k
        }
225
226
27.2k
        if (fido_dev_is_fido2(dev) && info != NULL) {
227
8.97k
                dev->maxmsgsize = fido_cbor_info_maxmsgsiz(info);
228
8.97k
                fido_log_debug("%s: FIDO_MAXMSG=%d, maxmsgsiz=%lu", __func__,
229
8.97k
                    FIDO_MAXMSG, (unsigned long)dev->maxmsgsize);
230
8.97k
        }
231
232
27.1k
        r = FIDO_OK;
233
70.6k
fail:
234
70.6k
        fido_cbor_info_free(&info);
235
236
70.6k
        if (r != FIDO_OK) {
237
43.5k
                dev->io.close(dev->io_handle);
238
43.5k
                dev->io_handle = NULL;
239
43.5k
        }
240
241
70.6k
        return (r);
242
27.1k
}
243
244
static int
245
fido_dev_open_wait(fido_dev_t *dev, const char *path, int *ms)
246
72.2k
{
247
72.2k
        int r;
248
249
#ifdef USE_WINHELLO
250
        if (strcmp(path, FIDO_WINHELLO_PATH) == 0)
251
                return (fido_winhello_open(dev));
252
#endif
253
72.2k
        if ((r = fido_dev_open_tx(dev, path, ms)) != FIDO_OK ||
254
72.2k
            (r = fido_dev_open_rx(dev, ms)) != FIDO_OK)
255
72.2k
                return (r);
256
257
27.1k
        return (FIDO_OK);
258
27.1k
}
259
260
int
261
fido_dev_register_manifest_func(const dev_manifest_func_t f)
262
2.41k
{
263
2.41k
        dev_manifest_func_node_t *prev, *curr, *n;
264
265
2.41k
        find_manifest_func_node(f, &curr, &prev);
266
2.41k
        if (curr != NULL)
267
2.41k
                return (FIDO_OK);
268
269
2
        if ((n = calloc(1, sizeof(*n))) == NULL) {
270
0
                fido_log_debug("%s: calloc", __func__);
271
0
                return (FIDO_ERR_INTERNAL);
272
0
        }
273
274
2
        n->manifest_func = f;
275
2
        n->next = manifest_funcs;
276
2
        manifest_funcs = n;
277
278
2
        return (FIDO_OK);
279
2
}
280
281
void
282
fido_dev_unregister_manifest_func(const dev_manifest_func_t f)
283
0
{
284
0
        dev_manifest_func_node_t *prev, *curr;
285
286
0
        find_manifest_func_node(f, &curr, &prev);
287
0
        if (curr == NULL)
288
0
                return;
289
0
        if (prev != NULL)
290
0
                prev->next = curr->next;
291
0
        else
292
0
                manifest_funcs = curr->next;
293
294
0
        free(curr);
295
0
}
296
297
int
298
fido_dev_info_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
299
1.20k
{
300
1.20k
        dev_manifest_func_node_t        *curr = NULL;
301
1.20k
        dev_manifest_func_t              m_func;
302
1.20k
        size_t                           curr_olen;
303
1.20k
        int                              r;
304
305
1.20k
        *olen = 0;
306
307
1.20k
        if (fido_dev_register_manifest_func(fido_hid_manifest) != FIDO_OK)
308
1.20k
                return (FIDO_ERR_INTERNAL);
309
1.20k
#ifdef NFC_LINUX
310
1.20k
        if (fido_dev_register_manifest_func(fido_nfc_manifest) != FIDO_OK)
311
1.20k
                return (FIDO_ERR_INTERNAL);
312
1.20k
#endif
313
#ifdef USE_WINHELLO
314
        if (fido_dev_register_manifest_func(fido_winhello_manifest) != FIDO_OK)
315
                return (FIDO_ERR_INTERNAL);
316
#endif
317
318
3.54k
        for (curr = manifest_funcs; curr != NULL; curr = curr->next) {
319
2.40k
                curr_olen = 0;
320
2.40k
                m_func = curr->manifest_func;
321
2.40k
                r = m_func(devlist + *olen, ilen - *olen, &curr_olen);
322
2.40k
                if (r != FIDO_OK)
323
2.40k
                        return (r);
324
2.37k
                *olen += curr_olen;
325
2.37k
                if (*olen == ilen)
326
37
                        break;
327
2.37k
        }
328
329
1.20k
        return (FIDO_OK);
330
1.20k
}
331
332
int
333
fido_dev_open_with_info(fido_dev_t *dev)
334
0
{
335
0
        int ms = dev->timeout_ms;
336
337
0
        if (dev->path == NULL)
338
0
                return (FIDO_ERR_INVALID_ARGUMENT);
339
340
0
        return (fido_dev_open_wait(dev, dev->path, &ms));
341
0
}
342
343
int
344
fido_dev_open(fido_dev_t *dev, const char *path)
345
72.2k
{
346
72.2k
        int ms = dev->timeout_ms;
347
348
72.2k
#ifdef NFC_LINUX
349
72.2k
        if (strncmp(path, FIDO_NFC_PREFIX, strlen(FIDO_NFC_PREFIX)) == 0) {
350
0
                dev->io_own = true;
351
0
                dev->io = (fido_dev_io_t) {
352
0
                        fido_nfc_open,
353
0
                        fido_nfc_close,
354
0
                        fido_nfc_read,
355
0
                        fido_nfc_write,
356
0
                };
357
0
                dev->transport = (fido_dev_transport_t) {
358
0
                        fido_nfc_rx,
359
0
                        fido_nfc_tx,
360
0
                };
361
0
        }
362
72.2k
#endif
363
364
72.2k
        return (fido_dev_open_wait(dev, path, &ms));
365
72.2k
}
366
367
int
368
fido_dev_close(fido_dev_t *dev)
369
27.1k
{
370
#ifdef USE_WINHELLO
371
        if (dev->flags & FIDO_DEV_WINHELLO)
372
                return (fido_winhello_close(dev));
373
#endif
374
27.1k
        if (dev->io_handle == NULL || dev->io.close == NULL)
375
27.1k
                return (FIDO_ERR_INVALID_ARGUMENT);
376
377
27.1k
        dev->io.close(dev->io_handle);
378
27.1k
        dev->io_handle = NULL;
379
27.1k
        dev->cid = CTAP_CID_BROADCAST;
380
381
27.1k
        return (FIDO_OK);
382
27.1k
}
383
384
int
385
fido_dev_set_sigmask(fido_dev_t *dev, const fido_sigset_t *sigmask)
386
0
{
387
0
        if (dev->io_handle == NULL || sigmask == NULL)
388
0
                return (FIDO_ERR_INVALID_ARGUMENT);
389
390
0
#ifdef NFC_LINUX
391
0
        if (dev->transport.rx == fido_nfc_rx && dev->io.read == fido_nfc_read)
392
0
                return (fido_nfc_set_sigmask(dev->io_handle, sigmask));
393
0
#endif
394
0
        if (dev->transport.rx == NULL && dev->io.read == fido_hid_read)
395
0
                return (fido_hid_set_sigmask(dev->io_handle, sigmask));
396
397
0
        return (FIDO_ERR_INVALID_ARGUMENT);
398
0
}
399
400
int
401
fido_dev_cancel(fido_dev_t *dev)
402
6.85k
{
403
6.85k
        int ms = dev->timeout_ms;
404
405
#ifdef USE_WINHELLO
406
        if (dev->flags & FIDO_DEV_WINHELLO)
407
                return (fido_winhello_cancel(dev));
408
#endif
409
6.85k
        if (fido_dev_is_fido2(dev) == false)
410
6.85k
                return (FIDO_ERR_INVALID_ARGUMENT);
411
2.60k
        if (fido_tx(dev, CTAP_CMD_CANCEL, NULL, 0, &ms) < 0)
412
100
                return (FIDO_ERR_TX);
413
414
2.50k
        return (FIDO_OK);
415
2.50k
}
416
417
int
418
fido_dev_get_touch_begin(fido_dev_t *dev)
419
2.37k
{
420
2.37k
        fido_blob_t      f;
421
2.37k
        cbor_item_t     *argv[9];
422
2.37k
        const char      *clientdata = FIDO_DUMMY_CLIENTDATA;
423
2.37k
        const uint8_t    user_id = FIDO_DUMMY_USER_ID;
424
2.37k
        unsigned char    cdh[SHA256_DIGEST_LENGTH];
425
2.37k
        fido_rp_t        rp;
426
2.37k
        fido_user_t      user;
427
2.37k
        int              ms = dev->timeout_ms;
428
2.37k
        int              r = FIDO_ERR_INTERNAL;
429
430
2.37k
        memset(&f, 0, sizeof(f));
431
2.37k
        memset(argv, 0, sizeof(argv));
432
2.37k
        memset(cdh, 0, sizeof(cdh));
433
2.37k
        memset(&rp, 0, sizeof(rp));
434
2.37k
        memset(&user, 0, sizeof(user));
435
436
2.37k
        if (fido_dev_is_fido2(dev) == false)
437
2.37k
                return (u2f_get_touch_begin(dev, &ms));
438
439
203
        if (SHA256((const void *)clientdata, strlen(clientdata), cdh) != cdh) {
440
1
                fido_log_debug("%s: sha256", __func__);
441
1
                return (FIDO_ERR_INTERNAL);
442
1
        }
443
444
202
        if ((rp.id = strdup(FIDO_DUMMY_RP_ID)) == NULL ||
445
202
            (user.name = strdup(FIDO_DUMMY_USER_NAME)) == NULL) {
446
5
                fido_log_debug("%s: strdup", __func__);
447
5
                goto fail;
448
5
        }
449
450
197
        if (fido_blob_set(&user.id, &user_id, sizeof(user_id)) < 0) {
451
2
                fido_log_debug("%s: fido_blob_set", __func__);
452
2
                goto fail;
453
2
        }
454
455
195
        if ((argv[0] = cbor_build_bytestring(cdh, sizeof(cdh))) == NULL ||
456
195
            (argv[1] = cbor_encode_rp_entity(&rp)) == NULL ||
457
195
            (argv[2] = cbor_encode_user_entity(&user)) == NULL ||
458
195
            (argv[3] = cbor_encode_pubkey_param(COSE_ES256)) == NULL) {
459
42
                fido_log_debug("%s: cbor encode", __func__);
460
42
                goto fail;
461
42
        }
462
463
153
        if (fido_dev_supports_pin(dev)) {
464
136
                if ((argv[7] = cbor_new_definite_bytestring()) == NULL ||
465
136
                    (argv[8] = cbor_encode_pin_opt(dev)) == NULL) {
466
5
                        fido_log_debug("%s: cbor encode", __func__);
467
5
                        goto fail;
468
5
                }
469
148
        }
470
471
148
        if (cbor_build_frame(CTAP_CBOR_MAKECRED, argv, nitems(argv), &f) < 0 ||
472
148
            fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, &ms) < 0) {
473
21
                fido_log_debug("%s: fido_tx", __func__);
474
21
                r = FIDO_ERR_TX;
475
21
                goto fail;
476
21
        }
477
478
127
        r = FIDO_OK;
479
202
fail:
480
202
        cbor_vector_free(argv, nitems(argv));
481
202
        free(f.ptr);
482
202
        free(rp.id);
483
202
        free(user.name);
484
202
        free(user.id.ptr);
485
486
202
        return (r);
487
127
}
488
489
int
490
fido_dev_get_touch_status(fido_dev_t *dev, int *touched, int ms)
491
2.37k
{
492
2.37k
        int r;
493
494
2.37k
        *touched = 0;
495
496
2.37k
        if (fido_dev_is_fido2(dev) == false)
497
2.37k
                return (u2f_get_touch_status(dev, touched, &ms));
498
499
203
        switch ((r = fido_rx_cbor_status(dev, &ms))) {
500
1
        case FIDO_ERR_PIN_AUTH_INVALID:
501
2
        case FIDO_ERR_PIN_INVALID:
502
3
        case FIDO_ERR_PIN_NOT_SET:
503
76
        case FIDO_ERR_SUCCESS:
504
76
                *touched = 1;
505
76
                break;
506
74
        case FIDO_ERR_RX:
507
                /* ignore */
508
74
                break;
509
53
        default:
510
53
                fido_log_debug("%s: fido_rx_cbor_status", __func__);
511
53
                return (r);
512
150
        }
513
514
150
        return (FIDO_OK);
515
150
}
516
517
int
518
fido_dev_set_io_functions(fido_dev_t *dev, const fido_dev_io_t *io)
519
72.2k
{
520
72.2k
        if (dev->io_handle != NULL) {
521
0
                fido_log_debug("%s: non-NULL handle", __func__);
522
0
                return (FIDO_ERR_INVALID_ARGUMENT);
523
0
        }
524
525
72.2k
        if (io == NULL || io->open == NULL || io->close == NULL ||
526
72.2k
            io->read == NULL || io->write == NULL) {
527
0
                fido_log_debug("%s: NULL function", __func__);
528
0
                return (FIDO_ERR_INVALID_ARGUMENT);
529
0
        }
530
531
72.2k
        dev->io = *io;
532
72.2k
        dev->io_own = true;
533
534
72.2k
        return (FIDO_OK);
535
72.2k
}
536
537
int
538
fido_dev_set_transport_functions(fido_dev_t *dev, const fido_dev_transport_t *t)
539
752
{
540
752
        if (dev->io_handle != NULL) {
541
0
                fido_log_debug("%s: non-NULL handle", __func__);
542
0
                return (FIDO_ERR_INVALID_ARGUMENT);
543
0
        }
544
545
752
        dev->transport = *t;
546
752
        dev->io_own = true;
547
548
752
        return (FIDO_OK);
549
752
}
550
551
void *
552
fido_dev_io_handle(const fido_dev_t *dev)
553
0
{
554
555
0
        return (dev->io_handle);
556
0
}
557
558
void
559
fido_init(int flags)
560
17.4k
{
561
17.4k
        if (flags & FIDO_DEBUG || getenv("FIDO_DEBUG") != NULL)
562
17.4k
                fido_log_init();
563
564
17.4k
        disable_u2f_fallback = (flags & FIDO_DISABLE_U2F_FALLBACK);
565
17.4k
}
566
567
fido_dev_t *
568
fido_dev_new(void)
569
72.4k
{
570
72.4k
        fido_dev_t *dev;
571
572
72.4k
        if ((dev = calloc(1, sizeof(*dev))) == NULL)
573
72.4k
                return (NULL);
574
575
72.2k
        dev->cid = CTAP_CID_BROADCAST;
576
72.2k
        dev->timeout_ms = -1;
577
72.2k
        dev->io = (fido_dev_io_t) {
578
72.2k
                &fido_hid_open,
579
72.2k
                &fido_hid_close,
580
72.2k
                &fido_hid_read,
581
72.2k
                &fido_hid_write,
582
72.2k
        };
583
584
72.2k
        return (dev);
585
72.2k
}
586
587
fido_dev_t *
588
fido_dev_new_with_info(const fido_dev_info_t *di)
589
0
{
590
0
        fido_dev_t *dev;
591
592
0
        if ((dev = calloc(1, sizeof(*dev))) == NULL)
593
0
                return (NULL);
594
595
#if 0
596
        if (di->io.open == NULL || di->io.close == NULL ||
597
            di->io.read == NULL || di->io.write == NULL) {
598
                fido_log_debug("%s: NULL function", __func__);
599
                fido_dev_free(&dev);
600
                return (NULL);
601
        }
602
#endif
603
604
0
        dev->io = di->io;
605
0
        dev->io_own = di->transport.tx != NULL || di->transport.rx != NULL;
606
0
        dev->transport = di->transport;
607
0
        dev->cid = CTAP_CID_BROADCAST;
608
0
        dev->timeout_ms = -1;
609
610
0
        if ((dev->path = strdup(di->path)) == NULL) {
611
0
                fido_log_debug("%s: strdup", __func__);
612
0
                fido_dev_free(&dev);
613
0
                return (NULL);
614
0
        }
615
616
0
        return (dev);
617
0
}
618
619
void
620
fido_dev_free(fido_dev_t **dev_p)
621
81.5k
{
622
81.5k
        fido_dev_t *dev;
623
624
81.5k
        if (dev_p == NULL || (dev = *dev_p) == NULL)
625
81.5k
                return;
626
627
72.2k
        free(dev->path);
628
72.2k
        free(dev);
629
630
72.2k
        *dev_p = NULL;
631
72.2k
}
632
633
uint8_t
634
fido_dev_protocol(const fido_dev_t *dev)
635
305
{
636
305
        return (dev->attr.protocol);
637
305
}
638
639
uint8_t
640
fido_dev_major(const fido_dev_t *dev)
641
305
{
642
305
        return (dev->attr.major);
643
305
}
644
645
uint8_t
646
fido_dev_minor(const fido_dev_t *dev)
647
305
{
648
305
        return (dev->attr.minor);
649
305
}
650
651
uint8_t
652
fido_dev_build(const fido_dev_t *dev)
653
305
{
654
305
        return (dev->attr.build);
655
305
}
656
657
uint8_t
658
fido_dev_flags(const fido_dev_t *dev)
659
305
{
660
305
        return (dev->attr.flags);
661
305
}
662
663
bool
664
fido_dev_is_fido2(const fido_dev_t *dev)
665
82.6k
{
666
82.6k
        return (dev->attr.flags & FIDO_CAP_CBOR);
667
82.6k
}
668
669
bool
670
fido_dev_is_winhello(const fido_dev_t *dev)
671
0
{
672
0
        return (dev->flags & FIDO_DEV_WINHELLO);
673
0
}
674
675
bool
676
fido_dev_supports_pin(const fido_dev_t *dev)
677
3.35k
{
678
3.35k
        return (dev->flags & (FIDO_DEV_PIN_SET|FIDO_DEV_PIN_UNSET));
679
3.35k
}
680
681
bool
682
fido_dev_has_pin(const fido_dev_t *dev)
683
3.19k
{
684
3.19k
        return (dev->flags & FIDO_DEV_PIN_SET);
685
3.19k
}
686
687
bool
688
fido_dev_supports_cred_prot(const fido_dev_t *dev)
689
3.99k
{
690
3.99k
        return (dev->flags & FIDO_DEV_CRED_PROT);
691
3.99k
}
692
693
bool
694
fido_dev_supports_credman(const fido_dev_t *dev)
695
3.99k
{
696
3.99k
        return (dev->flags & FIDO_DEV_CREDMAN);
697
3.99k
}
698
699
bool
700
fido_dev_supports_uv(const fido_dev_t *dev)
701
3.19k
{
702
3.19k
        return (dev->flags & (FIDO_DEV_UV_SET|FIDO_DEV_UV_UNSET));
703
3.19k
}
704
705
bool
706
fido_dev_has_uv(const fido_dev_t *dev)
707
3.29k
{
708
3.29k
        return (dev->flags & FIDO_DEV_UV_SET);
709
3.29k
}
710
711
bool
712
fido_dev_supports_permissions(const fido_dev_t *dev)
713
6.04k
{
714
6.04k
        return (dev->flags & FIDO_DEV_TOKEN_PERMS);
715
6.04k
}
716
717
void
718
fido_dev_force_u2f(fido_dev_t *dev)
719
14.7k
{
720
14.7k
        dev->attr.flags &= (uint8_t)~FIDO_CAP_CBOR;
721
14.7k
        dev->flags = 0;
722
14.7k
}
723
724
void
725
fido_dev_force_fido2(fido_dev_t *dev)
726
0
{
727
0
        dev->attr.flags |= FIDO_CAP_CBOR;
728
0
}
729
730
uint8_t
731
fido_dev_get_pin_protocol(const fido_dev_t *dev)
732
27.9k
{
733
27.9k
        if (dev->flags & FIDO_DEV_PIN_PROTOCOL2)
734
27.9k
                return (CTAP_PIN_PROTOCOL2);
735
25.6k
        else if (dev->flags & FIDO_DEV_PIN_PROTOCOL1)
736
25.6k
                return (CTAP_PIN_PROTOCOL1);
737
738
2.42k
        return (0);
739
2.42k
}
740
741
uint64_t
742
fido_dev_maxmsgsize(const fido_dev_t *dev)
743
2.89k
{
744
2.89k
        return (dev->maxmsgsize);
745
2.89k
}
746
747
int
748
fido_dev_set_timeout(fido_dev_t *dev, int ms)
749
72.2k
{
750
72.2k
        if (ms < -1)
751
0
                return (FIDO_ERR_INVALID_ARGUMENT);
752
753
72.2k
        dev->timeout_ms = ms;
754
755
72.2k
        return (FIDO_OK);
756
72.2k
}