Skip to content

Commit

Permalink
Merge pull request #43 from Nitrokey/more-info
Browse files Browse the repository at this point in the history
Add support for nitrokey 3 distinction between the secrets app firmware and the device firmware versions
  • Loading branch information
sosthene-nitrokey committed Dec 9, 2024
2 parents e9050e0 + 707c654 commit 5d91e48
Show file tree
Hide file tree
Showing 8 changed files with 280 additions and 43 deletions.
71 changes: 70 additions & 1 deletion src/ccid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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) {

Expand Down
2 changes: 2 additions & 0 deletions src/ccid.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
29 changes: 13 additions & 16 deletions src/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
}

Expand All @@ -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) {
Expand Down Expand Up @@ -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);
}
}
2 changes: 1 addition & 1 deletion src/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
51 changes: 39 additions & 12 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "operations.h"
#include "return_codes.h"
#include "utils.h"
#include "operations_ccid.h"
#include "version.h"
#include <stdio.h>
#include <string.h>
Expand All @@ -38,8 +39,9 @@ void print_help(char *app_name) {
"\t%s version\n"
"\t%s check <HOTP CODE>\n"
"\t%s regenerate <ADMIN PIN>\n"
"\t%s set <BASE32 HOTP SECRET> <ADMIN PIN> [COUNTER]\n",
app_name, app_name, app_name, app_name, app_name, app_name);
"\t%s set <BASE32 HOTP SECRET> <ADMIN PIN> [COUNTER]\n"
"\t%s nk3-change-pin <old-pin> <new-pin>\n",
app_name, app_name, app_name, app_name, app_name, app_name, app_name);
}


Expand Down Expand Up @@ -93,25 +95,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) {
Expand All @@ -123,6 +146,10 @@ int parse_cmd_and_run(int argc, char *const *argv) {
if (argc != 3) break;
res = check_code_on_device(&dev, argv[2]);
break;
case 'n':
if (strcmp(argv[1], "nk3-change-pin") != 0 || argc != 4) break;
res = nk3_change_pin(&dev, argv[2], argv[3]);
break;
case 's':
if (argc != 4 && argc != 5) break;
{
Expand Down
Loading

0 comments on commit 5d91e48

Please sign in to comment.