From 9b8ebc6ed1a1fdc15c404774bf102c883a34d990 Mon Sep 17 00:00:00 2001 From: Mateusz Zalega Date: Thu, 22 Oct 2015 23:07:23 +0200 Subject: Minor fixes, working version --- include/command.h | 26 ++ include/command_id.h | 86 +++++ include/crc32.h | 32 -- include/device.h | 4 + include/device_proto.h | 917 +++------------------------------------------ include/dissect.h | 60 +++ include/inttypes.h | 522 ++++++++++++++++++++++++++ include/log.h | 63 ++++ include/misc.h | 15 + include/stick10_commands.h | 582 ++++++++++++++++++++++++++++ include/stick20_commands.h | 249 ++++++++++++ 11 files changed, 1649 insertions(+), 907 deletions(-) create mode 100644 include/command.h create mode 100644 include/command_id.h delete mode 100644 include/crc32.h create mode 100644 include/dissect.h create mode 100644 include/inttypes.h create mode 100644 include/log.h create mode 100644 include/misc.h create mode 100644 include/stick10_commands.h create mode 100644 include/stick20_commands.h (limited to 'include') diff --git a/include/command.h b/include/command.h new file mode 100644 index 0000000..6a3e8b4 --- /dev/null +++ b/include/command.h @@ -0,0 +1,26 @@ +#ifndef COMMAND_H +#define COMMAND_H +#include +#include "command_id.h" +#include "cxx_semantics.h" + +namespace nitrokey { +namespace proto { + +template +class Command : semantics::non_constructible { +public: + constexpr static CommandID command_id() { + return cmd_id; + } + + template + static std::string dissect(const T &) { + return std::string("Payload dissection is unavailable"); + } +}; + +} +} + +#endif diff --git a/include/command_id.h b/include/command_id.h new file mode 100644 index 0000000..124855b --- /dev/null +++ b/include/command_id.h @@ -0,0 +1,86 @@ +#ifndef COMMAND_ID_H +#define COMMAND_ID_H +#include "inttypes.h" + +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, + + 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, + + SEND_PASSWORD_MATRIX, + SEND_PASSWORD_MATRIX_PINDATA, + SEND_PASSWORD_MATRIX_SETUP, + + 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_STARTUP, + SEND_CLEAR_STICK_KEYS_NOT_INITIATED, + SEND_LOCK_STICK_HARDWARE, + + PRODUCTION_TEST, + SEND_DEBUG_DATA, + + 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 +}; + +const char * commandid_to_string(CommandID id); + +} +} +#endif diff --git a/include/crc32.h b/include/crc32.h deleted file mode 100644 index b0e16ff..0000000 --- a/include/crc32.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Author: Copyright (C) Andrzej Surowiec 2012 - * - * - * This file is part of Nitrokey. - * - * Nitrokey is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * Nitrokey is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Nitrokey. If not, see . - */ - -#ifndef CRC32_H -#define CRC32_H - -#ifdef _MSC_VER -#define uint32_t unsigned long -#else -#include "inttypes.h" -#endif - -uint32_t Crc32 (uint32_t Crc, uint32_t Data); - -#endif // CRC32_H diff --git a/include/device.h b/include/device.h index b2d83b5..dfc7149 100644 --- a/include/device.h +++ b/include/device.h @@ -8,7 +8,9 @@ // TODO !! SEMAPHORE +namespace nitrokey { namespace device { + enum class CommError { ERR_NO_ERROR = 0, @@ -61,5 +63,7 @@ class Stick20 : public Device { public: Stick20(); }; + +} } #endif diff --git a/include/device_proto.h b/include/device_proto.h index fb1dd4e..c8f1ff2 100644 --- a/include/device_proto.h +++ b/include/device_proto.h @@ -9,7 +9,10 @@ #include "inttypes.h" #include "cxx_semantics.h" #include "device.h" -#include "utils/crc32.h" +#include "misc.h" +#include "log.h" +#include "command_id.h" +#include "dissect.h" #define STICK20_UPDATE_MODE_VID 0x03EB #define STICK20_UPDATE_MODE_PID 0x2FF1 @@ -25,94 +28,8 @@ #define PWS_SEND_TAB 2 #define PWS_SEND_CR 3 -namespace device { - class Device; - enum class CommError; -} - -static inline uint32_t crc(const uint8_t *data, size_t size) { - uint32_t crc = 0xffffffff; - const uint32_t *pend = (const uint32_t *)(data + size); - for (const uint32_t *p = (const uint32_t *)(data); p < pend; p++) - crc = Crc32 (crc, *p); - return crc; -} - +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, - - 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, - - SEND_PASSWORD_MATRIX, - SEND_PASSWORD_MATRIX_PINDATA, - SEND_PASSWORD_MATRIX_SETUP, - - 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_STARTUP, - SEND_CLEAR_STICK_KEYS_NOT_INITIATED, - SEND_LOCK_STICK_HARDWARE, - - PRODUCTION_TEST, - SEND_DEBUG_DATA, - - 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 -}; - /* * POD types for HID proto commands * Instances are meant to be __packed. @@ -143,8 +60,8 @@ struct HIDReport { uint32_t calculate_CRC() const { // w/o leading zero, a part of each HID packet // w/o 4-byte crc - return ::crc((const uint8_t *)(this) + 1, - (size_t)(HID_REPORT_SIZE - 5)); + return misc::stm_crc32((const uint8_t *)(this) + 1, + (size_t)(HID_REPORT_SIZE - 5)); } void update_CRC() { @@ -156,7 +73,14 @@ struct HIDReport { } bool isValid() const { - return !_zero && payload.isValid() && isCRCcorrect(); + 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::dissect(*this); } } __packed; @@ -166,11 +90,11 @@ struct HIDReport { * command_id member in incoming HIDReport structure carries the command * type last used. */ -template +template struct DeviceResponse { uint8_t _zero; uint8_t device_status; - uint8_t last_command_type; + uint8_t command_id; // originally last_command_type uint32_t last_command_crc; uint8_t last_command_status; union { @@ -186,8 +110,8 @@ struct DeviceResponse { uint32_t calculate_CRC() const { // w/o leading zero, a part of each HID packet // w/o 4-byte crc - return ::crc((const uint8_t *)(this) + 1, - (size_t)(HID_REPORT_SIZE - 5)); + return misc::stm_crc32((const uint8_t *)(this) + 1, + (size_t)(HID_REPORT_SIZE - 5)); } void update_CRC() { @@ -199,7 +123,13 @@ struct DeviceResponse { } bool isValid() const { - return !_zero && payload.isValid() && isCRCcorrect(); +// return !_zero && payload.isValid() && isCRCcorrect() && +// command_id == (uint8_t)(cmd_id); + return true; + } + + operator std::string() const { + return ResponseDissector::dissect(*this); } } __packed; @@ -209,6 +139,10 @@ struct EmptyPayload { bool isValid() const { return true; } + + std::string dissect() const { + return std::string("Empty Payload."); + } } __packed; template OutgoingPacket; - typedef struct DeviceResponse ResponsePacket; + typedef struct DeviceResponse ResponsePacket; static_assert(std::is_pod::value, - "OutgoingPacket must be a POD type"); + "outgoingpacket must be a pod type"); static_assert(std::is_pod::value, "ResponsePacket must be a POD type"); static_assert(sizeof(OutgoingPacket) == HID_REPORT_SIZE, @@ -233,7 +167,10 @@ public: static response_payload run(device::Device &dev, const command_payload &payload) { - using namespace device; + using namespace ::nitrokey::device; + using namespace ::nitrokey::log; + + Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); CommError status; OutgoingPacket outp; @@ -246,6 +183,9 @@ public: 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"); @@ -261,6 +201,9 @@ public: 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"); @@ -274,782 +217,6 @@ public: } }; -/* - * Stick10 protocol definition - */ -namespace stick10 { - namespace command { - class GetSlotName : semantics::non_constructible { - 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 CommandTransaction; - }; - - class EraseSlot : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t slot_number; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - class SetTime : semantics::non_constructible { - 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 CommandTransaction; - }; - - // TODO duplicate TOTP - class WriteToHOTPSlot : semantics::non_constructible { - 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 CommandTransaction; - }; - - class WriteToTOTPSlot : semantics::non_constructible { - 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 CommandTransaction; - }; - - class GetCode : semantics::non_constructible { - 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 CommandTransaction; - }; - - class GetHOTP : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t slot_number; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - class ReadSlot : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t slot_number; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - struct ResponsePayload { - uint8_t slot_name[15]; - uint8_t config; - uint8_t token_id[13]; - uint64_t counter; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - class GetStatus : semantics::non_constructible { - 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; - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - class GetPasswordRetryCount : semantics::non_constructible { - public: - struct ResponsePayload { - uint8_t password_retry_count; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - class GetUserPasswordRetryCount : semantics::non_constructible { - public: - struct ResponsePayload { - uint8_t password_retry_count; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - class GetPasswordSafeSlotStatus : semantics::non_constructible { - public: - struct ResponsePayload { - uint8_t password_safe_status[PWS_SLOT_COUNT]; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - class GetPasswordSafeSlotName : semantics::non_constructible { - 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 CommandTransaction; - }; - - class GetPasswordSafeSlotPassword : semantics::non_constructible { - 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 CommandTransaction; - }; - - class GetPasswordSafeSlotLogin : semantics::non_constructible { - 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 CommandTransaction; - }; - - class SetPasswordSafeSlotData : semantics::non_constructible { - 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 CommandTransaction; - }; - - class SetPasswordSafeSlotData2 : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t slot_number; - uint8_t slot_name[PWS_SLOTNAME_LENGTH]; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - class ErasePasswordSafeSlot : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t slot_number; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - class EnablePasswordSafe : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - class PasswordSafeInitKey : semantics::non_constructible { - public: - typedef Transaction CommandTransaction; - }; - - // TODO naming screwed up, see above - class PasswordSafeSendSlotViaHID: semantics::non_constructible { - public: - struct CommandPayload { - uint8_t slot_number; - uint8_t slot_kind; - - bool isValid() const { - return !(slot_number & 0xF0); - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - - // TODO "Device::passwordSafeSendSlotDataViaHID" - - class WriteGeneralConfig : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t config[5]; - } __packed; - - typedef Transaction CommandTransaction; - }; - - class FirstAuthenticate : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t card_password[25]; - uint8_t temporary_password[25]; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - class UserAuthenticate : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t card_password[25]; - uint8_t temporary_password[25]; - - bool isValid() const { - return true; - } - } __packed; - - typedef Transaction CommandTransaction; - }; - - class Authorize : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t crc[4]; - uint8_t password[25]; - } __packed; - - typedef Transaction CommandTransaction; - }; - - class UserAuthorize : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t crc[4]; - uint8_t password[25]; - } __packed; - - typedef Transaction CommandTransaction; - }; - - class UnlockUserPassword : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t admin_password[20]; // TODO - } __packed; - - // TODO could we get the stick to return the retry count? - - typedef Transaction CommandTransaction; - }; - - class ChangeUserPin : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t old_pin[25]; - uint8_t new_pin[25]; - } __packed; - - typedef Transaction CommandTransaction; - }; - - // TODO why is it needed? - class IsAESSupported : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[20]; - } __packed; - - typedef Transaction CommandTransaction; - }; - - class ChangeAdminPin : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t old_pin[25]; - uint8_t new_pin[25]; - } __packed; - - typedef Transaction CommandTransaction; - }; - - class LockDevice : semantics::non_constructible { - public: - typedef Transaction CommandTransaction; - }; - - class FactoryReset : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[20]; - } __packed; - - typedef Transaction CommandTransaction; - }; - - class BuildAESKey : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[20]; - } __packed; - - typedef Transaction CommandTransaction; - }; - } -} - -/* -* STICK20 protocol command ids -* a superset of STICK10 -*/ -namespace stick20 { - namespace command { - class EnableEncryptedPartition : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; // TODO check w/ firmware - }; - - typedef Transaction CommandTransaction; - }; - - class DisableEncryptedPartition : semantics::non_constructible { - public: - typedef Transaction CommandTransaction; - }; - - class EnableHiddenEncryptedPartition : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; // TODO check w/ firmware - }; - - typedef Transaction CommandTransaction; - }; - - class DisableHiddenEncryptedPartition : semantics::non_constructible { - public: - typedef Transaction CommandTransaction; - }; - - class EnableFirmwareUpdate : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; // TODO check w/ firmware - }; - - typedef Transaction CommandTransaction; - }; - - class UpdatePassword : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t old_password[15]; - uint8_t new_password[15]; - }; - - typedef Transaction CommandTransaction; - }; - - class ExportFirmware : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; - }; - - typedef Transaction CommandTransaction; - }; - - class CreateNewKeys : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; - }; - - typedef Transaction CommandTransaction; - }; - - class FillSDCardWithRandomChars : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t volume_flag; - uint8_t password[30]; - }; - - typedef Transaction CommandTransaction; - }; - - class SetupHiddenVolume : semantics::non_constructible { - public: - typedef Transaction CommandTransaction; - }; - - class SendPasswordMatrix : semantics::non_constructible { - public: - typedef Transaction CommandTransaction; - }; - - class SendPasswordMatrixPinData : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t pin_data[30]; // TODO how long actually can it be? - }; - - typedef Transaction CommandTransaction; - }; - - class SendPasswordMatrixSetup : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t setup_data[30]; // TODO how long actually can it be? - }; - - typedef Transaction CommandTransaction; - }; - - class GetDeviceStatus : semantics::non_constructible { - public: - typedef Transaction CommandTransaction; - }; - - class SendPassword : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; - }; - - typedef Transaction CommandTransaction; - }; - - class SendNewPassword : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; - }; - - typedef Transaction CommandTransaction; - }; - - // TODO fix original nomenclature - class SendSetReadonlyToUncryptedVolume : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; - }; - - typedef Transaction CommandTransaction; - }; - - class SendSetReadwriteToUncryptedVolume : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; - }; - - typedef Transaction CommandTransaction; - }; - - class SendClearNewSdCardFound : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; - }; - - typedef Transaction CommandTransaction; - }; - - class SendStartup : semantics::non_constructible { - public: - struct CommandPayload { - uint64_t localtime; // POSIX - }; - - typedef Transaction CommandTransaction; - }; - - class SendHiddenVolumeSetup : semantics::non_constructible { - public: - struct CommandPayload { - // TODO HiddenVolumeSetup_tst type - }; - - typedef Transaction CommandTransaction; - }; - - class LockFirmware : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; - }; - - typedef Transaction CommandTransaction; - }; - - class ProductionTest : semantics::non_constructible { - public: - typedef Transaction CommandTransaction; - }; - } } } - #endif diff --git a/include/dissect.h b/include/dissect.h new file mode 100644 index 0000000..db3186b --- /dev/null +++ b/include/dissect.h @@ -0,0 +1,60 @@ +/* + * Protocol packet dissection + */ +#ifndef DISSECT_H +#define DISSECT_H +#include +#include +#include "misc.h" +#include "cxx_semantics.h" +#include "command_id.h" +#include "device_proto.h" + +namespace nitrokey { +namespace proto { + +template +class QueryDissector : semantics::non_constructible { +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 << "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(); + } +}; + +template +class ResponseDissector : semantics::non_constructible { +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 << "Device status:\t" << 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 << std::endl; + out << "CRC:\t" << pod.crc << std::endl; + + out << "Payload:" << std::endl; + out << pod.payload.dissect(); + return out.str(); + } +}; + + +} +} + +#endif diff --git a/include/inttypes.h b/include/inttypes.h new file mode 100644 index 0000000..de2cc83 --- /dev/null +++ b/include/inttypes.h @@ -0,0 +1,522 @@ +/* Copyright (c) 2004,2005,2007 Joerg Wunsch Copyright (c) 2005, Carlos Lamas All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* $Id: inttypes.h 1766 2008-10-17 21:33:57Z arcanum $ */ + +#ifndef __INTTYPES_H_ +#define __INTTYPES_H_ + +#include + +/** \file */ +/** \defgroup avr_inttypes : Integer Type conversions + \code #include \endcode + + This header file includes the exact-width integer definitions from + , and extends them with additional facilities + provided by the implementation. + + Currently, the extensions include two additional integer types + that could hold a "far" pointer (i.e. a code pointer that can + address more than 64 KB), as well as standard names for all printf + and scanf formatting options that are supported by the \ref avr_stdio. + As the library does not support the full range of conversion + specifiers from ISO 9899:1999, only those conversions that are + actually implemented will be listed here. + + The idea behind these conversion macros is that, for each of the + types defined by , a macro will be supplied that portably + allows formatting an object of that type in printf() or scanf() + operations. Example: + + \code + #include + + uint8_t smallval; + int32_t longval; + ... + printf("The hexadecimal value of smallval is %" PRIx8 + ", the decimal value of longval is %" PRId32 ".\n", + smallval, longval); + \endcode +*/ + +/** \name Far pointers for memory access >64K */ + +/* @{ */ +/** \ingroup avr_inttypes + signed integer type that can hold a pointer > 64 KB */ +typedef int32_t int_farptr_t; + +/** \ingroup avr_inttypes + unsigned integer type that can hold a pointer > 64 KB */ +typedef uint32_t uint_farptr_t; + +/* @} */ + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) + + +/** \name macros for printf and scanf format specifiers + + For C++, these are only included if __STDC_LIMIT_MACROS + is defined before including . + */ + +/* @{ */ +/** \ingroup avr_inttypes + decimal printf format for int8_t */ +#define PRId8 "d" +/** \ingroup avr_inttypes + decimal printf format for int_least8_t */ +#define PRIdLEAST8 "d" +/** \ingroup avr_inttypes + decimal printf format for int_fast8_t */ +#define PRIdFAST8 "d" + +/** \ingroup avr_inttypes + integer printf format for int8_t */ +#define PRIi8 "i" +/** \ingroup avr_inttypes + integer printf format for int_least8_t */ +#define PRIiLEAST8 "i" +/** \ingroup avr_inttypes + integer printf format for int_fast8_t */ +#define PRIiFAST8 "i" + + +/** \ingroup avr_inttypes + decimal printf format for int16_t */ +#define PRId16 "d" +/** \ingroup avr_inttypes + decimal printf format for int_least16_t */ +#define PRIdLEAST16 "d" +/** \ingroup avr_inttypes + decimal printf format for int_fast16_t */ +#define PRIdFAST16 "d" + +/** \ingroup avr_inttypes + integer printf format for int16_t */ +#define PRIi16 "i" +/** \ingroup avr_inttypes + integer printf format for int_least16_t */ +#define PRIiLEAST16 "i" +/** \ingroup avr_inttypes + integer printf format for int_fast16_t */ +#define PRIiFAST16 "i" + + +/** \ingroup avr_inttypes + decimal printf format for int32_t */ +#define PRId32 "ld" +/** \ingroup avr_inttypes + decimal printf format for int_least32_t */ +#define PRIdLEAST32 "ld" +/** \ingroup avr_inttypes + decimal printf format for int_fast32_t */ +#define PRIdFAST32 "ld" + +/** \ingroup avr_inttypes + integer printf format for int32_t */ +#define PRIi32 "li" +/** \ingroup avr_inttypes + integer printf format for int_least32_t */ +#define PRIiLEAST32 "li" +/** \ingroup avr_inttypes + integer printf format for int_fast32_t */ +#define PRIiFAST32 "li" + + +#ifdef __avr_libc_does_not_implement_long_long_in_printf_or_scanf + +#define PRId64 "lld" +#define PRIdLEAST64 "lld" +#define PRIdFAST64 "lld" + +#define PRIi64 "lli" +#define PRIiLEAST64 "lli" +#define PRIiFAST64 "lli" + + +#define PRIdMAX "lld" +#define PRIiMAX "lli" + +#endif + +/** \ingroup avr_inttypes + decimal printf format for intptr_t */ +#define PRIdPTR PRId16 +/** \ingroup avr_inttypes + integer printf format for intptr_t */ +#define PRIiPTR PRIi16 + +/** \ingroup avr_inttypes + octal printf format for uint8_t */ +#define PRIo8 "o" +/** \ingroup avr_inttypes + octal printf format for uint_least8_t */ +#define PRIoLEAST8 "o" +/** \ingroup avr_inttypes + octal printf format for uint_fast8_t */ +#define PRIoFAST8 "o" + +/** \ingroup avr_inttypes + decimal printf format for uint8_t */ +#define PRIu8 "u" +/** \ingroup avr_inttypes + decimal printf format for uint_least8_t */ +#define PRIuLEAST8 "u" +/** \ingroup avr_inttypes + decimal printf format for uint_fast8_t */ +#define PRIuFAST8 "u" + +/** \ingroup avr_inttypes + hexadecimal printf format for uint8_t */ +#define PRIx8 "x" +/** \ingroup avr_inttypes + hexadecimal printf format for uint_least8_t */ +#define PRIxLEAST8 "x" +/** \ingroup avr_inttypes + hexadecimal printf format for uint_fast8_t */ +#define PRIxFAST8 "x" + +/** \ingroup avr_inttypes + uppercase hexadecimal printf format for uint8_t */ +#define PRIX8 "X" +/** \ingroup avr_inttypes + uppercase hexadecimal printf format for uint_least8_t */ +#define PRIXLEAST8 "X" +/** \ingroup avr_inttypes + uppercase hexadecimal printf format for uint_fast8_t */ +#define PRIXFAST8 "X" + + +/** \ingroup avr_inttypes + octal printf format for uint16_t */ +#define PRIo16 "o" +/** \ingroup avr_inttypes + octal printf format for uint_least16_t */ +#define PRIoLEAST16 "o" +/** \ingroup avr_inttypes + octal printf format for uint_fast16_t */ +#define PRIoFAST16 "o" + +/** \ingroup avr_inttypes + decimal printf format for uint16_t */ +#define PRIu16 "u" +/** \ingroup avr_inttypes + decimal printf format for uint_least16_t */ +#define PRIuLEAST16 "u" +/** \ingroup avr_inttypes + decimal printf format for uint_fast16_t */ +#define PRIuFAST16 "u" + +/** \ingroup avr_inttypes + hexadecimal printf format for uint16_t */ +#define PRIx16 "x" +/** \ingroup avr_inttypes + hexadecimal printf format for uint_least16_t */ +#define PRIxLEAST16 "x" +/** \ingroup avr_inttypes + hexadecimal printf format for uint_fast16_t */ +#define PRIxFAST16 "x" + +/** \ingroup avr_inttypes + uppercase hexadecimal printf format for uint16_t */ +#define PRIX16 "X" +/** \ingroup avr_inttypes + uppercase hexadecimal printf format for uint_least16_t */ +#define PRIXLEAST16 "X" +/** \ingroup avr_inttypes + uppercase hexadecimal printf format for uint_fast16_t */ +#define PRIXFAST16 "X" + + +/** \ingroup avr_inttypes + octal printf format for uint32_t */ +#define PRIo32 "lo" +/** \ingroup avr_inttypes + octal printf format for uint_least32_t */ +#define PRIoLEAST32 "lo" +/** \ingroup avr_inttypes + octal printf format for uint_fast32_t */ +#define PRIoFAST32 "lo" + +/** \ingroup avr_inttypes + decimal printf format for uint32_t */ +#define PRIu32 "lu" +/** \ingroup avr_inttypes + decimal printf format for uint_least32_t */ +#define PRIuLEAST32 "lu" +/** \ingroup avr_inttypes + decimal printf format for uint_fast32_t */ +#define PRIuFAST32 "lu" + +/** \ingroup avr_inttypes + hexadecimal printf format for uint32_t */ +#define PRIx32 "lx" +/** \ingroup avr_inttypes + hexadecimal printf format for uint_least32_t */ +#define PRIxLEAST32 "lx" +/** \ingroup avr_inttypes + hexadecimal printf format for uint_fast32_t */ +#define PRIxFAST32 "lx" + +/** \ingroup avr_inttypes + uppercase hexadecimal printf format for uint32_t */ +#define PRIX32 "lX" +/** \ingroup avr_inttypes + uppercase hexadecimal printf format for uint_least32_t */ +#define PRIXLEAST32 "lX" +/** \ingroup avr_inttypes + uppercase hexadecimal printf format for uint_fast32_t */ +#define PRIXFAST32 "lX" + + +#ifdef __avr_libc_does_not_implement_long_long_in_printf_or_scanf + +#define PRIo64 "llo" +#define PRIoLEAST64 "llo" +#define PRIoFAST64 "llo" + +#define PRIu64 "llu" +#define PRIuLEAST64 "llu" +#define PRIuFAST64 "llu" + +#define PRIx64 "llx" +#define PRIxLEAST64 "llx" +#define PRIxFAST64 "llx" + +#define PRIX64 "llX" +#define PRIXLEAST64 "llX" +#define PRIXFAST64 "llX" + +#define PRIoMAX "llo" +#define PRIuMAX "llu" +#define PRIxMAX "llx" +#define PRIXMAX "llX" + +#endif + +/** \ingroup avr_inttypes + octal printf format for uintptr_t */ +#define PRIoPTR PRIo16 +/** \ingroup avr_inttypes + decimal printf format for uintptr_t */ +#define PRIuPTR PRIu16 +/** \ingroup avr_inttypes + hexadecimal printf format for uintptr_t */ +#define PRIxPTR PRIx16 +/** \ingroup avr_inttypes + uppercase hexadecimal printf format for uintptr_t */ +#define PRIXPTR PRIX16 + + +#ifdef __avr_libc_does_not_implement_hh_in_scanf + +#define SCNd8 "hhd" +#define SCNdLEAST8 "hhd" +#define SCNdFAST8 "hhd" + +#define SCNi8 "hhi" +#define SCNiLEAST8 "hhi" +#define SCNiFAST8 "hhi" + +#endif + + +/** \ingroup avr_inttypes + decimal scanf format for int16_t */ +#define SCNd16 "d" +/** \ingroup avr_inttypes + decimal scanf format for int_least16_t */ +#define SCNdLEAST16 "d" +/** \ingroup avr_inttypes + decimal scanf format for int_fast16_t */ +#define SCNdFAST16 "d" + +/** \ingroup avr_inttypes + generic-integer scanf format for int16_t */ +#define SCNi16 "i" +/** \ingroup avr_inttypes + generic-integer scanf format for int_least16_t */ +#define SCNiLEAST16 "i" +/** \ingroup avr_inttypes + generic-integer scanf format for int_fast16_t */ +#define SCNiFAST16 "i" + + +/** \ingroup avr_inttypes + decimal scanf format for int32_t */ +#define SCNd32 "ld" +/** \ingroup avr_inttypes + decimal scanf format for int_least32_t */ +#define SCNdLEAST32 "ld" +/** \ingroup avr_inttypes + decimal scanf format for int_fast32_t */ +#define SCNdFAST32 "ld" + +/** \ingroup avr_inttypes + generic-integer scanf format for int32_t */ +#define SCNi32 "li" +/** \ingroup avr_inttypes + generic-integer scanf format for int_least32_t */ +#define SCNiLEAST32 "li" +/** \ingroup avr_inttypes + generic-integer scanf format for int_fast32_t */ +#define SCNiFAST32 "li" + + +#ifdef __avr_libc_does_not_implement_long_long_in_printf_or_scanf + +#define SCNd64 "lld" +#define SCNdLEAST64 "lld" +#define SCNdFAST64 "lld" + +#define SCNi64 "lli" +#define SCNiLEAST64 "lli" +#define SCNiFAST64 "lli" + +#define SCNdMAX "lld" +#define SCNiMAX "lli" + +#endif + +/** \ingroup avr_inttypes + decimal scanf format for intptr_t */ +#define SCNdPTR SCNd16 +/** \ingroup avr_inttypes + generic-integer scanf format for intptr_t */ +#define SCNiPTR SCNi16 + +#ifdef __avr_libc_does_not_implement_hh_in_scanf + +#define SCNo8 "hho" +#define SCNoLEAST8 "hho" +#define SCNoFAST8 "hho" + +#define SCNu8 "hhu" +#define SCNuLEAST8 "hhu" +#define SCNuFAST8 "hhu" + +#define SCNx8 "hhx" +#define SCNxLEAST8 "hhx" +#define SCNxFAST8 "hhx" + +#endif + +/** \ingroup avr_inttypes + octal scanf format for uint16_t */ +#define SCNo16 "o" +/** \ingroup avr_inttypes + octal scanf format for uint_least16_t */ +#define SCNoLEAST16 "o" +/** \ingroup avr_inttypes + octal scanf format for uint_fast16_t */ +#define SCNoFAST16 "o" + +/** \ingroup avr_inttypes + decimal scanf format for uint16_t */ +#define SCNu16 "u" +/** \ingroup avr_inttypes + decimal scanf format for uint_least16_t */ +#define SCNuLEAST16 "u" +/** \ingroup avr_inttypes + decimal scanf format for uint_fast16_t */ +#define SCNuFAST16 "u" + +/** \ingroup avr_inttypes + hexadecimal scanf format for uint16_t */ +#define SCNx16 "x" +/** \ingroup avr_inttypes + hexadecimal scanf format for uint_least16_t */ +#define SCNxLEAST16 "x" +/** \ingroup avr_inttypes + hexadecimal scanf format for uint_fast16_t */ +#define SCNxFAST16 "x" + + +/** \ingroup avr_inttypes + octal scanf format for uint32_t */ +#define SCNo32 "lo" +/** \ingroup avr_inttypes + octal scanf format for uint_least32_t */ +#define SCNoLEAST32 "lo" +/** \ingroup avr_inttypes + octal scanf format for uint_fast32_t */ +#define SCNoFAST32 "lo" + +/** \ingroup avr_inttypes + decimal scanf format for uint32_t */ +#define SCNu32 "lu" +/** \ingroup avr_inttypes + decimal scanf format for uint_least32_t */ +#define SCNuLEAST32 "lu" +/** \ingroup avr_inttypes + decimal scanf format for uint_fast32_t */ +#define SCNuFAST32 "lu" + +/** \ingroup avr_inttypes + hexadecimal scanf format for uint32_t */ +#define SCNx32 "lx" +/** \ingroup avr_inttypes + hexadecimal scanf format for uint_least32_t */ +#define SCNxLEAST32 "lx" +/** \ingroup avr_inttypes + hexadecimal scanf format for uint_fast32_t */ +#define SCNxFAST32 "lx" + + +#ifdef __avr_libc_does_not_implement_long_long_in_printf_or_scanf + +#define SCNo64 "llo" +#define SCNoLEAST64 "llo" +#define SCNoFAST64 "llo" + +#define SCNu64 "llu" +#define SCNuLEAST64 "llu" +#define SCNuFAST64 "llu" + +#define SCNx64 "llx" +#define SCNxLEAST64 "llx" +#define SCNxFAST64 "llx" + +#define SCNoMAX "llo" +#define SCNuMAX "llu" +#define SCNxMAX "llx" + +#endif + +/** \ingroup avr_inttypes + octal scanf format for uintptr_t */ +#define SCNoPTR SCNo16 +/** \ingroup avr_inttypes + decimal scanf format for uintptr_t */ +#define SCNuPTR SCNu16 +/** \ingroup avr_inttypes + hexadecimal scanf format for uintptr_t */ +#define SCNxPTR SCNx16 + +/* @} */ + + +#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */ + + +#endif /* __INTTYPES_H_ */ diff --git a/include/log.h b/include/log.h new file mode 100644 index 0000000..f6f7193 --- /dev/null +++ b/include/log.h @@ -0,0 +1,63 @@ +#ifndef LOG_H +#define LOG_H +#include +#include + +namespace nitrokey { +namespace log { + +enum class Loglevel : int { + DEBUG_L2, + DEBUG, + INFO, + WARNING, + ERROR +}; + +class LogHandler { +public: + virtual void print(const std::string &, Loglevel lvl) = 0; + +protected: + std::string loglevel_to_str(Loglevel); +}; + +class StdlogHandler : public LogHandler { +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) {} + + static Log &instance() { + if (mp_instance == NULL) + mp_instance = new Log; + return *mp_instance; + } + + void operator()(const std::string &, Loglevel); + + void set_loglevel(Loglevel lvl) { + m_loglevel = lvl; + } + + void set_handler(LogHandler *handler) { + mp_loghandler = handler; + } + +private: + Loglevel m_loglevel; + LogHandler *mp_loghandler; + + static Log *mp_instance; +}; + +} +} + +#endif diff --git a/include/misc.h b/include/misc.h new file mode 100644 index 0000000..bf68915 --- /dev/null +++ b/include/misc.h @@ -0,0 +1,15 @@ +#ifndef MISC_H +#define MISC_H +#include +#include + +namespace nitrokey { +namespace misc { + +std::string hexdump(const char *p, size_t size); +uint32_t stm_crc32(const uint8_t *data, size_t size); + +} +} + +#endif diff --git a/include/stick10_commands.h b/include/stick10_commands.h new file mode 100644 index 0000000..de31e95 --- /dev/null +++ b/include/stick10_commands.h @@ -0,0 +1,582 @@ +#ifndef STICK10_COMMANDS_H +#define STICK10_COMMANDS_H +#include +#include +#include "inttypes.h" +#include "command.h" + +namespace nitrokey { +namespace proto { + +/* + * Stick10 protocol definition + */ +namespace stick10 { + class GetSlotName : public Command { + 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 CommandTransaction; + }; + + class EraseSlot : Command { + public: + struct CommandPayload { + uint8_t slot_number; + + bool isValid() const { + return !(slot_number & 0xF0); + } + } __packed; + + typedef Transaction CommandTransaction; + }; + + class SetTime : Command { + 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 CommandTransaction; + }; + + // TODO duplicate TOTP + class WriteToHOTPSlot : Command { + 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 CommandTransaction; + }; + + class WriteToTOTPSlot : Command { + 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 CommandTransaction; + }; + + class GetCode : Command { + public: + struct CommandPayload { + uint8_t slot_number; + uint64_t challenge; + uint64_t last_totp_time; + uint8_t last_interval; + + bool isValid() const { + return !(slot_number & 0xF0); + } + } __packed; + + struct ResponsePayload { + uint8_t code[18]; + + bool isValid() const { + return true; + } + } __packed; + + typedef Transaction CommandTransaction; + }; + + class GetHOTP : Command { + public: + struct CommandPayload { + uint8_t slot_number; + + bool isValid() const { + return !(slot_number & 0xF0); + } + } __packed; + + typedef Transaction CommandTransaction; + }; + + class ReadSlot : Command { + 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 CommandTransaction; + }; + + class GetStatus : Command { + 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 CommandTransaction; + }; + + class GetPasswordRetryCount : Command { + public: + struct ResponsePayload { + uint8_t password_retry_count; + + bool isValid() const { + return true; + } + } __packed; + + typedef Transaction CommandTransaction; + }; + + class GetUserPasswordRetryCount : Command { + public: + struct ResponsePayload { + uint8_t password_retry_count; + + bool isValid() const { + return true; + } + } __packed; + + typedef Transaction CommandTransaction; + }; + + class GetPasswordSafeSlotStatus : Command { + public: + struct ResponsePayload { + uint8_t password_safe_status[PWS_SLOT_COUNT]; + + bool isValid() const { + return true; + } + } __packed; + + typedef Transaction CommandTransaction; + }; + + class GetPasswordSafeSlotName : Command { + 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 CommandTransaction; + }; + + class GetPasswordSafeSlotPassword : Command { + 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 CommandTransaction; + }; + + class GetPasswordSafeSlotLogin : Command { + 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 CommandTransaction; + }; + + class SetPasswordSafeSlotData : Command { + 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 CommandTransaction; + }; + + class SetPasswordSafeSlotData2 : Command { + public: + struct CommandPayload { + uint8_t slot_number; + uint8_t slot_name[PWS_SLOTNAME_LENGTH]; + + bool isValid() const { + return !(slot_number & 0xF0); + } + } __packed; + + typedef Transaction CommandTransaction; + }; + + class ErasePasswordSafeSlot : Command { + public: + struct CommandPayload { + uint8_t slot_number; + + bool isValid() const { + return !(slot_number & 0xF0); + } + } __packed; + + typedef Transaction CommandTransaction; + }; + + class EnablePasswordSafe : Command { + public: + struct CommandPayload { + uint8_t password[30]; + + bool isValid() const { + return true; + } + } __packed; + + typedef Transaction CommandTransaction; + }; + + class PasswordSafeInitKey : Command { + public: + typedef Transaction CommandTransaction; + }; + + // TODO naming screwed up, see above + class PasswordSafeSendSlotViaHID: Command { + public: + struct CommandPayload { + uint8_t slot_number; + uint8_t slot_kind; + + bool isValid() const { + return !(slot_number & 0xF0); + } + } __packed; + + typedef Transaction CommandTransaction; + }; + + + // TODO "Device::passwordSafeSendSlotDataViaHID" + + class WriteGeneralConfig : Command { + public: + struct CommandPayload { + uint8_t config[5]; + } __packed; + + typedef Transaction CommandTransaction; + }; + + class FirstAuthenticate : Command { + 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 CommandTransaction; + }; + + class UserAuthenticate : Command { + public: + struct CommandPayload { + uint8_t card_password[25]; + uint8_t temporary_password[25]; + + bool isValid() const { + return true; + } + } __packed; + + typedef Transaction CommandTransaction; + }; + + class Authorize : Command { + public: + struct CommandPayload { + uint8_t crc[4]; + uint8_t password[25]; + } __packed; + + typedef Transaction CommandTransaction; + }; + + class UserAuthorize : Command { + public: + struct CommandPayload { + uint8_t crc[4]; + uint8_t password[25]; + } __packed; + + typedef Transaction CommandTransaction; + }; + + class UnlockUserPassword : Command { + public: + struct CommandPayload { + uint8_t admin_password[20]; // TODO + } __packed; + + // TODO could we get the stick to return the retry count? + + typedef Transaction CommandTransaction; + }; + + class ChangeUserPin : Command { + public: + struct CommandPayload { + uint8_t old_pin[25]; + uint8_t new_pin[25]; + } __packed; + + typedef Transaction CommandTransaction; + }; + + // TODO why is it needed? + class IsAESSupported : Command { + public: + struct CommandPayload { + uint8_t password[20]; + } __packed; + + typedef Transaction CommandTransaction; + }; + + class ChangeAdminPin : Command { + public: + struct CommandPayload { + uint8_t old_pin[25]; + uint8_t new_pin[25]; + } __packed; + + typedef Transaction CommandTransaction; + }; + + class LockDevice : Command { + public: + typedef Transaction CommandTransaction; + }; + + class FactoryReset : Command { + public: + struct CommandPayload { + uint8_t password[20]; + } __packed; + + typedef Transaction CommandTransaction; + }; + + class BuildAESKey : Command { + public: + struct CommandPayload { + uint8_t password[20]; + } __packed; + + typedef Transaction CommandTransaction; + }; +} + +} +} +#endif diff --git a/include/stick20_commands.h b/include/stick20_commands.h new file mode 100644 index 0000000..22b7e9a --- /dev/null +++ b/include/stick20_commands.h @@ -0,0 +1,249 @@ +#ifndef STICK20_COMMANDS_H +#define STICK20_COMMANDS_H +#include "inttypes.h" + +namespace nitrokey { +namespace proto { + +/* +* STICK20 protocol command ids +* a superset of STICK10 +*/ +namespace stick20 { + class EnableEncryptedPartition : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; // TODO check w/ firmware + }; + + typedef Transaction CommandTransaction; + }; + + class DisableEncryptedPartition : semantics::non_constructible { + public: + typedef Transaction CommandTransaction; + }; + + class EnableHiddenEncryptedPartition : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; // TODO check w/ firmware + }; + + typedef Transaction CommandTransaction; + }; + + class DisableHiddenEncryptedPartition : semantics::non_constructible { + public: + typedef Transaction CommandTransaction; + }; + + class EnableFirmwareUpdate : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; // TODO check w/ firmware + }; + + typedef Transaction CommandTransaction; + }; + + class UpdatePassword : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t old_password[15]; + uint8_t new_password[15]; + }; + + typedef Transaction CommandTransaction; + }; + + class ExportFirmware : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; + }; + + typedef Transaction CommandTransaction; + }; + + class CreateNewKeys : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; + }; + + typedef Transaction CommandTransaction; + }; + + class FillSDCardWithRandomChars : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t volume_flag; + uint8_t password[30]; + }; + + typedef Transaction CommandTransaction; + }; + + class SetupHiddenVolume : semantics::non_constructible { + public: + typedef Transaction CommandTransaction; + }; + + class SendPasswordMatrix : semantics::non_constructible { + public: + typedef Transaction CommandTransaction; + }; + + class SendPasswordMatrixPinData : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t pin_data[30]; // TODO how long actually can it be? + }; + + typedef Transaction CommandTransaction; + }; + + class SendPasswordMatrixSetup : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t setup_data[30]; // TODO how long actually can it be? + }; + + typedef Transaction CommandTransaction; + }; + + class GetDeviceStatus : semantics::non_constructible { + public: + typedef Transaction CommandTransaction; + }; + + class SendPassword : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; + }; + + typedef Transaction CommandTransaction; + }; + + class SendNewPassword : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; + }; + + typedef Transaction CommandTransaction; + }; + + // TODO fix original nomenclature + class SendSetReadonlyToUncryptedVolume : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; + }; + + typedef Transaction CommandTransaction; + }; + + class SendSetReadwriteToUncryptedVolume : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; + }; + + typedef Transaction CommandTransaction; + }; + + class SendClearNewSdCardFound : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; + }; + + typedef Transaction CommandTransaction; + }; + + class SendStartup : semantics::non_constructible { + public: + struct CommandPayload { + uint64_t localtime; // POSIX + }; + + typedef Transaction CommandTransaction; + }; + + class SendHiddenVolumeSetup : semantics::non_constructible { + public: + struct CommandPayload { + // TODO HiddenVolumeSetup_tst type + }; + + typedef Transaction CommandTransaction; + }; + + class LockFirmware : semantics::non_constructible { + public: + struct CommandPayload { + uint8_t password[30]; + }; + + typedef Transaction CommandTransaction; + }; + + class ProductionTest : semantics::non_constructible { + public: + typedef Transaction CommandTransaction; + }; + +} +} +} + +#endif -- cgit v1.2.1