diff options
Diffstat (limited to 'src/hid_openbsd.c')
-rw-r--r-- | src/hid_openbsd.c | 91 |
1 files changed, 24 insertions, 67 deletions
diff --git a/src/hid_openbsd.c b/src/hid_openbsd.c index 2b31dba..319f7b8 100644 --- a/src/hid_openbsd.c +++ b/src/hid_openbsd.c | |||
@@ -8,19 +8,16 @@ | |||
8 | 8 | ||
9 | #include <sys/ioctl.h> | 9 | #include <sys/ioctl.h> |
10 | #include <dev/usb/usb.h> | 10 | #include <dev/usb/usb.h> |
11 | #include <dev/usb/usbhid.h> | ||
12 | 11 | ||
13 | #include <errno.h> | 12 | #include <errno.h> |
14 | #include <fcntl.h> | 13 | #include <fcntl.h> |
15 | #include <string.h> | 14 | #include <string.h> |
16 | #include <unistd.h> | 15 | #include <unistd.h> |
17 | #include <usbhid.h> | ||
18 | #include <poll.h> | 16 | #include <poll.h> |
19 | 17 | ||
20 | #include "fido.h" | 18 | #include "fido.h" |
21 | 19 | ||
22 | #define MAX_UHID 64 | 20 | #define MAX_UHID 64 |
23 | #define MAX_REPORT_LEN (sizeof(((struct usb_ctl_report *)(NULL))->ucr_data)) | ||
24 | 21 | ||
25 | struct hid_openbsd { | 22 | struct hid_openbsd { |
26 | int fd; | 23 | int fd; |
@@ -33,11 +30,8 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
33 | { | 30 | { |
34 | size_t i; | 31 | size_t i; |
35 | char path[64]; | 32 | char path[64]; |
36 | int is_fido, fd; | 33 | int fd; |
37 | struct usb_device_info udi; | 34 | struct usb_device_info udi; |
38 | report_desc_t rdesc = NULL; | ||
39 | hid_data_t hdata = NULL; | ||
40 | hid_item_t hitem; | ||
41 | fido_dev_info_t *di; | 35 | fido_dev_info_t *di; |
42 | 36 | ||
43 | if (ilen == 0) | 37 | if (ilen == 0) |
@@ -47,7 +41,7 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
47 | return (FIDO_ERR_INVALID_ARGUMENT); | 41 | return (FIDO_ERR_INVALID_ARGUMENT); |
48 | 42 | ||
49 | for (i = *olen = 0; i < MAX_UHID && *olen < ilen; i++) { | 43 | for (i = *olen = 0; i < MAX_UHID && *olen < ilen; i++) { |
50 | snprintf(path, sizeof(path), "/dev/uhid%zu", i); | 44 | snprintf(path, sizeof(path), "/dev/fido/%zu", i); |
51 | if ((fd = open(path, O_RDWR)) == -1) { | 45 | if ((fd = open(path, O_RDWR)) == -1) { |
52 | if (errno != ENOENT && errno != ENXIO) { | 46 | if (errno != ENOENT && errno != ENXIO) { |
53 | fido_log_debug("%s: open %s: %s", __func__, | 47 | fido_log_debug("%s: open %s: %s", __func__, |
@@ -55,6 +49,7 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
55 | } | 49 | } |
56 | continue; | 50 | continue; |
57 | } | 51 | } |
52 | |||
58 | memset(&udi, 0, sizeof(udi)); | 53 | memset(&udi, 0, sizeof(udi)); |
59 | if (ioctl(fd, USB_GET_DEVICEINFO, &udi) != 0) { | 54 | if (ioctl(fd, USB_GET_DEVICEINFO, &udi) != 0) { |
60 | fido_log_debug("%s: get device info %s: %s", __func__, | 55 | fido_log_debug("%s: get device info %s: %s", __func__, |
@@ -62,35 +57,8 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
62 | close(fd); | 57 | close(fd); |
63 | continue; | 58 | continue; |
64 | } | 59 | } |
65 | if ((rdesc = hid_get_report_desc(fd)) == NULL) { | ||
66 | fido_log_debug("%s: failed to get report descriptor: %s", | ||
67 | __func__, path); | ||
68 | close(fd); | ||
69 | continue; | ||
70 | } | ||
71 | if ((hdata = hid_start_parse(rdesc, | ||
72 | 1<<hid_collection, -1)) == NULL) { | ||
73 | fido_log_debug("%s: failed to parse report descriptor: %s", | ||
74 | __func__, path); | ||
75 | hid_dispose_report_desc(rdesc); | ||
76 | close(fd); | ||
77 | continue; | ||
78 | } | ||
79 | is_fido = 0; | ||
80 | for (is_fido = 0; !is_fido;) { | ||
81 | memset(&hitem, 0, sizeof(hitem)); | ||
82 | if (hid_get_item(hdata, &hitem) <= 0) | ||
83 | break; | ||
84 | if ((hitem._usage_page & 0xFFFF0000) == 0xf1d00000) | ||
85 | is_fido = 1; | ||
86 | } | ||
87 | hid_end_parse(hdata); | ||
88 | hid_dispose_report_desc(rdesc); | ||
89 | close(fd); | 60 | close(fd); |
90 | 61 | ||
91 | if (!is_fido) | ||
92 | continue; | ||
93 | |||
94 | fido_log_debug("%s: %s: bus = 0x%02x, addr = 0x%02x", | 62 | fido_log_debug("%s: %s: bus = 0x%02x, addr = 0x%02x", |
95 | __func__, path, udi.udi_bus, udi.udi_addr); | 63 | __func__, path, udi.udi_bus, udi.udi_addr); |
96 | fido_log_debug("%s: %s: vendor = \"%s\", product = \"%s\"", | 64 | fido_log_debug("%s: %s: vendor = \"%s\", product = \"%s\"", |
@@ -116,8 +84,8 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
116 | explicit_bzero(di, sizeof(*di)); | 84 | explicit_bzero(di, sizeof(*di)); |
117 | return FIDO_ERR_INTERNAL; | 85 | return FIDO_ERR_INTERNAL; |
118 | } | 86 | } |
119 | di->vendor_id = udi.udi_vendorNo; | 87 | di->vendor_id = (int16_t)udi.udi_vendorNo; |
120 | di->product_id = udi.udi_productNo; | 88 | di->product_id = (int16_t)udi.udi_productNo; |
121 | (*olen)++; | 89 | (*olen)++; |
122 | } | 90 | } |
123 | 91 | ||
@@ -184,42 +152,15 @@ void * | |||
184 | fido_hid_open(const char *path) | 152 | fido_hid_open(const char *path) |
185 | { | 153 | { |
186 | struct hid_openbsd *ret = NULL; | 154 | struct hid_openbsd *ret = NULL; |
187 | report_desc_t rdesc = NULL; | ||
188 | int len, usb_report_id = 0; | ||
189 | 155 | ||
190 | if ((ret = calloc(1, sizeof(*ret))) == NULL || | 156 | if ((ret = calloc(1, sizeof(*ret))) == NULL || |
191 | (ret->fd = open(path, O_RDWR)) < 0) { | 157 | (ret->fd = open(path, O_RDWR)) < 0) { |
192 | free(ret); | 158 | free(ret); |
193 | return (NULL); | 159 | return (NULL); |
194 | } | 160 | } |
195 | if (ioctl(ret->fd, USB_GET_REPORT_ID, &usb_report_id) != 0) { | 161 | ret->report_in_len = ret->report_out_len = CTAP_MAX_REPORT_LEN; |
196 | fido_log_debug("%s: failed to get report ID: %s", __func__, | 162 | fido_log_debug("%s: inlen = %zu outlen = %zu", __func__, |
197 | strerror(errno)); | 163 | ret->report_in_len, ret->report_out_len); |
198 | goto fail; | ||
199 | } | ||
200 | if ((rdesc = hid_get_report_desc(ret->fd)) == NULL) { | ||
201 | fido_log_debug("%s: failed to get report descriptor", __func__); | ||
202 | goto fail; | ||
203 | } | ||
204 | if ((len = hid_report_size(rdesc, hid_input, usb_report_id)) <= 0 || | ||
205 | (size_t)len > MAX_REPORT_LEN) { | ||
206 | fido_log_debug("%s: bad input report size %d", __func__, len); | ||
207 | goto fail; | ||
208 | } | ||
209 | ret->report_in_len = (size_t)len; | ||
210 | if ((len = hid_report_size(rdesc, hid_output, usb_report_id)) <= 0 || | ||
211 | (size_t)len > MAX_REPORT_LEN) { | ||
212 | fido_log_debug("%s: bad output report size %d", __func__, len); | ||
213 | fail: | ||
214 | hid_dispose_report_desc(rdesc); | ||
215 | close(ret->fd); | ||
216 | free(ret); | ||
217 | return NULL; | ||
218 | } | ||
219 | ret->report_out_len = (size_t)len; | ||
220 | hid_dispose_report_desc(rdesc); | ||
221 | fido_log_debug("%s: USB report ID %d, inlen = %zu outlen = %zu", | ||
222 | __func__, usb_report_id, ret->report_in_len, ret->report_out_len); | ||
223 | 164 | ||
224 | /* | 165 | /* |
225 | * OpenBSD (as of 201910) has a bug that causes it to lose | 166 | * OpenBSD (as of 201910) has a bug that causes it to lose |
@@ -281,3 +222,19 @@ fido_hid_write(void *handle, const unsigned char *buf, size_t len) | |||
281 | } | 222 | } |
282 | return ((int)len); | 223 | return ((int)len); |
283 | } | 224 | } |
225 | |||
226 | size_t | ||
227 | fido_hid_report_in_len(void *handle) | ||
228 | { | ||
229 | struct hid_openbsd *ctx = handle; | ||
230 | |||
231 | return (ctx->report_in_len); | ||
232 | } | ||
233 | |||
234 | size_t | ||
235 | fido_hid_report_out_len(void *handle) | ||
236 | { | ||
237 | struct hid_openbsd *ctx = handle; | ||
238 | |||
239 | return (ctx->report_out_len); | ||
240 | } | ||