Coverage Report

Created: 2026-04-08 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/libfido2/src/cbor.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2018-2025 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 <openssl/hmac.h>
9
#include <openssl/sha.h>
10
#include "fido.h"
11
12
static int
13
check_key_type(cbor_item_t *item)
14
4.25M
{
15
4.25M
        if (item->type == CBOR_TYPE_UINT || item->type == CBOR_TYPE_NEGINT ||
16
4.25M
            item->type == CBOR_TYPE_STRING)
17
4.25M
                return (0);
18
19
3.49k
        fido_log_debug("%s: invalid type: %d", __func__, item->type);
20
21
3.49k
        return (-1);
22
4.25M
}
23
24
/*
25
 * Validate CTAP2 canonical CBOR encoding rules for maps.
26
 */
27
static int
28
ctap_check_cbor(cbor_item_t *prev, cbor_item_t *curr)
29
2.13M
{
30
2.13M
        size_t  curr_len;
31
2.13M
        size_t  prev_len;
32
33
2.13M
        if (check_key_type(prev) < 0 || check_key_type(curr) < 0)
34
3.49k
                return (-1);
35
36
2.12M
        if (prev->type != curr->type) {
37
87.3k
                if (prev->type < curr->type)
38
81.7k
                        return (0);
39
5.61k
                fido_log_debug("%s: unsorted types", __func__);
40
5.61k
                return (-1);
41
87.3k
        }
42
43
2.03M
        if (curr->type == CBOR_TYPE_UINT || curr->type == CBOR_TYPE_NEGINT) {
44
1.24M
                if (cbor_int_get_width(curr) >= cbor_int_get_width(prev) &&
45
1.24M
                    cbor_get_int(curr) > cbor_get_int(prev))
46
1.23M
                        return (0);
47
1.24M
        } else {
48
798k
                curr_len = cbor_string_length(curr);
49
798k
                prev_len = cbor_string_length(prev);
50
51
798k
                if (curr_len > prev_len || (curr_len == prev_len &&
52
215k
                    memcmp(cbor_string_handle(prev), cbor_string_handle(curr),
53
214k
                    curr_len) < 0))
54
794k
                        return (0);
55
798k
        }
56
57
7.57k
        fido_log_debug("%s: invalid cbor", __func__);
58
59
7.57k
        return (-1);
60
2.03M
}
61
62
int
63
cbor_map_iter(const cbor_item_t *item, void *arg, int(*f)(const cbor_item_t *,
64
    const cbor_item_t *, void *))
65
536k
{
66
536k
        struct cbor_pair        *v;
67
536k
        size_t                   n;
68
69
536k
        if ((v = cbor_map_handle(item)) == NULL) {
70
1.36k
                fido_log_debug("%s: cbor_map_handle", __func__);
71
1.36k
                return (-1);
72
1.36k
        }
73
74
534k
        n = cbor_map_size(item);
75
76
3.14M
        for (size_t i = 0; i < n; i++) {
77
2.65M
                if (v[i].key == NULL || v[i].value == NULL) {
78
0
                        fido_log_debug("%s: key=%p, value=%p for i=%zu",
79
0
                            __func__, (void *)v[i].key, (void *)v[i].value, i);
80
0
                        return (-1);
81
0
                }
82
2.65M
                if (i && ctap_check_cbor(v[i - 1].key, v[i].key) < 0) {
83
16.6k
                        fido_log_debug("%s: ctap_check_cbor", __func__);
84
16.6k
                        return (-1);
85
16.6k
                }
86
2.63M
                if (f(v[i].key, v[i].value, arg) < 0) {
87
29.7k
                        fido_log_debug("%s: iterator < 0 on i=%zu", __func__,
88
29.7k
                            i);
89
29.7k
                        return (-1);
90
29.7k
                }
91
2.63M
        }
92
93
488k
        return (0);
94
534k
}
95
96
int
97
cbor_array_iter(const cbor_item_t *item, void *arg, int(*f)(const cbor_item_t *,
98
    void *))
99
395k
{
100
395k
        cbor_item_t     **v;
101
395k
        size_t            n;
102
103
395k
        if ((v = cbor_array_handle(item)) == NULL) {
104
120
                fido_log_debug("%s: cbor_array_handle", __func__);
105
120
                return (-1);
106
120
        }
107
108
395k
        n = cbor_array_size(item);
109
110
1.45M
        for (size_t i = 0; i < n; i++)
111
1.06M
                if (v[i] == NULL || f(v[i], arg) < 0) {
112
5.31k
                        fido_log_debug("%s: iterator < 0 on i=%zu,%p",
113
5.31k
                            __func__, i, (void *)v[i]);
114
5.31k
                        return (-1);
115
5.31k
                }
116
117
390k
        return (0);
118
395k
}
119
120
int
121
cbor_parse_reply(const unsigned char *blob, size_t blob_len, void *arg,
122
    int(*parser)(const cbor_item_t *, const cbor_item_t *, void *))
123
273k
{
124
273k
        cbor_item_t             *item = NULL;
125
273k
        struct cbor_load_result  cbor;
126
273k
        int                      r;
127
128
273k
        if (blob_len < 1) {
129
77.2k
                fido_log_debug("%s: blob_len=%zu", __func__, blob_len);
130
77.2k
                r = FIDO_ERR_RX;
131
77.2k
                goto fail;
132
77.2k
        }
133
134
195k
        if (blob[0] != FIDO_OK) {
135
11.6k
                fido_log_debug("%s: blob[0]=0x%02x", __func__, blob[0]);
136
11.6k
                r = blob[0];
137
11.6k
                goto fail;
138
11.6k
        }
139
140
184k
        if ((item = cbor_load(blob + 1, blob_len - 1, &cbor)) == NULL) {
141
7.91k
                fido_log_debug("%s: cbor_load", __func__);
142
7.91k
                r = FIDO_ERR_RX_NOT_CBOR;
143
7.91k
                goto fail;
144
7.91k
        }
145
146
176k
        if (cbor_isa_map(item) == false ||
147
176k
            cbor_map_is_definite(item) == false) {
148
5.31k
                fido_log_debug("%s: cbor type", __func__);
149
5.31k
                r = FIDO_ERR_RX_INVALID_CBOR;
150
5.31k
                goto fail;
151
5.31k
        }
152
153
171k
        if (cbor_map_iter(item, arg, parser) < 0) {
154
23.9k
                fido_log_debug("%s: cbor_map_iter", __func__);
155
23.9k
                r = FIDO_ERR_RX_INVALID_CBOR;
156
23.9k
                goto fail;
157
23.9k
        }
158
159
147k
        r = FIDO_OK;
160
273k
fail:
161
273k
        if (item != NULL)
162
176k
                cbor_decref(&item);
163
164
273k
        return (r);
165
147k
}
166
167
void
168
cbor_vector_free(cbor_item_t **item, size_t len)
169
378k
{
170
1.74M
        for (size_t i = 0; i < len; i++)
171
1.37M
                if (item[i] != NULL)
172
606k
                        cbor_decref(&item[i]);
173
378k
}
174
175
int
176
cbor_bytestring_copy(const cbor_item_t *item, unsigned char **buf, size_t *len)
177
177k
{
178
177k
        if (*buf != NULL || *len != 0) {
179
0
                fido_log_debug("%s: dup", __func__);
180
0
                return (-1);
181
0
        }
182
183
177k
        if (cbor_isa_bytestring(item) == false ||
184
177k
            cbor_bytestring_is_definite(item) == false) {
185
558
                fido_log_debug("%s: cbor type", __func__);
186
558
                return (-1);
187
558
        }
188
189
176k
        *len = cbor_bytestring_length(item);
190
176k
        if ((*buf = malloc(*len)) == NULL) {
191
558
                *len = 0;
192
558
                return (-1);
193
558
        }
194
195
175k
        memcpy(*buf, cbor_bytestring_handle(item), *len);
196
197
175k
        return (0);
198
176k
}
199
200
int
201
cbor_string_copy(const cbor_item_t *item, char **str)
202
1.86M
{
203
1.86M
        size_t len;
204
205
1.86M
        if (*str != NULL) {
206
1
                fido_log_debug("%s: dup", __func__);
207
1
                return (-1);
208
1
        }
209
210
1.86M
        if (cbor_isa_string(item) == false ||
211
1.86M
            cbor_string_is_definite(item) == false) {
212
9.21k
                fido_log_debug("%s: cbor type", __func__);
213
9.21k
                return (-1);
214
9.21k
        }
215
216
1.85M
        if ((len = cbor_string_length(item)) == SIZE_MAX ||
217
1.85M
            (*str = malloc(len + 1)) == NULL)
218
3.93k
                return (-1);
219
220
1.84M
        memcpy(*str, cbor_string_handle(item), len);
221
1.84M
        (*str)[len] = '\0';
222
223
1.84M
        return (0);
224
1.85M
}
225
226
int
227
cbor_add_bytestring(cbor_item_t *item, const char *key,
228
    const unsigned char *value, size_t value_len)
