Coverage Report

Created: 2021-03-26 11:35

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