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