From a36392dd83def4397d100addf57870ebea5de0e9 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Tue, 28 Jul 2020 12:50:53 +0200 Subject: Extract OTP features to separate unit Signed-off-by: Szczepan Zalega --- NitrokeyManager.cc | 371 ++--------------------------------------------------- 1 file changed, 8 insertions(+), 363 deletions(-) (limited to 'NitrokeyManager.cc') diff --git a/NitrokeyManager.cc b/NitrokeyManager.cc index 3e0b5f6..cde559b 100644 --- a/NitrokeyManager.cc +++ b/NitrokeyManager.cc @@ -19,25 +19,23 @@ * SPDX-License-Identifier: LGPL-3.0 */ -#include -#include #include "libnitrokey/NitrokeyManager.h" +#include "NitrokeyManagerOTP.h" #include "libnitrokey/LibraryException.h" -#include -#include -#include -#include "libnitrokey/misc.h" -#include #include "libnitrokey/cxx_semantics.h" #include "libnitrokey/misc.h" +#include +#include #include +#include +#include #include +#include +#include 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; using nitrokey::misc::strcpyT; @@ -420,265 +418,7 @@ using nitrokey::misc::strcpyT; return response.data().dissect(); } - string getFilledOTPCode(uint32_t code, bool use_8_digits){ - stringstream s; - s << std::right << std::setw(use_8_digits ? 8 : 6) << std::setfill('0') << code; - return s.str(); - } - - string NitrokeyManager::get_HOTP_code(uint8_t slot_number, const char *user_temporary_password) { - if (!is_valid_hotp_slot_number(slot_number)) throw InvalidSlotException(slot_number); - - if (is_authorization_command_supported()){ - auto gh = get_payload(); - gh.slot_number = get_internal_slot_number_for_hotp(slot_number); - if(user_temporary_password != nullptr && strlen(user_temporary_password)!=0){ //FIXME use string instead of strlen - authorize_packet(gh, user_temporary_password, device); - } - auto resp = GetHOTP::CommandTransaction::run(device, gh); - return getFilledOTPCode(resp.data().code, resp.data().use_8_digits); - } else { - auto gh = get_payload(); - gh.slot_number = get_internal_slot_number_for_hotp(slot_number); - if(user_temporary_password != nullptr && strlen(user_temporary_password)!=0) { - strcpyT(gh.temporary_user_password, user_temporary_password); - } - auto resp = stick10_08::GetHOTP::CommandTransaction::run(device, gh); - return getFilledOTPCode(resp.data().code, resp.data().use_8_digits); - } - return ""; - } - - bool NitrokeyManager::is_internal_hotp_slot_number(uint8_t slot_number) const { return slot_number < 0x20; } - bool NitrokeyManager::is_valid_hotp_slot_number(uint8_t slot_number) const { return slot_number < 3; } - bool NitrokeyManager::is_valid_totp_slot_number(uint8_t slot_number) const { return slot_number < 0x10-1; } //15 - uint8_t NitrokeyManager::get_internal_slot_number_for_totp(uint8_t slot_number) const { return (uint8_t) (0x20 + slot_number); } - uint8_t NitrokeyManager::get_internal_slot_number_for_hotp(uint8_t slot_number) const { return (uint8_t) (0x10 + slot_number); } - - - - string NitrokeyManager::get_TOTP_code(uint8_t slot_number, uint64_t challenge, uint64_t last_totp_time, - uint8_t last_interval, - const char *user_temporary_password) { - if(!is_valid_totp_slot_number(slot_number)) throw InvalidSlotException(slot_number); - slot_number = get_internal_slot_number_for_totp(slot_number); - - if (is_authorization_command_supported()){ - auto gt = get_payload(); - gt.slot_number = slot_number; - gt.challenge = challenge; - gt.last_interval = last_interval; - gt.last_totp_time = last_totp_time; - - if(user_temporary_password != nullptr && strlen(user_temporary_password)!=0){ //FIXME use string instead of strlen - authorize_packet(gt, user_temporary_password, device); - } - auto resp = GetTOTP::CommandTransaction::run(device, gt); - return getFilledOTPCode(resp.data().code, resp.data().use_8_digits); - } else { - auto gt = get_payload(); - strcpyT(gt.temporary_user_password, user_temporary_password); - gt.slot_number = slot_number; - auto resp = stick10_08::GetTOTP::CommandTransaction::run(device, gt); - return getFilledOTPCode(resp.data().code, resp.data().use_8_digits); - } - return ""; - } - - bool NitrokeyManager::erase_slot(uint8_t slot_number, const char *temporary_password) { - if (is_authorization_command_supported()){ - auto p = get_payload(); - p.slot_number = slot_number; - authorize_packet(p, temporary_password, device); - auto resp = EraseSlot::CommandTransaction::run(device,p); - } else { - auto p = get_payload(); - p.slot_number = slot_number; - strcpyT(p.temporary_admin_password, temporary_password); - auto resp = stick10_08::EraseSlot::CommandTransaction::run(device,p); - } - return true; - } - - bool NitrokeyManager::erase_hotp_slot(uint8_t slot_number, const char *temporary_password) { - if (!is_valid_hotp_slot_number(slot_number)) throw InvalidSlotException(slot_number); - slot_number = get_internal_slot_number_for_hotp(slot_number); - return erase_slot(slot_number, temporary_password); - } - - bool NitrokeyManager::erase_totp_slot(uint8_t slot_number, const char *temporary_password) { - if (!is_valid_totp_slot_number(slot_number)) throw InvalidSlotException(slot_number); - slot_number = get_internal_slot_number_for_totp(slot_number); - return erase_slot(slot_number, temporary_password); - } - - template - void vector_copy_ranged(T& dest, std::vector &vec, size_t begin, size_t elements_to_copy){ - const size_t d_size = sizeof(dest); - if(d_size < elements_to_copy){ - throw TargetBufferSmallerThanSource(elements_to_copy, d_size); - } - std::fill(dest, dest+d_size, 0); - std::copy(vec.begin() + begin, vec.begin() +begin + elements_to_copy, dest); - } - - template - void vector_copy(T& dest, std::vector &vec){ - const size_t d_size = sizeof(dest); - if(d_size < vec.size()){ - throw TargetBufferSmallerThanSource(vec.size(), d_size); - } - std::fill(dest, dest+d_size, 0); - std::copy(vec.begin(), vec.end(), dest); - } - - bool NitrokeyManager::write_HOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint64_t hotp_counter, - bool use_8_digits, bool use_enter, bool use_tokenID, const char *token_ID, - const char *temporary_password) { - if (!is_valid_hotp_slot_number(slot_number)) throw InvalidSlotException(slot_number); - - int internal_slot_number = get_internal_slot_number_for_hotp(slot_number); - if (is_authorization_command_supported()){ - write_HOTP_slot_authorize(internal_slot_number, slot_name, secret, hotp_counter, use_8_digits, use_enter, use_tokenID, - token_ID, temporary_password); - } else { - write_OTP_slot_no_authorize(internal_slot_number, slot_name, secret, hotp_counter, use_8_digits, use_enter, use_tokenID, - token_ID, temporary_password); - } - return true; - } - - void NitrokeyManager::write_HOTP_slot_authorize(uint8_t slot_number, const char *slot_name, const char *secret, - uint64_t hotp_counter, bool use_8_digits, bool use_enter, - bool use_tokenID, const char *token_ID, const char *temporary_password) { - auto payload = get_payload(); - payload.slot_number = slot_number; - auto secret_bin = misc::hex_string_to_byte(secret); - vector_copy(payload.slot_secret, secret_bin); - strcpyT(payload.slot_name, slot_name); - strcpyT(payload.slot_token_id, token_ID); - switch (device->get_device_model() ){ - case DeviceModel::LIBREM: - case DeviceModel::PRO: { - payload.slot_counter = hotp_counter; - break; - } - case DeviceModel::STORAGE: { - string counter = to_string(hotp_counter); - strcpyT(payload.slot_counter_s, counter.c_str()); - break; - } - default: - LOG(string(__FILE__) + to_string(__LINE__) + - string(__FUNCTION__) + string(" Unhandled device model for HOTP") - , Loglevel::DEBUG); - break; - } - payload.use_8_digits = use_8_digits; - payload.use_enter = use_enter; - payload.use_tokenID = use_tokenID; - - authorize_packet(payload, temporary_password, device); - - auto resp = WriteToHOTPSlot::CommandTransaction::run(device, payload); - } - - bool NitrokeyManager::write_TOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint16_t time_window, - bool use_8_digits, bool use_enter, bool use_tokenID, const char *token_ID, - const char *temporary_password) { - if (!is_valid_totp_slot_number(slot_number)) throw InvalidSlotException(slot_number); - int internal_slot_number = get_internal_slot_number_for_totp(slot_number); - - if (is_authorization_command_supported()){ - write_TOTP_slot_authorize(internal_slot_number, slot_name, secret, time_window, use_8_digits, use_enter, use_tokenID, - token_ID, temporary_password); - } else { - write_OTP_slot_no_authorize(internal_slot_number, slot_name, secret, time_window, use_8_digits, use_enter, use_tokenID, - token_ID, temporary_password); - } - - return true; - } - - void NitrokeyManager::write_OTP_slot_no_authorize(uint8_t internal_slot_number, const char *slot_name, - const char *secret, - uint64_t counter_or_interval, bool use_8_digits, bool use_enter, - bool use_tokenID, const char *token_ID, - const char *temporary_password) const { - - auto payload2 = get_payload(); - strcpyT(payload2.temporary_admin_password, temporary_password); - strcpyT(payload2.data, slot_name); - payload2.setTypeName(); - stick10_08::SendOTPData::CommandTransaction::run(device, payload2); - - payload2.setTypeSecret(); - payload2.id = 0; - auto secret_bin = misc::hex_string_to_byte(secret); - auto remaining_secret_length = secret_bin.size(); - const auto maximum_OTP_secret_size = 40; - if(remaining_secret_length > maximum_OTP_secret_size){ - throw TargetBufferSmallerThanSource(remaining_secret_length, maximum_OTP_secret_size); - } - - while (remaining_secret_length>0){ - const auto bytesToCopy = std::min(sizeof(payload2.data), remaining_secret_length); - const auto start = secret_bin.size() - remaining_secret_length; - memset(payload2.data, 0, sizeof(payload2.data)); - vector_copy_ranged(payload2.data, secret_bin, start, bytesToCopy); - stick10_08::SendOTPData::CommandTransaction::run(device, payload2); - remaining_secret_length -= bytesToCopy; - payload2.id++; - } - - auto payload = get_payload(); - strcpyT(payload.temporary_admin_password, temporary_password); - strcpyT(payload.slot_token_id, token_ID); - payload.use_8_digits = use_8_digits; - payload.use_enter = use_enter; - payload.use_tokenID = use_tokenID; - payload.slot_counter_or_interval = counter_or_interval; - payload.slot_number = internal_slot_number; - stick10_08::WriteToOTPSlot::CommandTransaction::run(device, payload); - } - - void NitrokeyManager::write_TOTP_slot_authorize(uint8_t slot_number, const char *slot_name, const char *secret, - uint16_t time_window, bool use_8_digits, bool use_enter, - bool use_tokenID, const char *token_ID, const char *temporary_password) { - auto payload = get_payload(); - payload.slot_number = slot_number; - auto secret_bin = misc::hex_string_to_byte(secret); - vector_copy(payload.slot_secret, secret_bin); - strcpyT(payload.slot_name, slot_name); - strcpyT(payload.slot_token_id, token_ID); - payload.slot_interval = time_window; //FIXME naming - payload.use_8_digits = use_8_digits; - payload.use_enter = use_enter; - payload.use_tokenID = use_tokenID; - - authorize_packet(payload, temporary_password, device); - - auto resp = WriteToTOTPSlot::CommandTransaction::run(device, payload); - } - - char * NitrokeyManager::get_totp_slot_name(uint8_t slot_number) { - if (!is_valid_totp_slot_number(slot_number)) throw InvalidSlotException(slot_number); - slot_number = get_internal_slot_number_for_totp(slot_number); - return get_slot_name(slot_number); - } - char * NitrokeyManager::get_hotp_slot_name(uint8_t slot_number) { - if (!is_valid_hotp_slot_number(slot_number)) throw InvalidSlotException(slot_number); - slot_number = get_internal_slot_number_for_hotp(slot_number); - return get_slot_name(slot_number); - } - - - char * NitrokeyManager::get_slot_name(uint8_t slot_number) { - auto payload = get_payload(); - payload.slot_number = slot_number; - auto resp = GetSlotName::CommandTransaction::run(device, payload); - return strndup((const char *) resp.data().slot_name, max_string_field_length); - } + // 15 bool NitrokeyManager::first_authenticate(const char *pin, const char *temporary_password) { auto authreq = get_payload(); @@ -688,26 +428,6 @@ using nitrokey::misc::strcpyT; return true; } - bool NitrokeyManager::set_time(uint64_t time) { - auto p = get_payload(); - p.reset = 1; - p.time = time; - SetTime::CommandTransaction::run(device, p); - return false; - } - - void NitrokeyManager::set_time_soft(uint64_t time) { - auto p = get_payload(); - p.reset = 0; - p.time = time; - SetTime::CommandTransaction::run(device, p); - } - - bool NitrokeyManager::get_time(uint64_t time) { - set_time_soft(time); - return true; - } - void NitrokeyManager::change_user_PIN(const char *current_PIN, const char *new_PIN) { change_PIN_general(current_PIN, new_PIN); } @@ -888,30 +608,6 @@ using nitrokey::misc::strcpyT; } } - - void NitrokeyManager::write_config(uint8_t numlock, uint8_t capslock, uint8_t scrolllock, bool enable_user_password, - bool delete_user_password, const char *admin_temporary_password) { - auto p = get_payload(); - p.numlock = numlock; - p.capslock = capslock; - p.scrolllock = scrolllock; - p.enable_user_password = static_cast(enable_user_password ? 1 : 0); - p.delete_user_password = static_cast(delete_user_password ? 1 : 0); - if (is_authorization_command_supported()){ - authorize_packet(p, admin_temporary_password, device); - } else { - strcpyT(p.temporary_admin_password, admin_temporary_password); - } - stick10_08::WriteGeneralConfig::CommandTransaction::run(device, p); - } - - vector NitrokeyManager::read_config() { - auto responsePayload = GetStatus::CommandTransaction::run(device); - vector v = vector(responsePayload.data().general_config, - responsePayload.data().general_config+sizeof(responsePayload.data().general_config)); - return v; - } - bool NitrokeyManager::is_authorization_command_supported(){ //authorization command is supported for versions equal or below: auto m = std::unordered_map({ @@ -922,16 +618,6 @@ using nitrokey::misc::strcpyT; return get_minor_firmware_version() <= m[device->get_device_model()]; } - bool NitrokeyManager::is_320_OTP_secret_supported(){ - // 320 bit OTP secret is supported by version bigger or equal to: - auto m = std::unordered_map({ - {DeviceModel::PRO, 8}, - {DeviceModel::LIBREM, 8}, - {DeviceModel::STORAGE, 54}, - }); - return get_minor_firmware_version() >= m[device->get_device_model()]; - } - DeviceModel NitrokeyManager::get_connected_device_model() const{ if (device == nullptr){ throw DeviceNotConnected("device not connected"); @@ -988,47 +674,6 @@ using nitrokey::misc::strcpyT; return true; } - - 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); - } - - /** - * Returns ReadSlot structure, describing OTP slot configuration. Always return binary counter - - * does the necessary conversion, if needed, to unify the behavior across Pro and Storage. - * @private For internal use only - * @param slot_number which OTP slot to use (usual format) - * @return ReadSlot structure - */ - stick10::ReadSlot::ResponsePayload NitrokeyManager::get_OTP_slot_data(const uint8_t slot_number) { - auto p = get_payload(); - p.slot_number = slot_number; - p.data_format = stick10::ReadSlot::CounterFormat::BINARY; // ignored for devices other than Storage v0.54+ - auto data = stick10::ReadSlot::CommandTransaction::run(device, p); - - auto &payload = data.data(); - - // if fw <=v0.53 and asked binary - do the conversion from ASCII - if (device->get_device_model() == DeviceModel::STORAGE && get_minor_firmware_version() <= 53 - && is_internal_hotp_slot_number(slot_number)) - { - //convert counter from string to ull - auto counter_s = std::string(payload.slot_counter_s, payload.slot_counter_s + sizeof(payload.slot_counter_s)); - payload.slot_counter = std::stoull(counter_s); - } - - return payload; - } - - stick10::ReadSlot::ResponsePayload NitrokeyManager::get_TOTP_slot_data(const uint8_t slot_number) { - return get_OTP_slot_data(get_internal_slot_number_for_totp(slot_number)); - } - - stick10::ReadSlot::ResponsePayload NitrokeyManager::get_HOTP_slot_data(const uint8_t slot_number) { - return get_OTP_slot_data(get_internal_slot_number_for_hotp(slot_number)); - } - - const string NitrokeyManager::get_current_device_id() const { return current_device_id; } -- cgit v1.2.1