summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/CommandFailedException.h5
-rw-r--r--include/LibraryException.h6
-rw-r--r--include/NitrokeyManager.h6
-rw-r--r--include/command_id.h42
-rw-r--r--include/device.h6
-rw-r--r--include/device_proto.h480
-rw-r--r--include/dissect.h10
-rw-r--r--include/stick10_commands.h14
-rw-r--r--include/stick20_commands.h50
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;