Coverage Report

Created: 2021-03-26 11:35

/libfido2/src/info.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 "fido.h"
8
9
static int
10
decode_version(const cbor_item_t *item, void *arg)
11
20.5k
{
12
20.5k
        fido_str_array_t        *v = arg;
13
20.5k
        const size_t             i = v->len;
14
20.5k
15
20.5k
        /* keep ptr[x] and len consistent */
16
20.5k
        if (cbor_string_copy(item, &v->ptr[i]) < 0) {
17
83
                fido_log_debug("%s: cbor_string_copy", __func__);
18
83
                return (-1);
19
83
        }
20
20.4k
21
20.4k
        v->len++;
22
20.4k
23
20.4k
        return (0);
24
20.4k
}
25
26
static int
27
decode_versions(const cbor_item_t *item, fido_str_array_t *v)
28
6.80k
{
29
6.80k
        v->ptr = NULL;
30
6.80k
        v->len = 0;
31
6.80k
32
6.80k
        if (cbor_isa_array(item) == false ||
33
6.80k
            cbor_array_is_definite(item) == false) {
34
39
                fido_log_debug("%s: cbor type", __func__);
35
39
                return (-1);
36
39
        }
37
6.76k
38
6.76k
        v->ptr = calloc(cbor_array_size(item), sizeof(char *));
39
6.76k
        if (v->ptr == NULL)
40
6.76k
                return (-1);
41
6.74k
42
6.74k
        if (cbor_array_iter(item, v, decode_version) < 0) {
43
89
                fido_log_debug("%s: decode_version", __func__);
44
89
                return (-1);
45
89
        }
46
6.65k
47
6.65k
        return (0);
48
6.65k
}
49
50
static int
51
decode_extension(const cbor_item_t *item, void *arg)
52
14.6k
{
53
14.6k
        fido_str_array_t        *e = arg;
54
14.6k
        const size_t             i = e->len;
55
14.6k
56
14.6k
        /* keep ptr[x] and len consistent */
57
14.6k
        if (cbor_string_copy(item, &e->ptr[i]) < 0) {
58
55
                fido_log_debug("%s: cbor_string_copy", __func__);
59
55
                return (-1);
60
55
        }
61
14.5k
62
14.5k
        e->len++;
63
14.5k
64
14.5k
        return (0);
65
14.5k
}
66
67
static int
68
decode_extensions(const cbor_item_t *item, fido_str_array_t *e)
69
6.95k
{
70
6.95k
        e->ptr = NULL;
71
6.95k
        e->len = 0;
72
6.95k
73
6.95k
        if (cbor_isa_array(item) == false ||
74
6.95k
            cbor_array_is_definite(item) == false) {
75
37
                fido_log_debug("%s: cbor type", __func__);
76
37
                return (-1);
77
37
        }
78
6.91k
79
6.91k
        e->ptr = calloc(cbor_array_size(item), sizeof(char *));
80
6.91k
        if (e->ptr == NULL)
81
6.91k
                return (-1);
82
6.90k
83
6.90k
        if (cbor_array_iter(item, e, decode_extension) < 0) {
84
62
                fido_log_debug("%s: decode_extension", __func__);
85
62
                return (-1);
86
62
        }
87
6.84k
88
6.84k
        return (0);
89
6.84k
}
90
91
static int
92
decode_aaguid(const cbor_item_t *item, unsigned char *aaguid, size_t aaguid_len)
93
6.65k
{
94
6.65k
        if (cbor_isa_bytestring(item) == false ||
95
6.65k
            cbor_bytestring_is_definite(item) == false ||
96
6.65k
            cbor_bytestring_length(item) != aaguid_len) {
97
116
                fido_log_debug("%s: cbor type", __func__);
98
116
                return (-1);
99
116
        }
100
6.53k
101
6.53k
        memcpy(aaguid, cbor_bytestring_handle(item), aaguid_len);
102
6.53k
103
6.53k
        return (0);
104
6.53k
}
105
106
static int
107
decode_option(const cbor_item_t *key, const cbor_item_t *val, void *arg)
108
34.6k
{
109
34.6k
        fido_opt_array_t        *o = arg;
110
34.6k
        const size_t             i = o->len;
111
34.6k
112
34.6k
        if (cbor_isa_float_ctrl(val) == false ||
113
34.6k
            cbor_float_get_width(val) != CBOR_FLOAT_0 ||
114
34.6k
            cbor_is_bool(val) == false) {
115
1.55k
                fido_log_debug("%s: cbor type", __func__);
116
1.55k
                return (0); /* ignore */
117
1.55k
        }
118
33.1k
119
33.1k
        if (cbor_string_copy(key, &o->name[i]) < 0) {
120
176
                fido_log_debug("%s: cbor_string_copy", __func__);
121
176
                return (0); /* ignore */
122
176
        }
123
32.9k
124
32.9k
        /* keep name/value and len consistent */
125
32.9k
        o->value[i] = cbor_ctrl_value(val) == CBOR_CTRL_TRUE;
126
32.9k
        o->len++;
127
32.9k
128
32.9k
        return (0);
129
32.9k
}
130
131
static int
132
decode_options(const cbor_item_t *item, fido_opt_array_t *o)
133
6.48k
{
134
6.48k
        o->name = NULL;
135
6.48k
        o->value = NULL;
136
6.48k
        o->len = 0;
137
6.48k
138
6.48k
        if (cbor_isa_map(item) == false ||
139
6.48k
            cbor_map_is_definite(item) == false) {
140
34
                fido_log_debug("%s: cbor type", __func__);
141
34
                return (-1);
142
34
        }
143
6.45k
144
6.45k
        o->name = calloc(cbor_map_size(item), sizeof(char *));
145
6.45k
        o->value = calloc(cbor_map_size(item), sizeof(bool));
146
6.45k
        if (o->name == NULL || o->value == NULL)
147
6.45k
                return (-1);
148
6.42k
149
6.42k
        return (cbor_map_iter(item, o, decode_option));
150
6.42k
}
151
152
static int
153
decode_protocol(const cbor_item_t *item, void *arg)
154
7.64k
{
155
7.64k
        fido_byte_array_t       *p = arg;
156
7.64k
        const size_t             i = p->len;
157
7.64k
158
7.64k
        if (cbor_isa_uint(item) == false ||
159
7.64k
            cbor_int_get_width(item) != CBOR_INT_8) {
160
77
                fido_log_debug("%s: cbor type", __func__);
161
77
                return (-1);
162
77
        }
163
7.56k
164
7.56k
        /* keep ptr[x] and len consistent */
165
7.56k
        p->ptr[i] = cbor_get_uint8(item);
166
7.56k
        p->len++;
167
7.56k
168
7.56k
        return (0);
169
7.56k
}
170
171
static int
172
decode_protocols(const cbor_item_t *item, fido_byte_array_t *p)
173
6.15k
{
174
6.15k
        p->ptr = NULL;
175
6.15k
        p->len = 0;
176
6.15k
177
6.15k
        if (cbor_isa_array(item) == false ||
178
6.15k
            cbor_array_is_definite(item) == false) {
179
44
                fido_log_debug("%s: cbor type", __func__);
180
44
                return (-1);
181
44
        }
182
6.10k
183
6.10k
        p->ptr = calloc(cbor_array_size(item), sizeof(uint8_t));
184
6.10k
        if (p->ptr == NULL)
185
6.10k
                return (-1);
186
6.09k
187
6.09k
        if (cbor_array_iter(item, p, decode_protocol) < 0) {
188
84
                fido_log_debug("%s: decode_protocol", __func__);
189
84
                return (-1);
190
84
        }
191
6.01k
192
6.01k
        return (0);
193
6.01k
}
194
195
static int
196
parse_reply_element(const cbor_item_t *key, const cbor_item_t *val, void *arg)
197
62.1k
{
198
62.1k
        fido_cbor_info_t *ci = arg;
199
62.1k
200
62.1k
        if (cbor_isa_uint(key) == false ||
201
62.1k
            cbor_int_get_width(key) != CBOR_INT_8) {
202
2.44k
                fido_log_debug("%s: cbor type", __func__);
203
2.44k
                return (0); /* ignore */
204
2.44k
        }
205
59.7k
206
59.7k
        switch (cbor_get_uint8(key)) {
207
6.80k
        case 1: /* versions */
208
6.80k
                return (decode_versions(val, &ci->versions));
209
6.95k
        case 2: /* extensions */
210
6.95k
                return (decode_extensions(val, &ci->extensions));
211
6.65k
        case 3: /* aaguid */
212
6.65k
                return (decode_aaguid(val, ci->aaguid, sizeof(ci->aaguid)));
213
6.48k
        case 4: /* options */
214
6.48k
                return (decode_options(val, &ci->options));
215
6.25k
        case 5: /* maxMsgSize */
216
6.25k
                return (cbor_decode_uint64(val, &ci->maxmsgsiz));
217
6.15k
        case 6: /* pinProtocols */
218
6.15k
                return (decode_protocols(val, &ci->protocols));
219
5.76k
        case 7: /* maxCredentialCountInList */
220
5.76k
                return (cbor_decode_uint64(val, &ci->maxcredcntlst));
221
5.72k
        case 8: /* maxCredentialIdLength */
222
5.72k
                return (cbor_decode_uint64(val, &ci->maxcredidlen));
223
309
        case 14: /* fwVersion */
224
309
                return (cbor_decode_uint64(val, &ci->fwversion));
225
285
        case 15: /* maxCredBlobLen */
226
285
                return (cbor_decode_uint64(val, &ci->maxcredbloblen));
227
8.33k
        default: /* ignore */
228
8.33k
                fido_log_debug("%s: cbor type", __func__);
229
8.33k
                return (0);
230
59.7k
        }
231
59.7k
}
232
233
static int
234
fido_dev_get_cbor_info_tx(fido_dev_t *dev)
235
14.0k
{
236
14.0k
        const unsigned char cbor[] = { CTAP_CBOR_GETINFO };
237
14.0k
238
14.0k
        fido_log_debug("%s: dev=%p", __func__, (void *)dev);
239
14.0k
240
14.0k
        if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor)) < 0) {
241
139
                fido_log_debug("%s: fido_tx", __func__);
242
139
                return (FIDO_ERR_TX);
243
139
        }
