Coverage Report

Created: 2025-03-01 02:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/libfido2/src/info.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2018-2022 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
static int
11
decode_string(const cbor_item_t *item, void *arg)
12
556k
{
13
556k
        fido_str_array_t        *a = arg;
14
556k
        const size_t             i = a->len;
15
16
        /* keep ptr[x] and len consistent */
17
556k
        if (cbor_string_copy(item, &a->ptr[i]) < 0) {
18
643
                fido_log_debug("%s: cbor_string_copy", __func__);
19
643
                return (-1);
20
643
        }
21
22
555k
        a->len++;
23
24
555k
        return (0);
25
556k
}
26
27
static int
28
decode_string_array(const cbor_item_t *item, fido_str_array_t *v)
29
220k
{
30
220k
        v->ptr = NULL;
31
220k
        v->len = 0;
32
33
220k
        if (cbor_isa_array(item) == false ||
34
220k
            cbor_array_is_definite(item) == false) {
35
297
                fido_log_debug("%s: cbor type", __func__);
36
297
                return (-1);
37
297
        }
38
39
220k
        v->ptr = calloc(cbor_array_size(item), sizeof(char *));
40
220k
        if (v->ptr == NULL)
41
62
                return (-1);
42
43
220k
        if (cbor_array_iter(item, v, decode_string) < 0) {
44
679
                fido_log_debug("%s: decode_string", __func__);
45
679
                return (-1);
46
679
        }
47
48
219k
        return (0);
49
220k
}
50
51
static int
52
decode_aaguid(const cbor_item_t *item, unsigned char *aaguid, size_t aaguid_len)
53
97.4k
{
54
97.4k
        if (cbor_isa_bytestring(item) == false ||
55
97.4k
            cbor_bytestring_is_definite(item) == false ||
56
97.4k
            cbor_bytestring_length(item) != aaguid_len) {
57
400
                fido_log_debug("%s: cbor type", __func__);
58
400
                return (-1);
59
400
        }
60
61
97.0k
        memcpy(aaguid, cbor_bytestring_handle(item), aaguid_len);
62
63
97.0k
        return (0);
64
97.4k
}
65
66
static int
67
decode_option(const cbor_item_t *key, const cbor_item_t *val, void *arg)
68
526k
{
69
526k
        fido_opt_array_t        *o = arg;
70
526k
        const size_t             i = o->len;
71
72
526k
        if (cbor_decode_bool(val, NULL) < 0) {
73
33.0k
                fido_log_debug("%s: cbor_decode_bool", __func__);
74
33.0k
                return (0); /* ignore */
75
33.0k
        }
76
77
493k
        if (cbor_string_copy(key, &o->name[i]) < 0) {
78
1.28k
                fido_log_debug("%s: cbor_string_copy", __func__);
79
1.28k
                return (0); /* ignore */
80
1.28k
        }
81
82
        /* keep name/value and len consistent */
83
492k
        o->value[i] = cbor_ctrl_value(val) == CBOR_CTRL_TRUE;
84
492k
        o->len++;
85
86
492k
        return (0);
87
493k
}
88
89
static int
90
decode_options(const cbor_item_t *item, fido_opt_array_t *o)
91
92.3k
{
92
92.3k
        o->name = NULL;
93
92.3k
        o->value = NULL;
94
92.3k
        o->len = 0;
95
96
92.3k
        if (cbor_isa_map(item) == false ||
97
92.3k
            cbor_map_is_definite(item) == false) {
98
181
                fido_log_debug("%s: cbor type", __func__);
99
181
                return (-1);
100
181
        }
101
102
92.1k
        o->name = calloc(cbor_map_size(item), sizeof(char *));
103
92.1k
        o->value = calloc(cbor_map_size(item), sizeof(bool));
104
92.1k
        if (o->name == NULL || o->value == NULL)
105
188
                return (-1);
106
107
91.9k
        return (cbor_map_iter(item, o, decode_option));
108
92.1k
}
109
110
static int
111
decode_protocol(const cbor_item_t *item, void *arg)
112
124k
{
113
124k
        fido_byte_array_t       *p = arg;
114
124k
        const size_t             i = p->len;
115
116
124k
        if (cbor_isa_uint(item) == false ||
117
124k
            cbor_int_get_width(item) != CBOR_INT_8) {
118
203
                fido_log_debug("%s: cbor type", __func__);
119
203
                return (-1);
120
203
        }
121
122
        /* keep ptr[x] and len consistent */
123
124k
        p->ptr[i] = cbor_get_uint8(item);
124
124k
        p->len++;
125
126
124k
        return (0);
127
124k
}
128
129
static int
130
decode_protocols(const cbor_item_t *item, fido_byte_array_t *p)
131
91.1k
{
132
91.1k
        p->ptr = NULL;
133
91.1k
        p->len = 0;
134
135
91.1k
        if (cbor_isa_array(item) == false ||
136
91.1k
            cbor_array_is_definite(item) == false) {
137
142
                fido_log_debug("%s: cbor type", __func__);
138
142
                return (-1);
139
142
        }
140
141
91.0k
        p->ptr = calloc(cbor_array_size(item), sizeof(uint8_t));
142
91.0k
        if (p->ptr == NULL)
143
57
                return (-1);
144
145
90.9k
        if (cbor_array_iter(item, p, decode_protocol) < 0) {
146
224
                fido_log_debug("%s: decode_protocol", __func__);
147
224
                return (-1);
148
224
        }
149
150
90.7k
        return (0);
151
90.9k
}
152
153
static int
154
decode_algorithm_entry(const cbor_item_t *key, const cbor_item_t *val,
155
    void *arg)
