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 | 
