diff options
-rw-r--r-- | CMakeLists.txt | 67 | ||||
-rw-r--r-- | NK_C_API.cc | 322 | ||||
-rw-r--r-- | NK_C_API.h | 1 | ||||
-rw-r--r-- | NK_C_API_helpers.h | 88 | ||||
-rw-r--r-- | NK_C_API_storage.cpp | 256 | ||||
-rw-r--r-- | NK_C_API_storage.h | 6 | ||||
-rw-r--r-- | NitrokeyManager.cc | 185 | ||||
-rw-r--r-- | NitrokeyManagerStorage.cpp | 175 | ||||
-rw-r--r-- | NitrokeyManagerStorage.h | 6 | ||||
-rw-r--r-- | libnitrokey/NitrokeyManager.h | 11 | ||||
-rw-r--r-- | libnitrokey/nk_strndup.h | 9 | ||||
-rw-r--r-- | nk_strndup.c | 14 |
12 files changed, 614 insertions, 526 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 30ca485..6793ac9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,35 +44,56 @@ MESSAGE("${PROJECT_NAME}: Build type: ${CMAKE_BUILD_TYPE}") include_directories(hidapi) include_directories(libnitrokey) + +set(COMMON_FILES + libnitrokey/command.h + libnitrokey/command_id.h + libnitrokey/cxx_semantics.h + libnitrokey/device.h + libnitrokey/device_proto.h + libnitrokey/dissect.h + libnitrokey/log.h + libnitrokey/misc.h + libnitrokey/NitrokeyManager.h + libnitrokey/stick10_commands.h + libnitrokey/stick20_commands.h + libnitrokey/CommandFailedException.h + libnitrokey/LibraryException.h + libnitrokey/LongOperationInProgressException.h + libnitrokey/stick10_commands_0.8.h + command_id.cc + device.cc + log.cc + misc.cc + nk_strndup.c + DeviceCommunicationExceptions.cpp + ${CMAKE_CURRENT_BINARY_DIR}/version.cc + ) + set(SOURCE_FILES - libnitrokey/command.h - libnitrokey/command_id.h - libnitrokey/cxx_semantics.h - libnitrokey/device.h - libnitrokey/device_proto.h - libnitrokey/dissect.h - libnitrokey/log.h - libnitrokey/misc.h - libnitrokey/NitrokeyManager.h - libnitrokey/stick10_commands.h - libnitrokey/stick20_commands.h - libnitrokey/CommandFailedException.h - libnitrokey/LibraryException.h - libnitrokey/LongOperationInProgressException.h - libnitrokey/stick10_commands_0.8.h - command_id.cc - device.cc - log.cc - misc.cc + ${COMMON_FILES} NitrokeyManager.cc + NitrokeyManagerStorage.cpp + NitrokeyManagerStorage.h NK_C_API.h NK_C_API.cc - DeviceCommunicationExceptions.cpp - ${CMAKE_CURRENT_BINARY_DIR}/version.cc + NK_C_API_helpers.h + NK_C_API_storage.h + NK_C_API_storage.cpp + ) + +set(SOURCE_FILES_storage + ${COMMON_FILES} + NitrokeyManagerStorage.cpp + NitrokeyManagerStorage.h + NK_C_API_helpers.h + NK_C_API_storage.h + NK_C_API_storage.cpp ) set(BUILD_SHARED_LIBS ON CACHE BOOL "Build all libraries as shared") add_library(nitrokey ${SOURCE_FILES}) +add_library(nitrokey-storage ${SOURCE_FILES_storage}) IF(APPLE) include_directories(hidapi/hidapi) @@ -88,6 +109,7 @@ ELSEIF(UNIX) target_link_options(nitrokey PRIVATE "-Wl,-Map=output.map") ENDIF() target_link_libraries(nitrokey ${HIDAPI_LIBUSB_LDFLAGS}) + target_link_libraries(nitrokey-storage ${HIDAPI_LIBUSB_LDFLAGS}) ELSEIF(WIN32) include_directories(hidapi/hidapi) add_library(hidapi-libusb STATIC hidapi/windows/hid.c ) @@ -98,6 +120,9 @@ ENDIF() set_target_properties(nitrokey PROPERTIES VERSION ${libnitrokey_VERSION} SOVERSION ${libnitrokey_VERSION_MAJOR}) +set_target_properties(nitrokey-storage PROPERTIES + VERSION ${libnitrokey_VERSION} + SOVERSION ${libnitrokey_VERSION_MAJOR}) OPTION(ERROR_ON_WARNING "Stop compilation on warning found (not supported for MSVC)" OFF) if (NOT MSVC) diff --git a/NK_C_API.cc b/NK_C_API.cc index 538a6a1..2f5a0cc 100644 --- a/NK_C_API.cc +++ b/NK_C_API.cc @@ -30,92 +30,16 @@ #include "libnitrokey/device_proto.h" #include "libnitrokey/version.h" -#ifdef _MSC_VER -#ifdef _WIN32 -#pragma message "Using own strndup" -char * strndup(const char* str, size_t maxlen) { - size_t len = strnlen(str, maxlen); - char* dup = (char *)malloc(len + 1); - memcpy(dup, str, len); - dup[len] = 0; - return dup; -} -#endif -#endif + +#include "nk_strndup.h" using namespace nitrokey; const uint8_t NK_PWS_SLOT_COUNT = PWS_SLOT_COUNT; -static uint8_t NK_last_command_status = 0; +uint8_t NK_last_command_status = 0; static const int max_string_field_length = 100; -template <typename T> -T* duplicate_vector_and_clear(std::vector<T> &v){ - auto d = new T[v.size()]; - std::copy(v.begin(), v.end(), d); - std::fill(v.begin(), v.end(), 0); - return d; -} - -template <typename R, typename T> -std::tuple<int, R> get_with_status(T func, R fallback) { - NK_last_command_status = 0; - try { - return std::make_tuple(0, func()); - } - catch (CommandFailedException & commandFailedException){ - NK_last_command_status = commandFailedException.last_command_status; - } - catch (LibraryException & libraryException){ - NK_last_command_status = libraryException.exception_id(); - } - catch (const DeviceCommunicationException &deviceException){ - NK_last_command_status = 256-deviceException.getType(); - } - return std::make_tuple(NK_last_command_status, fallback); -} - -template <typename T> -uint8_t * get_with_array_result(T func){ - return std::get<1>(get_with_status<uint8_t*>(func, nullptr)); -} - -template <typename T> -char* get_with_string_result(T func){ - auto result = std::get<1>(get_with_status<char*>(func, nullptr)); - if (result == nullptr) { - return strndup("", MAXIMUM_STR_REPLY_LENGTH); - } - return result; -} - -template <typename T> -auto get_with_result(T func){ - return std::get<1>(get_with_status(func, static_cast<decltype(func())>(0))); -} - -template <typename T> -uint8_t get_without_result(T func){ - NK_last_command_status = 0; - try { - func(); - return 0; - } - catch (CommandFailedException & commandFailedException){ - NK_last_command_status = commandFailedException.last_command_status; - } - catch (LibraryException & libraryException){ - NK_last_command_status = libraryException.exception_id(); - } - catch (const InvalidCRCReceived &invalidCRCException){ - ; - } - catch (const DeviceCommunicationException &deviceException){ - NK_last_command_status = 256-deviceException.getType(); - } - return NK_last_command_status; -} - +#include "NK_C_API_helpers.h" #ifdef __cplusplus extern "C" { @@ -558,238 +482,6 @@ extern "C" { }); } - // storage commands - - NK_C_API int NK_send_startup(uint64_t seconds_from_epoch) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->send_startup(seconds_from_epoch); - }); - } - - NK_C_API int NK_unlock_encrypted_volume(const char* user_pin) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->unlock_encrypted_volume(user_pin); - }); - } - - NK_C_API int NK_lock_encrypted_volume() { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->lock_encrypted_volume(); - }); - } - - NK_C_API int NK_unlock_hidden_volume(const char* hidden_volume_password) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->unlock_hidden_volume(hidden_volume_password); - }); - } - - NK_C_API int NK_lock_hidden_volume() { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->lock_hidden_volume(); - }); - } - - NK_C_API int NK_create_hidden_volume(uint8_t slot_nr, uint8_t start_percent, uint8_t end_percent, - const char *hidden_volume_password) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->create_hidden_volume(slot_nr, start_percent, end_percent, - hidden_volume_password); - }); - } - - NK_C_API int NK_set_unencrypted_read_only(const char *user_pin) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->set_unencrypted_read_only(user_pin); - }); - } - - NK_C_API int NK_set_unencrypted_read_write(const char *user_pin) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->set_unencrypted_read_write(user_pin); - }); - } - - NK_C_API int NK_set_unencrypted_read_only_admin(const char *admin_pin) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->set_unencrypted_read_only_admin(admin_pin); - }); - } - - NK_C_API int NK_set_unencrypted_read_write_admin(const char *admin_pin) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->set_unencrypted_read_write_admin(admin_pin); - }); - } - - NK_C_API int NK_set_encrypted_read_only(const char* admin_pin) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->set_encrypted_volume_read_only(admin_pin); - }); - } - - NK_C_API int NK_set_encrypted_read_write(const char* admin_pin) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->set_encrypted_volume_read_write(admin_pin); - }); - } - - NK_C_API int NK_export_firmware(const char* admin_pin) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->export_firmware(admin_pin); - }); - } - - NK_C_API int NK_clear_new_sd_card_warning(const char* admin_pin) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->clear_new_sd_card_warning(admin_pin); - }); - } - - NK_C_API int NK_fill_SD_card_with_random_data(const char* admin_pin) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->fill_SD_card_with_random_data(admin_pin); - }); - } - - NK_C_API int NK_change_update_password(const char* current_update_password, - const char* new_update_password) { - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->change_update_password(current_update_password, new_update_password); - }); - } - - NK_C_API int NK_enable_firmware_update(const char* update_password){ - auto m = NitrokeyManager::instance(); - return get_without_result([&]() { - m->enable_firmware_update(update_password); - }); - } - - NK_C_API char* NK_get_status_storage_as_string() { - auto m = NitrokeyManager::instance(); - return get_with_string_result([&]() { - return m->get_status_storage_as_string(); - }); - } - - NK_C_API int NK_get_status_storage(NK_storage_status* out) { - if (out == nullptr) { - return -1; - } - auto m = NitrokeyManager::instance(); - auto result = get_with_status([&]() { - return m->get_status_storage(); - }, proto::stick20::DeviceConfigurationResponsePacket::ResponsePayload()); - auto error_code = std::get<0>(result); - if (error_code != 0) { - return error_code; - } - - auto status = std::get<1>(result); - out->unencrypted_volume_read_only = status.ReadWriteFlagUncryptedVolume_u8 != 0; - out->unencrypted_volume_active = status.VolumeActiceFlag_st.unencrypted; - out->encrypted_volume_read_only = status.ReadWriteFlagCryptedVolume_u8 != 0; - out->encrypted_volume_active = status.VolumeActiceFlag_st.encrypted; - out->hidden_volume_read_only = status.ReadWriteFlagHiddenVolume_u8 != 0; - out->hidden_volume_active = status.VolumeActiceFlag_st.hidden; - out->firmware_version_major = status.versionInfo.major; - out->firmware_version_minor = status.versionInfo.minor; - out->firmware_locked = status.FirmwareLocked_u8 != 0; - out->serial_number_sd_card = status.ActiveSD_CardID_u32; - out->serial_number_smart_card = status.ActiveSmartCardID_u32; - out->user_retry_count = status.UserPwRetryCount; - out->admin_retry_count = status.AdminPwRetryCount; - out->new_sd_card_found = status.NewSDCardFound_st.NewCard; - out->filled_with_random = (status.SDFillWithRandomChars_u8 & 0x01) != 0; - out->stick_initialized = status.StickKeysNotInitiated == 0; - return 0; - } - - NK_C_API int NK_get_storage_production_info(NK_storage_ProductionTest * out){ - if (out == nullptr) { - return -1; - } - auto m = NitrokeyManager::instance(); - auto result = get_with_status([&]() { - return m->production_info(); - }, proto::stick20::ProductionTest::ResponsePayload()); - - auto error_code = std::get<0>(result); - if (error_code != 0) { - return error_code; - } - - stick20::ProductionTest::ResponsePayload status = std::get<1>(result); - // Cannot use memcpy without declaring C API struct packed - // (which is not parsed by Python's CFFI apparently), hence the manual way. -#define a(x) out->x = status.x; - a(FirmwareVersion_au8[0]); - a(FirmwareVersion_au8[1]); - a(FirmwareVersionInternal_u8); - a(SD_Card_Size_u8); - a(CPU_CardID_u32); - a(SmartCardID_u32); - a(SD_CardID_u32); - a(SC_UserPwRetryCount); - a(SC_AdminPwRetryCount); - a(SD_Card_ManufacturingYear_u8); - a(SD_Card_ManufacturingMonth_u8); - a(SD_Card_OEM_u16); - a(SD_WriteSpeed_u16); - a(SD_Card_Manufacturer_u8); -#undef a - 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(); - return get_with_string_result([&]() { - return m->get_SD_usage_data_as_string(); - }); - } - - NK_C_API int NK_get_progress_bar_value() { - auto m = NitrokeyManager::instance(); - return std::get<1>(get_with_status([&]() { - return m->get_progress_bar_value(); - }, -2)); - } - NK_C_API uint8_t NK_get_major_firmware_version() { auto m = NitrokeyManager::instance(); return get_with_result([&]() { @@ -804,12 +496,6 @@ NK_C_API char* NK_get_SD_usage_data_as_string() { }); } - NK_C_API int NK_set_unencrypted_volume_rorw_pin_type_user() { - auto m = NitrokeyManager::instance(); - return get_with_result([&]() { - return m->set_unencrypted_volume_rorw_pin_type_user() ? 1 : 0; - }); - } NK_C_API char* NK_list_devices_by_cpuID() { auto nm = NitrokeyManager::instance(); @@ -1082,5 +1082,6 @@ NK_C_API int NK_read_HOTP_slot(const uint8_t slot_num, struct ReadSlot_t* out); #ifdef __cplusplus } #endif +extern uint8_t NK_last_command_status; #endif //LIBNITROKEY_NK_C_API_H diff --git a/NK_C_API_helpers.h b/NK_C_API_helpers.h new file mode 100644 index 0000000..e9ae4d1 --- /dev/null +++ b/NK_C_API_helpers.h @@ -0,0 +1,88 @@ +#ifndef LIBNITROKEY_NK_C_API_HELPERS_H +#define LIBNITROKEY_NK_C_API_HELPERS_H + + +#include "NK_C_API.h" +#include <iostream> +#include <tuple> +#include "libnitrokey/NitrokeyManager.h" +#include <cstring> +#include "libnitrokey/LibraryException.h" +#include "libnitrokey/cxx_semantics.h" +#include "libnitrokey/stick20_commands.h" +#include "libnitrokey/device_proto.h" +#include "libnitrokey/version.h" + + +extern uint8_t NK_last_command_status; + + +template <typename T> +T* duplicate_vector_and_clear(std::vector<T> &v){ + auto d = new T[v.size()]; + std::copy(v.begin(), v.end(), d); + std::fill(v.begin(), v.end(), 0); + return d; +} + +template <typename R, typename T> +std::tuple<int, R> get_with_status(T func, R fallback) { + NK_last_command_status = 0; + try { + return std::make_tuple(0, func()); + } + catch (CommandFailedException & commandFailedException){ + NK_last_command_status = commandFailedException.last_command_status; + } + catch (LibraryException & libraryException){ + NK_last_command_status = libraryException.exception_id(); + } + catch (const DeviceCommunicationException &deviceException){ + NK_last_command_status = 256-deviceException.getType(); + } + return std::make_tuple(NK_last_command_status, fallback); +} + +template <typename T> +uint8_t * get_with_array_result(T func){ + return std::get<1>(get_with_status<uint8_t*>(func, nullptr)); +} + +template <typename T> +char* get_with_string_result(T func){ + auto result = std::get<1>(get_with_status<char*>(func, nullptr)); + if (result == nullptr) { + return strndup("", MAXIMUM_STR_REPLY_LENGTH); + } + return result; +} + +template <typename T> +auto get_with_result(T func){ + return std::get<1>(get_with_status(func, static_cast<decltype(func())>(0))); +} + +template <typename T> +uint8_t get_without_result(T func){ + NK_last_command_status = 0; + try { + func(); + return 0; + } + catch (CommandFailedException & commandFailedException){ + NK_last_command_status = commandFailedException.last_command_status; + } + catch (LibraryException & libraryException){ + NK_last_command_status = libraryException.exception_id(); + } + catch (const InvalidCRCReceived &invalidCRCException){ + ; + } + catch (const DeviceCommunicationException &deviceException){ + NK_last_command_status = 256-deviceException.getType(); + } + return NK_last_command_status; +} + + +#endif // LIBNITROKEY_NK_C_API_HELPERS_H diff --git a/NK_C_API_storage.cpp b/NK_C_API_storage.cpp new file mode 100644 index 0000000..59bae85 --- /dev/null +++ b/NK_C_API_storage.cpp @@ -0,0 +1,256 @@ +#include "NK_C_API_storage.h" +#include "NK_C_API_helpers.h" + +using namespace nitrokey; + +#include "nk_strndup.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +// storage commands + +NK_C_API int NK_send_startup(uint64_t seconds_from_epoch) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->send_startup(seconds_from_epoch); + }); +} + +NK_C_API int NK_unlock_encrypted_volume(const char* user_pin) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->unlock_encrypted_volume(user_pin); + }); +} + +NK_C_API int NK_lock_encrypted_volume() { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->lock_encrypted_volume(); + }); +} + +NK_C_API int NK_unlock_hidden_volume(const char* hidden_volume_password) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->unlock_hidden_volume(hidden_volume_password); + }); +} + +NK_C_API int NK_lock_hidden_volume() { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->lock_hidden_volume(); + }); +} + +NK_C_API int NK_create_hidden_volume(uint8_t slot_nr, uint8_t start_percent, uint8_t end_percent, + const char *hidden_volume_password) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->create_hidden_volume(slot_nr, start_percent, end_percent, + hidden_volume_password); + }); +} + +NK_C_API int NK_set_unencrypted_read_only(const char *user_pin) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->set_unencrypted_read_only(user_pin); + }); +} + +NK_C_API int NK_set_unencrypted_read_write(const char *user_pin) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->set_unencrypted_read_write(user_pin); + }); +} + +NK_C_API int NK_set_unencrypted_read_only_admin(const char *admin_pin) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->set_unencrypted_read_only_admin(admin_pin); + }); +} + +NK_C_API int NK_set_unencrypted_read_write_admin(const char *admin_pin) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->set_unencrypted_read_write_admin(admin_pin); + }); +} + +NK_C_API int NK_set_encrypted_read_only(const char* admin_pin) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->set_encrypted_volume_read_only(admin_pin); + }); +} + +NK_C_API int NK_set_encrypted_read_write(const char* admin_pin) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->set_encrypted_volume_read_write(admin_pin); + }); +} + +NK_C_API int NK_export_firmware(const char* admin_pin) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->export_firmware(admin_pin); + }); +} + +NK_C_API int NK_clear_new_sd_card_warning(const char* admin_pin) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->clear_new_sd_card_warning(admin_pin); + }); +} + +NK_C_API int NK_fill_SD_card_with_random_data(const char* admin_pin) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->fill_SD_card_with_random_data(admin_pin); + }); +} + +NK_C_API int NK_change_update_password(const char* current_update_password, + const char* new_update_password) { + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->change_update_password(current_update_password, new_update_password); + }); +} + +NK_C_API int NK_enable_firmware_update(const char* update_password){ + auto m = NitrokeyManager::instance(); + return get_without_result([&]() { + m->enable_firmware_update(update_password); + }); +} + +NK_C_API char* NK_get_status_storage_as_string() { + auto m = NitrokeyManager::instance(); + return get_with_string_result([&]() { + return m->get_status_storage_as_string(); + }); +} + +NK_C_API int NK_get_status_storage(NK_storage_status* out) { + if (out == nullptr) { + return -1; + } + auto m = NitrokeyManager::instance(); + auto result = get_with_status([&]() { + return m->get_status_storage(); + }, proto::stick20::DeviceConfigurationResponsePacket::ResponsePayload()); + auto error_code = std::get<0>(result); + if (error_code != 0) { + return error_code; + } + + auto status = std::get<1>(result); + out->unencrypted_volume_read_only = status.ReadWriteFlagUncryptedVolume_u8 != 0; + out->unencrypted_volume_active = status.VolumeActiceFlag_st.unencrypted; + out->encrypted_volume_read_only = status.ReadWriteFlagCryptedVolume_u8 != 0; + out->encrypted_volume_active = status.VolumeActiceFlag_st.encrypted; + out->hidden_volume_read_only = status.ReadWriteFlagHiddenVolume_u8 != 0; + out->hidden_volume_active = status.VolumeActiceFlag_st.hidden; + out->firmware_version_major = status.versionInfo.major; + out->firmware_version_minor = status.versionInfo.minor; + out->firmware_locked = status.FirmwareLocked_u8 != 0; + out->serial_number_sd_card = status.ActiveSD_CardID_u32; + out->serial_number_smart_card = status.ActiveSmartCardID_u32; + out->user_retry_count = status.UserPwRetryCount; + out->admin_retry_count = status.AdminPwRetryCount; + out->new_sd_card_found = status.NewSDCardFound_st.NewCard; + out->filled_with_random = (status.SDFillWithRandomChars_u8 & 0x01) != 0; + out->stick_initialized = status.StickKeysNotInitiated == 0; + return 0; +} + +NK_C_API int NK_get_storage_production_info(NK_storage_ProductionTest * out){ + if (out == nullptr) { + return -1; + } + auto m = NitrokeyManager::instance(); + auto result = get_with_status([&]() { + return m->production_info(); + }, proto::stick20::ProductionTest::ResponsePayload()); + + auto error_code = std::get<0>(result); + if (error_code != 0) { + return error_code; + } + + stick20::ProductionTest::ResponsePayload status = std::get<1>(result); + // Cannot use memcpy without declaring C API struct packed + // (which is not parsed by Python's CFFI apparently), hence the manual way. +#define a(x) out->x = status.x; + a(FirmwareVersion_au8[0]); + a(FirmwareVersion_au8[1]); + a(FirmwareVersionInternal_u8); + a(SD_Card_Size_u8); + a(CPU_CardID_u32); + a(SmartCardID_u32); + a(SD_CardID_u32); + a(SC_UserPwRetryCount); + a(SC_AdminPwRetryCount); + a(SD_Card_ManufacturingYear_u8); + a(SD_Card_ManufacturingMonth_u8); + a(SD_Card_OEM_u16); + a(SD_WriteSpeed_u16); + a(SD_Card_Manufacturer_u8); +#undef a + 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(); + return get_with_string_result([&]() { + return m->get_SD_usage_data_as_string(); + }); +} + +NK_C_API int NK_get_progress_bar_value() { + auto m = NitrokeyManager::instance(); + return std::get<1>(get_with_status([&]() { + return m->get_progress_bar_value(); + }, -2)); +} + +NK_C_API int NK_set_unencrypted_volume_rorw_pin_type_user() { + auto m = NitrokeyManager::instance(); + return get_with_result([&]() { + return m->set_unencrypted_volume_rorw_pin_type_user() ? 1 : 0; + }); +} + + +#ifdef __cplusplus +} +#endif diff --git a/NK_C_API_storage.h b/NK_C_API_storage.h new file mode 100644 index 0000000..48d415d --- /dev/null +++ b/NK_C_API_storage.h @@ -0,0 +1,6 @@ +#ifndef LIBNITROKEY_NK_C_API_STORAGE_H +#define LIBNITROKEY_NK_C_API_STORAGE_H + + + +#endif // LIBNITROKEY_NK_C_API_STORAGE_H diff --git a/NitrokeyManager.cc b/NitrokeyManager.cc index 329d155..3e0b5f6 100644 --- a/NitrokeyManager.cc +++ b/NitrokeyManager.cc @@ -36,32 +36,12 @@ std::mutex nitrokey::proto::send_receive_mtx; namespace nitrokey{ +constexpr int max_string_field_length = 2*1024; //storage's status string is ~1k std::mutex mex_dev_com_manager; -#ifndef strndup -#ifdef _WIN32 -#pragma message "Using own strndup" -char * strndup(const char* str, size_t maxlen){ - size_t len = strnlen(str, maxlen); - char* dup = (char *) malloc(len + 1); - memcpy(dup, str, len); - dup[len] = 0; - return dup; -} -#endif -#endif - using nitrokey::misc::strcpyT; - template <typename T> - typename T::CommandPayload get_payload(){ - //Create, initialize and return by value command payload - typename T::CommandPayload st; - bzero(&st, sizeof(st)); - return st; - } - // package type to auth, auth type [Authorize,UserAuthorize] template <typename S, typename A, typename T> @@ -692,7 +672,6 @@ using nitrokey::misc::strcpyT; return get_slot_name(slot_number); } - static const int max_string_field_length = 2*1024; //storage's status string is ~1k char * NitrokeyManager::get_slot_name(uint8_t slot_number) { auto payload = get_payload<GetSlotName>(); @@ -1009,147 +988,6 @@ using nitrokey::misc::strcpyT; return true; } - //storage commands - - void NitrokeyManager::send_startup(uint64_t seconds_from_epoch){ - auto p = get_payload<stick20::SendStartup>(); -// p.set_defaults(); //set current time - p.localtime = seconds_from_epoch; - stick20::SendStartup::CommandTransaction::run(device, p); - } - - void NitrokeyManager::unlock_encrypted_volume(const char* user_pin){ - misc::execute_password_command<stick20::EnableEncryptedPartition>(device, user_pin); - } - - void NitrokeyManager::unlock_hidden_volume(const char* hidden_volume_password) { - misc::execute_password_command<stick20::EnableHiddenEncryptedPartition>(device, hidden_volume_password); - } - - void NitrokeyManager::set_encrypted_volume_read_only(const char* admin_pin) { - misc::execute_password_command<stick20::SetEncryptedVolumeReadOnly>(device, admin_pin); - } - - void NitrokeyManager::set_encrypted_volume_read_write(const char* admin_pin) { - misc::execute_password_command<stick20::SetEncryptedVolumeReadWrite>(device, admin_pin); - } - - //TODO check is encrypted volume unlocked before execution - //if not return library exception - void NitrokeyManager::create_hidden_volume(uint8_t slot_nr, uint8_t start_percent, uint8_t end_percent, - const char *hidden_volume_password) { - auto p = get_payload<stick20::SetupHiddenVolume>(); - p.SlotNr_u8 = slot_nr; - p.StartBlockPercent_u8 = start_percent; - p.EndBlockPercent_u8 = end_percent; - strcpyT(p.HiddenVolumePassword_au8, hidden_volume_password); - stick20::SetupHiddenVolume::CommandTransaction::run(device, p); - } - - void NitrokeyManager::set_unencrypted_read_only_admin(const char* admin_pin) { - //from v0.49, v0.52+ it needs Admin PIN - if (set_unencrypted_volume_rorw_pin_type_user()){ - LOG("set_unencrypted_read_only_admin is not supported for this version of Storage device. " - "Please update firmware to v0.52+. Doing nothing.", nitrokey::log::Loglevel::WARNING); - return; - } - misc::execute_password_command<stick20::SetUnencryptedVolumeReadOnlyAdmin>(device, admin_pin); - } - - void NitrokeyManager::set_unencrypted_read_only(const char *user_pin) { - //until v0.48 (incl. v0.50 and v0.51) User PIN was sufficient - LOG("set_unencrypted_read_only is deprecated. Use set_unencrypted_read_only_admin instead.", - nitrokey::log::Loglevel::WARNING); - if (!set_unencrypted_volume_rorw_pin_type_user()){ - LOG("set_unencrypted_read_only is not supported for this version of Storage device. Doing nothing.", - nitrokey::log::Loglevel::WARNING); - return; - } - misc::execute_password_command<stick20::SendSetReadonlyToUncryptedVolume>(device, user_pin); - } - - void NitrokeyManager::set_unencrypted_read_write_admin(const char* admin_pin) { - //from v0.49, v0.52+ it needs Admin PIN - if (set_unencrypted_volume_rorw_pin_type_user()){ - LOG("set_unencrypted_read_write_admin is not supported for this version of Storage device. " - "Please update firmware to v0.52+. Doing nothing.", nitrokey::log::Loglevel::WARNING); - return; - } - misc::execute_password_command<stick20::SetUnencryptedVolumeReadWriteAdmin>(device, admin_pin); - } - - void NitrokeyManager::set_unencrypted_read_write(const char *user_pin) { - //until v0.48 (incl. v0.50 and v0.51) User PIN was sufficient - LOG("set_unencrypted_read_write is deprecated. Use set_unencrypted_read_write_admin instead.", - nitrokey::log::Loglevel::WARNING); - if (!set_unencrypted_volume_rorw_pin_type_user()){ - LOG("set_unencrypted_read_write is not supported for this version of Storage device. Doing nothing.", - nitrokey::log::Loglevel::WARNING); - return; - } - misc::execute_password_command<stick20::SendSetReadwriteToUncryptedVolume>(device, user_pin); - } - - bool NitrokeyManager::set_unencrypted_volume_rorw_pin_type_user(){ - auto minor_firmware_version = get_minor_firmware_version(); - return minor_firmware_version <= 48 || minor_firmware_version == 50 || minor_firmware_version == 51; - } - - void NitrokeyManager::export_firmware(const char* admin_pin) { - misc::execute_password_command<stick20::ExportFirmware>(device, admin_pin); - } - - void NitrokeyManager::enable_firmware_update(const char* firmware_pin) { - misc::execute_password_command<stick20::EnableFirmwareUpdate>(device, firmware_pin); - } - - void NitrokeyManager::clear_new_sd_card_warning(const char* admin_pin) { - misc::execute_password_command<stick20::SendClearNewSdCardFound>(device, admin_pin); - } - - void NitrokeyManager::fill_SD_card_with_random_data(const char* admin_pin) { - auto p = get_payload<stick20::FillSDCardWithRandomChars>(); - p.set_defaults(); - strcpyT(p.admin_pin, admin_pin); - stick20::FillSDCardWithRandomChars::CommandTransaction::run(device, p); - } - - void NitrokeyManager::change_update_password(const char* current_update_password, const char* new_update_password) { - auto p = get_payload<stick20::ChangeUpdatePassword>(); - strcpyT(p.current_update_password, current_update_password); - strcpyT(p.new_update_password, new_update_password); - stick20::ChangeUpdatePassword::CommandTransaction::run(device, p); - } - - char * NitrokeyManager::get_status_storage_as_string(){ - auto p = stick20::GetDeviceStatus::CommandTransaction::run(device); - return strndup(p.data().dissect().c_str(), max_string_field_length); - } - - stick20::DeviceConfigurationResponsePacket::ResponsePayload NitrokeyManager::get_status_storage(){ - auto p = stick20::GetDeviceStatus::CommandTransaction::run(device); - return p.data(); - } - - char * NitrokeyManager::get_SD_usage_data_as_string(){ - auto p = stick20::GetSDCardOccupancy::CommandTransaction::run(device); - return strndup(p.data().dissect().c_str(), max_string_field_length); - } - - std::pair<uint8_t,uint8_t> NitrokeyManager::get_SD_usage_data(){ - auto p = stick20::GetSDCardOccupancy::CommandTransaction::run(device); - return std::make_pair(p.data().WriteLevelMin, p.data().WriteLevelMax); - } - - int NitrokeyManager::get_progress_bar_value(){ - try{ - stick20::GetDeviceStatus::CommandTransaction::run(device); - return -1; - } - catch (LongOperationInProgressException &e){ - return e.progress_bar_value; - } - } string NitrokeyManager::get_TOTP_code(uint8_t slot_number, const char *user_temporary_password) { return get_TOTP_code(slot_number, 0, 0, 0, user_temporary_password); @@ -1190,32 +1028,11 @@ using nitrokey::misc::strcpyT; return get_OTP_slot_data(get_internal_slot_number_for_hotp(slot_number)); } - void NitrokeyManager::lock_encrypted_volume() { - misc::execute_password_command<stick20::DisableEncryptedPartition>(device, ""); - } - - void NitrokeyManager::lock_hidden_volume() { - misc::execute_password_command<stick20::DisableHiddenEncryptedPartition>(device, ""); - } - - uint8_t NitrokeyManager::get_SD_card_size() { - auto data = stick20::ProductionTest::CommandTransaction::run(device); - return data.data().SD_Card_Size_u8; - } const string NitrokeyManager::get_current_device_id() const { return current_device_id; } - void NitrokeyManager::wink(){ - stick20::Wink::CommandTransaction::run(device); - }; - - stick20::ProductionTest::ResponsePayload NitrokeyManager::production_info(){ - auto data = stick20::ProductionTest::CommandTransaction::run(device); - return data.data(); - }; - void NitrokeyManager::enable_firmware_update_pro(const char *firmware_pin) { auto p = get_payload<FirmwareUpdate>(); strcpyT(p.firmware_password, firmware_pin); diff --git a/NitrokeyManagerStorage.cpp b/NitrokeyManagerStorage.cpp new file mode 100644 index 0000000..6f37d88 --- /dev/null +++ b/NitrokeyManagerStorage.cpp @@ -0,0 +1,175 @@ +#include "NitrokeyManagerStorage.h" + +//using namespace nitrokey; +namespace nitrokey{ + +using nitrokey::misc::strcpyT; +constexpr int max_string_field_length = 2*1024; //storage's status string is ~1k + +//storage commands + +void NitrokeyManager::send_startup(uint64_t seconds_from_epoch){ + auto p = get_payload<stick20::SendStartup>(); +// p.set_defaults(); //set current time + p.localtime = seconds_from_epoch; + stick20::SendStartup::CommandTransaction::run(device, p); +} + +void NitrokeyManager::unlock_encrypted_volume(const char* user_pin){ + misc::execute_password_command<stick20::EnableEncryptedPartition>(device, user_pin); +} + +void NitrokeyManager::unlock_hidden_volume(const char* hidden_volume_password) { + misc::execute_password_command<stick20::EnableHiddenEncryptedPartition>(device, hidden_volume_password); +} + +void NitrokeyManager::set_encrypted_volume_read_only(const char* admin_pin) { + misc::execute_password_command<stick20::SetEncryptedVolumeReadOnly>(device, admin_pin); +} + +void NitrokeyManager::set_encrypted_volume_read_write(const char* admin_pin) { + misc::execute_password_command<stick20::SetEncryptedVolumeReadWrite>(device, admin_pin); +} + +//TODO check is encrypted volume unlocked before execution +//if not return library exception +void NitrokeyManager::create_hidden_volume(uint8_t slot_nr, uint8_t start_percent, uint8_t end_percent, + const char *hidden_volume_password) { + auto p = get_payload<stick20::SetupHiddenVolume>(); + p.SlotNr_u8 = slot_nr; + p.StartBlockPercent_u8 = start_percent; + p.EndBlockPercent_u8 = end_percent; + strcpyT(p.HiddenVolumePassword_au8, hidden_volume_password); + stick20::SetupHiddenVolume::CommandTransaction::run(device, p); +} + +void NitrokeyManager::set_unencrypted_read_only_admin(const char* admin_pin) { + //from v0.49, v0.52+ it needs Admin PIN + if (set_unencrypted_volume_rorw_pin_type_user()){ + LOG("set_unencrypted_read_only_admin is not supported for this version of Storage device. " + "Please update firmware to v0.52+. Doing nothing.", nitrokey::log::Loglevel::WARNING); + return; + } + misc::execute_password_command<stick20::SetUnencryptedVolumeReadOnlyAdmin>(device, admin_pin); +} + +void NitrokeyManager::set_unencrypted_read_only(const char *user_pin) { + //until v0.48 (incl. v0.50 and v0.51) User PIN was sufficient + LOG("set_unencrypted_read_only is deprecated. Use set_unencrypted_read_only_admin instead.", + nitrokey::log::Loglevel::WARNING); + if (!set_unencrypted_volume_rorw_pin_type_user()){ + LOG("set_unencrypted_read_only is not supported for this version of Storage device. Doing nothing.", + nitrokey::log::Loglevel::WARNING); + return; + } + misc::execute_password_command<stick20::SendSetReadonlyToUncryptedVolume>(device, user_pin); +} + +void NitrokeyManager::set_unencrypted_read_write_admin(const char* admin_pin) { + //from v0.49, v0.52+ it needs Admin PIN + if (set_unencrypted_volume_rorw_pin_type_user()){ + LOG("set_unencrypted_read_write_admin is not supported for this version of Storage device. " + "Please update firmware to v0.52+. Doing nothing.", nitrokey::log::Loglevel::WARNING); + return; + } + misc::execute_password_command<stick20::SetUnencryptedVolumeReadWriteAdmin>(device, admin_pin); +} + +void NitrokeyManager::set_unencrypted_read_write(const char *user_pin) { + //until v0.48 (incl. v0.50 and v0.51) User PIN was sufficient + LOG("set_unencrypted_read_write is deprecated. Use set_unencrypted_read_write_admin instead.", + nitrokey::log::Loglevel::WARNING); + if (!set_unencrypted_volume_rorw_pin_type_user()){ + LOG("set_unencrypted_read_write is not supported for this version of Storage device. Doing nothing.", + nitrokey::log::Loglevel::WARNING); + return; + } + misc::execute_password_command<stick20::SendSetReadwriteToUncryptedVolume>(device, user_pin); +} + +bool NitrokeyManager::set_unencrypted_volume_rorw_pin_type_user(){ + auto minor_firmware_version = get_minor_firmware_version(); + return minor_firmware_version <= 48 || minor_firmware_version == 50 || minor_firmware_version == 51; +} + +void NitrokeyManager::export_firmware(const char* admin_pin) { + misc::execute_password_command<stick20::ExportFirmware>(device, admin_pin); +} + +void NitrokeyManager::enable_firmware_update(const char* firmware_pin) { + misc::execute_password_command<stick20::EnableFirmwareUpdate>(device, firmware_pin); +} + +void NitrokeyManager::clear_new_sd_card_warning(const char* admin_pin) { + misc::execute_password_command<stick20::SendClearNewSdCardFound>(device, admin_pin); +} + +void NitrokeyManager::fill_SD_card_with_random_data(const char* admin_pin) { + auto p = get_payload<stick20::FillSDCardWithRandomChars>(); + p.set_defaults(); + strcpyT(p.admin_pin, admin_pin); + stick20::FillSDCardWithRandomChars::CommandTransaction::run(device, p); +} + +void NitrokeyManager::change_update_password(const char* current_update_password, const char* new_update_password) { + auto p = get_payload<stick20::ChangeUpdatePassword>(); + strcpyT(p.current_update_password, current_update_password); + strcpyT(p.new_update_password, new_update_password); + stick20::ChangeUpdatePassword::CommandTransaction::run(device, p); +} + +char * NitrokeyManager::get_status_storage_as_string(){ + auto p = stick20::GetDeviceStatus::CommandTransaction::run(device); + return strndup(p.data().dissect().c_str(), max_string_field_length); +} + +stick20::DeviceConfigurationResponsePacket::ResponsePayload NitrokeyManager::get_status_storage(){ + auto p = stick20::GetDeviceStatus::CommandTransaction::run(device); + return p.data(); +} + +char * NitrokeyManager::get_SD_usage_data_as_string(){ + auto p = stick20::GetSDCardOccupancy::CommandTransaction::run(device); + return strndup(p.data().dissect().c_str(), max_string_field_length); +} + +std::pair<uint8_t,uint8_t> NitrokeyManager::get_SD_usage_data(){ + auto p = stick20::GetSDCardOccupancy::CommandTransaction::run(device); + return std::make_pair(p.data().WriteLevelMin, p.data().WriteLevelMax); +} + +int NitrokeyManager::get_progress_bar_value(){ + try{ + stick20::GetDeviceStatus::CommandTransaction::run(device); + return -1; + } + catch (LongOperationInProgressException &e){ + return e.progress_bar_value; + } +} + + +void NitrokeyManager::lock_encrypted_volume() { + misc::execute_password_command<stick20::DisableEncryptedPartition>(device, ""); +} + +void NitrokeyManager::lock_hidden_volume() { + misc::execute_password_command<stick20::DisableHiddenEncryptedPartition>(device, ""); +} + +uint8_t NitrokeyManager::get_SD_card_size() { + auto data = stick20::ProductionTest::CommandTransaction::run(device); + return data.data().SD_Card_Size_u8; +} + + +void NitrokeyManager::wink(){ + stick20::Wink::CommandTransaction::run(device); +}; + +stick20::ProductionTest::ResponsePayload NitrokeyManager::production_info(){ + auto data = stick20::ProductionTest::CommandTransaction::run(device); + return data.data(); +}; + +}
\ No newline at end of file diff --git a/NitrokeyManagerStorage.h b/NitrokeyManagerStorage.h new file mode 100644 index 0000000..a127bac --- /dev/null +++ b/NitrokeyManagerStorage.h @@ -0,0 +1,6 @@ +#ifndef LIBNITROKEY_NITROKEYMANAGERSTORAGE_H +#define LIBNITROKEY_NITROKEYMANAGERSTORAGE_H + +#include "NitrokeyManager.h" + +#endif // LIBNITROKEY_NITROKEYMANAGERSTORAGE_H diff --git a/libnitrokey/NitrokeyManager.h b/libnitrokey/NitrokeyManager.h index 163a799..ba61793 100644 --- a/libnitrokey/NitrokeyManager.h +++ b/libnitrokey/NitrokeyManager.h @@ -40,10 +40,15 @@ namespace nitrokey { using namespace nitrokey::proto; using namespace nitrokey::log; +template <typename T> +typename T::CommandPayload get_payload(){ + //Create, initialize and return by value command payload + typename T::CommandPayload st; + bzero(&st, sizeof(st)); + return st; +} -#ifdef __WIN32 -char * strndup(const char* str, size_t maxlen); -#endif +#include "nk_strndup.h" class NitrokeyManager { public: diff --git a/libnitrokey/nk_strndup.h b/libnitrokey/nk_strndup.h new file mode 100644 index 0000000..0c96726 --- /dev/null +++ b/libnitrokey/nk_strndup.h @@ -0,0 +1,9 @@ +#ifndef LIBNITROKEY_NK_STRNDUP_H +#define LIBNITROKEY_NK_STRNDUP_H + +#ifdef __WIN32 +char * strndup(const char* str, size_t maxlen); +#endif + + +#endif // LIBNITROKEY_NK_STRNDUP_H diff --git a/nk_strndup.c b/nk_strndup.c new file mode 100644 index 0000000..e24c584 --- /dev/null +++ b/nk_strndup.c @@ -0,0 +1,14 @@ +#include "nk_strndup.h" + +#ifndef strndup +#ifdef _WIN32 +#pragma message "Using own strndup" +char * strndup(const char* str, size_t maxlen){ + size_t len = strnlen(str, maxlen); + char* dup = (char *) malloc(len + 1); + memcpy(dup, str, len); + dup[len] = 0; + return dup; +} +#endif +#endif
\ No newline at end of file |