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 | } |