229
298k
{
230
298k
        struct cbor_pair pair;
231
298k
        int ok = -1;
232
233
298k
        memset(&pair, 0, sizeof(pair));
234
235
298k
        if ((pair.key = cbor_build_string(key)) == NULL ||
236
298k
            (pair.value = cbor_build_bytestring(value, value_len)) == NULL) {
237
540
                fido_log_debug("%s: cbor_build", __func__);
238
540
                goto fail;
239
540
        }
240
241
298k
        if (!cbor_map_add(item, pair)) {
242
294
                fido_log_debug("%s: cbor_map_add", __func__);
243
294
                goto fail;
244
294
        }
245
246
298k
        ok = 0;
247
298k
fail:
248
298k
        if (pair.key)
249
298k
                cbor_decref(&pair.key);
250
298k
        if (pair.value)
251
298k
                cbor_decref(&pair.value);
252
253
298k
        return (ok);
254
298k
}
255
256
int
257
cbor_add_string(cbor_item_t *item, const char *key, const char *value)
258
332k
{
259
332k
        struct cbor_pair pair;
260
332k
        int ok = -1;
261
262
332k
        memset(&pair, 0, sizeof(pair));
263
264
332k
        if ((pair.key = cbor_build_string(key)) == NULL ||
265
332k
            (pair.value = cbor_build_string(value)) == NULL) {
266
642
                fido_log_debug("%s: cbor_build", __func__);
267
642
                goto fail;
268
642
        }
269
270
332k
        if (!cbor_map_add(item, pair)) {
271
229
                fido_log_debug("%s: cbor_map_add", __func__);
272
229
                goto fail;
273
229
        }
274
275
331k
        ok = 0;
276
332k
fail:
277
332k
        if (pair.key)
278
332k
                cbor_decref(&pair.key);
279
332k
        if (pair.value)
280
332k
                cbor_decref(&pair.value);
281
282
332k
        return (ok);
283
331k
}
284
285
int
286
cbor_add_bool(cbor_item_t *item, const char *key, fido_opt_t value)
287
11.3k
{
288
11.3k
        struct cbor_pair pair;
289
11.3k
        int ok = -1;
290
291
11.3k
        memset(&pair, 0, sizeof(pair));
292
293
11.3k
        if ((pair.key = cbor_build_string(key)) == NULL ||
294
11.3k
            (pair.value = cbor_build_bool(value == FIDO_OPT_TRUE)) == NULL) {
295
79
                fido_log_debug("%s: cbor_build", __func__);
296
79
                goto fail;
297
79
        }
298
299
11.2k
        if (!cbor_map_add(item, pair)) {
300
25
                fido_log_debug("%s: cbor_map_add", __func__);
301
25
                goto fail;
302
25
        }
303
304
11.2k
        ok = 0;
305
11.3k
fail:
306
11.3k
        if (pair.key)
307
11.3k
                cbor_decref(&pair.key);
308
11.3k
        if (pair.value)
309
11.2k
                cbor_decref(&pair.value);
310
311
11.3k
        return (ok);
312
11.2k
}
313
314
static int
315
cbor_add_uint8(cbor_item_t *item, const char *key, uint8_t value)
316
2.46k
{
317
2.46k
        struct cbor_pair pair;
318
2.46k
        int ok = -1;
319
320
2.46k
        memset(&pair, 0, sizeof(pair));
321
322
2.46k
        if ((pair.key = cbor_build_string(key)) == NULL ||
323
2.46k
            (pair.value = cbor_build_uint8(value)) == NULL) {
324
16
                fido_log_debug("%s: cbor_build", __func__);
325
16
                goto fail;
326
16
        }
327
328
2.44k
        if (!cbor_map_add(item, pair)) {
329
7
                fido_log_debug("%s: cbor_map_add", __func__);
330
7
                goto fail;
331
7
        }
332
333
2.43k
        ok = 0;
334
2.46k
fail:
335
2.46k
        if (pair.key)
336
2.45k
                cbor_decref(&pair.key);
337
2.46k
        if (pair.value)
338
2.44k
                cbor_decref(&pair.value);
339
340
2.46k
        return (ok);
341
2.43k
}
342
343
static int
344
cbor_add_arg(cbor_item_t *item, uint8_t n, cbor_item_t *arg)
345
703k
{
346
703k
        struct cbor_pair pair;
347
703k
        int ok = -1;
348
349
703k
        memset(&pair, 0, sizeof(pair));
350
351
703k
        if (arg == NULL)
352
250k
                return (0); /* empty argument */
353
354
453k
        if ((pair.key = cbor_build_uint8(n)) == NULL) {
355
1.23k
                fido_log_debug("%s: cbor_build", __func__);
356
1.23k
                goto fail;
357
1.23k
        }
358
359
452k
        pair.value = arg;
360
361
452k
        if (!cbor_map_add(item, pair)) {
362
1.00k
                fido_log_debug("%s: cbor_map_add", __func__);
363
1.00k
                goto fail;
364
1.00k
        }
365
366
451k
        ok = 0;
367
453k
fail:
368
453k
        if (pair.key)
369
452k
                cbor_decref(&pair.key);
370
371
453k
        return (ok);
372
451k
}
373
374
cbor_item_t *
375
cbor_flatten_vector(cbor_item_t *argv[], size_t argc)
376
205k
{
377
205k
        cbor_item_t     *map;
378
205k
        uint8_t          i;
379
380
205k
        if (argc > UINT8_MAX - 1)
381
0
                return (NULL);
382
383
205k
        if ((map = cbor_new_definite_map(argc)) == NULL)
384
393
                return (NULL);
385
386
906k
        for (i = 0; i < argc; i++)
387
703k
                if (cbor_add_arg(map, (uint8_t)(i + 1), argv[i]) < 0)
388
2.23k
                        break;
389
390
205k
        if (i != argc) {
391
2.23k
                cbor_decref(&map);
392
2.23k
                map = NULL;
393
2.23k
        }
394
395
205k
        return (map);
396
205k
}
397
398
int
399
cbor_build_frame(uint8_t cmd, cbor_item_t *argv[], size_t argc, fido_blob_t *f)
400
154k
{
401
154k
        cbor_item_t     *flat = NULL;
402
154k
        unsigned char   *cbor = NULL;
403
154k
        size_t           cbor_len;
404
154k
        size_t           cbor_alloc_len;
405
154k
        int              ok = -1;
406
407
154k
        if ((flat = cbor_flatten_vector(argv, argc)) == NULL)
408
2.01k
                goto fail;
409
410
152k
        cbor_len = cbor_serialize_alloc(flat, &cbor, &cbor_alloc_len);
411
152k
        if (cbor_len == 0 || cbor_len == SIZE_MAX) {
412
426
                fido_log_debug("%s: cbor_len=%zu", __func__, cbor_len);
413
426
                goto fail;
414
426
        }
415
416
151k
        if ((f->ptr = malloc(cbor_len + 1)) == NULL)
417
291
                goto fail;
418
419
151k
        f->len = cbor_len + 1;
420
151k
        f->ptr[0] = cmd;
421
151k
        memcpy(f->ptr + 1, cbor, f->len - 1);
422
423
151k
        ok = 0;
424
154k
fail:
425
154k
        if (flat != NULL)
426
152k
                cbor_decref(&flat);
427
428
154k
        free(cbor);
429
430
154k
        return (ok);
431
151k
}
432
433
cbor_item_t *
434
cbor_encode_rp_entity(const fido_rp_t *rp)
435
8.27k
{
436
8.27k
        cbor_item_t *item = NULL;
437
438
8.27k
        if ((item = cbor_new_definite_map(2)) == NULL)
439
18
                return (NULL);
440
441
8.25k
        if ((rp->id && cbor_add_string(item, "id", rp->id) < 0) ||
442
8.25k
            (rp->name && cbor_add_string(item, "name", rp->name) < 0)) {
443
40
                cbor_decref(&item);
444
40
                return (NULL);
445
40
        }
446
447
8.21k
        return (item);
448
8.25k
}
449
450
cbor_item_t *
451
cbor_encode_user_entity(const fido_user_t *user)
452
11.0k
{
453
11.0k
        cbor_item_t             *item = NULL;
454
11.0k
        const fido_blob_t       *id = &user->id;
455
11.0k
        const char              *display = user->display_name;
456
457
11.0k
        if ((item = cbor_new_definite_map(4)) == NULL)
458
25
                return (NULL);
459
460
11.0k
        if ((id->ptr && cbor_add_bytestring(item, "id", id->ptr, id->len) < 0) ||
461
11.0k
            (user->icon && cbor_add_string(item, "icon", user->icon) < 0) ||
462
11.0k
            (user->name && cbor_add_string(item, "name", user->name) < 0) ||
463
11.0k
            (display && cbor_add_string(item, "displayName", display) < 0)) {
464
194
                cbor_decref(&item);
465
194
                return (NULL);
466
194
        }
467
468
10.8k
        return (item);
469
11.0k
}
470
471
cbor_item_t *
472
cbor_encode_pubkey_param(int cose_alg)
473
8.06k
{
474
8.06k
        cbor_item_t             *item = NULL;
475
8.06k
        cbor_item_t             *body = NULL;
476
8.06k
        struct cbor_pair         alg;
477
8.06k
        int                      ok = -1;
478
479
8.06k
        memset(&alg, 0, sizeof(alg));
480
481
8.06k
        if ((item = cbor_new_definite_array(1)) == NULL ||
482
8.06k
            (body = cbor_new_definite_map(2)) == NULL ||
483
8.06k
            cose_alg > -1 || cose_alg < INT16_MIN)
484
37
                goto fail;
485
486
8.02k
        alg.key = cbor_build_string("alg");
487
488
8.02k
        if (-cose_alg - 1 > UINT8_MAX)
489
1.20k
                alg.value = cbor_build_negint16((uint16_t)(-cose_alg - 1));
490
6.82k
        else
491
6.82k
                alg.value = cbor_build_negint8((uint8_t)(-cose_alg - 1));
492
493
8.02k
        if (alg.key == NULL || alg.value == NULL) {
494
36
                fido_log_debug("%s: cbor_build", __func__);
495
36
                goto fail;
496
36
        }
497
498
7.98k
        if (cbor_map_add(body, alg) == false ||
499
7.98k
            cbor_add_string(body, "type", "public-key") < 0 ||
500
7.98k
            cbor_array_push(item, body) == false)
501
108
                goto fail;
502
503
7.87k
        ok  = 0;
504
8.06k
fail:
505
8.06k
        if (ok < 0) {
506
181
                if (item != NULL) {
507
159
                        cbor_decref(&item);
508
159
                        item = NULL;
509
159
                }
510
181
        }
511
512
8.06k
        if (body != NULL)
513
8.02k
                cbor_decref(&body);
514
8.06k
        if (alg.key != NULL)
515
8.00k
                cbor_decref(&alg.key);
516
8.06k
        if (alg.value != NULL)
517
8.00k
                cbor_decref(&alg.value);
518
519
8.06k
        return (item);
520
7.87k
}
521
522
cbor_item_t *
523
cbor_encode_pubkey(const fido_blob_t *pubkey)
524
286k
{
525
286k
        cbor_item_t *cbor_key = NULL;
526
527
286k
        if ((cbor_key = cbor_new_definite_map(2)) == NULL ||
528
286k
            cbor_add_bytestring(cbor_key, "id", pubkey->ptr, pubkey->len) < 0 ||
529
286k
            cbor_add_string(cbor_key, "type", "public-key") < 0) {
530
1.65k
                if (cbor_key)
531
1.42k
                        cbor_decref(&cbor_key);
532
1.65k
                return (NULL);
533
1.65k
        }
534
535
285k
        return (cbor_key);
536
286k
}
537
538
cbor_item_t *
539
cbor_encode_pubkey_list(const fido_blob_array_t *list)
540
7.80k
{
541
7.80k
        cbor_item_t     *array = NULL;
542
7.80k
        cbor_item_t     *key = NULL;
543
544
7.80k
        if ((array = cbor_new_definite_array(list->len)) == NULL)
545
4
                goto fail;
546
547
287k
        for (size_t i = 0; i < list->len; i++) {
548
281k
                if ((key = cbor_encode_pubkey(&list->ptr[i])) == NULL ||
549
281k
                    cbor_array_push(array, key) == false)
550
1.72k
                        goto fail;
551
279k
                cbor_decref(&key);
552
279k
        }
553
554
6.07k
        return (array);
555
1.72k
fail:
556
1.72k
        if (key != NULL)
557
218
                cbor_decref(&key);
558
1.72k
        if (array != NULL)
559
1.72k
                cbor_decref(&array);
560
561
1.72k
        return (NULL);
562
7.80k
}
563
564
cbor_item_t *
565
cbor_encode_str_array(const fido_str_array_t *a)
566
12.7k
{
567
12.7k
        cbor_item_t     *array = NULL;
568
12.7k
        cbor_item_t     *entry = NULL;
569
570
12.7k
        if ((array = cbor_new_definite_array(a->len)) == NULL)
571
19
                goto fail;
572
573
349k
        for (size_t i = 0; i < a->len; i++) {
574
338k
                if ((entry = cbor_build_string(a->ptr[i])) == NULL ||
575
338k
                    cbor_array_push(array, entry) == false)
576
1.73k
                        goto fail;
577
337k
                cbor_decref(&entry);
578
337k
        }
579
580
11.0k
        return (array);
581
1.75k
fail:
582
1.75k
        if (entry != NULL)
583
907
                cbor_decref(&entry);
584
1.75k
        if (array != NULL)
585
1.73k
                cbor_decref(&array);
586
587
1.75k
        return (NULL);
588
12.7k
}
589
590
static int
591
cbor_encode_largeblob_key_ext(cbor_item_t *map)
592
2.54k
{
593
2.54k
        if (map == NULL ||
594
2.54k
            cbor_add_bool(map, "largeBlobKey", FIDO_OPT_TRUE) < 0)
595
7
                return (-1);
596
597
2.54k
        return (0);
598
2.54k
}
599
600
static int
601
cbor_encode_hmac_secret_param(const char *key, const fido_dev_t *dev,
602
    cbor_item_t *item, const fido_blob_t *ecdh, const es256_pk_t *pk,
603
    const fido_blob_t *salt)
