diff options
author | Andrej Shadura <andrew.shadura@collabora.co.uk> | 2021-10-23 16:17:11 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2021-10-27 10:15:55 +0200 |
commit | 6748031a854dc016c02839aecbe267adc5fd0153 (patch) | |
tree | f54a11679db997d1e89020995d10217cc7d9b9bd /drivers/hid/hid-u2fzero.c | |
parent | 42d43c92fc577dca59ed74aec7868abec8d6ca6e (diff) |
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: https://github.com/Nitrokey/nitrokey-fido-u2f-firmware/commit/a93c16b41f
Signed-off-by: Andrej Shadura <andrew.shadura@collabora.co.uk>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-u2fzero.c')
-rw-r--r-- | drivers/hid/hid-u2fzero.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/drivers/hid/hid-u2fzero.c b/drivers/hid/hid-u2fzero.c index d70cd3d7f583..7a7a17804247 100644 --- a/drivers/hid/hid-u2fzero.c +++ b/drivers/hid/hid-u2fzero.c @@ -26,6 +26,30 @@ #define HID_REPORT_SIZE 64 +enum hw_revision { + HW_U2FZERO, + HW_NITROKEY_U2F, +}; + +struct hw_revision_config { + u8 rng_cmd; + u8 wink_cmd; + const char *name; +}; + +static const struct hw_revision_config hw_configs[] = { + [HW_U2FZERO] = { + .rng_cmd = 0x21, + .wink_cmd = 0x24, + .name = "U2F Zero", + }, + [HW_NITROKEY_U2F] = { + .rng_cmd = 0xc0, + .wink_cmd = 0xc2, + .name = "NitroKey U2F", + }, +}; + /* We only use broadcast (CID-less) messages */ #define CID_BROADCAST 0xffffffff @@ -52,10 +76,6 @@ struct u2f_hid_report { #define U2F_HID_MSG_LEN(f) (size_t)(((f).init.bcnth << 8) + (f).init.bcntl) -/* Custom extensions to the U2FHID protocol */ -#define U2F_CUSTOM_GET_RNG 0x21 -#define U2F_CUSTOM_WINK 0x24 - struct u2fzero_device { struct hid_device *hdev; struct urb *urb; /* URB for the RNG data */ @@ -67,6 +87,7 @@ struct u2fzero_device { u8 *buf_in; struct mutex lock; bool present; + kernel_ulong_t hw_revision; }; 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) .report_type = 0, .msg.cid = CID_BROADCAST, .msg.init = { - .cmd = U2F_CUSTOM_WINK, + .cmd = hw_configs[dev->hw_revision].wink_cmd, .bcnth = 0, .bcntl = 0, .data = {0}, @@ -182,7 +203,7 @@ static int u2fzero_rng_read(struct hwrng *rng, void *data, .report_type = 0, .msg.cid = CID_BROADCAST, .msg.init = { - .cmd = U2F_CUSTOM_GET_RNG, + .cmd = hw_configs[dev->hw_revision].rng_cmd, .bcnth = 0, .bcntl = 0, .data = {0}, @@ -295,6 +316,8 @@ static int u2fzero_probe(struct hid_device *hdev, if (dev == NULL) return -ENOMEM; + dev->hw_revision = id->driver_data; + dev->buf_out = devm_kmalloc(&hdev->dev, sizeof(struct u2f_hid_report), GFP_KERNEL); if (dev->buf_out == NULL) @@ -329,7 +352,7 @@ static int u2fzero_probe(struct hid_device *hdev, return ret; } - hid_info(hdev, "U2F Zero LED initialised\n"); + hid_info(hdev, "%s LED initialised\n", hw_configs[dev->hw_revision].name); ret = u2fzero_init_hwrng(dev, minor); if (ret) { @@ -337,7 +360,7 @@ static int u2fzero_probe(struct hid_device *hdev, return ret; } - hid_info(hdev, "U2F Zero RNG initialised\n"); + hid_info(hdev, "%s RNG initialised\n", hw_configs[dev->hw_revision].name); return 0; } @@ -357,7 +380,11 @@ static void u2fzero_remove(struct hid_device *hdev) static const struct hid_device_id u2fzero_table[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, - USB_DEVICE_ID_U2F_ZERO) }, + USB_DEVICE_ID_U2F_ZERO), + .driver_data = HW_U2FZERO }, + { HID_USB_DEVICE(USB_VENDOR_ID_CLAY_LOGIC, + USB_DEVICE_ID_NITROKEY_U2F), + .driver_data = HW_NITROKEY_U2F }, { } }; MODULE_DEVICE_TABLE(hid, u2fzero_table); |