Coverage Report

Created: 2026-04-08 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/libfido2/src/info.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
static int
11
decode_string(const cbor_item_t *item, void *arg)
12
694k
{
13
694k
        fido_str_array_t        *a = arg;
14
694k
        const size_t             i = a->len;
15
16
        /* keep ptr[x] and len consistent */
17
694k
        if (cbor_string_copy(item, &a->ptr[i]) < 0) {
18
907
                fido_log_debug("%s: cbor_string_copy", __func__);
19
907
                return (-1);
20
907
        }
21
22
693k
        a->len++;
23
24
693k
        return (0);
25
694k
}
26
27
static int
28
decode_string_array(const cbor_item_t *item, fido_str_array_t *v)
29
222k
{
30
222k
        v->ptr = NULL;
31
222k
        v->len = 0;
32
33
222k
        if (cbor_isa_array(item) == false ||
34
222k
            cbor_array_is_definite(item) == false) {
35
151
                fido_log_debug("%s: cbor type", __func__);
36
151
                return (-1);
37
151
        }
38
39
222k
        v->ptr = calloc(cbor_array_size(item), sizeof(char *));
40
222k
        if (v->ptr == NULL)
41
67
                return (-1);
42
43
222k
        if (cbor_array_iter(item, v, decode_string) < 0) {
44
953
                fido_log_debug("%s: decode_string", __func__);
45
953
                return (-1);
46
953
        }
47
48
221k
        return (0);
49
222k
}
50
51
static int
52
decode_aaguid(const cbor_item_t *item, unsigned char *aaguid, size_t aaguid_len)
53
77.2k
{
54
77.2k
        if (cbor_isa_bytestring(item) == false ||
55
77.2k
            cbor_bytestring_is_definite(item) == false ||
56
77.2k
            cbor_bytestring_length(item) != aaguid_len) {
57
473
                fido_log_debug("%s: cbor type", __func__);
58
473
                return (-1);
59
473
        }
60
61
76.8k
        memcpy(aaguid, cbor_bytestring_handle(item), aaguid_len);
62
63
76.8k
        return (0);
64
77.2k
}
65
66
static int
67
decode_option(const cbor_item_t *key, const cbor_item_t *val, void *arg)
68
611k
{
69
611k
        fido_opt_array_t        *o = arg;
70
611k
        const size_t             i = o->len;
71
72
611k
        if (cbor_decode_bool(val, NULL) < 0) {
73
26.6k
                fido_log_debug("%s: cbor_decode_bool", __func__);
74
26.6k
                return (0); /* ignore */
75
26.6k
        }
76
77
584k
        if (cbor_string_copy(key, &o->name[i]) < 0) {
78
1.87k
                fido_log_debug("%s: cbor_string_copy", __func__);
79
1.87k
                return (0); /* ignore */
80
1.87k
        }
81
82
        /* keep name/value and len consistent */
83
582k
        o->value[i] = cbor_ctrl_value(val) == CBOR_CTRL_TRUE;
84
582k
        o->len++;
85
86
582k
        return (0);
87
584k
}
88
89
static int
90
decode_options(const cbor_item_t *item, fido_opt_array_t *o)
91
74.2k
{
92
74.2k
        o->name = NULL;
93
74.2k
        o->value = NULL;
94
74.2k
        o->len = 0;
95
96
74.2k
        if (cbor_isa_map(item) == false ||
97
74.2k
            cbor_map_is_definite(item) == false) {
98
114
                fido_log_debug("%s: cbor type", __func__);
99
114
                return (-1);
100
114
        }
101
102
74.1k
        o->name = calloc(cbor_map_size(item), sizeof(char *));
103
74.1k
        o->value = calloc(cbor_map_size(item), sizeof(bool));
104
74.1k
        if (o->name == NULL || o->value == NULL)
105
113
                return (-1);
106
107
74.0k
        return (cbor_map_iter(item, o, decode_option));
108
74.1k
}
109
110
static int
111
decode_byte_array_item(const cbor_item_t *item, void *arg)
112
185k
{
113
185k
        fido_byte_array_t       *p = arg;
114
185k
        const size_t             i = p->len;
115
116
185k
        if (cbor_isa_uint(item) == false ||
117
185k
            cbor_int_get_width(item) != CBOR_INT_8) {
118
199
                fido_log_debug("%s: cbor type", __func__);
119
199
                return (-1);
120
199
        }
121
122
        /* keep ptr[x] and len consistent */
123
185k
        p->ptr[i] = cbor_get_uint8(item);
124
185k
        p->len++;
125
126
185k
        return (0);
127
185k
}
128
129
static int
130
decode_byte_array(const cbor_item_t *item, fido_byte_array_t *p)
131
91.0k
{
132
91.0k
        p->ptr = NULL;
133
91.0k
        p->len = 0;
134
135
91.0k
        if (cbor_isa_array(item) == false ||
136
91.0k
            cbor_array_is_definite(item) == false) {
137
108
                fido_log_debug("%s: cbor type", __func__);
138
108
                return (-1);
139
108
        }
140
141
90.9k
        p->ptr = calloc(cbor_array_size(item), sizeof(uint8_t));
142
90.9k
        if (p->ptr == NULL)
143
83
                return (-1);
144
145
90.8k
        if (cbor_array_iter(item, p, decode_byte_array_item) < 0) {
146
224
                fido_log_debug("%s: decode_byte_array_item", __func__);
147
224
                return (-1);
148
224
        }
149
150
90.6k
        return (0);
151
90.8k
}
152
153
static int
154
decode_algorithm_entry(const cbor_item_t *key, const cbor_item_t *val,
155
    void *arg)
