diff --git a/src/main.c b/src/main.c index 9b38552..ed26932 100644 --- a/src/main.c +++ b/src/main.c @@ -23,6 +23,7 @@ #include "operations.h" #include "return_codes.h" #include "utils.h" +#include "operations_ccid.h" #include "version.h" #include #include @@ -38,8 +39,9 @@ void print_help(char *app_name) { "\t%s version\n" "\t%s check \n" "\t%s regenerate \n" - "\t%s set [COUNTER]\n", - app_name, app_name, app_name, app_name, app_name, app_name); + "\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); } @@ -144,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; { diff --git a/src/operations_ccid.c b/src/operations_ccid.c index 25772e5..1ca6f54 100644 --- a/src/operations_ccid.c +++ b/src/operations_ccid.c @@ -63,6 +63,59 @@ int set_pin_ccid(struct Device *dev, const char *admin_PIN) { return 0; } +int nk3_change_pin(struct Device *dev, const char *old_pin, const char*new_pin) { + libusb_device *usb_dev; + struct libusb_device_descriptor usb_desc; + + if (!dev->mp_devhandle_ccid) { + return RET_NO_ERROR; + } + + 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 RET_NO_ERROR; + } + + TLV tlvs[] = { + { + .tag = Tag_Password, + .length = strnlen(old_pin, MAX_PIN_SIZE_CCID), + .type = 'S', + .v_str = old_pin, + }, + { + .tag = Tag_NewPassword, + .length = strnlen(new_pin, MAX_PIN_SIZE_CCID), + .type = 'S', + .v_str = new_pin, + }, + }; + // encode + uint32_t icc_actual_length = icc_pack_tlvs_for_sending(dev->ccid_buffer_out, sizeof dev->ccid_buffer_out, + tlvs, ARR_LEN(tlvs), Ins_ChangePIN); + // 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 authenticate_ccid(struct Device *dev, const char *admin_PIN) { TLV tlvs[] = { diff --git a/src/operations_ccid.h b/src/operations_ccid.h index ea463b4..77a6fdc 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, struct FullResponseStatus *full_response); +int nk3_change_pin(struct Device *dev, const char *old_pin, const char*new_pin); #endif//NITROKEY_HOTP_VERIFICATION_OPERATIONS_CCID_H diff --git a/src/return_codes.c b/src/return_codes.c index 0ad1455..b54c2c2 100644 --- a/src/return_codes.c +++ b/src/return_codes.c @@ -55,4 +55,4 @@ int res_to_exit_code(int res) { if (res == RET_BADLY_FORMATTED_HOTP_CODE) return EXIT_BAD_FORMAT; if (res == RET_CONNECTION_LOST) return EXIT_CONNECTION_LOST; return EXIT_OTHER_ERROR; -} \ No newline at end of file +}