diff options
Diffstat (limited to 'nitrokey-sys')
-rw-r--r-- | nitrokey-sys/CHANGELOG.md | 26 | ||||
-rw-r--r-- | nitrokey-sys/Cargo.toml | 2 | ||||
-rw-r--r-- | nitrokey-sys/build.rs | 4 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/DeviceCommunicationExceptions.cpp (renamed from nitrokey-sys/libnitrokey-v3.4.1/DeviceCommunicationExceptions.cpp) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/LICENSE (renamed from nitrokey-sys/libnitrokey-v3.4.1/LICENSE) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/NK_C_API.cc (renamed from nitrokey-sys/libnitrokey-v3.4.1/NK_C_API.cc) | 165 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/NK_C_API.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/NK_C_API.h) | 230 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/NitrokeyManager.cc (renamed from nitrokey-sys/libnitrokey-v3.4.1/NitrokeyManager.cc) | 92 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/README.md (renamed from nitrokey-sys/libnitrokey-v3.4.1/README.md) | 103 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/command_id.cc (renamed from nitrokey-sys/libnitrokey-v3.4.1/command_id.cc) | 4 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/device.cc (renamed from nitrokey-sys/libnitrokey-v3.4.1/device.cc) | 66 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/CommandFailedException.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/CommandFailedException.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/DeviceCommunicationExceptions.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/DeviceCommunicationExceptions.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/LibraryException.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/LibraryException.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/LongOperationInProgressException.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/LongOperationInProgressException.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/NitrokeyManager.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/NitrokeyManager.h) | 11 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/command.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/command.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/command_id.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/command_id.h) | 2 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/cxx_semantics.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/cxx_semantics.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/deprecated.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/deprecated.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/device.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/device.h) | 57 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/device_proto.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/device_proto.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/dissect.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/dissect.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/hidapi/hidapi.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/hidapi/hidapi.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/log.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/log.h) | 1 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/misc.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/misc.h) | 41 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/stick10_commands.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/stick10_commands.h) | 40 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/stick10_commands_0.8.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/stick10_commands_0.8.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/stick20_commands.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/stick20_commands.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/libnitrokey/version.h (renamed from nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/version.h) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/log.cc (renamed from nitrokey-sys/libnitrokey-v3.4.1/log.cc) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/misc.cc (renamed from nitrokey-sys/libnitrokey-v3.4.1/misc.cc) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/version.cc (renamed from nitrokey-sys/libnitrokey-v3.4.1/version.cc) | 0 | ||||
-rw-r--r-- | nitrokey-sys/libnitrokey-v3.5/version.cc.in (renamed from nitrokey-sys/libnitrokey-v3.4.1/version.cc.in) | 0 | ||||
-rw-r--r-- | nitrokey-sys/src/ffi.rs | 377 |
35 files changed, 1154 insertions, 67 deletions
diff --git a/nitrokey-sys/CHANGELOG.md b/nitrokey-sys/CHANGELOG.md index a11d168..a440ca1 100644 --- a/nitrokey-sys/CHANGELOG.md +++ b/nitrokey-sys/CHANGELOG.md @@ -1,3 +1,29 @@ +# v3.5.0 (2019-07-04) +- Mark deprecated functions using the `deprecated` attribute. +- Update to libnitrokey 3.5, causing all following changes. +- New constant `NK_PWS_SLOT_COUNT`. +- New structures: + - `NK_device_info` + - `NK_status` + - `NK_SD_usage_data` + - `ReadSlot_t` +- New functions: + - `NK_get_SD_usage_data` + - `NK_get_status` + - `NK_get_status_as_string` + - `NK_list_devices` + - `NK_free_device_info` + - `NK_connect_with_path` + - `NK_enable_firmware_update_pro` + - `NK_change_firmware_password_pro` + - `NK_read_HOTP_slot` +- Deprecated functions: + - `NK_status` +- Changed the return type for `NK_get_major_firmware_version` and + `NK_get_minor_firmware_version` to `u8`. +- Changed `NK_get_progress_bar_value` to return -2 instead of 0 if an error + occurs. + # v3.4.3 (2019-10-12) - Link directly against `libnitrokey` if the `USE_SYSTEM_LIBNITROKEY` environment variable is set. diff --git a/nitrokey-sys/Cargo.toml b/nitrokey-sys/Cargo.toml index f9d304b..068670b 100644 --- a/nitrokey-sys/Cargo.toml +++ b/nitrokey-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nitrokey-sys" -version = "3.4.3" +version = "3.5.0" authors = ["Robin Krahl <robin.krahl@ireas.org>"] edition = "2018" homepage = "https://code.ireas.org/nitrokey-rs/" diff --git a/nitrokey-sys/build.rs b/nitrokey-sys/build.rs index defce72..a9d0778 100644 --- a/nitrokey-sys/build.rs +++ b/nitrokey-sys/build.rs @@ -25,8 +25,8 @@ impl string::ToString for Version { const LIBNITROKEY_VERSION: Version = Version { major: 3, - minor: 4, - patch: Some(1), + minor: 5, + patch: None, }; fn prepare_version_source( diff --git a/nitrokey-sys/libnitrokey-v3.4.1/DeviceCommunicationExceptions.cpp b/nitrokey-sys/libnitrokey-v3.5/DeviceCommunicationExceptions.cpp index 4d62aad..4d62aad 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/DeviceCommunicationExceptions.cpp +++ b/nitrokey-sys/libnitrokey-v3.5/DeviceCommunicationExceptions.cpp diff --git a/nitrokey-sys/libnitrokey-v3.4.1/LICENSE b/nitrokey-sys/libnitrokey-v3.5/LICENSE index 341c30b..341c30b 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/LICENSE +++ b/nitrokey-sys/libnitrokey-v3.5/LICENSE diff --git a/nitrokey-sys/libnitrokey-v3.4.1/NK_C_API.cc b/nitrokey-sys/libnitrokey-v3.5/NK_C_API.cc index 7d0a10e..1d3fa3a 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/NK_C_API.cc +++ b/nitrokey-sys/libnitrokey-v3.5/NK_C_API.cc @@ -27,7 +27,8 @@ #include "libnitrokey/LibraryException.h" #include "libnitrokey/cxx_semantics.h" #include "libnitrokey/stick20_commands.h" -#include "version.h" +#include "libnitrokey/device_proto.h" +#include "libnitrokey/version.h" #ifdef _MSC_VER #ifdef _WIN32 @@ -44,6 +45,7 @@ char * strndup(const char* str, size_t maxlen) { using namespace nitrokey; +const uint8_t NK_PWS_SLOT_COUNT = PWS_SLOT_COUNT; static uint8_t NK_last_command_status = 0; static const int max_string_field_length = 100; @@ -250,6 +252,10 @@ extern "C" { NK_C_API char * NK_status() { + return NK_get_status_as_string(); + } + + NK_C_API char * NK_get_status_as_string() { auto m = NitrokeyManager::instance(); return get_with_string_result([&]() { string && s = m->get_status_as_string(); @@ -259,6 +265,30 @@ extern "C" { }); } + NK_C_API int NK_get_status(struct NK_status* out) { + if (out == nullptr) { + return -1; + } + auto m = NitrokeyManager::instance(); + auto result = get_with_status([&]() { + return m->get_status(); + }, proto::stick10::GetStatus::ResponsePayload()); + auto error_code = std::get<0>(result); + if (error_code != 0) { + return error_code; + } + + auto status = std::get<1>(result); + out->firmware_version_major = status.firmware_version_st.major; + out->firmware_version_minor = status.firmware_version_st.minor; + out->serial_number_smart_card = status.card_serial_u32; + out->config_numlock = status.numlock; + out->config_capslock = status.capslock; + out->config_scrolllock = status.scrolllock; + out->otp_user_password = status.enable_user_password != 0; + return 0; + } + NK_C_API char * NK_device_serial_number() { auto m = NitrokeyManager::instance(); return get_with_string_result([&]() { @@ -687,6 +717,23 @@ extern "C" { return 0; } + NK_C_API int NK_get_SD_usage_data(struct NK_SD_usage_data* out) { + if (out == nullptr) + return -1; + auto m = NitrokeyManager::instance(); + auto result = get_with_status([&]() { + return m->get_SD_usage_data(); + }, std::make_pair<uint8_t, uint8_t>(0, 0)); + auto error_code = std::get<0>(result); + if (error_code != 0) + return error_code; + + auto data = std::get<1>(result); + out->write_level_min = std::get<0>(data); + out->write_level_max = std::get<1>(data); + + return 0; + } NK_C_API char* NK_get_SD_usage_data_as_string() { auto m = NitrokeyManager::instance(); @@ -697,19 +744,19 @@ NK_C_API char* NK_get_SD_usage_data_as_string() { NK_C_API int NK_get_progress_bar_value() { auto m = NitrokeyManager::instance(); - return get_with_result([&]() { + return std::get<1>(get_with_status([&]() { return m->get_progress_bar_value(); - }); + }, -2)); } - NK_C_API int NK_get_major_firmware_version() { + NK_C_API uint8_t NK_get_major_firmware_version() { auto m = NitrokeyManager::instance(); return get_with_result([&]() { return m->get_major_firmware_version(); }); } - NK_C_API int NK_get_minor_firmware_version() { + NK_C_API uint8_t NK_get_minor_firmware_version() { auto m = NitrokeyManager::instance(); return get_with_result([&]() { return m->get_minor_firmware_version(); @@ -736,6 +783,66 @@ NK_C_API char* NK_get_SD_usage_data_as_string() { }); } + bool copy_device_info(const DeviceInfo& source, NK_device_info* target) { + switch (source.m_deviceModel) { + case DeviceModel::PRO: + target->model = NK_PRO; + break; + case DeviceModel::STORAGE: + target->model = NK_STORAGE; + break; + default: + return false; + } + + target->path = strndup(source.m_path.c_str(), MAXIMUM_STR_REPLY_LENGTH); + target->serial_number = strndup(source.m_serialNumber.c_str(), MAXIMUM_STR_REPLY_LENGTH); + target->next = nullptr; + + return target->path && target->serial_number; + } + + NK_C_API struct NK_device_info* NK_list_devices() { + auto nm = NitrokeyManager::instance(); + return get_with_result([&]() -> NK_device_info* { + auto v = nm->list_devices(); + if (v.empty()) + return nullptr; + + auto result = new NK_device_info(); + auto ptr = result; + auto first = v.begin(); + if (!copy_device_info(*first, ptr)) { + NK_free_device_info(result); + return nullptr; + } + v.erase(first); + + for (auto& info : v) { + ptr->next = new NK_device_info(); + ptr = ptr->next; + + if (!copy_device_info(info, ptr)) { + NK_free_device_info(result); + return nullptr; + } + } + return result; + }); + } + + NK_C_API void NK_free_device_info(struct NK_device_info* device_info) { + if (!device_info) + return; + + if (device_info->next) + NK_free_device_info(device_info->next); + + free(device_info->path); + free(device_info->serial_number); + delete device_info; + } + NK_C_API int NK_connect_with_ID(const char* id) { auto m = NitrokeyManager::instance(); return get_with_result([&]() { @@ -743,6 +850,14 @@ NK_C_API char* NK_get_SD_usage_data_as_string() { }); } + NK_C_API int NK_connect_with_path(const char* path) { + auto m = NitrokeyManager::instance(); + return get_with_result([&]() { + return m->connect_with_path(path) ? 1 : 0; + }); + } + + NK_C_API int NK_wink() { auto m = NitrokeyManager::instance(); return get_without_result([&]() { @@ -750,6 +865,46 @@ NK_C_API char* NK_get_SD_usage_data_as_string() { }); } + NK_C_API int NK_enable_firmware_update_pro(const char* update_password){ + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->enable_firmware_update_pro(update_password); + }); +} + + NK_C_API int NK_change_firmware_password_pro(const char *current_firmware_password, const char *new_firmware_password) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->change_firmware_update_password_pro(current_firmware_password, + new_firmware_password); + }); + } + + + NK_C_API int NK_read_HOTP_slot(const uint8_t slot_num, struct ReadSlot_t* out){ + if (out == nullptr) + return -1; + auto m = NitrokeyManager::instance(); + auto result = get_with_status([&]() { + return m->get_HOTP_slot_data(slot_num); + }, stick10::ReadSlot::ResponsePayload() ); + auto error_code = std::get<0>(result); + if (error_code != 0) { + return error_code; + } +#define a(x) out->x = read_slot.x + stick10::ReadSlot::ResponsePayload read_slot = std::get<1>(result); + a(_slot_config); + a(slot_counter); +#undef a +#define m(x) memmove(out->x, read_slot.x, sizeof(read_slot.x)) + m(slot_name); + m(slot_token_id); +#undef m + return 0; +} + + #ifdef __cplusplus } #endif diff --git a/nitrokey-sys/libnitrokey-v3.4.1/NK_C_API.h b/nitrokey-sys/libnitrokey-v3.5/NK_C_API.h index b1bdf1e..d5c54a3 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/NK_C_API.h +++ b/nitrokey-sys/libnitrokey-v3.5/NK_C_API.h @@ -33,10 +33,67 @@ #define NK_C_API #endif +/** + * \file + * + * C API for libnitrokey + * + * \mainpage + * + * **libnitrokey** provides access to Nitrokey Pro and Nitrokey Storage devices. + * This documentation describes libnitrokey’s C API. For a list of the + * available functions, see the NK_C_API.h file. + * + * \section getting_started Example + * + * \code{.c} + * #include <stdio.h> + * #include <stdlib.h> + * #include <libnitrokey/NK_C_API.h> + * + * int main(void) + * { + * if (NK_login_auto() != 1) { + * fprintf(stderr, "No Nitrokey found.\n"); + * return 1; + * } + * + * NK_device_model model = NK_get_device_model(); + * printf("Connected to "); + * switch (model) { + * case NK_PRO: + * printf("a Nitrokey Pro"); + * break; + * case NK_STORAGE: + * printf("a Nitrokey Storage"); + * break; + * default: + * printf("an unsupported Nitrokey"); + * break; + * } + * + * char* serial_number = NK_device_serial_number(); + * if (serial_number) + * printf(" with serial number %s\n", serial_number); + * else + * printf(" -- could not query serial number!\n"); + * free(serial_number); + * + * NK_logout(); + * return 0; + * } + * \endcode + */ + #ifdef __cplusplus extern "C" { #endif + /** + * The number of slots in the password safe. + */ + extern const uint8_t NK_PWS_SLOT_COUNT; + static const int MAXIMUM_STR_REPLY_LENGTH = 8192; /** @@ -57,6 +114,70 @@ extern "C" { NK_STORAGE = 2 }; + /** + * The connection info for a Nitrokey device as a linked list. + */ + struct NK_device_info { + /** + * The model of the Nitrokey device. + */ + enum NK_device_model model; + /** + * The USB device path for NK_connect_with_path. + */ + char* path; + /** + * The serial number. + */ + char* serial_number; + /** + * The pointer to the next element of the linked list or null + * if this is the last element in the list. + */ + struct NK_device_info* next; + }; + + /** + * Stores the common device status for all Nitrokey devices. + */ + struct NK_status { + /** + * The major firmware version, e. g. 0 in v0.40. + */ + uint8_t firmware_version_major; + /** + * The minor firmware version, e. g. 40 in v0.40. + */ + uint8_t firmware_version_minor; + /** + * The serial number of the smart card. + */ + uint32_t serial_number_smart_card; + /** + * The HOTP slot to generate a password from if the numlock + * key is pressed twice (slot 0-1, or any other value to + * disable the function). + */ + uint8_t config_numlock; + /** + * The HOTP slot to generate a password from if the capslock + * key is pressed twice (slot 0-1, or any other value to + * disable the function). + */ + uint8_t config_capslock; + /** + * The HOTP slot to generate a password from if the scrolllock + * key is pressed twice (slot 0-1, or any other value to + * disable the function). + */ + uint8_t config_scrolllock; + /** + * Indicates whether the user password is required to generate + * an OTP value. + */ + bool otp_user_password; + }; + /** * Stores the status of a Storage device. */ @@ -128,6 +249,23 @@ extern "C" { bool stick_initialized; }; + /** + * Data about the usage of the SD card. + */ + struct NK_SD_usage_data { + /** + * The minimum write level, as a percentage of the total card + * size. + */ + uint8_t write_level_min; + /** + * The maximum write level, as a percentage of the total card + * size. + */ + uint8_t write_level_max; + }; + + struct NK_storage_ProductionTest{ uint8_t FirmwareVersion_au8[2]; uint8_t FirmwareVersionInternal_u8; @@ -215,10 +353,31 @@ extern "C" { NK_C_API enum NK_device_model NK_get_device_model(); /** + * Return the debug status string. Debug purposes. This function is + * deprecated in favor of NK_get_status_as_string. + * @return string representation of the status or an empty string + * if the command failed + */ + DEPRECATED + NK_C_API char * NK_status(); + + /** * Return the debug status string. Debug purposes. + * @return string representation of the status or an empty string + * if the command failed + */ + NK_C_API char * NK_get_status_as_string(); + + /** + * Get the stick status common to all Nitrokey devices and return the + * command processing error code. If the code is zero, i. e. the + * command was successful, the storage status is written to the output + * pointer's target. The output pointer must not be null. + * + * @param out the output pointer for the status * @return command processing error code */ - NK_C_API char * NK_status(); + NK_C_API int NK_get_status(struct NK_status* out); /** * Return the device's serial number string in hex. @@ -528,13 +687,13 @@ extern "C" { * Get device's major firmware version * @return major part of the version number (e.g. 0 from 0.48, 0 from 0.7 etc.) */ - NK_C_API int NK_get_major_firmware_version(); + NK_C_API uint8_t NK_get_major_firmware_version(); /** * Get device's minor firmware version * @return minor part of the version number (e.g. 7 from 0.7, 48 from 0.48 etc.) */ - NK_C_API int NK_get_minor_firmware_version(); + NK_C_API uint8_t NK_get_minor_firmware_version(); /** * Function to determine unencrypted volume PIN type @@ -737,6 +896,17 @@ extern "C" { NK_C_API int NK_get_status_storage(struct NK_storage_status* out); /** + * Get SD card usage attributes. Usable during hidden volumes creation. + * If the command was successful (return value 0), the usage data is + * written to the output pointer’s target. The output pointer must + * not be null. + * Storage only + * @param out the output pointer for the usage data + * @return command processing error code + */ + NK_C_API int NK_get_SD_usage_data(struct NK_SD_usage_data* out); + + /** * Get SD card usage attributes as string. * Usable during hidden volumes creation. * Storage only @@ -747,7 +917,8 @@ extern "C" { /** * Get progress value of current long operation. * Storage only - * @return int in range 0-100 or -1 if device is not busy + * @return int in range 0-100 or -1 if device is not busy or -2 if an + * error occured */ NK_C_API int NK_get_progress_bar_value(); @@ -768,6 +939,19 @@ extern "C" { */ NK_C_API char* NK_list_devices_by_cpuID(); + /** + * Returns a linked list of all connected devices, or null if no devices + * are connected or an error occured. The linked list must be freed by + * calling NK_free_device_info. + * @return a linked list of all connected devices + */ + NK_C_API struct NK_device_info* NK_list_devices(); + + /** + * Free a linked list returned by NK_list_devices. + * @param the linked list to free or null + */ + NK_C_API void NK_free_device_info(struct NK_device_info* device_info); /** * Connects to the device with given ID. ID's list could be created with NK_list_devices_by_cpuID. @@ -780,11 +964,49 @@ extern "C" { NK_C_API int NK_connect_with_ID(const char* id); /** + * Connects to a device with the given path. The path is a USB device + * path as returned by hidapi. + * @param path the device path + * @return 1 on successful connection, 0 otherwise + */ + NK_C_API int NK_connect_with_path(const char* path); + + /** * Blink red and green LED alternatively and infinitely (until device is reconnected). * @return command processing error code */ NK_C_API int NK_wink(); + + /** + * Enable update mode on Nitrokey Pro. + * Supported from v0.11. + * @param update_password 20 bytes update password + * @return command processing error code + */ + NK_C_API int NK_enable_firmware_update_pro(const char* update_password); + + /** + * Change update-mode password on Nitrokey Pro. + * Supported from v0.11. + * @param current_firmware_password 20 bytes update password + * @param new_firmware_password 20 bytes update password + * @return command processing error code + */ + NK_C_API int NK_change_firmware_password_pro(const char *current_firmware_password, const char *new_firmware_password); + + +// as in ReadSlot::ResponsePayload +struct ReadSlot_t { + uint8_t slot_name[15]; + uint8_t _slot_config; + uint8_t slot_token_id[13]; + uint64_t slot_counter; +}; + + +NK_C_API int NK_read_HOTP_slot(const uint8_t slot_num, struct ReadSlot_t* out); + #ifdef __cplusplus } #endif diff --git a/nitrokey-sys/libnitrokey-v3.4.1/NitrokeyManager.cc b/nitrokey-sys/libnitrokey-v3.5/NitrokeyManager.cc index a950e4b..6c26a43 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/NitrokeyManager.cc +++ b/nitrokey-sys/libnitrokey-v3.5/NitrokeyManager.cc @@ -29,6 +29,7 @@ #include "libnitrokey/misc.h" #include <mutex> #include "libnitrokey/cxx_semantics.h" +#include "libnitrokey/misc.h" #include <functional> #include <stick10_commands.h> @@ -105,11 +106,10 @@ using nitrokey::misc::strcpyT; return true; } - std::vector<std::string> NitrokeyManager::list_devices(){ + std::vector<DeviceInfo> NitrokeyManager::list_devices(){ std::lock_guard<std::mutex> lock(mex_dev_com_manager); - auto p = make_shared<Stick20>(); - return p->enumerate(); // make static + return Device::enumerate(); } std::vector<std::string> NitrokeyManager::list_devices_by_cpuID(){ @@ -127,11 +127,13 @@ using nitrokey::misc::strcpyT; LOGD1("Enumerating devices"); std::vector<std::string> res; - auto d = make_shared<Stick20>(); - const auto v = d->enumerate(); + const auto v = Device::enumerate(); LOGD1("Discovering IDs"); - for (auto & p: v){ - d = make_shared<Stick20>(); + for (auto & i: v){ + if (i.m_deviceModel != DeviceModel::STORAGE) + continue; + auto p = i.m_path; + auto d = make_shared<Stick20>(); LOGD1( std::string("Found: ") + p ); d->set_path(p); try{ @@ -215,7 +217,26 @@ using nitrokey::misc::strcpyT; } } - auto p = make_shared<Stick20>(); + auto info_ptr = hid_enumerate(NITROKEY_VID, 0); + auto first_info_ptr = info_ptr; + if (!info_ptr) + return false; + + misc::Option<DeviceModel> model; + while (info_ptr && !model.has_value()) { + if (path == std::string(info_ptr->path)) { + model = product_id_to_model(info_ptr->product_id); + } + info_ptr = info_ptr->next; + } + hid_free_enumeration(first_info_ptr); + + if (!model.has_value()) + return false; + + auto p = Device::create(model.value()); + if (!p) + return false; p->set_path(path); if(!p->connect()) return false; @@ -422,6 +443,7 @@ using nitrokey::misc::strcpyT; return ""; } + bool NitrokeyManager::is_internal_hotp_slot_number(uint8_t slot_number) const { return slot_number < 0x20; } bool NitrokeyManager::is_valid_hotp_slot_number(uint8_t slot_number) const { return slot_number < 3; } bool NitrokeyManager::is_valid_totp_slot_number(uint8_t slot_number) const { return slot_number < 0x10-1; } //15 uint8_t NitrokeyManager::get_internal_slot_number_for_totp(uint8_t slot_number) const { return (uint8_t) (0x20 + slot_number); } @@ -885,16 +907,16 @@ using nitrokey::misc::strcpyT; //authorization command is supported for versions equal or below: auto m = std::unordered_map<DeviceModel , int, EnumClassHash>({ {DeviceModel::PRO, 7}, - {DeviceModel::STORAGE, 999}, + {DeviceModel::STORAGE, 53}, }); return get_minor_firmware_version() <= m[device->get_device_model()]; } bool NitrokeyManager::is_320_OTP_secret_supported(){ - //authorization command is supported for versions equal or below: + // 320 bit OTP secret is supported by version bigger or equal to: auto m = std::unordered_map<DeviceModel , int, EnumClassHash>({ {DeviceModel::PRO, 8}, - {DeviceModel::STORAGE, 999}, + {DeviceModel::STORAGE, 54}, }); return get_minor_firmware_version() >= m[device->get_device_model()]; } @@ -916,7 +938,7 @@ using nitrokey::misc::strcpyT; return false; } - int NitrokeyManager::get_minor_firmware_version(){ + uint8_t NitrokeyManager::get_minor_firmware_version(){ switch(device->get_device_model()){ case DeviceModel::PRO:{ auto status_p = GetStatus::CommandTransaction::run(device); @@ -932,7 +954,7 @@ using nitrokey::misc::strcpyT; } return 0; } - int NitrokeyManager::get_major_firmware_version(){ + uint8_t NitrokeyManager::get_major_firmware_version(){ switch(device->get_device_model()){ case DeviceModel::PRO:{ auto status_p = GetStatus::CommandTransaction::run(device); @@ -1099,11 +1121,31 @@ using nitrokey::misc::strcpyT; return get_TOTP_code(slot_number, 0, 0, 0, user_temporary_password); } + /** + * Returns ReadSlot structure, describing OTP slot configuration. Always return binary counter - + * does the necessary conversion, if needed, to unify the behavior across Pro and Storage. + * @private For internal use only + * @param slot_number which OTP slot to use (usual format) + * @return ReadSlot structure + */ stick10::ReadSlot::ResponsePayload NitrokeyManager::get_OTP_slot_data(const uint8_t slot_number) { auto p = get_payload<stick10::ReadSlot>(); p.slot_number = slot_number; + p.data_format = stick10::ReadSlot::CounterFormat::BINARY; // ignored for devices other than Storage v0.54+ auto data = stick10::ReadSlot::CommandTransaction::run(device, p); - return data.data(); + + auto &payload = data.data(); + + // if fw <=v0.53 and asked binary - do the conversion from ASCII + if (device->get_device_model() == DeviceModel::STORAGE && get_minor_firmware_version() <= 53 + && is_internal_hotp_slot_number(slot_number)) + { + //convert counter from string to ull + auto counter_s = std::string(payload.slot_counter_s, payload.slot_counter_s + sizeof(payload.slot_counter_s)); + payload.slot_counter = std::stoull(counter_s); + } + + return payload; } stick10::ReadSlot::ResponsePayload NitrokeyManager::get_TOTP_slot_data(const uint8_t slot_number) { @@ -1111,13 +1153,7 @@ using nitrokey::misc::strcpyT; } stick10::ReadSlot::ResponsePayload NitrokeyManager::get_HOTP_slot_data(const uint8_t slot_number) { - auto slot_data = get_OTP_slot_data(get_internal_slot_number_for_hotp(slot_number)); - if (device->get_device_model() == DeviceModel::STORAGE){ - //convert counter from string to ull - auto counter_s = std::string(slot_data.slot_counter_s, slot_data.slot_counter_s+sizeof(slot_data.slot_counter_s)); - slot_data.slot_counter = std::stoull(counter_s); - } - return slot_data; + return get_OTP_slot_data(get_internal_slot_number_for_hotp(slot_number)); } void NitrokeyManager::lock_encrypted_volume() { @@ -1146,4 +1182,18 @@ using nitrokey::misc::strcpyT; return data.data(); }; + void NitrokeyManager::enable_firmware_update_pro(const char *firmware_pin) { + auto p = get_payload<FirmwareUpdate>(); + strcpyT(p.firmware_password, firmware_pin); + FirmwareUpdate::CommandTransaction::run(device, p); + } + + void + NitrokeyManager::change_firmware_update_password_pro(const char *firmware_pin_current, const char *firmware_pin_new) { + auto p = get_payload<FirmwarePasswordChange>(); + strcpyT(p.firmware_password_current, firmware_pin_current); + strcpyT(p.firmware_password_new, firmware_pin_new); + FirmwarePasswordChange::CommandTransaction::run(device, p); + } + } diff --git a/nitrokey-sys/libnitrokey-v3.4.1/README.md b/nitrokey-sys/libnitrokey-v3.5/README.md index 81b367a..a3683c0 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/README.md +++ b/nitrokey-sys/libnitrokey-v3.5/README.md @@ -4,7 +4,7 @@ # libnitrokey libnitrokey is a project to communicate with Nitrokey Pro and Storage devices in a clean and easy manner. Written in C++14, testable with `py.test` and `Catch` frameworks, with C API, Python access (through CFFI and C API, in future with Pybind11). -The development of this project is aimed to make it itself a living documentation of communication protocol between host and the Nitrokey stick devices. The command packets' format is described here: [Pro v0.7](include/stick10_commands.h), [Pro v0.8](include/stick10_commands_0.8.h), [Storage](include/stick20_commands.h). Handling and additional operations are described here: [NitrokeyManager.cc](NitrokeyManager.cc). +The development of this project is aimed to make it itself a living documentation of communication protocol between host and the Nitrokey stick devices. The command packets' format is described here: [Pro v0.7](libnitrokey/stick10_commands.h), [Pro v0.8](libnitrokey/stick10_commands_0.8.h), [Storage](libnitrokey/stick20_commands.h). Handling and additional operations are described here: [NitrokeyManager.cc](NitrokeyManager.cc). A C++14 complying compiler is required due to heavy use of variable templates. For feature support tables please check [table 1](https://gcc.gnu.org/projects/cxx-status.html#cxx14) or [table 2](http://en.cppreference.com/w/cpp/compiler_support). @@ -44,7 +44,7 @@ qmake .. make -j2 ``` -### Windows MS Visual Studio 2017 +### Windows and Visual Studio 2017 Lately Visual Studio has started handling CMake files directly. After opening the project's directory it should recognize it and initialize build system. Afterwards please run: 1. `CMake -> Cache -> View Cache CMakeLists.txt -> CMakeLists.txt` to edit settings 2. `CMake -> Build All` to build @@ -76,6 +76,14 @@ Other build options (all take either `ON` or `OFF`): * NO_LOG (default: OFF) - do not compile LOG statements - will make library smaller, but without any diagnostic messages +### Meson +It is possible to use Meson and Ninja to build the project as well (currently available only `master` branch). +Please run: +``` +meson builddir <OPTIONS> +meson configure builddir # to show available build flags +ninja -C builddir +``` # Using libnitrokey with Python To use libnitrokey with Python a [CFFI](http://cffi.readthedocs.io/en/latest/overview.html) library is required (either 2.7+ or 3.0+). It can be installed with: @@ -155,25 +163,31 @@ In case no devices are connected, a friendly message will be printed. All available functions for C and Python are listed in [NK_C_API.h](NK_C_API.h). Please check `Documentation` section below. ## Documentation -The documentation of C API is included in the sources (could be generated with doxygen if requested). -Please check [NK_C_API.h](NK_C_API.h) (C API) for high level commands and [include/NitrokeyManager.h](include/NitrokeyManager.h) (C++ API). All devices' commands are listed along with packet format in [include/stick10_commands.h](include/stick10_commands.h) and [include/stick20_commands.h](include/stick20_commands.h) respectively for Nitrokey Pro and Nitrokey Storage products. +The documentation of C API is included in the sources (can be generated with `make doc` if Doxygen is installed). +Please check [NK_C_API.h](NK_C_API.h) (C API) for high level commands and [libnitrokey/NitrokeyManager.h](libnitrokey/NitrokeyManager.h) (C++ API). All devices' commands are listed along with packet format in [libnitrokey/stick10_commands.h](libnitrokey/stick10_commands.h) and [libnitrokey/stick20_commands.h](libnitrokey/stick20_commands.h) respectively for Nitrokey Pro and Nitrokey Storage products. # Tests -Warning! Before you run unittests please either change both your Admin and User PINs on your Nitrostick to defaults (`12345678` and `123456` respectively) or change the values in tests source code. If you do not change them the tests might lock your device and lose your data. If it's too late, you can reset your Nitrokey using instructions from [homepage](https://www.nitrokey.com/de/documentation/how-reset-nitrokey). +**Warning!** Most of the tests will overwrite user data. The only user-data safe tests are specified in `unittest/test_safe.cpp` (see *C++ tests* chapter). + +**Warning!** Before you run unittests please change both your Admin and User PINs on your Nitrostick to defaults (`12345678` and `123456` respectively), or change the values in tests source code. If you do not change them, the tests might lock your device temporarily. If it's too late already, you can reset your Nitrokey using instructions from [homepage](https://www.nitrokey.com/de/documentation/how-reset-nitrokey). ## Python tests -libnitrokey has a great suite of tests written in Python 3 under the path: `unittest/test_*.py`: +libnitrokey has a great suite of tests written in Python 3 under the path: [unittest/test_*.py](https://github.com/Nitrokey/libnitrokey/tree/master/unittest): * `test_pro.py` - contains tests of OTP, Password Safe and PIN control functionality. Could be run on both Pro and Storage devices. * `test_storage.py` - contains tests of Encrypted Volumes functionality. Could be run only on Storage. + The tests themselves show how to handle common requests to device. Before running please install all required libraries with: ```bash cd unittest pip install --user -r requirements.txt ``` +or use Python's environment managing tool like [pipenv](https://pipenv.readthedocs.io/en/latest/) or `virtualenv`. + + To run them please execute: ```bash -# substitute <dev> with either pro or storage +# substitute <dev> with either 'pro' or 'storage' py.test -v test_<dev>.py # more specific use - run tests containing in name <test_name> 5 times: py.test -v test_<dev>.py -k <test_name> --count 5 @@ -182,9 +196,76 @@ py.test -v test_<dev>.py -k <test_name> --count 5 For additional documentation please check the following for [py.test installation](http://doc.pytest.org/en/latest/getting-started.html). For better coverage [randomly plugin](https://pypi.python.org/pypi/pytest-randomly) is installed - it randomizes the test order allowing to detect unseen dependencies between the tests. ## C++ tests -There are also some unit tests implemented in C++, placed in unittest directory. They are not written as extensively as Python tests and are rather more a C++ low level interface check, often not using C++ API from `NitrokeyManager.cc`. Some of them are: [test_HOTP.cc](https://github.com/Nitrokey/libnitrokey/blob/master/unittest/test_HOTP.cc), -[test.cc](https://github.com/Nitrokey/libnitrokey/blob/master/unittest/test.cc). -Unit tests were written and tested on Ubuntu 16.04/16.10/17.04. To run them just execute binaries built in ./libnitrokey/build dir after enabling them by passing `-DCOMPILE_TESTS=ON` option like in `cmake .. -DCOMPILE_TESTS=ON && make`. +There are also some unit tests implemented in C++, placed in unittest directory. The only user-data safe online test set here is [test_safe.cpp](https://github.com/Nitrokey/libnitrokey/blob/master/unittest/test_safe.cpp), which tries to connect to the device, and collect its status data. Example run for Storage: +```text +# Storage device inserted, firmware version v0.53 +$ ./test_safe +[Wed Jan 2 13:31:17 2019][DEBUG_L1] => GET_DEVICE_STATUS +.. +[Wed Jan 2 13:31:17 2019][DEBUG_L1] <= GET_DEVICE_STATUS 0 1 +[Wed Jan 2 13:31:17 2019][DEBUG_L1] => GET_PASSWORD_RETRY_COUNT +[Wed Jan 2 13:31:17 2019][DEBUG_L1] <= GET_PASSWORD_RETRY_COUNT 0 0 +[Wed Jan 2 13:31:17 2019][DEBUG_L1] => GET_DEVICE_STATUS +.. +[Wed Jan 2 13:31:17 2019][DEBUG_L1] <= GET_DEVICE_STATUS 0 1 +[Wed Jan 2 13:31:17 2019][DEBUG_L1] => GET_USER_PASSWORD_RETRY_COUNT +[Wed Jan 2 13:31:17 2019][DEBUG_L1] <= GET_USER_PASSWORD_RETRY_COUNT 0 0 +[Wed Jan 2 13:31:17 2019][DEBUG_L1] => GET_DEVICE_STATUS +... +[Wed Jan 2 13:31:17 2019][DEBUG_L1] <= GET_DEVICE_STATUS 0 1 + transmission_data.dissect(): _padding: +0000 00 00 00 00 00 00 00 00 00 00 00 00 00 05 2e 01 ................ +0010 00 00 -- -- -- -- -- -- -- -- -- -- -- -- -- -- .. + (int) SendCounter_u8: 0 + (int) SendDataType_u8: 3 + (int) FollowBytesFlag_u8: 0 + (int) SendSize_u8: 28 + + MagicNumber_StickConfig_u16: 13080 + (int) ReadWriteFlagUncryptedVolume_u8: 1 + (int) ReadWriteFlagCryptedVolume_u8: 0 + (int) ReadWriteFlagHiddenVolume_u8: 0 + (int) versionInfo.major: 0 + (int) versionInfo.minor: 53 + (int) versionInfo.build_iteration: 0 + (int) FirmwareLocked_u8: 0 + (int) NewSDCardFound_u8: 1 + (int) NewSDCardFound_st.NewCard: 1 + (int) NewSDCardFound_st.Counter: 0 + (int) SDFillWithRandomChars_u8: 1 + ActiveSD_CardID_u32: 3670817656 + (int) VolumeActiceFlag_u8: 1 + (int) VolumeActiceFlag_st.unencrypted: 1 + (int) VolumeActiceFlag_st.encrypted: 0 + (int) VolumeActiceFlag_st.hidden: 0 + (int) NewSmartCardFound_u8: 0 + (int) UserPwRetryCount: 3 + (int) AdminPwRetryCount: 3 + ActiveSmartCardID_u32: 24122 + (int) StickKeysNotInitiated: 0 + +[Wed Jan 2 13:31:17 2019][DEBUG_L1] => GET_DEVICE_STATUS +.. +[Wed Jan 2 13:31:17 2019][DEBUG_L1] <= GET_DEVICE_STATUS 0 1 +00005e3a +[Wed Jan 2 13:31:17 2019][DEBUG_L1] => GET_DEVICE_STATUS +.... +[Wed Jan 2 13:31:18 2019][DEBUG_L1] <= GET_DEVICE_STATUS 0 1 +[Wed Jan 2 13:31:18 2019][DEBUG_L1] => GET_DEVICE_STATUS +... +[Wed Jan 2 13:31:18 2019][DEBUG_L1] <= GET_DEVICE_STATUS 0 1 +=============================================================================== +All tests passed (18 assertions in 6 test cases) +``` +Test's execution configuration and verbosity could be manipulated - please see `./test_safe --help` for details. + +The other tests sets are not written as extensively as Python tests and are rather more a C++ low level interface check used during the library development, using either low-level components, C API from `NK_C_API.cc`, or C++ API from `NitrokeyManager.cc`. Some of them are: [test_HOTP.cc](https://github.com/Nitrokey/libnitrokey/blob/master/unittest/test_HOTP.cc), +[test1.cc](https://github.com/Nitrokey/libnitrokey/blob/master/unittest/test1.cc). See more in [unittest](https://github.com/Nitrokey/libnitrokey/tree/master/unittest) directory. + +**Note: these are not device model agnostic, and will most probably destroy your data on the device.** + + +Unit tests were checked on Ubuntu 16.04/16.10/17.04. To run them just execute binaries built in `./libnitrokey/build` dir, after enabling them by passing `-DCOMPILE_TESTS=ON` option to `cmake` - e.g.: `cmake .. -DCOMPILE_TESTS=ON && make`. The documentation of how it works could be found in nitrokey-app project's README on Github: @@ -198,7 +279,7 @@ firmware code should show how things works: # Known issues / tasks * Currently only one device can be connected at a time (experimental work could be found in `wip-multiple_devices` branch), -* C++ API needs some reorganization to C++ objects (instead of pointers to arrays). This will be also preparing for integration with Pybind11, +* C++ API needs some reorganization to C++ objects (instead of pointers to byte arrays). This will be also preparing for integration with Pybind11, * Fix compilation warnings. Other tasks might be listed either in [TODO](TODO) file or on project's issues page. diff --git a/nitrokey-sys/libnitrokey-v3.4.1/command_id.cc b/nitrokey-sys/libnitrokey-v3.5/command_id.cc index a6c2a28..9a329bc 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/command_id.cc +++ b/nitrokey-sys/libnitrokey-v3.5/command_id.cc @@ -71,6 +71,10 @@ const char *commandid_to_string(CommandID id) { return "CHANGE_USER_PIN"; case CommandID::CHANGE_ADMIN_PIN: return "CHANGE_ADMIN_PIN"; + case CommandID::FIRMWARE_UPDATE: + return "FIRMWARE_UPDATE"; + case CommandID::FIRMWARE_PASSWORD_CHANGE: + return "FIRMWARE_PASSWORD_CHANGE"; case CommandID::ENABLE_CRYPTED_PARI: return "ENABLE_CRYPTED_PARI"; diff --git a/nitrokey-sys/libnitrokey-v3.4.1/device.cc b/nitrokey-sys/libnitrokey-v3.5/device.cc index 80e4b38..bc42965 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/device.cc +++ b/nitrokey-sys/libnitrokey-v3.5/device.cc @@ -20,7 +20,9 @@ */ #include <chrono> +#include <codecvt> #include <iostream> +#include <locale> #include <thread> #include <cstddef> #include <stdexcept> @@ -36,11 +38,42 @@ std::mutex mex_dev_com; using namespace nitrokey::device; using namespace nitrokey::log; +using namespace nitrokey::misc; using namespace std::chrono; +const uint16_t nitrokey::device::NITROKEY_VID = 0x20a0; +const uint16_t nitrokey::device::NITROKEY_PRO_PID = 0x4108; +const uint16_t nitrokey::device::NITROKEY_STORAGE_PID = 0x4109; + +Option<DeviceModel> nitrokey::device::product_id_to_model(uint16_t product_id) { + switch (product_id) { + case NITROKEY_PRO_PID: + return DeviceModel::PRO; + case NITROKEY_STORAGE_PID: + return DeviceModel::STORAGE; + default: + return {}; + } +} + std::atomic_int Device::instances_count{0}; std::chrono::milliseconds Device::default_delay {0} ; +std::ostream& nitrokey::device::operator<<(std::ostream& stream, DeviceModel model) { + switch (model) { + case DeviceModel::PRO: + stream << "Pro"; + break; + case DeviceModel::STORAGE: + stream << "Storage"; + break; + default: + stream << "Unknown"; + break; + } + return stream; +} + Device::Device(const uint16_t vid, const uint16_t pid, const DeviceModel model, const milliseconds send_receive_delay, const int retry_receiving_count, const milliseconds retry_timeout) @@ -171,14 +204,20 @@ int Device::recv(void *packet) { return status; } -std::vector<std::string> Device::enumerate(){ - //TODO make static - auto pInfo = hid_enumerate(m_vid, m_pid); +std::vector<DeviceInfo> Device::enumerate(){ + auto pInfo = hid_enumerate(NITROKEY_VID, 0); auto pInfo_ = pInfo; - std::vector<std::string> res; + std::vector<DeviceInfo> res; while (pInfo != nullptr){ - std::string a (pInfo->path); - res.push_back(a); + auto deviceModel = product_id_to_model(pInfo->product_id); + if (deviceModel.has_value()) { + std::string path(pInfo->path); + std::wstring serialNumberW(pInfo->serial_number); + std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; + std::string serialNumber = converter.to_bytes(serialNumberW); + DeviceInfo info = { deviceModel.value(), path, serialNumber }; + res.push_back(info); + } pInfo = pInfo->next; } @@ -189,6 +228,17 @@ std::vector<std::string> Device::enumerate(){ return res; } +std::shared_ptr<Device> Device::create(DeviceModel model) { + switch (model) { + case DeviceModel::PRO: + return std::make_shared<Stick10>(); + case DeviceModel::STORAGE: + return std::make_shared<Stick20>(); + default: + return {}; + } +} + bool Device::could_be_enumerated() { LOG(__FUNCTION__, Loglevel::DEBUG_L2); std::lock_guard<std::mutex> lock(mex_dev_com); @@ -243,14 +293,14 @@ void Device::set_retry_delay(const std::chrono::milliseconds delay){ } Stick10::Stick10(): - Device(0x20a0, 0x4108, DeviceModel::PRO, 100ms, 5, 100ms) + Device(NITROKEY_VID, NITROKEY_PRO_PID, DeviceModel::PRO, 100ms, 5, 100ms) { setDefaultDelay(); } Stick20::Stick20(): - Device(0x20a0, 0x4109, DeviceModel::STORAGE, 40ms, 55, 40ms) + Device(NITROKEY_VID, NITROKEY_STORAGE_PID, DeviceModel::STORAGE, 40ms, 55, 40ms) { setDefaultDelay(); } diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/CommandFailedException.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/CommandFailedException.h index 32bd6b7..32bd6b7 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/CommandFailedException.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/CommandFailedException.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/DeviceCommunicationExceptions.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/DeviceCommunicationExceptions.h index f710d0b..f710d0b 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/DeviceCommunicationExceptions.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/DeviceCommunicationExceptions.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/LibraryException.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/LibraryException.h index 3b9d177..3b9d177 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/LibraryException.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/LibraryException.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/LongOperationInProgressException.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/LongOperationInProgressException.h index 865d6b5..865d6b5 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/LongOperationInProgressException.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/LongOperationInProgressException.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/NitrokeyManager.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/NitrokeyManager.h index d6e5df4..33ede1b 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/NitrokeyManager.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/NitrokeyManager.h @@ -80,7 +80,7 @@ char * strndup(const char* str, size_t maxlen); bool get_time(uint64_t time = 0); bool erase_totp_slot(uint8_t slot_number, const char *temporary_password); bool erase_hotp_slot(uint8_t slot_number, const char *temporary_password); - std::vector<std::string> list_devices(); + std::vector<DeviceInfo> list_devices(); std::vector<std::string> list_devices_by_cpuID(); /** @@ -215,7 +215,7 @@ char * strndup(const char* str, size_t maxlen); template <typename S, typename A, typename T> void authorize_packet(T &package, const char *admin_temporary_password, shared_ptr<Device> device); - int get_minor_firmware_version(); + uint8_t get_minor_firmware_version(); explicit NitrokeyManager(); void set_log_function(std::function<void(std::string)> log_function); @@ -278,7 +278,7 @@ char * strndup(const char* str, size_t maxlen); */ void set_encrypted_volume_read_write(const char *admin_pin); - int get_major_firmware_version(); + uint8_t get_major_firmware_version(); bool is_smartcard_in_use(); @@ -295,6 +295,11 @@ char * strndup(const char* str, size_t maxlen); void wink(); stick20::ProductionTest::ResponsePayload production_info(); + + void enable_firmware_update_pro(const char *firmware_pin); + + void change_firmware_update_password_pro(const char *firmware_pin_current, const char *firmware_pin_new); + bool is_internal_hotp_slot_number(uint8_t slot_number) const; }; } diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/command.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/command.h index 6852bf0..6852bf0 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/command.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/command.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/command_id.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/command_id.h index eb0d450..ee6726c 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/command_id.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/command_id.h @@ -88,6 +88,8 @@ enum class CommandID : uint8_t { CHANGE_ADMIN_PIN = 0x15, WRITE_TO_SLOT_2 = 0x16, SEND_OTP_DATA = 0x17, + FIRMWARE_UPDATE = 0x19, + FIRMWARE_PASSWORD_CHANGE = 0x1A, ENABLE_CRYPTED_PARI = 0x20, DISABLE_CRYPTED_PARI = 0x20 + 1, diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/cxx_semantics.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/cxx_semantics.h index 36ed142..36ed142 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/cxx_semantics.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/cxx_semantics.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/deprecated.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/deprecated.h index 5a83288..5a83288 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/deprecated.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/deprecated.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/device.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/device.h index f6d2380..d50080d 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/device.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/device.h @@ -24,8 +24,11 @@ #include <chrono> #include "hidapi/hidapi.h" #include <cstdint> +#include <memory> #include <string> +#include <ostream> #include <vector> +#include "misc.h" #define HID_REPORT_SIZE 65 @@ -50,6 +53,48 @@ enum class DeviceModel{ STORAGE }; +std::ostream& operator<<(std::ostream& stream, DeviceModel model); + +/** + * The USB vendor ID for Nitrokey devices. + */ +extern const uint16_t NITROKEY_VID; +/** + * The USB product ID for the Nitrokey Pro. + */ +extern const uint16_t NITROKEY_PRO_PID; +/** + * The USB product ID for the Nitrokey Storage. + */ +extern const uint16_t NITROKEY_STORAGE_PID; + +/** + * Convert the given USB product ID to a Nitrokey model. If there is no model + * with that ID, return an absent value. + */ +misc::Option<DeviceModel> product_id_to_model(uint16_t product_id); + +/** + * Information about a connected device. + * + * This struct contains the information about a connected device returned by + * hidapi when enumerating the connected devices. + */ +struct DeviceInfo { + /** + * The model of the connected device. + */ + DeviceModel m_deviceModel; + /** + * The USB connection path for the device. + */ + std::string m_path; + /** + * The serial number of the device. + */ + std::string m_serialNumber; +}; + #include <atomic> class Device { @@ -106,7 +151,17 @@ public: * @return true if visible by OS */ bool could_be_enumerated(); - std::vector<std::string> enumerate(); + /** + * Returns a vector with all connected Nitrokey devices. + * + * @return information about all connected devices + */ + static std::vector<DeviceInfo> enumerate(); + + /** + * Create a Device of the given model. + */ + static std::shared_ptr<Device> create(DeviceModel model); void show_stats(); diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/device_proto.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/device_proto.h index 45a6c16..45a6c16 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/device_proto.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/device_proto.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/dissect.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/dissect.h index 690b5b7..690b5b7 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/dissect.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/dissect.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/hidapi/hidapi.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/hidapi/hidapi.h index e5bc2dc..e5bc2dc 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/hidapi/hidapi.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/hidapi/hidapi.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/log.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/log.h index 2a64bef..278b49c 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/log.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/log.h @@ -46,6 +46,7 @@ namespace nitrokey { class LogHandler { public: virtual void print(const std::string &, Loglevel lvl) = 0; + virtual ~LogHandler() = default; protected: std::string loglevel_to_str(Loglevel); std::string format_message_to_string(const std::string &str, const Loglevel &lvl); diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/misc.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/misc.h index 88254dd..a9c4672 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/misc.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/misc.h @@ -29,12 +29,37 @@ #include "log.h" #include "LibraryException.h" #include <sstream> +#include <stdexcept> #include <iomanip> namespace nitrokey { namespace misc { +/** + * Simple replacement for std::optional (C++17). + */ +template<typename T> +class Option { +public: + Option() : m_hasValue(false), m_value() {} + Option(T value) : m_hasValue(true), m_value(value) {} + + bool has_value() const { + return m_hasValue; + } + T value() const { + if (!m_hasValue) { + throw std::logic_error("Called Option::value without value"); + } + return m_value; + } + +private: + bool m_hasValue; + T m_value; +}; + template<typename T> std::string toHex(T value){ using namespace std; @@ -42,7 +67,8 @@ namespace misc { oss << std::hex << std::setw(sizeof(value)*2) << std::setfill('0') << value; return oss.str(); } - + +#define FIELD_WIDTH_MAX (100) /** * Copies string from pointer to fixed size C-style array. Src needs to be a valid C-string - eg. ended with '\0'. * Throws when source is bigger than destination. @@ -57,12 +83,13 @@ namespace misc { // throw EmptySourceStringException(slot_number); return; const size_t s_dest = sizeof dest; - LOG(std::string("strcpyT sizes dest src ") - +std::to_string(s_dest)+ " " - +std::to_string(strlen(src))+ " " - ,nitrokey::log::Loglevel::DEBUG_L2); - if (strlen(src) > s_dest){ - throw TooLongStringException(strlen(src), s_dest, src); + const size_t src_strlen = strnlen(src, FIELD_WIDTH_MAX); + LOG(std::string("strcpyT sizes dest src ") + + std::to_string(s_dest) + " " + + std::to_string(src_strlen) + " " + , nitrokey::log::Loglevel::DEBUG_L2); + if (src_strlen > s_dest){ + throw TooLongStringException(src_strlen, s_dest, src); } strncpy((char*) &dest, src, s_dest); } diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/stick10_commands.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/stick10_commands.h index f2ffba2..5e8a5aa 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/stick10_commands.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/stick10_commands.h @@ -304,8 +304,13 @@ class GetHOTP : Command<CommandID::GET_CODE> { class ReadSlot : Command<CommandID::READ_SLOT> { public: + enum class CounterFormat { + ASCII = 0, + BINARY = 1, + }; struct CommandPayload { uint8_t slot_number; + CounterFormat data_format; //Storage v0.54+ only: slot_counter value format: 0 - in ascii, 1 - binary bool isValid() const { return !(slot_number & 0xF0); } @@ -882,6 +887,41 @@ class BuildAESKey : Command<CommandID::NEW_AES_KEY> { }; +class FirmwareUpdate : Command<CommandID::FIRMWARE_UPDATE> { +public: + struct CommandPayload { + uint8_t firmware_password[20]; + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(firmware_password); + return ss.str(); + } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; + +}; + +class FirmwarePasswordChange : Command<CommandID::FIRMWARE_PASSWORD_CHANGE> { +public: + struct CommandPayload { + uint8_t firmware_password_current[20]; + uint8_t firmware_password_new[20]; + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(firmware_password_current); + print_to_ss_volatile(firmware_password_new); + return ss.str(); + } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; + +}; + + } } } diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/stick10_commands_0.8.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/stick10_commands_0.8.h index 9477890..9477890 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/stick10_commands_0.8.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/stick10_commands_0.8.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/stick20_commands.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/stick20_commands.h index 7efa1b6..7efa1b6 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/stick20_commands.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/stick20_commands.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/version.h b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/version.h index 6547af0..6547af0 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/libnitrokey/version.h +++ b/nitrokey-sys/libnitrokey-v3.5/libnitrokey/version.h diff --git a/nitrokey-sys/libnitrokey-v3.4.1/log.cc b/nitrokey-sys/libnitrokey-v3.5/log.cc index 06acee7..06acee7 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/log.cc +++ b/nitrokey-sys/libnitrokey-v3.5/log.cc diff --git a/nitrokey-sys/libnitrokey-v3.4.1/misc.cc b/nitrokey-sys/libnitrokey-v3.5/misc.cc index 59185f3..59185f3 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/misc.cc +++ b/nitrokey-sys/libnitrokey-v3.5/misc.cc diff --git a/nitrokey-sys/libnitrokey-v3.4.1/version.cc b/nitrokey-sys/libnitrokey-v3.5/version.cc index dfdc802..dfdc802 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/version.cc +++ b/nitrokey-sys/libnitrokey-v3.5/version.cc diff --git a/nitrokey-sys/libnitrokey-v3.4.1/version.cc.in b/nitrokey-sys/libnitrokey-v3.5/version.cc.in index 0eae647..0eae647 100644 --- a/nitrokey-sys/libnitrokey-v3.4.1/version.cc.in +++ b/nitrokey-sys/libnitrokey-v3.5/version.cc.in diff --git a/nitrokey-sys/src/ffi.rs b/nitrokey-sys/src/ffi.rs index 58879ad..a01eae8 100644 --- a/nitrokey-sys/src/ffi.rs +++ b/nitrokey-sys/src/ffi.rs @@ -1,5 +1,10 @@ /* automatically generated by rust-bindgen, manually modified */ +extern "C" { + #[link_name = "\u{1}NK_PWS_SLOT_COUNT"] + pub static mut NK_PWS_SLOT_COUNT: u8; +} +pub const MAXIMUM_STR_REPLY_LENGTH: ::std::os::raw::c_int = 8192; /// Use, if no supported device is connected pub const NK_device_model_NK_DISCONNECTED: NK_device_model = 0; /// Nitrokey Pro. @@ -8,6 +13,188 @@ pub const NK_device_model_NK_PRO: NK_device_model = 1; pub const NK_device_model_NK_STORAGE: NK_device_model = 2; /// The Nitrokey device models supported by the API. pub type NK_device_model = u32; +/// The connection info for a Nitrokey device as a linked list. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct NK_device_info { + /// The model of the Nitrokey device. + pub model: NK_device_model, + /// The USB device path for NK_connect_with_path. + pub path: *mut ::std::os::raw::c_char, + /// The serial number. + pub serial_number: *mut ::std::os::raw::c_char, + /// The pointer to the next element of the linked list or null + /// if this is the last element in the list. + pub next: *mut NK_device_info, +} +#[test] +fn bindgen_test_layout_NK_device_info() { + assert_eq!( + ::std::mem::size_of::<NK_device_info>(), + 32usize, + concat!("Size of: ", stringify!(NK_device_info)) + ); + assert_eq!( + ::std::mem::align_of::<NK_device_info>(), + 8usize, + concat!("Alignment of ", stringify!(NK_device_info)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<NK_device_info>())).model as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(NK_device_info), + "::", + stringify!(model) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<NK_device_info>())).path as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(NK_device_info), + "::", + stringify!(path) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<NK_device_info>())).serial_number as *const _ as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(NK_device_info), + "::", + stringify!(serial_number) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<NK_device_info>())).next as *const _ as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(NK_device_info), + "::", + stringify!(next) + ) + ); +} +/// Stores the common device status for all Nitrokey devices. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct NK_status { + /// The major firmware version, e. g. 0 in v0.40. + pub firmware_version_major: u8, + /// The minor firmware version, e. g. 40 in v0.40. + pub firmware_version_minor: u8, + /// The serial number of the smart card. + pub serial_number_smart_card: u32, + /// The HOTP slot to generate a password from if the numlock + /// key is pressed twice (slot 0-1, or any other value to + /// disable the function). + pub config_numlock: u8, + /// The HOTP slot to generate a password from if the capslock + /// key is pressed twice (slot 0-1, or any other value to + /// disable the function). + pub config_capslock: u8, + /// The HOTP slot to generate a password from if the scrolllock + /// key is pressed twice (slot 0-1, or any other value to + /// disable the function). + pub config_scrolllock: u8, + /// Indicates whether the user password is required to generate + /// an OTP value. + pub otp_user_password: bool, +} +#[test] +fn bindgen_test_layout_NK_status() { + assert_eq!( + ::std::mem::size_of::<NK_status>(), + 12usize, + concat!("Size of: ", stringify!(NK_status)) + ); + assert_eq!( + ::std::mem::align_of::<NK_status>(), + 4usize, + concat!("Alignment of ", stringify!(NK_status)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<NK_status>())).firmware_version_major as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(NK_status), + "::", + stringify!(firmware_version_major) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<NK_status>())).firmware_version_minor as *const _ as usize + }, + 1usize, + concat!( + "Offset of field: ", + stringify!(NK_status), + "::", + stringify!(firmware_version_minor) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<NK_status>())).serial_number_smart_card as *const _ as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(NK_status), + "::", + stringify!(serial_number_smart_card) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<NK_status>())).config_numlock as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(NK_status), + "::", + stringify!(config_numlock) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<NK_status>())).config_capslock as *const _ as usize }, + 9usize, + concat!( + "Offset of field: ", + stringify!(NK_status), + "::", + stringify!(config_capslock) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<NK_status>())).config_scrolllock as *const _ as usize }, + 10usize, + concat!( + "Offset of field: ", + stringify!(NK_status), + "::", + stringify!(config_scrolllock) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<NK_status>())).otp_user_password as *const _ as usize }, + 11usize, + concat!( + "Offset of field: ", + stringify!(NK_status), + "::", + stringify!(otp_user_password) + ) + ); +} /// Stores the status of a Storage device. #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -259,6 +446,54 @@ fn bindgen_test_layout_NK_storage_status() { ) ); } +/// Data about the usage of the SD card. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct NK_SD_usage_data { + /// The minimum write level, as a percentage of the total card + /// size. + pub write_level_min: u8, + /// The maximum write level, as a percentage of the total card + /// size. + pub write_level_max: u8, +} +#[test] +fn bindgen_test_layout_NK_SD_usage_data() { + assert_eq!( + ::std::mem::size_of::<NK_SD_usage_data>(), + 2usize, + concat!("Size of: ", stringify!(NK_SD_usage_data)) + ); + assert_eq!( + ::std::mem::align_of::<NK_SD_usage_data>(), + 1usize, + concat!("Alignment of ", stringify!(NK_SD_usage_data)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<NK_SD_usage_data>())).write_level_min as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(NK_SD_usage_data), + "::", + stringify!(write_level_min) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<NK_SD_usage_data>())).write_level_max as *const _ as usize + }, + 1usize, + concat!( + "Offset of field: ", + stringify!(NK_SD_usage_data), + "::", + stringify!(write_level_max) + ) + ); +} #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct NK_storage_ProductionTest { @@ -520,9 +755,28 @@ extern "C" { pub fn NK_get_device_model() -> NK_device_model; } extern "C" { + /// Return the debug status string. Debug purposes. This function is + /// deprecated in favor of NK_get_status_as_string. + /// @return string representation of the status or an empty string + /// if the command failed + #[deprecated(since = "3.5.0", note="use `NK_get_status_as_string` instead")] + pub fn NK_status() -> *mut ::std::os::raw::c_char; +} +extern "C" { /// Return the debug status string. Debug purposes. + /// @return string representation of the status or an empty string + /// if the command failed + pub fn NK_get_status_as_string() -> *mut ::std::os::raw::c_char; +} +extern "C" { + /// Get the stick status common to all Nitrokey devices and return the + /// command processing error code. If the code is zero, i. e. the + /// command was successful, the storage status is written to the output + /// pointer's target. The output pointer must not be null. + /// + /// @param out the output pointer for the status /// @return command processing error code - pub fn NK_status() -> *mut ::std::os::raw::c_char; + pub fn NK_get_status(out: *mut NK_status) -> ::std::os::raw::c_int; } extern "C" { /// Return the device's serial number string in hex. @@ -760,6 +1014,7 @@ extern "C" { pub fn NK_totp_set_time_soft(time: u64) -> ::std::os::raw::c_int; } extern "C" { + #[deprecated(since = "3.4.0", note="use `NK_totp_set_time_soft` instead")] pub fn NK_totp_get_time() -> ::std::os::raw::c_int; } extern "C" { @@ -853,12 +1108,12 @@ extern "C" { extern "C" { /// Get device's major firmware version /// @return major part of the version number (e.g. 0 from 0.48, 0 from 0.7 etc.) - pub fn NK_get_major_firmware_version() -> ::std::os::raw::c_int; + pub fn NK_get_major_firmware_version() -> u8; } extern "C" { /// Get device's minor firmware version /// @return minor part of the version number (e.g. 7 from 0.7, 48 from 0.48 etc.) - pub fn NK_get_minor_firmware_version() -> ::std::os::raw::c_int; + pub fn NK_get_minor_firmware_version() -> u8; } extern "C" { /// Function to determine unencrypted volume PIN type @@ -1068,6 +1323,16 @@ extern "C" { pub fn NK_get_status_storage(out: *mut NK_storage_status) -> ::std::os::raw::c_int; } extern "C" { + /// Get SD card usage attributes. Usable during hidden volumes creation. + /// If the command was successful (return value 0), the usage data is + /// written to the output pointer’s target. The output pointer must + /// not be null. + /// Storage only + /// @param out the output pointer for the usage data + /// @return command processing error code + pub fn NK_get_SD_usage_data(out: *mut NK_SD_usage_data) -> ::std::os::raw::c_int; +} +extern "C" { /// Get SD card usage attributes as string. /// Usable during hidden volumes creation. /// Storage only @@ -1077,7 +1342,8 @@ extern "C" { extern "C" { /// Get progress value of current long operation. /// Storage only - /// @return int in range 0-100 or -1 if device is not busy + /// @return int in range 0-100 or -1 if device is not busy or -2 if an + /// error occured pub fn NK_get_progress_bar_value() -> ::std::os::raw::c_int; } extern "C" { @@ -1097,6 +1363,18 @@ extern "C" { pub fn NK_list_devices_by_cpuID() -> *mut ::std::os::raw::c_char; } extern "C" { + /// Returns a linked list of all connected devices, or null if no devices + /// are connected or an error occured. The linked list must be freed by + /// calling NK_free_device_info. + /// @return a linked list of all connected devices + pub fn NK_list_devices() -> *mut NK_device_info; +} +extern "C" { + /// Free a linked list returned by NK_list_devices. + /// @param the linked list to free or null + pub fn NK_free_device_info(device_info: *mut NK_device_info); +} +extern "C" { /// Connects to the device with given ID. ID's list could be created with NK_list_devices_by_cpuID. /// Requires calling to NK_list_devices_by_cpuID first. Connecting to arbitrary ID/USB path is not handled. /// On connection requests status from device and disconnects it / removes from map on connection failure. @@ -1106,7 +1384,98 @@ extern "C" { pub fn NK_connect_with_ID(id: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; } extern "C" { + /// Connects to a device with the given path. The path is a USB device + /// path as returned by hidapi. + /// @param path the device path + /// @return 1 on successful connection, 0 otherwise + pub fn NK_connect_with_path(path: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; +} +extern "C" { /// Blink red and green LED alternatively and infinitely (until device is reconnected). /// @return command processing error code pub fn NK_wink() -> ::std::os::raw::c_int; } +extern "C" { + /// Enable update mode on Nitrokey Pro. + /// Supported from v0.11. + /// @param update_password 20 bytes update password + /// @return command processing error code + pub fn NK_enable_firmware_update_pro( + update_password: *const ::std::os::raw::c_char, + ) -> ::std::os::raw::c_int; +} +extern "C" { + /// Change update-mode password on Nitrokey Pro. + /// Supported from v0.11. + /// @param current_firmware_password 20 bytes update password + /// @param new_firmware_password 20 bytes update password + /// @return command processing error code + pub fn NK_change_firmware_password_pro( + current_firmware_password: *const ::std::os::raw::c_char, + new_firmware_password: *const ::std::os::raw::c_char, + ) -> ::std::os::raw::c_int; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ReadSlot_t { + pub slot_name: [u8; 15usize], + pub _slot_config: u8, + pub slot_token_id: [u8; 13usize], + pub slot_counter: u64, +} +#[test] +fn bindgen_test_layout_ReadSlot_t() { + assert_eq!( + ::std::mem::size_of::<ReadSlot_t>(), + 40usize, + concat!("Size of: ", stringify!(ReadSlot_t)) + ); + assert_eq!( + ::std::mem::align_of::<ReadSlot_t>(), + 8usize, + concat!("Alignment of ", stringify!(ReadSlot_t)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<ReadSlot_t>())).slot_name as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(ReadSlot_t), + "::", + stringify!(slot_name) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<ReadSlot_t>()))._slot_config as *const _ as usize }, + 15usize, + concat!( + "Offset of field: ", + stringify!(ReadSlot_t), + "::", + stringify!(_slot_config) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<ReadSlot_t>())).slot_token_id as *const _ as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(ReadSlot_t), + "::", + stringify!(slot_token_id) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<ReadSlot_t>())).slot_counter as *const _ as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(ReadSlot_t), + "::", + stringify!(slot_counter) + ) + ); +} +extern "C" { + pub fn NK_read_HOTP_slot(slot_num: u8, out: *mut ReadSlot_t) -> ::std::os::raw::c_int; +} |