156
278k
{
157
278k
        fido_algo_t *alg = arg;
158
278k
        char *name = NULL;
159
278k
        int ok = -1;
160
161
278k
        if (cbor_string_copy(key, &name) < 0) {
162
3.72k
                fido_log_debug("%s: cbor type", __func__);
163
3.72k
                ok = 0; /* ignore */
164
3.72k
                goto out;
165
3.72k
        }
166
167
275k
        if (!strcmp(name, "alg")) {
168
124k
                if (cbor_isa_negint(val) == false ||
169
124k
                    cbor_get_int(val) > INT_MAX || alg->cose != 0) {
170
1.00k
                        fido_log_debug("%s: alg", __func__);
171
1.00k
                        goto out;
172
1.00k
                }
173
123k
                alg->cose = -(int)cbor_get_int(val) - 1;
174
150k
        } else if (!strcmp(name, "type")) {
175
113k
                if (cbor_string_copy(val, &alg->type) < 0) {
176
185
                        fido_log_debug("%s: type", __func__);
177
185
                        goto out;
178
185
                }
179
113k
        }
180
181
273k
        ok = 0;
182
278k
out:
183
278k
        free(name);
184
185
278k
        return (ok);
186
273k
}
187
188
static int
189
decode_algorithm(const cbor_item_t *item, void *arg)
190
152k
{
191
152k
        fido_algo_array_t *aa = arg;
192
152k
        const size_t i = aa->len;
193
194
152k
        if (cbor_isa_map(item) == false ||
195
152k
            cbor_map_is_definite(item) == false) {
196
1.13k
                fido_log_debug("%s: cbor type", __func__);
197
1.13k
                return (-1);
198
1.13k
        }
199
200
151k
        memset(&aa->ptr[i], 0, sizeof(aa->ptr[i]));
201
202
151k
        if (cbor_map_iter(item, &aa->ptr[i], decode_algorithm_entry) < 0) {
203
2.26k
                fido_log_debug("%s: decode_algorithm_entry", __func__);
204
2.26k
                fido_algo_free(&aa->ptr[i]);
205
2.26k
                return (-1);
206
2.26k
        }
207
208
        /* keep ptr[x] and len consistent */
209
148k
        aa->len++;
210
211
148k
        return (0);
212
151k
}
213
214
static int
215
decode_algorithms(const cbor_item_t *item, fido_algo_array_t *aa)
216
63.5k
{
217
63.5k
        aa->ptr = NULL;
218
63.5k
        aa->len = 0;
219
220
63.5k
        if (cbor_isa_array(item) == false ||
221
63.5k
            cbor_array_is_definite(item) == false) {
222
120
                fido_log_debug("%s: cbor type", __func__);
223
120
                return (-1);
224
120
        }
225
226
63.4k
        aa->ptr = calloc(cbor_array_size(item), sizeof(fido_algo_t));
227
63.4k
        if (aa->ptr == NULL)
228
48
                return (-1);
229
230
63.3k
        if (cbor_array_iter(item, aa, decode_algorithm) < 0) {
231
3.41k
                fido_log_debug("%s: decode_algorithm", __func__);
232
3.41k
                return (-1);
233
3.41k
        }
234
235
59.9k
        return (0);
236
63.3k
}
237
238
static int
239
decode_cert(const cbor_item_t *key, const cbor_item_t *val, void *arg)
240
26.4k
{
241
26.4k
        fido_cert_array_t       *c = arg;
242
26.4k
        const size_t             i = c->len;
243
244
26.4k
        if (cbor_is_int(val) == false) {
245
6.62k
                fido_log_debug("%s: cbor_is_int", __func__);
246
6.62k
                return (0); /* ignore */
247
6.62k
        }
248
249
19.8k
        if (cbor_string_copy(key, &c->name[i]) < 0) {
250
1.49k
                fido_log_debug("%s: cbor_string_copy", __func__);
251
1.49k
                return (0); /* ignore */
252
1.49k
        }
253
254
        /* keep name/value and len consistent */
255
18.3k
        c->value[i] = cbor_get_int(val);
256
18.3k
        c->len++;
257
258
18.3k
        return (0);
259
19.8k
}
260
261
static int
262
decode_certs(const cbor_item_t *item, fido_cert_array_t *c)
263
6.15k
{
264
6.15k
        c->name = NULL;
265
6.15k
        c->value = NULL;
266
6.15k
        c->len = 0;
267
268
6.15k
        if (cbor_isa_map(item) == false ||
269
6.15k
            cbor_map_is_definite(item) == false) {
270
109
                fido_log_debug("%s: cbor type", __func__);
271
109
                return (-1);
272
109
        }
273
274
6.04k
        c->name = calloc(cbor_map_size(item), sizeof(char *));
275
6.04k
        c->value = calloc(cbor_map_size(item), sizeof(uint64_t));
276
6.04k
        if (c->name == NULL || c->value == NULL)
277
86
                return (-1);
278
279
5.96k
        return (cbor_map_iter(item, c, decode_cert));
280
6.04k
}
281
282
static int
283
parse_reply_element(const cbor_item_t *key, const cbor_item_t *val, void *arg)
284
1.07M
{
285
1.07M
        fido_cbor_info_t *ci = arg;
286
1.07M
        uint64_t x;
287
1.07M
        bool b;
288
289
1.07M
        if (cbor_isa_uint(key) == false ||
290
1.07M
            cbor_int_get_width(key) != CBOR_INT_8) {
291
17.6k
                fido_log_debug("%s: cbor type", __func__);
292
17.6k
                return (0); /* ignore */
293
17.6k
        }
294
295
1.06M
        switch (cbor_get_uint8(key)) {
296
75.7k
        case 1: /* versions */
297
75.7k
                return (decode_string_array(val, &ci->versions));
298
80.9k
        case 2: /* extensions */
299
80.9k
                return (decode_string_array(val, &ci->extensions));
300
77.2k
        case 3: /* aaguid */
301
77.2k
                return (decode_aaguid(val, ci->aaguid, sizeof(ci->aaguid)));
302
74.2k
        case 4: /* options */
303
74.2k
                return (decode_options(val, &ci->options));
304
73.6k
        case 5: /* maxMsgSize */
305
73.6k
                return (cbor_decode_uint64(val, &ci->maxmsgsiz));
306
73.8k
        case 6: /* pinProtocols */
307
73.8k
                return (decode_byte_array(val, &ci->protocols));
308
70.4k
        case 7: /* maxCredentialCountInList */
309
70.4k
                return (cbor_decode_uint64(val, &ci->maxcredcntlst));
310
68.9k
        case 8: /* maxCredentialIdLength */
311
68.9k
                return (cbor_decode_uint64(val, &ci->maxcredidlen));
312
30.4k
        case 9: /* transports */
313
30.4k
                return (decode_string_array(val, &ci->transports));
314
63.5k
        case 10: /* algorithms */
315
63.5k
                return (decode_algorithms(val, &ci->algorithms));
316
24.6k
        case 11: /* maxSerializedLargeBlobArray */
317
24.6k
                return (cbor_decode_uint64(val, &ci->maxlargeblob));
318
24.6k
        case 12: /* forcePINChange */
319
24.6k
                return (cbor_decode_bool(val, &ci->new_pin_reqd));
320
28.2k
        case 13: /* minPINLength */
321
28.2k
                return (cbor_decode_uint64(val, &ci->minpinlen));
322
28.7k
        case 14: /* fwVersion */
323
28.7k
                return (cbor_decode_uint64(val, &ci->fwversion));
324
25.0k
        case 15: /* maxCredBlobLen */
325
25.0k
                return (cbor_decode_uint64(val, &ci->maxcredbloblen));
326
24.6k
        case 16: /* maxRPIDsForSetMinPINLength */
327
24.6k
                return (cbor_decode_uint64(val, &ci->maxrpid_minlen));
328
6.66k
        case 17: /* preferredPlatformUvAttempts */
329
6.66k
                return (cbor_decode_uint64(val, &ci->uv_attempts));
330
6.56k
        case 18: /* uvModality */
331
6.56k
                return (cbor_decode_uint64(val, &ci->uv_modality));
332
6.15k
        case 19: /* certifications */
333
6.15k
                return (decode_certs(val, &ci->certs));
334
26.0k
        case 20: /* remainingDiscoverableCredentials */
335
26.0k
                if (cbor_decode_uint64(val, &x) < 0 || x > INT64_MAX) {
336
244
                        fido_log_debug("%s: cbor_decode_uint64", __func__);
337
244
                        return (-1);
338
244
                }
339
25.7k
                ci->rk_remaining = (int64_t)x;
340
25.7k
                return (0);
341
17.9k
        case 22: /* attestationFormats */
342
17.9k
                return (decode_string_array(val, &ci->attfmts));
343
1.74k
        case 23: /* uvCountSinceLastPinEntry */
344
1.74k
                if (cbor_decode_uint64(val, &x) < 0 || x > INT64_MAX) {
345
247
                        fido_log_debug("%s: cbor_decode_uint64", __func__);
346
247
                        return (-1);
347
247
                }
348
1.49k
                ci->uv_since_pin = (int64_t)x;
349
1.49k
                return (0);
350
17.8k
        case 24: /* longTouchForReset */
351
17.8k
                return (cbor_decode_bool(val, &ci->long_reset));
352
17.9k
        case 25: /* encIdentifier */
353
17.9k
                return (fido_blob_decode(val, &ci->encid));
354
17.7k
        case 26: /* transportsForReset */
355
17.7k
                return (decode_string_array(val, &ci->rsttransports));
356
17.6k
        case 27: /* pinComplexityPolicy */
357
17.6k
                if (cbor_decode_bool(val, &b) < 0) {
358
102
                        fido_log_debug("%s: cbor_decode_bool", __func__);
359
102
                        return (-1);
360
102
                }
361
17.5k
                ci->pinpolicy = b;
362
17.5k
                return (0);
363
17.4k
        case 28: /* pinComplexityPolicyUrl */
364
17.4k
                return (fido_blob_decode(val, &ci->pinpolicyurl));
365
17.4k
        case 29: /* maxPINLength */
366
17.4k
                return (cbor_decode_uint64(val, &ci->maxpinlen));
367
17.4k
        case 30: /* encCredStoreState */
368
17.4k
                return (fido_blob_decode(val, &ci->encstate));
369
17.1k
        case 31: /* authenticatorConfigCommands */
370
17.1k
                return (decode_byte_array(val, &ci->cfgcmds));
371
9.20k
        default: /* ignore */
372
9.20k
                fido_log_debug("%s: cbor type: 0x%02x", __func__, cbor_get_uint8(key));
373
9.20k
                return (0);
374
1.06M
        }
375
1.06M
}
376
377
static int
378
fido_dev_get_cbor_info_tx(fido_dev_t *dev, int *ms)
379
237k
{
380
237k
        const unsigned char cbor[] = { CTAP_CBOR_GETINFO };
381
382
237k
        fido_log_debug("%s: dev=%p", __func__, (void *)dev);
383
384
237k
        if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor), ms) < 0) {
385
2.64k
                fido_log_debug("%s: fido_tx", __func__);
386
2.64k
                return (FIDO_ERR_TX);
387
2.64k
        }
