From a5d11eab6003a6ed0f7c78ecb7136b28ee938a23 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Mon, 18 Jul 2016 18:04:34 +0200 Subject: Initial version of C/Python bindings Signed-off-by: Szczepan Zalega --- include/NitrokeyManager.h | 56 ++++++++++++++++++++++++++++ include/dissect.h | 4 +- include/stick10_commands.h | 91 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 142 insertions(+), 9 deletions(-) create mode 100644 include/NitrokeyManager.h (limited to 'include') diff --git a/include/NitrokeyManager.h b/include/NitrokeyManager.h new file mode 100644 index 0000000..37b628d --- /dev/null +++ b/include/NitrokeyManager.h @@ -0,0 +1,56 @@ +#ifndef LIBNITROKEY_NITROKEYMANAGER_H +#define LIBNITROKEY_NITROKEYMANAGER_H + +#include "device.h" +#include "log.h" +#include "device_proto.h" +#include "stick10_commands.h" + +namespace nitrokey { + using namespace nitrokey::device; + using namespace std; + using namespace nitrokey::proto::stick10; + using namespace nitrokey::proto; + using namespace nitrokey::log; + + class NitrokeyManager { + public: + static NitrokeyManager *instance(); + + bool authorize(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 *secret, uint16_t time_window); + uint32_t get_HOTP_code(uint8_t slot_number); + uint32_t get_TOTP_code(uint8_t slot_number, uint64_t challenge, uint64_t last_totp_time, + uint8_t last_interval); + bool erase_totp_slot(uint8_t slot_number); + bool erase_hotp_slot(uint8_t slot_number); + bool connect(); + bool disconnect(); + void set_debug(bool state); + string get_status(); + + const char * get_totp_slot_name(uint8_t slot_number); + const char * get_hotp_slot_name(uint8_t slot_number); + + private: + NitrokeyManager(); + ~NitrokeyManager(); + + static NitrokeyManager *_instance; + bool connected; + Device *device; + + bool is_valid_hotp_slot_number(uint8_t slot_number) const; + bool is_valid_totp_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); + uint8_t *get_slot_name(uint8_t slot_number) const; + }; +} + + + +#endif //LIBNITROKEY_NITROKEYMANAGER_H diff --git a/include/dissect.h b/include/dissect.h index 993d348..ab94e62 100644 --- a/include/dissect.h +++ b/include/dissect.h @@ -5,6 +5,7 @@ #define DISSECT_H #include #include +#include #include "misc.h" #include "cxx_semantics.h" #include "command_id.h" @@ -66,7 +67,8 @@ class ResponseDissector : semantics::non_constructible { << status[pod.device_status] << std::endl; out << "Command ID:\t" << commandid_to_string((CommandID)(pod.command_id)) << std::endl; - out << "Last command CRC:\t" << pod.last_command_crc << std::endl; + out << "Last command CRC:\t" << std::hex << std::setw(2) << std::setfill('0') + << pod.last_command_crc << std::endl; out << "Last command status:\t" << pod.last_command_status + 0 << " " << cmd[pod.last_command_status] << std::endl; out << "CRC:\t" << pod.crc << std::endl; diff --git a/include/stick10_commands.h b/include/stick10_commands.h index f1903aa..b7f6de0 100644 --- a/include/stick10_commands.h +++ b/include/stick10_commands.h @@ -1,9 +1,12 @@ #ifndef STICK10_COMMANDS_H #define STICK10_COMMANDS_H +#include +#include #include #include #include "inttypes.h" #include "command.h" +#include "device_proto.h" namespace nitrokey { namespace proto { @@ -18,13 +21,23 @@ class GetSlotName : public Command { struct CommandPayload { uint8_t slot_number; - bool isValid() const { return !(slot_number & 0xF0); } + bool isValid() const { return slot_number<0x10+3; } + std::string dissect() const { + std::stringstream ss; + ss << "slot_number:\t" << (int)(slot_number) << std::endl; + return ss.str(); + } } __packed; struct ResponsePayload { uint8_t slot_name[15]; bool isValid() const { return true; } + std::string dissect() const { + std::stringstream ss; + ss << "slot_name:\t" << slot_name << std::endl; + return ss.str(); + } } __packed; typedef Transaction { uint8_t slot_number; 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 @@ -56,6 +74,7 @@ class SetTime : Command { CommandTransaction; }; + // TODO duplicate TOTP class WriteToHOTPSlot : Command { public: @@ -65,7 +84,7 @@ class WriteToHOTPSlot : Command { uint8_t slot_secret[20]; uint8_t slot_config; uint8_t slot_token_id[13]; - uint8_t slot_counter[8]; + uint64_t slot_counter; bool isValid() const { return !(slot_number & 0xF0); } std::string dissect() const { @@ -73,9 +92,12 @@ class WriteToHOTPSlot : Command { ss << "slot_number:\t" << (int)(slot_number) << std::endl; ss << "slot_name:\t" << slot_name << std::endl; ss << "slot_secret:\t" << slot_secret << std::endl; - ss << "slot_config:\t" << slot_config << std::endl; - ss << "slot_token_id:\t" << slot_token_id << std::endl; - ss << "slot_counter:\t" << slot_counter << std::endl; + ss << "slot_config:\t" << std::bitset<8>((int)slot_config) << 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; + ss << "slot_counter:\t" << (int)slot_counter << std::endl; return ss.str(); } } __packed; @@ -122,6 +144,47 @@ class GetCode : Command { struct ResponsePayload> CommandTransaction; }; +class GetTOTP : Command { + public: + struct CommandPayload { + uint8_t slot_number; + uint64_t challenge; + uint64_t last_totp_time; + uint8_t last_interval; + + 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]; //TODO remove if not needed + struct { + uint32_t code; + uint8_t config; + } __packed; + } __packed; + + bool isValid() const { return true; } + std::string dissect() const { + std::stringstream ss; + ss << "code:\t" << (code) << std::endl; + ss << "config:\t" << "TODO" /*(config) */<< std::endl; //TODO show byte field options + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + class GetHOTP : Command { public: struct CommandPayload { @@ -444,6 +507,15 @@ class WriteGeneralConfig : Command { CommandTransaction; }; +// struct clear_on_const { +// clear_on_const(){ +// initialize(); +// } +// void initialize(){ +// bzero(this, sizeof(*this)); +// } +// }; + class FirstAuthenticate : Command { public: struct CommandPayload { @@ -451,6 +523,7 @@ class FirstAuthenticate : Command { uint8_t temporary_password[25]; bool isValid() const { return true; } + void initialize(){ bzero(this, sizeof(*this)); } std::string dissect() const { std::stringstream ss; @@ -480,12 +553,14 @@ class UserAuthenticate : Command { class Authorize : Command { public: struct CommandPayload { - uint32_t crc_to_authorize; + uint32_t crc_to_authorize; uint8_t temporary_password[25]; - std::string dissect() const { + void initialize(){ bzero(this, sizeof(*this)); } + + std::string dissect() const { std::stringstream ss; - ss << " crc_to_authorize:\t" << crc_to_authorize<< std::endl; + ss << " crc_to_authorize:\t" << std::hex << std::setw(2) << std::setfill('0') << crc_to_authorize<< std::endl; ss << " temporary_password:\t" << temporary_password<< std::endl; return ss.str(); } -- cgit v1.2.3