aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/CommandFailedException.h36
-rw-r--r--include/DeviceCommunicationExceptions.h40
-rw-r--r--include/LibraryException.h6
-rw-r--r--include/LongOperationInProgressException.h2
-rw-r--r--include/NitrokeyManager.h43
-rw-r--r--include/command.h7
-rw-r--r--include/command_id.h8
-rw-r--r--include/cxx_semantics.h8
-rw-r--r--include/device.h85
-rw-r--r--include/device_proto.h132
-rw-r--r--include/dissect.h4
-rw-r--r--include/hidapi/hidapi.h391
-rw-r--r--include/log.h15
-rw-r--r--include/misc.h18
-rw-r--r--include/stick10_commands.h63
-rw-r--r--include/stick10_commands_0.8.h2
-rw-r--r--include/stick20_commands.h45
17 files changed, 789 insertions, 116 deletions
diff --git a/include/CommandFailedException.h b/include/CommandFailedException.h
index 9b0c59e..417e850 100644
--- a/include/CommandFailedException.h
+++ b/include/CommandFailedException.h
@@ -7,23 +7,47 @@
#include <exception>
#include <cstdint>
-#include <log.h>
+#include "log.h"
+#include "command_id.h"
+
+using cs = nitrokey::proto::stick10::command_status;
class CommandFailedException : public std::exception {
public:
- uint8_t last_command_code;
- uint8_t last_command_status;
+ const uint8_t last_command_id;
+ const uint8_t last_command_status;
- CommandFailedException(uint8_t last_command_code, uint8_t last_command_status) :
- last_command_code(last_command_code),
+ CommandFailedException(uint8_t last_command_id, uint8_t last_command_status) :
+ last_command_id(last_command_id),
last_command_status(last_command_status){
- nitrokey::log::Log::instance()(std::string("CommandFailedException, status: ")+ std::to_string(last_command_status), nitrokey::log::Loglevel::DEBUG);
+ LOG(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";
}
+
+ bool reason_timestamp_warning() const throw(){
+ return last_command_status == static_cast<uint8_t>(cs::timestamp_warning);
+ }
+
+ bool reason_AES_not_initialized() const throw(){
+ return last_command_status == static_cast<uint8_t>(cs::AES_dec_failed);
+ }
+
+ bool reason_not_authorized() const throw(){
+ return last_command_status == static_cast<uint8_t>(cs::not_authorized);
+ }
+
+ bool reason_slot_not_programmed() const throw(){
+ return last_command_status == static_cast<uint8_t>(cs::slot_not_programmed);
+ }
+
+ bool reason_wrong_password() const throw(){
+ return last_command_status == static_cast<uint8_t>(cs::wrong_password);
+ }
+
};
diff --git a/include/DeviceCommunicationExceptions.h b/include/DeviceCommunicationExceptions.h
new file mode 100644
index 0000000..6d21561
--- /dev/null
+++ b/include/DeviceCommunicationExceptions.h
@@ -0,0 +1,40 @@
+#ifndef LIBNITROKEY_DEVICECOMMUNICATIONEXCEPTIONS_H
+#define LIBNITROKEY_DEVICECOMMUNICATIONEXCEPTIONS_H
+
+#include <atomic>
+#include <exception>
+#include <stdexcept>
+#include <string>
+
+class DeviceCommunicationException: public std::runtime_error
+{
+ std::string message;
+ static std::atomic_int occurred;
+public:
+ DeviceCommunicationException(std::string _msg): std::runtime_error(_msg), message(_msg){
+ ++occurred;
+ }
+// virtual const char* what() const throw() override {
+// return message.c_str();
+// }
+ static bool has_occurred(){ return occurred > 0; };
+ static void reset_occurred_flag(){ occurred = 0; };
+};
+
+class DeviceNotConnected: public DeviceCommunicationException {
+public:
+ DeviceNotConnected(std::string msg) : DeviceCommunicationException(msg){}
+};
+
+class DeviceSendingFailure: public DeviceCommunicationException {
+public:
+ DeviceSendingFailure(std::string msg) : DeviceCommunicationException(msg){}
+};
+
+class DeviceReceivingFailure: public DeviceCommunicationException {
+public:
+ DeviceReceivingFailure(std::string msg) : DeviceCommunicationException(msg){}
+};
+
+
+#endif //LIBNITROKEY_DEVICECOMMUNICATIONEXCEPTIONS_H
diff --git a/include/LibraryException.h b/include/LibraryException.h
index 3c3fab4..b9303ad 100644
--- a/include/LibraryException.h
+++ b/include/LibraryException.h
@@ -11,8 +11,6 @@ public:
virtual uint8_t exception_id()= 0;
};
-
-
class TargetBufferSmallerThanSource: public LibraryException {
public:
virtual uint8_t exception_id() override {
@@ -29,7 +27,7 @@ public:
virtual const char *what() const throw() override {
std::string s = " ";
- auto ts = [](int x){ return std::to_string(x); };
+ auto ts = [](size_t x){ return std::to_string(x); };
std::string msg = std::string("Target buffer size is smaller than source: [source size, buffer size]")
+s+ ts(source_size) +s+ ts(target_size);
return msg.c_str();
@@ -85,7 +83,7 @@ public:
TooLongStringException(size_t size_source, size_t size_destination, const std::string &message = "") : size_source(
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);
+ LOG(std::string("TooLongStringException, size diff: ")+ std::to_string(size_source-size_destination), nitrokey::log::Loglevel::DEBUG);
}
diff --git a/include/LongOperationInProgressException.h b/include/LongOperationInProgressException.h
index 7f182b0..5b441c0 100644
--- a/include/LongOperationInProgressException.h
+++ b/include/LongOperationInProgressException.h
@@ -15,7 +15,7 @@ public:
LongOperationInProgressException(
unsigned char _command_id, uint8_t last_command_status, unsigned char _progress_bar_value)
: CommandFailedException(_command_id, last_command_status), progress_bar_value(_progress_bar_value){
- nitrokey::log::Log::instance()(
+ LOG(
std::string("LongOperationInProgressException, progress bar status: ")+
std::to_string(progress_bar_value), nitrokey::log::Loglevel::DEBUG);
}
diff --git a/include/NitrokeyManager.h b/include/NitrokeyManager.h
index fd39445..4f11314 100644
--- a/include/NitrokeyManager.h
+++ b/include/NitrokeyManager.h
@@ -32,22 +32,31 @@ namespace nitrokey {
uint32_t get_HOTP_code(uint8_t slot_number, const char *user_temporary_password);
uint32_t get_TOTP_code(uint8_t slot_number, uint64_t challenge, uint64_t last_totp_time, uint8_t last_interval,
const char *user_temporary_password);
+ uint32_t get_TOTP_code(uint8_t slot_number, const char *user_temporary_password);
+ stick10::ReadSlot::ResponsePayload get_TOTP_slot_data(const uint8_t slot_number);
+ stick10::ReadSlot::ResponsePayload get_HOTP_slot_data(const uint8_t slot_number);
+
bool set_time(uint64_t time);
- bool get_time();
+ bool get_time(uint64_t time = 0);
bool erase_totp_slot(uint8_t slot_number, const char *temporary_password);
bool erase_hotp_slot(uint8_t slot_number, const char *temporary_password);
bool connect(const char *device_model);
bool connect();
bool disconnect();
- void set_debug(bool state);
- string get_status();
+ bool is_connected() throw() ;
+ bool could_current_device_be_enumerated();
+
+ DeviceModel get_connected_device_model() const;
+ void set_debug(bool state);
+ stick10::GetStatus::ResponsePayload get_status();
+ string get_status_as_string();
string get_serial_number();
const char * get_totp_slot_name(uint8_t slot_number);
const char * get_hotp_slot_name(uint8_t slot_number);
- void change_user_PIN(char *current_PIN, char *new_PIN);
- void change_admin_PIN(char *current_PIN, char *new_PIN);
+ void change_user_PIN(const char *current_PIN, const char *new_PIN);
+ void change_admin_PIN(const char *current_PIN, const char *new_PIN);
void enable_password_safe(const char *user_pin);
@@ -84,19 +93,24 @@ namespace nitrokey {
bool is_AES_supported(const char *user_password);
void unlock_encrypted_volume(const char *user_password);
+ void lock_encrypted_volume();
void unlock_hidden_volume(const char *hidden_volume_password);
+ void lock_hidden_volume();
void set_unencrypted_read_only(const char *user_pin);
void set_unencrypted_read_write(const char *user_pin);
void export_firmware(const char *admin_pin);
+ void enable_firmware_update(const char *firmware_pin);
void clear_new_sd_card_warning(const char *admin_pin);
void fill_SD_card_with_random_data(const char *admin_pin);
+ uint8_t get_SD_card_size();
+
void change_update_password(const char *current_update_password, const char *new_update_password);
void create_hidden_volume(uint8_t slot_nr, uint8_t start_percent, uint8_t end_percent,
@@ -105,26 +119,31 @@ namespace nitrokey {
void send_startup(uint64_t seconds_from_epoch);
const char * get_status_storage_as_string();
+ stick20::DeviceConfigurationResponsePacket::ResponsePayload get_status_storage();
const char *get_SD_usage_data_as_string();
+ std::pair<uint8_t,uint8_t> get_SD_usage_data();
+
int get_progress_bar_value();
~NitrokeyManager();
bool is_authorization_command_supported();
+ bool is_320_OTP_secret_supported();
+
- template <typename S, typename A, typename T>
+ template <typename S, typename A, typename T>
void authorize_packet(T &package, const char *admin_temporary_password, shared_ptr<Device> device);
- int get_major_firmware_version();
+ int get_minor_firmware_version();
+ explicit NitrokeyManager();
private:
- NitrokeyManager();
static shared_ptr <NitrokeyManager> _instance;
- bool connected;
std::shared_ptr<Device> device;
- bool is_valid_hotp_slot_number(uint8_t slot_number) const;
+ stick10::ReadSlot::ResponsePayload get_OTP_slot_data(const uint8_t slot_number);
+ bool is_valid_hotp_slot_number(uint8_t slot_number) const;
bool is_valid_totp_slot_number(uint8_t slot_number) const;
bool is_valid_password_safe_slot_number(uint8_t slot_number) const;
uint8_t get_internal_slot_number_for_hotp(uint8_t slot_number) const;
@@ -133,7 +152,7 @@ namespace nitrokey {
const char * get_slot_name(uint8_t slot_number);
template <typename ProCommand, PasswordKind StoKind>
- void change_PIN_general(char *current_PIN, char *new_PIN);
+ void change_PIN_general(const char *current_PIN, const char *new_PIN);
void write_HOTP_slot_authorize(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,
@@ -148,6 +167,8 @@ namespace nitrokey {
bool use_8_digits, bool use_enter, bool use_tokenID, const char *token_ID,
const char *temporary_password) const;
+ bool _disconnect_no_lock();
+
};
}
diff --git a/include/command.h b/include/command.h
index 0a875e4..fc374f7 100644
--- a/include/command.h
+++ b/include/command.h
@@ -28,6 +28,7 @@ namespace stick20{
template<CommandID cmd_id, PasswordKind Tpassword_kind = PasswordKind::User, int password_length = 20>
class PasswordCommand : public Command<cmd_id> {
+ constexpr static CommandID _command_id() { return cmd_id; }
public:
struct CommandPayload {
uint8_t kind;
@@ -69,8 +70,10 @@ namespace stick20{
} __packed;
- typedef Transaction<Command<cmd_id>::command_id(), struct CommandPayload, struct EmptyPayload>
- CommandTransaction;
+ //typedef Transaction<Command<cmd_id>::command_id(), struct CommandPayload, struct EmptyPayload>
+ // CommandTransaction;
+ using CommandTransaction = Transaction<cmd_id, CommandPayload, EmptyPayload>;
+ //using CommandTransaction = Transaction<_command_id(), CommandPayload, EmptyPayload>;
};
}
diff --git a/include/command_id.h b/include/command_id.h
index 346b750..d1246dd 100644
--- a/include/command_id.h
+++ b/include/command_id.h
@@ -1,6 +1,6 @@
#ifndef COMMAND_ID_H
#define COMMAND_ID_H
-#include "inttypes.h"
+#include <stdint.h>
namespace nitrokey {
namespace proto {
@@ -12,7 +12,7 @@ namespace proto {
wrong_password,
busy_progressbar,
password_matrix_ready,
- no_user_password_unlock,
+ no_user_password_unlock, // FIXME: translate on receive to command status error (fix in firmware?)
smartcard_error,
security_bit_active
};
@@ -69,9 +69,9 @@ enum class CommandID : uint8_t {
SEND_OTP_DATA = 0x17,
ENABLE_CRYPTED_PARI = 0x20,
- DISABLE_CRYPTED_PARI = 0x20 + 1, //@unused
+ DISABLE_CRYPTED_PARI = 0x20 + 1,
ENABLE_HIDDEN_CRYPTED_PARI = 0x20 + 2,
- DISABLE_HIDDEN_CRYPTED_PARI = 0x20 + 3, //@unused
+ DISABLE_HIDDEN_CRYPTED_PARI = 0x20 + 3,
ENABLE_FIRMWARE_UPDATE = 0x20 + 4, //enables update mode
EXPORT_FIRMWARE_TO_FILE = 0x20 + 5,
GENERATE_NEW_KEYS = 0x20 + 6,
diff --git a/include/cxx_semantics.h b/include/cxx_semantics.h
index b846317..f358e8f 100644
--- a/include/cxx_semantics.h
+++ b/include/cxx_semantics.h
@@ -1,7 +1,15 @@
#ifndef CXX_SEMANTICS_H
#define CXX_SEMANTICS_H
+#ifndef _MSC_VER
#define __packed __attribute__((__packed__))
+#else
+#define __packed
+#endif
+
+#ifdef _MSC_VER
+#define strdup _strdup
+#endif
/*
* There's no need to include Boost for a simple subset this project needs.
diff --git a/include/device.h b/include/device.h
index 62c4073..7b300e5 100644
--- a/include/device.h
+++ b/include/device.h
@@ -1,16 +1,18 @@
#ifndef DEVICE_H
#define DEVICE_H
#include <chrono>
-#include <hidapi/hidapi.h>
-#include "inttypes.h"
+#include "hidapi/hidapi.h"
+#include <cstdint>
+#include <string>
#define HID_REPORT_SIZE 65
-// TODO !! SEMAPHORE
+#include <atomic>
namespace nitrokey {
namespace device {
using namespace std::chrono_literals;
+ using std::chrono::milliseconds;
struct EnumClassHash
{
@@ -26,11 +28,39 @@ enum class DeviceModel{
STORAGE
};
+#include <atomic>
+
class Device {
public:
- Device();
- virtual ~Device(){disconnect();}
+
+ struct ErrorCounters{
+ using cnt = std::atomic_int;
+ cnt wrong_CRC;
+ cnt CRC_other_than_awaited;
+ cnt busy;
+ cnt total_retries;
+ cnt sending_error;
+ cnt receiving_error;
+ cnt total_comm_runs;
+ cnt successful_storage_commands;
+ cnt command_successful_recv;
+ cnt recv_executed;
+ cnt sends_executed;
+ cnt busy_progressbar;
+ cnt command_result_not_equal_0_recv;
+ cnt communication_successful;
+ cnt low_level_reconnect;
+ std::string get_as_string();
+
+ } m_counters = {};
+
+
+ Device(const uint16_t vid, const uint16_t pid, const DeviceModel model,
+ const milliseconds send_receive_delay, const int retry_receiving_count,
+ const milliseconds retry_timeout);
+
+ virtual ~Device();
// lack of device is not actually an error,
// so it doesn't throw
@@ -48,34 +78,49 @@ public:
*/
virtual int recv(void *packet);
+ /***
+ * Returns true if some device is visible by OS with given VID and PID
+ * whether the device is connected through HID API or not.
+ * @return true if visible by OS
+ */
+ bool could_be_enumerated();
+
+ void show_stats();
+// ErrorCounters get_stats(){ return m_counters; }
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;}
+ std::chrono::milliseconds get_send_receive_delay() const {return m_send_receive_delay;}
- int get_last_command_status() {auto a = last_command_status; last_command_status = 0; return a;};
- void set_last_command_status(uint8_t _err) { last_command_status = _err;} ;
- bool last_command_sucessfull() const {return last_command_status == 0;};
- DeviceModel get_device_model() const {return m_model;}
+ int get_last_command_status() {int a = std::atomic_exchange(&last_command_status, static_cast<uint8_t>(0)); return a;};
+ void set_last_command_status(uint8_t _err) { last_command_status = _err;} ;
+ bool last_command_sucessfull() const {return last_command_status == 0;};
+ DeviceModel get_device_model() const {return m_model;}
private:
- uint8_t last_command_status;
+ std::atomic<uint8_t> last_command_status;
+ void _reconnect();
+ bool _connect();
+ bool _disconnect();
- protected:
- uint16_t m_vid;
- uint16_t m_pid;
- DeviceModel m_model;
+protected:
+ const uint16_t m_vid;
+ const uint16_t m_pid;
+ const DeviceModel m_model;
/*
* While the project uses Signal11 portable HIDAPI
* library, there's no way of doing it asynchronously,
* hence polling.
*/
- int m_retry_sending_count;
- int m_retry_receiving_count;
- std::chrono::milliseconds m_retry_timeout;
- std::chrono::milliseconds m_send_receive_delay;
+ const int m_retry_sending_count;
+ const int m_retry_receiving_count;
+ const std::chrono::milliseconds m_retry_timeout;
+ const std::chrono::milliseconds m_send_receive_delay;
+
+ std::atomic<hid_device *>mp_devhandle;
+
- hid_device *mp_devhandle;
+ static std::atomic_int instances_count;
};
class Stick10 : public Device {
diff --git a/include/device_proto.h b/include/device_proto.h
index 0953566..b137689 100644
--- a/include/device_proto.h
+++ b/include/device_proto.h
@@ -6,9 +6,8 @@
#include <type_traits>
#include <stdexcept>
#include <string>
-#include <strings.h>
// a local version for compatibility with Windows
-#include "inttypes.h"
+#include <stdint.h>
#include "cxx_semantics.h"
#include "device.h"
#include "misc.h"
@@ -32,6 +31,10 @@
#define PWS_SEND_TAB 2
#define PWS_SEND_CR 3
+#include <mutex>
+#include "DeviceCommunicationExceptions.h"
+#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
+
namespace nitrokey {
namespace proto {
/*
@@ -40,7 +43,7 @@ namespace nitrokey {
*
* TODO (future) support for Big Endian
*/
-
+#pragma pack (push,1)
/*
* Every packet is a USB HID report (check USB spec)
*/
@@ -178,8 +181,10 @@ namespace nitrokey {
typedef command_payload CommandPayload;
typedef response_payload ResponsePayload;
+
typedef struct HIDReport<cmd_id, CommandPayload> OutgoingPacket;
typedef struct DeviceResponse<cmd_id, ResponsePayload> ResponsePacket;
+#pragma pack (pop)
static_assert(std::is_pod<OutgoingPacket>::value,
"outgoingpacket must be a pod type");
@@ -204,14 +209,21 @@ namespace nitrokey {
bzero(&st, sizeof(st));
}
-
- static ClearingProxy<ResponsePacket, response_payload> run(device::Device &dev,
+ static ClearingProxy<ResponsePacket, response_payload> run(std::shared_ptr<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);
+ static std::mutex send_receive_mtx;
+ std::lock_guard<std::mutex> guard(send_receive_mtx);
+
+ LOG(__FUNCTION__, Loglevel::DEBUG_L2);
+
+ if (dev == nullptr){
+ throw DeviceNotConnected("Device not initialized");
+ }
+ dev->m_counters.total_comm_runs++;
int status;
OutgoingPacket outp;
@@ -224,32 +236,41 @@ namespace nitrokey {
outp.payload = payload;
outp.update_CRC();
- Log::instance()("Outgoing HID packet:", Loglevel::DEBUG);
- Log::instance()(static_cast<std::string>(outp), Loglevel::DEBUG);
+ LOG("Outgoing HID packet:", Loglevel::DEBUG);
+ LOG(static_cast<std::string>(outp), Loglevel::DEBUG);
- if (!outp.isValid()) throw std::runtime_error("Invalid outgoing packet");
+ if (!outp.isValid()) throw DeviceSendingFailure("Invalid outgoing packet");
bool successful_communication = false;
int receiving_retry_counter = 0;
- int sending_retry_counter = dev.get_retry_sending_count();
+ 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(
+ dev->m_counters.sends_executed++;
+ status = dev->send(&outp);
+ if (status <= 0){
+ //FIXME early disconnection not yet working properly
+// LOG("Encountered communication error, disconnecting device", Loglevel::DEBUG_L2);
+// dev->disconnect();
+ dev->m_counters.sending_error++;
+ throw DeviceSendingFailure(
std::string("Device error while sending command ") +
std::to_string(status));
+ }
- std::this_thread::sleep_for(dev.get_send_receive_delay());
+ 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();
+ receiving_retry_counter = dev->get_retry_receiving_count();
+ int busy_counter = 0;
+ auto retry_timeout = dev->get_retry_timeout();
while (receiving_retry_counter-- > 0) {
- status = dev.recv(&resp);
+ dev->m_counters.recv_executed++;
+ status = dev->recv(&resp);
- if (dev.get_device_model() == DeviceModel::STORAGE &&
+ 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: ") +
+ LOG(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);
@@ -267,7 +288,7 @@ namespace nitrokey {
resp.device_status = static_cast<uint8_t>(stick10::device_status::ok);
break;
default:
- Log::instance()(std::string("Unknown storage device status, cannot translate: ") +
+ LOG(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;
@@ -276,15 +297,25 @@ namespace nitrokey {
//SENDPASSWORD gives wrong CRC , for now rely on !=0 (TODO report)
// if (resp.device_status == 0 && resp.last_command_crc == outp.crc && resp.isCRCcorrect()) break;
+ auto CRC_equal_awaited = resp.last_command_crc == outp.crc;
if (resp.device_status == static_cast<uint8_t>(stick10::device_status::ok) &&
- resp.last_command_crc == outp.crc && resp.isValid()){
+ CRC_equal_awaited && resp.isValid()){
successful_communication = true;
break;
}
if (resp.device_status == static_cast<uint8_t>(stick10::device_status::busy)) {
- receiving_retry_counter++;
- Log::instance()("Status busy, not decresing receiving_retry_counter counter: " +
- std::to_string(receiving_retry_counter), Loglevel::DEBUG_L2);
+ dev->m_counters.busy++;
+ if (busy_counter++<10) {
+ receiving_retry_counter++;
+ LOG("Status busy, not decreasing receiving_retry_counter counter: " +
+ std::to_string(receiving_retry_counter), Loglevel::DEBUG_L2);
+ } else {
+ retry_timeout *= 2;
+ busy_counter = 0;
+ LOG("Status busy, decreasing receiving_retry_counter counter: " +
+ std::to_string(receiving_retry_counter) + ", current delay:"
+ + std::to_string(retry_timeout.count()), Loglevel::DEBUG);
+ }
}
if (resp.device_status == static_cast<uint8_t>(stick10::device_status::busy) &&
static_cast<stick20::device_status>(resp.storage_status.device_status)
@@ -292,59 +323,78 @@ namespace nitrokey {
successful_communication = true;
break;
}
- Log::instance()(std::string("Retry status - dev status, equal crc, correct CRC: ")
+ LOG(std::string("Retry status - dev status, awaited cmd crc, correct packet CRC: ")
+ std::to_string(resp.device_status) + " " +
- std::to_string(resp.last_command_crc == outp.crc) +
+ std::to_string(CRC_equal_awaited) +
" " + std::to_string(resp.isCRCcorrect()), Loglevel::DEBUG_L2);
- Log::instance()(
+ if (!resp.isCRCcorrect()) dev->m_counters.wrong_CRC++;
+ if (!CRC_equal_awaited) dev->m_counters.CRC_other_than_awaited++;
+
+
+ LOG(
"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()(static_cast<std::string>(resp), Loglevel::DEBUG_L2);
- std::this_thread::sleep_for(dev.get_retry_timeout());
+ LOG("Invalid incoming HID packet:", Loglevel::DEBUG_L2);
+ LOG(static_cast<std::string>(resp), Loglevel::DEBUG_L2);
+ dev->m_counters.total_retries++;
+ std::this_thread::sleep_for(retry_timeout);
continue;
}
if (successful_communication) break;
- Log::instance()(std::string("Resending (outer loop) "), Loglevel::DEBUG_L2);
- Log::instance()(std::string("sending_retry_counter count: ") + std::to_string(sending_retry_counter),
+ LOG(std::string("Resending (outer loop) "), Loglevel::DEBUG_L2);
+ LOG(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
+ 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( //FIXME replace with CriticalErrorException
+ if (status <= 0) {
+ dev->m_counters.receiving_error++;
+ throw DeviceReceivingFailure( //FIXME replace with CriticalErrorException
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),
+ LOG("Incoming HID packet:", Loglevel::DEBUG);
+ LOG(static_cast<std::string>(resp), Loglevel::DEBUG);
+ LOG(std::string("receiving_retry_counter count: ") + std::to_string(receiving_retry_counter),
Loglevel::DEBUG);
if (resp.device_status == static_cast<uint8_t>(stick10::device_status::busy) &&
static_cast<stick20::device_status>(resp.storage_status.device_status)
== stick20::device_status::busy_progressbar){
+ dev->m_counters.busy_progressbar++;
throw LongOperationInProgressException(
resp.command_id, resp.device_status, resp.storage_status.progress_bar_value);
}
- if (!resp.isValid()) throw std::runtime_error("Invalid incoming packet");
+ if (!resp.isValid()) throw DeviceReceivingFailure("Invalid incoming packet");
if (receiving_retry_counter <= 0)
- throw std::runtime_error(
+ throw DeviceReceivingFailure(
"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))
+ dev->m_counters.communication_successful++;
+
+ if (resp.last_command_status != static_cast<uint8_t>(stick10::command_status::ok)){
+ dev->m_counters.command_result_not_equal_0_recv++;
throw CommandFailedException(resp.command_id, resp.last_command_status);
+ }
+
+ dev->m_counters.command_successful_recv++;
+ if (dev->get_device_model() == DeviceModel::STORAGE &&
+ resp.command_id >= stick20::CMD_START_VALUE &&
+ resp.command_id < stick20::CMD_END_VALUE ) {
+ dev->m_counters.successful_storage_commands++;
+ }
// See: DeviceResponse
return resp;
}
- static ClearingProxy<ResponsePacket, response_payload> run(device::Device &dev) {
+ static ClearingProxy<ResponsePacket, response_payload> run(std::shared_ptr<device::Device> dev) {
command_payload empty_payload;
return run(dev, empty_payload);
}
diff --git a/include/dissect.h b/include/dissect.h
index 8c975c5..8992c56 100644
--- a/include/dissect.h
+++ b/include/dissect.h
@@ -98,7 +98,8 @@ 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;
+ if((int)pod.command_id == pod.storage_status.command_id){
+ out << "Storage stick status (where applicable):" << 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);
@@ -106,6 +107,7 @@ class ResponseDissector : semantics::non_constructible {
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/hidapi/hidapi.h b/include/hidapi/hidapi.h
new file mode 100644
index 0000000..e5bc2dc
--- /dev/null
+++ b/include/hidapi/hidapi.h
@@ -0,0 +1,391 @@
+/*******************************************************
+ HIDAPI - Multi-Platform library for
+ communication with HID devices.
+
+ Alan Ott
+ Signal 11 Software
+
+ 8/22/2009
+
+ Copyright 2009, All Rights Reserved.
+
+ At the discretion of the user of this library,
+ this software may be licensed under the terms of the
+ GNU General Public License v3, a BSD-Style license, or the
+ original HIDAPI license as outlined in the LICENSE.txt,
+ LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
+ files located at the root of the source distribution.
+ These files may also be found in the public source
+ code repository located at:
+ http://github.com/signal11/hidapi .
+********************************************************/
+
+/** @file
+ * @defgroup API hidapi API
+ */
+
+#ifndef HIDAPI_H__
+#define HIDAPI_H__
+
+#include <wchar.h>
+
+#ifdef _WIN32
+ #define HID_API_EXPORT __declspec(dllexport)
+ #define HID_API_CALL
+#else
+ #define HID_API_EXPORT /**< API export macro */
+ #define HID_API_CALL /**< API call macro */
+#endif
+
+#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ struct hid_device_;
+ typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
+
+ /** hidapi info structure */
+ struct hid_device_info {
+ /** Platform-specific device path */
+ char *path;
+ /** Device Vendor ID */
+ unsigned short vendor_id;
+ /** Device Product ID */
+ unsigned short product_id;
+ /** Serial Number */
+ wchar_t *serial_number;
+ /** Device Release Number in binary-coded decimal,
+ also known as Device Version Number */
+ unsigned short release_number;
+ /** Manufacturer String */
+ wchar_t *manufacturer_string;
+ /** Product string */
+ wchar_t *product_string;
+ /** Usage Page for this Device/Interface
+ (Windows/Mac only). */
+ unsigned short usage_page;
+ /** Usage for this Device/Interface
+ (Windows/Mac only).*/
+ unsigned short usage;
+ /** The USB interface which this logical device
+ represents. Valid on both Linux implementations
+ in all cases, and valid on the Windows implementation
+ only if the device contains more than one interface. */
+ int interface_number;
+
+ /** Pointer to the next device */
+ struct hid_device_info *next;
+ };
+
+
+ /** @brief Initialize the HIDAPI library.
+
+ This function initializes the HIDAPI library. Calling it is not
+ strictly necessary, as it will be called automatically by
+ hid_enumerate() and any of the hid_open_*() functions if it is
+ needed. This function should be called at the beginning of
+ execution however, if there is a chance of HIDAPI handles
+ being opened by different threads simultaneously.
+
+ @ingroup API
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_init(void);
+
+ /** @brief Finalize the HIDAPI library.
+
+ This function frees all of the static data associated with
+ HIDAPI. It should be called at the end of execution to avoid
+ memory leaks.
+
+ @ingroup API
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_exit(void);
+
+ /** @brief Enumerate the HID Devices.
+
+ This function returns a linked list of all the HID devices
+ attached to the system which match vendor_id and product_id.
+ If @p vendor_id is set to 0 then any vendor matches.
+ If @p product_id is set to 0 then any product matches.
+ If @p vendor_id and @p product_id are both set to 0, then
+ all HID devices will be returned.
+
+ @ingroup API
+ @param vendor_id The Vendor ID (VID) of the types of device
+ to open.
+ @param product_id The Product ID (PID) of the types of
+ device to open.
+
+ @returns
+ This function returns a pointer to a linked list of type
+ struct #hid_device, containing information about the HID devices
+ attached to the system, or NULL in the case of failure. Free
+ this linked list by calling hid_free_enumeration().
+ */
+ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
+
+ /** @brief Free an enumeration Linked List
+
+ This function frees a linked list created by hid_enumerate().
+
+ @ingroup API
+ @param devs Pointer to a list of struct_device returned from
+ hid_enumerate().
+ */
+ void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
+
+ /** @brief Open a HID device using a Vendor ID (VID), Product ID
+ (PID) and optionally a serial number.
+
+ If @p serial_number is NULL, the first device with the
+ specified VID and PID is opened.
+
+ @ingroup API
+ @param vendor_id The Vendor ID (VID) of the device to open.
+ @param product_id The Product ID (PID) of the device to open.
+ @param serial_number The Serial Number of the device to open
+ (Optionally NULL).
+
+ @returns
+ This function returns a pointer to a #hid_device object on
+ success or NULL on failure.
+ */
+ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
+
+ /** @brief Open a HID device by its path name.
+
+ The path name be determined by calling hid_enumerate(), or a
+ platform-specific path name can be used (eg: /dev/hidraw0 on
+ Linux).
+
+ @ingroup API
+ @param path The path name of the device to open
+
+ @returns
+ This function returns a pointer to a #hid_device object on
+ success or NULL on failure.
+ */
+ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path);
+
+ /** @brief Write an Output report to a HID device.
+
+ The first byte of @p data[] must contain the Report ID. For
+ devices which only support a single report, this must be set
+ to 0x0. The remaining bytes contain the report data. Since
+ the Report ID is mandatory, calls to hid_write() will always
+ contain one more byte than the report contains. For example,
+ if a hid report is 16 bytes long, 17 bytes must be passed to
+ hid_write(), the Report ID (or 0x0, for devices with a
+ single report), followed by the report data (16 bytes). In
+ this example, the length passed in would be 17.
+
+ hid_write() will send the data on the first OUT endpoint, if
+ one exists. If it does not, it will send the data through
+ the Control Endpoint (Endpoint 0).
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+ @param data The data to send, including the report number as
+ the first byte.
+ @param length The length in bytes of the data to send.
+
+ @returns
+ This function returns the actual number of bytes written and
+ -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length);
+
+ /** @brief Read an Input report from a HID device with timeout.
+
+ Input reports are returned
+ to the host through the INTERRUPT IN endpoint. The first byte will
+ contain the Report number if the device uses numbered reports.
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+ @param data A buffer to put the read data into.
+ @param length The number of bytes to read. For devices with
+ multiple reports, make sure to read an extra byte for
+ the report number.
+ @param milliseconds timeout in milliseconds or -1 for blocking wait.
+
+ @returns
+ This function returns the actual number of bytes read and
+ -1 on error. If no packet was available to be read within
+ the timeout period, this function returns 0.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
+
+ /** @brief Read an Input report from a HID device.
+
+ Input reports are returned
+ to the host through the INTERRUPT IN endpoint. The first byte will
+ contain the Report number if the device uses numbered reports.
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+ @param data A buffer to put the read data into.
+ @param length The number of bytes to read. For devices with
+ multiple reports, make sure to read an extra byte for
+ the report number.
+
+ @returns
+ This function returns the actual number of bytes read and
+ -1 on error. If no packet was available to be read and
+ the handle is in non-blocking mode, this function returns 0.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length);
+
+ /** @brief Set the device handle to be non-blocking.
+
+ In non-blocking mode calls to hid_read() will return
+ immediately with a value of 0 if there is no data to be
+ read. In blocking mode, hid_read() will wait (block) until
+ there is data to read before returning.
+
+ Nonblocking can be turned on and off at any time.
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+ @param nonblock enable or not the nonblocking reads
+ - 1 to enable nonblocking
+ - 0 to disable nonblocking.
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock);
+
+ /** @brief Send a Feature report to the device.
+
+ Feature reports are sent over the Control endpoint as a
+ Set_Report transfer. The first byte of @p data[] must
+ contain the Report ID. For devices which only support a
+ single report, this must be set to 0x0. The remaining bytes
+ contain the report data. Since the Report ID is mandatory,
+ calls to hid_send_feature_report() will always contain one
+ more byte than the report contains. For example, if a hid
+ report is 16 bytes long, 17 bytes must be passed to
+ hid_send_feature_report(): the Report ID (or 0x0, for
+ devices which do not use numbered reports), followed by the
+ report data (16 bytes). In this example, the length passed
+ in would be 17.
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+ @param data The data to send, including the report number as
+ the first byte.
+ @param length The length in bytes of the data to send, including
+ the report number.
+
+ @returns
+ This function returns the actual number of bytes written and
+ -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length);
+
+ /** @brief Get a feature report from a HID device.
+
+ Set the first byte of @p data[] to the Report ID of the
+ report to be read. Make sure to allow space for this
+ extra byte in @p data[]. Upon return, the first byte will
+ still contain the Report ID, and the report data will
+ start in data[1].
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+ @param data A buffer to put the read data into, including
+ the Report ID. Set the first byte of @p data[] to the
+ Report ID of the report to be read, or set it to zero
+ if your device does not use numbered reports.
+ @param length The number of bytes to read, including an
+ extra byte for the report ID. The buffer can be longer
+ than the actual report.
+
+ @returns
+ This function returns the number of bytes read plus
+ one for the report ID (which is still in the first
+ byte), or -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length);
+
+ /** @brief Close a HID device.
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+ */
+ void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device);
+
+ /** @brief Get The Manufacturer String from a HID device.
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+ @param string A wide string buffer to put the data into.
+ @param maxlen The length of the buffer in multiples of wchar_t.
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen);
+
+ /** @brief Get The Product String from a HID device.
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+ @param string A wide string buffer to put the data into.
+ @param maxlen The length of the buffer in multiples of wchar_t.
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen);
+
+ /** @brief Get The Serial Number String from a HID device.
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+ @param string A wide string buffer to put the data into.
+ @param maxlen The length of the buffer in multiples of wchar_t.
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen);
+
+ /** @brief Get a string from a HID device, based on its string index.
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+ @param string_index The index of the string to get.
+ @param string A wide string buffer to put the data into.
+ @param maxlen The length of the buffer in multiples of wchar_t.
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen);
+
+ /** @brief Get a string describing the last error which occurred.
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+
+ @returns
+ This function returns a string containing the last error
+ which occurred or NULL if none has occurred.
+ */
+ HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/include/log.h b/include/log.h
index 8eda4fb..7c25918 100644
--- a/include/log.h
+++ b/include/log.h
@@ -6,6 +6,12 @@
namespace nitrokey {
namespace log {
+//for MSVC
+#ifdef ERROR
+#undef ERROR
+#endif
+
+
enum class Loglevel : int { DEBUG_L2, DEBUG, INFO, WARNING, ERROR };
class LogHandler {
@@ -28,7 +34,7 @@ class Log {
Log() : mp_loghandler(&stdlog_handler), m_loglevel(Loglevel::WARNING) {}
static Log &instance() {
- if (mp_instance == NULL) mp_instance = new Log;
+ if (mp_instance == nullptr) mp_instance = new Log;
return *mp_instance;
}
@@ -47,4 +53,11 @@ class Log {
}
}
+
+#ifdef NO_LOG
+#define LOG(string, level) while(false){}
+#else
+#define LOG(string, level) nitrokey::log::Log::instance()((string), (level))
+#endif
+
#endif
diff --git a/include/misc.h b/include/misc.h
index 5158de0..111d772 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -6,10 +6,21 @@
#include <string.h>
#include "log.h"
#include "LibraryException.h"
+#include <sstream>
+#include <iomanip>
+
namespace nitrokey {
namespace misc {
+ template<typename T>
+ std::string toHex(T value){
+ using namespace std;
+ std::ostringstream oss;
+ oss << std::hex << std::setw(sizeof(value)*2) << std::setfill('0') << value;
+ return oss.str();
+ }
+
template <typename T>
void strcpyT(T& dest, const char* src){
@@ -17,7 +28,7 @@ namespace misc {
// throw EmptySourceStringException(slot_number);
return;
const size_t s_dest = sizeof dest;
- nitrokey::log::Log::instance()(std::string("strcpyT sizes dest src ")
+ LOG(std::string("strcpyT sizes dest src ")
+std::to_string(s_dest)+ " "
+std::to_string(strlen(src))+ " "
,nitrokey::log::Loglevel::DEBUG);
@@ -27,7 +38,7 @@ namespace misc {
strncpy((char*) &dest, src, s_dest);
}
-
+#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
template <typename T>
typename T::CommandPayload get_payload(){
//Create, initialize and return by value command payload
@@ -44,7 +55,8 @@ typename T::CommandPayload get_payload(){
CMDTYPE::CommandTransaction::run(stick, p);
}
- std::string hexdump(const char *p, size_t size, bool print_header=true);
+ std::string hexdump(const char *p, size_t size, bool print_header=true, bool print_ascii=true,
+ bool print_empty=true);
uint32_t stm_crc32(const uint8_t *data, size_t size);
std::vector<uint8_t> hex_string_to_byte(const char* hexString);
}
diff --git a/include/stick10_commands.h b/include/stick10_commands.h
index f02fd70..a50d0ae 100644
--- a/include/stick10_commands.h
+++ b/include/stick10_commands.h
@@ -1,16 +1,21 @@
#ifndef STICK10_COMMANDS_H
#define STICK10_COMMANDS_H
+
#include <bitset>
#include <iomanip>
#include <string>
#include <sstream>
-#include "inttypes.h"
-#include "command.h"
+#include <stdint.h>
#include "device_proto.h"
+#include "command.h"
+
+#pragma pack (push,1)
namespace nitrokey {
namespace proto {
+
+
/*
* Stick10 protocol definition
*/
@@ -293,18 +298,44 @@ class ReadSlot : Command<CommandID::READ_SLOT> {
struct ResponsePayload {
uint8_t slot_name[15];
- uint8_t config;
- uint8_t token_id[13];
- uint64_t counter;
+ union{
+ uint8_t _slot_config;
+ struct{
+ bool use_8_digits : 1;
+ bool use_enter : 1;
+ bool use_tokenID : 1;
+ };
+ };
+ union{
+ uint8_t slot_token_id[13]; /** OATH Token Identifier */
+ struct{ /** @see https://openauthentication.org/token-specs/ */
+ uint8_t omp[2];
+ uint8_t tt[2];
+ uint8_t mui[8];
+ uint8_t keyboard_layout; //disabled feature in nitroapp as of 20160805
+ } slot_token_fields;
+ };
+ union{
+ uint64_t slot_counter;
+ uint8_t slot_counter_s[8];
+ } __packed;
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;
+ 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;
+ ss << "\tuse_tokenID(2):\t" << use_tokenID << std::endl;
+
+ ss << "slot_token_id:\t";
+ 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 << "]\t"
+ << ::nitrokey::misc::hexdump((const char *)(&slot_counter), sizeof slot_counter, false);
return ss.str();
}
} __packed;
@@ -317,7 +348,10 @@ class GetStatus : Command<CommandID::GET_STATUS> {
public:
struct ResponsePayload {
uint16_t firmware_version;
- uint8_t card_serial[4];
+ union{
+ uint8_t card_serial[4];
+ uint32_t card_serial_u32;
+ } __packed;
union {
uint8_t general_config[5];
struct{
@@ -326,13 +360,12 @@ class GetStatus : Command<CommandID::GET_STATUS> {
uint8_t scrolllock; /** same as numlock */
uint8_t enable_user_password;
uint8_t delete_user_password;
- };
- };
+ } __packed;
+ } __packed;
bool isValid() const { return enable_user_password!=delete_user_password; }
std::string get_card_serial_hex() const {
- return ::nitrokey::misc::hexdump((const char *)(card_serial),
- sizeof card_serial, false);
+ return nitrokey::misc::toHex(card_serial_u32);
}
std::string dissect() const {
@@ -341,6 +374,7 @@ class GetStatus : Command<CommandID::GET_STATUS> {
<< "[" << firmware_version << "]" << "\t"
<< ::nitrokey::misc::hexdump(
(const char *)(&firmware_version), sizeof firmware_version, false);
+ ss << "card_serial_u32:\t" << std::hex << card_serial_u32 << std::endl;
ss << "card_serial:\t"
<< ::nitrokey::misc::hexdump((const char *)(card_serial),
sizeof card_serial, false);
@@ -812,8 +846,11 @@ class BuildAESKey : Command<CommandID::NEW_AES_KEY> {
typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload>
CommandTransaction;
+
};
+
}
}
}
+#pragma pack (pop)
#endif
diff --git a/include/stick10_commands_0.8.h b/include/stick10_commands_0.8.h
index 9594d1e..ead5add 100644
--- a/include/stick10_commands_0.8.h
+++ b/include/stick10_commands_0.8.h
@@ -9,7 +9,7 @@
#include <iomanip>
#include <string>
#include <sstream>
-#include "inttypes.h"
+#include <stdint.h>
#include "command.h"
#include "device_proto.h"
#include "stick10_commands.h"
diff --git a/include/stick20_commands.h b/include/stick20_commands.h
index e6df770..d88919b 100644
--- a/include/stick20_commands.h
+++ b/include/stick20_commands.h
@@ -1,12 +1,15 @@
#ifndef STICK20_COMMANDS_H
#define STICK20_COMMANDS_H
-#include "inttypes.h"
+
+
+#include <stdint.h>
#include "command.h"
#include <string>
#include <sstream>
#include "device_proto.h"
+#pragma pack (push,1)
namespace nitrokey {
namespace proto {
@@ -26,9 +29,12 @@ namespace nitrokey {
public PasswordCommand<CommandID::UNLOCK_USER_PASSWORD, PasswordKind::Admin> {};
class EnableEncryptedPartition : public PasswordCommand<CommandID::ENABLE_CRYPTED_PARI> {};
- class DisableEncryptedPartition : public PasswordCommand<CommandID::DISABLE_CRYPTED_PARI> {};
class EnableHiddenEncryptedPartition : public PasswordCommand<CommandID::ENABLE_HIDDEN_CRYPTED_PARI> {};
- class DisableHiddenEncryptedPartition : public PasswordCommand<CommandID::DISABLE_CRYPTED_PARI> {};
+
+ //FIXME the volume disabling commands do not need password
+ class DisableEncryptedPartition : public PasswordCommand<CommandID::DISABLE_CRYPTED_PARI> {};
+ class DisableHiddenEncryptedPartition : public PasswordCommand<CommandID::DISABLE_HIDDEN_CRYPTED_PARI> {};
+
class EnableFirmwareUpdate : public PasswordCommand<CommandID::ENABLE_FIRMWARE_UPDATE> {};
class ChangeUpdatePassword : Command<CommandID::CHANGE_UPDATE_PIN> {
@@ -123,6 +129,9 @@ namespace nitrokey {
StorageCommandResponsePayload::TransmissionData transmission_data;
uint16_t MagicNumber_StickConfig_u16;
+ /**
+ * READ_WRITE_ACTIVE = ReadWriteFlagUncryptedVolume_u8 == 0;
+ */
uint8_t ReadWriteFlagUncryptedVolume_u8;
uint8_t ReadWriteFlagCryptedVolume_u8;
@@ -130,18 +139,36 @@ namespace nitrokey {
uint8_t VersionInfo_au8[4];
struct {
uint8_t __unused;
- uint8_t major;
- uint8_t __unused2;
uint8_t minor;
+ uint8_t __unused2;
+ uint8_t major;
} __packed versionInfo;
- };
+ } __packed;
uint8_t ReadWriteFlagHiddenVolume_u8;
uint8_t FirmwareLocked_u8;
- uint8_t NewSDCardFound_u8;
+
+ union{
+ uint8_t NewSDCardFound_u8;
+ struct {
+ bool NewCard :1;
+ uint8_t Counter :7;
+ } __packed NewSDCardFound_st;
+ } __packed;
+
+ /**
+ * SD card FILLED with random chars
+ */
uint8_t SDFillWithRandomChars_u8;
uint32_t ActiveSD_CardID_u32;
- uint8_t VolumeActiceFlag_u8;
+ union{
+ uint8_t VolumeActiceFlag_u8;
+ struct {
+ bool unencrypted :1;
+ bool encrypted :1;
+ bool hidden :1;
+ } __packed VolumeActiceFlag_st;
+ } __packed;
uint8_t NewSmartCardFound_u8;
uint8_t UserPwRetryCount;
uint8_t AdminPwRetryCount;
@@ -308,10 +335,12 @@ namespace nitrokey {
typedef Transaction<command_id(), struct EmptyPayload, struct ResponsePayload>
CommandTransaction;
};
+
}
}
}
#undef print_to_ss
+#pragma pack (pop)
#endif