From 45fb0932c3a45978d894fcaae2c242ffa93516f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Mon, 25 Nov 2024 17:04:47 +0100 Subject: [PATCH 1/4] Add reset command for nitrokey 3 --- src/main.c | 10 ++++++++-- src/operations_ccid.c | 41 +++++++++++++++++++++++++++++++++++++++++ src/operations_ccid.h | 1 + 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index ed26932..41b1692 100644 --- a/src/main.c +++ b/src/main.c @@ -21,6 +21,7 @@ #include "ccid.h" #include "operations.h" +#include "operations_ccid.h" #include "return_codes.h" #include "utils.h" #include "operations_ccid.h" @@ -161,8 +162,13 @@ int parse_cmd_and_run(int argc, char *const *argv) { } break; case 'r': - if (argc != 3) break; - res = regenerate_AES_key(&dev, argv[2]); + if (strncmp(argv[1], "reset", 15) == 0) { + if (argc != 2) break; + res = nk3_reset(&dev); + } else if (strncmp(argv[1], "regenerate", 15) == 0) { + if (argc != 3) break; + res = regenerate_AES_key(&dev, argv[2]); + } break; default: break; diff --git a/src/operations_ccid.c b/src/operations_ccid.c index 1ca6f54..cdaf940 100644 --- a/src/operations_ccid.c +++ b/src/operations_ccid.c @@ -32,6 +32,47 @@ #include + +int nk3_reset(struct Device *dev) { + libusb_device *usb_dev; + struct libusb_device_descriptor usb_desc; + usb_dev = libusb_get_device(dev->mp_devhandle_ccid); + + int r = libusb_get_device_descriptor(usb_dev, &usb_desc); + + if (r < 0) { + return r; + } + + + if (usb_desc.idVendor != NITROKEY_USB_VID || usb_desc.idProduct != NITROKEY_3_USB_PID) { + return 0; + } + + + uint8_t buf[10]; + // encode + uint32_t icc_actual_length = iso7816_compose(buf, sizeof buf, Ins_Reset, 0xDE, 0xAD, 0, 0, NULL, 0); + + // encode ccid wrapper + icc_actual_length = icc_compose(dev->ccid_buffer_out, sizeof dev->ccid_buffer_out, + 0x6F, icc_actual_length, + 0, 0, 0, buf); + // send + IccResult iccResult; + r = ccid_process_single(dev->mp_devhandle_ccid, dev->ccid_buffer_in, sizeof dev->ccid_buffer_in, + dev->ccid_buffer_out, icc_actual_length, &iccResult); + if (r != 0) { + return r; + } + // check status code + if (iccResult.data_status_code != 0x9000) { + return 1; + } + + return RET_NO_ERROR; +} + int set_pin_ccid(struct Device *dev, const char *admin_PIN) { TLV tlvs[] = { { diff --git a/src/operations_ccid.h b/src/operations_ccid.h index 77a6fdc..20415c0 100644 --- a/src/operations_ccid.h +++ b/src/operations_ccid.h @@ -12,6 +12,7 @@ int set_secret_on_device_ccid(struct Device *dev, const char *admin_PIN, const c int verify_code_ccid(struct Device *dev, const uint32_t code_to_verify); int status_ccid(libusb_device_handle *handle, struct FullResponseStatus *full_response); int nk3_change_pin(struct Device *dev, const char *old_pin, const char*new_pin); +int nk3_reset(struct Device *dev); #endif//NITROKEY_HOTP_VERIFICATION_OPERATIONS_CCID_H From 12ba32eb823a3d895ce77052022f8da3e40172ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Mon, 2 Dec 2024 10:29:59 +0100 Subject: [PATCH 2/4] Add optional new pin when resetting --- src/main.c | 11 +++++++---- src/operations_ccid.c | 6 +++++- src/operations_ccid.h | 5 ++++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/main.c b/src/main.c index 41b1692..84c0afe 100644 --- a/src/main.c +++ b/src/main.c @@ -41,8 +41,11 @@ void print_help(char *app_name) { "\t%s check \n" "\t%s regenerate \n" "\t%s set [COUNTER]\n" - "\t%s nk3-change-pin \n", - app_name, app_name, app_name, app_name, app_name, app_name, app_name); + "\t%s nk3-change-pin \n" + "\t%s reset [ADMIN PIN]\n" + "\t%s regenerate\n" + "\t%s set [COUNTER]\n", + app_name, app_name, app_name, app_name, app_name, app_name, app_name, app_name, app_name, app_name); } @@ -163,8 +166,8 @@ int parse_cmd_and_run(int argc, char *const *argv) { break; case 'r': if (strncmp(argv[1], "reset", 15) == 0) { - if (argc != 2) break; - res = nk3_reset(&dev); + if (argc != 2 && argc != 3) break; + res = nk3_reset(&dev, argc == 3 ? argv[2]: NULL); } else if (strncmp(argv[1], "regenerate", 15) == 0) { if (argc != 3) break; res = regenerate_AES_key(&dev, argv[2]); diff --git a/src/operations_ccid.c b/src/operations_ccid.c index cdaf940..8b6ba77 100644 --- a/src/operations_ccid.c +++ b/src/operations_ccid.c @@ -33,7 +33,7 @@ -int nk3_reset(struct Device *dev) { +int nk3_reset(struct Device *dev, const char * new_pin) { libusb_device *usb_dev; struct libusb_device_descriptor usb_desc; usb_dev = libusb_get_device(dev->mp_devhandle_ccid); @@ -70,6 +70,10 @@ int nk3_reset(struct Device *dev) { return 1; } + if (new_pin != NULL) { + set_pin_ccid(dev, new_pin); + } + return RET_NO_ERROR; } diff --git a/src/operations_ccid.h b/src/operations_ccid.h index 20415c0..4d55ad8 100644 --- a/src/operations_ccid.h +++ b/src/operations_ccid.h @@ -12,7 +12,10 @@ int set_secret_on_device_ccid(struct Device *dev, const char *admin_PIN, const c int verify_code_ccid(struct Device *dev, const uint32_t code_to_verify); int status_ccid(libusb_device_handle *handle, struct FullResponseStatus *full_response); int nk3_change_pin(struct Device *dev, const char *old_pin, const char*new_pin); -int nk3_reset(struct Device *dev); +// new_pin can be `null` +// +// If it is, no new pin will be set +int nk3_reset(struct Device *dev, const char * new_pin); #endif//NITROKEY_HOTP_VERIFICATION_OPERATIONS_CCID_H From 0bbc6ea354b1f807a4d7ad4c0cd57f9cbab25a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Tue, 3 Dec 2024 10:48:27 +0100 Subject: [PATCH 3/4] Fix null pointer bug on non nk3 --- src/operations_ccid.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/operations_ccid.c b/src/operations_ccid.c index 8b6ba77..1221764 100644 --- a/src/operations_ccid.c +++ b/src/operations_ccid.c @@ -36,6 +36,12 @@ int nk3_reset(struct Device *dev, const char * new_pin) { libusb_device *usb_dev; struct libusb_device_descriptor usb_desc; + + if (!dev->mp_devhandle_ccid) { + // Not an NK3 + return RET_NO_ERROR; + } + usb_dev = libusb_get_device(dev->mp_devhandle_ccid); int r = libusb_get_device_descriptor(usb_dev, &usb_desc); @@ -46,7 +52,7 @@ int nk3_reset(struct Device *dev, const char * new_pin) { if (usb_desc.idVendor != NITROKEY_USB_VID || usb_desc.idProduct != NITROKEY_3_USB_PID) { - return 0; + return RET_NO_ERROR; } From 0c5bd3da36ea8de5b8adf7878e9260b079bc110b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Mon, 9 Dec 2024 17:42:54 +0100 Subject: [PATCH 4/4] Print warning when device is not an NK3 --- src/operations_ccid.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/operations_ccid.c b/src/operations_ccid.c index 1221764..356a1b4 100644 --- a/src/operations_ccid.c +++ b/src/operations_ccid.c @@ -39,6 +39,7 @@ int nk3_reset(struct Device *dev, const char * new_pin) { if (!dev->mp_devhandle_ccid) { // Not an NK3 + printf("No Nitrokey 3 found. No operation performed\n"); return RET_NO_ERROR; } @@ -52,6 +53,7 @@ int nk3_reset(struct Device *dev, const char * new_pin) { if (usb_desc.idVendor != NITROKEY_USB_VID || usb_desc.idProduct != NITROKEY_3_USB_PID) { + printf("No Nitrokey 3 found. No operation performed\n"); return RET_NO_ERROR; }