604
2.06k
{
605
2.06k
        cbor_item_t             *param = NULL;
606
2.06k
        cbor_item_t             *argv[4];
607
2.06k
        struct cbor_pair         pair;
608
2.06k
        fido_blob_t             *enc = NULL;
609
2.06k
        uint8_t                  prot;
610
2.06k
        int                      r;
611
612
2.06k
        memset(argv, 0, sizeof(argv));
613
2.06k
        memset(&pair, 0, sizeof(pair));
614
615
2.06k
        if (item == NULL || ecdh == NULL || pk == NULL || salt->ptr == NULL) {
616
1.34k
                fido_log_debug("%s: ecdh=%p, pk=%p, salt->ptr=%p", __func__,
617
1.34k
                    (const void *)ecdh, (const void *)pk,
618
1.34k
                    (const void *)salt->ptr);
619
1.34k
                r = FIDO_ERR_INTERNAL;
620
1.34k
                goto fail;
621
1.34k
        }
622
623
720
        if (salt->len != 32 && salt->len != 64) {
624
0
                fido_log_debug("%s: salt->len=%zu", __func__, salt->len);
625
0
                r = FIDO_ERR_INTERNAL;
626
0
                goto fail;
627
0
        }
628
629
720
        if ((enc = fido_blob_new()) == NULL ||
630
720
            aes256_cbc_enc(dev, ecdh, salt, enc) < 0) {
631
11
                fido_log_debug("%s: aes256_cbc_enc", __func__);
632
11
                r = FIDO_ERR_INTERNAL;
633
11
                goto fail;
634
11
        }
635
636
709
        if ((prot = fido_dev_get_pin_protocol(dev)) == 0) {
637
0
                fido_log_debug("%s: fido_dev_get_pin_protocol", __func__);
638
0
                r = FIDO_ERR_INTERNAL;
639
0
                goto fail;
640
0
        }
641
642
        /* XXX not pin, but salt */
643
709
        if ((argv[0] = es256_pk_encode(pk, 1)) == NULL ||
644
709
            (argv[1] = fido_blob_encode(enc)) == NULL ||
645
709
            (argv[2] = cbor_encode_pin_auth(dev, ecdh, enc)) == NULL ||
646
709
            (prot != 1 && (argv[3] = cbor_build_uint8(prot)) == NULL)) {
647
55
                fido_log_debug("%s: cbor encode", __func__);
648
55
                r = FIDO_ERR_INTERNAL;
649
55
                goto fail;
650
55
        }
651
652
654
        if ((param = cbor_flatten_vector(argv, nitems(argv))) == NULL) {
653
33
                fido_log_debug("%s: cbor_flatten_vector", __func__);
654
33
                r = FIDO_ERR_INTERNAL;
655
33
                goto fail;
656
33
        }
657
658
621
        if ((pair.key = cbor_build_string(key)) == NULL) {
659
12
                fido_log_debug("%s: cbor_build", __func__);
660
12
                r = FIDO_ERR_INTERNAL;
661
12
                goto fail;
662
12
        }
663
664
609
        pair.value = param;
665
666
609
        if (!cbor_map_add(item, pair)) {
667
43
                fido_log_debug("%s: cbor_map_add", __func__);
668
43
                r = FIDO_ERR_INTERNAL;
669
43
                goto fail;
670
43
        }
671
672
566
        r = FIDO_OK;
673
674
2.06k
fail:
675
2.06k
        cbor_vector_free(argv, nitems(argv));
676
677
2.06k
        if (param != NULL)
678
621
                cbor_decref(&param);
679
2.06k
        if (pair.key != NULL)
680
609
                cbor_decref(&pair.key);
681
682
2.06k
        fido_blob_free(&enc);
683
684
2.06k
        return (r);
685
566
}
686
687
cbor_item_t *
688
cbor_encode_cred_ext(const fido_dev_t *dev, const fido_cred_extin_t *ext,
689
    const fido_blob_t *ecdh, const es256_pk_t *pk)
