diff options
| -rw-r--r-- | command_id.cc | 3 | ||||
| -rw-r--r-- | include/stick10_commands_0.8.h | 83 | ||||
| -rw-r--r-- | unittest/test3.cc | 69 | 
3 files changed, 149 insertions, 6 deletions
| diff --git a/command_id.cc b/command_id.cc index 9512b7d..a93d05c 100644 --- a/command_id.cc +++ b/command_id.cc @@ -139,6 +139,9 @@ const char *commandid_to_string(CommandID id) {        return "DETECT_SC_AES";      case CommandID::NEW_AES_KEY:        return "NEW_AES_KEY"; +    case CommandID::WRITE_TO_SLOT_2: +      return "WRITE_TO_SLOT_2"; +      break;    }    return "UNKNOWN";  } diff --git a/include/stick10_commands_0.8.h b/include/stick10_commands_0.8.h index 037a777..0c6633c 100644 --- a/include/stick10_commands_0.8.h +++ b/include/stick10_commands_0.8.h @@ -12,6 +12,7 @@  #include "inttypes.h"  #include "command.h"  #include "device_proto.h" +#include "stick10_commands.h"  namespace nitrokey {      namespace proto { @@ -20,6 +21,8 @@ namespace nitrokey {   *	Stick10 protocol definition   */          namespace stick10_08 { +            using stick10::FirstAuthenticate; +            using stick10::UserAuthenticate;              class EraseSlot : Command<CommandID::ERASE_SLOT> {              public: @@ -117,20 +120,68 @@ namespace nitrokey {                      CommandTransaction;              }; +            class GetHOTP : Command<CommandID::GET_CODE> { +            public: +                struct CommandPayload { +                    uint8_t temporary_user_password[25]; +                    uint8_t slot_number; + +                    bool isValid() const { return (slot_number & 0xF0); } +                    std::string dissect() const { +                      std::stringstream ss; +                      ss << "temporary_user_password:\t" << temporary_user_password << std::endl; +                      ss << "slot_number:\t" << (int)(slot_number) << 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; +            }; +              class GetTOTP : Command<CommandID::GET_CODE> {                  //user auth              public:                  struct CommandPayload { +                    uint8_t temporary_user_password[25];                      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 << "temporary_user_password:\t" << temporary_user_password << std::endl;                        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; @@ -172,6 +223,36 @@ namespace nitrokey {              }; +            class WriteGeneralConfig : Command<CommandID::WRITE_CONFIG> { +                //admin auth +            public: +                struct CommandPayload { +                    union{ +                        uint8_t config[5]; +                        struct{ +                            uint8_t numlock;     /** 0-1: HOTP slot number from which the code will be get on double press, other value - function disabled */ +                            uint8_t capslock;    /** same as numlock */ +                            uint8_t scrolllock;  /** same as numlock */ +                            uint8_t enable_user_password; +                            uint8_t delete_user_password; +                        }; +                    }; +                    uint8_t temporary_admin_password[25]; + +                    std::string dissect() const { +                      std::stringstream ss; +                      ss << "numlock:\t" << (int)numlock << std::endl; +                      ss << "capslock:\t" << (int)capslock << std::endl; +                      ss << "scrolllock:\t" << (int)scrolllock << std::endl; +                      ss << "enable_user_password:\t" << (bool) enable_user_password << std::endl; +                      ss << "delete_user_password:\t" << (bool) delete_user_password << std::endl; +                      return ss.str(); +                    } +                } __packed; + +                typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +                    CommandTransaction; +            };          }      }  } diff --git a/unittest/test3.cc b/unittest/test3.cc index 6fab862..226e35c 100644 --- a/unittest/test3.cc +++ b/unittest/test3.cc @@ -16,15 +16,13 @@ const char * RFC_SECRET = "12345678901234567890";  #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::proto::stick10_08;  using namespace nitrokey::log;  using namespace nitrokey::misc; @@ -39,6 +37,11 @@ void authorize(Stick10 &stick) {    strcpy((char *) (authreq.card_password), default_admin_pin);    strcpy((char *) (authreq.temporary_password), temporary_password);    FirstAuthenticate::CommandTransaction::run(stick, authreq); + +  auto user_auth = get_payload<UserAuthenticate>(); +  strcpyT(user_auth.temporary_password, temporary_password); +  strcpyT(user_auth.card_password, default_user_pin); +  UserAuthenticate::CommandTransaction::run(stick, user_auth);  }  TEST_CASE("write slot", "[pronew]"){ @@ -46,7 +49,6 @@ TEST_CASE("write slot", "[pronew]"){    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; @@ -71,8 +73,65 @@ TEST_CASE("erase slot", "[pronew]"){    connect_and_setup(stick);    authorize(stick); +  auto p3 = get_payload<GetHOTP>(); +  p3.slot_number = 0 + 0x10; +  GetHOTP::CommandTransaction::run(stick, p3); +    auto erase_payload = get_payload<stick10_08::EraseSlot>(); -  erase_payload.slot_number = 1 + 0x10; +  erase_payload.slot_number = 0 + 0x10;    strcpyT(erase_payload.temporary_admin_password, temporary_password);    stick10_08::EraseSlot::CommandTransaction::run(stick, erase_payload); + +  auto p4 = get_payload<GetHOTP>(); +  p4.slot_number = 0 + 0x10; +  REQUIRE_THROWS( +      GetHOTP::CommandTransaction::run(stick, p4) +  ); +} + +TEST_CASE("write general config", "[pronew]") { +  Stick10 stick; +  connect_and_setup(stick); +  authorize(stick); + +  auto p = get_payload<WriteGeneralConfig>(); +  p.enable_user_password = 1; +  REQUIRE_THROWS( +      WriteGeneralConfig::CommandTransaction::run(stick, p); +  ); +  strcpyT(p.temporary_admin_password, temporary_password); +  WriteGeneralConfig::CommandTransaction::run(stick, p); +} + +TEST_CASE("authorize user OTP", "[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<WriteToHOTPSlot>(); +  strcpyT(pw.slot_secret, RFC_SECRET); +  strcpyT(pw.temporary_admin_password, temporary_password); +  pw.use_8_digits = true; +  WriteToHOTPSlot::CommandTransaction::run(stick, pw); + +  auto pw2 = get_payload<WriteToHOTPSlot_2>(); +  strcpyT(pw2.temporary_admin_password, temporary_password); +  pw2.slot_number = 0 + 0x10; +  pw2.slot_counter = 0; +  strcpyT(pw2.slot_name, "test name aaa"); +  WriteToHOTPSlot_2::CommandTransaction::run(stick, pw2); + +  auto p3 = get_payload<GetHOTP>(); +  p3.slot_number = 0 + 0x10; +  REQUIRE_THROWS( +      GetHOTP::CommandTransaction::run(stick, p3); +  ); +  strcpyT(p3.temporary_user_password, temporary_password); +  GetHOTP::CommandTransaction::run(stick, p3); +  }
\ No newline at end of file | 