156
255k
{
157
255k
        fido_algo_t *alg = arg;
158
255k
        char *name = NULL;
159
255k
        int ok = -1;
160
161
255k
        if (cbor_string_copy(key, &name) < 0) {
162
2.16k
                fido_log_debug("%s: cbor type", __func__);
163
2.16k
                ok = 0; /* ignore */
164
2.16k
                goto out;
165
2.16k
        }
166
167
253k
        if (!strcmp(name, "alg")) {
168
99.6k
                if (cbor_isa_negint(val) == false ||
169
99.6k
                    cbor_get_int(val) > INT_MAX || alg->cose != 0) {
170
1.15k
                        fido_log_debug("%s: alg", __func__);
171
1.15k
                        goto out;
172
1.15k
                }
173
98.4k
                alg->cose = -(int)cbor_get_int(val) - 1;
174
153k
        } else if (!strcmp(name, "type")) {
175
81.4k
                if (cbor_string_copy(val, &alg->type) < 0) {
176
201
                        fido_log_debug("%s: type", __func__);
177
201
                        goto out;
178
201
                }
179
81.4k
        }
180
181
252k
        ok = 0;
182
255k
out:
183
255k
        free(name);
184
185
255k
        return (ok);
186
252k
}
187
188
static int
189
decode_algorithm(const cbor_item_t *item, void *arg)
190
133k
{
191
133k
        fido_algo_array_t *aa = arg;
192
133k
        const size_t i = aa->len;
193
194
133k
        if (cbor_isa_map(item) == false ||
195
133k
            cbor_map_is_definite(item) == false) {
196
1.80k
                fido_log_debug("%s: cbor type", __func__);
197
1.80k
                return (-1);
198
1.80k
        }
199
200
131k
        memset(&aa->ptr[i], 0, sizeof(aa->ptr[i]));
201
202
131k
        if (cbor_map_iter(item, &aa->ptr[i], decode_algorithm_entry) < 0) {
203
2.76k
                fido_log_debug("%s: decode_algorithm_entry", __func__);
204
2.76k
                fido_algo_free(&aa->ptr[i]);
205
2.76k
                return (-1);
206
2.76k
        }
207
208
        /* keep ptr[x] and len consistent */
209
129k
        aa->len++;
210
211
129k
        return (0);
212
131k
}
213
214
static int
215
decode_algorithms(const cbor_item_t *item, fido_algo_array_t *aa)
216
68.8k
{
217
68.8k
        aa->ptr = NULL;
218
68.8k
        aa->len = 0;
219
220
68.8k
        if (cbor_isa_array(item) == false ||
221
68.8k
            cbor_array_is_definite(item) == false) {
222
200
                fido_log_debug("%s: cbor type", __func__);
223
200
                return (-1);
224
200
        }
225
226
68.6k
        aa->ptr = calloc(cbor_array_size(item), sizeof(fido_algo_t));
227
68.6k
        if (aa->ptr == NULL)
228
73
                return (-1);
229
230
68.6k
        if (cbor_array_iter(item, aa, decode_algorithm) < 0) {
231
4.58k
                fido_log_debug("%s: decode_algorithm", __func__);
232
4.58k
                return (-1);
233
4.58k
        }
234
235
64.0k
        return (0);
236
68.6k
}
237
238
static int
239
decode_cert(const cbor_item_t *key, const cbor_item_t *val, void *arg)
240
14.6k
{
241
14.6k
        fido_cert_array_t       *c = arg;
242
14.6k
        const size_t             i = c->len;
243
244
14.6k
        if (cbor_is_int(val) == false) {
245
1.52k
                fido_log_debug("%s: cbor_is_int", __func__);
246
1.52k
                return (0); /* ignore */
247
1.52k
        }
248
249
13.0k
        if (cbor_string_copy(key, &c->name[i]) < 0) {
250
791
                fido_log_debug("%s: cbor_string_copy", __func__);
251
791
                return (0); /* ignore */
252
791
        }
253
254
        /* keep name/value and len consistent */
255
12.2k
        c->value[i] = cbor_get_int(val);
256
12.2k
        c->len++;
257
258
12.2k
        return (0);
259
13.0k
}
260
261
static int
262
decode_certs(const cbor_item_t *item, fido_cert_array_t *c)
263
6.78k
{
264
6.78k
        c->name = NULL;
265
6.78k
        c->value = NULL;
266
6.78k
        c->len = 0;
267
268
6.78k
        if (cbor_isa_map(item) == false ||
269
6.78k
            cbor_map_is_definite(item) == false) {
270
182
                fido_log_debug("%s: cbor type", __func__);
271
182
                return (-1);
272
182
        }
273
274
6.60k
        c->name = calloc(cbor_map_size(item), sizeof(char *));
275
6.60k
        c->value = calloc(cbor_map_size(item), sizeof(uint64_t));
276
6.60k
        if (c->name == NULL || c->value == NULL)
277
110
                return (-1);
278
279
6.49k
        return (cbor_map_iter(item, c, decode_cert));
280
6.60k
}
281
282
static int
283
parse_reply_element(const cbor_item_t *key, const cbor_item_t *val, void *arg)
284
972k
{
285
972k
        fido_cbor_info_t *ci = arg;
286
972k
        uint64_t x;
287
288
972k
        if (cbor_isa_uint(key) == false ||
289
972k
            cbor_int_get_width(key) != CBOR_INT_8) {
290
43.0k
                fido_log_debug("%s: cbor type", __func__);
291
43.0k
                return (0); /* ignore */
292
43.0k
        }
293
294
929k
        switch (cbor_get_uint8(key)) {
295
102k
        case 1: /* versions */
296
102k
                return (decode_string_array(val, &ci->versions));
297
103k
        case 2: /* extensions */
298
103k
                return (decode_string_array(val, &ci->extensions));
299
97.4k
        case 3: /* aaguid */
300
97.4k
                return (decode_aaguid(val, ci->aaguid, sizeof(ci->aaguid)));
301
92.3k
        case 4: /* options */
302
92.3k
                return (decode_options(val, &ci->options));
303
93.2k
        case 5: /* maxMsgSize */
304
93.2k
                return (cbor_decode_uint64(val, &ci->maxmsgsiz));
305
91.1k
        case 6: /* pinProtocols */
306
91.1k
                return (decode_protocols(val, &ci->protocols));
307
87.9k
        case 7: /* maxCredentialCountInList */
308
87.9k
                return (cbor_decode_uint64(val, &ci->maxcredcntlst));
309
82.6k
        case 8: /* maxCredentialIdLength */
310
82.6k
                return (cbor_decode_uint64(val, &ci->maxcredidlen));
311
14.6k
        case 9: /* transports */
312
14.6k
                return (decode_string_array(val, &ci->transports));
313
68.8k
        case 10: /* algorithms */
314
68.8k
                return (decode_algorithms(val, &ci->algorithms));
315
5.99k
        case 11: /* maxSerializedLargeBlobArray */
316
5.99k
                return (cbor_decode_uint64(val, &ci->maxlargeblob));
317
6.28k
        case 12: /* forcePINChange */
318
6.28k
                return (cbor_decode_bool(val, &ci->new_pin_reqd));
319
13.0k
        case 13: /* minPINLength */
320
13.0k
                return (cbor_decode_uint64(val, &ci->minpinlen));
321
13.5k
        case 14: /* fwVersion */
322
13.5k
                return (cbor_decode_uint64(val, &ci->fwversion));
323
6.89k
        case 15: /* maxCredBlobLen */
324
6.89k
                return (cbor_decode_uint64(val, &ci->maxcredbloblen));
325
6.19k
        case 16: /* maxRPIDsForSetMinPINLength */
326
6.19k
                return (cbor_decode_uint64(val, &ci->maxrpid_minlen));
327
6.37k
        case 17: /* preferredPlatformUvAttempts */
328
6.37k
                return (cbor_decode_uint64(val, &ci->uv_attempts));
329
6.15k
        case 18: /* uvModality */
330
6.15k
                return (cbor_decode_uint64(val, &ci->uv_modality));
331
6.78k
        case 19: /* certifications */
332
6.78k
                return (decode_certs(val, &ci->certs));
333
9.64k
        case 20: /* remainingDiscoverableCredentials */
334
9.64k
                if (cbor_decode_uint64(val, &x) < 0 || x > INT64_MAX) {
335
590
                        fido_log_debug("%s: cbor_decode_uint64", __func__);
336
590
                        return (-1);
337
590
                }
338
9.05k
                ci->rk_remaining = (int64_t)x;
339
9.05k
                return (0);
340
14.1k
        default: /* ignore */
341
14.1k
                fido_log_debug("%s: cbor type: 0x%02x", __func__, cbor_get_uint8(key));
342
14.1k
                return (0);
343
929k
        }
344
929k
}
345
346
static int
347
fido_dev_get_cbor_info_tx(fido_dev_t *dev, int *ms)
348
244k
{
349
244k
        const unsigned char cbor[] = { CTAP_CBOR_GETINFO };
350
351
244k
        fido_log_debug("%s: dev=%p", __func__, (void *)dev);
352
353
244k
        if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor), ms) < 0) {
354
1.51k
                fido_log_debug("%s: fido_tx", __func__);
355
1.51k
                return (FIDO_ERR_TX);
356
1.51k
        }
