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