Coverage Report

Created: 2026-04-08 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/libfido2/src/dev.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2018-2026 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
 * SPDX-License-Identifier: BSD-2-Clause
6
 */
7
8
#include "fido.h"
9
10
#ifndef TLS
11
#define TLS
12
#endif
13
14
static TLS bool disable_u2f_fallback;
15
16
#ifdef FIDO_FUZZ
17
static void
18
set_random_report_len(fido_dev_t *dev)
19
671k
{
20
671k
        dev->rx_len = CTAP_MIN_REPORT_LEN +
21
671k
            uniform_random(CTAP_MAX_REPORT_LEN - CTAP_MIN_REPORT_LEN + 1);
22
671k
        dev->tx_len = CTAP_MIN_REPORT_LEN +
23
671k
            uniform_random(CTAP_MAX_REPORT_LEN - CTAP_MIN_REPORT_LEN + 1);
24
671k
}
25
#endif
26
27
static void
28
fido_dev_set_extension_flags(fido_dev_t *dev, const fido_cbor_info_t *info)
29
72.1k
{
30
72.1k
        char * const    *ptr = fido_cbor_info_extensions_ptr(info);
31
72.1k
        size_t           len = fido_cbor_info_extensions_len(info);
32
33
323k
        for (size_t i = 0; i < len; i++)
34
251k
                if (strcmp(ptr[i], "credProtect") == 0)
35
42.5k
                        dev->flags |= FIDO_DEV_CRED_PROT;
36
72.1k
}
37
38
static void
39
fido_dev_set_option_flags(fido_dev_t *dev, const fido_cbor_info_t *info)
40
72.1k
{
41
72.1k
        char * const    *ptr = fido_cbor_info_options_name_ptr(info);
42
72.1k
        const bool      *val = fido_cbor_info_options_value_ptr(info);
43
72.1k
        size_t           len = fido_cbor_info_options_len(info);
44
45
602k
        for (size_t i = 0; i < len; i++)
46
530k
                if (strcmp(ptr[i], "clientPin") == 0) {
47
42.6k
                        dev->flags |= val[i] ?
48
38.4k
                            FIDO_DEV_PIN_SET : FIDO_DEV_PIN_UNSET;
49
488k
                } else if (strcmp(ptr[i], "credMgmt") == 0) {
50
18.9k
                        if (val[i])
51
18.7k
                                dev->flags |= FIDO_DEV_CREDMAN;
52
469k
                } else if (strcmp(ptr[i], "credentialMgmtPreview") == 0) {
53
32.0k
                        if (val[i])
54
31.8k
                                dev->flags |= FIDO_DEV_CREDMAN_PRE;
55
437k
                } else if (strcmp(ptr[i], "uv") == 0) {
56
6.89k
                        dev->flags |= val[i] ?
57
6.56k
                            FIDO_DEV_UV_SET : FIDO_DEV_UV_UNSET;
58
430k
                } else if (strcmp(ptr[i], "pinUvAuthToken") == 0) {
59
18.1k
                        if (val[i])
60
17.6k
                                dev->flags |= FIDO_DEV_TOKEN_PERMS;
61
412k
                } else if (strcmp(ptr[i], "bioEnroll") == 0) {
62
2.80k
                        dev->flags |= val[i] ?
63
2.52k
                            FIDO_DEV_BIO_SET : FIDO_DEV_BIO_UNSET;
64
2.80k
                }
65
72.1k
}
66
67
static void
68
fido_dev_set_protocol_flags(fido_dev_t *dev, const fido_cbor_info_t *info)
69
72.1k
{
70
72.1k
        const uint8_t   *ptr = fido_cbor_info_protocols_ptr(info);
71
72.1k
        size_t           len = fido_cbor_info_protocols_len(info);
72
73
197k
        for (size_t i = 0; i < len; i++)
74
124k
                switch (ptr[i]) {
75
69.2k
                case CTAP_PIN_PROTOCOL1:
76
69.2k
                        dev->flags |= FIDO_DEV_PIN_PROTOCOL1;
77
69.2k
                        break;
78
33.7k
                case CTAP_PIN_PROTOCOL2:
79
33.7k
                        dev->flags |= FIDO_DEV_PIN_PROTOCOL2;
80
33.7k
                        break;
81
21.9k
                default:
82
21.9k
                        fido_log_debug("%s: unknown protocol %u", __func__,
83
21.9k
                            ptr[i]);
84
21.9k
                        break;
85
124k
                }
86
72.1k
}
87
88
static void
89
fido_dev_set_flags(fido_dev_t *dev, const fido_cbor_info_t *info)
90
72.1k
{
91
72.1k
        fido_dev_set_extension_flags(dev, info);
92
72.1k
        fido_dev_set_option_flags(dev, info);
93
72.1k
        fido_dev_set_protocol_flags(dev, info);
94
72.1k
}
95
96
static int
97
fido_dev_open_tx(fido_dev_t *dev, const char *path, int *ms)
98
2.97M
{
99
2.97M
        int r;
100
101
2.97M
        if (dev->io_handle != NULL) {
102
0
                fido_log_debug("%s: handle=%p", __func__, dev->io_handle);
103
0
                return (FIDO_ERR_INVALID_ARGUMENT);
104
0
        }
105
106
2.97M
        if (dev->io.open == NULL || dev->io.close == NULL) {
107
0
                fido_log_debug("%s: NULL open/close", __func__);
108
0
                return (FIDO_ERR_INVALID_ARGUMENT);
109
0
        }
110
111
2.97M
        if (dev->cid != CTAP_CID_BROADCAST) {
112
0
                fido_log_debug("%s: cid=0x%x", __func__, dev->cid);
113
0
                return (FIDO_ERR_INVALID_ARGUMENT);
114
0
        }
115
116
2.97M
        if (fido_get_random(&dev->nonce, sizeof(dev->nonce)) < 0) {
117
6.99k
                fido_log_debug("%s: fido_get_random", __func__);
118
6.99k
                return (FIDO_ERR_INTERNAL);
119
6.99k
        }
120
121
2.96M
        if ((dev->io_handle = dev->io.open(path)) == NULL) {
122
2.29M
                fido_log_debug("%s: dev->io.open", __func__);
123
2.29M
                return (FIDO_ERR_INTERNAL);
124
2.29M
        }
125
126
671k
        if (dev->io_own) {
127
671k
                dev->rx_len = CTAP_MAX_REPORT_LEN;
128
671k
                dev->tx_len = CTAP_MAX_REPORT_LEN;
129
671k
        } else {
130
0
                dev->rx_len = fido_hid_report_in_len(dev->io_handle);
131
0
                dev->tx_len = fido_hid_report_out_len(dev->io_handle);
132
0
        }
133
134
671k
#ifdef FIDO_FUZZ
135
671k
        set_random_report_len(dev);
136
671k
#endif
137
138
671k
        if (dev->rx_len < CTAP_MIN_REPORT_LEN ||
139
671k
            dev->rx_len > CTAP_MAX_REPORT_LEN) {
140
0
                fido_log_debug("%s: invalid rx_len %zu", __func__, dev->rx_len);
141
0
                r = FIDO_ERR_RX;
142
0
                goto fail;
143
0
        }
144
145
671k
        if (dev->tx_len < CTAP_MIN_REPORT_LEN ||
146
671k
            dev->tx_len > CTAP_MAX_REPORT_LEN) {
147
0
                fido_log_debug("%s: invalid tx_len %zu", __func__, dev->tx_len);
148
0
                r = FIDO_ERR_TX;
149
0
                goto fail;
150
0
        }
151
152
671k
        if (fido_tx(dev, CTAP_CMD_INIT, &dev->nonce, sizeof(dev->nonce),
153
671k
            ms) < 0) {
154
10.8k
                fido_log_debug("%s: fido_tx", __func__);
155
10.8k
                r = FIDO_ERR_TX;
156
10.8k
                goto fail;
157
10.8k
        }
158
159
660k
        return (FIDO_OK);
160
10.8k
fail:
161
10.8k
        dev->io.close(dev->io_handle);
162
10.8k
        dev->io_handle = NULL;
163
164
10.8k
        return (r);
165
671k
}
166
167
static int
168
fido_dev_open_rx(fido_dev_t *dev, int *ms)
169
660k
{
170
660k
        fido_cbor_info_t        *info = NULL;
171
660k
        int                      reply_len;
172
660k
        int                      r;
173
174
660k
        if ((reply_len = fido_rx(dev, CTAP_CMD_INIT, &dev->attr,
175
660k
            sizeof(dev->attr), ms)) < 0) {
176
346k
                fido_log_debug("%s: fido_rx", __func__);
177
346k
                r = FIDO_ERR_RX;
178
346k
                goto fail;
179
346k
        }
180
181
314k
#ifdef FIDO_FUZZ
182
314k
        dev->attr.nonce = dev->nonce;
183
314k
#endif
184
185
314k
        if ((size_t)reply_len != sizeof(dev->attr) ||
186
314k
            dev->attr.nonce != dev->nonce) {
187
15.3k
                fido_log_debug("%s: invalid nonce", __func__);
188
15.3k
                r = FIDO_ERR_RX;
189
15.3k
                goto fail;
190
15.3k
        }
191
192
298k
        dev->flags = 0;
193
298k
        dev->cid = dev->attr.cid;
194
195
298k
        if (fido_dev_is_fido2(dev)) {
196
233k
                if ((info = fido_cbor_info_new()) == NULL) {
197
676
                        fido_log_debug("%s: fido_cbor_info_new", __func__);
198
676
                        r = FIDO_ERR_INTERNAL;
199
676
                        goto fail;
200
676
                }
201
232k
                if ((r = fido_dev_get_cbor_info_wait(dev, info,
202
232k
                    ms)) != FIDO_OK) {
203
160k
                        fido_log_debug("%s: fido_dev_cbor_info_wait: %d",
204
160k
                            __func__, r);
205
160k
                        if (disable_u2f_fallback)
206
0
                                goto fail;
207
160k
                        fido_log_debug("%s: falling back to u2f", __func__);
208
160k
                        fido_dev_force_u2f(dev);
209
160k
                } else {
210
72.1k
                        fido_dev_set_flags(dev, info);
211
72.1k
                }
212
232k
        }
213
214
298k
        if (fido_dev_is_fido2(dev) && info != NULL) {
215
72.1k
                dev->maxmsgsize = fido_cbor_info_maxmsgsiz(info);
216
72.1k
                fido_log_debug("%s: FIDO_MAXMSG=%d, maxmsgsiz=%lu", __func__,
217
72.1k
                    FIDO_MAXMSG, (unsigned long)dev->maxmsgsize);
218
72.1k
        }
219
220
298k
        r = FIDO_OK;
221
660k
fail:
222
660k
        fido_cbor_info_free(&info);
223
224
660k
        if (r != FIDO_OK) {
225
362k
                dev->io.close(dev->io_handle);
226
362k
                dev->io_handle = NULL;
227
362k
        }
228
229
660k
        return (r);
230
298k
}
231
232
static int
233
fido_dev_open_wait(fido_dev_t *dev, const char *path, int *ms)
234
2.97M
{
235
2.97M
        int r;
236
237
#ifdef USE_WINHELLO
238
        if (strcmp(path, FIDO_WINHELLO_PATH) == 0)
239
                return (fido_winhello_open(dev));
240
#endif
241
2.97M
        if ((r = fido_dev_open_tx(dev, path, ms)) != FIDO_OK ||
242
2.97M
            (r = fido_dev_open_rx(dev, ms)) != FIDO_OK)
243
2.67M
                return (r);
244
245
298k
        return (FIDO_OK);
246
2.97M
}
247
248
static void
249
run_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen,
250
    const char *type, int (*manifest)(fido_dev_info_t *, size_t, size_t *))