357
358
243k
        return (FIDO_OK);
359
244k
}
360
361
static int
362
fido_dev_get_cbor_info_rx(fido_dev_t *dev, fido_cbor_info_t *ci, int *ms)
363
243k
{
364
243k
        unsigned char   *msg;
365
243k
        int              msglen;
366
243k
        int              r;
367
368
243k
        fido_log_debug("%s: dev=%p, ci=%p, ms=%d", __func__, (void *)dev,
369
243k
            (void *)ci, *ms);
370
371
243k
        fido_cbor_info_reset(ci);
372
373
243k
        if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
374
508
                r = FIDO_ERR_INTERNAL;
375
508
                goto out;
376
508
        }
377
378
242k
        if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
379
56.7k
                fido_log_debug("%s: fido_rx", __func__);
380
56.7k
                r = FIDO_ERR_RX;
381
56.7k
                goto out;
382
56.7k
        }
383
384
185k
        r = cbor_parse_reply(msg, (size_t)msglen, ci, parse_reply_element);
385
243k
out:
386
243k
        freezero(msg, FIDO_MAXMSG);
387
388
243k
        return (r);
389
185k
}
390
391
int
392
fido_dev_get_cbor_info_wait(fido_dev_t *dev, fido_cbor_info_t *ci, int *ms)
393
244k
{
394
244k
        int r;
395
396
#ifdef USE_WINHELLO
397
        if (dev->flags & FIDO_DEV_WINHELLO)
398
                return (fido_winhello_get_cbor_info(dev, ci));
399
#endif
400
244k
        if ((r = fido_dev_get_cbor_info_tx(dev, ms)) != FIDO_OK ||
401
244k
            (r = fido_dev_get_cbor_info_rx(dev, ci, ms)) != FIDO_OK)
402
150k
                return (r);
403
404
93.6k
        return (FIDO_OK);
405
244k
}
406
407
int
408
fido_dev_get_cbor_info(fido_dev_t *dev, fido_cbor_info_t *ci)
409
8.00k
{
410
8.00k
        int ms = dev->timeout_ms;
411
412
8.00k
        return (fido_dev_get_cbor_info_wait(dev, ci, &ms));
413
8.00k
}
414
415
/*
416
 * get/set functions for fido_cbor_info_t; always at the end of the file
417
 */
