Coverage Report

Created: 2020-09-01 07:05

/libfido2/src/cbor.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2018 Yubico AB. All rights reserved.
3
 * Use of this source code is governed by a BSD-style
4
 * license that can be found in the LICENSE file.
5
 */
6
7
#include <openssl/evp.h>
8
#include <openssl/hmac.h>
9
#include <openssl/sha.h>
10
11
#include <string.h>
12
#include "fido.h"
13
14
static int
15
check_key_type(cbor_item_t *item)
16
159k
{
17
159k
        if (item->type == CBOR_TYPE_UINT || item->type == CBOR_TYPE_NEGINT ||
18
159k
            item->type == CBOR_TYPE_STRING)
19
159k
                return (0);
20
213
21
213
        fido_log_debug("%s: invalid type: %d", __func__, item->type);
22
213
23
213
        return (-1);
24
213
}
25
26
/*
27
 * Validate CTAP2 canonical CBOR encoding rules for maps.
28
 */
29
static int
30
ctap_check_cbor(cbor_item_t *prev, cbor_item_t *curr)
31
79.7k
{
32
79.7k
        size_t  curr_len;
33
79.7k
        size_t  prev_len;
34
79.7k
35
79.7k
        if (check_key_type(prev) < 0 || check_key_type(curr) < 0)
36
213
                return (-1);
37
79.5k
38
79.5k
        if (prev->type != curr->type) {
39
7.00k
                if (prev->type < curr->type)
40
6.70k
                        return (0);
41
301
                fido_log_debug("%s: unsorted types", __func__);
42
301
                return (-1);
43
301
        }
44
72.4k
45
72.4k
        if (curr->type == CBOR_TYPE_UINT || curr->type == CBOR_TYPE_NEGINT) {
46
54.9k
                if (cbor_int_get_width(curr) >= cbor_int_get_width(prev) &&
47
54.9k
                    cbor_get_int(curr) > cbor_get_int(prev))
48
54.4k
                        return (0);
49
17.5k
        } else {
50
17.5k
                curr_len = cbor_string_length(curr);
51
17.5k
                prev_len = cbor_string_length(prev);
52
17.5k
53
17.5k
                if (curr_len > prev_len || (curr_len == prev_len &&
54
4.02k
                    memcmp(cbor_string_handle(prev), cbor_string_handle(curr),
55
3.96k
                    curr_len) < 0))
56
17.4k
                        return (0);
57
616
        }
58
616
59
616
        fido_log_debug("%s: invalid cbor", __func__);
60
616
61
616
        return (-1);
62
616
}
63
64
int
65
cbor_map_iter(const cbor_item_t *item, void *arg, int(*f)(const cbor_item_t *,
66
    const cbor_item_t *, void *))
67
26.6k
{
68
26.6k
        struct cbor_pair        *v;
69
26.6k
        size_t                   n;
70
26.6k
71
26.6k
        if ((v = cbor_map_handle(item)) == NULL) {
72
60
                fido_log_debug("%s: cbor_map_handle", __func__);
73
60
                return (-1);
74
60
        }
75
26.6k
76
26.6k
        n = cbor_map_size(item);
77
26.6k
78
129k
        for (size_t i = 0; i < n; i++) {
79
106k
                if (v[i].key == NULL || v[i].value == NULL) {
80
0
                        fido_log_debug("%s: key=%p, value=%p for i=%zu",
81
0
                            __func__, (void *)v[i].key, (void *)v[i].value, i);
82
0
                        return (-1);
83
0
                }
84
106k
                if (i && ctap_check_cbor(v[i - 1].key, v[i].key) < 0) {
85
1.13k
                        fido_log_debug("%s: ctap_check_cbor", __func__);
86
1.13k
                        return (-1);
87
1.13k
                }
88
105k
                if (f(v[i].key, v[i].value, arg) < 0) {
89
2.35k
                        fido_log_debug("%s: iterator < 0 on i=%zu", __func__,
90
2.35k
                            i);
91
2.35k
                        return (-1);
92
2.35k
                }
93
105k
        }
94
26.6k
95
26.6k
        return (0);
96
26.6k
}
97
98
int
99
cbor_array_iter(const cbor_item_t *item, void *arg, int(*f)(const cbor_item_t *,
100
    void *))
101
11.2k
{
102
11.2k
        cbor_item_t     **v;
103
11.2k
        size_t            n;
104
11.2k
105
11.2k
        if ((v = cbor_array_handle(item)) == NULL) {
106
24
                fido_log_debug("%s: cbor_array_handle", __func__);
107
24
                return (-1);
108
24
        }
109
11.2k
110
11.2k
        n = cbor_array_size(item);
111
11.2k
112
34.9k
        for (size_t i = 0; i < n; i++)
113
23.9k
                if (v[i] == NULL || f(v[i], arg) < 0) {
114
180
                        fido_log_debug("%s: iterator < 0 on i=%zu,%p",
115
180
                            __func__, i, (void *)v[i]);
116
180
                        return (-1);
117
180
                }
118
11.2k
119
11.2k
        return (0);
120
11.2k
}
121
122
int
123
cbor_parse_reply(const unsigned char *blob, size_t blob_len, void *arg,
124
    int(*parser)(const cbor_item_t *, const cbor_item_t *, void *))
125
16.1k
{
126
16.1k
        cbor_item_t             *item = NULL;
127
16.1k
        struct cbor_load_result  cbor;
128
16.1k
        int                      r;
129
16.1k
130
16.1k
        if (blob_len < 1) {
131
1.03k
                fido_log_debug("%s: blob_len=%zu", __func__, blob_len);
132
1.03k
                r = FIDO_ERR_RX;
133
1.03k
                goto fail;
134
1.03k
        }
135
15.1k
136
15.1k
        if (blob[0] != FIDO_OK) {
137
808
                fido_log_debug("%s: blob[0]=0x%02x", __func__, blob[0]);
138
808
                r = blob[0];
139
808
                goto fail;
140
808
        }
141
14.2k
142
14.2k
        if ((item = cbor_load(blob + 1, blob_len - 1, &cbor)) == NULL) {
143
211
                fido_log_debug("%s: cbor_load", __func__);
144
211
                r = FIDO_ERR_RX_NOT_CBOR;
145
211
                goto fail;
146
211
        }
147
14.0k
148
14.0k
        if (cbor_isa_map(item) == false ||
149
14.0k
            cbor_map_is_definite(item) == false) {
150
154
                fido_log_debug("%s: cbor type", __func__);
151
154
                r = FIDO_ERR_RX_INVALID_CBOR;
152
154
                goto fail;
153
154
        }
154
13.9k
155
13.9k
        if (cbor_map_iter(item, arg, parser) < 0) {
156
2.87k
                fido_log_debug("%s: cbor_map_iter", __func__);
157
2.87k
                r = FIDO_ERR_RX_INVALID_CBOR;
158
2.87k
                goto fail;
159
2.87k
        }
160
11.0k
161
11.0k
        r = FIDO_OK;
162
16.1k
fail:
163
16.1k
        if (item != NULL)
164
16.1k
                cbor_decref(&item);
165
16.1k
166
16.1k
        return (r);
167
11.0k
}
168
169
void
170
cbor_vector_free(cbor_item_t **item, size_t len)
171
15.6k
{
172
79.1k
        for (size_t i = 0; i < len; i++)
173
63.4k
                if (item[i] != NULL)
174
63.4k
                        cbor_decref(&item[i]);
175
15.6k
}
176
177
int
178
cbor_bytestring_copy(const cbor_item_t *item, unsigned char **buf, size_t *len)
179
4.17k
{
180
4.17k
        if (*buf != NULL || *len != 0) {
181
1
                fido_log_debug("%s: dup", __func__);
182
1
                return (-1);
183
1
        }
184
4.17k
185
4.17k
        if (cbor_isa_bytestring(item) == false ||
186
4.17k
            cbor_bytestring_is_definite(item) == false) {
187
12
                fido_log_debug("%s: cbor type", __func__);
188
12
                return (-1);
189
12
        }
190
4.16k
191
4.16k
        *len = cbor_bytestring_length(item);
192
4.16k
        if ((*buf = malloc(*len)) == NULL) {
193
19
                *len = 0;
194
19
                return (-1);
195
19
        }
196
4.14k
197
4.14k
        memcpy(*buf, cbor_bytestring_handle(item), *len);
198
4.14k
199
4.14k
        return (0);
200
4.14k
}
201
202
int
203
cbor_string_copy(const cbor_item_t *item, char **str)
204
44.1k
{
205
44.1k
        size_t len;
206
44.1k
207
44.1k
        if (*str != NULL) {
208
1
                fido_log_debug("%s: dup", __func__);
209
1
                return (-1);
210
1
        }
211
44.1k
212
44.1k
        if (cbor_isa_string(item) == false ||
213
44.1k
            cbor_string_is_definite(item) == false) {
214
450
                fido_log_debug("%s: cbor type", __func__);
215
450
                return (-1);
216
450
        }
217
43.7k
218
43.7k
        if ((len = cbor_string_length(item)) == SIZE_MAX ||
219
43.7k
            (*str = malloc(len + 1)) == NULL)
220
43.7k
                return (-1);
221
43.5k
222
43.5k
        memcpy(*str, cbor_string_handle(item), len);
223
43.5k
        (*str)[len] = '\0';
224
43.5k
225
43.5k
        return (0);
226
43.5k
}
227
228
int
229
cbor_add_bytestring(cbor_item_t *item, const char *key,
230
    const unsigned char *value, size_t value_len)
