modules/hotp-verification: revert to 1.6, add patches tested instead

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
This commit is contained in:
Thierry Laurion 2024-12-05 13:21:34 -05:00
parent c4832eed0e
commit a9d3d96ec1
No known key found for this signature in database
GPG Key ID: 9A53E1BB3FF00461
3 changed files with 672 additions and 3 deletions

View File

@ -2,12 +2,12 @@ modules-$(CONFIG_HOTPKEY) += hotp-verification
hotp-verification_depends := libusb $(musl_dep)
# v1.6 + patch from https://github.com/Nitrokey/nitrokey-hotp-verification/pull/46/commits/de355ed93ba50280bf377772082b76b7a2285185
hotp-verification_version := de355ed93ba50280bf377772082b76b7a2285185
# v1.6
hotp-verification_version := e9050e0c914e7a8ffef5d1c82a014e0e2bf79346
hotp-verification_dir := hotp-verification-$(hotp-verification_version)
hotp-verification_tar := nitrokey-hotp-verification-$(hotp-verification_version).tar.gz
hotp-verification_url := https://github.com/Nitrokey/nitrokey-hotp-verification/archive/$(hotp-verification_version).tar.gz
hotp-verification_hash := adbc2eb75257f4adda201419ed1282950a8cf86d167b2c76f708047d0b7aeaa5
hotp-verification_hash := 480c978d3585eee73b9aa5186b471d4caeeeeba411217e1544eef7cfd90312ac
hotp-verification_target := \
$(MAKE_JOBS) \

View File

@ -0,0 +1,450 @@
From 707c6545a509eeb24a06537e5f835d786c2e657e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= <sosthene@nitrokey.com>
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 <assert.h>
+#include <hidapi/hidapi.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
@@ -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

View File

@ -0,0 +1,219 @@
From de355ed93ba50280bf377772082b76b7a2285185 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= <sosthene@nitrokey.com>
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 <string.h>
+
+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?= <sosthene@nitrokey.com>
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 <HOTP CODE>\n"
- "\t%s regenerate <ADMIN PIN>\n"
+ "\t%s reset [ADMIN PIN]\n"
+ "\t%s regenerate\n"
"\t%s set <BASE32 HOTP SECRET> <ADMIN PIN> [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?= <sosthene@nitrokey.com>
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;
}