diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/CommandFailedException.h | 5 | ||||
-rw-r--r-- | include/LibraryException.h | 6 | ||||
-rw-r--r-- | include/NitrokeyManager.h | 6 | ||||
-rw-r--r-- | include/command_id.h | 42 | ||||
-rw-r--r-- | include/device.h | 6 | ||||
-rw-r--r-- | include/device_proto.h | 480 | ||||
-rw-r--r-- | include/dissect.h | 10 | ||||
-rw-r--r-- | include/stick10_commands.h | 14 | ||||
-rw-r--r-- | include/stick20_commands.h | 50 |
9 files changed, 385 insertions, 234 deletions
diff --git a/include/CommandFailedException.h b/include/CommandFailedException.h index 3306f7b..9b0c59e 100644 --- a/include/CommandFailedException.h +++ b/include/CommandFailedException.h @@ -7,6 +7,7 @@ #include <exception> #include <cstdint> +#include <log.h> class CommandFailedException : public std::exception { public: @@ -15,7 +16,9 @@ public: CommandFailedException(uint8_t last_command_code, uint8_t last_command_status) : last_command_code(last_command_code), - last_command_status(last_command_status){} + last_command_status(last_command_status){ + nitrokey::log::Log::instance()(std::string("CommandFailedException, status: ")+ std::to_string(last_command_status), nitrokey::log::Loglevel::DEBUG); + } virtual const char *what() const throw() { return "Command execution has failed on device"; diff --git a/include/LibraryException.h b/include/LibraryException.h index 72891fb..3c3fab4 100644 --- a/include/LibraryException.h +++ b/include/LibraryException.h @@ -4,6 +4,7 @@ #include <exception> #include <cstdint> #include <string> +#include "log.h" class LibraryException: std::exception { public: @@ -83,7 +84,10 @@ public: std::string message; TooLongStringException(size_t size_source, size_t size_destination, const std::string &message = "") : size_source( - size_source), size_destination(size_destination), message(message) {} + size_source), size_destination(size_destination), message(message) { + nitrokey::log::Log::instance()(std::string("TooLongStringException, size diff: ")+ std::to_string(size_source-size_destination), nitrokey::log::Loglevel::DEBUG); + + } virtual const char *what() const throw() override { //TODO add sizes and message data to final message diff --git a/include/NitrokeyManager.h b/include/NitrokeyManager.h index 1e518f4..52c18d7 100644 --- a/include/NitrokeyManager.h +++ b/include/NitrokeyManager.h @@ -22,9 +22,9 @@ namespace nitrokey { static shared_ptr <NitrokeyManager> instance(); bool first_authenticate(const char *pin, const char *temporary_password); - bool write_HOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint8_t hotp_counter, - bool use_8_digits, bool use_enter, bool use_tokenID, const char *token_ID, - const char *temporary_password); + bool write_HOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint64_t hotp_counter, + bool use_8_digits, bool use_enter, bool use_tokenID, const char *token_ID, + const char *temporary_password); bool write_TOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint16_t time_window, bool use_8_digits, bool use_enter, bool use_tokenID, const char *token_ID, const char *temporary_password); diff --git a/include/command_id.h b/include/command_id.h index 87d270e..8148cc1 100644 --- a/include/command_id.h +++ b/include/command_id.h @@ -4,8 +4,42 @@ namespace nitrokey { namespace proto { - -#define STICK20_CMD_START_VALUE 0x20 + namespace stick20 { + enum class device_status : uint8_t { + idle = 0, + ok, + busy, + wrong_password, + busy_progressbar, + password_matrix_ready, + no_user_password_unlock, + smartcard_error, + security_bit_active + }; + const int CMD_START_VALUE = 0x20; + const int CMD_END_VALUE = 0x60; + } + namespace stick10 { + enum class command_status : uint8_t { + ok = 0, + wrong_CRC, + wrong_slot, + slot_not_programmed, + wrong_password = 4, + not_authorized, + timestamp_warning, + no_name_error, + not_supported, + unknown_command, + AES_dec_failed + }; + enum class device_status : uint8_t { + ok = 0, + busy = 1, + error, + received_report, + }; + } enum class CommandID : uint8_t { @@ -32,8 +66,8 @@ enum class CommandID : uint8_t { CHANGE_USER_PIN = 0x14, CHANGE_ADMIN_PIN = 0x15, - STICK20_CMD_SEND_PASSWORD = STICK20_CMD_START_VALUE + 18, - STICK20_CMD_SEND_NEW_PASSWORD = STICK20_CMD_START_VALUE + 19, + STICK20_CMD_SEND_PASSWORD = stick20::CMD_START_VALUE + 18, + STICK20_CMD_SEND_NEW_PASSWORD = stick20::CMD_START_VALUE + 19, ENABLE_CRYPTED_PARI = 0x20, DISABLE_CRYPTED_PARI, diff --git a/include/device.h b/include/device.h index 67b739c..34b7a5b 100644 --- a/include/device.h +++ b/include/device.h @@ -38,7 +38,8 @@ public: */ virtual int recv(void *packet); - int get_retry_count() const { return m_retry_count; }; + int get_retry_receiving_count() const { return m_retry_receiving_count; }; + int get_retry_sending_count() const { return m_retry_sending_count; }; std::chrono::milliseconds get_retry_timeout() const { return m_retry_timeout; }; std::chrono::milliseconds get_send_receive_delay() const {return m_send_receive_delay;} @@ -59,7 +60,8 @@ private: * library, there's no way of doing it asynchronously, * hence polling. */ - int m_retry_count; + int m_retry_sending_count; + int m_retry_receiving_count; std::chrono::milliseconds m_retry_timeout; std::chrono::milliseconds m_send_receive_delay; diff --git a/include/device_proto.h b/include/device_proto.h index 4044cdc..45f165b 100644 --- a/include/device_proto.h +++ b/include/device_proto.h @@ -1,5 +1,6 @@ #ifndef DEVICE_PROTO_H #define DEVICE_PROTO_H + #include <utility> #include <thread> #include <type_traits> @@ -31,7 +32,7 @@ #define PWS_SEND_CR 3 namespace nitrokey { -namespace proto { + namespace proto { /* * POD types for HID proto commands * Instances are meant to be __packed. @@ -42,45 +43,45 @@ namespace proto { /* * Every packet is a USB HID report (check USB spec) */ -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); - } -} __packed; + 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); + } + } __packed; /* * Response payload (the parametrized type inside struct HIDReport) @@ -88,175 +89,238 @@ struct HIDReport { * command_id member in incoming HIDReport structure carries the command * type last used. */ -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); - } -} __packed; - -struct EmptyPayload { - uint8_t _data[]; - - bool isValid() const { return true; } - - std::string dissect() const { return std::string("Empty Payload."); } -} __packed; - -template <typename command_packet, typename response_payload> -class ClearingProxy{ -public: - ClearingProxy(command_packet &p){ - packet = p; - bzero(&p, sizeof(p)); - } - ~ClearingProxy(){ - bzero(&packet, sizeof(packet)); - } - - response_payload & data() { - return packet.payload; - } - - command_packet packet; -}; - -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 uint32_t getCRC( - const command_payload &payload) { - OutgoingPacket outp; - outp.initialize(); - outp.payload = payload; - outp.update_CRC(); - return outp.crc; - } - - template <typename T> - static void clear_packet(T &st){ - bzero(&st, sizeof(st)); - } - - - static ClearingProxy<ResponsePacket, response_payload> run(device::Device &dev, - const command_payload &payload) { - using namespace ::nitrokey::device; - using namespace ::nitrokey::log; - using namespace std::chrono_literals; - - Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); - - int 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 (status <= 0) - throw std::runtime_error( - std::string("Device error while sending command ") + - std::to_string((int)(status))); - - std::this_thread::sleep_for(dev.get_send_receive_delay()); - - // FIXME make checks done in device:recv here - int retry = dev.get_retry_count(); - while (retry-- > 0) { - status = dev.recv(&resp); - - dev.set_last_command_status(resp.last_command_status); // FIXME should be handled on device.recv - - if (resp.device_status == 0 && resp.last_command_crc == outp.crc) break; - Log::instance()("Device is not ready or received packet's last CRC is not equal to sent CRC packet, retrying...", + 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; + struct { + uint8_t _storage_status_padding[20 - 8 + 1]; //starts on 20th byte minus already 8 used + zero byte + uint8_t command_counter; + uint8_t command_id; + uint8_t device_status; //@see stick20::device_status + uint8_t progress_bar_value; + } storage_status __packed; + } __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 crc != 0; + } + + operator std::string() const { + return ResponseDissector<cmd_id, decltype(*this)>::dissect(*this); + } + } __packed; + + struct EmptyPayload { + uint8_t _data[]; + + bool isValid() const { return true; } + + std::string dissect() const { return std::string("Empty Payload."); } + } __packed; + + template<typename command_packet, typename response_payload> + class ClearingProxy { + public: + ClearingProxy(command_packet &p) { + packet = p; + bzero(&p, sizeof(p)); + } + + ~ClearingProxy() { + bzero(&packet, sizeof(packet)); + } + + response_payload &data() { + return packet.payload; + } + + command_packet packet; + }; + + 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 uint32_t getCRC( + const command_payload &payload) { + OutgoingPacket outp; + outp.initialize(); + outp.payload = payload; + outp.update_CRC(); + return outp.crc; + } + + template<typename T> + static void clear_packet(T &st) { + bzero(&st, sizeof(st)); + } + + + static ClearingProxy<ResponsePacket, response_payload> run(device::Device &dev, + const command_payload &payload) { + using namespace ::nitrokey::device; + using namespace ::nitrokey::log; + using namespace std::chrono_literals; + + Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); + + int 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()(static_cast<std::string>(outp), Loglevel::DEBUG); + + if (!outp.isValid()) throw std::runtime_error("Invalid outgoing packet"); + + int receiving_retry_counter = 0; + int sending_retry_counter = dev.get_retry_sending_count(); + while (sending_retry_counter-- > 0) { + status = dev.send(&outp); + if (status <= 0) + throw std::runtime_error( + std::string("Device error while sending command ") + + std::to_string(status)); + + std::this_thread::sleep_for(dev.get_send_receive_delay()); + + // FIXME make checks done in device:recv here + receiving_retry_counter = dev.get_retry_receiving_count(); + while (receiving_retry_counter-- > 0) { + status = dev.recv(&resp); + + if (dev.get_device_model() == DeviceModel::STORAGE && + resp.command_id >= stick20::CMD_START_VALUE && + resp.command_id < stick20::CMD_END_VALUE ) { + Log::instance()(std::string("Detected storage device cmd, status: ") + + std::to_string(resp.storage_status.device_status), Loglevel::DEBUG_L2); + + resp.last_command_status = static_cast<uint8_t>(stick10::command_status::ok); + switch (static_cast<stick20::device_status>(resp.storage_status.device_status)) { + case stick20::device_status::idle : + case stick20::device_status::ok: + resp.device_status = static_cast<uint8_t>(stick10::device_status::ok); + break; + case stick20::device_status::busy: + case stick20::device_status::busy_progressbar: //TODO this will be modified later for getting progressbar status + resp.device_status = static_cast<uint8_t>(stick10::device_status::busy); + break; + case stick20::device_status::wrong_password: + resp.last_command_status = static_cast<uint8_t>(stick10::command_status::wrong_password); + resp.device_status = static_cast<uint8_t>(stick10::device_status::ok); + break; + default: + Log::instance()(std::string("Unknown storage device status, cannot translate: ") + + std::to_string(resp.storage_status.device_status), Loglevel::DEBUG); + resp.device_status = resp.storage_status.device_status; + break; + }; + } + + //SENDPASSWORD gives wrong CRC , for now rely on !=0 (TODO report) +// if (resp.device_status == 0 && resp.last_command_crc == outp.crc && resp.isCRCcorrect()) break; + if (resp.device_status == static_cast<uint8_t>(stick10::device_status::ok) && + resp.last_command_crc == outp.crc && resp.isValid()) break; + if (resp.device_status == static_cast<uint8_t>(stick10::device_status::busy)) { + receiving_retry_counter++; + Log::instance()("Status busy, not decresing receiving_retry_counter counter: " + + std::to_string(receiving_retry_counter), Loglevel::DEBUG_L2); + } + Log::instance()(std::string("Retry status - dev status, equal crc, correct CRC: ") + + std::to_string(resp.device_status) + " " + + std::to_string(resp.last_command_crc == outp.crc) + + " " + std::to_string(resp.isCRCcorrect()), Loglevel::DEBUG_L2); + + Log::instance()( + "Device is not ready or received packet's last CRC is not equal to sent CRC packet, retrying...", Loglevel::DEBUG); - Log::instance()("Invalid incoming HID packet:", Loglevel::DEBUG_L2); - Log::instance()((std::string)(resp), Loglevel::DEBUG_L2); - std::this_thread::sleep_for(dev.get_retry_timeout()); - continue; + Log::instance()("Invalid incoming HID packet:", Loglevel::DEBUG_L2); + Log::instance()(static_cast<std::string>(resp), Loglevel::DEBUG_L2); + std::this_thread::sleep_for(dev.get_retry_timeout()); + continue; + } + if (resp.device_status == 0 && resp.last_command_crc == outp.crc) break; + Log::instance()(std::string("Resending (outer loop) "), Loglevel::DEBUG_L2); + Log::instance()(std::string("sending_retry_counter count: ") + std::to_string(sending_retry_counter), + Loglevel::DEBUG); + } + + dev.set_last_command_status(resp.last_command_status); // FIXME should be handled on device.recv + + clear_packet(outp); + + if (status <= 0) + throw std::runtime_error( + std::string("Device error while executing command ") + + std::to_string(status)); + + Log::instance()("Incoming HID packet:", Loglevel::DEBUG); + Log::instance()(static_cast<std::string>(resp), Loglevel::DEBUG); + Log::instance()(std::string("receiving_retry_counter count: ") + std::to_string(receiving_retry_counter), + Loglevel::DEBUG); + + if (!resp.isValid()) throw std::runtime_error("Invalid incoming packet"); + if (receiving_retry_counter <= 0) + throw std::runtime_error( + "Maximum receiving_retry_counter count reached for receiving response from the device!"); + if (resp.last_command_status != static_cast<uint8_t>(stick10::command_status::ok)) + throw CommandFailedException(resp.command_id, resp.last_command_status); + + + // See: DeviceResponse + return resp; + } + + static ClearingProxy<ResponsePacket, response_payload> run(device::Device &dev) { + command_payload empty_payload; + return run(dev, empty_payload); + } + }; } - clear_packet(outp); - - if (status <= 0) - throw std::runtime_error( - std::string("Device error while executing command ") + - std::to_string(status)); - - Log::instance()("Incoming HID packet:", Loglevel::DEBUG); - Log::instance()((std::string)(resp), Loglevel::DEBUG); - Log::instance()(std::string("Retry count: ") + std::to_string(retry), Loglevel::DEBUG); - - if (!resp.isValid()) throw std::runtime_error("Invalid incoming packet"); - if (retry <= 0) throw std::runtime_error("Maximum retry count reached for receiving response from the device!"); - if (resp.last_command_status!=0) throw CommandFailedException(resp.command_id, resp.last_command_status); - - - // See: DeviceResponse - return resp; - } - - static ClearingProxy<ResponsePacket, 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 c83e648..59e6e9c 100644 --- a/include/dissect.h +++ b/include/dissect.h @@ -67,7 +67,7 @@ class ResponseDissector : semantics::non_constructible { out << "Device status:\t" << pod.device_status + 0 << " " << status[pod.device_status] << std::endl; - out << "Command ID:\t" << commandid_to_string((CommandID)(pod.command_id)) + out << "Command ID:\t" << commandid_to_string((CommandID)(pod.command_id)) << " hex: " << std::hex << (int)pod.command_id << std::endl; out << "Last command CRC:\t" << std::hex << std::setw(2) << std::setfill('0') @@ -77,6 +77,14 @@ class ResponseDissector : semantics::non_constructible { out << "CRC:\t" << std::hex << std::setw(2) << std::setfill('0') << pod.crc << std::endl; + out << "Storage stick status:" << std::endl; +#define d(x) out << " "#x": \t"<< std::hex << std::setw(2) \ + << std::setfill('0')<< static_cast<int>(x) << std::endl; + d(pod.storage_status.command_counter); + d(pod.storage_status.command_id); + d(pod.storage_status.device_status); + d(pod.storage_status.progress_bar_value); +#undef d out << "Payload:" << std::endl; out << pod.payload.dissect(); diff --git a/include/stick10_commands.h b/include/stick10_commands.h index a60be59..a947e1e 100644 --- a/include/stick10_commands.h +++ b/include/stick10_commands.h @@ -111,7 +111,8 @@ class WriteToHOTPSlot : Command<CommandID::WRITE_TO_SLOT> { std::stringstream ss; ss << "slot_number:\t" << (int)(slot_number) << std::endl; ss << "slot_name:\t" << slot_name << std::endl; - ss << "slot_secret:\t" << slot_secret << std::endl; + ss << "slot_secret:" << std::endl + << ::nitrokey::misc::hexdump((const char *)(&slot_secret), sizeof slot_secret); ss << "slot_config:\t" << std::bitset<8>((int)_slot_config) << std::endl; ss << "\tuse_8_digits(0):\t" << use_8_digits << std::endl; ss << "\tuse_enter(1):\t" << use_enter << std::endl; @@ -121,8 +122,10 @@ class WriteToHOTPSlot : Command<CommandID::WRITE_TO_SLOT> { for (auto i : slot_token_id) ss << std::hex << std::setw(2) << std::setfill('0')<< (int) i << " " ; ss << std::endl; - ss << "slot_counter:\t" << (int)slot_counter << std::endl; - return ss.str(); + ss << "slot_counter:\t[" << (int)slot_counter << "]\t" + << ::nitrokey::misc::hexdump((const char *)(&slot_counter), sizeof slot_counter, false); + + return ss.str(); } } __packed; @@ -331,7 +334,10 @@ class GetStatus : Command<CommandID::GET_STATUS> { std::string dissect() const { std::stringstream ss; - ss << "firmware_version:\t" << firmware_version << std::endl; + ss << "firmware_version:\t" + << "[" << firmware_version << "]" << "\t" + << ::nitrokey::misc::hexdump( + (const char *)(&firmware_version), sizeof firmware_version, false); ss << "card_serial:\t" << ::nitrokey::misc::hexdump((const char *)(card_serial), sizeof card_serial, false); diff --git a/include/stick20_commands.h b/include/stick20_commands.h index c684e95..f4e7500 100644 --- a/include/stick20_commands.h +++ b/include/stick20_commands.h @@ -62,6 +62,26 @@ namespace stick20 { CommandTransaction; }; + + class UnlockUserPassword : Command<CommandID::UNLOCK_USER_PASSWORD> { + public: + struct CommandPayload { + uint8_t kind; + uint8_t user_new_password[20]; + std::string dissect() const { + std::stringstream ss; + ss << " user_new_password:\t" << user_new_password<< std::endl; + return ss.str(); + } + void set_kind(PasswordKind k){ + kind = (uint8_t)k; + } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; + }; + class EnableEncryptedPartition : semantics::non_constructible { public: struct CommandPayload { @@ -126,15 +146,25 @@ class ExportFirmware : semantics::non_constructible { struct EmptyPayload> CommandTransaction; }; -class CreateNewKeys : semantics::non_constructible { - public: - struct CommandPayload { - uint8_t password[30]; - }; + class CreateNewKeys : Command<CommandID::GENERATE_NEW_KEYS> { + public: + struct CommandPayload { + uint8_t kind; + uint8_t admin_password[30]; //CS20_MAX_PASSWORD_LEN + std::string dissect() const { + std::stringstream ss; + ss << " admin_password:\t" << admin_password<< std::endl; + return ss.str(); + } + void setKindPrefixed(){ + kind = 'P'; + } + } __packed; + + typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> + CommandTransaction; + }; - typedef Transaction<CommandID::GENERATE_NEW_KEYS, struct CommandPayload, - struct EmptyPayload> CommandTransaction; -}; class FillSDCardWithRandomChars : semantics::non_constructible { public: @@ -182,7 +212,7 @@ class SendPasswordMatrixSetup : semantics::non_constructible { struct EmptyPayload> CommandTransaction; }; -#define d(x) ss << #x":\t" << x << std::endl; +#define d(x) ss << " "#x":\t" << (int)x << std::endl; class GetDeviceStatus : Command<CommandID::GET_DEVICE_STATUS> { public: @@ -190,7 +220,7 @@ class SendPasswordMatrixSetup : semantics::non_constructible { static const int payload_absolute_begin = 8; static const int padding_size = OUTPUT_CMD_RESULT_STICK20_STATUS_START - payload_absolute_begin; struct ResponsePayload { - uint8_t _padding[padding_size]; + uint8_t _padding[padding_size]; //TODO confirm padding in Storage firmware //data starts from 21st byte of packet -> 13th byte of payload uint8_t command_counter; uint8_t last_command; |