Coverage Report

Created: 2022-01-17 10:46

/libfido2/src/hid.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
get_key_len(uint8_t tag, uint8_t *key, size_t *key_len)
11
1.59M
{
12
1.59M
        *key = tag & 0xfc;
13
1.59M
        if ((*key & 0xf0) == 0xf0) {
14
23.5k
                fido_log_debug("%s: *key=0x%02x", __func__, *key);
15
23.5k
                return (-1);
16
23.5k
        }
17
18
1.56M
        *key_len = tag & 0x3;
19
1.56M
        if (*key_len == 3) {
20
95.7k
                *key_len = 4;
21
95.7k
        }
22
23
1.56M
        return (0);
24
1.56M
}
25
26
static int
27
get_key_val(const void *body, size_t key_len, uint32_t *val)
28
1.33M
{
29
1.33M
        const uint8_t *ptr = body;
30
31
1.33M
        switch (key_len) {
32
1.15M
        case 0:
33
1.15M
                *val = 0;
34
1.15M
                break;
35
52.6k
        case 1:
36
52.6k
                *val = ptr[0];
37
52.6k
                break;
38
126k
        case 2:
39
126k
                *val = (uint32_t)((ptr[1] << 8) | ptr[0]);
40
126k
                break;
41
9.43k
        default:
42
9.43k
                fido_log_debug("%s: key_len=%zu", __func__, key_len);
43
9.43k
                return (-1);
44
1.32M
        }
45
46
1.32M
        return (0);
47
1.32M
}
48
49
int
50
fido_hid_get_usage(const uint8_t *report_ptr, size_t report_len,
51
    uint32_t *usage_page)
52
512k
{
53
512k
        const uint8_t   *ptr = report_ptr;
54
512k
        size_t           len = report_len;
55
56
1.83M
        while (len > 0) {
57
1.58M
                const uint8_t tag = ptr[0];
58
1.58M
                ptr++;
59
1.58M
                len--;
60
61
1.58M
                uint8_t  key;
62
1.58M
                size_t   key_len;
63
1.58M
                uint32_t key_val;
64
65
1.58M
                if (get_key_len(tag, &key, &key_len) < 0 || key_len > len ||
66
1.58M
                    get_key_val(ptr, key_len, &key_val) < 0) {
67
263k
                        return (-1);
68
263k
                }
69
70
1.32M
                if (key == 0x4) {
71
96.0k
                        *usage_page = key_val;
72
96.0k
                }
73
74
1.32M
                ptr += key_len;
75
1.32M
                len -= key_len;
76
1.32M
        }
77
78
512k
        return (0);
79
512k
}
80
81
int
82
fido_hid_get_report_len(const uint8_t *report_ptr, size_t report_len,
83
    size_t *report_in_len, size_t *report_out_len)