690
4.08k
{
691
4.08k
        cbor_item_t *item = NULL;
692
4.08k
        size_t size = 0;
693
694
4.08k
        if (ext->attr.mask & FIDO_EXT_CRED_BLOB)
695
1.55k
                size++;
696
4.08k
        if (ext->attr.mask & FIDO_EXT_HMAC_SECRET)
697
1.73k
                size++;
698
4.08k
        if (ext->attr.mask & FIDO_EXT_CRED_PROTECT)
699
2.47k
                size++;
700
4.08k
        if (ext->attr.mask & FIDO_EXT_LARGEBLOB_KEY)
701
1.34k
                size++;
702
4.08k
        if (ext->attr.mask & FIDO_EXT_MINPINLEN)
703
1.05k
                size++;
704
4.08k
        if (ext->attr.mask & FIDO_EXT_HMAC_SECRET_MC)
705
1.19k
                size++;
706
4.08k
        if (ext->attr.mask & FIDO_EXT_PAYMENT)
707
1.59k
                size++;
708
709
4.08k
        if (size == 0 || (item = cbor_new_definite_map(size)) == NULL)
710
4
                return (NULL);
711
712
4.07k
        if (ext->attr.mask & FIDO_EXT_CRED_BLOB) {
713
1.55k
                if (cbor_add_bytestring(item, "credBlob", ext->blob.ptr,
714
1.55k
                    ext->blob.len) < 0) {
715
9
                        cbor_decref(&item);
716
9
                        return (NULL);
717
9
                }
718
1.55k
        }
719
4.06k
        if (ext->attr.mask & FIDO_EXT_CRED_PROTECT) {
720
2.46k
                if (ext->attr.prot < 0 || ext->attr.prot > UINT8_MAX ||
721
2.46k
                    cbor_add_uint8(item, "credProtect",
722
2.46k
                    (uint8_t)ext->attr.prot) < 0) {
723
23
                        cbor_decref(&item);
724
23
                        return (NULL);
725
23
                }
726
2.46k
        }
727
4.04k
        if (ext->attr.mask & FIDO_EXT_HMAC_SECRET) {
728
1.72k
                if (cbor_add_bool(item, "hmac-secret", FIDO_OPT_TRUE) < 0) {
729
27
                        cbor_decref(&item);
730
27
                        return (NULL);
731
27
                }
732
1.72k
        }
733
4.01k
        if (ext->attr.mask & FIDO_EXT_LARGEBLOB_KEY) {
734
1.31k
                if (cbor_encode_largeblob_key_ext(item) < 0) {
735
4
                        cbor_decref(&item);
736
4
                        return (NULL);
737
4
                }
738
1.31k
        }
739
4.01k
        if (ext->attr.mask & FIDO_EXT_MINPINLEN) {
740
1.03k
                if (cbor_add_bool(item, "minPinLength", FIDO_OPT_TRUE) < 0) {
741
9
                        cbor_decref(&item);
742
9
                        return (NULL);
743
9
                }
744
1.03k
        }
745
4.00k
        if (ext->attr.mask & FIDO_EXT_HMAC_SECRET_MC) {
746
1.16k
                if (cbor_encode_hmac_secret_param("hmac-secret-mc", dev, item,
747
1.16k
                    ecdh, pk, &ext->hmac_salt) < 0) {
748
1.10k
                        cbor_decref(&item);
749
1.10k
                        return (NULL);
750
1.10k
                }
751
1.16k
        }
752
2.90k
        if (ext->attr.mask & FIDO_EXT_PAYMENT) {
753
794
                if (cbor_add_bool(item, "thirdPartyPayment",
754
794
                    FIDO_OPT_TRUE) < 0) {
755
12
                        cbor_decref(&item);
756
12
                        return (NULL);
757
12
                }
758
794
        }
759
760
2.88k
        return (item);
761
2.90k
}
762
763
cbor_item_t *
764
cbor_encode_cred_opt(fido_opt_t rk, fido_opt_t uv)
765
874
{
766
874
        cbor_item_t *item = NULL;
767
768
874
        if ((item = cbor_new_definite_map(2)) == NULL)
769
5
                return (NULL);
770
869
        if ((rk != FIDO_OPT_OMIT && cbor_add_bool(item, "rk", rk) < 0) ||
771
869
            (uv != FIDO_OPT_OMIT && cbor_add_bool(item, "uv", uv) < 0)) {
772
5
                cbor_decref(&item);
773
5
                return (NULL);
774
5
        }
775
776
864
        return (item);
777
869
}
778
779
cbor_item_t *
780
cbor_encode_assert_opt(fido_opt_t up, fido_opt_t uv)
781
1.17k
{
782
1.17k
        cbor_item_t *item = NULL;
783
784
1.17k
        if ((item = cbor_new_definite_map(2)) == NULL)
785
4
                return (NULL);
786
1.17k
        if ((up != FIDO_OPT_OMIT && cbor_add_bool(item, "up", up) < 0) ||
787
1.17k
            (uv != FIDO_OPT_OMIT && cbor_add_bool(item, "uv", uv) < 0)) {
788
8
                cbor_decref(&item);
789
8
                return (NULL);
790
8
        }
791
792
1.16k
        return (item);
793
1.17k
}
794
795
cbor_item_t *
796
cbor_encode_pin_auth(const fido_dev_t *dev, const fido_blob_t *secret,
797
    const fido_blob_t *data)
798
14.3k
{
799
14.3k
        const EVP_MD    *md = NULL;
800
14.3k
        unsigned char    dgst[SHA256_DIGEST_LENGTH];
801
14.3k
        unsigned int     dgst_len;
802
14.3k
        size_t           outlen;
803
14.3k
        uint8_t          prot;
804
14.3k
        fido_blob_t      key;
805
806
14.3k
        key.ptr = secret->ptr;
807
14.3k
        key.len = secret->len;
808
809
14.3k
        if ((prot = fido_dev_get_pin_protocol(dev)) == 0) {
810
0
                fido_log_debug("%s: fido_dev_get_pin_protocol", __func__);
811
0
                return (NULL);
812
0
        }
813
814
        /* select hmac portion of the shared secret */
815
14.3k
        if (prot == CTAP_PIN_PROTOCOL2 && key.len > 32)
816
741
                key.len = 32;
817
818
14.3k
        if ((md = EVP_sha256()) == NULL || HMAC(md, key.ptr,
819
14.2k
            (int)key.len, data->ptr, data->len, dgst,
820
14.2k
            &dgst_len) == NULL || dgst_len != SHA256_DIGEST_LENGTH)
821
230
                return (NULL);
822
823
14.1k
        outlen = (prot == CTAP_PIN_PROTOCOL1) ? 16 : dgst_len;
824
825
14.1k
        return (cbor_build_bytestring(dgst, outlen));
826
14.3k
}
827
828
cbor_item_t *
829
cbor_encode_pin_opt(const fido_dev_t *dev)
830
146k
{
831
146k
        uint8_t     prot;
832
833
146k
        if ((prot = fido_dev_get_pin_protocol(dev)) == 0) {
834
52.9k
                fido_log_debug("%s: fido_dev_get_pin_protocol", __func__);
835
52.9k
                return (NULL);
836
52.9k
        }
837
838
93.6k
        return (cbor_build_uint8(prot));
839
146k
}
840
841
cbor_item_t *
842
cbor_encode_change_pin_auth(const fido_dev_t *dev, const fido_blob_t *secret,
843
    const fido_blob_t *new_pin_enc, const fido_blob_t *pin_hash_enc)
844
315
{
845
315
        unsigned char    dgst[SHA256_DIGEST_LENGTH];
846
315
        unsigned int     dgst_len;
847
315
        cbor_item_t     *item = NULL;
848
315
        const EVP_MD    *md = NULL;
849
315
        HMAC_CTX        *ctx = NULL;
850
315
        fido_blob_t      key;
851
315
        uint8_t          prot;
852
315
        size_t           outlen;
853
854
315
        key.ptr = secret->ptr;
855
315
        key.len = secret->len;
856
857
315
        if ((prot = fido_dev_get_pin_protocol(dev)) == 0) {
858
0
                fido_log_debug("%s: fido_dev_get_pin_protocol", __func__);
859
0
                goto fail;
860
0
        }
861
862
315
        if (prot == CTAP_PIN_PROTOCOL2 && key.len > 32)
863
285
                key.len = 32;
864
865
315
        if ((ctx = HMAC_CTX_new()) == NULL ||
866
315
            (md = EVP_sha256())  == NULL ||
867
315
            HMAC_Init_ex(ctx, key.ptr, (int)key.len, md, NULL) == 0 ||
868
315
            HMAC_Update(ctx, new_pin_enc->ptr, new_pin_enc->len) == 0 ||
869
315
            HMAC_Update(ctx, pin_hash_enc->ptr, pin_hash_enc->len) == 0 ||
870
315
            HMAC_Final(ctx, dgst, &dgst_len) == 0 ||
871
315
            dgst_len != SHA256_DIGEST_LENGTH) {
872
44
                fido_log_debug("%s: HMAC", __func__);
873
44
                goto fail;
874
44
        }
875
876
271
        outlen = (prot == CTAP_PIN_PROTOCOL1) ? 16 : dgst_len;
877
878
271
        if ((item = cbor_build_bytestring(dgst, outlen)) == NULL) {
879
7
                fido_log_debug("%s: cbor_build_bytestring", __func__);
880
7
                goto fail;
881
7
        }
882
883
315
fail:
884
315
        HMAC_CTX_free(ctx);
885
886
315
        return (item);
887
271
}
888
889
cbor_item_t *
890
cbor_encode_assert_ext(fido_dev_t *dev, const fido_assert_ext_t *ext,
891
    const fido_blob_t *ecdh, const es256_pk_t *pk)
