From 1f51267df7e3d1c9f21ecf6dd369c8f1f8c3d0d3 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Fri, 6 Dec 2024 11:36:50 -0500 Subject: [PATCH] hotp-verification: removed patches/hotp-verification-e9050e0c914e7a8ffef5d1c82a014e0e2bf79346 directory: waiting for https://github.com/Nitrokey/nitrokey-hotp-verification/pull/43 and https://github.com/Nitrokey/nitrokey-hotp-verification/pull/46 to be merged to change modules/hotp-verification commit Signed-off-by: Thierry Laurion --- .../43.patch | 450 ------------------ 1 file changed, 450 deletions(-) delete mode 100644 patches/hotp-verification-e9050e0c914e7a8ffef5d1c82a014e0e2bf79346/43.patch diff --git a/patches/hotp-verification-e9050e0c914e7a8ffef5d1c82a014e0e2bf79346/43.patch b/patches/hotp-verification-e9050e0c914e7a8ffef5d1c82a014e0e2bf79346/43.patch deleted file mode 100644 index 26ad2bc45..000000000 --- a/patches/hotp-verification-e9050e0c914e7a8ffef5d1c82a014e0e2bf79346/43.patch +++ /dev/null @@ -1,450 +0,0 @@ -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