aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzczepan Zalega <szczepan@nitrokey.com>2016-11-08 17:03:48 +0100
committerSzczepan Zalega <szczepan@nitrokey.com>2016-11-26 20:21:21 +0100
commit130d7f12e42505a33f41073983d868ca0c3c78d1 (patch)
tree1e7067147c6aef95799a9b627dfbe23d18baf968
parentf60f2cf0144a91769a5fc00fac1314d2e00cdf0d (diff)
downloadlibnitrokey-130d7f12e42505a33f41073983d868ca0c3c78d1.tar.gz
libnitrokey-130d7f12e42505a33f41073983d868ca0c3c78d1.tar.bz2
Fix for auth issue in NK Pro
for commands EraseSlot, WriteToSlot, GetCode + tests Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
-rw-r--r--CMakeLists.txt2
-rw-r--r--include/command_id.h1
-rw-r--r--include/stick10_commands.h4
-rw-r--r--include/stick10_commands_0.8.h178
-rw-r--r--unittest/test3.cc78
5 files changed, 263 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e9cd54f..c324067 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -32,7 +32,9 @@ set(SOURCE_FILES
unittest/test_C_API.cpp
unittest/catch_main.cpp
unittest/test2.cc
+ unittest/test3.cc
include/LongOperationInProgressException.h
+ include/stick10_commands_0.8.h
)
add_executable(libnitrokey ${SOURCE_FILES}) \ No newline at end of file
diff --git a/include/command_id.h b/include/command_id.h
index a3806f0..1f7affc 100644
--- a/include/command_id.h
+++ b/include/command_id.h
@@ -65,6 +65,7 @@ enum class CommandID : uint8_t {
FACTORY_RESET = 0x13,
CHANGE_USER_PIN = 0x14,
CHANGE_ADMIN_PIN = 0x15,
+ WRITE_TO_SLOT_2 = 0x16,
ENABLE_CRYPTED_PARI = 0x20,
DISABLE_CRYPTED_PARI = 0x20 + 1, //@unused
diff --git a/include/stick10_commands.h b/include/stick10_commands.h
index f02fd70..5ae2591 100644
--- a/include/stick10_commands.h
+++ b/include/stick10_commands.h
@@ -48,6 +48,7 @@ class EraseSlot : Command<CommandID::ERASE_SLOT> {
public:
struct CommandPayload {
uint8_t slot_number;
+ uint8_t temporary_admin_password[25];
bool isValid() const { return !(slot_number & 0xF0); }
std::string dissect() const {
@@ -137,6 +138,7 @@ class WriteToHOTPSlot : Command<CommandID::WRITE_TO_SLOT> {
};
class WriteToTOTPSlot : Command<CommandID::WRITE_TO_SLOT> {
+ //admin auth
public:
struct CommandPayload {
uint8_t slot_number;
@@ -182,6 +184,7 @@ class WriteToTOTPSlot : Command<CommandID::WRITE_TO_SLOT> {
};
class GetTOTP : Command<CommandID::GET_CODE> {
+ //user auth
public:
struct CommandPayload {
uint8_t slot_number;
@@ -612,6 +615,7 @@ class PasswordSafeSendSlotViaHID : Command<CommandID::PW_SAFE_SEND_DATA> {
// TODO "Device::passwordSafeSendSlotDataViaHID"
class WriteGeneralConfig : Command<CommandID::WRITE_CONFIG> {
+ //admin auth
public:
struct CommandPayload {
union{
diff --git a/include/stick10_commands_0.8.h b/include/stick10_commands_0.8.h
new file mode 100644
index 0000000..037a777
--- /dev/null
+++ b/include/stick10_commands_0.8.h
@@ -0,0 +1,178 @@
+//
+// Created by sz on 08.11.16.
+//
+
+#ifndef LIBNITROKEY_STICK10_COMMANDS_0_8_H
+#define LIBNITROKEY_STICK10_COMMANDS_0_8_H
+
+#include <bitset>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include "inttypes.h"
+#include "command.h"
+#include "device_proto.h"
+
+namespace nitrokey {
+ namespace proto {
+
+/*
+ * Stick10 protocol definition
+ */
+ namespace stick10_08 {
+
+ class EraseSlot : Command<CommandID::ERASE_SLOT> {
+ public:
+ struct CommandPayload {
+ uint8_t slot_number;
+ uint8_t temporary_admin_password[25];
+
+ bool isValid() const { return !(slot_number & 0xF0); }
+ std::string dissect() const {
+ std::stringstream ss;
+ ss << "slot_number:\t" << (int)(slot_number) << std::endl;
+ return ss.str();
+ }
+ } __packed;
+
+ typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload>
+ CommandTransaction;
+ };
+
+ class WriteToHOTPSlot : 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 WriteToHOTPSlot_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];
+ union {
+ uint64_t slot_counter;
+ uint8_t slot_counter_s[8];
+ } __packed;
+
+ 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_counter:\t[" << (int) slot_counter << "]\t"
+ << ::nitrokey::misc::hexdump((const char *) (&slot_counter), sizeof slot_counter, false);
+
+ return ss.str();
+ }
+ } __packed;
+
+ typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload>
+ CommandTransaction;
+ };
+
+
+ class GetTOTP : Command<CommandID::GET_CODE> {
+ //user auth
+ public:
+ struct CommandPayload {
+ uint8_t slot_number;
+ uint64_t challenge;
+ uint64_t last_totp_time;
+ uint8_t last_interval;
+ uint8_t user_temporary_password[25];
+
+ bool isValid() const { return !(slot_number & 0xF0); }
+ std::string dissect() const {
+ std::stringstream ss;
+ ss << "slot_number:\t" << (int)(slot_number) << std::endl;
+ ss << "challenge:\t" << (challenge) << std::endl;
+ ss << "last_totp_time:\t" << (last_totp_time) << std::endl;
+ ss << "last_interval:\t" << (int)(last_interval) << std::endl;
+ return ss.str();
+ }
+ } __packed;
+
+ struct ResponsePayload {
+ union {
+ uint8_t whole_response[18]; //14 bytes reserved for config, but used only 1
+ struct {
+ uint32_t code;
+ union{
+ uint8_t _slot_config;
+ struct{
+ bool use_8_digits : 1;
+ bool use_enter : 1;
+ bool use_tokenID : 1;
+ };
+ };
+ } __packed ;
+ } __packed ;
+
+ bool isValid() const { return true; }
+ std::string dissect() const {
+ std::stringstream ss;
+ ss << "code:\t" << (code) << std::endl;
+ 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;
+ return ss.str();
+ }
+ } __packed;
+
+ typedef Transaction<command_id(), struct CommandPayload, struct ResponsePayload>
+ CommandTransaction;
+ };
+
+
+ }
+ }
+}
+#endif //LIBNITROKEY_STICK10_COMMANDS_0_8_H
diff --git a/unittest/test3.cc b/unittest/test3.cc
new file mode 100644
index 0000000..6fab862
--- /dev/null
+++ b/unittest/test3.cc
@@ -0,0 +1,78 @@
+//
+// Created by sz on 08.11.16.
+//
+
+#define CATCH_CONFIG_MAIN // This tells Catch to provide a main()
+
+static const char *const default_admin_pin = "12345678";
+static const char *const default_user_pin = "123456";
+const char * temporary_password = "123456789012345678901234";
+const char * RFC_SECRET = "12345678901234567890";
+
+#include "catch.hpp"
+
+#include <iostream>
+#include <string.h>
+#include <NitrokeyManager.h>
+#include "device_proto.h"
+#include "log.h"
+#include "stick10_commands.h"
+#include "stick10_commands_0.8.h"
+//#include "stick20_commands.h"
+
+using namespace std;
+using namespace nitrokey::device;
+using namespace nitrokey::proto;
+//using namespace nitrokey::proto::stick10_08;
+using namespace nitrokey::proto::stick10;
+using namespace nitrokey::log;
+using namespace nitrokey::misc;
+
+void connect_and_setup(Stick10 &stick) {
+ bool connected = stick.connect();
+ REQUIRE(connected == true);
+ Log::instance().set_loglevel(Loglevel::DEBUG);
+}
+
+void authorize(Stick10 &stick) {
+ auto authreq = get_payload<FirstAuthenticate>();
+ strcpy((char *) (authreq.card_password), default_admin_pin);
+ strcpy((char *) (authreq.temporary_password), temporary_password);
+ FirstAuthenticate::CommandTransaction::run(stick, authreq);
+}
+
+TEST_CASE("write slot", "[pronew]"){
+ Stick10 stick;
+ connect_and_setup(stick);
+
+ auto p = get_payload<stick10_08::WriteToHOTPSlot>();
+// p.slot_number = 0 + 0x10;
+ strcpyT(p.slot_secret, RFC_SECRET);
+ strcpyT(p.temporary_admin_password, temporary_password);
+ p.use_8_digits = true;
+ stick10_08::WriteToHOTPSlot::CommandTransaction::run(stick, p);
+
+ auto p2 = get_payload<stick10_08::WriteToHOTPSlot_2>();
+ strcpyT(p2.temporary_admin_password, temporary_password);
+ p2.slot_number = 0 + 0x10;
+ p2.slot_counter = 0;
+ strcpyT(p2.slot_name, "test name aaa");
+ stick10_08::WriteToHOTPSlot_2::CommandTransaction::run(stick, p2);
+
+ auto p3 = get_payload<GetHOTP>();
+ p3.slot_number = 0 + 0x10;
+ GetHOTP::CommandTransaction::run(stick, p3);
+
+}
+
+
+TEST_CASE("erase slot", "[pronew]"){
+ Stick10 stick;
+ connect_and_setup(stick);
+ authorize(stick);
+
+ auto erase_payload = get_payload<stick10_08::EraseSlot>();
+ erase_payload.slot_number = 1 + 0x10;
+ strcpyT(erase_payload.temporary_admin_password, temporary_password);
+ stick10_08::EraseSlot::CommandTransaction::run(stick, erase_payload);
+} \ No newline at end of file