From f5b5339a0cd272b3be33013f01e14f5bcc6e5aa8 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Tue, 26 Jul 2016 23:35:24 +0200 Subject: Erasing slot - initial version with some authorization issues Signed-off-by: Szczepan Zalega --- NK_C_API.cc | 25 ++++++++++++++++++++----- NK_C_API.h | 5 ++++- NitrokeyManager.cc | 25 +++++++++++++++++++------ include/NitrokeyManager.h | 10 ++++++---- include/stick10_commands.h | 6 ++++++ unittest/test_bindings.py | 17 +++++++++++------ 6 files changed, 66 insertions(+), 22 deletions(-) diff --git a/NK_C_API.cc b/NK_C_API.cc index 094a7e3..db96c52 100644 --- a/NK_C_API.cc +++ b/NK_C_API.cc @@ -50,7 +50,7 @@ extern int NK_login(const char *admin_pin, const char *temporary_password) { auto m = NitrokeyManager::instance(); try { m->connect(); - m->authorize(admin_pin, temporary_password); + m->first_authenticate(admin_pin, temporary_password); } catch (CommandFailedException & commandFailedException){ NK_last_command_status = commandFailedException.last_command_status; @@ -71,6 +71,21 @@ extern int NK_logout() { return 0; } +extern int NK_first_authenticate(const char* admin_password, const char* admin_temporary_password){ + auto m = NitrokeyManager::instance(); + return get_without_result( [&](){ + return m->first_authenticate(admin_password, admin_temporary_password); + }); +} + + +extern int NK_user_authenticate(const char* user_password, const char* user_temporary_password){ + auto m = NitrokeyManager::instance(); + return get_without_result( [&](){ + return m->user_authenticate(user_password, user_temporary_password); + }); +} + extern const char * NK_status() { auto m = NitrokeyManager::instance(); try { @@ -106,10 +121,10 @@ extern uint32_t NK_get_totp_code(uint8_t slot_number, uint64_t challenge, uint64 return 0; } -extern int NK_erase_hotp_slot(uint8_t slot_number) { +extern int NK_erase_hotp_slot(uint8_t slot_number, const char *temporary_password) { auto m = NitrokeyManager::instance(); try { - m->erase_hotp_slot(slot_number); + m->erase_hotp_slot(slot_number, temporary_password); } catch (CommandFailedException & commandFailedException){ NK_last_command_status = commandFailedException.last_command_status; @@ -118,10 +133,10 @@ extern int NK_erase_hotp_slot(uint8_t slot_number) { return 0; } -extern int NK_erase_totp_slot(uint8_t slot_number) { +extern int NK_erase_totp_slot(uint8_t slot_number, const char *temporary_password) { auto m = NitrokeyManager::instance(); try { - m->erase_totp_slot(slot_number); + m->erase_totp_slot(slot_number, temporary_password); } catch (CommandFailedException & commandFailedException){ NK_last_command_status = commandFailedException.last_command_status; diff --git a/NK_C_API.h b/NK_C_API.h index 804f6a7..26f99f9 100644 --- a/NK_C_API.h +++ b/NK_C_API.h @@ -15,10 +15,13 @@ extern int NK_logout(); extern const char * NK_status(); extern uint8_t NK_get_last_command_status(); extern int NK_lock_device(); +extern int NK_user_authenticate(const char* user_password, const char* user_temporary_password); +extern int NK_first_authenticate(const char* admin_password, const char* admin_temporary_password); //otp extern const char * NK_get_totp_slot_name(uint8_t slot_number); extern const char * NK_get_hotp_slot_name(uint8_t slot_number); -extern int NK_erase_slot(uint8_t slot_number); +extern int NK_erase_hotp_slot(uint8_t slot_number, const char *temporary_password); +extern int NK_erase_totp_slot(uint8_t slot_number, const char *temporary_password); extern int NK_write_hotp_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint8_t hotp_counter, const char *temporary_password); extern int NK_write_totp_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint16_t time_window, bool use_8_digits, const char *temporary_password); extern uint32_t NK_get_hotp_code(uint8_t slot_number); diff --git a/NitrokeyManager.cc b/NitrokeyManager.cc index ef0eb5e..69b2059 100644 --- a/NitrokeyManager.cc +++ b/NitrokeyManager.cc @@ -82,23 +82,29 @@ namespace nitrokey{ return resp.code; } - bool NitrokeyManager::erase_slot(uint8_t slot_number) { + bool NitrokeyManager::erase_slot(uint8_t slot_number, const char *temporary_password) { auto p = get_payload(); p.slot_number = slot_number; + + auto auth = get_payload(); + strcpyT(auth.temporary_password, temporary_password); + auth.crc_to_authorize = EraseSlot::CommandTransaction::getCRC(p); + Authorize::CommandTransaction::run(*device, auth); + auto resp = EraseSlot::CommandTransaction::run(*device,p); return true; } - bool NitrokeyManager::erase_hotp_slot(uint8_t slot_number) { + bool NitrokeyManager::erase_hotp_slot(uint8_t slot_number, const char *temporary_password) { assert(is_valid_hotp_slot_number(slot_number)); slot_number = get_internal_slot_number_for_hotp(slot_number); - return erase_slot(slot_number); + return erase_slot(slot_number, temporary_password); } - bool NitrokeyManager::erase_totp_slot(uint8_t slot_number) { + bool NitrokeyManager::erase_totp_slot(uint8_t slot_number, const char *temporary_password) { assert(is_valid_totp_slot_number(slot_number)); slot_number = get_internal_slot_number_for_totp(slot_number); - return erase_slot(slot_number); + return erase_slot(slot_number, temporary_password); } @@ -173,7 +179,7 @@ namespace nitrokey{ return (uint8_t *) strdup((const char *) resp.slot_name); } - bool NitrokeyManager::authorize(const char *pin, const char *temporary_password) { + bool NitrokeyManager::first_authenticate(const char *pin, const char *temporary_password) { auto authreq = get_payload(); assert(strlen(pin) < sizeof authreq.card_password); @@ -294,4 +300,11 @@ namespace nitrokey{ ErasePasswordSafeSlot::CommandTransaction::run(*device, p); } + void NitrokeyManager::user_authenticate(const char *user_password, const char *temporary_password) { + auto p = get_payload(); + strcpyT(p.card_password, user_password); + strcpyT(p.temporary_password, temporary_password); + UserAuthenticate::CommandTransaction::run(*device, p); + } + } \ No newline at end of file diff --git a/include/NitrokeyManager.h b/include/NitrokeyManager.h index 00011e2..e6e79c7 100644 --- a/include/NitrokeyManager.h +++ b/include/NitrokeyManager.h @@ -17,7 +17,7 @@ namespace nitrokey { public: static NitrokeyManager *instance(); - bool authorize(const char *pin, const char *temporary_password); + bool first_authenticate(const char *pin, const char *temporary_password); bool write_HOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint64_t hotp_counter, const char *temporary_password); bool write_TOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret, @@ -27,8 +27,8 @@ namespace nitrokey { uint8_t last_interval); bool set_time(uint64_t time); bool get_time(); - bool erase_totp_slot(uint8_t slot_number); - bool erase_hotp_slot(uint8_t slot_number); + bool erase_totp_slot(uint8_t slot_number, const char *temporary_password); + bool erase_hotp_slot(uint8_t slot_number, const char *temporary_password); bool connect(); bool disconnect(); void set_debug(bool state); @@ -59,6 +59,8 @@ namespace nitrokey { void erase_password_safe_slot(uint8_t slot_number); + void user_authenticate(const char *user_password, const char *temporary_password); + private: NitrokeyManager(); ~NitrokeyManager(); @@ -72,7 +74,7 @@ namespace nitrokey { bool is_valid_password_safe_slot_number(uint8_t slot_number) const; uint8_t get_internal_slot_number_for_hotp(uint8_t slot_number) const; uint8_t get_internal_slot_number_for_totp(uint8_t slot_number) const; - bool erase_slot(uint8_t slot_number); + bool erase_slot(uint8_t slot_number, const char *temporary_password); uint8_t *get_slot_name(uint8_t slot_number) const; }; diff --git a/include/stick10_commands.h b/include/stick10_commands.h index d88c36b..fbd0698 100644 --- a/include/stick10_commands.h +++ b/include/stick10_commands.h @@ -587,6 +587,12 @@ class UserAuthenticate : Command { uint8_t temporary_password[25]; bool isValid() const { return true; } + std::string dissect() const { + std::stringstream ss; + ss << "card_password:\t" << card_password << std::endl; + ss << "temporary_password:\t" << temporary_password << std::endl; + return ss.str(); + } } __packed; typedef Transaction diff --git a/unittest/test_bindings.py b/unittest/test_bindings.py index 899c802..4bd7bb0 100644 --- a/unittest/test_bindings.py +++ b/unittest/test_bindings.py @@ -12,7 +12,7 @@ class DefaultPasswords(Enum): ADMIN = '12345678' USER = '123456' ADMIN_TEMP = '123123123' - + USER_TEMP = '234234234' class DeviceErrorCode(Enum): STATUS_OK = 0 @@ -38,6 +38,7 @@ def C(request): C = ffi.dlopen("../build/libnitrokey.so") C.NK_login(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) + assert C.NK_user_authenticate(DefaultPasswords.USER, DefaultPasswords.USER_TEMP) == DeviceErrorCode.STATUS_OK # C.NK_set_debug(True) @@ -45,7 +46,6 @@ def C(request): print ('\nFinishing connection to device') C.NK_logout() print ('Finished') - request.addfinalizer(fin) return C @@ -58,12 +58,10 @@ def test_enable_password_safe(C): def test_write_password_safe_slot(C): - C.NK_set_debug(True) assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK assert C.NK_write_password_safe_slot(0, 'slotname1', 'login1', 'pass1') == DeviceErrorCode.STATUS_NOT_AUTHORIZED assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK assert C.NK_write_password_safe_slot(0, 'slotname1', 'login1', 'pass1') == DeviceErrorCode.STATUS_OK - C.NK_set_debug(False) def test_get_password_safe_slot_name(C): @@ -163,7 +161,12 @@ def test_TOTP_RFC(C): def test_get_slot_names(C): - # TODO add setup to have at least one slot not programmed + C.NK_set_debug(True) + # assert C.NK_erase_totp_slot(0, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + # erasing slot invalidates temporary password, so requesting authentication + # assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + # assert C.NK_erase_hotp_slot(0, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + for i in range(16): name = ffi.string(C.NK_get_totp_slot_name(i)) if name == '': @@ -175,7 +178,9 @@ def test_get_slot_names(C): def test_get_OTP_codes(C): - # TODO add setup to have at least one slot not programmed + C.NK_set_debug(True) + # assert C.NK_erase_hotp_slot(0, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + # assert C.NK_erase_totp_slot(0, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK for i in range(16): code = C.NK_get_totp_code(i, 0, 0, 0) if code == 0: -- cgit v1.2.1