diff options
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | include/command_id.h | 1 | ||||
| -rw-r--r-- | include/stick10_commands.h | 4 | ||||
| -rw-r--r-- | include/stick10_commands_0.8.h | 178 | ||||
| -rw-r--r-- | unittest/test3.cc | 78 | 
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 | 