892
3.07k
{
893
3.07k
        cbor_item_t *item = NULL;
894
3.07k
        size_t size = 0;
895
896
3.07k
        if (ext->mask & FIDO_EXT_CRED_BLOB)
897
1.69k
                size++;
898
3.07k
        if (ext->mask & FIDO_EXT_HMAC_SECRET)
899
908
                size++;
900
3.07k
        if (ext->mask & FIDO_EXT_LARGEBLOB_KEY)
901
1.42k
                size++;
902
3.07k
        if (ext->mask & FIDO_EXT_PAYMENT)
903
1.51k
                size++;
904
3.07k
        if (size == 0 || (item = cbor_new_definite_map(size)) == NULL)
905
5
                return (NULL);
906
907
3.07k
        if (ext->mask & FIDO_EXT_CRED_BLOB) {
908
1.68k
                if (cbor_add_bool(item, "credBlob", FIDO_OPT_TRUE) < 0) {
909
24
                        cbor_decref(&item);
910
24
                        return (NULL);
911
24
                }
912
1.68k
        }
913
3.05k
        if (ext->mask & FIDO_EXT_HMAC_SECRET) {
914
901
                if (cbor_encode_hmac_secret_param("hmac-secret", dev, item,
915
901
                    ecdh, pk, &ext->hmac_salt) < 0) {
916
391
                        cbor_decref(&item);
917
391
                        return (NULL);
918
391
                }
919
901
        }
920
2.65k
        if (ext->mask & FIDO_EXT_LARGEBLOB_KEY) {
921
1.23k
                if (cbor_encode_largeblob_key_ext(item) < 0) {
922
3
                        cbor_decref(&item);
923
3
                        return (NULL);
924
3
                }
925
1.23k
        }
926
2.65k
        if (ext->mask & FIDO_EXT_PAYMENT) {
927
1.30k
                if (cbor_add_bool(item, "thirdPartyPayment", FIDO_OPT_TRUE) < 0) {
928
12
                        cbor_decref(&item);
929
12
                        return (NULL);
930
12
                }
931
1.30k
        }
932
933
2.64k
        return (item);
934
2.65k
}
935
936
int
937
cbor_decode_fmt(const cbor_item_t *item, char **fmt)
938
19.2k
{
939
19.2k
        char    *type = NULL;
940
941
19.2k
        if (cbor_string_copy(item, &type) < 0) {
942
153
                fido_log_debug("%s: cbor_string_copy", __func__);
943
153
                return (-1);
944
153
        }
945
946
19.0k
        if (strcmp(type, "packed") && strcmp(type, "fido-u2f") &&
947
19.0k
            strcmp(type, "none") && strcmp(type, "tpm")) {
948
448
                fido_log_debug("%s: type=%s", __func__, type);
949
448
                free(type);
950
448
                return (-1);
951
448
        }
952
953
18.6k
        *fmt = type;
954
955
18.6k
        return (0);
956
19.0k
}
957
958
struct cose_key {
959
        int kty;
960
        int alg;
961
        int crv;
962
};
963
964
static int
965
find_cose_alg(const cbor_item_t *key, const cbor_item_t *val, void *arg)
966
89.5k
{
967
89.5k
        struct cose_key *cose_key = arg;
968
969
89.5k
        if (cbor_isa_uint(key) == true &&
970
89.5k
            cbor_int_get_width(key) == CBOR_INT_8) {
971
37.1k
                switch (cbor_get_uint8(key)) {
972
18.6k
                case 1:
973
18.6k
                        if (cbor_isa_uint(val) == false ||
974
18.6k
                            cbor_get_int(val) > INT_MAX || cose_key->kty != 0) {
975
188
                                fido_log_debug("%s: kty", __func__);
976
188
                                return (-1);
977
188
                        }
978
979
18.4k
                        cose_key->kty = (int)cbor_get_int(val);
980
981
18.4k
                        break;
982
18.3k
                case 3:
983
18.3k
                        if (cbor_isa_negint(val) == false ||
984
18.3k
                            cbor_get_int(val) > INT_MAX || cose_key->alg != 0) {
985
120
                                fido_log_debug("%s: alg", __func__);
986
120
                                return (-1);
987
120
                        }
988
989
18.1k
                        cose_key->alg = -(int)cbor_get_int(val) - 1;
990
991
18.1k
                        break;
992
37.1k
                }
993
52.4k
        } else if (cbor_isa_negint(key) == true &&
994
52.4k
            cbor_int_get_width(key) == CBOR_INT_8) {
995
50.6k
                if (cbor_get_uint8(key) == 0) {
996
                        /* get crv if not rsa, otherwise ignore */
997
17.8k
                        if (cbor_isa_uint(val) == true &&
998
17.8k
                            cbor_get_int(val) <= INT_MAX &&
999
17.8k
                            cose_key->crv == 0)
1000
17.4k
                                cose_key->crv = (int)cbor_get_int(val);
1001
17.8k
                }
1002
50.6k
        }
1003
1004
89.2k
        return (0);
1005
89.5k
}
1006
1007
static int
1008
get_cose_alg(const cbor_item_t *item, int *cose_alg)
1009
19.1k
{
1010
19.1k
        struct cose_key cose_key;
1011
1012
19.1k
        memset(&cose_key, 0, sizeof(cose_key));
1013
1014
19.1k
        *cose_alg = 0;
1015
1016
19.1k
        if (cbor_isa_map(item) == false ||
1017
19.1k
            cbor_map_is_definite(item) == false ||
1018
19.1k
            cbor_map_iter(item, &cose_key, find_cose_alg) < 0) {
1019
1.47k
                fido_log_debug("%s: cbor type", __func__);
1020
1.47k
                return (-1);
1021
1.47k
        }
1022
1023
17.7k
        switch (cose_key.alg) {
1024
15.8k
        case COSE_ES256:
1025
15.8k
                if (cose_key.kty != COSE_KTY_EC2 ||
1026
15.8k
                    cose_key.crv != COSE_P256) {
1027
161
                        fido_log_debug("%s: invalid kty/crv", __func__);
1028
161
                        return (-1);
1029
161
                }
1030
15.6k
                break;
1031
15.6k
        case COSE_ES384:
1032
439
                if (cose_key.kty != COSE_KTY_EC2 ||
1033
439
                    cose_key.crv != COSE_P384) {
1034
4
                        fido_log_debug("%s: invalid kty/crv", __func__);
1035
4
                        return (-1);
1036
4
                }
1037
435
                break;
1038
1.00k
        case COSE_EDDSA:
1039
1.00k
                if (cose_key.kty != COSE_KTY_OKP ||
1040
1.00k
                    cose_key.crv != COSE_ED25519) {
1041
138
                        fido_log_debug("%s: invalid kty/crv", __func__);
1042
138
                        return (-1);
1043
138
                }
1044
870
                break;
1045
870
        case COSE_RS256:
1046
258
                if (cose_key.kty != COSE_KTY_RSA) {
1047
2
                        fido_log_debug("%s: invalid kty/crv", __func__);
1048
2
                        return (-1);
1049
2
                }
1050
256
                break;
1051
256
        default:
1052
154
                fido_log_debug("%s: unknown alg %d", __func__, cose_key.alg);
1053
1054
154
                return (-1);
1055
17.7k
        }
1056
1057
17.2k
        *cose_alg = cose_key.alg;
1058
1059
17.2k
        return (0);
1060
17.7k
}
1061
1062
int
1063
cbor_decode_pubkey(const cbor_item_t *item, int *type, void *key)
1064
19.1k
{
1065
19.1k
        if (get_cose_alg(item, type) < 0) {
1066
1.93k
                fido_log_debug("%s: get_cose_alg", __func__);
1067
1.93k
                return (-1);
1068
1.93k
        }
1069
1070
17.2k
        switch (*type) {
1071
15.6k
        case COSE_ES256:
1072
15.6k
                if (es256_pk_decode(item, key) < 0) {
1073
296
                        fido_log_debug("%s: es256_pk_decode", __func__);
1074
296
                        return (-1);
1075
296
                }
1076
15.4k
                break;
1077
15.4k
        case COSE_ES384:
1078
435
                if (es384_pk_decode(item, key) < 0) {
1079
12
                        fido_log_debug("%s: es384_pk_decode", __func__);
1080
12
                        return (-1);
1081
12
                }
1082
423
                break;
1083
423
        case COSE_RS256:
1084
256
                if (rs256_pk_decode(item, key) < 0) {
1085
24
                        fido_log_debug("%s: rs256_pk_decode", __func__);
1086
24
                        return (-1);
1087
24
                }
1088
232
                break;
1089
870
        case COSE_EDDSA:
1090
870
                if (eddsa_pk_decode(item, key) < 0) {
1091
34
                        fido_log_debug("%s: eddsa_pk_decode", __func__);
1092
34
                        return (-1);
1093
34
                }
1094
836
                break;
1095
836
        default:
1096
0
                fido_log_debug("%s: invalid cose_alg %d", __func__, *type);
1097
0
                return (-1);
1098
17.2k
        }
1099
1100
16.8k
        return (0);
1101
17.2k
}
1102
1103
static int
1104
decode_attcred(const unsigned char **buf, size_t *len, int cose_alg,
1105
    fido_attcred_t *attcred)