231
33.3k
{
232
33.3k
        struct cbor_pair pair;
233
33.3k
        int ok = -1;
234
33.3k
235
33.3k
        memset(&pair, 0, sizeof(pair));
236
33.3k
237
33.3k
        if ((pair.key = cbor_build_string(key)) == NULL ||
238
33.3k
            (pair.value = cbor_build_bytestring(value, value_len)) == NULL) {
239
19
                fido_log_debug("%s: cbor_build", __func__);
240
19
                goto fail;
241
19
        }
242
33.3k
243
33.3k
        if (!cbor_map_add(item, pair)) {
244
11
                fido_log_debug("%s: cbor_map_add", __func__);
245
11
                goto fail;
246
11
        }
247
33.3k
248
33.3k
        ok = 0;
249
33.3k
fail:
250
33.3k
        if (pair.key)
251
33.3k
                cbor_decref(&pair.key);
252
33.3k
        if (pair.value)
253
33.3k
                cbor_decref(&pair.value);
254
33.3k
255
33.3k
        return (ok);
256
33.3k
}
257
258
int
259
cbor_add_string(cbor_item_t *item, const char *key, const char *value)
260
37.5k
{
261
37.5k
        struct cbor_pair pair;
262
37.5k
        int ok = -1;
263
37.5k
264
37.5k
        memset(&pair, 0, sizeof(pair));
265
37.5k
266
37.5k
        if ((pair.key = cbor_build_string(key)) == NULL ||
267
37.5k
            (pair.value = cbor_build_string(value)) == NULL) {
268
30
                fido_log_debug("%s: cbor_build", __func__);
269
30
                goto fail;
270
30
        }
271
37.5k
272
37.5k
        if (!cbor_map_add(item, pair)) {
273
13
                fido_log_debug("%s: cbor_map_add", __func__);
274
13
                goto fail;
275
13
        }
276
37.5k
277
37.5k
        ok = 0;
278
37.5k
fail:
279
37.5k
        if (pair.key)
280
37.5k
                cbor_decref(&pair.key);
281
37.5k
        if (pair.value)
282
37.5k
                cbor_decref(&pair.value);
283
37.5k
284
37.5k
        return (ok);
285
37.5k
}
286
287
int
288
cbor_add_bool(cbor_item_t *item, const char *key, fido_opt_t value)
289
951
{
290
951
        struct cbor_pair pair;
291
951
        int ok = -1;
292
951
293
951
        memset(&pair, 0, sizeof(pair));
294
951
295
951
        if ((pair.key = cbor_build_string(key)) == NULL ||
296
951
            (pair.value = cbor_build_bool(value == FIDO_OPT_TRUE)) == NULL) {
297
6
                fido_log_debug("%s: cbor_build", __func__);
298
6
                goto fail;
299
6
        }
300
945
301
945
        if (!cbor_map_add(item, pair)) {
302
2
                fido_log_debug("%s: cbor_map_add", __func__);
303
2
                goto fail;
304
2
        }
305
943
306
943
        ok = 0;
307
951
fail:
308
951
        if (pair.key)
309
948
                cbor_decref(&pair.key);
310
951
        if (pair.value)
311
945
                cbor_decref(&pair.value);
312
951
313
951
        return (ok);
314
943
}
315
316
static int
317
cbor_add_uint8(cbor_item_t *item, const char *key, uint8_t value)
318
364
{
319
364
        struct cbor_pair pair;
320
364
        int ok = -1;
321
364
322
364
        memset(&pair, 0, sizeof(pair));
323
364
324
364
        if ((pair.key = cbor_build_string(key)) == NULL ||
325
364
            (pair.value = cbor_build_uint8(value)) == NULL) {
326
2
                fido_log_debug("%s: cbor_build", __func__);
327
2
                goto fail;
328
2
        }
329
362
330
362
        if (!cbor_map_add(item, pair)) {
331
1
                fido_log_debug("%s: cbor_map_add", __func__);
332
1
                goto fail;
333
1
        }
334
361
335
361
        ok = 0;
336
364
fail:
337
364
        if (pair.key)
338
363
                cbor_decref(&pair.key);
339
364
        if (pair.value)
340
362
                cbor_decref(&pair.value);
341
364
342
364
        return (ok);
343
361
}
344
345
static int
346
cbor_add_arg(cbor_item_t *item, uint8_t n, cbor_item_t *arg)
347
48.1k
{
348
48.1k
        struct cbor_pair pair;
349
48.1k
        int ok = -1;
350
48.1k
351
48.1k
        memset(&pair, 0, sizeof(pair));
352
48.1k
353
48.1k
        if (arg == NULL)
354
48.1k
                return (0); /* empty argument */
355
36.2k
356
36.2k
        if ((pair.key = cbor_build_uint8(n)) == NULL) {
357
68
                fido_log_debug("%s: cbor_build", __func__);
358
68
                goto fail;
359
68
        }
360
36.1k
361
36.1k
        pair.value = arg;
362
36.1k
363
36.1k
        if (!cbor_map_add(item, pair)) {
364
70
                fido_log_debug("%s: cbor_map_add", __func__);
365
70
                goto fail;
366
70
        }
367
36.1k
368
36.1k
        ok = 0;
369
36.2k
fail:
370
36.2k
        if (pair.key)
371
36.1k
                cbor_decref(&pair.key);
372
36.2k
373
36.2k
        return (ok);
374
36.1k
}
375
376
cbor_item_t *
377
cbor_flatten_vector(cbor_item_t *argv[], size_t argc)
378
13.9k
{
379
13.9k
        cbor_item_t     *map;
380
13.9k
        uint8_t          i;
381
13.9k
382
13.9k
        if (argc > UINT8_MAX - 1)
383
0
                return (NULL);
384
13.9k
385
13.9k
        if ((map = cbor_new_definite_map(argc)) == NULL)
386
13.9k
                return (NULL);
387
13.9k
388
61.9k
        for (i = 0; i < argc; i++)
389
48.1k
                if (cbor_add_arg(map, (uint8_t)(i + 1), argv[i]) < 0)
390
138
                        break;
391
13.9k
392
13.9k
        if (i != argc) {
393
138
                cbor_decref(&map);
394
138
                map = NULL;
395
138
        }
396
13.9k
397
13.9k
        return (map);
398
13.9k
}
399
400
int
401
cbor_build_frame(uint8_t cmd, cbor_item_t *argv[], size_t argc, fido_blob_t *f)
402
11.8k
{
403
11.8k
        cbor_item_t     *flat = NULL;
404
11.8k
        unsigned char   *cbor = NULL;
405
11.8k
        size_t           cbor_len;
406
11.8k
        size_t           cbor_alloc_len;
407
11.8k
        int              ok = -1;
408
11.8k
409
11.8k
        if ((flat = cbor_flatten_vector(argv, argc)) == NULL)
410
11.8k
                goto fail;
411
11.6k
412
11.6k
        cbor_len = cbor_serialize_alloc(flat, &cbor, &cbor_alloc_len);
413
11.6k
        if (cbor_len == 0 || cbor_len == SIZE_MAX) {
414
37
                fido_log_debug("%s: cbor_len=%zu", __func__, cbor_len);
415
37
                goto fail;
416
37
        }
417
11.6k
418
11.6k
        if ((f->ptr = malloc(cbor_len + 1)) == NULL)
419
11.6k
                goto fail;
420
11.6k
421
11.6k
        f->len = cbor_len + 1;
422
11.6k
        f->ptr[0] = cmd;
423
11.6k
        memcpy(f->ptr + 1, cbor, f->len - 1);
424
11.6k
425
11.6k
        ok = 0;
426
11.8k
fail:
427
11.8k
        if (flat != NULL)
428
11.8k
                cbor_decref(&flat);
429
11.8k
430
11.8k
        free(cbor);
431
11.8k
432
11.8k
        return (ok);
433
11.6k
}
434
435
cbor_item_t *
436
cbor_encode_rp_entity(const fido_rp_t *rp)
437
927
{
438
927
        cbor_item_t *item = NULL;
439
927
440
927
        if ((item = cbor_new_definite_map(2)) == NULL)
441
927
                return (NULL);
442
926
443
926
        if ((rp->id && cbor_add_string(item, "id", rp->id) < 0) ||
444
926
            (rp->name && cbor_add_string(item, "name", rp->name) < 0)) {
445
7
                cbor_decref(&item);
446
7
                return (NULL);
447
7
        }
448
919
449
919
        return (item);
450
919
}
451
452
cbor_item_t *
453
cbor_encode_user_entity(const fido_user_t *user)
454
919
{
455
919
        cbor_item_t             *item = NULL;
456
919
        const fido_blob_t       *id = &user->id;
457
919
        const char              *display = user->display_name;
458
919
459
919
        if ((item = cbor_new_definite_map(4)) == NULL)
460
919
                return (NULL);
461
916
462
916
        if ((id->ptr && cbor_add_bytestring(item, "id", id->ptr, id->len) < 0) ||
463
916
            (user->icon && cbor_add_string(item, "icon", user->icon) < 0) ||
464
916
            (user->name && cbor_add_string(item, "name", user->name) < 0) ||
465
916
            (display && cbor_add_string(item, "displayName", display) < 0)) {
466
13
                cbor_decref(&item);
467
13
                return (NULL);
468
13
        }
469
903
470
903
        return (item);
471
903
}
472
473
cbor_item_t *
474
cbor_encode_pubkey_param(int cose_alg)
475
903
{
476
903
        cbor_item_t             *item = NULL;
477
903
        cbor_item_t             *body = NULL;
478
903
        struct cbor_pair         alg;
479
903
        int                      ok = -1;
480
903
481
903
        memset(&alg, 0, sizeof(alg));
482
903
483
903
        if ((item = cbor_new_definite_array(1)) == NULL ||
484
903
            (body = cbor_new_definite_map(2)) == NULL ||
485
903
            cose_alg > -1 || cose_alg < INT16_MIN)
486
903
                goto fail;
487
896
488
896
        alg.key = cbor_build_string("alg");
489
896
490
896
        if (-cose_alg - 1 > UINT8_MAX)
491
896
                alg.value = cbor_build_negint16((uint16_t)(-cose_alg - 1));
492
692
        else
493
692
                alg.value = cbor_build_negint8((uint8_t)(-cose_alg - 1));
494
896
495
896
        if (alg.key == NULL || alg.value == NULL) {
496
7
                fido_log_debug("%s: cbor_build", __func__);
497
7
                goto fail;
498
7
        }
499
889
500
889
        if (cbor_map_add(body, alg) == false ||
501
889
            cbor_add_string(body, "type", "public-key") < 0 ||
502
889
            cbor_array_push(item, body) == false)
503
889
                goto fail;
504
878
505
878
        ok  = 0;
506
903
fail:
507
903
        if (ok < 0) {
508
25
                if (item != NULL) {
509
23
                        cbor_decref(&item);
510
23
                        item = NULL;
511
23
                }
512
25
        }
513
903
514
903
        if (body != NULL)
515
903
                cbor_decref(&body);
516
903
        if (alg.key != NULL)
517
903
                cbor_decref(&alg.key);
518
903
        if (alg.value != NULL)
519
903
                cbor_decref(&alg.value);
520
903
521
903
        return (item);
522
878
}
523
524
cbor_item_t *
525
cbor_encode_pubkey(const fido_blob_t *pubkey)
526
32.4k
{
527
32.4k
        cbor_item_t *cbor_key = NULL;
528
32.4k
529
32.4k
        if ((cbor_key = cbor_new_definite_map(2)) == NULL ||
530
32.4k
            cbor_add_bytestring(cbor_key, "id", pubkey->ptr, pubkey->len) < 0 ||
531
32.4k
            cbor_add_string(cbor_key, "type", "public-key") < 0) {
532
55
                if (cbor_key)
533
47
                        cbor_decref(&cbor_key);
534
55
                return (NULL);
535
55
        }
536
32.4k
537
32.4k
        return (cbor_key);
538
32.4k
}
539
540
cbor_item_t *
541
cbor_encode_pubkey_list(const fido_blob_array_t *list)
542
896
{
543
896
        cbor_item_t     *array = NULL;
544
896
        cbor_item_t     *key = NULL;
545
896
546
896
        if ((array = cbor_new_definite_array(list->len)) == NULL)
547
896
                goto fail;
548
893
549
33.0k
        for (size_t i = 0; i < list->len; i++) {
550
32.2k
                if ((key = cbor_encode_pubkey(&list->ptr[i])) == NULL ||
551
32.2k
                    cbor_array_push(array, key) == false)
552
32.2k
                        goto fail;
553
32.1k
                cbor_decref(&key);
554
32.1k
        }
555
893
556
893
        return (array);
557
57
fail:
558
57
        if (key != NULL)
559
57
                cbor_decref(&key);
560
57
        if (array != NULL)
561
57
                cbor_decref(&array);
562
57
563
57
        return (NULL);
564
893
}
565
566
cbor_item_t *
567
cbor_encode_extensions(const fido_cred_ext_t *ext)
568
371
{
569
371
        cbor_item_t *item = NULL;
570
371
        size_t size = 0;
571
371
572
371
        if (ext->mask & FIDO_EXT_HMAC_SECRET)
573
371
                size++;
574
371
        if (ext->mask & FIDO_EXT_CRED_PROTECT)
575
371
                size++;
576
371
        if (size == 0 || (item = cbor_new_definite_map(size)) == NULL)
577
371
                return (NULL);
578
370
579
370
        if (ext->mask & FIDO_EXT_HMAC_SECRET) {
580
8
                if (cbor_add_bool(item, "hmac-secret", FIDO_OPT_TRUE) < 0) {
581
1
                        cbor_decref(&item);
582
1
                        return (NULL);
583
1
                }
584
369
        }
585
369
        if (ext->mask & FIDO_EXT_CRED_PROTECT) {
586
364
                if (ext->prot < 0 || ext->prot > UINT8_MAX ||
587
364
                    cbor_add_uint8(item, "credProtect",
588
364
                    (uint8_t)ext->prot) < 0) {
589
3
                        cbor_decref(&item);
590
3
                        return (NULL);
591
3
                }
592
366
        }
593
366
594
366
        return (item);
595
366
}
596
597
cbor_item_t *
598
cbor_encode_options(fido_opt_t rk, fido_opt_t uv)
599
471
{
600
471
        cbor_item_t *item = NULL;
601
471
602
471
        if ((item = cbor_new_definite_map(2)) == NULL)
603
471
                return (NULL);
604
470
605
470
        if ((rk != FIDO_OPT_OMIT && cbor_add_bool(item, "rk", rk) < 0) ||
606
470
            (uv != FIDO_OPT_OMIT && cbor_add_bool(item, "uv", uv) < 0)) {
607
2
                cbor_decref(&item);
608
2
                return (NULL);
609
2
        }
610
468
611
468
        return (item);
612
468
}
613
614
cbor_item_t *
615
cbor_encode_assert_options(fido_opt_t up, fido_opt_t uv)
616
275
{
617
275
        cbor_item_t *item = NULL;
618
275
619
275
        if ((item = cbor_new_definite_map(2)) == NULL)
620
275
                return (NULL);
621
273
622
273
        if ((up != FIDO_OPT_OMIT && cbor_add_bool(item, "up", up) < 0) ||
623
273
            (uv != FIDO_OPT_OMIT && cbor_add_bool(item, "uv", uv) < 0)) {
624
5
                cbor_decref(&item);
625
5
                return (NULL);
626
5
        }
627
268
628
268
        return (item);
629
268
}
630
631
cbor_item_t *
632
cbor_encode_pin_auth(const fido_blob_t *hmac_key, const fido_blob_t *data)
633
2.17k
{
634
2.17k
        const EVP_MD    *md = NULL;
635
2.17k
        unsigned char    dgst[SHA256_DIGEST_LENGTH];
636
2.17k
        unsigned int     dgst_len;
637
2.17k
638
2.17k
        if ((md = EVP_sha256()) == NULL || HMAC(md, hmac_key->ptr,
639
2.16k
            (int)hmac_key->len, data->ptr, data->len, dgst,
640
2.16k
            &dgst_len) == NULL || dgst_len != SHA256_DIGEST_LENGTH)
641
2.17k
                return (NULL);
642
2.16k
643
2.16k
        return (cbor_build_bytestring(dgst, 16));
644
2.16k
}
645
646
cbor_item_t *
647
cbor_encode_pin_opt(void)
648
2.24k
{
649
2.24k
        return (cbor_build_uint8(1));
650
2.24k
}
651
652
cbor_item_t *
653
cbor_encode_pin_enc(const fido_blob_t *key, const fido_blob_t *pin)
654
138
{
655
138
        fido_blob_t      pe;
656
138
        cbor_item_t     *item = NULL;
657
138
658
138
        if (aes256_cbc_enc(key, pin, &pe) < 0)
659
6
                return (NULL);
660
132
661
132
        item = cbor_build_bytestring(pe.ptr, pe.len);
662
132
        free(pe.ptr);
663
132
664
132
        return (item);
665
132
}
666
667
static int
668
sha256(const unsigned char *data, size_t data_len, fido_blob_t *digest)
669
2.47k
{
670
2.47k
        if ((digest->ptr = calloc(1, SHA256_DIGEST_LENGTH)) == NULL)
671
2.47k
                return (-1);
672
2.47k
673
2.47k
        digest->len = SHA256_DIGEST_LENGTH;
674
2.47k
675
2.47k
        if (SHA256(data, data_len, digest->ptr) != digest->ptr) {
676
7
                free(digest->ptr);
677
7
                digest->ptr = NULL;
678
7
                digest->len = 0;
679
7
                return (-1);
680
7
        }
681
2.46k
682
2.46k
        return (0);
683
2.46k
}
684
685
cbor_item_t *
686
cbor_encode_change_pin_auth(const fido_blob_t *key, const fido_blob_t *new_pin,
687
    const fido_blob_t *pin)