388
389
234k
        return (FIDO_OK);
390
237k
}
391
392
static int
393
fido_dev_get_cbor_info_rx(fido_dev_t *dev, fido_cbor_info_t *ci, int *ms)
394
234k
{
395
234k
        unsigned char   *msg;
396
234k
        int              msglen;
397
234k
        int              r;
398
399
234k
        fido_log_debug("%s: dev=%p, ci=%p, ms=%d", __func__, (void *)dev,
400
234k
            (void *)ci, *ms);
401
402
234k
        fido_cbor_info_reset(ci);
403
404
234k
        if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
405
596
                r = FIDO_ERR_INTERNAL;
406
596
                goto out;
407
596
        }
408
409
234k
        if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
410
54.9k
                fido_log_debug("%s: fido_rx", __func__);
411
54.9k
                r = FIDO_ERR_RX;
412
54.9k
                goto out;
413
54.9k
        }
414
415
179k
        r = cbor_parse_reply(msg, (size_t)msglen, ci, parse_reply_element);
416
234k
out:
417
234k
        freezero(msg, FIDO_MAXMSG);
418
419
234k
        return (r);
420
179k
}
421
422
int
423
fido_dev_get_cbor_info_wait(fido_dev_t *dev, fido_cbor_info_t *ci, int *ms)
424
237k
{
425
237k
        int r;
426
427
#ifdef USE_WINHELLO
428
        if (dev->flags & FIDO_DEV_WINHELLO)
429
                return (fido_winhello_get_cbor_info(dev, ci));
430
#endif
431
237k
        if ((r = fido_dev_get_cbor_info_tx(dev, ms)) != FIDO_OK ||
432
237k
            (r = fido_dev_get_cbor_info_rx(dev, ci, ms)) != FIDO_OK)
433
164k
                return (r);
434
435
73.1k
        return (FIDO_OK);
436
237k
}
437
438
int
439
fido_dev_get_cbor_info(fido_dev_t *dev, fido_cbor_info_t *ci)
440
5.05k
{
441
5.05k
        int ms = dev->timeout_ms;
442
443
5.05k
        return (fido_dev_get_cbor_info_wait(dev, ci, &ms));
444
5.05k
}
445
446
/*
447
 * get/set functions for fido_cbor_info_t; always at the end of the file
448
 */