1106
18.2k
{
1107
18.2k
        cbor_item_t             *item = NULL;
1108
18.2k
        struct cbor_load_result  cbor;
1109
18.2k
        uint16_t                 id_len;
1110
18.2k
        int                      ok = -1;
1111
1112
18.2k
        fido_log_xxd(*buf, *len, "%s", __func__);
1113
1114
18.2k
        if (fido_buf_read(buf, len, &attcred->aaguid,
1115
18.2k
            sizeof(attcred->aaguid)) < 0) {
1116
28
                fido_log_debug("%s: fido_buf_read aaguid", __func__);
1117
28
                return (-1);
1118
28
        }
1119
1120
18.2k
        if (fido_buf_read(buf, len, &id_len, sizeof(id_len)) < 0) {
1121
18
                fido_log_debug("%s: fido_buf_read id_len", __func__);
1122
18
                return (-1);
1123
18
        }
1124
1125
18.1k
        attcred->id.len = (size_t)be16toh(id_len);
1126
18.1k
        if ((attcred->id.ptr = malloc(attcred->id.len)) == NULL)
1127
28
                return (-1);
1128
1129
18.1k
        fido_log_debug("%s: attcred->id.len=%zu", __func__, attcred->id.len);
1130
1131
18.1k
        if (fido_buf_read(buf, len, attcred->id.ptr, attcred->id.len) < 0) {
1132
742
                fido_log_debug("%s: fido_buf_read id", __func__);
1133
742
                return (-1);
1134
742
        }
1135
1136
17.4k
        if ((item = cbor_load(*buf, *len, &cbor)) == NULL) {
1137
609
                fido_log_debug("%s: cbor_load", __func__);
1138
609
                goto fail;
1139
609
        }
1140
1141
16.8k
        if (cbor_decode_pubkey(item, &attcred->type, &attcred->pubkey) < 0) {
1142
1.85k
                fido_log_debug("%s: cbor_decode_pubkey", __func__);
1143
1.85k
                goto fail;
1144
1.85k
        }
1145
1146
14.9k
        if (attcred->type != cose_alg) {
1147
5.49k
                fido_log_debug("%s: cose_alg mismatch (%d != %d)", __func__,
1148
5.49k
                    attcred->type, cose_alg);
1149
5.49k
                goto fail;
1150
5.49k
        }
1151
1152
9.46k
        *buf += cbor.read;
1153
9.46k
        *len -= cbor.read;
1154
1155
9.46k
        ok = 0;
1156
17.4k
fail:
1157
17.4k
        if (item != NULL)
1158
16.8k
                cbor_decref(&item);
1159
1160
17.4k
        return (ok);
1161
9.46k
}
1162
1163
static int
1164
decode_attobj(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1165
47.6k
{
1166
47.6k
        fido_cred_t *cred = arg;
1167
47.6k
        char *name = NULL;
1168
47.6k
        int ok = -1;
1169
1170
47.6k
        if (cbor_string_copy(key, &name) < 0) {
1171
335
                fido_log_debug("%s: cbor type", __func__);
1172
335
                ok = 0; /* ignore */
1173
335
                goto fail;
1174
335
        }
1175
1176
47.2k
        if (!strcmp(name, "fmt")) {
1177
17.0k
                if (cbor_decode_fmt(val, &cred->fmt) < 0) {
1178
399
                        fido_log_debug("%s: cbor_decode_fmt", __func__);
1179
399
                        goto fail;
1180
399
                }
1181
30.2k
        } else if (!strcmp(name, "attStmt")) {
1182
16.2k
                if (cbor_decode_attstmt(val, &cred->attstmt) < 0) {
1183
1.47k
                        fido_log_debug("%s: cbor_decode_attstmt", __func__);
1184
1.47k
                        goto fail;
1185
1.47k
                }
1186
16.2k
        } else if (!strcmp(name, "authData")) {
1187
11.9k
                if (fido_blob_decode(val, &cred->authdata_raw) < 0) {
1188
15
                        fido_log_debug("%s: fido_blob_decode", __func__);
1189
15
                        goto fail;
1190
15
                }
1191
11.9k
                if (cbor_decode_cred_authdata(val, cred->type,
1192
11.9k
                    &cred->authdata_cbor, &cred->authdata, &cred->attcred,
1193
11.9k
                    &cred->authdata_ext) < 0) {
1194
8.66k
                        fido_log_debug("%s: cbor_decode_cred_authdata",
1195
8.66k
                            __func__);
1196
8.66k
                        goto fail;
1197
8.66k
                }
1198
11.9k
        }
1199
1200
36.7k
        ok = 0;
1201
47.6k
fail:
1202
47.6k
        free(name);
1203
1204
47.6k
        return (ok);
1205
36.7k
}
1206
1207
/* XXX introduce fido_attobj_t? */
1208
int
1209
cbor_decode_attobj(const cbor_item_t *item, fido_cred_t *cred)
1210
17.6k
{
1211
17.6k
        if (cbor_isa_map(item) == false ||
1212
17.6k
            cbor_map_is_definite(item) == false ||
1213
17.6k
            cbor_map_iter(item, cred, decode_attobj) < 0) {
1214
13.4k
                fido_log_debug("%s: cbor type", __func__);
1215
13.4k
                return (-1);
1216
13.4k
        }
1217
1218
4.20k
        return (0);
1219
17.6k
}
1220
1221
static int
1222
decode_cred_extension(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1223
1.69k
{
1224
1.69k
        fido_cred_extout_t      *ext = arg;
1225
1.69k
        char                    *type = NULL;
1226
1.69k
        int                      ok = -1;
1227
1228
1.69k
        if (cbor_string_copy(key, &type) < 0) {
1229
930
                fido_log_debug("%s: cbor type", __func__);
1230
930
                ok = 0; /* ignore */
1231
930
                goto out;
1232
930
        }
1233
1234
764
        if (strcmp(type, "hmac-secret") == 0) {
1235
10
                if (cbor_decode_bool(val, NULL) < 0) {
1236
10
                        fido_log_debug("%s: cbor_decode_bool", __func__);
1237
10
                        goto out;
1238
10
                }
1239
0
                if (cbor_ctrl_value(val) == CBOR_CTRL_TRUE)
1240
0
                        ext->attr.mask |= FIDO_EXT_HMAC_SECRET;
1241
754
        } else if (strcmp(type, "hmac-secret-mc") == 0) {
1242
0
                if (fido_blob_decode(val, &ext->hmac_secret_enc) < 0) {
1243
0
                        fido_log_debug("%s: fido_blob_decode", __func__);
1244
0
                        goto out;
1245
0
                }
1246
0
                ext->attr.mask |= FIDO_EXT_HMAC_SECRET_MC;
1247
754
        } else if (strcmp(type, "credProtect") == 0) {
1248
74
                if (cbor_isa_uint(val) == false ||
1249
74
                    cbor_int_get_width(val) != CBOR_INT_8) {
1250
0
                        fido_log_debug("%s: cbor type", __func__);
1251
0
                        goto out;
1252
0
                }
1253
74
                ext->attr.mask |= FIDO_EXT_CRED_PROTECT;
1254
74
                ext->attr.prot = cbor_get_uint8(val);
1255
680
        } else if (strcmp(type, "credBlob") == 0) {
1256
66
                if (cbor_decode_bool(val, NULL) < 0) {
1257
5
                        fido_log_debug("%s: cbor_decode_bool", __func__);
1258
5
                        goto out;
1259
5
                }
1260
61
                if (cbor_ctrl_value(val) == CBOR_CTRL_TRUE)
1261
61
                        ext->attr.mask |= FIDO_EXT_CRED_BLOB;
1262
614
        } else if (strcmp(type, "minPinLength") == 0) {
1263
50
                if (cbor_isa_uint(val) == false ||
1264
50
                    cbor_int_get_width(val) != CBOR_INT_8) {
1265
1
                        fido_log_debug("%s: cbor type", __func__);
1266
1
                        goto out;
1267
1
                }
1268
49
                ext->attr.mask |= FIDO_EXT_MINPINLEN;
1269
49
                ext->attr.minpinlen = cbor_get_uint8(val);
1270
49
        }
1271
1272
748
        ok = 0;
1273
1.69k
out:
1274
1.69k
        free(type);
1275
1276
1.69k
        return (ok);
1277
748
}
1278
1279
static int
1280
decode_cred_extensions(const unsigned char **buf, size_t *len,
1281
    fido_cred_extout_t *authdata_ext)
1282
967
{
1283
967
        cbor_item_t             *item = NULL;
1284
967
        struct cbor_load_result  cbor;
1285
967
        int                      ok = -1;
1286
1287
967
        memset(authdata_ext, 0, sizeof(*authdata_ext));
1288
1289
967
        fido_log_xxd(*buf, *len, "%s", __func__);
1290
1291
967
        if ((item = cbor_load(*buf, *len, &cbor)) == NULL) {
1292
41
                fido_log_debug("%s: cbor_load", __func__);
1293
41
                goto fail;
1294
41
        }
1295
1296
926
        if (cbor_isa_map(item) == false ||
1297
926
            cbor_map_is_definite(item) == false ||
1298
926
            cbor_map_iter(item, authdata_ext, decode_cred_extension) < 0) {
1299
92
                fido_log_debug("%s: cbor type", __func__);
1300
92
                goto fail;
1301
92
        }
1302
1303
834
        *buf += cbor.read;
1304
834
        *len -= cbor.read;
1305
1306
834
        ok = 0;
1307
967
fail:
1308
967
        if (item != NULL)
1309
926
                cbor_decref(&item);
1310
1311
967
        return (ok);
1312
834
}
1313
1314
static int
1315
decode_assert_extension(const cbor_item_t *key, const cbor_item_t *val,
1316
    void *arg)
1317
2.26k
{
1318
2.26k
        fido_assert_extattr_t   *authdata_ext = arg;
1319
2.26k
        char                    *type = NULL;
1320
2.26k
        int                      ok = -1;
1321
1322
2.26k
        if (cbor_string_copy(key, &type) < 0) {
1323
253
                fido_log_debug("%s: cbor type", __func__);
1324
253
                ok = 0; /* ignore */
1325
253
                goto out;
1326
253
        }
1327
1328
2.01k
        if (strcmp(type, "hmac-secret") == 0) {
1329
1.26k
                if (fido_blob_decode(val, &authdata_ext->hmac_secret_enc) < 0) {
1330
7
                        fido_log_debug("%s: fido_blob_decode", __func__);
1331
7
                        goto out;
1332
7
                }
1333
1.25k
                authdata_ext->mask |= FIDO_EXT_HMAC_SECRET;
1334
1.25k
        } else if (strcmp(type, "credBlob") == 0) {
1335
424
                if (fido_blob_decode(val, &authdata_ext->blob) < 0) {
1336
4
                        fido_log_debug("%s: fido_blob_decode", __func__);
1337
4
                        goto out;
1338
4
                }
1339
420
                authdata_ext->mask |= FIDO_EXT_CRED_BLOB;
1340
420
        } else if (strcmp(type, "thirdPartyPayment") == 0) {
1341
0
                if (cbor_decode_bool(val, NULL) < 0) {
1342
0
                        fido_log_debug("%s: cbor_decode_bool", __func__);
1343
0
                        goto out;
1344
0
                }
1345
0
                if (cbor_ctrl_value(val) == CBOR_CTRL_TRUE)
1346
0
                        authdata_ext->mask |= FIDO_EXT_PAYMENT;
1347
0
        }
1348
1349
2.00k
        ok = 0;
1350
2.26k
out:
1351
2.26k
        free(type);
1352
1353
2.26k
        return (ok);
1354
2.00k
}
1355
1356
static int
1357
decode_assert_extensions(const unsigned char **buf, size_t *len,
1358
    fido_assert_extattr_t *authdata_ext)
1359
3.57k
{
1360
3.57k
        cbor_item_t             *item = NULL;
1361
3.57k
        struct cbor_load_result  cbor;
1362
3.57k
        int                      ok = -1;
1363
1364
3.57k
        fido_log_xxd(*buf, *len, "%s", __func__);
1365
1366
3.57k
        if ((item = cbor_load(*buf, *len, &cbor)) == NULL) {
1367
678
                fido_log_debug("%s: cbor_load", __func__);
1368
678
                goto fail;
1369
678
        }
1370
1371
2.89k
        if (cbor_isa_map(item) == false ||
1372
2.89k
            cbor_map_is_definite(item) == false ||
1373
2.89k
            cbor_map_iter(item, authdata_ext, decode_assert_extension) < 0) {
1374
831
                fido_log_debug("%s: cbor type", __func__);
1375
831
                goto fail;
1376
831
        }
1377
1378
2.06k
        *buf += cbor.read;
1379
2.06k
        *len -= cbor.read;
1380
1381
2.06k
        ok = 0;
1382
3.57k
fail:
1383
3.57k
        if (item != NULL)
1384
2.89k
                cbor_decref(&item);
1385
1386
3.57k
        return (ok);
1387
2.06k
}
1388
1389
int
1390
cbor_decode_cred_authdata(const cbor_item_t *item, int cose_alg,
1391
    fido_blob_t *authdata_cbor, fido_authdata_t *authdata,
1392
    fido_attcred_t *attcred, fido_cred_extout_t *authdata_ext)
1393
18.6k
{
1394
18.6k
        const unsigned char     *buf = NULL;
1395
18.6k
        size_t                   len;
1396
18.6k
        size_t                   alloc_len;
1397
1398
18.6k
        if (cbor_isa_bytestring(item) == false ||
1399
18.6k
            cbor_bytestring_is_definite(item) == false) {
1400
0
                fido_log_debug("%s: cbor type", __func__);
1401
0
                return (-1);
1402
0
        }
1403
1404
18.6k
        if (authdata_cbor->ptr != NULL ||
1405
18.6k
            (authdata_cbor->len = cbor_serialize_alloc(item,
1406
18.6k
            &authdata_cbor->ptr, &alloc_len)) == 0) {
1407
209
                fido_log_debug("%s: cbor_serialize_alloc", __func__);
1408
209
                return (-1);
1409
209
        }
1410
1411
18.4k
        buf = cbor_bytestring_handle(item);
1412
18.4k
        len = cbor_bytestring_length(item);
1413
18.4k
        fido_log_xxd(buf, len, "%s", __func__);
1414
1415
18.4k
        if (fido_buf_read(&buf, &len, authdata, sizeof(*authdata)) < 0) {
1416
116
                fido_log_debug("%s: fido_buf_read", __func__);
1417
116
                return (-1);
1418
116
        }
1419
1420
18.3k
        authdata->sigcount = be32toh(authdata->sigcount);
1421
1422
18.3k
        if (attcred != NULL) {
1423
18.3k
                if ((authdata->flags & CTAP_AUTHDATA_ATT_CRED) == 0 ||
1424
18.3k
                    decode_attcred(&buf, &len, cose_alg, attcred) < 0)
1425
8.87k
                        return (-1);
1426
18.3k
        }
1427
1428
9.46k
        if (authdata_ext != NULL) {
1429
9.46k
                if ((authdata->flags & CTAP_AUTHDATA_EXT_DATA) != 0 &&
1430
9.46k
                    decode_cred_extensions(&buf, &len, authdata_ext) < 0)
1431
133
                        return (-1);
1432
9.46k
        }
1433
1434
        /* XXX we should probably ensure that len == 0 at this point */
1435
1436
9.32k
        return (FIDO_OK);
1437
9.46k
}
1438
1439
int
1440
cbor_decode_assert_authdata(const cbor_item_t *item, fido_blob_t *authdata_cbor,
1441
    fido_authdata_t *authdata, fido_assert_extattr_t *authdata_ext)
1442
8.77k
{
1443
8.77k
        const unsigned char     *buf = NULL;
1444
8.77k
        size_t                   len;
1445
8.77k
        size_t                   alloc_len;
1446
1447
8.77k
        if (cbor_isa_bytestring(item) == false ||
1448
8.77k
            cbor_bytestring_is_definite(item) == false) {
1449
0
                fido_log_debug("%s: cbor type", __func__);
1450
0
                return (-1);
1451
0
        }
1452
1453
8.77k
        if (authdata_cbor->ptr != NULL ||
1454
8.77k
            (authdata_cbor->len = cbor_serialize_alloc(item,
1455
8.77k
            &authdata_cbor->ptr, &alloc_len)) == 0) {
1456
50
                fido_log_debug("%s: cbor_serialize_alloc", __func__);
1457
50
                return (-1);
1458
50
        }
1459
1460
8.72k
        buf = cbor_bytestring_handle(item);
1461
8.72k
        len = cbor_bytestring_length(item);
1462
1463
8.72k
        fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)buf, len);
1464
1465
8.72k
        if (fido_buf_read(&buf, &len, authdata, sizeof(*authdata)) < 0) {
1466
148
                fido_log_debug("%s: fido_buf_read", __func__);
1467
148
                return (-1);
1468
148
        }
1469
1470
8.57k
        authdata->sigcount = be32toh(authdata->sigcount);
1471
1472
8.57k
        if ((authdata->flags & CTAP_AUTHDATA_EXT_DATA) != 0) {
1473
3.57k
                if (decode_assert_extensions(&buf, &len, authdata_ext) < 0) {
1474
1.50k
                        fido_log_debug("%s: decode_assert_extensions",
1475
1.50k
                            __func__);
1476
1.50k
                        return (-1);
1477
1.50k
                }
1478
3.57k
        }
1479
1480
        /* XXX we should probably ensure that len == 0 at this point */
1481
1482
7.07k
        return (FIDO_OK);
1483
8.57k
}
1484
1485
static int
1486
decode_x5c(const cbor_item_t *item, void *arg)
1487
33.6k
{
1488
33.6k
        fido_blob_array_t *x5c = arg;
1489
33.6k
        fido_blob_t *list_ptr = NULL;
1490
33.6k
        fido_blob_t x5c_blob;
1491
1492
33.6k
        memset(&x5c_blob, 0, sizeof(x5c_blob));
1493
1494
33.6k
        if (fido_blob_decode(item, &x5c_blob) < 0) {
1495
531
                fido_log_debug("%s: fido_blob_decode", __func__);
1496
531
                return (-1);
1497
531
        }
1498
1499
33.1k
        if (x5c->len == SIZE_MAX) {
1500
0
                fido_blob_reset(&x5c_blob);
1501
0
                return (-1);
1502
0
        }
1503
1504
33.1k
        if ((list_ptr = recallocarray(x5c->ptr, x5c->len,
1505
33.1k
            x5c->len + 1, sizeof(x5c_blob))) == NULL) {
1506
190
                fido_blob_reset(&x5c_blob);
1507
190
                return (-1);
1508
190
        }
1509
1510
32.9k
        list_ptr[x5c->len++] = x5c_blob;
1511
32.9k
        x5c->ptr = list_ptr;
1512
1513
32.9k
        return (0);
1514
33.1k
}
1515
1516
static int
1517
decode_x5c_array(const cbor_item_t *item, fido_blob_array_t *arr)
1518
18.6k
{
1519
18.6k
        if (arr->len) {
1520
0
                fido_log_debug("%s: dup", __func__);
1521
0
                return (-1);
1522
0
        }
1523
18.6k
        if (cbor_isa_array(item) == false ||
1524
18.6k
            cbor_array_is_definite(item) == false) {
1525
26
                fido_log_debug("%s: cbor", __func__);
1526
26
                return (-1);
1527
26
        }
1528
18.6k
        return (cbor_array_iter(item, arr, decode_x5c));
1529
18.6k
}
1530
1531
static int
1532
decode_attstmt_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1533
73.0k
{
1534
73.0k
        fido_attstmt_t  *attstmt = arg;
1535
73.0k
        char            *name = NULL;
1536
73.0k
        int              ok = -1;
1537
1538
73.0k
        if (cbor_string_copy(key, &name) < 0) {
1539
804
                fido_log_debug("%s: cbor type", __func__);
1540
804
                ok = 0; /* ignore */
1541
804
                goto out;
1542
804
        }
1543
1544
72.2k
        if (!strcmp(name, "alg")) {
1545
21.3k
                if (cbor_isa_negint(val) == false ||
1546
21.3k
                    cbor_get_int(val) > UINT16_MAX) {
1547
66
                        fido_log_debug("%s: alg", __func__);
1548
66
                        goto out;
1549
66
                }
1550
21.2k
                attstmt->alg = -(int)cbor_get_int(val) - 1;
1551
21.2k
                if (attstmt->alg != COSE_ES256 && attstmt->alg != COSE_ES384 &&
1552
21.2k
                    attstmt->alg != COSE_RS256 && attstmt->alg != COSE_EDDSA &&
1553
21.2k
                    attstmt->alg != COSE_RS1) {
1554
117
                        fido_log_debug("%s: unsupported attstmt->alg=%d",
1555
117
                            __func__, attstmt->alg);
1556
117
                        goto out;
1557
117
                }
1558
50.9k
        } else if (!strcmp(name, "sig")) {
1559
21.0k
                if (fido_blob_decode(val, &attstmt->sig) < 0) {
1560
41
                        fido_log_debug("%s: sig", __func__);
1561
41
                        goto out;
1562
41
                }
1563
29.9k
        } else if (!strcmp(name, "x5c")) {
1564
18.6k
                if (decode_x5c_array(val, &attstmt->x5c)) {
1565
776
                        fido_log_debug("%s: x5c", __func__);
1566
776
                        goto out;
1567
776
                }
1568
18.6k
        } else if (!strcmp(name, "certInfo")) {
1569
2.41k
                if (fido_blob_decode(val, &attstmt->certinfo) < 0) {
1570
10
                        fido_log_debug("%s: certinfo", __func__);
1571
10
                        goto out;
1572
10
                }
1573
8.84k
        } else if (!strcmp(name, "pubArea")) {
1574
2.47k
                if (fido_blob_decode(val, &attstmt->pubarea) < 0) {
1575
17
                        fido_log_debug("%s: pubarea", __func__);
1576
17
                        goto out;
1577
17
                }
1578
2.47k
        }
1579
1580
71.2k
        ok = 0;
1581
73.0k
out:
1582
73.0k
        free(name);
1583
1584
73.0k
        return (ok);
1585
71.2k
}
1586
1587
int
1588
cbor_decode_attstmt(const cbor_item_t *item, fido_attstmt_t *attstmt)
1589
22.3k
{
1590
22.3k
        size_t alloc_len;
1591
1592
22.3k
        if (cbor_isa_map(item) == false ||
1593
22.3k
            cbor_map_is_definite(item) == false ||
1594
22.3k
            cbor_map_iter(item, attstmt, decode_attstmt_entry) < 0) {
1595
1.67k
                fido_log_debug("%s: cbor type", __func__);
1596
1.67k
                return (-1);
1597
1.67k
        }
1598
1599
20.6k
        if (attstmt->cbor.ptr != NULL ||
1600
20.6k
            (attstmt->cbor.len = cbor_serialize_alloc(item,
1601
20.6k
            &attstmt->cbor.ptr, &alloc_len)) == 0) {
1602
29
                fido_log_debug("%s: cbor_serialize_alloc", __func__);
1603
29
                return (-1);
1604
29
        }
1605
1606
20.6k
        return (0);
1607
20.6k
}
1608
1609
int
1610
cbor_decode_uint64(const cbor_item_t *item, uint64_t *n)
1611
410k
{
1612
410k
        if (cbor_isa_uint(item) == false) {
1613
405
                fido_log_debug("%s: cbor type", __func__);
1614
405
                return (-1);
1615
405
        }
1616
1617
409k
        *n = cbor_get_int(item);
1618
1619
409k
        return (0);
1620
410k
}
1621
1622
static int
1623
decode_cred_id_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1624
11.9k
{
1625
11.9k
        fido_blob_t     *id = arg;
1626
11.9k
        char            *name = NULL;
1627
11.9k
        int              ok = -1;
1628
1629
11.9k
        if (cbor_string_copy(key, &name) < 0) {
1630
1.76k
                fido_log_debug("%s: cbor type", __func__);
1631
1.76k
                ok = 0; /* ignore */
1632
1.76k
                goto out;
1633
1.76k
        }
1634
1635
10.1k
        if (!strcmp(name, "id"))
1636
4.03k
                if (fido_blob_decode(val, id) < 0) {
1637
11
                        fido_log_debug("%s: cbor_bytestring_copy", __func__);
1638
11
                        goto out;
1639
11
                }
1640
1641
10.1k
        ok = 0;
1642
11.9k
out:
1643
11.9k
        free(name);
1644
1645
11.9k
        return (ok);
1646
10.1k
}
1647
1648
int
1649
cbor_decode_cred_id(const cbor_item_t *item, fido_blob_t *id)
1650
5.49k
{
1651
5.49k
        if (cbor_isa_map(item) == false ||
1652
5.49k
            cbor_map_is_definite(item) == false ||
1653
5.49k
            cbor_map_iter(item, id, decode_cred_id_entry) < 0) {
1654
98
                fido_log_debug("%s: cbor type", __func__);
1655
98
                return (-1);
1656
98
        }
1657
1658
5.39k
        return (0);
1659
5.49k
}
1660
1661
static int
1662
decode_user_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1663
9.31k
{
1664
9.31k
        fido_user_t     *user = arg;
1665
9.31k
        char            *name = NULL;
1666
9.31k
        int              ok = -1;
1667
1668
9.31k
        if (cbor_string_copy(key, &name) < 0) {
1669
488
                fido_log_debug("%s: cbor type", __func__);
1670
488
                ok = 0; /* ignore */
1671
488
                goto out;
1672
488
        }
1673
1674
8.82k
        if (!strcmp(name, "icon")) {
1675
34
                if (cbor_string_copy(val, &user->icon) < 0) {
1676
6
                        fido_log_debug("%s: icon", __func__);
1677
6
                        goto out;
1678
6
                }
1679
8.79k
        } else if (!strcmp(name, "name")) {
1680
813
                if (cbor_string_copy(val, &user->name) < 0) {
1681
6
                        fido_log_debug("%s: name", __func__);
1682
6
                        goto out;
1683
6
                }
1684
7.98k
        } else if (!strcmp(name, "displayName")) {
1685
430
                if (cbor_string_copy(val, &user->display_name) < 0) {
1686
3
                        fido_log_debug("%s: display_name", __func__);
1687
3
                        goto out;
1688
3
                }
1689
7.55k
        } else if (!strcmp(name, "id")) {
1690
3.13k
                if (fido_blob_decode(val, &user->id) < 0) {
1691
17
                        fido_log_debug("%s: id", __func__);
1692
17
                        goto out;
1693
17
                }
1694
3.13k
        }
1695
1696
8.79k
        ok = 0;
1697
9.31k
out:
1698
9.31k
        free(name);
1699
1700
9.31k
        return (ok);
1701
8.79k
}
1702
1703
int
1704
cbor_decode_user(const cbor_item_t *item, fido_user_t *user)
1705
4.49k
{
1706
4.49k
        if (cbor_isa_map(item) == false ||
1707
4.49k
            cbor_map_is_definite(item) == false ||
1708
4.49k
            cbor_map_iter(item, user, decode_user_entry) < 0) {
1709
184
                fido_log_debug("%s: cbor type", __func__);
1710
184
                return (-1);
1711
184
        }
1712
1713
4.30k
        return (0);
1714
4.49k
}
1715
1716
static int
1717
decode_rp_entity_entry(const cbor_item_t *key, const cbor_item_t *val,
1718
    void *arg)
