From f6e09cc2fb4541a15a57415439b575d7bf44b07f Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Fri, 25 May 2018 12:00:21 +0200 Subject: Refactor result retrieval in C API The result retrieval functions get_with_array_result, get_with_string_result, get_with_result and get_without_result currently contain much duplicated code: the error handling. This patch tries to simplify this code by introducing a new function, get_with_status, that executes a function, catches errors and returns the error code together with the result of the function or a fallback value passed by the user if the function failed. get_with_array_result, get_with_string_result and get_with_result are adapted to use this function. get_without_result is not changed as it has a different error handling logic than the other functions: It ignores any InvalidCRCReceived exceptions. --- NK_C_API.cc | 46 +++++++++++++++------------------------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/NK_C_API.cc b/NK_C_API.cc index 8e005b8..41c38aa 100644 --- a/NK_C_API.cc +++ b/NK_C_API.cc @@ -21,6 +21,7 @@ #include "NK_C_API.h" #include +#include #include "libnitrokey/NitrokeyManager.h" #include #include "libnitrokey/LibraryException.h" @@ -52,11 +53,11 @@ T* duplicate_vector_and_clear(std::vector &v){ return d; } -template -uint8_t * get_with_array_result(T func){ +template +std::tuple get_with_status(T func, R fallback) { NK_last_command_status = 0; try { - return func(); + return std::make_tuple(0, func()); } catch (CommandFailedException & commandFailedException){ NK_last_command_status = commandFailedException.last_command_status; @@ -67,43 +68,26 @@ uint8_t * get_with_array_result(T func){ catch (const DeviceCommunicationException &deviceException){ NK_last_command_status = 256-deviceException.getType(); } - return nullptr; + return std::make_tuple(NK_last_command_status, fallback); +} + +template +uint8_t * get_with_array_result(T func){ + return std::get<1>(get_with_status(func, nullptr)); } template char* get_with_string_result(T func){ - NK_last_command_status = 0; - try { - return func(); + auto result = std::get<1>(get_with_status(func, nullptr)); + if (result == nullptr) { + return strndup("", MAXIMUM_STR_REPLY_LENGTH); } - 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 strndup("", MAXIMUM_STR_REPLY_LENGTH); + return result; } template auto get_with_result(T func){ - NK_last_command_status = 0; - try { - return 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 static_cast(0); + return std::get<1>(get_with_status(func, static_cast(0))); } template -- cgit v1.2.1 From 98917cffc50e7934105e874abd4a4b6ed72edc21 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Fri, 25 May 2018 12:15:08 +0200 Subject: Add getter for Storage status to C API The C++ API currently provides the Storage status in NitrokeyManager::get_status_storage(). The C API only provides a string version of this data (NK_get_status_storage_as_string). This patch adds a struct to the C API that can store the storage status and a function that can retrieve it. The interpretation of the fields of the internal struct is based on the following code in the Nitrokey Storage firmware: - src/HighLevelFunctions/FlashStorage.h, lines 73 to 90 (struct definition with comments) - src/OTP/report_protocol.c, lines 241 to 376 (debug output of the data) --- NK_C_API.cc | 34 +++++++++++++++++++++++++ NK_C_API.h | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/NK_C_API.cc b/NK_C_API.cc index 41c38aa..f6a6153 100644 --- a/NK_C_API.cc +++ b/NK_C_API.cc @@ -26,6 +26,7 @@ #include #include "libnitrokey/LibraryException.h" #include "libnitrokey/cxx_semantics.h" +#include "libnitrokey/stick20_commands.h" #ifdef _MSC_VER #ifdef _WIN32 @@ -580,6 +581,39 @@ extern "C" { }); } + 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 char* NK_get_SD_usage_data_as_string() { auto m = NitrokeyManager::instance(); return get_with_string_result([&]() { diff --git a/NK_C_API.h b/NK_C_API.h index 5985c0b..97169d1 100644 --- a/NK_C_API.h +++ b/NK_C_API.h @@ -51,6 +51,77 @@ extern "C" { NK_STORAGE }; + /** + * Stores the status of a Storage device. + */ + struct NK_storage_status { + /** + * Indicates whether the unencrypted volume is read-only. + */ + bool unencrypted_volume_read_only; + /** + * Indicates whether the unencrypted volume is active. + */ + bool unencrypted_volume_active; + /** + * Indicates whether the encrypted volume is read-only. + */ + bool encrypted_volume_read_only; + /** + * Indicates whether the encrypted volume is active. + */ + bool encrypted_volume_active; + /** + * Indicates whether the hidden volume is read-only. + */ + bool hidden_volume_read_only; + /** + * Indicates whether the hidden volume is active. + */ + bool hidden_volume_active; + /** + * 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; + /** + * Indicates whether the firmware is locked. + */ + bool firmware_locked; + /** + * The serial number of the SD card in the Storage stick. + */ + uint32_t serial_number_sd_card; + /** + * The serial number of the smart card in the Storage stick. + */ + uint32_t serial_number_smart_card; + /** + * The number of remaining login attempts for the user PIN. + */ + uint8_t user_retry_count; + /** + * The number of remaining login attempts for the admin PIN. + */ + uint8_t admin_retry_count; + /** + * Indicates whether a new SD card was found. + */ + bool new_sd_card_found; + /** + * Indicates whether the SD card is filled with random characters. + */ + bool filled_with_random; + /** + * Indicates whether the stick has been initialized by generating + * the AES keys. + */ + bool stick_initialized; + }; + /** * Set debug level of messages written on stderr * @param state state=True - most messages, state=False - only errors level @@ -586,6 +657,17 @@ extern "C" { */ NK_C_API char* NK_get_status_storage_as_string(); + /** + * Get the Storage stick status 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 storage status + * @return command processing error code + */ + NK_C_API int NK_get_status_storage(NK_storage_status* out); + /** * Get SD card usage attributes as string. * Usable during hidden volumes creation. -- cgit v1.2.1 From 5edb645227c00c63badc4fb3cccefa4d7e1bb547 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Tue, 19 Jun 2018 14:23:47 +0200 Subject: Add missing struct keyword Signed-off-by: Szczepan Zalega --- NK_C_API.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NK_C_API.h b/NK_C_API.h index 97169d1..274f908 100644 --- a/NK_C_API.h +++ b/NK_C_API.h @@ -666,7 +666,7 @@ extern "C" { * @param out the output pointer for the storage status * @return command processing error code */ - NK_C_API int NK_get_status_storage(NK_storage_status* out); + NK_C_API int NK_get_status_storage(struct NK_storage_status* out); /** * Get SD card usage attributes as string. -- cgit v1.2.1