688
63
{
689
63
        unsigned char    dgst[SHA256_DIGEST_LENGTH];
690
63
        unsigned int     dgst_len;
691
63
        cbor_item_t     *item = NULL;
692
63
        const EVP_MD    *md = NULL;
693
#if OPENSSL_VERSION_NUMBER < 0x10100000L
694
        HMAC_CTX         ctx;
695
#else
696
        HMAC_CTX        *ctx = NULL;
697
63
#endif
698
63
        fido_blob_t     *npe = NULL; /* new pin, encrypted */
699
63
        fido_blob_t     *ph = NULL;  /* pin hash */
700
63
        fido_blob_t     *phe = NULL; /* pin hash, encrypted */
701
63
702
63
        if ((npe = fido_blob_new()) == NULL ||
703
63
            (ph = fido_blob_new()) == NULL ||
704
63
            (phe = fido_blob_new()) == NULL)
705
63
                goto fail;
706
60
707
60
        if (aes256_cbc_enc(key, new_pin, npe) < 0) {
708
1
                fido_log_debug("%s: aes256_cbc_enc 1", __func__);
709
1
                goto fail;
710
1
        }
711
59
712
59
        if (sha256(pin->ptr, pin->len, ph) < 0 || ph->len < 16) {
713
1
                fido_log_debug("%s: sha256", __func__);
714
1
                goto fail;
715
1
        }
716
58
717
58
        ph->len = 16; /* first 16 bytes */
718
58
719
58
        if (aes256_cbc_enc(key, ph, phe) < 0) {
720
1
                fido_log_debug("%s: aes256_cbc_enc 2", __func__);
721
1
                goto fail;
722
1
        }
723
57
724
#if OPENSSL_VERSION_NUMBER < 0x10100000L
725
        HMAC_CTX_init(&ctx);
726
727
        if ((md = EVP_sha256()) == NULL ||
728
            HMAC_Init_ex(&ctx, key->ptr, (int)key->len, md, NULL) == 0 ||
729
            HMAC_Update(&ctx, npe->ptr, (int)npe->len) == 0 ||
730
            HMAC_Update(&ctx, phe->ptr, (int)phe->len) == 0 ||
731
            HMAC_Final(&ctx, dgst, &dgst_len) == 0 || dgst_len != 32) {
732
                fido_log_debug("%s: HMAC", __func__);
733
                goto fail;
734
        }
735
#else
736
57
        if ((ctx = HMAC_CTX_new()) == NULL ||
737
57
            (md = EVP_sha256())  == NULL ||
738
57
            HMAC_Init_ex(ctx, key->ptr, (int)key->len, md, NULL) == 0 ||
739
57
            HMAC_Update(ctx, npe->ptr, npe->len) == 0 ||
740
57
            HMAC_Update(ctx, phe->ptr, phe->len) == 0 ||
741
57
            HMAC_Final(ctx, dgst, &dgst_len) == 0 || dgst_len != 32) {
742
7
                fido_log_debug("%s: HMAC", __func__);
743
7
                goto fail;
744
7
        }
745
50
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
746
50
747
50
        if ((item = cbor_build_bytestring(dgst, 16)) == NULL) {
748
1
                fido_log_debug("%s: cbor_build_bytestring", __func__);
749
1
                goto fail;
750
1
        }
751
63
752
63
fail:
753
63
        fido_blob_free(&npe);
754
63
        fido_blob_free(&ph);
755
63
        fido_blob_free(&phe);
756
63
757
63
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
758
63
        if (ctx != NULL)
759
63
                HMAC_CTX_free(ctx);
760
63
#endif
761
63
762
63
        return (item);
763
50
}
764
765
cbor_item_t *
766
cbor_encode_set_pin_auth(const fido_blob_t *key, const fido_blob_t *pin)
767
94
{
768
94
        const EVP_MD    *md = NULL;
769
94
        unsigned char    dgst[SHA256_DIGEST_LENGTH];
770
94
        unsigned int     dgst_len;
771
94
        cbor_item_t     *item = NULL;
772
94
        fido_blob_t     *pe = NULL;
773
94
774
94
        if ((pe = fido_blob_new()) == NULL)
775
94
                goto fail;
776
92
777
92
        if (aes256_cbc_enc(key, pin, pe) < 0) {
778
5
                fido_log_debug("%s: aes256_cbc_enc", __func__);
779
5
                goto fail;
780
5
        }
781
87
782
87
        if ((md = EVP_sha256()) == NULL || key->len != 32 || HMAC(md, key->ptr,
783
85
            (int)key->len, pe->ptr, pe->len, dgst, &dgst_len) == NULL ||
784
87
            dgst_len != SHA256_DIGEST_LENGTH) {
785
4
                fido_log_debug("%s: HMAC", __func__);
786
4
                goto fail;
787
4
        }
788
83
789
83
        item = cbor_build_bytestring(dgst, 16);
790
94
fail:
791
94
        fido_blob_free(&pe);
792
94
793
94
        return (item);
794
83
}
795
796
cbor_item_t *
797
cbor_encode_pin_hash_enc(const fido_blob_t *shared, const fido_blob_t *pin)
798
2.43k
{
799
2.43k
        cbor_item_t     *item = NULL;
800
2.43k
        fido_blob_t     *ph = NULL;
801
2.43k
        fido_blob_t     *phe = NULL;
802
2.43k
803
2.43k
        if ((ph = fido_blob_new()) == NULL || (phe = fido_blob_new()) == NULL)
804
2.43k
                goto fail;
805
2.41k
806
2.41k
        if (sha256(pin->ptr, pin->len, ph) < 0 || ph->len < 16) {
807
11
                fido_log_debug("%s: SHA256", __func__);
808
11
                goto fail;
809
11
        }
810
2.40k
811
2.40k
        ph->len = 16; /* first 16 bytes */
812
2.40k
813
2.40k
        if (aes256_cbc_enc(shared, ph, phe) < 0) {
814
26
                fido_log_debug("%s: aes256_cbc_enc", __func__);
815
26
                goto fail;
816
26
        }
817
2.38k
818
2.38k
        item = cbor_build_bytestring(phe->ptr, phe->len);
819
2.43k
fail:
820
2.43k
        fido_blob_free(&ph);
821
2.43k
        fido_blob_free(&phe);
822
2.43k
823
2.43k
        return (item);
824
2.38k
}
825
826
cbor_item_t *
827
cbor_encode_hmac_secret_param(const fido_blob_t *ecdh, const es256_pk_t *pk,
828
    const fido_blob_t *hmac_salt)