1719
3.17k
{
1720
3.17k
        fido_rp_t       *rp = arg;
1721
3.17k
        char            *name = NULL;
1722
3.17k
        int              ok = -1;
1723
1724
3.17k
        if (cbor_string_copy(key, &name) < 0) {
1725
208
                fido_log_debug("%s: cbor type", __func__);
1726
208
                ok = 0; /* ignore */
1727
208
                goto out;
1728
208
        }
1729
1730
2.96k
        if (!strcmp(name, "id")) {
1731
205
                if (cbor_string_copy(val, &rp->id) < 0) {
1732
10
                        fido_log_debug("%s: id", __func__);
1733
10
                        goto out;
1734
10
                }
1735
2.76k
        } else if (!strcmp(name, "name")) {
1736
4
                if (cbor_string_copy(val, &rp->name) < 0) {
1737
1
                        fido_log_debug("%s: name", __func__);
1738
1
                        goto out;
1739
1
                }
1740
4
        }
1741
1742
2.95k
        ok = 0;
1743
3.17k
out:
1744
3.17k
        free(name);
1745
1746
3.17k
        return (ok);
1747
2.95k
}
1748
1749
int
1750
cbor_decode_rp_entity(const cbor_item_t *item, fido_rp_t *rp)
1751
3.15k
{
1752
3.15k
        if (cbor_isa_map(item) == false ||
1753
3.15k
            cbor_map_is_definite(item) == false ||
1754
3.15k
            cbor_map_iter(item, rp, decode_rp_entity_entry) < 0) {
1755
18
                fido_log_debug("%s: cbor type", __func__);
1756
18
                return (-1);
1757
18
        }
1758
1759
3.13k
        return (0);
1760
3.15k
}
1761
1762
int
1763
cbor_decode_bool(const cbor_item_t *item, bool *v)
1764
671k
{
1765
671k
        if (cbor_isa_float_ctrl(item) == false ||
1766
671k
            cbor_float_get_width(item) != CBOR_FLOAT_0 ||
1767
671k
            cbor_is_bool(item) == false) {
1768
26.8k
                fido_log_debug("%s: cbor type", __func__);
1769
26.8k
                return (-1);
1770
26.8k
        }
1771
1772
644k
        if (v != NULL)
1773
60.0k
                *v = cbor_ctrl_value(item) == CBOR_CTRL_TRUE;
1774
1775
644k
        return (0);
1776
671k
}
1777
1778
cbor_item_t *
1779
cbor_build_uint(const uint64_t value)
1780
29.8k
{
1781
29.8k
        if (value <= UINT8_MAX)
1782
20.1k
                return cbor_build_uint8((uint8_t)value);
1783
9.71k
        else if (value <= UINT16_MAX)
1784
7.32k
                return cbor_build_uint16((uint16_t)value);
1785
2.39k
        else if (value <= UINT32_MAX)
1786
2.39k
                return cbor_build_uint32((uint32_t)value);
1787
1788
0
        return cbor_build_uint64(value);
1789
29.8k
}
1790
1791
int
1792
cbor_array_append(cbor_item_t **array, cbor_item_t *item)
1793
1.76k
{
1794
1.76k
        cbor_item_t **v, *ret;
1795
1.76k
        size_t n;
1796
1797
1.76k
        if ((v = cbor_array_handle(*array)) == NULL ||
1798
1.76k
            (n = cbor_array_size(*array)) == SIZE_MAX ||
1799
1.76k
            (ret = cbor_new_definite_array(n + 1)) == NULL)
1800
21
                return -1;
1801
2.81k
        for (size_t i = 0; i < n; i++) {
1802
1.09k
                if (cbor_array_push(ret, v[i]) == 0) {
1803
17
                        cbor_decref(&ret);
1804
17
                        return -1;
1805
17
                }
1806
1.09k
        }
1807
1.72k
        if (cbor_array_push(ret, item) == 0) {
1808
9
                cbor_decref(&ret);
1809
9
                return -1;
1810
9
        }
1811
1.71k
        cbor_decref(array);
1812
1.71k
        *array = ret;
1813
1814
1.71k
        return 0;
1815
1.72k
}
1816
1817
int
1818
cbor_array_drop(cbor_item_t **array, size_t idx)
1819
321
{
1820
321
        cbor_item_t **v, *ret;
1821
321
        size_t n;
1822
1823
321
        if ((v = cbor_array_handle(*array)) == NULL ||
1824
321
            (n = cbor_array_size(*array)) == 0 || idx >= n ||
1825
321
            (ret = cbor_new_definite_array(n - 1)) == NULL)
1826
2
                return -1;
1827
876
        for (size_t i = 0; i < n; i++) {
1828
566
                if (i != idx && cbor_array_push(ret, v[i]) == 0) {
1829
9
                        cbor_decref(&ret);
1830
9
                        return -1;
1831
9
                }
1832
566
        }
1833
310
        cbor_decref(array);
1834
310
        *array = ret;
1835
1836
310
        return 0;
1837
319
}