84
1.21k
{
85
1.21k
        const uint8_t   *ptr = report_ptr;
86
1.21k
        size_t           len = report_len;
87
1.21k
        uint32_t         report_size = 0;
88
89
5.12k
        while (len > 0) {
90
4.55k
                const uint8_t tag = ptr[0];
91
4.55k
                ptr++;
92
4.55k
                len--;
93
94
4.55k
                uint8_t  key;
95
4.55k
                size_t   key_len;
96
4.55k
                uint32_t key_val;
97
98
4.55k
                if (get_key_len(tag, &key, &key_len) < 0 || key_len > len ||
99
4.55k
                    get_key_val(ptr, key_len, &key_val) < 0) {
100
642
                        return (-1);
101
642
                }
102
103
3.91k
                if (key == 0x94) {
104
224
                        report_size = key_val;
105
3.68k
                } else if (key == 0x80) {
106
2.01k
                        *report_in_len = (size_t)report_size;
107
2.01k
                } else if (key == 0x90) {
108
248
                        *report_out_len = (size_t)report_size;
109
248
                }
110
111
3.91k
                ptr += key_len;
112
3.91k
                len -= key_len;
113
3.91k
        }
114
115
1.21k
        return (0);
116
1.21k
}
117
118
fido_dev_info_t *
119
fido_dev_info_new(size_t n)
120
2.41k
{
121
2.41k
        return (calloc(n, sizeof(fido_dev_info_t)));
122
2.41k
}
123
124
static void
125
fido_dev_info_reset(fido_dev_info_t *di)
126
43.6k
{
127
43.6k
        free(di->path);
128
43.6k
        free(di->manufacturer);
129
43.6k
        free(di->product);
130
43.6k
        memset(di, 0, sizeof(*di));
131
43.6k
}
132
133
void
134
fido_dev_info_free(fido_dev_info_t **devlist_p, size_t n)
135
2.42k
{
136
2.42k
        fido_dev_info_t *devlist;
137
138
2.42k
        if (devlist_p == NULL || (devlist = *devlist_p) == NULL)
139
2.42k
                return;
140
141
44.8k
        for (size_t i = 0; i < n; i++)
142
42.4k
                fido_dev_info_reset(&devlist[i]);
143
144
2.41k
        free(devlist);
145
146
2.41k
        *devlist_p = NULL;
147
2.41k
}
148
149
const fido_dev_info_t *
150
fido_dev_info_ptr(const fido_dev_info_t *devlist, size_t i)
151
1.26k
{
152
1.26k
        return (&devlist[i]);
153
1.26k
}
154
155
int
156
fido_dev_info_set(fido_dev_info_t *devlist, size_t i,
157
    const char *path, const char *manufacturer, const char *product,
158
    const fido_dev_io_t *io, const fido_dev_transport_t *transport)
159
1.26k
{
160
1.26k
        char *path_copy = NULL, *manu_copy = NULL, *prod_copy = NULL;
161
1.26k
        int r;
162
163
1.26k
        if (path == NULL || manufacturer == NULL || product == NULL ||
164
1.26k
            io == NULL) {
165
0
                r = FIDO_ERR_INVALID_ARGUMENT;
166
0
                goto out;
167
0
        }
168
169
1.26k
        if ((path_copy = strdup(path)) == NULL ||
170
1.26k
            (manu_copy = strdup(manufacturer)) == NULL ||
171
1.26k
            (prod_copy = strdup(product)) == NULL) {
172
44
                r = FIDO_ERR_INTERNAL;
173
44
                goto out;
174
44
        }
175
176
1.21k
        fido_dev_info_reset(&devlist[i]);
177
1.21k
        devlist[i].path = path_copy;
178
1.21k
        devlist[i].manufacturer = manu_copy;
179
1.21k
        devlist[i].product = prod_copy;
180
1.21k
        devlist[i].io = *io;
181
1.21k
        if (transport)
182
1.21k
                devlist[i].transport = *transport;
183
1.21k
        r = FIDO_OK;
184
1.26k
out:
185
1.26k
        if (r != FIDO_OK) {
186
44
                free(prod_copy);
187
44
                free(manu_copy);
188
44
                free(path_copy);
189
44
        }
190
1.26k
        return (r);
191
1.21k
}
192
193
const char *
194
fido_dev_info_path(const fido_dev_info_t *di)
195
2.52k
{
196
2.52k
        return (di->path);
197
2.52k
}
198
199
int16_t
200
fido_dev_info_vendor(const fido_dev_info_t *di)
201
1.26k
{
202
1.26k
        return (di->vendor_id);
203
1.26k
}
204
205
int16_t
206
fido_dev_info_product(const fido_dev_info_t *di)
207
1.26k
{
208
1.26k
        return (di->product_id);
209
1.26k
}
210
211
const char *
212
fido_dev_info_manufacturer_string(const fido_dev_info_t *di)
213
2.52k
{
214
2.52k
        return (di->manufacturer);
215
2.52k
}
216
217
const char *
218
fido_dev_info_product_string(const fido_dev_info_t *di)
219
2.52k
{
220
2.52k
        return (di->product);
221
2.52k
}