diff --git a/patches/hotp-verification-e9050e0c914e7a8ffef5d1c82a014e0e2bf79346/43.patch b/patches/hotp-verification-e9050e0c914e7a8ffef5d1c82a014e0e2bf79346/43.patch new file mode 100644 index 000000000..26ad2bc45 --- /dev/null +++ b/patches/hotp-verification-e9050e0c914e7a8ffef5d1c82a014e0e2bf79346/43.patch @@ -0,0 +1,450 @@ +From 707c6545a509eeb24a06537e5f835d786c2e657e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= +Date: Thu, 5 Dec 2024 16:44:30 +0100 +Subject: [PATCH] Add support for nitrokey 3 distinction between the secrets + app and other + +This now adds the secrets app version and the nitrokey 3 firmware version, +and also the gpg pins +--- + src/ccid.c | 71 +++++++++++++++++++++++++- + src/ccid.h | 2 + + src/device.c | 29 +++++------ + src/device.h | 2 +- + src/main.c | 41 +++++++++++---- + src/operations_ccid.c | 113 +++++++++++++++++++++++++++++++++++++----- + src/operations_ccid.h | 2 +- + src/structs.h | 19 +++++++ + 8 files changed, 238 insertions(+), 41 deletions(-) + +diff --git a/src/ccid.c b/src/ccid.c +index 9cf24a0..a2cc919 100644 +--- a/src/ccid.c ++++ b/src/ccid.c +@@ -104,7 +104,7 @@ IccResult parse_icc_result(uint8_t *buf, size_t buf_len) { + // .buffer_len = buf_len + }; + // Make sure the response do not contain overread attempts +- rassert(i.data_len < buf_len - 10); ++ rassert(i.data_len <= buf_len - 10); + return i; + } + +@@ -307,6 +307,75 @@ int send_select_ccid(libusb_device_handle *handle, uint8_t buf[], size_t buf_siz + return RET_NO_ERROR; + } + ++int send_select_nk3_admin_ccid(libusb_device_handle *handle, uint8_t buf[], size_t buf_size, IccResult *iccResult) { ++ unsigned char cmd_select[] = { ++ 0x6f, ++ 0x0E, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0xa4, ++ 0x04, ++ 0x00, ++ 0x09, ++ 0xa0, ++ 0x00, ++ 0x00, ++ 0x08, ++ 0x47, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x01, ++ }; ++ ++ check_ret( ++ ccid_process_single(handle, buf, buf_size, cmd_select, sizeof cmd_select, iccResult), ++ RET_COMM_ERROR); ++ ++ ++ return RET_NO_ERROR; ++} ++ ++int send_select_nk3_pgp_ccid(libusb_device_handle *handle, uint8_t buf[], size_t buf_size, IccResult *iccResult) { ++ unsigned char cmd_select[] = { ++ 0x6f, ++ 0x0C, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0xA4, ++ 0x04, ++ 0x00, ++ 0x06, ++ 0xD2, ++ 0x76, ++ 0x00, ++ 0x01, ++ 0x24, ++ 0x01, ++ 0x00, ++ }; ++ ++ check_ret( ++ ccid_process_single(handle, buf, buf_size, cmd_select, sizeof cmd_select, iccResult), ++ RET_COMM_ERROR); ++ ++ ++ return RET_NO_ERROR; ++} + + int ccid_init(libusb_device_handle *handle) { + +diff --git a/src/ccid.h b/src/ccid.h +index ed17dc7..3dcf106 100644 +--- a/src/ccid.h ++++ b/src/ccid.h +@@ -70,6 +70,8 @@ uint32_t icc_pack_tlvs_for_sending(uint8_t *buf, size_t buflen, TLV tlvs[], int + libusb_device_handle *get_device(libusb_context *ctx, const struct VidPid pPid[], int devices_count); + int ccid_init(libusb_device_handle *handle); + int send_select_ccid(libusb_device_handle *handle, uint8_t buf[], size_t buf_size, IccResult *iccResult); ++int send_select_nk3_admin_ccid(libusb_device_handle *handle, uint8_t buf[], size_t buf_size, IccResult *iccResult); ++int send_select_nk3_pgp_ccid(libusb_device_handle *handle, uint8_t buf[], size_t buf_size, IccResult *iccResult); + + + enum { +diff --git a/src/device.c b/src/device.c +index 4b9361e..52acece 100644 +--- a/src/device.c ++++ b/src/device.c +@@ -29,6 +29,7 @@ + #include "structs.h" + #include "utils.h" + #include ++#include + #include + #include + #include +@@ -259,23 +260,19 @@ int device_receive_buf(struct Device *dev) { + + #include "operations_ccid.h" + +-int device_get_status(struct Device *dev, struct ResponseStatus *out_status) { +- assert(out_status != NULL); ++int device_get_status(struct Device *dev, struct FullResponseStatus *out_response) { ++ assert(out_response != NULL); + assert(dev != NULL); +- memset(out_status, 0, sizeof(struct ResponseStatus)); ++ memset(out_response, 0, sizeof(struct FullResponseStatus)); ++ ++ struct ResponseStatus *out_status = &out_response->response_status; + + if (dev->connection_type == CONNECTION_CCID) { +- int counter = 0; +- uint32_t serial = 0; +- uint16_t version = 0; +- int res = status_ccid(dev->mp_devhandle_ccid, +- &counter, +- &version, +- &serial); +- out_status->retry_admin = counter; +- out_status->retry_user = counter; +- out_status->card_serial_u32 = serial; +- out_status->firmware_version = version; ++ int res = status_ccid(dev->mp_devhandle_ccid, out_response); ++ // out_status->retry_admin = counter; ++ // out_status->retry_user = counter; ++ // out_status->card_serial_u32 = serial; ++ // out_status->firmware_version = version; + return res; + } + +@@ -290,7 +287,7 @@ int device_get_status(struct Device *dev, struct ResponseStatus *out_status) { + + device_send_buf(dev, GET_STATUS); + device_receive_buf(dev); +- *out_status = *(struct ResponseStatus *) dev->packet_response.response_st.payload; ++ out_response->response_status = *(struct ResponseStatus *) dev->packet_response.response_st.payload; + + if (out_status->firmware_version_st.minor == 1) { + for (int i = 0; i < 100; ++i) { +@@ -343,4 +340,4 @@ const char *command_status_to_string(uint8_t status_code) { + void clean_buffers(struct Device *dev) { + memset(dev->ccid_buffer_in, 0, sizeof dev->ccid_buffer_in); + memset(dev->ccid_buffer_out, 0, sizeof dev->ccid_buffer_out); +-} +\ No newline at end of file ++} +diff --git a/src/device.h b/src/device.h +index c895546..97feeeb 100644 +--- a/src/device.h ++++ b/src/device.h +@@ -72,7 +72,7 @@ struct Device { + + int device_connect(struct Device *dev); + int device_disconnect(struct Device *dev); +-int device_get_status(struct Device *dev, struct ResponseStatus *out_status); ++int device_get_status(struct Device *dev, struct FullResponseStatus *out_status); + int device_send(struct Device *dev, uint8_t *in_data, size_t data_size, uint8_t command_ID); + int device_receive(struct Device *dev, uint8_t *out_data, size_t out_buffer_size); + int device_send_buf(struct Device *dev, uint8_t command_ID); +diff --git a/src/main.c b/src/main.c +index 059069e..9b38552 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -93,25 +93,46 @@ int parse_cmd_and_run(int argc, char *const *argv) { + res = RET_NO_ERROR; + break; + case 'i': {// id | info +- struct ResponseStatus status; ++ struct FullResponseStatus status; ++ memset(&status, 0, sizeof (struct FullResponseStatus)); ++ + res = device_get_status(&dev, &status); + check_ret((res != RET_NO_ERROR) && (res != RET_NO_PIN_ATTEMPTS), res); + if (strnlen(argv[1], 10) == 2 && argv[1][1] == 'd') { + // id command - print ID only +- print_card_serial(&status); ++ print_card_serial(&status.response_status); + } else { + // info command - print status + printf("Connected device status:\n"); + printf("\tCard serial: "); +- print_card_serial(&status); +- printf("\tFirmware: v%d.%d\n", +- status.firmware_version_st.major, +- status.firmware_version_st.minor); +- if (res != RET_NO_PIN_ATTEMPTS) { +- printf("\tCard counters: Admin %d, User %d\n", +- status.retry_admin, status.retry_user); ++ print_card_serial(&status.response_status); ++ if (status.device_type == Nk3) { ++ printf("\tFirmware Nitrokey 3: v%d.%d.%d\n", ++ (status.nk3_extra_info.firmware_version >> 22) & 0b1111111111, ++ (status.nk3_extra_info.firmware_version >> 6) & 0xFFFF, ++ status.nk3_extra_info.firmware_version & 0b111111); ++ printf("\tFirmware Secrets App: v%d.%d\n", ++ status.response_status.firmware_version_st.major, ++ status.response_status.firmware_version_st.minor); ++ if (res != RET_NO_PIN_ATTEMPTS) { ++ printf("\tSecrets app PIN counter: %d\n", ++ status.response_status.retry_user); ++ } else { ++ printf("\tSecrets app PIN counter: PIN is not set - set PIN before the first use\n"); ++ } ++ printf("\tGPG Card counters: Admin %d, User %d\n", ++ status.nk3_extra_info.pgp_admin_pin_retries, ++ status.nk3_extra_info.pgp_user_pin_retries); + } else { +- printf("\tCard counters: PIN is not set - set PIN before the first use\n"); ++ printf("\tFirmware: v%d.%d\n", ++ status.response_status.firmware_version_st.major, ++ status.response_status.firmware_version_st.minor); ++ if (res != RET_NO_PIN_ATTEMPTS) { ++ printf("\tCard counters: Admin %d, User %d\n", ++ status.response_status.retry_admin, status.response_status.retry_user); ++ } else { ++ printf("\tCard counters: PIN is not set - set PIN before the first use\n"); ++ } + } + } + if (res == RET_NO_PIN_ATTEMPTS) { +diff --git a/src/operations_ccid.c b/src/operations_ccid.c +index eb46124..25772e5 100644 +--- a/src/operations_ccid.c ++++ b/src/operations_ccid.c +@@ -273,14 +273,102 @@ int verify_code_ccid(struct Device *dev, const uint32_t code_to_verify) { + return RET_VALIDATION_PASSED; + } + +-int status_ccid(libusb_device_handle *handle, int *attempt_counter, uint16_t *firmware_version, uint32_t *serial_number) { ++int status_ccid(libusb_device_handle *handle, struct FullResponseStatus *full_response) { ++ rassert(full_response != NULL); ++ struct ResponseStatus *response = &full_response->response_status; + rassert(handle != NULL); +- rassert(attempt_counter != NULL); +- rassert(firmware_version != NULL); +- rassert(serial_number != NULL); + uint8_t buf[1024] = {}; + IccResult iccResult = {}; +- int r = send_select_ccid(handle, buf, sizeof buf, &iccResult); ++ bool pin_counter_is_error = false; ++ int r; ++ libusb_device *usb_dev; ++ struct libusb_device_descriptor usb_desc; ++ ++ usb_dev = libusb_get_device(handle); ++ ++ 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) { ++ full_response->device_type = Nk3; ++ } else if (usb_desc.idVendor == NITROKEY_USB_VID || usb_desc.idProduct == NITROKEY_PRO_USB_PID) { ++ full_response->device_type = NkPro2; ++ } else if (usb_desc.idVendor == NITROKEY_USB_VID || usb_desc.idProduct == NITROKEY_STORAGE_USB_PID) { ++ full_response->device_type = NkStorage; ++ } else if (usb_desc.idVendor == LIBREM_KEY_USB_VID || usb_desc.idProduct == LIBREM_KEY_USB_PID) { ++ full_response->device_type = LibremKey; ++ } ++ ++ if (full_response->device_type == Nk3) { ++ r = send_select_nk3_admin_ccid(handle, buf, sizeof buf, &iccResult); ++ if (r != RET_NO_ERROR) { ++ return r; ++ } ++ ++ uint8_t data_iso[MAX_CCID_BUFFER_SIZE] = {}; ++ uint32_t iso_actual_length = iso7816_compose( ++ data_iso, sizeof data_iso, ++ 0x61, 0, 0, 0, 4, NULL, 0); ++ ++ // encode ccid wrapper ++ uint32_t icc_actual_length = icc_compose(buf, sizeof buf, ++ 0x6F, iso_actual_length, ++ 0, 0, 0, data_iso); ++ int transferred; ++ r = ccid_send(handle, &transferred, buf, icc_actual_length); ++ if (r != 0) { ++ return r; ++ } ++ ++ r = ccid_receive(handle, &transferred, buf, sizeof buf); ++ if (r != 0) { ++ return r; ++ } ++ ++ IccResult iccResult = parse_icc_result(buf, transferred); ++ rassert(iccResult.data_status_code == 0x9000); ++ rassert(iccResult.data_len == 6); ++ full_response->nk3_extra_info.firmware_version = be32toh(*(uint32_t *) iccResult.data); ++ } ++ ++ if (full_response->device_type == Nk3) { ++ r = send_select_nk3_pgp_ccid(handle, buf, sizeof buf, &iccResult); ++ if (r != RET_NO_ERROR) { ++ return r; ++ } ++ ++ uint8_t data_iso[MAX_CCID_BUFFER_SIZE] = {}; ++ uint32_t iso_actual_length = iso7816_compose( ++ data_iso, sizeof data_iso, ++ 0xCA, 0, 0xC4, 0, 0xFF, NULL, 0); ++ ++ // encode ccid wrapper ++ uint32_t icc_actual_length = icc_compose(buf, sizeof buf, ++ 0x6F, iso_actual_length, ++ 0, 0, 0, data_iso); ++ int transferred; ++ r = ccid_send(handle, &transferred, buf, icc_actual_length); ++ if (r != 0) { ++ return r; ++ } ++ ++ r = ccid_receive(handle, &transferred, buf, sizeof buf); ++ if (r != 0) { ++ return r; ++ } ++ ++ IccResult iccResult = parse_icc_result(buf, transferred); ++ rassert(iccResult.data_status_code == 0x9000); ++ rassert(iccResult.data_len == 9); ++ full_response->nk3_extra_info.pgp_user_pin_retries = iccResult.data[4]; ++ full_response->nk3_extra_info.pgp_admin_pin_retries = iccResult.data[6]; ++ } ++ ++ r = send_select_ccid(handle, buf, sizeof buf, &iccResult); + if (r != RET_NO_ERROR) { + return r; + } +@@ -292,29 +380,30 @@ int status_ccid(libusb_device_handle *handle, int *attempt_counter, uint16_t *fi + r = get_tlv(iccResult.data, iccResult.data_len, Tag_PINCounter, &counter_tlv); + if (!(r == RET_NO_ERROR && counter_tlv.tag == Tag_PINCounter)) { + // PIN counter not found - comm error (ignore) or PIN not set +- *attempt_counter = -1; ++ pin_counter_is_error = true; + } else { +- *attempt_counter = counter_tlv.v_data[0]; ++ response->retry_admin = counter_tlv.v_data[0]; ++ response->retry_user = counter_tlv.v_data[0]; + } + + TLV serial_tlv = {}; + r = get_tlv(iccResult.data, iccResult.data_len, Tag_SerialNumber, &serial_tlv); + if (r == RET_NO_ERROR && serial_tlv.tag == Tag_SerialNumber) { +- *serial_number = be32toh(*(uint32_t *) serial_tlv.v_data); ++ response->card_serial_u32 = be32toh(*(uint32_t *) serial_tlv.v_data); + } else { + // ignore errors - unsupported or hidden serial_tlv number +- *serial_number = 0; ++ response->card_serial_u32 = 0; + } + + TLV version_tlv = {}; + r = get_tlv(iccResult.data, iccResult.data_len, Tag_Version, &version_tlv); + if (!(r == RET_NO_ERROR && version_tlv.tag == Tag_Version)) { +- *firmware_version = 0; ++ response->firmware_version = 0; + return RET_COMM_ERROR; + } +- *firmware_version = be16toh(*(uint16_t *) version_tlv.v_data); ++ response->firmware_version = be16toh(*(uint16_t *) version_tlv.v_data); + +- if (*attempt_counter == -1) { ++ if (pin_counter_is_error == true) { + return RET_NO_PIN_ATTEMPTS; + } + return RET_NO_ERROR; +diff --git a/src/operations_ccid.h b/src/operations_ccid.h +index b26b3c7..ea463b4 100644 +--- a/src/operations_ccid.h ++++ b/src/operations_ccid.h +@@ -10,7 +10,7 @@ int authenticate_ccid(struct Device *dev, const char *admin_PIN); + int authenticate_or_set_ccid(struct Device *dev, const char *admin_PIN); + int set_secret_on_device_ccid(struct Device *dev, const char *admin_PIN, const char *OTP_secret_base32, const uint64_t hotp_counter); + int verify_code_ccid(struct Device *dev, const uint32_t code_to_verify); +-int status_ccid(libusb_device_handle *handle, int *attempt_counter, uint16_t *firmware_version, uint32_t *serial_number); ++int status_ccid(libusb_device_handle *handle, struct FullResponseStatus *full_response); + + + #endif//NITROKEY_HOTP_VERIFICATION_OPERATIONS_CCID_H +diff --git a/src/structs.h b/src/structs.h +index 6309cd0..9e87134 100644 +--- a/src/structs.h ++++ b/src/structs.h +@@ -116,6 +116,25 @@ struct ResponseStatus { + uint8_t retry_user; /*not present in the firmware response for the Status command in v0.8 firmware*/ + }; + ++enum DeviceType { ++ Unknown = 0, ++ Nk3, ++ NkPro2, ++ NkStorage, ++ LibremKey, ++}; ++ ++struct FullResponseStatus { ++ enum DeviceType device_type; ++ struct ResponseStatus response_status; ++ struct { ++ // Only valid if device_type is NK3 ++ uint8_t pgp_admin_pin_retries; ++ uint8_t pgp_user_pin_retries; ++ uint32_t firmware_version; ++ } nk3_extra_info; ++}; ++ + + struct WriteToOTPSlot { + //admin auth diff --git a/patches/hotp-verification-e9050e0c914e7a8ffef5d1c82a014e0e2bf79346/46.patch b/patches/hotp-verification-e9050e0c914e7a8ffef5d1c82a014e0e2bf79346/46.patch deleted file mode 100644 index 781c10ffa..000000000 --- a/patches/hotp-verification-e9050e0c914e7a8ffef5d1c82a014e0e2bf79346/46.patch +++ /dev/null @@ -1,219 +0,0 @@ -From de355ed93ba50280bf377772082b76b7a2285185 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/3] 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 059069e..b80b71d 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 "version.h" -@@ -134,8 +135,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 eb46124..574155d 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 b26b3c7..ec0070c 100644 ---- a/src/operations_ccid.h -+++ b/src/operations_ccid.h -@@ -11,6 +11,7 @@ int authenticate_or_set_ccid(struct Device *dev, const char *admin_PIN); - int set_secret_on_device_ccid(struct Device *dev, const char *admin_PIN, const char *OTP_secret_base32, const uint64_t hotp_counter); - int verify_code_ccid(struct Device *dev, const uint32_t code_to_verify); - int status_ccid(libusb_device_handle *handle, int *attempt_counter, uint16_t *firmware_version, uint32_t *serial_number); -+int nk3_reset(struct Device *dev); - - - #endif//NITROKEY_HOTP_VERIFICATION_OPERATIONS_CCID_H - -From 8425e8c622138aef9ab207119e14f7cbedd40175 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/3] Add optional new pin when resetting - ---- - src/main.c | 9 +++++---- - src/operations_ccid.c | 6 +++++- - src/operations_ccid.h | 5 ++++- - 3 files changed, 14 insertions(+), 6 deletions(-) - -diff --git a/src/main.c b/src/main.c -index b80b71d..3f4a1cc 100644 ---- a/src/main.c -+++ b/src/main.c -@@ -38,9 +38,10 @@ void print_help(char *app_name) { - "\t%s info\n" - "\t%s version\n" - "\t%s check \n" -- "\t%s regenerate \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, app_name, app_name, app_name); - } - - -@@ -136,8 +137,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 574155d..07834ce 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 ec0070c..61cad72 100644 ---- a/src/operations_ccid.h -+++ b/src/operations_ccid.h -@@ -11,7 +11,10 @@ int authenticate_or_set_ccid(struct Device *dev, const char *admin_PIN); - int set_secret_on_device_ccid(struct Device *dev, const char *admin_PIN, const char *OTP_secret_base32, const uint64_t hotp_counter); - int verify_code_ccid(struct Device *dev, const uint32_t code_to_verify); - int status_ccid(libusb_device_handle *handle, int *attempt_counter, uint16_t *firmware_version, uint32_t *serial_number); --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 596f701985682adf6bfab06c78cbe132cbcb2aae 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/3] 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 07834ce..538d434 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; - } - -