251
15.4k
{
252
15.4k
        size_t ndevs = 0;
253
15.4k
        int r;
254
255
15.4k
        if (*olen >= ilen) {
256
478
                fido_log_debug("%s: skipping %s", __func__, type);
257
478
                return;
258
478
        }
259
14.9k
        if ((r = manifest(devlist + *olen, ilen - *olen, &ndevs)) != FIDO_OK)
260
122
                fido_log_debug("%s: %s: 0x%x", __func__, type, r);
261
14.9k
        fido_log_debug("%s: found %zu %s device%s", __func__, ndevs, type,
262
14.9k
            ndevs == 1 ? "" : "s");
263
14.9k
        *olen += ndevs;
264
14.9k
}
265
266
int
267
fido_dev_info_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
268
5.14k
{
269
5.14k
        *olen = 0;
270
271
5.14k
        run_manifest(devlist, ilen, olen, "hid", fido_hid_manifest);
272
5.14k
#ifdef USE_NFC
273
5.14k
        run_manifest(devlist, ilen, olen, "nfc", fido_nfc_manifest);
274
5.14k
#endif
275
5.14k
#ifdef USE_PCSC
276
5.14k
        run_manifest(devlist, ilen, olen, "pcsc", fido_pcsc_manifest);
277
5.14k
#endif
278
#ifdef USE_WINHELLO
279
        run_manifest(devlist, ilen, olen, "winhello", fido_winhello_manifest);
280
#endif
281
282
5.14k
        return (FIDO_OK);
283
5.14k
}
284
285
int
286
fido_dev_open_with_info(fido_dev_t *dev)
287
0
{
288
0
        int ms = dev->timeout_ms;
289
290
0
        if (dev->path == NULL)
291
0
                return (FIDO_ERR_INVALID_ARGUMENT);
292
293
0
        return (fido_dev_open_wait(dev, dev->path, &ms));
294
0
}
295
296
int
297
fido_dev_open(fido_dev_t *dev, const char *path)
298
2.97M
{
299
2.97M
        int ms = dev->timeout_ms;
300
301
2.97M
#ifdef USE_NFC
302
2.97M
        if (fido_is_nfc(path) && fido_dev_set_nfc(dev) < 0) {
303
0
                fido_log_debug("%s: fido_dev_set_nfc", __func__);
304
0
                return FIDO_ERR_INTERNAL;
305
0
        }
306
2.97M
#endif
307
2.97M
#ifdef USE_PCSC
308
2.97M
        if (fido_is_pcsc(path) && fido_dev_set_pcsc(dev) < 0) {
309
0
                fido_log_debug("%s: fido_dev_set_pcsc", __func__);
310
0
                return FIDO_ERR_INTERNAL;
311
0
        }
312
2.97M
#endif
313
314
2.97M
        return (fido_dev_open_wait(dev, path, &ms));
315
2.97M
}
316
317
int
318
fido_dev_close(fido_dev_t *dev)
319
298k
{
320
#ifdef USE_WINHELLO
321
        if (dev->flags & FIDO_DEV_WINHELLO)
322
                return (fido_winhello_close(dev));
323
#endif
324
298k
        if (dev->io_handle == NULL || dev->io.close == NULL)
325
0
                return (FIDO_ERR_INVALID_ARGUMENT);
326
327
298k
        dev->io.close(dev->io_handle);
328
298k
        dev->io_handle = NULL;
329
298k
        dev->cid = CTAP_CID_BROADCAST;
330
331
298k
        return (FIDO_OK);
332
298k
}
333
334
int
335
fido_dev_set_sigmask(fido_dev_t *dev, const fido_sigset_t *sigmask)
336
0
{
337
0
        if (dev->io_handle == NULL || sigmask == NULL)
338
0
                return (FIDO_ERR_INVALID_ARGUMENT);
339
340
0
#ifdef USE_NFC
341
0
        if (dev->transport.rx == fido_nfc_rx && dev->io.read == fido_nfc_read)
342
0
                return (fido_nfc_set_sigmask(dev->io_handle, sigmask));
343
0
#endif
344
0
        if (dev->transport.rx == NULL && dev->io.read == fido_hid_read)
345
0
                return (fido_hid_set_sigmask(dev->io_handle, sigmask));
346
347
0
        return (FIDO_ERR_INVALID_ARGUMENT);
348
0
}
349
350
int
351
fido_dev_cancel(fido_dev_t *dev)
352
63.6k
{
353
63.6k
        int ms = dev->timeout_ms;
354
355
#ifdef USE_WINHELLO
356
        if (dev->flags & FIDO_DEV_WINHELLO)
357
                return (fido_winhello_cancel(dev));
358
#endif
359
63.6k
        if (fido_dev_is_fido2(dev) == false)
360
42.5k
                return (FIDO_ERR_INVALID_ARGUMENT);
361
21.1k
        if (fido_tx(dev, CTAP_CMD_CANCEL, NULL, 0, &ms) < 0)
362
373
                return (FIDO_ERR_TX);
363
364
20.7k
        return (FIDO_OK);
365
21.1k
}
366
367
int
368
fido_dev_set_io_functions(fido_dev_t *dev, const fido_dev_io_t *io)
369
603k
{
370
603k
        if (dev->io_handle != NULL) {
371
0
                fido_log_debug("%s: non-NULL handle", __func__);
372
0
                return (FIDO_ERR_INVALID_ARGUMENT);
373
0
        }
374
375
603k
        if (io == NULL || io->open == NULL || io->close == NULL ||
376
603k
            io->read == NULL || io->write == NULL) {
377
0
                fido_log_debug("%s: NULL function", __func__);
378
0
                return (FIDO_ERR_INVALID_ARGUMENT);
379
0
        }
380
381
603k
        dev->io = *io;
382
603k
        dev->io_own = true;
383
384
603k
        return (FIDO_OK);
385
603k
}
386
387
int
388
fido_dev_set_transport_functions(fido_dev_t *dev, const fido_dev_transport_t *t)
389
9.46k
{
390
9.46k
        if (dev->io_handle != NULL) {
391
0
                fido_log_debug("%s: non-NULL handle", __func__);
392
0
                return (FIDO_ERR_INVALID_ARGUMENT);
393
0
        }
394
395
9.46k
        dev->transport = *t;
396
9.46k
        dev->io_own = true;
397
398
9.46k
        return (FIDO_OK);
399
9.46k
}
400
401
void *
402
fido_dev_io_handle(const fido_dev_t *dev)
403
0
{
404
405
0
        return (dev->io_handle);
406
0
}
407
408
void
409
fido_init(int flags)
410
195k
{
411
195k
        if (flags & FIDO_DEBUG || getenv("FIDO_DEBUG") != NULL)
412
195k
                fido_log_init();
413
414
195k
        disable_u2f_fallback = (flags & FIDO_DISABLE_U2F_FALLBACK);
415
195k
}
416
417
fido_dev_t *
418
fido_dev_new(void)
419
2.98M
{
420
2.98M
        fido_dev_t *dev;
421
422
2.98M
        if ((dev = calloc(1, sizeof(*dev))) == NULL)
423
6.91k
                return (NULL);
424
425
2.97M
        dev->cid = CTAP_CID_BROADCAST;
426
2.97M
        dev->timeout_ms = -1;
427
2.97M
        dev->io = (fido_dev_io_t) {
428
2.97M
                &fido_hid_open,
429
2.97M
                &fido_hid_close,
430
2.97M
                &fido_hid_read,
431
2.97M
                &fido_hid_write,
432
2.97M
        };
433
434
2.97M
        return (dev);
435
2.98M
}
436
437
fido_dev_t *
438
fido_dev_new_with_info(const fido_dev_info_t *di)
439
0
{
440
0
        fido_dev_t *dev;
441
442
0
        if ((dev = calloc(1, sizeof(*dev))) == NULL)
443
0
                return (NULL);
444
445
#if 0
446
        if (di->io.open == NULL || di->io.close == NULL ||
447
            di->io.read == NULL || di->io.write == NULL) {
448
                fido_log_debug("%s: NULL function", __func__);
449
                fido_dev_free(&dev);
450
                return (NULL);
451
        }
452
#endif
453
454
0
        dev->io = di->io;
455
0
        dev->io_own = di->transport.tx != NULL || di->transport.rx != NULL;
456
0
        dev->transport = di->transport;
457
0
        dev->cid = CTAP_CID_BROADCAST;
458
0
        dev->timeout_ms = -1;
459
460
0
        if ((dev->path = strdup(di->path)) == NULL) {
461
0
                fido_log_debug("%s: strdup", __func__);
462
0
                fido_dev_free(&dev);
463
0
                return (NULL);
464
0
        }
465
466
0
        return (dev);
467
0
}
468
469
void
470
fido_dev_free(fido_dev_t **dev_p)
471
3.04M
{
472
3.04M
        fido_dev_t *dev;
473
474
3.04M
        if (dev_p == NULL || (dev = *dev_p) == NULL)
475
68.1k
                return;
476
477
2.97M
        fido_blob_reset(&dev->puat);
478
2.97M
        free(dev->path);
479
2.97M
        free(dev);
480
481
2.97M
        *dev_p = NULL;
482
2.97M
}
483
484
uint8_t
485
fido_dev_protocol(const fido_dev_t *dev)
486
5.06k
{
487
5.06k
        return (dev->attr.protocol);
488
5.06k
}
489
490
uint8_t
491
fido_dev_major(const fido_dev_t *dev)
492
5.06k
{
493
5.06k
        return (dev->attr.major);
494
5.06k
}
495
496
uint8_t
497
fido_dev_minor(const fido_dev_t *dev)
498
5.06k
{
499
5.06k
        return (dev->attr.minor);
500
5.06k
}
501
502
uint8_t
503
fido_dev_build(const fido_dev_t *dev)
504
5.06k
{
505
5.06k
        return (dev->attr.build);
506
5.06k
}
507
508
uint8_t
509
fido_dev_flags(const fido_dev_t *dev)
510
5.06k
{
511
5.06k
        return (dev->attr.flags);
512
5.06k
}
513
514
bool
515
fido_dev_is_fido2(const fido_dev_t *dev)
516
908k
{
517
908k
        return (dev->attr.flags & FIDO_CAP_CBOR);
518
908k
}
519
520
bool
521
fido_dev_is_winhello(const fido_dev_t *dev)
522
16.8k
{
523
16.8k
        return (dev->flags & FIDO_DEV_WINHELLO);
524
16.8k
}
525
526
bool
527
fido_dev_supports_pin(const fido_dev_t *dev)
528
38.8k
{
529
38.8k
        return (dev->flags & (FIDO_DEV_PIN_SET|FIDO_DEV_PIN_UNSET));
530
38.8k
}
531
532
bool
533
fido_dev_has_pin(const fido_dev_t *dev)
534
37.5k
{
535
37.5k
        return (dev->flags & FIDO_DEV_PIN_SET);
536
37.5k
}
537
538
bool
539
fido_dev_supports_cred_prot(const fido_dev_t *dev)
540
32.6k
{
541
32.6k
        return (dev->flags & FIDO_DEV_CRED_PROT);
542
32.6k
}
543
544
bool
545
fido_dev_supports_credman(const fido_dev_t *dev)
546
32.6k
{
547
32.6k
        return (dev->flags & (FIDO_DEV_CREDMAN|FIDO_DEV_CREDMAN_PRE));
548
32.6k
}
549
550
bool
551
fido_dev_supports_uv(const fido_dev_t *dev)
552
37.5k
{
553
37.5k
        return (dev->flags & (FIDO_DEV_UV_SET|FIDO_DEV_UV_UNSET));
554
37.5k
}
555
556
bool
557
fido_dev_has_uv(const fido_dev_t *dev)
558
39.3k
{
559
39.3k
        return (dev->flags & FIDO_DEV_UV_SET);
560
39.3k
}
561
562
bool
563
fido_dev_supports_permissions(const fido_dev_t *dev)
564
42.4k
{
565
42.4k
        return (dev->flags & FIDO_DEV_TOKEN_PERMS);
566
42.4k
}
567
568
void
569
fido_dev_force_u2f(fido_dev_t *dev)
570
178k
{
571
178k
        dev->attr.flags &= (uint8_t)~FIDO_CAP_CBOR;
572
178k
        dev->flags = 0;
573
178k
}
574
575
void
576
fido_dev_force_fido2(fido_dev_t *dev)
577
0
{
578
0
        dev->attr.flags |= FIDO_CAP_CBOR;
579
0
}
580
581
uint8_t
582
fido_dev_get_pin_protocol(const fido_dev_t *dev)
583
230k
{
584
230k
        if (dev->flags & FIDO_DEV_PIN_PROTOCOL2)
585
72.7k
                return (CTAP_PIN_PROTOCOL2);
586
157k
        else if (dev->flags & FIDO_DEV_PIN_PROTOCOL1)
587
105k
                return (CTAP_PIN_PROTOCOL1);
588
589
52.9k
        return (0);
590
230k
}
591
592
uint64_t
593
fido_dev_maxmsgsize(const fido_dev_t *dev)
594
26.9k
{
595
26.9k
        return (dev->maxmsgsize);
596
26.9k
}
597
598
int
599
fido_dev_set_timeout(fido_dev_t *dev, int ms)
600
603k
{
601
603k
        if (ms < -1)
602
0
                return (FIDO_ERR_INVALID_ARGUMENT);
603
604
603k
        dev->timeout_ms = ms;
605
606
603k
        return (FIDO_OK);
607
603k
}
608
609
const unsigned char *
610
fido_dev_puat_ptr(const fido_dev_t *dev)
611
0
{
612
0
        return dev->puat.ptr;
613
0
}
614
615
size_t
616
fido_dev_puat_len(const fido_dev_t *dev)
617
0
{
618
0
        return dev->puat.len;
619
0
}
620
621
const fido_blob_t *
622
fido_dev_puat_blob(const fido_dev_t *dev)
623
149k
{
624
149k
        return fido_blob_is_empty(&dev->puat) ? NULL : &dev->puat;
625
149k
}
626
627
int
628
fido_dev_set_puat(fido_dev_t *dev, const unsigned char *ptr, size_t len)
629
0
{
630
0
        if (fido_dev_is_winhello(dev))
631
0
                return FIDO_ERR_INVALID_ARGUMENT;
632
633
0
        if (ptr == NULL || len == 0) {
634
0
                fido_blob_reset(&dev->puat);
635
0
                return FIDO_OK;
636
0
        }
637
638
0
        if (fido_blob_set(&dev->puat, ptr, len) != 0)
639
0
                return FIDO_ERR_INTERNAL;
640
641
0
        return FIDO_OK;
642
0
}