diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/LongOperationInProgressException.h | 28 | ||||
| -rw-r--r-- | include/NitrokeyManager.h | 28 | ||||
| -rw-r--r-- | include/command.h | 84 | ||||
| -rw-r--r-- | include/command_id.h | 59 | ||||
| -rw-r--r-- | include/device.h | 1 | ||||
| -rw-r--r-- | include/device_proto.h | 44 | ||||
| -rw-r--r-- | include/misc.h | 30 | ||||
| -rw-r--r-- | include/stick20_commands.h | 600 | 
8 files changed, 503 insertions, 371 deletions
diff --git a/include/LongOperationInProgressException.h b/include/LongOperationInProgressException.h new file mode 100644 index 0000000..7f182b0 --- /dev/null +++ b/include/LongOperationInProgressException.h @@ -0,0 +1,28 @@ +// +// Created by sz on 24.10.16. +// + +#ifndef LIBNITROKEY_LONGOPERATIONINPROGRESSEXCEPTION_H +#define LIBNITROKEY_LONGOPERATIONINPROGRESSEXCEPTION_H + +#include "CommandFailedException.h" + +class LongOperationInProgressException : public CommandFailedException { + +public: +    unsigned char progress_bar_value; + +    LongOperationInProgressException( +        unsigned char _command_id, uint8_t last_command_status, unsigned char _progress_bar_value) +    : CommandFailedException(_command_id, last_command_status), progress_bar_value(_progress_bar_value){ +      nitrokey::log::Log::instance()( +          std::string("LongOperationInProgressException, progress bar status: ")+ +              std::to_string(progress_bar_value), nitrokey::log::Loglevel::DEBUG); +    } +    virtual const char *what() const throw() { +      return "Device returned busy status with long operation in progress"; +    } +}; + + +#endif //LIBNITROKEY_LONGOPERATIONINPROGRESSEXCEPTION_H diff --git a/include/NitrokeyManager.h b/include/NitrokeyManager.h index 52c18d7..60fa753 100644 --- a/include/NitrokeyManager.h +++ b/include/NitrokeyManager.h @@ -82,6 +82,33 @@ namespace nitrokey {          bool is_AES_supported(const char *user_password); +        void unlock_encrypted_volume(const char *user_password); + +        void unlock_hidden_volume(const char *hidden_volume_password); + +        void set_unencrypted_read_only(const char *user_pin); + +        void set_unencrypted_read_write(const char *user_pin); + +        void export_firmware(const char *admin_pin); + +        void clear_new_sd_card_warning(const char *admin_pin); + +        void fill_SD_card_with_random_data(const char *admin_pin); + +        void change_update_password(const char *current_update_password, const char *new_update_password); + +        void create_hidden_volume(uint8_t slot_nr, uint8_t start_percent, uint8_t end_percent, +                                  const char *hidden_volume_password); + +        void send_startup(uint64_t seconds_from_epoch); + +        const char * get_status_storage_as_string(); + +        const char *get_SD_usage_data_as_string(); + +        int get_progress_bar_value(); +          ~NitrokeyManager();      private:          NitrokeyManager(); @@ -101,7 +128,6 @@ namespace nitrokey {          template <typename ProCommand, PasswordKind StoKind>          void change_PIN_general(char *current_PIN, char *new_PIN); -      };  } diff --git a/include/command.h b/include/command.h index 715902d..0a875e4 100644 --- a/include/command.h +++ b/include/command.h @@ -5,19 +5,77 @@  #include "cxx_semantics.h"  namespace nitrokey { -namespace proto { - -template <CommandID cmd_id> -class Command : semantics::non_constructible { - public: -  constexpr static CommandID command_id() { return cmd_id; } - -  template <typename T> -  static std::string dissect(const T &) { -    return std::string("Payload dissection is unavailable"); -  } -}; -} +    namespace proto { + +        template<CommandID cmd_id> +        class Command : semantics::non_constructible { +        public: +            constexpr static CommandID command_id() { return cmd_id; } + +            template<typename T> +            std::string dissect(const T &) { +              return std::string("Payload dissection is unavailable"); +            } +        }; + +#define print_to_ss(x) ( ss << " " << (#x) <<":\t" << (x) << std::endl ); +namespace stick20{ +        enum class PasswordKind : uint8_t { +            User = 'P', +            Admin = 'A', +            AdminPrefixed +        }; + +        template<CommandID cmd_id, PasswordKind Tpassword_kind = PasswordKind::User, int password_length = 20> +        class PasswordCommand : public Command<cmd_id> { +        public: +            struct CommandPayload { +                uint8_t kind; +                uint8_t password[password_length]; + +                std::string dissect() const { +                  std::stringstream ss; +                  print_to_ss( kind ); +                  print_to_ss(password); +                  return ss.str(); +                } +                void set_kind_admin() { +                  kind = (uint8_t) 'A'; +                } +                void set_kind_admin_prefixed() { +                  kind = (uint8_t) 'P'; +                } +                void set_kind_user() { +                  kind = (uint8_t) 'P'; +                } + +                void set_defaults(){ +                  set_kind(Tpassword_kind); +                } + +                void set_kind(PasswordKind password_kind){ +                  switch (password_kind){ +                    case PasswordKind::Admin: +                      set_kind_admin(); +                    break; +                    case PasswordKind::User: +                      set_kind_user(); +                    break; +                    case PasswordKind::AdminPrefixed: +                      set_kind_admin_prefixed(); +                      break; +                  } +                }; + +            } __packed; + +            typedef Transaction<Command<cmd_id>::command_id(), struct CommandPayload, struct EmptyPayload> +                CommandTransaction; + +        }; +    } +    }  } +#undef print_to_ss  #endif diff --git a/include/command_id.h b/include/command_id.h index 8148cc1..a3806f0 100644 --- a/include/command_id.h +++ b/include/command_id.h @@ -66,43 +66,40 @@ enum class CommandID : uint8_t {    CHANGE_USER_PIN = 0x14,    CHANGE_ADMIN_PIN = 0x15, -  STICK20_CMD_SEND_PASSWORD = stick20::CMD_START_VALUE + 18, -  STICK20_CMD_SEND_NEW_PASSWORD = stick20::CMD_START_VALUE + 19, -    ENABLE_CRYPTED_PARI = 0x20, -  DISABLE_CRYPTED_PARI, -  ENABLE_HIDDEN_CRYPTED_PARI, -  DISABLE_HIDDEN_CRYPTED_PARI, -  ENABLE_FIRMWARE_UPDATE, -  EXPORT_FIRMWARE_TO_FILE, -  GENERATE_NEW_KEYS, -  FILL_SD_CARD_WITH_RANDOM_CHARS, +  DISABLE_CRYPTED_PARI = 0x20 + 1, //@unused +  ENABLE_HIDDEN_CRYPTED_PARI = 0x20 + 2, +  DISABLE_HIDDEN_CRYPTED_PARI = 0x20 + 3, //@unused +  ENABLE_FIRMWARE_UPDATE = 0x20 + 4, //enables update mode +  EXPORT_FIRMWARE_TO_FILE = 0x20 + 5, +  GENERATE_NEW_KEYS = 0x20 + 6, +  FILL_SD_CARD_WITH_RANDOM_CHARS = 0x20 + 7, -  WRITE_STATUS_DATA, -  ENABLE_READONLY_UNCRYPTED_LUN, -  ENABLE_READWRITE_UNCRYPTED_LUN, +  WRITE_STATUS_DATA = 0x20 + 8, //@unused +  ENABLE_READONLY_UNCRYPTED_LUN = 0x20 + 9, +  ENABLE_READWRITE_UNCRYPTED_LUN = 0x20 + 10, -  SEND_PASSWORD_MATRIX, -  SEND_PASSWORD_MATRIX_PINDATA, -  SEND_PASSWORD_MATRIX_SETUP, +  SEND_PASSWORD_MATRIX = 0x20 + 11, //@unused +  SEND_PASSWORD_MATRIX_PINDATA = 0x20 + 12, //@unused +  SEND_PASSWORD_MATRIX_SETUP = 0x20 + 13, //@unused -  GET_DEVICE_STATUS, -  SEND_DEVICE_STATUS, +  GET_DEVICE_STATUS = 0x20 + 14, +  SEND_DEVICE_STATUS = 0x20 + 15, -  SEND_HIDDEN_VOLUME_PASSWORD, -  SEND_HIDDEN_VOLUME_SETUP, -  SEND_PASSWORD, -  SEND_NEW_PASSWORD, -  CLEAR_NEW_SD_CARD_FOUND, +  SEND_HIDDEN_VOLUME_PASSWORD = 0x20 + 16, //@unused +  SEND_HIDDEN_VOLUME_SETUP = 0x20 + 17, +  SEND_PASSWORD = 0x20 + 18, +  SEND_NEW_PASSWORD = 0x20 + 19, +  CLEAR_NEW_SD_CARD_FOUND = 0x20 + 20, -  SEND_STARTUP, -  SEND_CLEAR_STICK_KEYS_NOT_INITIATED, -  SEND_LOCK_STICK_HARDWARE, +  SEND_STARTUP = 0x20 + 21, +  SEND_CLEAR_STICK_KEYS_NOT_INITIATED = 0x20 + 22, +  SEND_LOCK_STICK_HARDWARE = 0x20 + 23, //locks firmware upgrade -  PRODUCTION_TEST, -  SEND_DEBUG_DATA, +  PRODUCTION_TEST = 0x20 + 24, +  SEND_DEBUG_DATA = 0x20 + 25, //@unused -  CHANGE_UPDATE_PIN, +  CHANGE_UPDATE_PIN = 0x20 + 26,    GET_PW_SAFE_SLOT_STATUS = 0x60,    GET_PW_SAFE_SLOT_NAME = 0x61, @@ -112,8 +109,8 @@ enum class CommandID : uint8_t {    SET_PW_SAFE_SLOT_DATA_2 = 0x65,    PW_SAFE_ERASE_SLOT = 0x66,    PW_SAFE_ENABLE = 0x67, -  PW_SAFE_INIT_KEY = 0x68, -  PW_SAFE_SEND_DATA = 0x69, +  PW_SAFE_INIT_KEY = 0x68, //@unused +  PW_SAFE_SEND_DATA = 0x69, //@unused    SD_CARD_HIGH_WATERMARK = 0x70,    DETECT_SC_AES = 0x6a,    NEW_AES_KEY = 0x6b diff --git a/include/device.h b/include/device.h index 34b7a5b..3f18921 100644 --- a/include/device.h +++ b/include/device.h @@ -21,6 +21,7 @@ class Device {  public:    Device(); +  virtual ~Device(){disconnect();}    // lack of device is not actually an error,    // so it doesn't throw diff --git a/include/device_proto.h b/include/device_proto.h index cde1d51..0953566 100644 --- a/include/device_proto.h +++ b/include/device_proto.h @@ -16,6 +16,7 @@  #include "command_id.h"  #include "dissect.h"  #include "CommandFailedException.h" +#include "LongOperationInProgressException.h"  #define STICK20_UPDATE_MODE_VID 0x03EB  #define STICK20_UPDATE_MODE_PID 0x2FF1 @@ -89,24 +90,38 @@ namespace nitrokey {   *	command_id member in incoming HIDReport structure carries the command   *	type last used.   */ +        namespace DeviceResponseConstants{ +            //magic numbers from firmware +            static constexpr auto storage_status_absolute_address = 21; +            static constexpr auto storage_data_absolute_address = storage_status_absolute_address + 5; +            static constexpr auto header_size = 8; //from _zero to last_command_status inclusive +            static constexpr auto footer_size = 4; //crc +            static constexpr auto wrapping_size = header_size + footer_size; +        } +          template<CommandID cmd_id, typename ResponsePayload>          struct DeviceResponse { +            static constexpr auto storage_status_padding_size = +                DeviceResponseConstants::storage_status_absolute_address - DeviceResponseConstants::header_size; +              uint8_t _zero;              uint8_t device_status;              uint8_t command_id;  // originally last_command_type              uint32_t last_command_crc;              uint8_t last_command_status; +              union { -                uint8_t _padding[HID_REPORT_SIZE - 12]; +                uint8_t _padding[HID_REPORT_SIZE - DeviceResponseConstants::wrapping_size];                  ResponsePayload payload;                  struct { -                    uint8_t _storage_status_padding[20 - 8 + 1]; //starts on 20th byte minus already 8 used + zero byte +                    uint8_t _storage_status_padding[storage_status_padding_size];                      uint8_t command_counter;                      uint8_t command_id;                      uint8_t device_status; //@see stick20::device_status                      uint8_t progress_bar_value;                  } __packed storage_status;              } __packed; +              uint32_t crc;              void initialize() { bzero(this, sizeof *this); } @@ -119,9 +134,7 @@ namespace nitrokey {              }              void update_CRC() { crc = calculate_CRC(); } -              bool isCRCcorrect() const { return crc == calculate_CRC(); } -              bool isValid() const {                //		return !_zero && payload.isValid() && isCRCcorrect() &&                //				command_id == (uint8_t)(cmd_id); @@ -216,6 +229,7 @@ namespace nitrokey {                if (!outp.isValid()) throw std::runtime_error("Invalid outgoing packet"); +              bool successful_communication = false;                int receiving_retry_counter = 0;                int sending_retry_counter = dev.get_retry_sending_count();                while (sending_retry_counter-- > 0) { @@ -263,12 +277,21 @@ namespace nitrokey {                    //SENDPASSWORD gives wrong CRC , for now rely on !=0 (TODO report)  //                  if (resp.device_status == 0 && resp.last_command_crc == outp.crc && resp.isCRCcorrect()) break;                    if (resp.device_status == static_cast<uint8_t>(stick10::device_status::ok) && -                      resp.last_command_crc == outp.crc && resp.isValid()) break; +                      resp.last_command_crc == outp.crc && resp.isValid()){ +                    successful_communication = true; +                    break; +                  }                    if (resp.device_status == static_cast<uint8_t>(stick10::device_status::busy)) {                      receiving_retry_counter++;                      Log::instance()("Status busy, not decresing receiving_retry_counter counter: " +                                      std::to_string(receiving_retry_counter), Loglevel::DEBUG_L2);                    } +                  if (resp.device_status == static_cast<uint8_t>(stick10::device_status::busy) && +                      static_cast<stick20::device_status>(resp.storage_status.device_status) +                      == stick20::device_status::busy_progressbar){ +                    successful_communication = true; +                    break; +                  }                    Log::instance()(std::string("Retry status - dev status, equal crc, correct CRC: ")                                    + std::to_string(resp.device_status) + " " +                                    std::to_string(resp.last_command_crc == outp.crc) + @@ -282,7 +305,7 @@ namespace nitrokey {                    std::this_thread::sleep_for(dev.get_retry_timeout());                    continue;                  } -                if (resp.device_status == 0 && resp.last_command_crc == outp.crc) break; +                if (successful_communication) break;                  Log::instance()(std::string("Resending (outer loop) "), Loglevel::DEBUG_L2);                  Log::instance()(std::string("sending_retry_counter count: ") + std::to_string(sending_retry_counter),                                  Loglevel::DEBUG); @@ -293,7 +316,7 @@ namespace nitrokey {                clear_packet(outp);                if (status <= 0) -                throw std::runtime_error( +                throw std::runtime_error( //FIXME replace with CriticalErrorException                      std::string("Device error while executing command ") +                      std::to_string(status)); @@ -302,6 +325,13 @@ namespace nitrokey {                Log::instance()(std::string("receiving_retry_counter count: ") + std::to_string(receiving_retry_counter),                                Loglevel::DEBUG); +              if (resp.device_status == static_cast<uint8_t>(stick10::device_status::busy) && +                  static_cast<stick20::device_status>(resp.storage_status.device_status) +                  == stick20::device_status::busy_progressbar){ +                throw LongOperationInProgressException( +                    resp.command_id, resp.device_status, resp.storage_status.progress_bar_value); +              } +                if (!resp.isValid()) throw std::runtime_error("Invalid incoming packet");                if (receiving_retry_counter <= 0)                  throw std::runtime_error( diff --git a/include/misc.h b/include/misc.h index 5fcd16d..5158de0 100644 --- a/include/misc.h +++ b/include/misc.h @@ -3,11 +3,32 @@  #include <stdio.h>  #include <string>  #include <vector> +#include <string.h> +#include "log.h" +#include "LibraryException.h"  namespace nitrokey {  namespace misc { -template <typename T> +    template <typename T> +    void strcpyT(T& dest, const char* src){ + +        if (src == nullptr) +//            throw EmptySourceStringException(slot_number); +            return; +        const size_t s_dest = sizeof dest; +        nitrokey::log::Log::instance()(std::string("strcpyT sizes dest src ") +                                       +std::to_string(s_dest)+ " " +                                       +std::to_string(strlen(src))+ " " +            ,nitrokey::log::Loglevel::DEBUG); +        if (strlen(src) > s_dest){ +            throw TooLongStringException(strlen(src), s_dest, src); +        } +        strncpy((char*) &dest, src, s_dest); +    } + + +    template <typename T>  typename T::CommandPayload get_payload(){      //Create, initialize and return by value command payload      typename T::CommandPayload st; @@ -15,6 +36,13 @@ typename T::CommandPayload get_payload(){      return st;  } +    template<typename CMDTYPE, typename Tdev> +    void execute_password_command(Tdev &stick, const char *password) { +        auto p = get_payload<CMDTYPE>(); +        p.set_defaults(); +        strcpyT(p.password, password); +        CMDTYPE::CommandTransaction::run(stick, p); +    }      std::string hexdump(const char *p, size_t size, bool print_header=true);      uint32_t stm_crc32(const uint8_t *data, size_t size); diff --git a/include/stick20_commands.h b/include/stick20_commands.h index f4e7500..1af9da3 100644 --- a/include/stick20_commands.h +++ b/include/stick20_commands.h @@ -1,5 +1,6 @@  #ifndef STICK20_COMMANDS_H  #define STICK20_COMMANDS_H +  #include "inttypes.h"  #include "command.h"  #include <string> @@ -8,336 +9,299 @@  namespace nitrokey { -namespace proto { +    namespace proto {  /*  *	STICK20 protocol command ids  *	a superset (almost) of STICK10  */ -namespace stick20 { - -    enum class PasswordKind : uint8_t { -        User = 'P', -        Admin = 'A' -    }; - -    class ChangeAdminUserPin20Current : Command<CommandID::STICK20_CMD_SEND_PASSWORD> { -  public: -      struct CommandPayload { -          uint8_t kind; -          uint8_t old_pin[20]; -          std::string dissect() const { -            std::stringstream ss; -            ss << " old_pin:\t" <<  old_pin<< std::endl; -            return ss.str(); -          } -          void set_kind(PasswordKind k){ -            kind = (uint8_t)k; -          } -      } __packed; - -      typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> -              CommandTransaction; -  }; - - -    class ChangeAdminUserPin20New : Command<CommandID::STICK20_CMD_SEND_NEW_PASSWORD> { -    public: - -        struct CommandPayload { -            uint8_t kind; -            uint8_t new_pin[20]; -            std::string dissect() const { -              std::stringstream ss; -              ss << " new_pin:\t" << new_pin<< std::endl; -              return ss.str(); -            } -            void set_kind(PasswordKind k){ -              kind = (uint8_t)k; +#define print_to_ss(x) ( ss << " " << (#x) <<":\t" << (x) << std::endl ); +        namespace stick20 { + +            class ChangeAdminUserPin20Current : +                public PasswordCommand<CommandID::SEND_PASSWORD, PasswordKind::Admin> {}; +            class ChangeAdminUserPin20New : +                public PasswordCommand<CommandID::SEND_NEW_PASSWORD, PasswordKind::Admin> {}; +            class UnlockUserPin : +                public PasswordCommand<CommandID::UNLOCK_USER_PASSWORD, PasswordKind::Admin> {}; + +            class EnableEncryptedPartition : public PasswordCommand<CommandID::ENABLE_CRYPTED_PARI> {}; +            class DisableEncryptedPartition : public PasswordCommand<CommandID::DISABLE_CRYPTED_PARI> {}; +            class EnableHiddenEncryptedPartition : public PasswordCommand<CommandID::ENABLE_HIDDEN_CRYPTED_PARI> {}; +            class DisableHiddenEncryptedPartition : public PasswordCommand<CommandID::DISABLE_CRYPTED_PARI> {}; +            class EnableFirmwareUpdate : public PasswordCommand<CommandID::ENABLE_FIRMWARE_UPDATE> {}; + +            class ChangeUpdatePassword : Command<CommandID::CHANGE_UPDATE_PIN> { +            public: +                struct CommandPayload { +                    uint8_t __gap; +                    uint8_t current_update_password[20]; +                    uint8_t __gap2; +                    uint8_t new_update_password[20]; +                    std::string dissect() const { +                      std::stringstream ss; +                      print_to_ss( current_update_password ); +                      print_to_ss( new_update_password ); +                      return ss.str(); +                    } +                }; + +                typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +                    CommandTransaction; +            }; + +            class ExportFirmware : public PasswordCommand<CommandID::EXPORT_FIRMWARE_TO_FILE> {}; + +            class CreateNewKeys : +                public PasswordCommand<CommandID::GENERATE_NEW_KEYS, PasswordKind::AdminPrefixed, 30> {}; + + +            class FillSDCardWithRandomChars : Command<CommandID::FILL_SD_CARD_WITH_RANDOM_CHARS> { +            public: +                enum class ChosenVolumes : uint8_t { +                    all_volumes = 0, +                    encrypted_volume = 1 +                }; + +                struct CommandPayload { +                    uint8_t volume_flag; +                    uint8_t kind; +                    uint8_t admin_pin[20]; + +                    std::string dissect() const { +                      std::stringstream ss; +                      print_to_ss( (int) volume_flag ); +                      print_to_ss( kind ); +                      print_to_ss(admin_pin); +                      return ss.str(); +                    } +                    void set_kind_user() { +                      kind = (uint8_t) 'P'; +                    } +                    void set_defaults(){ +                      set_kind_user(); +                      volume_flag = static_cast<uint8_t>(ChosenVolumes::encrypted_volume); +                    } + +                } __packed; + +                typedef Transaction<Command<CommandID::FILL_SD_CARD_WITH_RANDOM_CHARS>::command_id(), +                    struct CommandPayload, struct EmptyPayload> +                    CommandTransaction; +            }; + +            namespace StorageCommandResponsePayload{ +                using namespace DeviceResponseConstants; +              static constexpr auto padding_size = +                  storage_data_absolute_address - header_size; +              struct TransmissionData{ +                  uint8_t _padding[padding_size]; + +                  uint8_t SendCounter_u8; +                  uint8_t SendDataType_u8; +                  uint8_t FollowBytesFlag_u8; +                  uint8_t SendSize_u8; + +                  std::string dissect() const { +                    std::stringstream ss; +                    ss << "_padding:" << std::endl +                       << ::nitrokey::misc::hexdump((const char *) (_padding), +                                                    sizeof _padding); +                    print_to_ss((int) SendCounter_u8); +                    print_to_ss((int) SendDataType_u8); +                    print_to_ss((int) FollowBytesFlag_u8); +                    print_to_ss((int) SendSize_u8); +                    return ss.str(); +                  } + +              } __packed;              } -        } __packed; - -        typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> -                CommandTransaction; -    }; - - -    class UnlockUserPassword : Command<CommandID::UNLOCK_USER_PASSWORD> { -    public: -        struct CommandPayload { -            uint8_t kind; -            uint8_t user_new_password[20]; -            std::string dissect() const { -              std::stringstream ss; -              ss << " user_new_password:\t" <<  user_new_password<< std::endl; -              return ss.str(); -            } -            void set_kind(PasswordKind k){ -              kind = (uint8_t)k; -            } -        } __packed; - -        typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> -            CommandTransaction; -    }; - -class EnableEncryptedPartition : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t password[30];  // TODO check w/ firmware -  }; - -  typedef Transaction<CommandID::ENABLE_CRYPTED_PARI, struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class DisableEncryptedPartition : semantics::non_constructible { - public: -  typedef Transaction<CommandID::DISABLE_CRYPTED_PARI, struct EmptyPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class EnableHiddenEncryptedPartition : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t password[30];  // TODO check w/ firmware -  }; - -  typedef Transaction<CommandID::ENABLE_HIDDEN_CRYPTED_PARI, -                      struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class DisableHiddenEncryptedPartition : semantics::non_constructible { - public: -  typedef Transaction<CommandID::DISABLE_CRYPTED_PARI, struct EmptyPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class EnableFirmwareUpdate : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t password[30];  // TODO check w/ firmware -  }; - -  typedef Transaction<CommandID::ENABLE_FIRMWARE_UPDATE, struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class UpdatePassword : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t old_password[15]; -    uint8_t new_password[15]; -  }; - -  typedef Transaction<CommandID::CHANGE_UPDATE_PIN, struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class ExportFirmware : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t password[30]; -  }; - -  typedef Transaction<CommandID::EXPORT_FIRMWARE_TO_FILE, struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -    class CreateNewKeys : Command<CommandID::GENERATE_NEW_KEYS> { -    public: -        struct CommandPayload { -            uint8_t kind; -            uint8_t admin_password[30]; //CS20_MAX_PASSWORD_LEN -            std::string dissect() const { -              std::stringstream ss; -              ss << " admin_password:\t" <<  admin_password<< std::endl; -              return ss.str(); -            } -            void setKindPrefixed(){ -              kind = 'P'; +            namespace DeviceConfigurationResponsePacket{ + +                struct ResponsePayload { +                    StorageCommandResponsePayload::TransmissionData transmission_data; + +                    uint16_t MagicNumber_StickConfig_u16; +                    uint8_t ReadWriteFlagUncryptedVolume_u8; +                    uint8_t ReadWriteFlagCryptedVolume_u8; +                    uint8_t VersionInfo_au8[4]; +                    uint8_t ReadWriteFlagHiddenVolume_u8; +                    uint8_t FirmwareLocked_u8; +                    uint8_t NewSDCardFound_u8; +                    uint8_t SDFillWithRandomChars_u8; +                    uint32_t ActiveSD_CardID_u32; +                    uint8_t VolumeActiceFlag_u8; +                    uint8_t NewSmartCardFound_u8; +                    uint8_t UserPwRetryCount; +                    uint8_t AdminPwRetryCount; +                    uint32_t ActiveSmartCardID_u32; +                    uint8_t StickKeysNotInitiated; + +                    bool isValid() const { return true; } + +                    std::string dissect() const { +                      std::stringstream ss; + +                      print_to_ss(transmission_data.dissect()); +                      print_to_ss( MagicNumber_StickConfig_u16 ); +                      print_to_ss((int) ReadWriteFlagUncryptedVolume_u8 ); +                      print_to_ss((int) ReadWriteFlagCryptedVolume_u8 ); +                      print_to_ss((int) VersionInfo_au8[1] ); +                      print_to_ss((int) VersionInfo_au8[3] ); +                      print_to_ss((int) ReadWriteFlagHiddenVolume_u8 ); +                      print_to_ss((int) FirmwareLocked_u8 ); +                      print_to_ss((int) NewSDCardFound_u8 ); +                      print_to_ss((int) SDFillWithRandomChars_u8 ); +                      print_to_ss( ActiveSD_CardID_u32 ); +                      print_to_ss((int) VolumeActiceFlag_u8 ); +                      print_to_ss((int) NewSmartCardFound_u8 ); +                      print_to_ss((int) UserPwRetryCount ); +                      print_to_ss((int) AdminPwRetryCount ); +                      print_to_ss( ActiveSmartCardID_u32 ); +                      print_to_ss((int) StickKeysNotInitiated ); + +                      return ss.str(); +                    } +                } __packed;              } -        } __packed; - -        typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> -            CommandTransaction; -    }; - - -class FillSDCardWithRandomChars : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t volume_flag; -    uint8_t password[30]; -  }; - -  typedef Transaction<CommandID::FILL_SD_CARD_WITH_RANDOM_CHARS, -                      struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class SetupHiddenVolume : semantics::non_constructible { - public: -  typedef Transaction<CommandID::SEND_HIDDEN_VOLUME_SETUP, struct EmptyPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class SendPasswordMatrix : semantics::non_constructible { - public: -  typedef Transaction<CommandID::SEND_PASSWORD_MATRIX, struct EmptyPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class SendPasswordMatrixPinData : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t pin_data[30];  // TODO how long actually can it be? -  }; - -  typedef Transaction<CommandID::SEND_PASSWORD_MATRIX_PINDATA, -                      struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class SendPasswordMatrixSetup : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t setup_data[30];  // TODO how long actually can it be? -  }; - -  typedef Transaction<CommandID::SEND_PASSWORD_MATRIX_SETUP, -                      struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -#define d(x) ss << " "#x":\t" << (int)x << std::endl; - -    class GetDeviceStatus : Command<CommandID::GET_DEVICE_STATUS> { -    public: -        static const int OUTPUT_CMD_RESULT_STICK20_STATUS_START = 20 +1; -        static const int payload_absolute_begin = 8; -        static const int padding_size = OUTPUT_CMD_RESULT_STICK20_STATUS_START - payload_absolute_begin; -        struct ResponsePayload { -            uint8_t _padding[padding_size]; //TODO confirm padding in Storage firmware -            //data starts from 21st byte of packet -> 13th byte of payload -            uint8_t command_counter; -            uint8_t last_command; -            uint8_t status; -            uint8_t progress_bar_value; -            bool isValid() const { return true; } - -            std::string dissect() const { -              std::stringstream ss; -                d(command_counter); -                d(last_command); -                d(status); -                d(progress_bar_value); -              ss << "_padding:\t" -                 << ::nitrokey::misc::hexdump((const char *)(_padding), -                                              sizeof _padding); -              return ss.str(); -            } -        } __packed; - -        typedef Transaction<command_id(), struct EmptyPayload, struct ResponsePayload> -                CommandTransaction; -    }; - - -class SendPassword : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t password[30]; -  }; -  typedef Transaction<CommandID::SEND_PASSWORD, struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; +            class SendStartup : Command<CommandID::SEND_STARTUP> { +            public: +                struct CommandPayload { +                    uint64_t localtime;  // POSIX seconds from epoch start, supports until year 2106 +                    std::string dissect() const { +                      std::stringstream ss; +                      print_to_ss( localtime ); +                      return ss.str(); +                    } +                    void set_defaults(){ +                      localtime = +                          std::chrono::duration_cast<std::chrono::seconds> ( +                              std::chrono::system_clock::now().time_since_epoch()).count(); +                    } +                }__packed; + +                using ResponsePayload = DeviceConfigurationResponsePacket::ResponsePayload; + +                typedef Transaction<command_id(), struct CommandPayload, ResponsePayload> +                    CommandTransaction; +            }; -class SendNewPassword : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t password[30]; -  }; - -  typedef Transaction<CommandID::SEND_NEW_PASSWORD, struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -};  // TODO fix original nomenclature -class SendSetReadonlyToUncryptedVolume : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t password[30]; -  }; - -  typedef Transaction<CommandID::ENABLE_READWRITE_UNCRYPTED_LUN, -                      struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class SendSetReadwriteToUncryptedVolume : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t password[30]; -  }; - -  typedef Transaction<CommandID::ENABLE_READWRITE_UNCRYPTED_LUN, -                      struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class SendClearNewSdCardFound : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t password[30]; -  }; - -  typedef Transaction<CommandID::CLEAR_NEW_SD_CARD_FOUND, struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class SendStartup : semantics::non_constructible { - public: -  struct CommandPayload { -    uint64_t localtime;  // POSIX -  }; - -  typedef Transaction<CommandID::SEND_STARTUP, struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class SendHiddenVolumeSetup : semantics::non_constructible { - public: -  struct CommandPayload { -    // TODO HiddenVolumeSetup_tst type -  }; - -  typedef Transaction<CommandID::SEND_HIDDEN_VOLUME_SETUP, -                      struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class LockFirmware : semantics::non_constructible { - public: -  struct CommandPayload { -    uint8_t password[30]; -  }; - -  typedef Transaction<CommandID::SEND_LOCK_STICK_HARDWARE, -                      struct CommandPayload, -                      struct EmptyPayload> CommandTransaction; -}; - -class ProductionTest : semantics::non_constructible { - public: -  typedef Transaction<CommandID::PRODUCTION_TEST, struct EmptyPayload, -                      struct EmptyPayload> CommandTransaction; -}; -} -} +            class SendSetReadonlyToUncryptedVolume : public PasswordCommand<CommandID::ENABLE_READONLY_UNCRYPTED_LUN> {}; +            class SendSetReadwriteToUncryptedVolume : public PasswordCommand<CommandID::ENABLE_READWRITE_UNCRYPTED_LUN> {}; +            class SendClearNewSdCardFound : public PasswordCommand<CommandID::CLEAR_NEW_SD_CARD_FOUND> {}; + +            class GetDeviceStatus : Command<CommandID::GET_DEVICE_STATUS> { +            public: +                using ResponsePayload = DeviceConfigurationResponsePacket::ResponsePayload; + +                typedef Transaction<command_id(), struct EmptyPayload, ResponsePayload> +                    CommandTransaction; +            }; + +            class GetSDCardOccupancy : Command<CommandID::SD_CARD_HIGH_WATERMARK> { +            public: +                struct ResponsePayload { +                    uint8_t WriteLevelMin; +                    uint8_t WriteLevelMax; +                    uint8_t ReadLevelMin; +                    uint8_t ReadLevelMax; +                    std::string dissect() const { +                      std::stringstream ss; +                      print_to_ss((int) WriteLevelMin); +                      print_to_ss((int) WriteLevelMax); +                      print_to_ss((int) ReadLevelMin); +                      print_to_ss((int) ReadLevelMax); +                      return ss.str(); +                    } +                } __packed; + +                typedef Transaction<command_id(), struct EmptyPayload, struct ResponsePayload> +                    CommandTransaction; +            }; + + +            class SetupHiddenVolume : Command<CommandID::SEND_HIDDEN_VOLUME_SETUP> { +            public: +                constexpr static int MAX_HIDDEN_VOLUME_PASSWORD_SIZE = 20; +                struct CommandPayload { +                    uint8_t SlotNr_u8; +                    uint8_t StartBlockPercent_u8; +                    uint8_t EndBlockPercent_u8; +                    uint8_t HiddenVolumePassword_au8[MAX_HIDDEN_VOLUME_PASSWORD_SIZE]; +                    std::string dissect() const { +                      std::stringstream ss; +                      print_to_ss((int) SlotNr_u8); +                      print_to_ss((int) StartBlockPercent_u8); +                      print_to_ss((int) EndBlockPercent_u8); +                      print_to_ss(HiddenVolumePassword_au8); +                      return ss.str(); +                    } +                } __packed; + +                typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +                    CommandTransaction; +            }; + + +//disable this command for now +//            class LockFirmware : public PasswordCommand<CommandID::SEND_LOCK_STICK_HARDWARE> {}; + +            class ProductionTest : Command<CommandID::PRODUCTION_TEST> { +            public: +                struct ResponsePayload { + +                    StorageCommandResponsePayload::TransmissionData transmission_data; + +                    uint8_t FirmwareVersion_au8[2];        // 2 byte // 2 +                    uint8_t FirmwareVersionInternal_u8;    // 1 byte // 3 +                    uint8_t SD_Card_Size_u8;               // 1 byte // 4 +                    uint32_t CPU_CardID_u32;                     // 4 byte // 8 +                    uint32_t SmartCardID_u32;                    // 4 byte // 12 +                    uint32_t SD_CardID_u32;                      // 4 byte // 16 +                    uint8_t SC_UserPwRetryCount;           // User PIN retry count 1 byte  // 17 +                    uint8_t SC_AdminPwRetryCount;          // Admin PIN retry count 1 byte // 18 +                    uint8_t SD_Card_ManufacturingYear_u8;  // 1 byte // 19 +                    uint8_t SD_Card_ManufacturingMonth_u8; // 1 byte // 20 +                    uint16_t SD_Card_OEM_u16;              // 2 byte // 22 +                    uint16_t SD_WriteSpeed_u16;            // in kbyte / sec 2 byte // 24 +                    uint8_t SD_Card_Manufacturer_u8;       // 1 byte // 25 + +                    bool isValid() const { return true; } + +                    std::string dissect() const { +                      std::stringstream ss; + +                      print_to_ss(transmission_data.dissect()); +                      print_to_ss((int) FirmwareVersion_au8[0]); +                      print_to_ss((int) FirmwareVersion_au8[1]); +                      print_to_ss((int) FirmwareVersionInternal_u8); +                      print_to_ss((int) SD_Card_Size_u8); +                      print_to_ss( CPU_CardID_u32); +                      print_to_ss( SmartCardID_u32); +                      print_to_ss( SD_CardID_u32); +                      print_to_ss((int) SC_UserPwRetryCount); +                      print_to_ss((int) SC_AdminPwRetryCount); +                      print_to_ss((int) SD_Card_ManufacturingYear_u8); +                      print_to_ss((int) SD_Card_ManufacturingMonth_u8); +                      print_to_ss( SD_Card_OEM_u16); +                      print_to_ss( SD_WriteSpeed_u16); +                      print_to_ss((int) SD_Card_Manufacturer_u8); +                      return ss.str(); +                    } + +                  } __packed; + +                typedef Transaction<command_id(), struct EmptyPayload, struct ResponsePayload> +                    CommandTransaction; +            }; +        } +    }  } +#undef print_to_ss +  #endif  | 
