Coverage Report

Created: 2020-12-02 17:02

/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 <stdint.h>
8
#include <stdlib.h>
9
#include <string.h>
10
#include "fido.h"
11
12
static int
13
get_key_len(uint8_t tag, uint8_t *key, size_t *key_len)
14
21.3k
{
15
21.3k
        *key = tag & 0xfc;
16
21.3k
        if ((*key & 0xf0) == 0xf0) {
17
30
                fido_log_debug("%s: *key=0x%02x", __func__, *key);
18
30
                return (-1);
19
30
        }
20
21.3k
21
21.3k
        *key_len = tag & 0x3;
22
21.3k
        if (*key_len == 3) {
23
54
                *key_len = 4;
24
54
        }
25
21.3k
26
21.3k
        return (0);
27
21.3k
}
28
29
static int
30
get_key_val(const void *body, size_t key_len, uint32_t *val)
31
21.3k
{
32
21.3k
        const uint8_t *ptr = body;
33
21.3k
34
21.3k
        switch (key_len) {
35
14.1k
        case 0:
36
14.1k
                *val = 0;
37
14.1k
                break;
38
5.99k
        case 1:
39
5.99k
                *val = ptr[0];
40
5.99k
                break;
41
1.16k
        case 2:
42
1.16k
                *val = (uint32_t)((ptr[1] << 8) | ptr[0]);
43
1.16k
                break;
44
32
        default:
45
32
                fido_log_debug("%s: key_len=%zu", __func__, key_len);
46
32
                return (-1);
47
21.2k
        }
48
21.2k
49
21.2k
        return (0);
50
21.2k
}
51
52
int
53
fido_hid_get_usage(const uint8_t *report_ptr, size_t report_len,
54
    uint32_t *usage_page)
55
120
{
56
120
        const uint8_t   *ptr = report_ptr;
57
120
        size_t           len = report_len;
58
120
59
10.7k
        while (len > 0) {
60
10.6k
                const uint8_t tag = ptr[0];
61
10.6k
                ptr++;
62
10.6k
                len--;
63
10.6k
64
10.6k
                uint8_t  key;
65
10.6k
                size_t   key_len;
66
10.6k
                uint32_t key_val;
67
10.6k
68
10.6k
                if (get_key_len(tag, &key, &key_len) < 0 || key_len > len ||
69
10.6k
                    get_key_val(ptr, key_len, &key_val) < 0) {
70
48
                        return (-1);
71
48
                }
72
10.6k
73
10.6k
                if (key == 0x4) {
74
347
                        *usage_page = key_val;
75
347
                }
76
10.6k
77
10.6k
                ptr += key_len;
78
10.6k
                len -= key_len;
79
10.6k
        }
80
120
81
120
        return (0);
82
120
}
83
84
int
85
fido_hid_get_report_len(const uint8_t *report_ptr, size_t report_len,
86
    size_t *report_in_len, size_t *report_out_len)
87
120
{
88
120
        const uint8_t   *ptr = report_ptr;
89
120
        size_t           len = report_len;
90
120
        uint32_t         report_size = 0;
91
120
92
10.7k
        while (len > 0) {
93
10.6k
                const uint8_t tag = ptr[0];
94
10.6k
                ptr++;
95
10.6k
                len--;
96
10.6k
97
10.6k
                uint8_t  key;
98
10.6k
                size_t   key_len;
99
10.6k
                uint32_t key_val;
100
10.6k
101
10.6k
                if (get_key_len(tag, &key, &key_len) < 0 || key_len > len ||
102
10.6k
                    get_key_val(ptr, key_len, &key_val) < 0) {
103
48
                        return (-1);
104
48
                }
105
10.6k
106
10.6k
                if (key == 0x94) {
107
406
                        report_size = key_val;
108
10.2k
                } else if (key == 0x80) {
109
435
                        *report_in_len = (size_t)report_size;
110
9.80k
                } else if (key == 0x90) {
111
216
                        *report_out_len = (size_t)report_size;
112
216
                }
113
10.6k
114
10.6k
                ptr += key_len;
115
10.6k
                len -= key_len;
116
10.6k
        }
117
120
118
120
        return (0);
119
120
}
120
121
fido_dev_info_t *
122
fido_dev_info_new(size_t n)
123
0
{
124
0
        return (calloc(n, sizeof(fido_dev_info_t)));
125
0
}
126
127
void
128
fido_dev_info_free(fido_dev_info_t **devlist_p, size_t n)
129
0
{
130
0
        fido_dev_info_t *devlist;
131
0
132
0
        if (devlist_p == NULL || (devlist = *devlist_p) == NULL)
133
0
                return;
134
0
135
0
        for (size_t i = 0; i < n; i++) {
136
0
                const fido_dev_info_t *di = &devlist[i];
137
0
                free(di->path);
138
0
                free(di->manufacturer);
139
0
                free(di->product);
140
0
        }
141
0
142
0
        free(devlist);
143
0
144
0
        *devlist_p = NULL;
145
0
}
146
147
const fido_dev_info_t *
148
fido_dev_info_ptr(const fido_dev_info_t *devlist, size_t i)
149
0
{
150
0
        return (&devlist[i]);
151
0
}
152
153
const char *
154
fido_dev_info_path(const fido_dev_info_t *di)
155
0
{
156
0
        return (di->path);
157
0
}
158
159
int16_t
160
fido_dev_info_vendor(const fido_dev_info_t *di)
161
0
{
162
0
        return (di->vendor_id);
163
0
}
164
165
int16_t
166
fido_dev_info_product(const fido_dev_info_t *di)
167
0
{
168
0
        return (di->product_id);
169
0
}
170
171
const char *
172
fido_dev_info_manufacturer_string(const fido_dev_info_t *di)
173
0
{
174
0
        return (di->manufacturer);
175
0
}
176
177
const char *
178
fido_dev_info_product_string(const fido_dev_info_t *di)
179
0
{
180
0
        return (di->product);
181
0
}