829
52
{
830
52
        cbor_item_t             *item = NULL;
831
52
        cbor_item_t             *param = NULL;
832
52
        cbor_item_t             *argv[3];
833
52
        struct cbor_pair         pair;
834
52
835
52
        memset(argv, 0, sizeof(argv));
836
52
        memset(&pair, 0, sizeof(pair));
837
52
838
52
        if (ecdh == NULL || pk == NULL || hmac_salt->ptr == NULL) {
839
11
                fido_log_debug("%s: ecdh=%p, pk=%p, hmac_salt->ptr=%p",
840
11
                    __func__, (const void *)ecdh, (const void *)pk,
841
11
                    (const void *)hmac_salt->ptr);
842
11
                goto fail;
843
11
        }
844
41
845
41
        if (hmac_salt->len != 32 && hmac_salt->len != 64) {
846
0
                fido_log_debug("%s: hmac_salt->len=%zu", __func__,
847
0
                    hmac_salt->len);
848
0
                goto fail;
849
0
        }
850
41
851
41
        /* XXX not pin, but salt */
852
41
        if ((argv[0] = es256_pk_encode(pk, 1)) == NULL ||
853
41
            (argv[1] = cbor_encode_pin_enc(ecdh, hmac_salt)) == NULL ||
854
41
            (argv[2] = cbor_encode_set_pin_auth(ecdh, hmac_salt)) == NULL) {
855
10
                fido_log_debug("%s: cbor encode", __func__);
856
10
                goto fail;
857
10
        }
858
31
859
31
        if ((param = cbor_flatten_vector(argv, 3)) == NULL) {
860
2
                fido_log_debug("%s: cbor_flatten_vector", __func__);
861
2
                goto fail;
862
2
        }
863
29
864
29
        if ((item = cbor_new_definite_map(1)) == NULL) {
865
1
                fido_log_debug("%s: cbor_new_definite_map", __func__);
866
1
                goto fail;
867
1
        }
868
28
869
28
        if ((pair.key = cbor_build_string("hmac-secret")) == NULL) {
870
1
                fido_log_debug("%s: cbor_build", __func__);
871
1
                goto fail;
872
1
        }
873
27
874
27
        pair.value = param;
875
27
876
27
        if (!cbor_map_add(item, pair)) {
877
1
                fido_log_debug("%s: cbor_map_add", __func__);
878
1
                cbor_decref(&item);
879
1
                item = NULL;
880
1
                goto fail;
881
1
        }
882
52
883
52
fail:
884
208
        for (size_t i = 0; i < 3; i++)
885
156
                if (argv[i] != NULL)
886
156
                        cbor_decref(&argv[i]);
887
52
888
52
        if (param != NULL)
889
52
                cbor_decref(&param);
890
52
        if (pair.key != NULL)
891
52
                cbor_decref(&pair.key);
892
52
893
52
        return (item);
894
27
}
895
896
int
897
cbor_decode_fmt(const cbor_item_t *item, char **fmt)
898
360
{
899
360
        char    *type = NULL;
900
360
901
360
        if (cbor_string_copy(item, &type) < 0) {
902
12
                fido_log_debug("%s: cbor_string_copy", __func__);
903
12
                return (-1);
904
12
        }
905
348
906
348
        if (strcmp(type, "packed") && strcmp(type, "fido-u2f")) {
907
21
                fido_log_debug("%s: type=%s", __func__, type);
908
21
                free(type);
909
21
                return (-1);
910
21
        }
911
327
912
327
        *fmt = type;
913
327
914
327
        return (0);
915
327
}
916
917
struct cose_key {
918
        int kty;
919
        int alg;
920
        int crv;
921
};
922
923
static int
924
find_cose_alg(const cbor_item_t *key, const cbor_item_t *val, void *arg)
925
7.52k
{
926
7.52k
        struct cose_key *cose_key = arg;
927
7.52k
928
7.52k
        if (cbor_isa_uint(key) == true &&
929
7.52k
            cbor_int_get_width(key) == CBOR_INT_8) {
930
3.42k
                switch (cbor_get_uint8(key)) {
931
1.70k
                case 1:
932
1.70k
                        if (cbor_isa_uint(val) == false ||
933
1.70k
                            cbor_get_int(val) > INT_MAX || cose_key->kty != 0) {
934
47
                                fido_log_debug("%s: kty", __func__);
935
47
                                return (-1);
936
47
                        }
937
1.66k
938
1.66k
                        cose_key->kty = (int)cbor_get_int(val);
939
1.66k
940
1.66k
                        break;
941
1.66k
                case 3:
942
1.62k
                        if (cbor_isa_negint(val) == false ||
943
1.62k
                            cbor_get_int(val) > INT_MAX || cose_key->alg != 0) {
944
61
                                fido_log_debug("%s: alg", __func__);
945
61
                                return (-1);
946
61
                        }
947
1.55k
948
1.55k
                        cose_key->alg = -(int)cbor_get_int(val) - 1;
949
1.55k
950
1.55k
                        break;
951
4.09k
                }
952
4.09k
        } else if (cbor_isa_negint(key) == true &&
953
4.09k
            cbor_int_get_width(key) == CBOR_INT_8) {
954
3.96k
                if (cbor_get_uint8(key) == 0) {
955
1.42k
                        /* get crv if not rsa, otherwise ignore */
956
1.42k
                        if (cbor_isa_uint(val) == true &&
957
1.42k
                            cbor_get_int(val) <= INT_MAX &&
958
1.42k
                            cose_key->crv == 0)
959
1.34k
                                cose_key->crv = (int)cbor_get_int(val);
960
1.42k
                }
961
3.96k
        }
962
7.52k
963
7.52k
        return (0);
964
7.52k
}
965
966
static int
967
get_cose_alg(const cbor_item_t *item, int *cose_alg)
968
1.77k
{
969
1.77k
        struct cose_key cose_key;
970
1.77k
971
1.77k
        memset(&cose_key, 0, sizeof(cose_key));
972
1.77k
973
1.77k
        *cose_alg = 0;
974
1.77k
975
1.77k
        if (cbor_isa_map(item) == false ||
976
1.77k
            cbor_map_is_definite(item) == false ||
977
1.77k
            cbor_map_iter(item, &cose_key, find_cose_alg) < 0) {
978
258
                fido_log_debug("%s: cbor type", __func__);
979
258
                return (-1);
980
258
        }
981
1.51k
982
1.51k
        switch (cose_key.alg) {
983
1.13k
        case COSE_ES256:
984
1.13k
                if (cose_key.kty != COSE_KTY_EC2 ||
985
1.13k
                    cose_key.crv != COSE_P256) {
986
71
                        fido_log_debug("%s: invalid kty/crv", __func__);
987
71
                        return (-1);
988
71
                }
989
1.06k
990
1.06k
                break;
991
1.06k
        case COSE_EDDSA:
992
224
                if (cose_key.kty != COSE_KTY_OKP ||
993
224
                    cose_key.crv != COSE_ED25519) {
994
70
                        fido_log_debug("%s: invalid kty/crv", __func__);
995
70
                        return (-1);
996
70
                }
997
154
998
154
                break;
999
154
        case COSE_RS256:
1000
66
                if (cose_key.kty != COSE_KTY_RSA) {
1001
1
                        fido_log_debug("%s: invalid kty/crv", __func__);
1002
1
                        return (-1);
1003
1
                }
1004
65
1005
65
                break;
1006
93
        default:
1007
93
                fido_log_debug("%s: unknown alg %d", __func__, cose_key.alg);
1008
93
1009
93
                return (-1);
1010
1.28k
        }
1011
1.28k
1012
1.28k
        *cose_alg = cose_key.alg;
1013
1.28k
1014
1.28k
        return (0);
1015
1.28k
}
1016
1017
int
1018
cbor_decode_pubkey(const cbor_item_t *item, int *type, void *key)
1019
1.77k
{
1020
1.77k
        if (get_cose_alg(item, type) < 0) {
1021
493
                fido_log_debug("%s: get_cose_alg", __func__);
1022
493
                return (-1);
1023
493
        }
1024
1.28k
1025
1.28k
        switch (*type) {
1026
1.06k
        case COSE_ES256:
1027
1.06k
                if (es256_pk_decode(item, key) < 0) {
1028
22
                        fido_log_debug("%s: es256_pk_decode", __func__);
1029
22
                        return (-1);
1030
22
                }
1031
1.04k
                break;
1032
1.04k
        case COSE_RS256:
1033
65
                if (rs256_pk_decode(item, key) < 0) {
1034
4
                        fido_log_debug("%s: rs256_pk_decode", __func__);
1035
4
                        return (-1);
1036
4
                }
1037
61
                break;
1038
154
        case COSE_EDDSA:
1039
154
                if (eddsa_pk_decode(item, key) < 0) {
1040
8
                        fido_log_debug("%s: eddsa_pk_decode", __func__);
1041
8
                        return (-1);
1042
8
                }
1043
146
                break;
1044
146
        default:
1045
0
                fido_log_debug("%s: invalid cose_alg %d", __func__, *type);
1046
0
                return (-1);
1047
1.24k
        }
1048
1.24k
1049
1.24k
        return (0);
1050
1.24k
}
1051
1052
static int
1053
decode_attcred(const unsigned char **buf, size_t *len, int cose_alg,
1054
    fido_attcred_t *attcred)
