Skip to content

Commit 6748031

Browse files
andrewshaduraJiri Kosina
authored andcommitted
HID: u2fzero: Support NitroKey U2F revision of the device
NitroKey produced a clone of U2F Zero with a different firmware, which moved extra commands into the vendor range. Disambiguate hardware revisions and select the correct configuration in u2fzero_probe. Link: Nitrokey/nitrokey-fido-u2f-firmware@a93c16b41f Signed-off-by: Andrej Shadura <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 42d43c9 commit 6748031

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed

drivers/hid/hid-ids.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,9 @@
288288
#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020 0x0020
289289
#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040 0x0040
290290

291+
#define USB_VENDOR_ID_CLAY_LOGIC 0x20a0
292+
#define USB_DEVICE_ID_NITROKEY_U2F 0x4287
293+
291294
#define USB_VENDOR_ID_CMEDIA 0x0d8c
292295
#define USB_DEVICE_ID_CM109 0x000e
293296
#define USB_DEVICE_ID_CMEDIA_HS100B 0x0014

drivers/hid/hid-u2fzero.c

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,30 @@
2626

2727
#define HID_REPORT_SIZE 64
2828

29+
enum hw_revision {
30+
HW_U2FZERO,
31+
HW_NITROKEY_U2F,
32+
};
33+
34+
struct hw_revision_config {
35+
u8 rng_cmd;
36+
u8 wink_cmd;
37+
const char *name;
38+
};
39+
40+
static const struct hw_revision_config hw_configs[] = {
41+
[HW_U2FZERO] = {
42+
.rng_cmd = 0x21,
43+
.wink_cmd = 0x24,
44+
.name = "U2F Zero",
45+
},
46+
[HW_NITROKEY_U2F] = {
47+
.rng_cmd = 0xc0,
48+
.wink_cmd = 0xc2,
49+
.name = "NitroKey U2F",
50+
},
51+
};
52+
2953
/* We only use broadcast (CID-less) messages */
3054
#define CID_BROADCAST 0xffffffff
3155

@@ -52,10 +76,6 @@ struct u2f_hid_report {
5276

5377
#define U2F_HID_MSG_LEN(f) (size_t)(((f).init.bcnth << 8) + (f).init.bcntl)
5478

55-
/* Custom extensions to the U2FHID protocol */
56-
#define U2F_CUSTOM_GET_RNG 0x21
57-
#define U2F_CUSTOM_WINK 0x24
58-
5979
struct u2fzero_device {
6080
struct hid_device *hdev;
6181
struct urb *urb; /* URB for the RNG data */
@@ -67,6 +87,7 @@ struct u2fzero_device {
6787
u8 *buf_in;
6888
struct mutex lock;
6989
bool present;
90+
kernel_ulong_t hw_revision;
7091
};
7192

7293
static int u2fzero_send(struct u2fzero_device *dev, struct u2f_hid_report *req)
@@ -154,7 +175,7 @@ static int u2fzero_blink(struct led_classdev *ldev)
154175
.report_type = 0,
155176
.msg.cid = CID_BROADCAST,
156177
.msg.init = {
157-
.cmd = U2F_CUSTOM_WINK,
178+
.cmd = hw_configs[dev->hw_revision].wink_cmd,
158179
.bcnth = 0,
159180
.bcntl = 0,
160181
.data = {0},
@@ -182,7 +203,7 @@ static int u2fzero_rng_read(struct hwrng *rng, void *data,
182203
.report_type = 0,
183204
.msg.cid = CID_BROADCAST,
184205
.msg.init = {
185-
.cmd = U2F_CUSTOM_GET_RNG,
206+
.cmd = hw_configs[dev->hw_revision].rng_cmd,
186207
.bcnth = 0,
187208
.bcntl = 0,
188209
.data = {0},
@@ -295,6 +316,8 @@ static int u2fzero_probe(struct hid_device *hdev,
295316
if (dev == NULL)
296317
return -ENOMEM;
297318

319+
dev->hw_revision = id->driver_data;
320+
298321
dev->buf_out = devm_kmalloc(&hdev->dev,
299322
sizeof(struct u2f_hid_report), GFP_KERNEL);
300323
if (dev->buf_out == NULL)
@@ -329,15 +352,15 @@ static int u2fzero_probe(struct hid_device *hdev,
329352
return ret;
330353
}
331354

332-
hid_info(hdev, "U2F Zero LED initialised\n");
355+
hid_info(hdev, "%s LED initialised\n", hw_configs[dev->hw_revision].name);
333356

334357
ret = u2fzero_init_hwrng(dev, minor);
335358
if (ret) {
336359
hid_hw_stop(hdev);
337360
return ret;
338361
}
339362

340-
hid_info(hdev, "U2F Zero RNG initialised\n");
363+
hid_info(hdev, "%s RNG initialised\n", hw_configs[dev->hw_revision].name);
341364

342365
return 0;
343366
}
@@ -357,7 +380,11 @@ static void u2fzero_remove(struct hid_device *hdev)
357380

358381
static const struct hid_device_id u2fzero_table[] = {
359382
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL,
360-
USB_DEVICE_ID_U2F_ZERO) },
383+
USB_DEVICE_ID_U2F_ZERO),
384+
.driver_data = HW_U2FZERO },
385+
{ HID_USB_DEVICE(USB_VENDOR_ID_CLAY_LOGIC,
386+
USB_DEVICE_ID_NITROKEY_U2F),
387+
.driver_data = HW_NITROKEY_U2F },
361388
{ }
362389
};
363390
MODULE_DEVICE_TABLE(hid, u2fzero_table);

0 commit comments

Comments
 (0)