244
13.8k
245
13.8k
        return (FIDO_OK);
246
13.8k
}
247
248
static int
249
fido_dev_get_cbor_info_rx(fido_dev_t *dev, fido_cbor_info_t *ci, int ms)
250
13.8k
{
251
13.8k
        unsigned char   reply[FIDO_MAXMSG];
252
13.8k
        int             reply_len;
253
13.8k
254
13.8k
        fido_log_debug("%s: dev=%p, ci=%p, ms=%d", __func__, (void *)dev,
255
13.8k
            (void *)ci, ms);
256
13.8k
257
13.8k
        memset(ci, 0, sizeof(*ci));
258
13.8k
259
13.8k
        if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply),
260
13.8k
            ms)) < 0) {
261
2.76k
                fido_log_debug("%s: fido_rx", __func__);
262
2.76k
                return (FIDO_ERR_RX);
263
2.76k
        }
264
11.1k
265
11.1k
        return (cbor_parse_reply(reply, (size_t)reply_len, ci,
266
11.1k
            parse_reply_element));
267
11.1k
}
268
269
int
270
fido_dev_get_cbor_info_wait(fido_dev_t *dev, fido_cbor_info_t *ci, int ms)
271
14.0k
{
272
14.0k
        int r;
273
14.0k
274
14.0k
        if ((r = fido_dev_get_cbor_info_tx(dev)) != FIDO_OK ||
275
14.0k
            (r = fido_dev_get_cbor_info_rx(dev, ci, ms)) != FIDO_OK)
276
14.0k
                return (r);
277
6.52k
278
6.52k
        return (FIDO_OK);
279
6.52k
}
280
281
int
282
fido_dev_get_cbor_info(fido_dev_t *dev, fido_cbor_info_t *ci)
283
222
{
284
222
        return (fido_dev_get_cbor_info_wait(dev, ci, -1));
285
222
}
286
287
/*
288
 * get/set functions for fido_cbor_info_t; always at the end of the file
289
 */