1055
977
{
1056
977
        cbor_item_t             *item = NULL;
1057
977
        struct cbor_load_result  cbor;
1058
977
        uint16_t                 id_len;
1059
977
        int                      ok = -1;
1060
977
1061
977
        fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)*buf,
1062
977
            *len);
1063
977
1064
977
        if (fido_buf_read(buf, len, &attcred->aaguid,
1065
977
            sizeof(attcred->aaguid)) < 0) {
1066
13
                fido_log_debug("%s: fido_buf_read aaguid", __func__);
1067
13
                return (-1);
1068
13
        }
1069
964
1070
964
        if (fido_buf_read(buf, len, &id_len, sizeof(id_len)) < 0) {
1071
6
                fido_log_debug("%s: fido_buf_read id_len", __func__);
1072
6
                return (-1);
1073
6
        }
1074
958
1075
958
        attcred->id.len = (size_t)be16toh(id_len);
1076
958
        if ((attcred->id.ptr = malloc(attcred->id.len)) == NULL)
1077
958
                return (-1);
1078
948
1079
948
        fido_log_debug("%s: attcred->id.len=%zu", __func__, attcred->id.len);
1080
948
1081
948
        if (fido_buf_read(buf, len, attcred->id.ptr, attcred->id.len) < 0) {
1082
48
                fido_log_debug("%s: fido_buf_read id", __func__);
1083
48
                return (-1);
1084
48
        }