449
450
fido_cbor_info_t *
451
fido_cbor_info_new(void)
452
238k
{
453
238k
        fido_cbor_info_t *ci;
454
455
238k
        if ((ci = calloc(1, sizeof(fido_cbor_info_t))) == NULL)
456
682
                return (NULL);
457
458
237k
        fido_cbor_info_reset(ci);
459
460
237k
        return (ci);
461
238k
}
462
463
void
464
fido_cbor_info_reset(fido_cbor_info_t *ci)
465
709k
{
466
709k
        fido_str_array_free(&ci->versions);
467
709k
        fido_str_array_free(&ci->extensions);
468
709k
        fido_str_array_free(&ci->transports);
469
709k
        fido_str_array_free(&ci->attfmts);
470
709k
        fido_str_array_free(&ci->rsttransports);
471
709k
        fido_opt_array_free(&ci->options);
472
709k
        fido_byte_array_free(&ci->protocols);
473
709k
        fido_byte_array_free(&ci->cfgcmds);
474
709k
        fido_algo_array_free(&ci->algorithms);
475
709k
        fido_cert_array_free(&ci->certs);
476
709k
        fido_blob_reset(&ci->encid);
477
709k
        fido_blob_reset(&ci->id);
478
709k
        fido_blob_reset(&ci->pinpolicyurl);
479
709k
        fido_blob_reset(&ci->encstate);
480
709k
        fido_blob_reset(&ci->state);
481
709k
        ci->rk_remaining = -1;
482
709k
        ci->uv_since_pin = -1;
483
709k
        ci->pinpolicy = -1;
484
709k
}
485
486
void
487
fido_cbor_info_free(fido_cbor_info_t **ci_p)
488
665k
{
489
665k
        fido_cbor_info_t *ci;
490
491
665k
        if (ci_p == NULL || (ci = *ci_p) ==  NULL)
492
428k
                return;
493
237k
        fido_cbor_info_reset(ci);
494
237k
        free(ci);
495
237k
        *ci_p = NULL;
496
237k
}
497
498
char **
499
fido_cbor_info_versions_ptr(const fido_cbor_info_t *ci)
500
8.53k
{
501
8.53k
        return (ci->versions.ptr);
502
8.53k
}
503
504
size_t
505
fido_cbor_info_versions_len(const fido_cbor_info_t *ci)
506
13.5k
{
507
13.5k
        return (ci->versions.len);
508
13.5k
}
509
510
char **
511
fido_cbor_info_extensions_ptr(const fido_cbor_info_t *ci)
512
81.3k
{
513
81.3k
        return (ci->extensions.ptr);
514
81.3k
}
515
516
size_t
517
fido_cbor_info_extensions_len(const fido_cbor_info_t *ci)
518
86.3k
{
519
86.3k
        return (ci->extensions.len);
520
86.3k
}
521
522
char **
523
fido_cbor_info_transports_ptr(const fido_cbor_info_t *ci)
524
4.19k
{
525
4.19k
        return (ci->transports.ptr);
526
4.19k
}
527
528
size_t
529
fido_cbor_info_transports_len(const fido_cbor_info_t *ci)
530
9.24k
{
531
9.24k
        return (ci->transports.len);
532
9.24k
}
533
534
const unsigned char *
535
fido_cbor_info_aaguid_ptr(const fido_cbor_info_t *ci)
536
5.05k
{
537
5.05k
        return (ci->aaguid);
538
5.05k
}
539
540
size_t
541
fido_cbor_info_aaguid_len(const fido_cbor_info_t *ci)
542
5.05k
{
543
5.05k
        return (sizeof(ci->aaguid));
544
5.05k
}
545
546
const unsigned char *
547
fido_cbor_info_encid_ptr(const fido_cbor_info_t *ci)
548
5.05k
{
549
5.05k
        return (ci->encid.ptr);
550
5.05k
}
551
552
size_t
553
fido_cbor_info_encid_len(const fido_cbor_info_t *ci)
554
5.05k
{
555
5.05k
        return (ci->encid.len);
556
5.05k
}
557
558
const unsigned char *
559
fido_cbor_info_id_ptr(const fido_cbor_info_t *ci)
560
5.05k
{
561
5.05k
        return (ci->id.ptr);
562
5.05k
}
563
564
size_t
565
fido_cbor_info_id_len(const fido_cbor_info_t *ci)
566
5.05k
{
567
5.05k
        return (ci->id.len);
568
5.05k
}
569
570
const unsigned char *
571
fido_cbor_info_encstate_ptr(const fido_cbor_info_t *ci)
572
5.05k
{
573
5.05k
        return (ci->encstate.ptr);
574
5.05k
}
575
576
size_t
577
fido_cbor_info_encstate_len(const fido_cbor_info_t *ci)
578
5.05k
{
579
5.05k
        return (ci->encstate.len);
580
5.05k
}
581
582
const unsigned char *
583
fido_cbor_info_state_ptr(const fido_cbor_info_t *ci)
584
5.05k
{
585
5.05k
        return (ci->state.ptr);
586
5.05k
}
587
588
size_t
589
fido_cbor_info_state_len(const fido_cbor_info_t *ci)
590
5.05k
{
591
5.05k
        return (ci->state.len);
592
5.05k
}
593
594
char **
595
fido_cbor_info_options_name_ptr(const fido_cbor_info_t *ci)
596
86.1k
{
597
86.1k
        return (ci->options.name);
598
86.1k
}
599
600
const bool *
601
fido_cbor_info_options_value_ptr(const fido_cbor_info_t *ci)
602
86.1k
{
603
86.1k
        return (ci->options.value);
604
86.1k
}
605
606
size_t
607
fido_cbor_info_options_len(const fido_cbor_info_t *ci)
608
91.1k
{
609
91.1k
        return (ci->options.len);
610
91.1k
}
611
612
uint64_t
613
fido_cbor_info_maxcredbloblen(const fido_cbor_info_t *ci)
614
5.05k
{
615
5.05k
        return (ci->maxcredbloblen);
616
5.05k
}
617
618
uint64_t
619
fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *ci)
620
77.1k
{
621
77.1k
        return (ci->maxmsgsiz);
622
77.1k
}
623
624
uint64_t
625
fido_cbor_info_maxcredcntlst(const fido_cbor_info_t *ci)
626
5.05k
{
627
5.05k
        return (ci->maxcredcntlst);
628
5.05k
}
629
630
uint64_t
631
fido_cbor_info_maxcredidlen(const fido_cbor_info_t *ci)
632
5.05k
{
633
5.05k
        return (ci->maxcredidlen);
634
5.05k
}
635
636
uint64_t
637
fido_cbor_info_maxlargeblob(const fido_cbor_info_t *ci)
638
5.05k
{
639
5.05k
        return (ci->maxlargeblob);
640
5.05k
}
641
642
uint64_t
643
fido_cbor_info_fwversion(const fido_cbor_info_t *ci)
644
5.05k
{
645
5.05k
        return (ci->fwversion);
646
5.05k
}
647
648
uint64_t
649
fido_cbor_info_minpinlen(const fido_cbor_info_t *ci)
650
5.05k
{
651
5.05k
        return (ci->minpinlen);
652
5.05k
}
653
654
uint64_t
655
fido_cbor_info_maxrpid_minpinlen(const fido_cbor_info_t *ci)
656
5.05k
{
657
5.05k
        return (ci->maxrpid_minlen);
658
5.05k
}
659
660
uint64_t
661
fido_cbor_info_uv_attempts(const fido_cbor_info_t *ci)
662
5.05k
{
663
5.05k
        return (ci->uv_attempts);
664
5.05k
}
665
666
int64_t
667
fido_cbor_info_uv_count_since_pin(const fido_cbor_info_t *ci)
668
5.05k
{
669
5.05k
        return (ci->uv_since_pin);
670
5.05k
}
671
672
uint64_t
673
fido_cbor_info_uv_modality(const fido_cbor_info_t *ci)
674
5.05k
{
675
5.05k
        return (ci->uv_modality);
676
5.05k
}
677
678
int64_t
679
fido_cbor_info_rk_remaining(const fido_cbor_info_t *ci)
680
5.05k
{
681
5.05k
        return (ci->rk_remaining);
682
5.05k
}
683
684
const uint8_t *
685
fido_cbor_info_protocols_ptr(const fido_cbor_info_t *ci)
686
77.1k
{
687
77.1k
        return (ci->protocols.ptr);
688
77.1k
}
689
690
size_t
691
fido_cbor_info_protocols_len(const fido_cbor_info_t *ci)
692
77.1k
{
693
77.1k
        return (ci->protocols.len);
694
77.1k
}
695
696
size_t
697
fido_cbor_info_algorithm_count(const fido_cbor_info_t *ci)
698
13.5k
{
699
13.5k
        return (ci->algorithms.len);
700
13.5k
}
701
702
const char *
703
fido_cbor_info_algorithm_type(const fido_cbor_info_t *ci, size_t idx)
704
8.48k
{
705
8.48k
        if (idx >= ci->algorithms.len)
706
5.05k
                return (NULL);
707
708
3.42k
        return (ci->algorithms.ptr[idx].type);
709
8.48k
}
710
711
int
712
fido_cbor_info_algorithm_cose(const fido_cbor_info_t *ci, size_t idx)
713
8.48k
{
714
8.48k
        if (idx >= ci->algorithms.len)
715
5.05k
                return (0);
716
717
3.42k
        return (ci->algorithms.ptr[idx].cose);
718
8.48k
}
719
720
bool
721
fido_cbor_info_new_pin_required(const fido_cbor_info_t *ci)
722
5.05k
{
723
5.05k
        return (ci->new_pin_reqd);
724
5.05k
}
725
726
bool
727
fido_cbor_info_long_touch_reset(const fido_cbor_info_t *ci)
728
5.05k
{
729
5.05k
        return (ci->long_reset);
730
5.05k
}
731
732
char **
733
fido_cbor_info_certs_name_ptr(const fido_cbor_info_t *ci)
734
475
{
735
475
        return (ci->certs.name);
736
475
}
737
738
const uint64_t *
739
fido_cbor_info_certs_value_ptr(const fido_cbor_info_t *ci)
740
475
{
741
475
        return (ci->certs.value);
742
475
}
743
744
size_t
745
fido_cbor_info_certs_len(const fido_cbor_info_t *ci)
746
5.52k
{
747
5.52k
        return (ci->certs.len);
748
5.52k
}
749
750
char **
751
fido_cbor_info_attfmts_ptr(const fido_cbor_info_t *ci)
752
808
{
753
808
        return (ci->attfmts.ptr);
754
808
}
755
756
size_t
757
fido_cbor_info_attfmts_len(const fido_cbor_info_t *ci)
758
5.86k
{
759
5.86k
        return (ci->attfmts.len);
760
5.86k
}
761
762
char **
763
fido_cbor_info_reset_transports_ptr(const fido_cbor_info_t *ci)
764
1.47k
{
765
1.47k
        return (ci->rsttransports.ptr);
766
1.47k
}
767
768
size_t
769
fido_cbor_info_reset_transports_len(const fido_cbor_info_t *ci)
770
6.52k
{
771
6.52k
        return (ci->rsttransports.len);
772
6.52k
}
773
774
int
775
fido_cbor_info_pin_policy(const fido_cbor_info_t *ci)
776
5.05k
{
777
5.05k
        return (ci->pinpolicy);
778
5.05k
}
779
780
const unsigned char*
781
fido_cbor_info_pin_policy_url_ptr(const fido_cbor_info_t *ci)
782
5.05k
{
783
5.05k
        return (ci->pinpolicyurl.ptr);
784
5.05k
}
785
786
size_t
787
fido_cbor_info_pin_policy_url_len(const fido_cbor_info_t *ci)
788
5.05k
{
789
5.05k
        return (ci->pinpolicyurl.len);
790
5.05k
}
791
792
uint64_t
793
fido_cbor_info_maxpinlen(const fido_cbor_info_t *ci)
794
5.05k
{
795
5.05k
        return (ci->maxpinlen);
796
5.05k
}
797
798
const uint8_t *
799
fido_cbor_info_cfgcmds_ptr(const fido_cbor_info_t *ci)
800
5.05k
{
801
5.05k
        return (ci->cfgcmds.ptr);
802
5.05k
}
803
804
size_t
805
fido_cbor_info_cfgcmds_len(const fido_cbor_info_t *ci)
806
5.05k
{
807
5.05k
        return (ci->cfgcmds.len);
808
5.05k
}
809
810
static int
811
decrypt(const fido_blob_t *secret, const char *info, const fido_blob_t *in,
812
    fido_blob_t *out)