290
291
fido_cbor_info_t *
292
fido_cbor_info_new(void)
293
14.0k
{
294
14.0k
        return (calloc(1, sizeof(fido_cbor_info_t)));
295
14.0k
}
296
297
static void
298
free_str_array(fido_str_array_t *sa)
299
28.0k
{
300
63.0k
        for (size_t i = 0; i < sa->len; i++)
301
35.0k
                free(sa->ptr[i]);
302
28.0k
303
28.0k
        free(sa->ptr);
304
28.0k
        sa->ptr = NULL;
305
28.0k
        sa->len = 0;
306
28.0k
}
307
308
static void
309
free_opt_array(fido_opt_array_t *oa)
310
14.0k
{
311
46.9k
        for (size_t i = 0; i < oa->len; i++)
312
32.9k
                free(oa->name[i]);
313
14.0k
314
14.0k
        free(oa->name);
315
14.0k
        free(oa->value);
316
14.0k
        oa->name = NULL;
317
14.0k
        oa->value = NULL;
318
14.0k
}
319
320
static void
321
free_byte_array(fido_byte_array_t *ba)
322
14.0k
{
323
14.0k
        free(ba->ptr);
324
14.0k
325
14.0k
        ba->ptr = NULL;
326
14.0k
        ba->len = 0;
327
14.0k
}
328
329
void
330
fido_cbor_info_free(fido_cbor_info_t **ci_p)
331
45.3k
{
332
45.3k
        fido_cbor_info_t *ci;
333
45.3k
334
45.3k
        if (ci_p == NULL || (ci = *ci_p) ==  NULL)
335
45.3k
                return;
336
14.0k
337
14.0k
        free_str_array(&ci->versions);
338
14.0k
        free_str_array(&ci->extensions);
339
14.0k
        free_opt_array(&ci->options);
340
14.0k
        free_byte_array(&ci->protocols);
341
14.0k
        free(ci);
342
14.0k
343
14.0k
        *ci_p = NULL;
344
14.0k
}
345
346
char **
347
fido_cbor_info_versions_ptr(const fido_cbor_info_t *ci)
348
293
{
349
293
        return (ci->versions.ptr);
350
293
}
351
352
size_t
353
fido_cbor_info_versions_len(const fido_cbor_info_t *ci)
354
515
{
355
515
        return (ci->versions.len);
356
515
}
357
358
char **
359
fido_cbor_info_extensions_ptr(const fido_cbor_info_t *ci)
360
6.63k
{
361
6.63k
        return (ci->extensions.ptr);
362
6.63k
}
363
364
size_t
365
fido_cbor_info_extensions_len(const fido_cbor_info_t *ci)
366
6.85k
{
367
6.85k
        return (ci->extensions.len);
368
6.85k
}
369
370
const unsigned char *
371
fido_cbor_info_aaguid_ptr(const fido_cbor_info_t *ci)
372
222
{
373
222
        return (ci->aaguid);
374
222
}
375
376
size_t
377
fido_cbor_info_aaguid_len(const fido_cbor_info_t *ci)
378
222
{
379
222
        return (sizeof(ci->aaguid));
380
222
}
381
382
char **
383
fido_cbor_info_options_name_ptr(const fido_cbor_info_t *ci)
384
6.62k
{
385
6.62k
        return (ci->options.name);
386
6.62k
}
387
388
const bool *
389
fido_cbor_info_options_value_ptr(const fido_cbor_info_t *ci)
390
6.62k
{
391
6.62k
        return (ci->options.value);
392
6.62k
}
393
394
size_t
395
fido_cbor_info_options_len(const fido_cbor_info_t *ci)
396
6.85k
{
397
6.85k
        return (ci->options.len);
398
6.85k
}
399
400
uint64_t
401
fido_cbor_info_maxcredbloblen(const fido_cbor_info_t *ci)
402
222
{
403
222
        return (ci->maxcredbloblen);
404
222
}
405
406
uint64_t
407
fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *ci)
408
6.73k
{
409
6.73k
        return (ci->maxmsgsiz);
410
6.73k
}
411
412
uint64_t
413
fido_cbor_info_maxcredcntlst(const fido_cbor_info_t *ci)
414
222
{
415
222
        return (ci->maxcredcntlst);
416
222
}
417
418
uint64_t
419
fido_cbor_info_maxcredidlen(const fido_cbor_info_t *ci)
420
222
{
421
222
        return (ci->maxcredidlen);
422
222
}
423
424
uint64_t
425
fido_cbor_info_fwversion(const fido_cbor_info_t *ci)
426
222
{
427
222
        return (ci->fwversion);
428
222
}
429
430
const uint8_t *
431
fido_cbor_info_protocols_ptr(const fido_cbor_info_t *ci)
432
6.73k
{
433
6.73k
        return (ci->protocols.ptr);
434
6.73k
}
435
436
size_t
437
fido_cbor_info_protocols_len(const fido_cbor_info_t *ci)
438
6.73k
{
439
6.73k
        return (ci->protocols.len);
440
6.73k
}