1085
900
1086
900
        if ((item = cbor_load(*buf, *len, &cbor)) == NULL) {
1087
26
                fido_log_debug("%s: cbor_load", __func__);
1088
26
                fido_log_xxd(*buf, *len);
1089
26
                goto fail;
1090
26
        }
1091
874
1092
874
        if (cbor_decode_pubkey(item, &attcred->type, &attcred->pubkey) < 0) {
1093
215
                fido_log_debug("%s: cbor_decode_pubkey", __func__);
1094
215
                goto fail;
1095
215
        }
1096
659
1097
659
        if (attcred->type != cose_alg) {
1098
61
                fido_log_debug("%s: cose_alg mismatch (%d != %d)", __func__,
1099
61
                    attcred->type, cose_alg);
1100
61
                goto fail;
1101
61
        }
1102
598
1103
598
        *buf += cbor.read;
1104
598
        *len -= cbor.read;
1105
598
1106
598
        ok = 0;
1107
900
fail:
1108
900
        if (item != NULL)
1109
900
                cbor_decref(&item);
1110
900
1111
900
        return (ok);
1112
598
}
1113
1114
static int
1115
decode_extension(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1116
54
{
1117
54
        fido_cred_ext_t *authdata_ext = arg;
1118
54
        char            *type = NULL;
1119
54
        int              ok = -1;
1120
54
1121
54
        if (cbor_string_copy(key, &type) < 0) {
1122
5
                fido_log_debug("%s: cbor type", __func__);
1123
5
                ok = 0; /* ignore */
1124
5
                goto out;
1125
5
        }
1126
49
1127
49
        if (strcmp(type, "hmac-secret") == 0) {
1128
25
                if (cbor_isa_float_ctrl(val) == false ||
1129
25
                    cbor_float_get_width(val) != CBOR_FLOAT_0 ||
1130
25
                    cbor_is_bool(val) == false) {
1131
0
                        fido_log_debug("%s: cbor type", __func__);
1132
0
                        goto out;
1133
0
                }
1134
25
                if (cbor_ctrl_value(val) == CBOR_CTRL_TRUE)
1135
25
                        authdata_ext->mask |= FIDO_EXT_HMAC_SECRET;
1136
25
        } else if (strcmp(type, "credProtect") == 0) {
1137
24
                if (cbor_isa_uint(val) == false ||
1138
24
                    cbor_int_get_width(val) != CBOR_INT_8) {
1139
0
                        fido_log_debug("%s: cbor type", __func__);
1140
0
                        goto out;
1141
0
                }
1142
24
                authdata_ext->mask |= FIDO_EXT_CRED_PROTECT;
1143
24
                authdata_ext->prot = cbor_get_uint8(val);
1144
24
        }
1145
49
1146
49
        ok = 0;
1147
54
out:
1148
54
        free(type);
1149
54
1150
54
        return (ok);
1151
49
}
1152
1153
static int
1154
decode_extensions(const unsigned char **buf, size_t *len,
1155
    fido_cred_ext_t *authdata_ext)
1156
36
{
1157
36
        cbor_item_t             *item = NULL;
1158
36
        struct cbor_load_result  cbor;
1159
36
        int                      ok = -1;
1160
36
1161
36
        fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)*buf,
1162
36
            *len);
1163
36
        fido_log_xxd(*buf, *len);
1164
36
1165
36
        memset(authdata_ext, 0, sizeof(*authdata_ext));
1166
36
1167
36
        if ((item = cbor_load(*buf, *len, &cbor)) == NULL) {
1168
6
                fido_log_debug("%s: cbor_load", __func__);
1169
6
                fido_log_xxd(*buf, *len);
1170
6
                goto fail;
1171
6
        }
1172
30
1173
30
        if (cbor_isa_map(item) == false ||
1174
30
            cbor_map_is_definite(item) == false ||
1175
30
            cbor_map_iter(item, authdata_ext, decode_extension) < 0) {
1176
3
                fido_log_debug("%s: cbor type", __func__);
1177
3
                goto fail;
1178
3
        }
1179
27
1180
27
        *buf += cbor.read;
1181
27
        *len -= cbor.read;
1182
27
1183
27
        ok = 0;
1184
36
fail:
1185
36
        if (item != NULL)