418
419
fido_cbor_info_t *
420
fido_cbor_info_new(void)
421
244k
{
422
244k
        fido_cbor_info_t *ci;
423
424
244k
        if ((ci = calloc(1, sizeof(fido_cbor_info_t))) == NULL)
425
463
                return (NULL);
426
427
244k
        fido_cbor_info_reset(ci);
428
429
244k
        return (ci);
430
244k
}
431
432
void
433
fido_cbor_info_reset(fido_cbor_info_t *ci)
434
732k
{
435
732k
        fido_str_array_free(&ci->versions);
436
732k
        fido_str_array_free(&ci->extensions);
437
732k
        fido_str_array_free(&ci->transports);
438
732k
        fido_opt_array_free(&ci->options);
439
732k
        fido_byte_array_free(&ci->protocols);
440
732k
        fido_algo_array_free(&ci->algorithms);
441
732k
        fido_cert_array_free(&ci->certs);
442
732k
        ci->rk_remaining = -1;
443
732k
}
444
445
void
446
fido_cbor_info_free(fido_cbor_info_t **ci_p)
447
834k
{
448
834k
        fido_cbor_info_t *ci;
449
450
834k
        if (ci_p == NULL || (ci = *ci_p) ==  NULL)
451
590k
                return;
452
244k
        fido_cbor_info_reset(ci);
453
244k
        free(ci);
454
244k
        *ci_p = NULL;
455
244k
}
456
457
char **
458
fido_cbor_info_versions_ptr(const fido_cbor_info_t *ci)
459
9.44k
{
460
9.44k
        return (ci->versions.ptr);
461
9.44k
}
462
463
size_t
464
fido_cbor_info_versions_len(const fido_cbor_info_t *ci)
465
17.4k
{
466
17.4k
        return (ci->versions.len);
467
17.4k
}
468
469
char **
470
fido_cbor_info_extensions_ptr(const fido_cbor_info_t *ci)
471
92.3k
{
472
92.3k
        return (ci->extensions.ptr);
473
92.3k
}
474
475
size_t
476
fido_cbor_info_extensions_len(const fido_cbor_info_t *ci)
477
100k
{
478
100k
        return (ci->extensions.len);
479
100k
}
480
481
char **
482
fido_cbor_info_transports_ptr(const fido_cbor_info_t *ci)
483
327
{
484
327
        return (ci->transports.ptr);
485
327
}
486
487
size_t
488
fido_cbor_info_transports_len(const fido_cbor_info_t *ci)
489
8.32k
{
490
8.32k
        return (ci->transports.len);
491
8.32k
}
492
493
const unsigned char *
494
fido_cbor_info_aaguid_ptr(const fido_cbor_info_t *ci)
495
8.00k
{
496
8.00k
        return (ci->aaguid);
497
8.00k
}
498
499
size_t
500
fido_cbor_info_aaguid_len(const fido_cbor_info_t *ci)
501
8.00k
{
502
8.00k
        return (sizeof(ci->aaguid));
503
8.00k
}
504
505
char **
506
fido_cbor_info_options_name_ptr(const fido_cbor_info_t *ci)
507
92.4k
{
508
92.4k
        return (ci->options.name);
509
92.4k
}
510
511
const bool *
512
fido_cbor_info_options_value_ptr(const fido_cbor_info_t *ci)
513
92.4k
{
514
92.4k
        return (ci->options.value);
515
92.4k
}
516
517
size_t
518
fido_cbor_info_options_len(const fido_cbor_info_t *ci)
519
100k
{
520
100k
        return (ci->options.len);
521
100k
}
522
523
uint64_t
524
fido_cbor_info_maxcredbloblen(const fido_cbor_info_t *ci)
525
8.00k
{
526
8.00k
        return (ci->maxcredbloblen);
527
8.00k
}
528
529
uint64_t
530
fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *ci)
531
99.8k
{
532
99.8k
        return (ci->maxmsgsiz);
533
99.8k
}
534
535
uint64_t
536
fido_cbor_info_maxcredcntlst(const fido_cbor_info_t *ci)
537
8.00k
{
538
8.00k
        return (ci->maxcredcntlst);
539
8.00k
}
540
541
uint64_t
542
fido_cbor_info_maxcredidlen(const fido_cbor_info_t *ci)
543
8.00k
{
544
8.00k
        return (ci->maxcredidlen);
545
8.00k
}
546
547
uint64_t
548
fido_cbor_info_maxlargeblob(const fido_cbor_info_t *ci)
549
8.00k
{
550
8.00k
        return (ci->maxlargeblob);
551
8.00k
}
552
553
uint64_t
554
fido_cbor_info_fwversion(const fido_cbor_info_t *ci)
555
8.00k
{
556
8.00k
        return (ci->fwversion);
557
8.00k
}
558
559
uint64_t
560
fido_cbor_info_minpinlen(const fido_cbor_info_t *ci)
561
8.00k
{
562
8.00k
        return (ci->minpinlen);
563
8.00k
}
564
565
uint64_t
566
fido_cbor_info_maxrpid_minpinlen(const fido_cbor_info_t *ci)
567
8.00k
{
568
8.00k
        return (ci->maxrpid_minlen);
569
8.00k
}
570
571
uint64_t
572
fido_cbor_info_uv_attempts(const fido_cbor_info_t *ci)
573
8.00k
{
574
8.00k
        return (ci->uv_attempts);
575
8.00k
}
576
577
uint64_t
578
fido_cbor_info_uv_modality(const fido_cbor_info_t *ci)
579
8.00k
{
580
8.00k
        return (ci->uv_modality);
581
8.00k
}
582
583
int64_t
584
fido_cbor_info_rk_remaining(const fido_cbor_info_t *ci)
585
8.00k
{
586
8.00k
        return (ci->rk_remaining);
587
8.00k
}
588
589
const uint8_t *
590
fido_cbor_info_protocols_ptr(const fido_cbor_info_t *ci)
591
99.8k
{
592
99.8k
        return (ci->protocols.ptr);
593
99.8k
}
594
595
size_t
596
fido_cbor_info_protocols_len(const fido_cbor_info_t *ci)
597
99.8k
{
598
99.8k
        return (ci->protocols.len);
599
99.8k
}
600
601
size_t
602
fido_cbor_info_algorithm_count(const fido_cbor_info_t *ci)
603
16.1k
{
604
16.1k
        return (ci->algorithms.len);
605
16.1k
}
606
607
const char *
608
fido_cbor_info_algorithm_type(const fido_cbor_info_t *ci, size_t idx)
609
8.18k
{
610
8.18k
        if (idx >= ci->algorithms.len)
611
8.00k
                return (NULL);
612
613
182
        return (ci->algorithms.ptr[idx].type);
614
8.18k
}
615
616
int
617
fido_cbor_info_algorithm_cose(const fido_cbor_info_t *ci, size_t idx)
618
8.18k
{
619
8.18k
        if (idx >= ci->algorithms.len)
620
8.00k
                return (0);
621
622
182
        return (ci->algorithms.ptr[idx].cose);
623
8.18k
}
624
625
bool
626
fido_cbor_info_new_pin_required(const fido_cbor_info_t *ci)
627
8.00k
{
628
8.00k
        return (ci->new_pin_reqd);
629
8.00k
}
630
631
char **
632
fido_cbor_info_certs_name_ptr(const fido_cbor_info_t *ci)
633
105
{
634
105
        return (ci->certs.name);
635
105
}
636
637
const uint64_t *
638
fido_cbor_info_certs_value_ptr(const fido_cbor_info_t *ci)
639
105
{
640
105
        return (ci->certs.value);
641
105
}
642
643
size_t
644
fido_cbor_info_certs_len(const fido_cbor_info_t *ci)
645
8.10k
{
646
8.10k
        return (ci->certs.len);
647
8.10k
}