From f76ac655fff3df7eb0e645ca39d18510714b0039 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Wed, 9 Nov 2016 14:29:18 +0100 Subject: Authorization fix: GetTOTP and WriteToTOTPSLot + test Signed-off-by: Szczepan Zalega --- include/stick10_commands_0.8.h | 77 ++++++++++++++++++++++++++++++++++++++++++ unittest/test3.cc | 46 +++++++++++++++++++++++-- 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/include/stick10_commands_0.8.h b/include/stick10_commands_0.8.h index 0c6633c..cee0d78 100644 --- a/include/stick10_commands_0.8.h +++ b/include/stick10_commands_0.8.h @@ -23,6 +23,7 @@ namespace nitrokey { namespace stick10_08 { using stick10::FirstAuthenticate; using stick10::UserAuthenticate; + using stick10::SetTime; class EraseSlot : Command { public: @@ -120,6 +121,82 @@ namespace nitrokey { CommandTransaction; }; + + class WriteToTOTPSlot : Command { + //admin auth + public: + struct CommandPayload { + uint8_t temporary_admin_password[25]; + uint8_t slot_secret[20]; + union { + uint8_t _slot_config; + struct { + bool use_8_digits : 1; + bool use_enter : 1; + bool use_tokenID : 1; + }; + }; + union { + uint8_t slot_token_id[13]; /** OATH Token Identifier */ + struct { /** @see https://openauthentication.org/token-specs/ */ + uint8_t omp[2]; + uint8_t tt[2]; + uint8_t mui[8]; + uint8_t keyboard_layout; //disabled feature in nitroapp as of 20160805 + } slot_token_fields; + }; + + bool isValid() const { return true; } + + std::string dissect() const { + std::stringstream ss; + ss << "temporary_admin_password:\t" << temporary_admin_password << std::endl; + ss << "slot_secret:" << std::endl + << ::nitrokey::misc::hexdump((const char *) (&slot_secret), sizeof slot_secret); + ss << "slot_config:\t" << std::bitset<8>((int) _slot_config) << std::endl; + ss << "\tuse_8_digits(0):\t" << use_8_digits << std::endl; + ss << "\tuse_enter(1):\t" << use_enter << std::endl; + ss << "\tuse_tokenID(2):\t" << use_tokenID << std::endl; + + ss << "slot_token_id:\t"; + for (auto i : slot_token_id) + ss << std::hex << std::setw(2) << std::setfill('0') << (int) i << " "; + ss << std::endl; + + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; + }; + + class WriteToTOTPSlot_2 : Command { + public: + struct CommandPayload { + uint8_t temporary_admin_password[25]; + uint8_t slot_number; + uint8_t slot_name[15]; + uint16_t slot_interval; + + bool isValid() const { return !(slot_number & 0xF0); } + + std::string dissect() const { + std::stringstream ss; + ss << "temporary_admin_password:\t" << temporary_admin_password << std::endl; + ss << "slot_number:\t" << (int) (slot_number) << std::endl; + ss << "slot_name:\t" << slot_name << std::endl; + ss << "slot_interval:\t" << (int)slot_interval << std::endl; + + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; + }; + + class GetHOTP : Command { public: struct CommandPayload { diff --git a/unittest/test3.cc b/unittest/test3.cc index 226e35c..8a9423f 100644 --- a/unittest/test3.cc +++ b/unittest/test3.cc @@ -103,7 +103,7 @@ TEST_CASE("write general config", "[pronew]") { WriteGeneralConfig::CommandTransaction::run(stick, p); } -TEST_CASE("authorize user OTP", "[pronew]") { +TEST_CASE("authorize user HOTP", "[pronew]") { Stick10 stick; connect_and_setup(stick); authorize(stick); @@ -132,6 +132,48 @@ TEST_CASE("authorize user OTP", "[pronew]") { GetHOTP::CommandTransaction::run(stick, p3); ); strcpyT(p3.temporary_user_password, temporary_password); - GetHOTP::CommandTransaction::run(stick, p3); + auto code_response = GetHOTP::CommandTransaction::run(stick, p3); + REQUIRE(code_response.data().code == 1284755224); + +} + + +TEST_CASE("authorize user TOTP", "[pronew]") { + Stick10 stick; + connect_and_setup(stick); + authorize(stick); + + auto p = get_payload(); + p.enable_user_password = 1; + strcpyT(p.temporary_admin_password, temporary_password); + WriteGeneralConfig::CommandTransaction::run(stick, p); + + auto pw = get_payload(); + strcpyT(pw.slot_secret, RFC_SECRET); + strcpyT(pw.temporary_admin_password, temporary_password); + pw.use_8_digits = true; + WriteToTOTPSlot::CommandTransaction::run(stick, pw); + + auto pw2 = get_payload(); + strcpyT(pw2.temporary_admin_password, temporary_password); + pw2.slot_number = 0 + 0x20; + pw2.slot_interval= 30; + strcpyT(pw2.slot_name, "test name TOTP"); + WriteToTOTPSlot_2::CommandTransaction::run(stick, pw2); + + auto p_get_totp = get_payload(); + p_get_totp.slot_number = 0 + 0x20; + + REQUIRE_THROWS( + GetTOTP::CommandTransaction::run(stick, p_get_totp); + ); + strcpyT(p_get_totp.temporary_user_password, temporary_password); + + auto p_set_time = get_payload(); + p_set_time.reset = 1; + p_set_time.time = 59; + SetTime::CommandTransaction::run(stick, p_set_time); + auto code = GetTOTP::CommandTransaction::run(stick, p_get_totp); + REQUIRE(code.data().code == 94287082); } \ No newline at end of file -- cgit v1.2.3