1186
36
                cbor_decref(&item);
1187
36
1188
36
        return (ok);
1189
27
}
1190
1191
static int
1192
decode_hmac_secret_aux(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1193
26
{
1194
26
        fido_blob_t     *out = arg;
1195
26
        char            *type = NULL;
1196
26
        int              ok = -1;
1197
26
1198
26
        if (cbor_string_copy(key, &type) < 0 || strcmp(type, "hmac-secret")) {
1199
3
                fido_log_debug("%s: cbor type", __func__);
1200
3
                ok = 0; /* ignore */
1201
3
                goto out;
1202
3
        }
1203
23
1204
23
        ok = cbor_bytestring_copy(val, &out->ptr, &out->len);
1205
26
out:
1206
26
        free(type);
1207
26
1208
26
        return (ok);
1209
23
}
1210
1211
static int
1212
decode_hmac_secret(const unsigned char **buf, size_t *len, fido_blob_t *out)
1213
64
{
1214
64
        cbor_item_t             *item = NULL;
1215
64
        struct cbor_load_result  cbor;
1216
64
        int                      ok = -1;
1217
64
1218
64
        fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)*buf,
1219
64
            *len);
1220
64
1221
64
        if ((item = cbor_load(*buf, *len, &cbor)) == NULL) {
1222
7
                fido_log_debug("%s: cbor_load", __func__);
1223
7
                fido_log_xxd(*buf, *len);
1224
7
                goto fail;
1225
7
        }
1226
57
1227
57
        if (cbor_isa_map(item) == false ||
1228
57
            cbor_map_is_definite(item) == false ||
1229
57
            cbor_map_size(item) != 1 ||
1230
57
            cbor_map_iter(item, out, decode_hmac_secret_aux) < 0) {
1231
33
                fido_log_debug("%s: cbor type", __func__);
1232
33
                goto fail;
1233
33
        }
1234
24
1235
24
        *buf += cbor.read;
1236
24
        *len -= cbor.read;
1237
24
1238
24
        ok = 0;
1239
64
fail:
1240
64
        if (item != NULL)
1241
64
                cbor_decref(&item);
1242
64
1243
64
        return (ok);
1244
24
}
1245
1246
int
1247
cbor_decode_cred_authdata(const cbor_item_t *item, int cose_alg,
1248
    fido_blob_t *authdata_cbor, fido_authdata_t *authdata,
1249
    fido_attcred_t *attcred, fido_cred_ext_t *authdata_ext)
1250
1.24k
{
1251
1.24k
        const unsigned char     *buf = NULL;
1252
1.24k
        size_t                   len;
1253
1.24k
        size_t                   alloc_len;
1254
1.24k
1255
1.24k
        if (cbor_isa_bytestring(item) == false ||
1256
1.24k
            cbor_bytestring_is_definite(item) == false) {
1257
1
                fido_log_debug("%s: cbor type", __func__);
1258
1
                return (-1);
1259
1
        }
1260
1.24k
1261
1.24k
        if (authdata_cbor->ptr != NULL ||
1262
1.24k
            (authdata_cbor->len = cbor_serialize_alloc(item,
1263
1.24k
            &authdata_cbor->ptr, &alloc_len)) == 0) {
1264
9
                fido_log_debug("%s: cbor_serialize_alloc", __func__);
1265
9
                return (-1);
1266
9
        }
1267
1.23k
1268
1.23k
        buf = cbor_bytestring_handle(item);
1269
1.23k
        len = cbor_bytestring_length(item);
1270
1.23k
1271
1.23k
        fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)buf, len);
1272
1.23k
        fido_log_xxd(buf, len);
1273
1.23k
1274
1.23k
        if (fido_buf_read(&buf, &len, authdata, sizeof(*authdata)) < 0) {
1275
25
                fido_log_debug("%s: fido_buf_read", __func__);
1276
25
                return (-1);
1277
25
        }
1278
1.21k
1279
1.21k
        authdata->sigcount = be32toh(authdata->sigcount);
1280
1.21k
1281
1.21k
        if (attcred != NULL) {
1282
1.21k
                if ((authdata->flags & CTAP_AUTHDATA_ATT_CRED) == 0 ||
1283
1.21k
                    decode_attcred(&buf, &len, cose_alg, attcred) < 0)
1284
616
                        return (-1);
1285
598
        }
1286
598
1287
598
        if (authdata_ext != NULL) {
1288
598
                if ((authdata->flags & CTAP_AUTHDATA_EXT_DATA) != 0 &&
1289
598
                    decode_extensions(&buf, &len, authdata_ext) < 0)
1290
9
                        return (-1);
1291
589
        }
1292
589
1293
589
        /* XXX we should probably ensure that len == 0 at this point */
1294
589
1295
589
        return (FIDO_OK);
1296
589
}
1297
1298
int
1299
cbor_decode_assert_authdata(const cbor_item_t *item, fido_blob_t *authdata_cbor,
1300
    fido_authdata_t *authdata, int *authdata_ext, fido_blob_t *hmac_secret_enc)
1301
1.33k
{
1302
1.33k
        const unsigned char     *buf = NULL;
1303
1.33k
        size_t                   len;
1304
1.33k
        size_t                   alloc_len;
1305
1.33k
1306
1.33k
        if (cbor_isa_bytestring(item) == false ||
1307
1.33k
            cbor_bytestring_is_definite(item) == false) {
1308
1
                fido_log_debug("%s: cbor type", __func__);
1309
1
                return (-1);
1310
1
        }
1311
1.33k
1312
1.33k
        if (authdata_cbor->ptr != NULL ||
1313
1.33k
            (authdata_cbor->len = cbor_serialize_alloc(item,
1314
1.33k
            &authdata_cbor->ptr, &alloc_len)) == 0) {
1315
21
                fido_log_debug("%s: cbor_serialize_alloc", __func__);
1316
21
                return (-1);
1317
21
        }
1318
1.31k
1319
1.31k
        buf = cbor_bytestring_handle(item);
1320
1.31k
        len = cbor_bytestring_length(item);
1321
1.31k
1322
1.31k
        fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)buf, len);
1323
1.31k
1324
1.31k
        if (fido_buf_read(&buf, &len, authdata, sizeof(*authdata)) < 0) {
1325
5
                fido_log_debug("%s: fido_buf_read", __func__);
1326
5
                return (-1);
1327
5
        }
1328
1.30k
1329
1.30k
        authdata->sigcount = be32toh(authdata->sigcount);
1330
1.30k
1331
1.30k
        *authdata_ext = 0;
1332
1.30k
        if ((authdata->flags & CTAP_AUTHDATA_EXT_DATA) != 0) {
1333
64
                /* XXX semantic leap: extensions -> hmac_secret */
1334
64
                if (decode_hmac_secret(&buf, &len, hmac_secret_enc) < 0) {
1335
40
                        fido_log_debug("%s: decode_hmac_secret", __func__);
1336
40
                        return (-1);
1337
40
                }
1338
24
                *authdata_ext = FIDO_EXT_HMAC_SECRET;
1339
24
        }
1340
1.30k
1341
1.30k
        /* XXX we should probably ensure that len == 0 at this point */
1342
1.30k
1343
1.30k
        return (FIDO_OK);
