aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzczepan Zalega <szczepan@nitrokey.com>2016-11-09 14:29:18 +0100
committerSzczepan Zalega <szczepan@nitrokey.com>2016-12-03 16:01:35 +0100
commitf76ac655fff3df7eb0e645ca39d18510714b0039 (patch)
tree62e185b9f4d68507922431976270a3bba8cf8326
parent119ea0b111c9ca46fda32911c1c8c33b36aad3db (diff)
downloadlibnitrokey-f76ac655fff3df7eb0e645ca39d18510714b0039.tar.gz
libnitrokey-f76ac655fff3df7eb0e645ca39d18510714b0039.tar.bz2
Authorization fix: GetTOTP and WriteToTOTPSLot + test
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
-rw-r--r--include/stick10_commands_0.8.h77
-rw-r--r--unittest/test3.cc46
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<CommandID::ERASE_SLOT> {
public:
@@ -120,6 +121,82 @@ namespace nitrokey {
CommandTransaction;
};
+
+ class WriteToTOTPSlot : Command<CommandID::WRITE_TO_SLOT> {
+ //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<command_id(), struct CommandPayload, struct EmptyPayload>
+ CommandTransaction;
+ };
+
+ class WriteToTOTPSlot_2 : Command<CommandID::WRITE_TO_SLOT_2> {
+ 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<command_id(), struct CommandPayload, struct EmptyPayload>
+ CommandTransaction;
+ };
+
+
class GetHOTP : Command<CommandID::GET_CODE> {
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<WriteGeneralConfig>();
+ p.enable_user_password = 1;
+ strcpyT(p.temporary_admin_password, temporary_password);
+ WriteGeneralConfig::CommandTransaction::run(stick, p);
+
+ auto pw = get_payload<WriteToTOTPSlot>();
+ 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<WriteToTOTPSlot_2>();
+ 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<GetTOTP>();
+ 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<SetTime>();
+ 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