Coverage Report

Created: 2021-07-20 18:14

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