1344
1.30k
}
1345
1346
static int
1347
decode_x5c(const cbor_item_t *item, void *arg)
1348
95
{
1349
95
        fido_blob_t *x5c = arg;
1350
95
1351
95
        if (x5c->len)
1352
18
                return (0); /* ignore */
1353
77
1354
77
        return (cbor_bytestring_copy(item, &x5c->ptr, &x5c->len));
1355
77
}
1356
1357
static int
1358
decode_attstmt_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1359
443
{
1360
443
        fido_attstmt_t  *attstmt = arg;
1361
443
        char            *name = NULL;
1362
443
        int              cose_alg = 0;
1363
443
        int              ok = -1;
1364
443
1365
443
        if (cbor_string_copy(key, &name) < 0) {
1366
23
                fido_log_debug("%s: cbor type", __func__);
1367
23
                ok = 0; /* ignore */
1368
23
                goto out;
1369
23
        }
1370
420
1371
420
        if (!strcmp(name, "alg")) {
1372
148
                if (cbor_isa_negint(val) == false ||
1373
148
                    cbor_get_int(val) > UINT16_MAX) {
1374
5
                        fido_log_debug("%s: alg", __func__);
1375
5
                        goto out;
1376
5
                }
1377
143
                if ((cose_alg = -(int)cbor_get_int(val) - 1) != COSE_ES256 &&
1378
143
                    cose_alg != COSE_RS256 && cose_alg != COSE_EDDSA) {
1379
10
                        fido_log_debug("%s: unsupported cose_alg=%d", __func__,
1380
10
                            cose_alg);
1381
10
                        goto out;
1382
10
                }
1383
272
        } else if (!strcmp(name, "sig")) {
1384
128
                if (cbor_bytestring_copy(val, &attstmt->sig.ptr,
1385
128
                    &attstmt->sig.len) < 0) {
1386
1
                        fido_log_debug("%s: sig", __func__);
1387
1
                        goto out;
1388
1
                }
1389
144
        } else if (!strcmp(name, "x5c")) {
1390
85
                if (cbor_isa_array(val) == false ||
1391
85
                    cbor_array_is_definite(val) == false ||
1392
85
                    cbor_array_iter(val, &attstmt->x5c, decode_x5c) < 0) {
1393
9
                        fido_log_debug("%s: x5c", __func__);
1394
9
                        goto out;
1395
9
                }
1396
395
        }
1397
395
1398
395
        ok = 0;
1399
443
out:
1400
443
        free(name);
1401
443
1402
443
        return (ok);
1403
395
}
1404
1405
int
1406
cbor_decode_attstmt(const cbor_item_t *item, fido_attstmt_t *attstmt)
1407
173
{
1408
173
        if (cbor_isa_map(item) == false ||
1409
173
            cbor_map_is_definite(item) == false ||
1410
173
            cbor_map_iter(item, attstmt, decode_attstmt_entry) < 0) {
1411
53
                fido_log_debug("%s: cbor type", __func__);
1412
53
                return (-1);
1413
53
        }
1414
120
1415
120
        return (0);
1416
120
}
1417
1418
int
1419
cbor_decode_uint64(const cbor_item_t *item, uint64_t *n)
1420
11.6k
{
1421
11.6k
        if (cbor_isa_uint(item) == false) {
1422
39
                fido_log_debug("%s: cbor type", __func__);
1423
39
                return (-1);
1424
39
        }
1425
11.6k
1426
11.6k
        *n = cbor_get_int(item);
1427
11.6k
1428
11.6k
        return (0);
1429
11.6k
}
1430
1431
static int
1432
decode_cred_id_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1433
2.68k
{
1434
2.68k
        fido_blob_t     *id = arg;
1435
2.68k
        char            *name = NULL;
1436
2.68k
        int              ok = -1;
1437
2.68k
1438
2.68k
        if (cbor_string_copy(key, &name) < 0) {
1439
189
                fido_log_debug("%s: cbor type", __func__);
1440
189
                ok = 0; /* ignore */
1441
189
                goto out;
1442
189
        }
1443
2.49k
1444
2.49k
        if (!strcmp(name, "id"))
1445
916
                if (cbor_bytestring_copy(val, &id->ptr, &id->len) < 0) {
1446
6
                        fido_log_debug("%s: cbor_bytestring_copy", __func__);
1447
6
                        goto out;
1448
6
                }
1449
2.48k
1450
2.48k
        ok = 0;
1451
2.68k
out:
1452
2.68k
        free(name);
1453
2.68k
1454
2.68k
        return (ok);
1455
2.48k
}
1456
1457
int
1458
cbor_decode_cred_id(const cbor_item_t *item, fido_blob_t *id)
1459
1.30k
{
1460
1.30k
        if (cbor_isa_map(item) == false ||
1461
1.30k
            cbor_map_is_definite(item) == false ||
1462
1.30k
            cbor_map_iter(item, id, decode_cred_id_entry) < 0) {
1463
36
                fido_log_debug("%s: cbor type", __func__);
1464
36
                return (-1);
1465
36
        }
1466
1.27k
1467
1.27k
        return (0);
1468
1.27k
}
1469
1470
static int
1471
decode_user_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1472
3.03k
{
1473
3.03k
        fido_user_t     *user = arg;
1474
3.03k
        char            *name = NULL;
1475
3.03k
        int              ok = -1;
1476
3.03k
1477
3.03k
        if (cbor_string_copy(key, &name) < 0) {
1478
47
                fido_log_debug("%s: cbor type", __func__);
1479
47
                ok = 0; /* ignore */
1480
47
                goto out;
1481
47
        }
1482
2.99k
1483
2.99k
        if (!strcmp(name, "icon")) {
1484
3
                if (cbor_string_copy(val, &user->icon) < 0) {
1485
1
                        fido_log_debug("%s: icon", __func__);
1486
1
                        goto out;
1487
1
                }
1488
2.98k
        } else if (!strcmp(name, "name")) {
1489
376
                if (cbor_string_copy(val, &user->name) < 0) {
1490
2
                        fido_log_debug("%s: name", __func__);
1491
2
                        goto out;
1492
2
                }
1493
2.61k
        } else if (!strcmp(name, "displayName")) {
1494
93
                if (cbor_string_copy(val, &user->display_name) < 0) {
1495
1
                        fido_log_debug("%s: display_name", __func__);
1496
1
                        goto out;
1497
1
                }
1498
2.52k
        } else if (!strcmp(name, "id")) {
1499
813
                if (cbor_bytestring_copy(val, &user->id.ptr, &user->id.len) < 0) {
1500
2
                        fido_log_debug("%s: id", __func__);
1501
2
                        goto out;
1502
2
                }
1503
2.98k
        }
1504
2.98k
1505
2.98k
        ok = 0;
1506
3.03k
out:
1507
3.03k
        free(name);
1508
3.03k
1509
3.03k
        return (ok);
1510
2.98k
}
1511
1512
int
1513
cbor_decode_user(const cbor_item_t *item, fido_user_t *user)
1514
1.15k
{
1515
1.15k
        if (cbor_isa_map(item) == false ||
1516
1.15k
            cbor_map_is_definite(item) == false ||
1517
1.15k
            cbor_map_iter(item, user, decode_user_entry) < 0) {
1518
15
                fido_log_debug("%s: cbor type", __func__);
1519
15
                return (-1);
1520
15
        }
1521
1.14k
1522
1.14k
        return (0);
1523
1.14k
}
1524
1525
static int
1526
decode_rp_entity_entry(const cbor_item_t *key, const cbor_item_t *val,
1527
    void *arg)
1528
308
{
1529
308
        fido_rp_t       *rp = arg;
1530
308
        char            *name = NULL;
1531
308
        int              ok = -1;
1532
308
1533
308
        if (cbor_string_copy(key, &name) < 0) {
1534
115
                fido_log_debug("%s: cbor type", __func__);
1535
115
                ok = 0; /* ignore */
1536
115
                goto out;
1537
115
        }
1538
193
1539
193
        if (!strcmp(name, "id")) {
1540
83
                if (cbor_string_copy(val, &rp->id) < 0) {
1541
1
                        fido_log_debug("%s: id", __func__);
1542
1
                        goto out;
1543
1
                }
1544
110
        } else if (!strcmp(name, "name")) {
1545
2
                if (cbor_string_copy(val, &rp->name) < 0) {
1546
1
                        fido_log_debug("%s: name", __func__);
1547
1
                        goto out;
1548
1
                }
1549
191
        }
1550
191
1551
191
        ok = 0;
1552
308
out:
1553
308
        free(name);
1554
308
1555
308
        return (ok);
1556
191
}
1557
1558
int
1559
cbor_decode_rp_entity(const cbor_item_t *item, fido_rp_t *rp)
1560
221
{
1561
221
        if (cbor_isa_map(item) == false ||
1562
221
            cbor_map_is_definite(item) == false ||
1563
221
            cbor_map_iter(item, rp, decode_rp_entity_entry) < 0) {
1564
10
                fido_log_debug("%s: cbor type", __func__);
1565
10
                return (-1);
1566
10
        }
1567
211
1568
211
        return (0);
1569
211
}