813
1.40k
{
814
1.40k
        fido_blob_t key;
815
1.40k
        unsigned char keybuf[16];
816
1.40k
        int r = FIDO_ERR_INTERNAL;
817
818
1.40k
        key.ptr = keybuf;
819
1.40k
        key.len = sizeof(keybuf);
820
821
1.40k
        fido_blob_reset(out);
822
823
1.40k
        if (hkdf_sha256(key.ptr, key.len, info, secret) != 0) {
824
28
                fido_log_debug("%s: hkdf_sha256", __func__);
825
28
                goto fail;
826
28
        }
827
1.38k
        if (aes128_cbc_dec(&key, in, out) != 0) {
828
119
                fido_log_debug("%s: aes128_cbc_dec", __func__);
829
119
                goto fail;
830
119
        }
831
832
1.26k
        r = FIDO_OK;
833
1.40k
fail:
834
1.40k
        explicit_bzero(key.ptr, key.len);
835
836
1.40k
        return r;
837
1.26k
}
838
839
int
840
fido_cbor_info_decrypt(fido_cbor_info_t *ci, const unsigned char *ppuat,
841
    size_t ppuat_len)
842
5.05k
{
843
5.05k
        fido_blob_t secret;
844
5.05k
        int r;
845
846
5.05k
        memset(&secret, 0, sizeof(secret));
847
848
5.05k
        if (fido_blob_set(&secret, ppuat, ppuat_len) != 0) {
849
784
                fido_log_debug("%s: fido_blob_set", __func__);
850
784
                r = FIDO_ERR_INTERNAL;
851
784
                goto fail;
852
784
        }
853
854
4.27k
        if (!fido_blob_is_empty(&ci->encid) && (r = decrypt(&secret,
855
801
            "encIdentifier", &ci->encid, &ci->id)) != FIDO_OK) {
856
117
                fido_log_debug("%s: encIdentifier", __func__);
857
117
                goto fail;
858
117
        }
859
860
4.15k
        if (!fido_blob_is_empty(&ci->encstate) && (r = decrypt(&secret,
861
607
            "encCredStoreState", &ci->encstate, &ci->state)) != FIDO_OK) {
862
30
                fido_log_debug("%s: encIdentifier", __func__);
863
30
                goto fail;
864
30
        }
865
866
4.12k
        r = FIDO_OK;
867
5.05k
fail:
868
5.05k
        fido_blob_reset(&secret);
869
870
5.05k
        return r;
871
4.12k
}