diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/command.h | 17 | ||||
-rw-r--r-- | include/command_id.h | 127 | ||||
-rw-r--r-- | include/cxx_semantics.h | 6 | ||||
-rw-r--r-- | include/device.h | 74 | ||||
-rw-r--r-- | include/device_proto.h | 302 | ||||
-rw-r--r-- | include/dissect.h | 99 | ||||
-rw-r--r-- | include/log.h | 53 | ||||
-rw-r--r-- | include/misc.h | 1 | ||||
-rw-r--r-- | include/stick10_commands.h | 1043 | ||||
-rw-r--r-- | include/stick20_commands.h | 448 |
10 files changed, 1015 insertions, 1155 deletions
diff --git a/include/command.h b/include/command.h index 6a3e8b4..715902d 100644 --- a/include/command.h +++ b/include/command.h @@ -7,19 +7,16 @@ namespace nitrokey { namespace proto { -template <CommandID cmd_id> +template <CommandID cmd_id> class Command : semantics::non_constructible { -public: - constexpr static CommandID command_id() { - return cmd_id; - } + 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"); - } + template <typename T> + static std::string dissect(const T &) { + return std::string("Payload dissection is unavailable"); + } }; - } } diff --git a/include/command_id.h b/include/command_id.h index 124855b..37aa5d2 100644 --- a/include/command_id.h +++ b/include/command_id.h @@ -6,81 +6,80 @@ namespace nitrokey { namespace proto { enum class CommandID : uint8_t { - GET_STATUS = 0x00, - WRITE_TO_SLOT = 0x01, - READ_SLOT_NAME = 0x02, - READ_SLOT = 0x03, - GET_CODE = 0x04, - WRITE_CONFIG = 0x05, - ERASE_SLOT = 0x06, - FIRST_AUTHENTICATE = 0x07, - AUTHORIZE = 0x08, - GET_PASSWORD_RETRY_COUNT = 0x09, - CLEAR_WARNING = 0x0A, - SET_TIME = 0x0B, - TEST_COUNTER = 0x0C, - TEST_TIME = 0x0D, - USER_AUTHENTICATE = 0x0E, - GET_USER_PASSWORD_RETRY_COUNT = 0x0F, - USER_AUTHORIZE = 0x10, - UNLOCK_USER_PASSWORD = 0x11, - LOCK_DEVICE = 0x12, - FACTORY_RESET = 0x13, - CHANGE_USER_PIN = 0x14, - CHANGE_ADMIN_PIN = 0x15, + GET_STATUS = 0x00, + WRITE_TO_SLOT = 0x01, + READ_SLOT_NAME = 0x02, + READ_SLOT = 0x03, + GET_CODE = 0x04, + WRITE_CONFIG = 0x05, + ERASE_SLOT = 0x06, + FIRST_AUTHENTICATE = 0x07, + AUTHORIZE = 0x08, + GET_PASSWORD_RETRY_COUNT = 0x09, + CLEAR_WARNING = 0x0A, + SET_TIME = 0x0B, + TEST_COUNTER = 0x0C, + TEST_TIME = 0x0D, + USER_AUTHENTICATE = 0x0E, + GET_USER_PASSWORD_RETRY_COUNT = 0x0F, + USER_AUTHORIZE = 0x10, + UNLOCK_USER_PASSWORD = 0x11, + LOCK_DEVICE = 0x12, + FACTORY_RESET = 0x13, + CHANGE_USER_PIN = 0x14, + CHANGE_ADMIN_PIN = 0x15, - 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, + 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, - WRITE_STATUS_DATA, - ENABLE_READONLY_UNCRYPTED_LUN, - ENABLE_READWRITE_UNCRYPTED_LUN, + WRITE_STATUS_DATA, + ENABLE_READONLY_UNCRYPTED_LUN, + ENABLE_READWRITE_UNCRYPTED_LUN, - SEND_PASSWORD_MATRIX, - SEND_PASSWORD_MATRIX_PINDATA, - SEND_PASSWORD_MATRIX_SETUP, + SEND_PASSWORD_MATRIX, + SEND_PASSWORD_MATRIX_PINDATA, + SEND_PASSWORD_MATRIX_SETUP, - GET_DEVICE_STATUS, - SEND_DEVICE_STATUS, + GET_DEVICE_STATUS, + SEND_DEVICE_STATUS, - SEND_HIDDEN_VOLUME_PASSWORD, - SEND_HIDDEN_VOLUME_SETUP, - SEND_PASSWORD, - SEND_NEW_PASSWORD, - CLEAR_NEW_SD_CARD_FOUND, + SEND_HIDDEN_VOLUME_PASSWORD, + SEND_HIDDEN_VOLUME_SETUP, + SEND_PASSWORD, + SEND_NEW_PASSWORD, + CLEAR_NEW_SD_CARD_FOUND, - SEND_STARTUP, - SEND_CLEAR_STICK_KEYS_NOT_INITIATED, - SEND_LOCK_STICK_HARDWARE, + SEND_STARTUP, + SEND_CLEAR_STICK_KEYS_NOT_INITIATED, + SEND_LOCK_STICK_HARDWARE, - PRODUCTION_TEST, - SEND_DEBUG_DATA, + PRODUCTION_TEST, + SEND_DEBUG_DATA, - CHANGE_UPDATE_PIN, + CHANGE_UPDATE_PIN, - GET_PW_SAFE_SLOT_STATUS = 0x60, - GET_PW_SAFE_SLOT_NAME = 0x61, - GET_PW_SAFE_SLOT_PASSWORD = 0x62, - GET_PW_SAFE_SLOT_LOGINNAME = 0x63, - SET_PW_SAFE_SLOT_DATA_1 = 0x64, - 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, - SD_CARD_HIGH_WATERMARK = 0x70, - DETECT_SC_AES = 0x6a, - NEW_AES_KEY = 0x6b + GET_PW_SAFE_SLOT_STATUS = 0x60, + GET_PW_SAFE_SLOT_NAME = 0x61, + GET_PW_SAFE_SLOT_PASSWORD = 0x62, + GET_PW_SAFE_SLOT_LOGINNAME = 0x63, + SET_PW_SAFE_SLOT_DATA_1 = 0x64, + 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, + SD_CARD_HIGH_WATERMARK = 0x70, + DETECT_SC_AES = 0x6a, + NEW_AES_KEY = 0x6b }; -const char * commandid_to_string(CommandID id); - +const char *commandid_to_string(CommandID id); } } #endif diff --git a/include/cxx_semantics.h b/include/cxx_semantics.h index f5d3dca..b846317 100644 --- a/include/cxx_semantics.h +++ b/include/cxx_semantics.h @@ -7,9 +7,9 @@ * There's no need to include Boost for a simple subset this project needs. */ namespace semantics { - class non_constructible { - non_constructible() {} - }; +class non_constructible { + non_constructible() {} +}; } #endif diff --git a/include/device.h b/include/device.h index 943fe1a..768ac32 100644 --- a/include/device.h +++ b/include/device.h @@ -11,60 +11,58 @@ namespace nitrokey { namespace device { -enum class CommError -{ - ERR_NO_ERROR = 0, - ERR_NOT_CONNECTED = -1, - ERR_WRONG_RESPONSE_CRC = -2, - ERR_SENDING = -3, - ERR_STATUS_NOT_OK = -4 +enum class CommError { + ERR_NO_ERROR = 0, + ERR_NOT_CONNECTED = -1, + ERR_WRONG_RESPONSE_CRC = -2, + ERR_SENDING = -3, + ERR_STATUS_NOT_OK = -4 }; class Device { -public: - Device(); + public: + Device(); - // lack of device is not actually an error, - // so it doesn't throw - virtual bool connect(); - virtual bool disconnect(); + // lack of device is not actually an error, + // so it doesn't throw + virtual bool connect(); + virtual bool disconnect(); - /* - * Sends packet of HID_REPORT_SIZE. - */ - virtual CommError send(const void *packet); + /* + * Sends packet of HID_REPORT_SIZE. + */ + virtual CommError send(const void *packet); - /* - * Gets packet of HID_REPORT_SIZE. - * Can sleep. See below. - */ - virtual CommError recv(void *packet); + /* + * Gets packet of HID_REPORT_SIZE. + * Can sleep. See below. + */ + virtual CommError recv(void *packet); -protected: - uint16_t m_vid; - uint16_t m_pid; + protected: + uint16_t m_vid; + uint16_t m_pid; - /* - * While the project uses Signal11 portable HIDAPI - * library, there's no way of doing it asynchronously, - * hence polling. - */ - int m_retry_count; - std::chrono::milliseconds m_retry_timeout; + /* + * While the project uses Signal11 portable HIDAPI + * library, there's no way of doing it asynchronously, + * hence polling. + */ + int m_retry_count; + std::chrono::milliseconds m_retry_timeout; - hid_device *mp_devhandle; + hid_device *mp_devhandle; }; class Stick10 : public Device { -public: - Stick10(); + public: + Stick10(); }; class Stick20 : public Device { -public: - Stick20(); + public: + Stick20(); }; - } } #endif diff --git a/include/device_proto.h b/include/device_proto.h index c8f1ff2..142b45b 100644 --- a/include/device_proto.h +++ b/include/device_proto.h @@ -23,10 +23,10 @@ #define PWS_PASSWORD_LENGTH 20 #define PWS_LOGINNAME_LENGTH 32 -#define PWS_SEND_PASSWORD 0 -#define PWS_SEND_LOGINNAME 1 -#define PWS_SEND_TAB 2 -#define PWS_SEND_CR 3 +#define PWS_SEND_PASSWORD 0 +#define PWS_SEND_LOGINNAME 1 +#define PWS_SEND_TAB 2 +#define PWS_SEND_CR 3 namespace nitrokey { namespace proto { @@ -42,46 +42,42 @@ namespace proto { */ template <CommandID cmd_id, typename Payload> struct HIDReport { - uint8_t _zero; - CommandID command_id; // uint8_t - union { - uint8_t _padding[HID_REPORT_SIZE - 6]; - Payload payload; - } __packed; - uint32_t crc; - - // POD types can't have non-default constructors - // used in Transaction<>::run() - void initialize() { - bzero(this, sizeof *this); - command_id = cmd_id; - } - - uint32_t calculate_CRC() const { - // w/o leading zero, a part of each HID packet - // w/o 4-byte crc - return misc::stm_crc32((const uint8_t *)(this) + 1, - (size_t)(HID_REPORT_SIZE - 5)); - } - - void update_CRC() { - crc = calculate_CRC(); - } - - bool isCRCcorrect() const { - return crc == calculate_CRC(); - } - - bool isValid() const { - return true; -// return !_zero && payload.isValid() && isCRCcorrect(); - } - - operator std::string() const { - // Packet type is known upfront in normal operation. - // Can't be used to dissect random packets. - return QueryDissector<cmd_id, decltype(*this)>::dissect(*this); - } + uint8_t _zero; + CommandID command_id; // uint8_t + union { + uint8_t _padding[HID_REPORT_SIZE - 6]; + Payload payload; + } __packed; + uint32_t crc; + + // POD types can't have non-default constructors + // used in Transaction<>::run() + void initialize() { + bzero(this, sizeof *this); + command_id = cmd_id; + } + + uint32_t calculate_CRC() const { + // w/o leading zero, a part of each HID packet + // w/o 4-byte crc + return misc::stm_crc32((const uint8_t *)(this) + 1, + (size_t)(HID_REPORT_SIZE - 5)); + } + + void update_CRC() { crc = calculate_CRC(); } + + bool isCRCcorrect() const { return crc == calculate_CRC(); } + + bool isValid() const { + return true; + // return !_zero && payload.isValid() && isCRCcorrect(); + } + + operator std::string() const { + // Packet type is known upfront in normal operation. + // Can't be used to dissect random packets. + return QueryDissector<cmd_id, decltype(*this)>::dissect(*this); + } } __packed; /* @@ -92,131 +88,117 @@ struct HIDReport { */ template <CommandID cmd_id, typename ResponsePayload> struct DeviceResponse { - 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]; - ResponsePayload payload; - } __packed; - uint32_t crc; - - void initialize() { - bzero(this, sizeof *this); - } - - uint32_t calculate_CRC() const { - // w/o leading zero, a part of each HID packet - // w/o 4-byte crc - return misc::stm_crc32((const uint8_t *)(this) + 1, - (size_t)(HID_REPORT_SIZE - 5)); - } - - 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); - return true; - } - - operator std::string() const { - return ResponseDissector<cmd_id, decltype(*this)>::dissect(*this); - } + 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]; + ResponsePayload payload; + } __packed; + uint32_t crc; + + void initialize() { bzero(this, sizeof *this); } + + uint32_t calculate_CRC() const { + // w/o leading zero, a part of each HID packet + // w/o 4-byte crc + return misc::stm_crc32((const uint8_t *)(this) + 1, + (size_t)(HID_REPORT_SIZE - 5)); + } + + 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); + return true; + } + + operator std::string() const { + return ResponseDissector<cmd_id, decltype(*this)>::dissect(*this); + } } __packed; struct EmptyPayload { - uint8_t _data[]; + uint8_t _data[]; - bool isValid() const { - return true; - } + bool isValid() const { return true; } - std::string dissect() const { - return std::string("Empty Payload."); - } + std::string dissect() const { return std::string("Empty Payload."); } } __packed; -template<CommandID cmd_id, typename command_payload, - typename response_payload> +template <CommandID cmd_id, typename command_payload, typename response_payload> class Transaction : semantics::non_constructible { -public: - // Types declared in command class scope can't be reached from there. - typedef command_payload CommandPayload; - typedef response_payload ResponsePayload; - - typedef struct HIDReport<cmd_id, CommandPayload> OutgoingPacket; - typedef struct DeviceResponse<cmd_id, ResponsePayload> ResponsePacket; - - static_assert(std::is_pod<OutgoingPacket>::value, - "outgoingpacket must be a pod type"); - static_assert(std::is_pod<ResponsePacket>::value, - "ResponsePacket must be a POD type"); - static_assert(sizeof(OutgoingPacket) == HID_REPORT_SIZE, - "OutgoingPacket type is not the right size"); - static_assert(sizeof(ResponsePacket) == HID_REPORT_SIZE, - "ResponsePacket type is not the right size"); - - static response_payload run(device::Device &dev, - const command_payload &payload) { - using namespace ::nitrokey::device; - using namespace ::nitrokey::log; - - Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); - - CommError status; - OutgoingPacket outp; - ResponsePacket resp; - - // POD types can't have non-default constructors - outp.initialize(); - resp.initialize(); - - outp.payload = payload; - outp.update_CRC(); - - Log::instance()("Outgoing HID packet:", Loglevel::DEBUG); - Log::instance()((std::string)(outp), Loglevel::DEBUG); - - if (!outp.isValid()) - throw std::runtime_error("Invalid outgoing packet"); - - status = dev.send(&outp); - if ((int)(status) < 0 && status != CommError::ERR_NO_ERROR) - throw std::runtime_error( - std::string("Device error while sending command ") + - std::to_string((int)(status))); - - status = dev.recv(&resp); - if ((int)(status) < 0 && status != CommError::ERR_NO_ERROR) - throw std::runtime_error( - std::string("Device error while executing command ") + - std::to_string((int)(status))); - - Log::instance()("Incoming HID packet:", Loglevel::DEBUG); - Log::instance()((std::string)(resp), Loglevel::DEBUG); - - if (!resp.isValid()) - throw std::runtime_error("Invalid incoming packet"); - - // See: DeviceResponse - return resp.payload; - } - - static response_payload run(device::Device &dev) { - command_payload empty_payload; - return run(dev, empty_payload); - } + public: + // Types declared in command class scope can't be reached from there. + typedef command_payload CommandPayload; + typedef response_payload ResponsePayload; + + typedef struct HIDReport<cmd_id, CommandPayload> OutgoingPacket; + typedef struct DeviceResponse<cmd_id, ResponsePayload> ResponsePacket; + + static_assert(std::is_pod<OutgoingPacket>::value, + "outgoingpacket must be a pod type"); + static_assert(std::is_pod<ResponsePacket>::value, + "ResponsePacket must be a POD type"); + static_assert(sizeof(OutgoingPacket) == HID_REPORT_SIZE, + "OutgoingPacket type is not the right size"); + static_assert(sizeof(ResponsePacket) == HID_REPORT_SIZE, + "ResponsePacket type is not the right size"); + + static response_payload run(device::Device &dev, + const command_payload &payload) { + using namespace ::nitrokey::device; + using namespace ::nitrokey::log; + + Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); + + CommError status; + OutgoingPacket outp; + ResponsePacket resp; + + // POD types can't have non-default constructors + outp.initialize(); + resp.initialize(); + + outp.payload = payload; + outp.update_CRC(); + + Log::instance()("Outgoing HID packet:", Loglevel::DEBUG); + Log::instance()((std::string)(outp), Loglevel::DEBUG); + + if (!outp.isValid()) throw std::runtime_error("Invalid outgoing packet"); + + status = dev.send(&outp); + if ((int)(status) < 0 && status != CommError::ERR_NO_ERROR) + throw std::runtime_error( + std::string("Device error while sending command ") + + std::to_string((int)(status))); + + status = dev.recv(&resp); + if ((int)(status) < 0 && status != CommError::ERR_NO_ERROR) + throw std::runtime_error( + std::string("Device error while executing command ") + + std::to_string((int)(status))); + + Log::instance()("Incoming HID packet:", Loglevel::DEBUG); + Log::instance()((std::string)(resp), Loglevel::DEBUG); + + if (!resp.isValid()) throw std::runtime_error("Invalid incoming packet"); + + // See: DeviceResponse + return resp.payload; + } + + static response_payload run(device::Device &dev) { + command_payload empty_payload; + return run(dev, empty_payload); + } }; - } } #endif diff --git a/include/dissect.h b/include/dissect.h index e2ddc02..f552950 100644 --- a/include/dissect.h +++ b/include/dissect.h @@ -15,68 +15,67 @@ namespace proto { template <CommandID id, class HIDPacket> class QueryDissector : semantics::non_constructible { -public: - static std::string dissect(const HIDPacket &pod) { - std::stringstream out; + public: + static std::string dissect(const HIDPacket &pod) { + std::stringstream out; - out << "Raw HID packet:" << std::endl; - out << ::nitrokey::misc::hexdump((const char *)(&pod), sizeof pod); + out << "Raw HID packet:" << std::endl; + out << ::nitrokey::misc::hexdump((const char *)(&pod), sizeof pod); - out << "Contents:" << std::endl; - out << "Command ID:\t" << commandid_to_string((CommandID)(pod.command_id)) << std::endl; - out << "CRC:\t" << pod.crc << std::endl; + out << "Contents:" << std::endl; + out << "Command ID:\t" << commandid_to_string((CommandID)(pod.command_id)) + << std::endl; + out << "CRC:\t" << pod.crc << std::endl; - out << "Payload:" << std::endl; - out << pod.payload.dissect(); - return out.str(); - } + out << "Payload:" << std::endl; + out << pod.payload.dissect(); + return out.str(); + } }; - template <CommandID id, class HIDPacket> class ResponseDissector : semantics::non_constructible { -public: - static std::string dissect(const HIDPacket &pod) { - std::stringstream out; - + public: + static std::string dissect(const HIDPacket &pod) { + std::stringstream out; - // FIXME use values from firmware (possibly generate separate - // header automatically) - std::string status[4]; - status[0] = " STATUS_READY"; - status[1]= " STATUS_BUSY"; - status[2]= " STATUS_ERROR"; - status[3]= " STATUS_RECEIVED_REPORT"; - std::string cmd[11]; - cmd[0]= " CMD_STATUS_OK"; - cmd[1]= " CMD_STATUS_WRONG_CRC"; - cmd[2]= " CMD_STATUS_WRONG_SLOT"; - cmd[3]= " CMD_STATUS_SLOT_NOT_PROGRAMMED"; - cmd[4]= " CMD_STATUS_WRONG_PASSWORD"; - cmd[5]= " CMD_STATUS_NOT_AUTHORIZED"; - cmd[6]= " CMD_STATUS_TIMESTAMP_WARNING"; - cmd[7]= " CMD_STATUS_NO_NAME_ERROR"; - cmd[8]= " CMD_STATUS_NOT_SUPPORTED"; - cmd[9]= " CMD_STATUS_UNKNOWN_COMMAND"; - cmd[10]= " CMD_STATUS_AES_DEC_FAILED"; - + // FIXME use values from firmware (possibly generate separate + // header automatically) + std::string status[4]; + status[0] = " STATUS_READY"; + status[1] = " STATUS_BUSY"; + status[2] = " STATUS_ERROR"; + status[3] = " STATUS_RECEIVED_REPORT"; + std::string cmd[11]; + cmd[0] = " CMD_STATUS_OK"; + cmd[1] = " CMD_STATUS_WRONG_CRC"; + cmd[2] = " CMD_STATUS_WRONG_SLOT"; + cmd[3] = " CMD_STATUS_SLOT_NOT_PROGRAMMED"; + cmd[4] = " CMD_STATUS_WRONG_PASSWORD"; + cmd[5] = " CMD_STATUS_NOT_AUTHORIZED"; + cmd[6] = " CMD_STATUS_TIMESTAMP_WARNING"; + cmd[7] = " CMD_STATUS_NO_NAME_ERROR"; + cmd[8] = " CMD_STATUS_NOT_SUPPORTED"; + cmd[9] = " CMD_STATUS_UNKNOWN_COMMAND"; + cmd[10] = " CMD_STATUS_AES_DEC_FAILED"; - out << "Raw HID packet:" << std::endl; - out << ::nitrokey::misc::hexdump((const char *)(&pod), sizeof pod); + out << "Raw HID packet:" << std::endl; + out << ::nitrokey::misc::hexdump((const char *)(&pod), sizeof pod); - out << "Device status:\t" << pod.device_status + 0<<" "<< cmd[ 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 status:\t" << pod.last_command_status + 0<<" "<<status[pod.last_command_status] << std::endl; - out << "CRC:\t" << pod.crc << std::endl; + out << "Device status:\t" << pod.device_status + 0 << " " + << cmd[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 status:\t" << pod.last_command_status + 0 << " " + << status[pod.last_command_status] << std::endl; + out << "CRC:\t" << pod.crc << std::endl; - out << "Payload:" << std::endl; - out << pod.payload.dissect(); - return out.str(); - } + out << "Payload:" << std::endl; + out << pod.payload.dissect(); + return out.str(); + } }; - - } } diff --git a/include/log.h b/include/log.h index f6f7193..8eda4fb 100644 --- a/include/log.h +++ b/include/log.h @@ -6,57 +6,44 @@ namespace nitrokey { namespace log { -enum class Loglevel : int { - DEBUG_L2, - DEBUG, - INFO, - WARNING, - ERROR -}; +enum class Loglevel : int { DEBUG_L2, DEBUG, INFO, WARNING, ERROR }; class LogHandler { -public: - virtual void print(const std::string &, Loglevel lvl) = 0; + public: + virtual void print(const std::string &, Loglevel lvl) = 0; -protected: - std::string loglevel_to_str(Loglevel); + protected: + std::string loglevel_to_str(Loglevel); }; class StdlogHandler : public LogHandler { -public: - virtual void print(const std::string &, Loglevel lvl); + public: + virtual void print(const std::string &, Loglevel lvl); }; extern StdlogHandler stdlog_handler; class Log { -public: - Log() - : mp_loghandler(&stdlog_handler), m_loglevel(Loglevel::WARNING) {} + public: + Log() : mp_loghandler(&stdlog_handler), m_loglevel(Loglevel::WARNING) {} - static Log &instance() { - if (mp_instance == NULL) - mp_instance = new Log; - return *mp_instance; - } + static Log &instance() { + if (mp_instance == NULL) mp_instance = new Log; + return *mp_instance; + } - void operator()(const std::string &, Loglevel); + void operator()(const std::string &, Loglevel); - void set_loglevel(Loglevel lvl) { - m_loglevel = lvl; - } + void set_loglevel(Loglevel lvl) { m_loglevel = lvl; } - void set_handler(LogHandler *handler) { - mp_loghandler = handler; - } + void set_handler(LogHandler *handler) { mp_loghandler = handler; } -private: - Loglevel m_loglevel; - LogHandler *mp_loghandler; + private: + Loglevel m_loglevel; + LogHandler *mp_loghandler; - static Log *mp_instance; + static Log *mp_instance; }; - } } diff --git a/include/misc.h b/include/misc.h index bf68915..07f221c 100644 --- a/include/misc.h +++ b/include/misc.h @@ -8,7 +8,6 @@ namespace misc { std::string hexdump(const char *p, size_t size); uint32_t stm_crc32(const uint8_t *data, size_t size); - } } diff --git a/include/stick10_commands.h b/include/stick10_commands.h index de31e95..b140e99 100644 --- a/include/stick10_commands.h +++ b/include/stick10_commands.h @@ -12,571 +12,486 @@ namespace proto { * Stick10 protocol definition */ namespace stick10 { - class GetSlotName : public Command<CommandID::READ_SLOT_NAME> { - public: - // reachable as a typedef in Transaction - struct CommandPayload { - uint8_t slot_number; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - struct ResponsePayload { - uint8_t slot_name[15]; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct ResponsePayload> CommandTransaction; - }; - - class EraseSlot : Command<CommandID::ERASE_SLOT> { - public: - struct CommandPayload { - uint8_t slot_number; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class SetTime : Command<CommandID::SET_TIME> { - public: - struct CommandPayload { - uint8_t reset; // 0 - get time, 1 - set time - uint64_t time; // posix time - - bool isValid() const { - return reset && reset != 1; - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - // TODO duplicate TOTP - class WriteToHOTPSlot : Command<CommandID::WRITE_TO_SLOT> { - public: - struct CommandPayload { - uint8_t slot_number; - uint8_t slot_name[15]; - uint8_t slot_secret[20]; - uint8_t slot_config; - uint8_t slot_token_id[13]; - uint8_t slot_counter[8]; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class WriteToTOTPSlot : Command<CommandID::WRITE_TO_SLOT> { - public: - struct CommandPayload { - uint8_t slot_number; - uint8_t slot_name[15]; - uint8_t slot_secret[20]; - uint8_t slot_config; - uint8_t slot_token_id[13]; - uint16_t slot_interval; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class GetCode : Command<CommandID::GET_CODE> { - 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); - } - } __packed; - - struct ResponsePayload { - uint8_t code[18]; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct ResponsePayload> CommandTransaction; - }; - - class GetHOTP : Command<CommandID::GET_CODE> { - public: - struct CommandPayload { - uint8_t slot_number; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class ReadSlot : Command<CommandID::READ_SLOT> { - public: - struct CommandPayload { - 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; - - struct ResponsePayload { - uint8_t slot_name[15]; - uint8_t config; - uint8_t token_id[13]; - uint64_t counter; - - bool isValid() const { - return true; - } - - std::string dissect() const { - std::stringstream ss; - ss << "slot_name:\t" << slot_name << std::endl; - ss << "config:\t" << config << std::endl; - ss << "token_id:\t" << token_id << std::endl; - ss << "counter:\t" << counter << std::endl; - return ss.str(); - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct ResponsePayload> CommandTransaction; - }; - - class GetStatus : Command<CommandID::GET_STATUS> { - public: - struct ResponsePayload { - uint16_t firmware_version; - uint8_t card_serial[4]; - uint8_t general_config[3]; - uint8_t otp_password_config[2]; - - bool isValid() const { - return true; - } - - std::string dissect() const { - std::stringstream ss; - ss << "firmware_version:\t" << firmware_version << std::endl; - ss << "card_serial:\t" - << ::nitrokey::misc::hexdump((const char *)(card_serial), sizeof card_serial); - ss << "general_config:\t" - << ::nitrokey::misc::hexdump((const char *)(general_config), sizeof general_config); - ss << "otp_password_config:\t" - << ::nitrokey::misc::hexdump((const char *)(otp_password_config), sizeof otp_password_config); - return ss.str(); - } - } __packed; - - typedef Transaction<command_id(), - struct EmptyPayload, - struct ResponsePayload> CommandTransaction; - }; - - class GetPasswordRetryCount : Command<CommandID::GET_PASSWORD_RETRY_COUNT> { - public: - struct ResponsePayload { - uint8_t password_retry_count; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction<command_id(), - struct EmptyPayload, - struct ResponsePayload> CommandTransaction; - }; - - class GetUserPasswordRetryCount : Command<CommandID::GET_USER_PASSWORD_RETRY_COUNT> { - public: - struct ResponsePayload { - uint8_t password_retry_count; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction<command_id(), - struct EmptyPayload, - struct ResponsePayload> CommandTransaction; - }; - - class GetPasswordSafeSlotStatus : Command<CommandID::GET_PW_SAFE_SLOT_STATUS> { - public: - struct ResponsePayload { - uint8_t password_safe_status[PWS_SLOT_COUNT]; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction<command_id(), - struct EmptyPayload, - struct ResponsePayload> CommandTransaction; - }; - - class GetPasswordSafeSlotName : Command<CommandID::GET_PW_SAFE_SLOT_NAME> { - public: - struct CommandPayload { - uint8_t slot_number; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - struct ResponsePayload { - uint8_t slot_name[PWS_SLOTNAME_LENGTH]; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct ResponsePayload> CommandTransaction; - }; - - class GetPasswordSafeSlotPassword : Command<CommandID::GET_PW_SAFE_SLOT_PASSWORD> { - public: - struct CommandPayload { - uint8_t slot_number; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - struct ResponsePayload { - uint8_t slot_password[PWS_PASSWORD_LENGTH]; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct ResponsePayload> CommandTransaction; - }; - - class GetPasswordSafeSlotLogin : Command<CommandID::GET_PW_SAFE_SLOT_LOGINNAME> { - public: - struct CommandPayload { - uint8_t slot_number; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - struct ResponsePayload { - uint8_t slot_login[PWS_LOGINNAME_LENGTH]; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct ResponsePayload> CommandTransaction; - }; - - class SetPasswordSafeSlotData : Command<CommandID::SET_PW_SAFE_SLOT_DATA_1> { - public: - struct CommandPayload { - uint8_t slot_number; - uint8_t slot_name[PWS_SLOTNAME_LENGTH]; - uint8_t slot_password[PWS_PASSWORD_LENGTH]; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class SetPasswordSafeSlotData2 : Command<CommandID::SET_PW_SAFE_SLOT_DATA_2> { - public: - struct CommandPayload { - uint8_t slot_number; - uint8_t slot_name[PWS_SLOTNAME_LENGTH]; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class ErasePasswordSafeSlot : Command<CommandID::PW_SAFE_ERASE_SLOT> { - public: - struct CommandPayload { - uint8_t slot_number; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class EnablePasswordSafe : Command<CommandID::PW_SAFE_ENABLE> { - public: - struct CommandPayload { - uint8_t password[30]; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class PasswordSafeInitKey : Command<CommandID::PW_SAFE_INIT_KEY> { - public: - typedef Transaction<command_id(), - struct EmptyPayload, - struct EmptyPayload> CommandTransaction; - }; - - // TODO naming screwed up, see above - class PasswordSafeSendSlotViaHID: Command<CommandID::PW_SAFE_SEND_DATA> { - public: - struct CommandPayload { - uint8_t slot_number; - uint8_t slot_kind; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - - // TODO "Device::passwordSafeSendSlotDataViaHID" - - class WriteGeneralConfig : Command<CommandID::WRITE_CONFIG> { - public: - struct CommandPayload { - uint8_t config[5]; - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class FirstAuthenticate : Command<CommandID::FIRST_AUTHENTICATE> { - public: - struct CommandPayload { - uint8_t card_password[25]; - uint8_t temporary_password[25]; - - bool isValid() const { - return true; - } - - std::string dissect() const { - std::stringstream ss; - ss << "card_password:\t" << card_password << std::endl; - ss << "temporary_password:\t" << temporary_password << std::endl; - return ss.str(); - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class UserAuthenticate : Command<CommandID::USER_AUTHENTICATE> { - public: - struct CommandPayload { - uint8_t card_password[25]; - uint8_t temporary_password[25]; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class Authorize : Command<CommandID::AUTHORIZE> { - public: - struct CommandPayload { - uint8_t crc[4]; - uint8_t password[25]; - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class UserAuthorize : Command<CommandID::USER_AUTHORIZE> { - public: - struct CommandPayload { - uint8_t crc[4]; - uint8_t password[25]; - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class UnlockUserPassword : Command<CommandID::UNLOCK_USER_PASSWORD> { - public: - struct CommandPayload { - uint8_t admin_password[20]; // TODO - } __packed; - - // TODO could we get the stick to return the retry count? - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class ChangeUserPin : Command<CommandID::CHANGE_USER_PIN> { - public: - struct CommandPayload { - uint8_t old_pin[25]; - uint8_t new_pin[25]; - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - // TODO why is it needed? - class IsAESSupported : Command<CommandID::DETECT_SC_AES> { - public: - struct CommandPayload { - uint8_t password[20]; - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class ChangeAdminPin : Command<CommandID::CHANGE_ADMIN_PIN> { - public: - struct CommandPayload { - uint8_t old_pin[25]; - uint8_t new_pin[25]; - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class LockDevice : Command<CommandID::LOCK_DEVICE> { - public: - typedef Transaction<command_id(), - struct EmptyPayload, - struct EmptyPayload> CommandTransaction; - }; - - class FactoryReset : Command<CommandID::FACTORY_RESET> { - public: - struct CommandPayload { - uint8_t password[20]; - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; - - class BuildAESKey : Command<CommandID::NEW_AES_KEY> { - public: - struct CommandPayload { - uint8_t password[20]; - } __packed; - - typedef Transaction<command_id(), - struct CommandPayload, - struct EmptyPayload> CommandTransaction; - }; +class GetSlotName : public Command<CommandID::READ_SLOT_NAME> { + public: + // reachable as a typedef in Transaction + struct CommandPayload { + uint8_t slot_number; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + struct ResponsePayload { + uint8_t slot_name[15]; + + bool isValid() const { return true; } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, + struct ResponsePayload> CommandTransaction; +}; + +class EraseSlot : Command<CommandID::ERASE_SLOT> { + public: + struct CommandPayload { + uint8_t slot_number; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class SetTime : Command<CommandID::SET_TIME> { + public: + struct CommandPayload { + uint8_t reset; // 0 - get time, 1 - set time + uint64_t time; // posix time + + bool isValid() const { return reset && reset != 1; } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +// TODO duplicate TOTP +class WriteToHOTPSlot : Command<CommandID::WRITE_TO_SLOT> { + public: + struct CommandPayload { + uint8_t slot_number; + uint8_t slot_name[15]; + uint8_t slot_secret[20]; + uint8_t slot_config; + uint8_t slot_token_id[13]; + uint8_t slot_counter[8]; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class WriteToTOTPSlot : Command<CommandID::WRITE_TO_SLOT> { + public: + struct CommandPayload { + uint8_t slot_number; + uint8_t slot_name[15]; + uint8_t slot_secret[20]; + uint8_t slot_config; + uint8_t slot_token_id[13]; + uint16_t slot_interval; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class GetCode : Command<CommandID::GET_CODE> { + 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); } + } __packed; + + struct ResponsePayload { + uint8_t code[18]; + + bool isValid() const { return true; } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, + struct ResponsePayload> CommandTransaction; +}; + +class GetHOTP : Command<CommandID::GET_CODE> { + public: + struct CommandPayload { + uint8_t slot_number; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class ReadSlot : Command<CommandID::READ_SLOT> { + public: + struct CommandPayload { + 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; + + struct ResponsePayload { + uint8_t slot_name[15]; + uint8_t config; + uint8_t token_id[13]; + uint64_t counter; + + bool isValid() const { return true; } + + std::string dissect() const { + std::stringstream ss; + ss << "slot_name:\t" << slot_name << std::endl; + ss << "config:\t" << config << std::endl; + ss << "token_id:\t" << token_id << std::endl; + ss << "counter:\t" << counter << std::endl; + return ss.str(); + } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, + struct ResponsePayload> CommandTransaction; +}; + +class GetStatus : Command<CommandID::GET_STATUS> { + public: + struct ResponsePayload { + uint16_t firmware_version; + uint8_t card_serial[4]; + uint8_t general_config[3]; + uint8_t otp_password_config[2]; + + bool isValid() const { return true; } + + std::string dissect() const { + std::stringstream ss; + ss << "firmware_version:\t" << firmware_version << std::endl; + ss << "card_serial:\t" + << ::nitrokey::misc::hexdump((const char *)(card_serial), + sizeof card_serial); + ss << "general_config:\t" + << ::nitrokey::misc::hexdump((const char *)(general_config), + sizeof general_config); + ss << "otp_password_config:\t" + << ::nitrokey::misc::hexdump((const char *)(otp_password_config), + sizeof otp_password_config); + return ss.str(); + } + } __packed; + + typedef Transaction<command_id(), struct EmptyPayload, struct ResponsePayload> + CommandTransaction; +}; + +class GetPasswordRetryCount : Command<CommandID::GET_PASSWORD_RETRY_COUNT> { + public: + struct ResponsePayload { + uint8_t password_retry_count; + + bool isValid() const { return true; } + } __packed; + + typedef Transaction<command_id(), struct EmptyPayload, struct ResponsePayload> + CommandTransaction; +}; + +class GetUserPasswordRetryCount + : Command<CommandID::GET_USER_PASSWORD_RETRY_COUNT> { + public: + struct ResponsePayload { + uint8_t password_retry_count; + + bool isValid() const { return true; } + } __packed; + + typedef Transaction<command_id(), struct EmptyPayload, struct ResponsePayload> + CommandTransaction; +}; + +class GetPasswordSafeSlotStatus : Command<CommandID::GET_PW_SAFE_SLOT_STATUS> { + public: + struct ResponsePayload { + uint8_t password_safe_status[PWS_SLOT_COUNT]; + + bool isValid() const { return true; } + } __packed; + + typedef Transaction<command_id(), struct EmptyPayload, struct ResponsePayload> + CommandTransaction; +}; + +class GetPasswordSafeSlotName : Command<CommandID::GET_PW_SAFE_SLOT_NAME> { + public: + struct CommandPayload { + uint8_t slot_number; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + struct ResponsePayload { + uint8_t slot_name[PWS_SLOTNAME_LENGTH]; + + bool isValid() const { return true; } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, + struct ResponsePayload> CommandTransaction; +}; + +class GetPasswordSafeSlotPassword + : Command<CommandID::GET_PW_SAFE_SLOT_PASSWORD> { + public: + struct CommandPayload { + uint8_t slot_number; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + struct ResponsePayload { + uint8_t slot_password[PWS_PASSWORD_LENGTH]; + + bool isValid() const { return true; } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, + struct ResponsePayload> CommandTransaction; +}; + +class GetPasswordSafeSlotLogin + : Command<CommandID::GET_PW_SAFE_SLOT_LOGINNAME> { + public: + struct CommandPayload { + uint8_t slot_number; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + struct ResponsePayload { + uint8_t slot_login[PWS_LOGINNAME_LENGTH]; + + bool isValid() const { return true; } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, + struct ResponsePayload> CommandTransaction; +}; + +class SetPasswordSafeSlotData : Command<CommandID::SET_PW_SAFE_SLOT_DATA_1> { + public: + struct CommandPayload { + uint8_t slot_number; + uint8_t slot_name[PWS_SLOTNAME_LENGTH]; + uint8_t slot_password[PWS_PASSWORD_LENGTH]; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class SetPasswordSafeSlotData2 : Command<CommandID::SET_PW_SAFE_SLOT_DATA_2> { + public: + struct CommandPayload { + uint8_t slot_number; + uint8_t slot_name[PWS_SLOTNAME_LENGTH]; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class ErasePasswordSafeSlot : Command<CommandID::PW_SAFE_ERASE_SLOT> { + public: + struct CommandPayload { + uint8_t slot_number; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class EnablePasswordSafe : Command<CommandID::PW_SAFE_ENABLE> { + public: + struct CommandPayload { + uint8_t password[30]; + + bool isValid() const { return true; } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class PasswordSafeInitKey : Command<CommandID::PW_SAFE_INIT_KEY> { + public: + typedef Transaction<command_id(), struct EmptyPayload, struct EmptyPayload> + CommandTransaction; +}; + +// TODO naming screwed up, see above +class PasswordSafeSendSlotViaHID : Command<CommandID::PW_SAFE_SEND_DATA> { + public: + struct CommandPayload { + uint8_t slot_number; + uint8_t slot_kind; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +// TODO "Device::passwordSafeSendSlotDataViaHID" + +class WriteGeneralConfig : Command<CommandID::WRITE_CONFIG> { + public: + struct CommandPayload { + uint8_t config[5]; + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class FirstAuthenticate : Command<CommandID::FIRST_AUTHENTICATE> { + public: + struct CommandPayload { + uint8_t card_password[25]; + uint8_t temporary_password[25]; + + bool isValid() const { return true; } + + std::string dissect() const { + std::stringstream ss; + ss << "card_password:\t" << card_password << std::endl; + ss << "temporary_password:\t" << temporary_password << std::endl; + return ss.str(); + } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class UserAuthenticate : Command<CommandID::USER_AUTHENTICATE> { + public: + struct CommandPayload { + uint8_t card_password[25]; + uint8_t temporary_password[25]; + + bool isValid() const { return true; } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class Authorize : Command<CommandID::AUTHORIZE> { + public: + struct CommandPayload { + uint8_t crc[4]; + uint8_t password[25]; + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class UserAuthorize : Command<CommandID::USER_AUTHORIZE> { + public: + struct CommandPayload { + uint8_t crc[4]; + uint8_t password[25]; + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class UnlockUserPassword : Command<CommandID::UNLOCK_USER_PASSWORD> { + public: + struct CommandPayload { + uint8_t admin_password[20]; // TODO + } __packed; + + // TODO could we get the stick to return the retry count? + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class ChangeUserPin : Command<CommandID::CHANGE_USER_PIN> { + public: + struct CommandPayload { + uint8_t old_pin[25]; + uint8_t new_pin[25]; + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +// TODO why is it needed? +class IsAESSupported : Command<CommandID::DETECT_SC_AES> { + public: + struct CommandPayload { + uint8_t password[20]; + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class ChangeAdminPin : Command<CommandID::CHANGE_ADMIN_PIN> { + public: + struct CommandPayload { + uint8_t old_pin[25]; + uint8_t new_pin[25]; + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class LockDevice : Command<CommandID::LOCK_DEVICE> { + public: + typedef Transaction<command_id(), struct EmptyPayload, struct EmptyPayload> + CommandTransaction; +}; + +class FactoryReset : Command<CommandID::FACTORY_RESET> { + public: + struct CommandPayload { + uint8_t password[20]; + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; + +class BuildAESKey : Command<CommandID::NEW_AES_KEY> { + public: + struct CommandPayload { + uint8_t password[20]; + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; +}; } - } } #endif diff --git a/include/stick20_commands.h b/include/stick20_commands.h index 22b7e9a..b84d436 100644 --- a/include/stick20_commands.h +++ b/include/stick20_commands.h @@ -10,238 +10,222 @@ namespace proto { * a superset of STICK10 */ namespace stick20 { - 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 : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; - }; - - typedef Transaction<CommandID::GENERATE_NEW_KEYS, - 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; - }; - - class GetDeviceStatus : semantics::non_constructible { - public: - typedef Transaction<CommandID::GET_DEVICE_STATUS, - struct EmptyPayload, - struct EmptyPayload> CommandTransaction; - }; - - class SendPassword : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; - }; - - typedef Transaction<CommandID::SEND_PASSWORD, - struct CommandPayload, - struct EmptyPayload> 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 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 : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; + }; + + typedef Transaction<CommandID::GENERATE_NEW_KEYS, 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; +}; + +class GetDeviceStatus : semantics::non_constructible { + public: + typedef Transaction<CommandID::GET_DEVICE_STATUS, struct EmptyPayload, + struct EmptyPayload> CommandTransaction; +}; + +class SendPassword : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; + }; + + typedef Transaction<CommandID::SEND_PASSWORD, struct CommandPayload, + struct EmptyPayload> 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; +}; } } } |