diff options
| -rw-r--r-- | command_id.cc | 257 | ||||
| -rw-r--r-- | device.cc | 75 | ||||
| -rw-r--r-- | include/command.h | 17 | ||||
| -rw-r--r-- | include/command_id.h | 127 | ||||
| -rw-r--r-- | include/cxx_semantics.h | 6 | ||||
| -rw-r--r-- | include/device.h | 74 | ||||
| -rw-r--r-- | include/device_proto.h | 302 | ||||
| -rw-r--r-- | include/dissect.h | 99 | ||||
| -rw-r--r-- | include/log.h | 53 | ||||
| -rw-r--r-- | include/misc.h | 1 | ||||
| -rw-r--r-- | include/stick10_commands.h | 1043 | ||||
| -rw-r--r-- | include/stick20_commands.h | 448 | ||||
| -rw-r--r-- | log.cc | 40 | ||||
| -rw-r--r-- | misc.cc | 64 | ||||
| -rw-r--r-- | unittest/test.cc | 35 | 
15 files changed, 1247 insertions, 1394 deletions
| diff --git a/command_id.cc b/command_id.cc index 2c972c8..9512b7d 100644 --- a/command_id.cc +++ b/command_id.cc @@ -4,144 +4,143 @@  namespace nitrokey {  namespace proto { -const char * commandid_to_string(CommandID id) { -	switch (id) { -		case CommandID::GET_STATUS: -			return "GET_STATUS"; -		case CommandID::WRITE_TO_SLOT: -			return "WRITE_TO_SLOT"; -		case CommandID::READ_SLOT_NAME: -			return "READ_SLOT_NAME"; -		case CommandID::READ_SLOT: -			return "READ_SLOT"; -		case CommandID::GET_CODE: -			return "GET_CODE"; -		case CommandID::WRITE_CONFIG: -			return "WRITE_CONFIG"; -		case CommandID::ERASE_SLOT: -			return "ERASE_SLOT"; -		case CommandID::FIRST_AUTHENTICATE: -			return "FIRST_AUTHENTICATE"; -		case CommandID::AUTHORIZE: -			return "AUTHORIZE"; -		case CommandID::GET_PASSWORD_RETRY_COUNT: -			return "GET_PASSWORD_RETRY_COUNT"; -		case CommandID::CLEAR_WARNING: -			return "CLEAR_WARNING"; -		case CommandID::SET_TIME: -			return "SET_TIME"; -		case CommandID::TEST_COUNTER: -			return "TEST_COUNTER"; -		case CommandID::TEST_TIME: -			return "TEST_TIME"; -		case CommandID::USER_AUTHENTICATE: -			return "USER_AUTHENTICATE"; -		case CommandID::GET_USER_PASSWORD_RETRY_COUNT: -			return "GET_USER_PASSWORD_RETRY_COUNT"; -		case CommandID::USER_AUTHORIZE: -			return "USER_AUTHORIZE"; -		case CommandID::UNLOCK_USER_PASSWORD: -			return "UNLOCK_USER_PASSWORD"; -		case CommandID::LOCK_DEVICE: -			return "LOCK_DEVICE"; -		case CommandID::FACTORY_RESET: -			return "FACTORY_RESET"; -		case CommandID::CHANGE_USER_PIN: -			return "CHANGE_USER_PIN"; -		case CommandID::CHANGE_ADMIN_PIN: -			return "CHANGE_ADMIN_PIN"; +const char *commandid_to_string(CommandID id) { +  switch (id) { +    case CommandID::GET_STATUS: +      return "GET_STATUS"; +    case CommandID::WRITE_TO_SLOT: +      return "WRITE_TO_SLOT"; +    case CommandID::READ_SLOT_NAME: +      return "READ_SLOT_NAME"; +    case CommandID::READ_SLOT: +      return "READ_SLOT"; +    case CommandID::GET_CODE: +      return "GET_CODE"; +    case CommandID::WRITE_CONFIG: +      return "WRITE_CONFIG"; +    case CommandID::ERASE_SLOT: +      return "ERASE_SLOT"; +    case CommandID::FIRST_AUTHENTICATE: +      return "FIRST_AUTHENTICATE"; +    case CommandID::AUTHORIZE: +      return "AUTHORIZE"; +    case CommandID::GET_PASSWORD_RETRY_COUNT: +      return "GET_PASSWORD_RETRY_COUNT"; +    case CommandID::CLEAR_WARNING: +      return "CLEAR_WARNING"; +    case CommandID::SET_TIME: +      return "SET_TIME"; +    case CommandID::TEST_COUNTER: +      return "TEST_COUNTER"; +    case CommandID::TEST_TIME: +      return "TEST_TIME"; +    case CommandID::USER_AUTHENTICATE: +      return "USER_AUTHENTICATE"; +    case CommandID::GET_USER_PASSWORD_RETRY_COUNT: +      return "GET_USER_PASSWORD_RETRY_COUNT"; +    case CommandID::USER_AUTHORIZE: +      return "USER_AUTHORIZE"; +    case CommandID::UNLOCK_USER_PASSWORD: +      return "UNLOCK_USER_PASSWORD"; +    case CommandID::LOCK_DEVICE: +      return "LOCK_DEVICE"; +    case CommandID::FACTORY_RESET: +      return "FACTORY_RESET"; +    case CommandID::CHANGE_USER_PIN: +      return "CHANGE_USER_PIN"; +    case CommandID::CHANGE_ADMIN_PIN: +      return "CHANGE_ADMIN_PIN"; -		case CommandID::ENABLE_CRYPTED_PARI: -			return "ENABLE_CRYPTED_PARI"; -		case CommandID::DISABLE_CRYPTED_PARI: -			return "DISABLE_CRYPTED_PARI"; -		case CommandID::ENABLE_HIDDEN_CRYPTED_PARI: -			return "ENABLE_HIDDEN_CRYPTED_PARI"; -		case CommandID::DISABLE_HIDDEN_CRYPTED_PARI: -			return "DISABLE_HIDDEN_CRYPTED_PARI"; -		case CommandID::ENABLE_FIRMWARE_UPDATE: -			return "ENABLE_FIRMWARE_UPDATE"; -		case CommandID::EXPORT_FIRMWARE_TO_FILE: -			return "EXPORT_FIRMWARE_TO_FILE"; -		case CommandID::GENERATE_NEW_KEYS: -			return "GENERATE_NEW_KEYS"; -		case CommandID::FILL_SD_CARD_WITH_RANDOM_CHARS: -			return "FILL_SD_CARD_WITH_RANDOM_CHARS"; +    case CommandID::ENABLE_CRYPTED_PARI: +      return "ENABLE_CRYPTED_PARI"; +    case CommandID::DISABLE_CRYPTED_PARI: +      return "DISABLE_CRYPTED_PARI"; +    case CommandID::ENABLE_HIDDEN_CRYPTED_PARI: +      return "ENABLE_HIDDEN_CRYPTED_PARI"; +    case CommandID::DISABLE_HIDDEN_CRYPTED_PARI: +      return "DISABLE_HIDDEN_CRYPTED_PARI"; +    case CommandID::ENABLE_FIRMWARE_UPDATE: +      return "ENABLE_FIRMWARE_UPDATE"; +    case CommandID::EXPORT_FIRMWARE_TO_FILE: +      return "EXPORT_FIRMWARE_TO_FILE"; +    case CommandID::GENERATE_NEW_KEYS: +      return "GENERATE_NEW_KEYS"; +    case CommandID::FILL_SD_CARD_WITH_RANDOM_CHARS: +      return "FILL_SD_CARD_WITH_RANDOM_CHARS"; -		case CommandID::WRITE_STATUS_DATA: -			return "WRITE_STATUS_DATA"; -		case CommandID::ENABLE_READONLY_UNCRYPTED_LUN: -			return "ENABLE_READONLY_UNCRYPTED_LUN"; -		case CommandID::ENABLE_READWRITE_UNCRYPTED_LUN: -			return "ENABLE_READWRITE_UNCRYPTED_LUN"; +    case CommandID::WRITE_STATUS_DATA: +      return "WRITE_STATUS_DATA"; +    case CommandID::ENABLE_READONLY_UNCRYPTED_LUN: +      return "ENABLE_READONLY_UNCRYPTED_LUN"; +    case CommandID::ENABLE_READWRITE_UNCRYPTED_LUN: +      return "ENABLE_READWRITE_UNCRYPTED_LUN"; -		case CommandID::SEND_PASSWORD_MATRIX: -			return "SEND_PASSWORD_MATRIX"; -		case CommandID::SEND_PASSWORD_MATRIX_PINDATA: -			return "SEND_PASSWORD_MATRIX_PINDATA"; -		case CommandID::SEND_PASSWORD_MATRIX_SETUP: -			return "SEND_PASSWORD_MATRIX_SETUP"; +    case CommandID::SEND_PASSWORD_MATRIX: +      return "SEND_PASSWORD_MATRIX"; +    case CommandID::SEND_PASSWORD_MATRIX_PINDATA: +      return "SEND_PASSWORD_MATRIX_PINDATA"; +    case CommandID::SEND_PASSWORD_MATRIX_SETUP: +      return "SEND_PASSWORD_MATRIX_SETUP"; -		case CommandID::GET_DEVICE_STATUS: -			return "GET_DEVICE_STATUS"; -		case CommandID::SEND_DEVICE_STATUS: -			return "SEND_DEVICE_STATUS"; +    case CommandID::GET_DEVICE_STATUS: +      return "GET_DEVICE_STATUS"; +    case CommandID::SEND_DEVICE_STATUS: +      return "SEND_DEVICE_STATUS"; -		case CommandID::SEND_HIDDEN_VOLUME_PASSWORD: -			return "SEND_HIDDEN_VOLUME_PASSWORD"; -		case CommandID::SEND_HIDDEN_VOLUME_SETUP: -			return "SEND_HIDDEN_VOLUME_SETUP"; -		case CommandID::SEND_PASSWORD: -			return "SEND_PASSWORD"; -		case CommandID::SEND_NEW_PASSWORD: -			return "SEND_NEW_PASSWORD"; -		case CommandID::CLEAR_NEW_SD_CARD_FOUND: -			return "CLEAR_NEW_SD_CARD_FOUND"; +    case CommandID::SEND_HIDDEN_VOLUME_PASSWORD: +      return "SEND_HIDDEN_VOLUME_PASSWORD"; +    case CommandID::SEND_HIDDEN_VOLUME_SETUP: +      return "SEND_HIDDEN_VOLUME_SETUP"; +    case CommandID::SEND_PASSWORD: +      return "SEND_PASSWORD"; +    case CommandID::SEND_NEW_PASSWORD: +      return "SEND_NEW_PASSWORD"; +    case CommandID::CLEAR_NEW_SD_CARD_FOUND: +      return "CLEAR_NEW_SD_CARD_FOUND"; -		case CommandID::SEND_STARTUP: -			return "SEND_STARTUP"; -		case CommandID::SEND_CLEAR_STICK_KEYS_NOT_INITIATED: -			return "SEND_CLEAR_STICK_KEYS_NOT_INITIATED"; -		case CommandID::SEND_LOCK_STICK_HARDWARE: -			return "SEND_LOCK_STICK_HARDWARE"; +    case CommandID::SEND_STARTUP: +      return "SEND_STARTUP"; +    case CommandID::SEND_CLEAR_STICK_KEYS_NOT_INITIATED: +      return "SEND_CLEAR_STICK_KEYS_NOT_INITIATED"; +    case CommandID::SEND_LOCK_STICK_HARDWARE: +      return "SEND_LOCK_STICK_HARDWARE"; -		case CommandID::PRODUCTION_TEST: -			return "PRODUCTION_TEST"; -		case CommandID::SEND_DEBUG_DATA: -			return "SEND_DEBUG_DATA"; +    case CommandID::PRODUCTION_TEST: +      return "PRODUCTION_TEST"; +    case CommandID::SEND_DEBUG_DATA: +      return "SEND_DEBUG_DATA"; -		case CommandID::CHANGE_UPDATE_PIN: -			return "CHANGE_UPDATE_PIN"; +    case CommandID::CHANGE_UPDATE_PIN: +      return "CHANGE_UPDATE_PIN"; -		case CommandID::GET_PW_SAFE_SLOT_STATUS: -			return "GET_PW_SAFE_SLOT_STATUS"; -		case CommandID::GET_PW_SAFE_SLOT_NAME: -			return "GET_PW_SAFE_SLOT_NAME"; -		case CommandID::GET_PW_SAFE_SLOT_PASSWORD: -			return "GET_PW_SAFE_SLOT_PASSWORD"; -		case CommandID::GET_PW_SAFE_SLOT_LOGINNAME: -			return "GET_PW_SAFE_SLOT_LOGINNAME"; -		case CommandID::SET_PW_SAFE_SLOT_DATA_1: -			return "SET_PW_SAFE_SLOT_DATA_1"; -		case CommandID::SET_PW_SAFE_SLOT_DATA_2: -			return "SET_PW_SAFE_SLOT_DATA_2"; -		case CommandID::PW_SAFE_ERASE_SLOT: -			return "PW_SAFE_ERASE_SLOT"; -		case CommandID::PW_SAFE_ENABLE: -			return "PW_SAFE_ENABLE"; -		case CommandID::PW_SAFE_INIT_KEY: -			return "PW_SAFE_INIT_KEY"; -		case CommandID::PW_SAFE_SEND_DATA: -			return "PW_SAFE_SEND_DATA"; -		case CommandID::SD_CARD_HIGH_WATERMARK: -			return "SD_CARD_HIGH_WATERMARK"; -		case CommandID::DETECT_SC_AES: -			return "DETECT_SC_AES"; -		case CommandID::NEW_AES_KEY: -			return "NEW_AES_KEY"; -	} -	return "UNKNOWN"; +    case CommandID::GET_PW_SAFE_SLOT_STATUS: +      return "GET_PW_SAFE_SLOT_STATUS"; +    case CommandID::GET_PW_SAFE_SLOT_NAME: +      return "GET_PW_SAFE_SLOT_NAME"; +    case CommandID::GET_PW_SAFE_SLOT_PASSWORD: +      return "GET_PW_SAFE_SLOT_PASSWORD"; +    case CommandID::GET_PW_SAFE_SLOT_LOGINNAME: +      return "GET_PW_SAFE_SLOT_LOGINNAME"; +    case CommandID::SET_PW_SAFE_SLOT_DATA_1: +      return "SET_PW_SAFE_SLOT_DATA_1"; +    case CommandID::SET_PW_SAFE_SLOT_DATA_2: +      return "SET_PW_SAFE_SLOT_DATA_2"; +    case CommandID::PW_SAFE_ERASE_SLOT: +      return "PW_SAFE_ERASE_SLOT"; +    case CommandID::PW_SAFE_ENABLE: +      return "PW_SAFE_ENABLE"; +    case CommandID::PW_SAFE_INIT_KEY: +      return "PW_SAFE_INIT_KEY"; +    case CommandID::PW_SAFE_SEND_DATA: +      return "PW_SAFE_SEND_DATA"; +    case CommandID::SD_CARD_HIGH_WATERMARK: +      return "SD_CARD_HIGH_WATERMARK"; +    case CommandID::DETECT_SC_AES: +      return "DETECT_SC_AES"; +    case CommandID::NEW_AES_KEY: +      return "NEW_AES_KEY"; +  } +  return "UNKNOWN";  } -  }  } @@ -11,66 +11,65 @@ using namespace nitrokey::device;  using namespace nitrokey::log;  Device::Device() -: m_vid(0), m_pid(0), -  m_retry_count(4), -  m_retry_timeout(50), -  mp_devhandle(NULL) {} +    : m_vid(0), +      m_pid(0), +      m_retry_count(4), +      m_retry_timeout(50), +      mp_devhandle(NULL) {}  bool Device::disconnect() { -	Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); +  Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); -	hid_exit(); -	mp_devhandle = NULL; -	return true; +  hid_exit(); +  mp_devhandle = NULL; +  return true;  }  bool Device::connect() { -	Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); +  Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); -	//hid_init(); -	mp_devhandle = hid_open(m_vid, m_pid, NULL); -	//hid_init(); -	return mp_devhandle != NULL; +  // hid_init(); +  mp_devhandle = hid_open(m_vid, m_pid, NULL); +  // hid_init(); +  return mp_devhandle != NULL;  }  CommError Device::send(const void *packet) { -	Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); +  Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); -	if (mp_devhandle == NULL) -		throw std::runtime_error("Attempted HID send on an invalid descriptor."); +  if (mp_devhandle == NULL) +    throw std::runtime_error("Attempted HID send on an invalid descriptor."); -	return (CommError)( -		hid_send_feature_report(mp_devhandle, (const unsigned char *)(packet), -			HID_REPORT_SIZE)); +  return (CommError)(hid_send_feature_report( +      mp_devhandle, (const unsigned char *)(packet), HID_REPORT_SIZE));  }  CommError Device::recv(void *packet) { -	CommError status; -	int retry_count = 0; +  CommError status; +  int retry_count = 0; -	Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); -        std::this_thread::sleep_for( std::chrono::milliseconds(5000) ); //FIXME remove timeout in favor of sync communication +  Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); +  std::this_thread::sleep_for(std::chrono::milliseconds( +      5000));  // FIXME remove timeout in favor of sync communication -	if (mp_devhandle == NULL) -		throw std::runtime_error("Attempted HID receive on an invalid descriptor."); +  if (mp_devhandle == NULL) +    throw std::runtime_error("Attempted HID receive on an invalid descriptor."); -	for(;;) { -		status = (CommError)( -			hid_get_feature_report(mp_devhandle, (unsigned char *)(packet), -				HID_REPORT_SIZE)); -		if ((int)status >0 || retry_count++ >= m_retry_count) -			break; -		std::this_thread::sleep_for(m_retry_timeout); -	} +  for (;;) { +    status = (CommError)(hid_get_feature_report( +        mp_devhandle, (unsigned char *)(packet), HID_REPORT_SIZE)); +    if ((int)status > 0 || retry_count++ >= m_retry_count) break; +    std::this_thread::sleep_for(m_retry_timeout); +  } -	return status; +  return status;  }  Stick10::Stick10() { -	m_vid = 0x20a0; -	m_pid = 0x4108; +  m_vid = 0x20a0; +  m_pid = 0x4108;  }  Stick20::Stick20() { -	m_vid = 0x20a0; -	m_pid = 0x4109; +  m_vid = 0x20a0; +  m_pid = 0x4109;  } diff --git a/include/command.h b/include/command.h index 6a3e8b4..715902d 100644 --- a/include/command.h +++ b/include/command.h @@ -7,19 +7,16 @@  namespace nitrokey {  namespace proto { -template <CommandID cmd_id>  +template <CommandID cmd_id>  class Command : semantics::non_constructible { -public: -	constexpr static CommandID command_id() { -		return cmd_id; -	} + public: +  constexpr static CommandID command_id() { return cmd_id; } -	template<typename T> -	static std::string dissect(const T &) { -		return std::string("Payload dissection is unavailable"); -	} +  template <typename T> +  static std::string dissect(const T &) { +    return std::string("Payload dissection is unavailable"); +  }  }; -  }  } diff --git a/include/command_id.h b/include/command_id.h index 124855b..37aa5d2 100644 --- a/include/command_id.h +++ b/include/command_id.h @@ -6,81 +6,80 @@ namespace nitrokey {  namespace proto {  enum class CommandID : uint8_t { -	GET_STATUS                     = 0x00, -	WRITE_TO_SLOT                  = 0x01, -	READ_SLOT_NAME                 = 0x02, -	READ_SLOT                      = 0x03, -	GET_CODE                       = 0x04, -	WRITE_CONFIG                   = 0x05, -	ERASE_SLOT                     = 0x06, -	FIRST_AUTHENTICATE             = 0x07, -	AUTHORIZE                      = 0x08, -	GET_PASSWORD_RETRY_COUNT       = 0x09, -	CLEAR_WARNING                  = 0x0A, -	SET_TIME                       = 0x0B, -	TEST_COUNTER                   = 0x0C, -	TEST_TIME                      = 0x0D, -	USER_AUTHENTICATE              = 0x0E, -	GET_USER_PASSWORD_RETRY_COUNT  = 0x0F, -	USER_AUTHORIZE                 = 0x10, -	UNLOCK_USER_PASSWORD           = 0x11, -	LOCK_DEVICE                    = 0x12, -	FACTORY_RESET                  = 0x13, -	CHANGE_USER_PIN                = 0x14, -	CHANGE_ADMIN_PIN               = 0x15, +  GET_STATUS = 0x00, +  WRITE_TO_SLOT = 0x01, +  READ_SLOT_NAME = 0x02, +  READ_SLOT = 0x03, +  GET_CODE = 0x04, +  WRITE_CONFIG = 0x05, +  ERASE_SLOT = 0x06, +  FIRST_AUTHENTICATE = 0x07, +  AUTHORIZE = 0x08, +  GET_PASSWORD_RETRY_COUNT = 0x09, +  CLEAR_WARNING = 0x0A, +  SET_TIME = 0x0B, +  TEST_COUNTER = 0x0C, +  TEST_TIME = 0x0D, +  USER_AUTHENTICATE = 0x0E, +  GET_USER_PASSWORD_RETRY_COUNT = 0x0F, +  USER_AUTHORIZE = 0x10, +  UNLOCK_USER_PASSWORD = 0x11, +  LOCK_DEVICE = 0x12, +  FACTORY_RESET = 0x13, +  CHANGE_USER_PIN = 0x14, +  CHANGE_ADMIN_PIN = 0x15, -	ENABLE_CRYPTED_PARI = 0x20, -	DISABLE_CRYPTED_PARI, -	ENABLE_HIDDEN_CRYPTED_PARI, -	DISABLE_HIDDEN_CRYPTED_PARI, -	ENABLE_FIRMWARE_UPDATE, -	EXPORT_FIRMWARE_TO_FILE, -	GENERATE_NEW_KEYS, -	FILL_SD_CARD_WITH_RANDOM_CHARS, +  ENABLE_CRYPTED_PARI = 0x20, +  DISABLE_CRYPTED_PARI, +  ENABLE_HIDDEN_CRYPTED_PARI, +  DISABLE_HIDDEN_CRYPTED_PARI, +  ENABLE_FIRMWARE_UPDATE, +  EXPORT_FIRMWARE_TO_FILE, +  GENERATE_NEW_KEYS, +  FILL_SD_CARD_WITH_RANDOM_CHARS, -	WRITE_STATUS_DATA, -	ENABLE_READONLY_UNCRYPTED_LUN, -	ENABLE_READWRITE_UNCRYPTED_LUN, +  WRITE_STATUS_DATA, +  ENABLE_READONLY_UNCRYPTED_LUN, +  ENABLE_READWRITE_UNCRYPTED_LUN, -	SEND_PASSWORD_MATRIX, -	SEND_PASSWORD_MATRIX_PINDATA, -	SEND_PASSWORD_MATRIX_SETUP, +  SEND_PASSWORD_MATRIX, +  SEND_PASSWORD_MATRIX_PINDATA, +  SEND_PASSWORD_MATRIX_SETUP, -	GET_DEVICE_STATUS, -	SEND_DEVICE_STATUS, +  GET_DEVICE_STATUS, +  SEND_DEVICE_STATUS, -	SEND_HIDDEN_VOLUME_PASSWORD, -	SEND_HIDDEN_VOLUME_SETUP, -	SEND_PASSWORD, -	SEND_NEW_PASSWORD, -	CLEAR_NEW_SD_CARD_FOUND, +  SEND_HIDDEN_VOLUME_PASSWORD, +  SEND_HIDDEN_VOLUME_SETUP, +  SEND_PASSWORD, +  SEND_NEW_PASSWORD, +  CLEAR_NEW_SD_CARD_FOUND, -	SEND_STARTUP, -	SEND_CLEAR_STICK_KEYS_NOT_INITIATED, -	SEND_LOCK_STICK_HARDWARE, +  SEND_STARTUP, +  SEND_CLEAR_STICK_KEYS_NOT_INITIATED, +  SEND_LOCK_STICK_HARDWARE, -	PRODUCTION_TEST, -	SEND_DEBUG_DATA, +  PRODUCTION_TEST, +  SEND_DEBUG_DATA, -	CHANGE_UPDATE_PIN, +  CHANGE_UPDATE_PIN, -	GET_PW_SAFE_SLOT_STATUS			= 0x60, -	GET_PW_SAFE_SLOT_NAME      		= 0x61, -	GET_PW_SAFE_SLOT_PASSWORD  		= 0x62, -	GET_PW_SAFE_SLOT_LOGINNAME 		= 0x63, -	SET_PW_SAFE_SLOT_DATA_1    		= 0x64, -	SET_PW_SAFE_SLOT_DATA_2    		= 0x65, -	PW_SAFE_ERASE_SLOT         		= 0x66, -	PW_SAFE_ENABLE             		= 0x67, -	PW_SAFE_INIT_KEY           		= 0x68, -	PW_SAFE_SEND_DATA          		= 0x69, -	SD_CARD_HIGH_WATERMARK     		= 0x70, -	DETECT_SC_AES              		= 0x6a, -	NEW_AES_KEY                		= 0x6b +  GET_PW_SAFE_SLOT_STATUS = 0x60, +  GET_PW_SAFE_SLOT_NAME = 0x61, +  GET_PW_SAFE_SLOT_PASSWORD = 0x62, +  GET_PW_SAFE_SLOT_LOGINNAME = 0x63, +  SET_PW_SAFE_SLOT_DATA_1 = 0x64, +  SET_PW_SAFE_SLOT_DATA_2 = 0x65, +  PW_SAFE_ERASE_SLOT = 0x66, +  PW_SAFE_ENABLE = 0x67, +  PW_SAFE_INIT_KEY = 0x68, +  PW_SAFE_SEND_DATA = 0x69, +  SD_CARD_HIGH_WATERMARK = 0x70, +  DETECT_SC_AES = 0x6a, +  NEW_AES_KEY = 0x6b  }; -const char * commandid_to_string(CommandID id); - +const char *commandid_to_string(CommandID id);  }  }  #endif diff --git a/include/cxx_semantics.h b/include/cxx_semantics.h index f5d3dca..b846317 100644 --- a/include/cxx_semantics.h +++ b/include/cxx_semantics.h @@ -7,9 +7,9 @@   *	There's no need to include Boost for a simple subset this project needs.   */  namespace semantics { -	class non_constructible { -		non_constructible() {} -	}; +class non_constructible { +  non_constructible() {} +};  }  #endif diff --git a/include/device.h b/include/device.h index 943fe1a..768ac32 100644 --- a/include/device.h +++ b/include/device.h @@ -11,60 +11,58 @@  namespace nitrokey {  namespace device { -enum class CommError  -{ -	ERR_NO_ERROR = 0, -	ERR_NOT_CONNECTED = -1, -	ERR_WRONG_RESPONSE_CRC = -2, -	ERR_SENDING = -3, -	ERR_STATUS_NOT_OK = -4 +enum class CommError { +  ERR_NO_ERROR = 0, +  ERR_NOT_CONNECTED = -1, +  ERR_WRONG_RESPONSE_CRC = -2, +  ERR_SENDING = -3, +  ERR_STATUS_NOT_OK = -4  };  class Device { -public: -	Device(); + public: +  Device(); -	// lack of device is not actually an error, -	// so it doesn't throw -	virtual bool connect();  -	virtual bool disconnect();  +  // lack of device is not actually an error, +  // so it doesn't throw +  virtual bool connect(); +  virtual bool disconnect(); -	/* -	 *	Sends packet of HID_REPORT_SIZE. -	 */ -	virtual CommError send(const void *packet); +  /* +   *	Sends packet of HID_REPORT_SIZE. +   */ +  virtual CommError send(const void *packet); -	/* -	 *	Gets packet of HID_REPORT_SIZE. -	 *	Can sleep. See below. -	 */ -	virtual CommError recv(void *packet); +  /* +   *	Gets packet of HID_REPORT_SIZE. +   *	Can sleep. See below. +   */ +  virtual CommError recv(void *packet); -protected: -	uint16_t m_vid; -	uint16_t m_pid; + protected: +  uint16_t m_vid; +  uint16_t m_pid; -	/* -	 *	While the project uses Signal11 portable HIDAPI -	 *	library, there's no way of doing it asynchronously, -	 *	hence polling. -	 */ -	int m_retry_count; -	std::chrono::milliseconds m_retry_timeout; +  /* +   *	While the project uses Signal11 portable HIDAPI +   *	library, there's no way of doing it asynchronously, +   *	hence polling. +   */ +  int m_retry_count; +  std::chrono::milliseconds m_retry_timeout; -	hid_device *mp_devhandle; +  hid_device *mp_devhandle;  };  class Stick10 : public Device { -public: -	Stick10(); + public: +  Stick10();  };  class Stick20 : public Device { -public: -	Stick20(); + public: +  Stick20();  }; -  }  }  #endif diff --git a/include/device_proto.h b/include/device_proto.h index c8f1ff2..142b45b 100644 --- a/include/device_proto.h +++ b/include/device_proto.h @@ -23,10 +23,10 @@  #define PWS_PASSWORD_LENGTH 20  #define PWS_LOGINNAME_LENGTH 32 -#define PWS_SEND_PASSWORD     0 -#define PWS_SEND_LOGINNAME    1 -#define PWS_SEND_TAB          2 -#define PWS_SEND_CR           3 +#define PWS_SEND_PASSWORD 0 +#define PWS_SEND_LOGINNAME 1 +#define PWS_SEND_TAB 2 +#define PWS_SEND_CR 3  namespace nitrokey {  namespace proto { @@ -42,46 +42,42 @@ namespace proto {   */  template <CommandID cmd_id, typename Payload>  struct HIDReport { -	uint8_t _zero; -	CommandID command_id; // uint8_t -	union { -		uint8_t _padding[HID_REPORT_SIZE - 6]; -		Payload payload; -	} __packed; -	uint32_t crc; - -	// POD types can't have non-default constructors -	// used in Transaction<>::run() -	void initialize() { -		bzero(this, sizeof *this); -		command_id = cmd_id; -	} - -	uint32_t calculate_CRC() const { -		// w/o leading zero, a part of each HID packet -		// w/o 4-byte crc -		return misc::stm_crc32((const uint8_t *)(this) + 1, -							(size_t)(HID_REPORT_SIZE - 5)); -	} - -	void update_CRC() { -		crc = calculate_CRC(); -	} - -	bool isCRCcorrect() const { -		return crc == calculate_CRC(); -	} - -	bool isValid() const { -		return true; -//		return !_zero && payload.isValid() && isCRCcorrect(); -	} - -	operator std::string() const { -		// Packet type is known upfront in normal operation. -		// Can't be used to dissect random packets. -		return QueryDissector<cmd_id, decltype(*this)>::dissect(*this); -	} +  uint8_t _zero; +  CommandID command_id;  // uint8_t +  union { +    uint8_t _padding[HID_REPORT_SIZE - 6]; +    Payload payload; +  } __packed; +  uint32_t crc; + +  // POD types can't have non-default constructors +  // used in Transaction<>::run() +  void initialize() { +    bzero(this, sizeof *this); +    command_id = cmd_id; +  } + +  uint32_t calculate_CRC() const { +    // w/o leading zero, a part of each HID packet +    // w/o 4-byte crc +    return misc::stm_crc32((const uint8_t *)(this) + 1, +                           (size_t)(HID_REPORT_SIZE - 5)); +  } + +  void update_CRC() { crc = calculate_CRC(); } + +  bool isCRCcorrect() const { return crc == calculate_CRC(); } + +  bool isValid() const { +    return true; +    //		return !_zero && payload.isValid() && isCRCcorrect(); +  } + +  operator std::string() const { +    // Packet type is known upfront in normal operation. +    // Can't be used to dissect random packets. +    return QueryDissector<cmd_id, decltype(*this)>::dissect(*this); +  }  } __packed;  /* @@ -92,131 +88,117 @@ struct HIDReport {   */  template <CommandID cmd_id, typename ResponsePayload>  struct DeviceResponse { -	uint8_t _zero; -	uint8_t device_status; -	uint8_t command_id; // originally last_command_type -	uint32_t last_command_crc; -	uint8_t	last_command_status; -	union { -		uint8_t _padding[HID_REPORT_SIZE - 12]; -		ResponsePayload payload; -	} __packed; -	uint32_t crc; - -	void initialize() { -		bzero(this, sizeof *this); -	} - -	uint32_t calculate_CRC() const { -		// w/o leading zero, a part of each HID packet -		// w/o 4-byte crc -		return misc::stm_crc32((const uint8_t *)(this) + 1, -							(size_t)(HID_REPORT_SIZE - 5)); -	} - -	void update_CRC() { -		crc = calculate_CRC(); -	} - -	bool isCRCcorrect() const { -		return crc == calculate_CRC(); -	} - -	bool isValid() const { -//		return !_zero && payload.isValid() && isCRCcorrect() && -//				command_id == (uint8_t)(cmd_id); -		return true; -	} - -	operator std::string() const { -		return ResponseDissector<cmd_id, decltype(*this)>::dissect(*this); -	} +  uint8_t _zero; +  uint8_t device_status; +  uint8_t command_id;  // originally last_command_type +  uint32_t last_command_crc; +  uint8_t last_command_status; +  union { +    uint8_t _padding[HID_REPORT_SIZE - 12]; +    ResponsePayload payload; +  } __packed; +  uint32_t crc; + +  void initialize() { bzero(this, sizeof *this); } + +  uint32_t calculate_CRC() const { +    // w/o leading zero, a part of each HID packet +    // w/o 4-byte crc +    return misc::stm_crc32((const uint8_t *)(this) + 1, +                           (size_t)(HID_REPORT_SIZE - 5)); +  } + +  void update_CRC() { crc = calculate_CRC(); } + +  bool isCRCcorrect() const { return crc == calculate_CRC(); } + +  bool isValid() const { +    //		return !_zero && payload.isValid() && isCRCcorrect() && +    //				command_id == (uint8_t)(cmd_id); +    return true; +  } + +  operator std::string() const { +    return ResponseDissector<cmd_id, decltype(*this)>::dissect(*this); +  }  } __packed;  struct EmptyPayload { -	uint8_t _data[]; +  uint8_t _data[]; -	bool isValid() const { -		return true; -	} +  bool isValid() const { return true; } -	std::string dissect() const { -		return std::string("Empty Payload."); -	} +  std::string dissect() const { return std::string("Empty Payload."); }  } __packed; -template<CommandID cmd_id, typename command_payload, -							typename response_payload> +template <CommandID cmd_id, typename command_payload, typename response_payload>  class Transaction : semantics::non_constructible { -public: -	// Types declared in command class scope can't be reached from there. -	typedef command_payload CommandPayload; -	typedef response_payload ResponsePayload; - -	typedef struct HIDReport<cmd_id, CommandPayload> OutgoingPacket; -	typedef struct DeviceResponse<cmd_id, ResponsePayload> ResponsePacket; - -	static_assert(std::is_pod<OutgoingPacket>::value, -					"outgoingpacket must be a pod type"); -	static_assert(std::is_pod<ResponsePacket>::value, -					"ResponsePacket must be a POD type"); -	static_assert(sizeof(OutgoingPacket) == HID_REPORT_SIZE, -					"OutgoingPacket type is not the right size"); -	static_assert(sizeof(ResponsePacket) == HID_REPORT_SIZE, -					"ResponsePacket type is not the right size"); - -	static response_payload run(device::Device &dev, -			const command_payload &payload) { -		using namespace ::nitrokey::device; -		using namespace ::nitrokey::log; - -		Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); - -		CommError status; -		OutgoingPacket outp; -		ResponsePacket resp; - -		// POD types can't have non-default constructors -		outp.initialize(); -		resp.initialize(); - -		outp.payload = payload; -		outp.update_CRC(); - -		Log::instance()("Outgoing HID packet:", Loglevel::DEBUG); -		Log::instance()((std::string)(outp), Loglevel::DEBUG); - -		if (!outp.isValid()) -			throw std::runtime_error("Invalid outgoing packet"); - -		status = dev.send(&outp); -		if ((int)(status) < 0 && status != CommError::ERR_NO_ERROR)  -			throw std::runtime_error( -				std::string("Device error while sending command ") + -				std::to_string((int)(status))); - -		status = dev.recv(&resp); -		if ((int)(status) < 0 && status != CommError::ERR_NO_ERROR)  -			throw std::runtime_error( -				std::string("Device error while executing command ") + -				std::to_string((int)(status))); - -		Log::instance()("Incoming HID packet:", Loglevel::DEBUG); -		Log::instance()((std::string)(resp), Loglevel::DEBUG); - -		if (!resp.isValid()) -			throw std::runtime_error("Invalid incoming packet"); - -		// See: DeviceResponse -		return resp.payload; -	} - -	static response_payload run(device::Device &dev) { -		command_payload empty_payload; -		return run(dev, empty_payload); -	} + public: +  // Types declared in command class scope can't be reached from there. +  typedef command_payload CommandPayload; +  typedef response_payload ResponsePayload; + +  typedef struct HIDReport<cmd_id, CommandPayload> OutgoingPacket; +  typedef struct DeviceResponse<cmd_id, ResponsePayload> ResponsePacket; + +  static_assert(std::is_pod<OutgoingPacket>::value, +                "outgoingpacket must be a pod type"); +  static_assert(std::is_pod<ResponsePacket>::value, +                "ResponsePacket must be a POD type"); +  static_assert(sizeof(OutgoingPacket) == HID_REPORT_SIZE, +                "OutgoingPacket type is not the right size"); +  static_assert(sizeof(ResponsePacket) == HID_REPORT_SIZE, +                "ResponsePacket type is not the right size"); + +  static response_payload run(device::Device &dev, +                              const command_payload &payload) { +    using namespace ::nitrokey::device; +    using namespace ::nitrokey::log; + +    Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2); + +    CommError status; +    OutgoingPacket outp; +    ResponsePacket resp; + +    // POD types can't have non-default constructors +    outp.initialize(); +    resp.initialize(); + +    outp.payload = payload; +    outp.update_CRC(); + +    Log::instance()("Outgoing HID packet:", Loglevel::DEBUG); +    Log::instance()((std::string)(outp), Loglevel::DEBUG); + +    if (!outp.isValid()) throw std::runtime_error("Invalid outgoing packet"); + +    status = dev.send(&outp); +    if ((int)(status) < 0 && status != CommError::ERR_NO_ERROR) +      throw std::runtime_error( +          std::string("Device error while sending command ") + +          std::to_string((int)(status))); + +    status = dev.recv(&resp); +    if ((int)(status) < 0 && status != CommError::ERR_NO_ERROR) +      throw std::runtime_error( +          std::string("Device error while executing command ") + +          std::to_string((int)(status))); + +    Log::instance()("Incoming HID packet:", Loglevel::DEBUG); +    Log::instance()((std::string)(resp), Loglevel::DEBUG); + +    if (!resp.isValid()) throw std::runtime_error("Invalid incoming packet"); + +    // See: DeviceResponse +    return resp.payload; +  } + +  static response_payload run(device::Device &dev) { +    command_payload empty_payload; +    return run(dev, empty_payload); +  }  }; -  }  }  #endif diff --git a/include/dissect.h b/include/dissect.h index e2ddc02..f552950 100644 --- a/include/dissect.h +++ b/include/dissect.h @@ -15,68 +15,67 @@ namespace proto {  template <CommandID id, class HIDPacket>  class QueryDissector : semantics::non_constructible { -public: -	static std::string dissect(const HIDPacket &pod) { -		std::stringstream out; + public: +  static std::string dissect(const HIDPacket &pod) { +    std::stringstream out; -		out << "Raw HID packet:" << std::endl; -		out << ::nitrokey::misc::hexdump((const char *)(&pod), sizeof pod); +    out << "Raw HID packet:" << std::endl; +    out << ::nitrokey::misc::hexdump((const char *)(&pod), sizeof pod); -		out << "Contents:" << std::endl; -		out << "Command ID:\t" << commandid_to_string((CommandID)(pod.command_id)) << std::endl; -		out << "CRC:\t" << pod.crc << std::endl; +    out << "Contents:" << std::endl; +    out << "Command ID:\t" << commandid_to_string((CommandID)(pod.command_id)) +        << std::endl; +    out << "CRC:\t" << pod.crc << std::endl; -		out << "Payload:" << std::endl; -		out << pod.payload.dissect(); -		return out.str(); -	} +    out << "Payload:" << std::endl; +    out << pod.payload.dissect(); +    return out.str(); +  }  }; -  template <CommandID id, class HIDPacket>  class ResponseDissector : semantics::non_constructible { -public: -	static std::string dissect(const HIDPacket &pod) { -		std::stringstream out; - + public: +  static std::string dissect(const HIDPacket &pod) { +    std::stringstream out; -                // FIXME use values from firmware (possibly generate separate  -                // header automatically) -                std::string status[4]; -                status[0] = " STATUS_READY"; -                status[1]= " STATUS_BUSY"; -                status[2]= " STATUS_ERROR"; -                status[3]= " STATUS_RECEIVED_REPORT"; -                std::string cmd[11]; -                cmd[0]= " CMD_STATUS_OK"; -                cmd[1]= " CMD_STATUS_WRONG_CRC"; -                cmd[2]= " CMD_STATUS_WRONG_SLOT"; -                cmd[3]= " CMD_STATUS_SLOT_NOT_PROGRAMMED"; -                cmd[4]= " CMD_STATUS_WRONG_PASSWORD"; -                cmd[5]= " CMD_STATUS_NOT_AUTHORIZED"; -                cmd[6]= " CMD_STATUS_TIMESTAMP_WARNING"; -                cmd[7]= " CMD_STATUS_NO_NAME_ERROR"; -                cmd[8]= " CMD_STATUS_NOT_SUPPORTED"; -                cmd[9]= " CMD_STATUS_UNKNOWN_COMMAND"; -                cmd[10]= " CMD_STATUS_AES_DEC_FAILED"; -                  +    // FIXME use values from firmware (possibly generate separate +    // header automatically) +    std::string status[4]; +    status[0] = " STATUS_READY"; +    status[1] = " STATUS_BUSY"; +    status[2] = " STATUS_ERROR"; +    status[3] = " STATUS_RECEIVED_REPORT"; +    std::string cmd[11]; +    cmd[0] = " CMD_STATUS_OK"; +    cmd[1] = " CMD_STATUS_WRONG_CRC"; +    cmd[2] = " CMD_STATUS_WRONG_SLOT"; +    cmd[3] = " CMD_STATUS_SLOT_NOT_PROGRAMMED"; +    cmd[4] = " CMD_STATUS_WRONG_PASSWORD"; +    cmd[5] = " CMD_STATUS_NOT_AUTHORIZED"; +    cmd[6] = " CMD_STATUS_TIMESTAMP_WARNING"; +    cmd[7] = " CMD_STATUS_NO_NAME_ERROR"; +    cmd[8] = " CMD_STATUS_NOT_SUPPORTED"; +    cmd[9] = " CMD_STATUS_UNKNOWN_COMMAND"; +    cmd[10] = " CMD_STATUS_AES_DEC_FAILED"; -		out << "Raw HID packet:" << std::endl; -		out << ::nitrokey::misc::hexdump((const char *)(&pod), sizeof pod); +    out << "Raw HID packet:" << std::endl; +    out << ::nitrokey::misc::hexdump((const char *)(&pod), sizeof pod); -		out << "Device status:\t" << pod.device_status + 0<<" "<< cmd[ pod.device_status ] << std::endl; -		out << "Command ID:\t" << commandid_to_string((CommandID)(pod.command_id)) << std::endl; -		out << "Last command CRC:\t" << pod.last_command_crc << std::endl; -		out << "Last command status:\t" << pod.last_command_status + 0<<" "<<status[pod.last_command_status] << std::endl; -		out << "CRC:\t" << pod.crc << std::endl; +    out << "Device status:\t" << pod.device_status + 0 << " " +        << cmd[pod.device_status] << std::endl; +    out << "Command ID:\t" << commandid_to_string((CommandID)(pod.command_id)) +        << std::endl; +    out << "Last command CRC:\t" << pod.last_command_crc << std::endl; +    out << "Last command status:\t" << pod.last_command_status + 0 << " " +        << status[pod.last_command_status] << std::endl; +    out << "CRC:\t" << pod.crc << std::endl; -		out << "Payload:" << std::endl; -		out << pod.payload.dissect(); -		return out.str(); -	} +    out << "Payload:" << std::endl; +    out << pod.payload.dissect(); +    return out.str(); +  }  }; - -  }  } diff --git a/include/log.h b/include/log.h index f6f7193..8eda4fb 100644 --- a/include/log.h +++ b/include/log.h @@ -6,57 +6,44 @@  namespace nitrokey {  namespace log { -enum class Loglevel : int { -	DEBUG_L2, -	DEBUG, -	INFO, -	WARNING, -	ERROR -}; +enum class Loglevel : int { DEBUG_L2, DEBUG, INFO, WARNING, ERROR };  class LogHandler { -public: -	virtual void print(const std::string &, Loglevel lvl) = 0; + public: +  virtual void print(const std::string &, Loglevel lvl) = 0; -protected: -	std::string loglevel_to_str(Loglevel); + protected: +  std::string loglevel_to_str(Loglevel);  };  class StdlogHandler : public LogHandler { -public: -	virtual void print(const std::string &, Loglevel lvl); + public: +  virtual void print(const std::string &, Loglevel lvl);  };  extern StdlogHandler stdlog_handler;  class Log { -public: -	Log() -	: mp_loghandler(&stdlog_handler), m_loglevel(Loglevel::WARNING) {} + public: +  Log() : mp_loghandler(&stdlog_handler), m_loglevel(Loglevel::WARNING) {} -	static Log &instance() { -		if (mp_instance == NULL) -			mp_instance = new Log; -		return *mp_instance; -	} +  static Log &instance() { +    if (mp_instance == NULL) mp_instance = new Log; +    return *mp_instance; +  } -	void operator()(const std::string &, Loglevel); +  void operator()(const std::string &, Loglevel); -	void set_loglevel(Loglevel lvl) { -		m_loglevel = lvl; -	} +  void set_loglevel(Loglevel lvl) { m_loglevel = lvl; } -	void set_handler(LogHandler *handler) { -		mp_loghandler = handler; -	} +  void set_handler(LogHandler *handler) { mp_loghandler = handler; } -private: -	Loglevel m_loglevel; -	LogHandler *mp_loghandler; + private: +  Loglevel m_loglevel; +  LogHandler *mp_loghandler; -	static Log *mp_instance; +  static Log *mp_instance;  }; -  }  } diff --git a/include/misc.h b/include/misc.h index bf68915..07f221c 100644 --- a/include/misc.h +++ b/include/misc.h @@ -8,7 +8,6 @@ namespace misc {  std::string hexdump(const char *p, size_t size);  uint32_t stm_crc32(const uint8_t *data, size_t size); -  }  } diff --git a/include/stick10_commands.h b/include/stick10_commands.h index de31e95..b140e99 100644 --- a/include/stick10_commands.h +++ b/include/stick10_commands.h @@ -12,571 +12,486 @@ namespace proto {   *	Stick10 protocol definition   */  namespace stick10 { -		class GetSlotName : public Command<CommandID::READ_SLOT_NAME> {  -		public: -			// reachable as a typedef in Transaction -			struct CommandPayload { -				uint8_t slot_number; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			struct ResponsePayload { -				uint8_t slot_name[15]; - -				bool isValid() const { -					return true; -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct ResponsePayload> CommandTransaction; -		}; - -		class EraseSlot : Command<CommandID::ERASE_SLOT> { -		public: -			struct CommandPayload { -				uint8_t slot_number; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct EmptyPayload> CommandTransaction; -		}; - -		class SetTime : Command<CommandID::SET_TIME> { -		public: -			struct CommandPayload { -				uint8_t		reset; // 0 - get time, 1 - set time -				uint64_t	time; // posix time - -				bool isValid() const { -					return reset && reset != 1; -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct EmptyPayload> CommandTransaction; -		}; - -		// TODO duplicate TOTP -		class WriteToHOTPSlot : Command<CommandID::WRITE_TO_SLOT> { -		public: -			struct CommandPayload { -				uint8_t slot_number; -				uint8_t slot_name[15]; -				uint8_t slot_secret[20]; -				uint8_t slot_config; -				uint8_t slot_token_id[13]; -				uint8_t slot_counter[8]; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			typedef Transaction<command_id(), -							struct CommandPayload, -							struct EmptyPayload> CommandTransaction; -		}; - -		class WriteToTOTPSlot : Command<CommandID::WRITE_TO_SLOT> { -		public: -			struct CommandPayload { -				uint8_t slot_number; -				uint8_t slot_name[15]; -				uint8_t slot_secret[20]; -				uint8_t slot_config; -				uint8_t slot_token_id[13]; -				uint16_t slot_interval; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct EmptyPayload> CommandTransaction; -		}; - -		class GetCode : Command<CommandID::GET_CODE> { -		public: -			struct CommandPayload { -				uint8_t slot_number; -				uint64_t challenge; -				uint64_t last_totp_time; -				uint8_t	last_interval; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			struct ResponsePayload { -				uint8_t code[18]; - -				bool isValid() const { -					return true; -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct ResponsePayload> CommandTransaction; -		}; - -		class GetHOTP : Command<CommandID::GET_CODE> { -		public: -			struct CommandPayload { -				uint8_t slot_number; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct EmptyPayload> CommandTransaction; -		}; - -		class ReadSlot : Command<CommandID::READ_SLOT> { -		public: -			struct CommandPayload { -				uint8_t slot_number; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} - -				std::string dissect() const { -					std::stringstream ss; -					ss << "slot_number:\t" << (int)(slot_number) << std::endl; -					return ss.str(); -				} -			} __packed; - -			struct ResponsePayload { -				uint8_t slot_name[15]; -				uint8_t config; -				uint8_t token_id[13]; -				uint64_t counter; - -				bool isValid() const { -					return true; -				} - -				std::string dissect() const { -					std::stringstream ss; -					ss << "slot_name:\t" << slot_name << std::endl; -					ss << "config:\t" << config << std::endl; -					ss << "token_id:\t" << token_id << std::endl; -					ss << "counter:\t" << counter << std::endl; -					return ss.str(); -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct ResponsePayload> CommandTransaction; -		}; - -		class GetStatus : Command<CommandID::GET_STATUS> { -		public: -			struct ResponsePayload { -				uint16_t firmware_version; -				uint8_t	card_serial[4]; -				uint8_t	general_config[3]; -				uint8_t	otp_password_config[2]; - -				bool isValid() const { -					return true; -				} - -				std::string dissect() const { -					std::stringstream ss; -					ss << "firmware_version:\t" << firmware_version << std::endl; -					ss << "card_serial:\t" -					   << ::nitrokey::misc::hexdump((const char *)(card_serial), sizeof card_serial); -					ss << "general_config:\t" -					   << ::nitrokey::misc::hexdump((const char *)(general_config), sizeof general_config); -					ss << "otp_password_config:\t" -					   << ::nitrokey::misc::hexdump((const char *)(otp_password_config), sizeof otp_password_config); -					return ss.str(); -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct EmptyPayload, -								struct ResponsePayload> CommandTransaction; -		}; - -		class GetPasswordRetryCount : Command<CommandID::GET_PASSWORD_RETRY_COUNT> { -		public: -			struct ResponsePayload { -				uint8_t password_retry_count; - -				bool isValid() const { -					return true; -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct EmptyPayload, -								struct ResponsePayload> CommandTransaction; -		}; - -		class GetUserPasswordRetryCount : Command<CommandID::GET_USER_PASSWORD_RETRY_COUNT> { -		public: -			struct ResponsePayload { -				uint8_t password_retry_count; - -				bool isValid() const { -					return true; -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct EmptyPayload, -								struct ResponsePayload> CommandTransaction; -		}; - -		class GetPasswordSafeSlotStatus : Command<CommandID::GET_PW_SAFE_SLOT_STATUS> { -		public: -			struct ResponsePayload { -				uint8_t password_safe_status[PWS_SLOT_COUNT]; - -				bool isValid() const { -					return true; -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct EmptyPayload, -								struct ResponsePayload> CommandTransaction; -		}; - -		class GetPasswordSafeSlotName : Command<CommandID::GET_PW_SAFE_SLOT_NAME> { -		public: -			struct CommandPayload { -				uint8_t slot_number; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			struct ResponsePayload { -				uint8_t slot_name[PWS_SLOTNAME_LENGTH]; - -				bool isValid() const { -					return true; -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct ResponsePayload> CommandTransaction; -		}; - -		class GetPasswordSafeSlotPassword : Command<CommandID::GET_PW_SAFE_SLOT_PASSWORD> { -		public: -			struct CommandPayload { -				uint8_t slot_number; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			struct ResponsePayload { -				uint8_t slot_password[PWS_PASSWORD_LENGTH]; - -				bool isValid() const { -					return true; -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct ResponsePayload> CommandTransaction; -		}; - -		class GetPasswordSafeSlotLogin : Command<CommandID::GET_PW_SAFE_SLOT_LOGINNAME> { -		public: -			struct CommandPayload { -				uint8_t slot_number; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			struct ResponsePayload { -				uint8_t slot_login[PWS_LOGINNAME_LENGTH]; - -				bool isValid() const { -					return true; -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct ResponsePayload> CommandTransaction; -		}; - -		class SetPasswordSafeSlotData : Command<CommandID::SET_PW_SAFE_SLOT_DATA_1> { -		public: -			struct CommandPayload { -				uint8_t slot_number; -				uint8_t slot_name[PWS_SLOTNAME_LENGTH]; -				uint8_t slot_password[PWS_PASSWORD_LENGTH]; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct EmptyPayload> CommandTransaction; -		}; - -		class SetPasswordSafeSlotData2 : Command<CommandID::SET_PW_SAFE_SLOT_DATA_2> { -		public: -			struct CommandPayload { -				uint8_t slot_number; -				uint8_t slot_name[PWS_SLOTNAME_LENGTH]; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct EmptyPayload> CommandTransaction; -		}; - -		class ErasePasswordSafeSlot : Command<CommandID::PW_SAFE_ERASE_SLOT> { -		public: -			struct CommandPayload { -				uint8_t slot_number; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct EmptyPayload> CommandTransaction; -		}; - -		class EnablePasswordSafe : Command<CommandID::PW_SAFE_ENABLE> { -		public: -			struct CommandPayload { -				uint8_t password[30]; - -				bool isValid() const { -					return true; -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct EmptyPayload> CommandTransaction; -		}; - -		class PasswordSafeInitKey : Command<CommandID::PW_SAFE_INIT_KEY> { -		public: -			typedef Transaction<command_id(), -								struct EmptyPayload, -								struct EmptyPayload> CommandTransaction; -		}; - -		// TODO naming screwed up, see above -		class PasswordSafeSendSlotViaHID: Command<CommandID::PW_SAFE_SEND_DATA> { -		public: -			struct CommandPayload { -				uint8_t slot_number; -				uint8_t slot_kind; - -				bool isValid() const { -					return !(slot_number & 0xF0); -				} -			} __packed; - -			typedef Transaction<command_id(), -								struct CommandPayload, -								struct EmptyPayload> CommandTransaction; -		}; - - -		// TODO "Device::passwordSafeSendSlotDataViaHID" - -		class WriteGeneralConfig : Command<CommandID::WRITE_CONFIG> { -		public: -			struct CommandPayload { -				uint8_t	config[5]; -			} __packed; - -			typedef Transaction<command_id(), -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class FirstAuthenticate : Command<CommandID::FIRST_AUTHENTICATE> { -		public: -			struct CommandPayload { -				uint8_t card_password[25]; -				uint8_t temporary_password[25]; - -				bool isValid() const { -					return true; -				} - -				std::string dissect() const { -					std::stringstream ss; -					ss << "card_password:\t" << card_password << std::endl; -					ss << "temporary_password:\t" << temporary_password << std::endl; -					return ss.str(); -				} -			} __packed; - -			typedef Transaction<command_id(), -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class UserAuthenticate : Command<CommandID::USER_AUTHENTICATE> { -		public: -			struct CommandPayload { -				uint8_t card_password[25]; -				uint8_t temporary_password[25]; - -				bool isValid() const { -					return true; -				} -			} __packed; - -			typedef Transaction<command_id(), -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class Authorize : Command<CommandID::AUTHORIZE> { -		public: -			struct CommandPayload { -				uint8_t crc[4]; -				uint8_t password[25]; -			} __packed; - -			typedef Transaction<command_id(), -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class UserAuthorize : Command<CommandID::USER_AUTHORIZE> { -		public: -			struct CommandPayload { -				uint8_t crc[4]; -				uint8_t password[25]; -			} __packed; - -			typedef Transaction<command_id(), -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class UnlockUserPassword : Command<CommandID::UNLOCK_USER_PASSWORD> { -		public: -			struct CommandPayload { -				uint8_t admin_password[20]; // TODO -			} __packed; - -			// TODO could we get the stick to return the retry count? - -			typedef Transaction<command_id(), -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class ChangeUserPin : Command<CommandID::CHANGE_USER_PIN> { -		public: -			struct CommandPayload { -				uint8_t old_pin[25]; -				uint8_t new_pin[25]; -			} __packed; - -			typedef Transaction<command_id(), -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		// TODO why is it needed? -		class IsAESSupported : Command<CommandID::DETECT_SC_AES> { -		public: -			struct CommandPayload { -				uint8_t password[20]; -			} __packed; - -			typedef Transaction<command_id(), -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class ChangeAdminPin : Command<CommandID::CHANGE_ADMIN_PIN> { -		public: -			struct CommandPayload { -				uint8_t old_pin[25]; -				uint8_t new_pin[25]; -			} __packed; - -			typedef Transaction<command_id(), -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class LockDevice : Command<CommandID::LOCK_DEVICE> { -		public: -			typedef Transaction<command_id(), -									struct EmptyPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class FactoryReset : Command<CommandID::FACTORY_RESET> { -		public: -			struct CommandPayload { -				uint8_t password[20]; -			} __packed; - -			typedef Transaction<command_id(), -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class BuildAESKey : Command<CommandID::NEW_AES_KEY> { -		public: -			struct CommandPayload { -				uint8_t password[20]; -			} __packed; - -			typedef Transaction<command_id(), -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; +class GetSlotName : public Command<CommandID::READ_SLOT_NAME> { + public: +  // reachable as a typedef in Transaction +  struct CommandPayload { +    uint8_t slot_number; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  struct ResponsePayload { +    uint8_t slot_name[15]; + +    bool isValid() const { return true; } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, +                      struct ResponsePayload> CommandTransaction; +}; + +class EraseSlot : Command<CommandID::ERASE_SLOT> { + public: +  struct CommandPayload { +    uint8_t slot_number; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class SetTime : Command<CommandID::SET_TIME> { + public: +  struct CommandPayload { +    uint8_t reset;  // 0 - get time, 1 - set time +    uint64_t time;  // posix time + +    bool isValid() const { return reset && reset != 1; } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +// TODO duplicate TOTP +class WriteToHOTPSlot : Command<CommandID::WRITE_TO_SLOT> { + public: +  struct CommandPayload { +    uint8_t slot_number; +    uint8_t slot_name[15]; +    uint8_t slot_secret[20]; +    uint8_t slot_config; +    uint8_t slot_token_id[13]; +    uint8_t slot_counter[8]; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class WriteToTOTPSlot : Command<CommandID::WRITE_TO_SLOT> { + public: +  struct CommandPayload { +    uint8_t slot_number; +    uint8_t slot_name[15]; +    uint8_t slot_secret[20]; +    uint8_t slot_config; +    uint8_t slot_token_id[13]; +    uint16_t slot_interval; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class GetCode : Command<CommandID::GET_CODE> { + public: +  struct CommandPayload { +    uint8_t slot_number; +    uint64_t challenge; +    uint64_t last_totp_time; +    uint8_t last_interval; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  struct ResponsePayload { +    uint8_t code[18]; + +    bool isValid() const { return true; } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, +                      struct ResponsePayload> CommandTransaction; +}; + +class GetHOTP : Command<CommandID::GET_CODE> { + public: +  struct CommandPayload { +    uint8_t slot_number; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class ReadSlot : Command<CommandID::READ_SLOT> { + public: +  struct CommandPayload { +    uint8_t slot_number; + +    bool isValid() const { return !(slot_number & 0xF0); } + +    std::string dissect() const { +      std::stringstream ss; +      ss << "slot_number:\t" << (int)(slot_number) << std::endl; +      return ss.str(); +    } +  } __packed; + +  struct ResponsePayload { +    uint8_t slot_name[15]; +    uint8_t config; +    uint8_t token_id[13]; +    uint64_t counter; + +    bool isValid() const { return true; } + +    std::string dissect() const { +      std::stringstream ss; +      ss << "slot_name:\t" << slot_name << std::endl; +      ss << "config:\t" << config << std::endl; +      ss << "token_id:\t" << token_id << std::endl; +      ss << "counter:\t" << counter << std::endl; +      return ss.str(); +    } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, +                      struct ResponsePayload> CommandTransaction; +}; + +class GetStatus : Command<CommandID::GET_STATUS> { + public: +  struct ResponsePayload { +    uint16_t firmware_version; +    uint8_t card_serial[4]; +    uint8_t general_config[3]; +    uint8_t otp_password_config[2]; + +    bool isValid() const { return true; } + +    std::string dissect() const { +      std::stringstream ss; +      ss << "firmware_version:\t" << firmware_version << std::endl; +      ss << "card_serial:\t" +         << ::nitrokey::misc::hexdump((const char *)(card_serial), +                                      sizeof card_serial); +      ss << "general_config:\t" +         << ::nitrokey::misc::hexdump((const char *)(general_config), +                                      sizeof general_config); +      ss << "otp_password_config:\t" +         << ::nitrokey::misc::hexdump((const char *)(otp_password_config), +                                      sizeof otp_password_config); +      return ss.str(); +    } +  } __packed; + +  typedef Transaction<command_id(), struct EmptyPayload, struct ResponsePayload> +      CommandTransaction; +}; + +class GetPasswordRetryCount : Command<CommandID::GET_PASSWORD_RETRY_COUNT> { + public: +  struct ResponsePayload { +    uint8_t password_retry_count; + +    bool isValid() const { return true; } +  } __packed; + +  typedef Transaction<command_id(), struct EmptyPayload, struct ResponsePayload> +      CommandTransaction; +}; + +class GetUserPasswordRetryCount +    : Command<CommandID::GET_USER_PASSWORD_RETRY_COUNT> { + public: +  struct ResponsePayload { +    uint8_t password_retry_count; + +    bool isValid() const { return true; } +  } __packed; + +  typedef Transaction<command_id(), struct EmptyPayload, struct ResponsePayload> +      CommandTransaction; +}; + +class GetPasswordSafeSlotStatus : Command<CommandID::GET_PW_SAFE_SLOT_STATUS> { + public: +  struct ResponsePayload { +    uint8_t password_safe_status[PWS_SLOT_COUNT]; + +    bool isValid() const { return true; } +  } __packed; + +  typedef Transaction<command_id(), struct EmptyPayload, struct ResponsePayload> +      CommandTransaction; +}; + +class GetPasswordSafeSlotName : Command<CommandID::GET_PW_SAFE_SLOT_NAME> { + public: +  struct CommandPayload { +    uint8_t slot_number; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  struct ResponsePayload { +    uint8_t slot_name[PWS_SLOTNAME_LENGTH]; + +    bool isValid() const { return true; } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, +                      struct ResponsePayload> CommandTransaction; +}; + +class GetPasswordSafeSlotPassword +    : Command<CommandID::GET_PW_SAFE_SLOT_PASSWORD> { + public: +  struct CommandPayload { +    uint8_t slot_number; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  struct ResponsePayload { +    uint8_t slot_password[PWS_PASSWORD_LENGTH]; + +    bool isValid() const { return true; } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, +                      struct ResponsePayload> CommandTransaction; +}; + +class GetPasswordSafeSlotLogin +    : Command<CommandID::GET_PW_SAFE_SLOT_LOGINNAME> { + public: +  struct CommandPayload { +    uint8_t slot_number; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  struct ResponsePayload { +    uint8_t slot_login[PWS_LOGINNAME_LENGTH]; + +    bool isValid() const { return true; } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, +                      struct ResponsePayload> CommandTransaction; +}; + +class SetPasswordSafeSlotData : Command<CommandID::SET_PW_SAFE_SLOT_DATA_1> { + public: +  struct CommandPayload { +    uint8_t slot_number; +    uint8_t slot_name[PWS_SLOTNAME_LENGTH]; +    uint8_t slot_password[PWS_PASSWORD_LENGTH]; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class SetPasswordSafeSlotData2 : Command<CommandID::SET_PW_SAFE_SLOT_DATA_2> { + public: +  struct CommandPayload { +    uint8_t slot_number; +    uint8_t slot_name[PWS_SLOTNAME_LENGTH]; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class ErasePasswordSafeSlot : Command<CommandID::PW_SAFE_ERASE_SLOT> { + public: +  struct CommandPayload { +    uint8_t slot_number; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class EnablePasswordSafe : Command<CommandID::PW_SAFE_ENABLE> { + public: +  struct CommandPayload { +    uint8_t password[30]; + +    bool isValid() const { return true; } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class PasswordSafeInitKey : Command<CommandID::PW_SAFE_INIT_KEY> { + public: +  typedef Transaction<command_id(), struct EmptyPayload, struct EmptyPayload> +      CommandTransaction; +}; + +// TODO naming screwed up, see above +class PasswordSafeSendSlotViaHID : Command<CommandID::PW_SAFE_SEND_DATA> { + public: +  struct CommandPayload { +    uint8_t slot_number; +    uint8_t slot_kind; + +    bool isValid() const { return !(slot_number & 0xF0); } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +// TODO "Device::passwordSafeSendSlotDataViaHID" + +class WriteGeneralConfig : Command<CommandID::WRITE_CONFIG> { + public: +  struct CommandPayload { +    uint8_t config[5]; +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class FirstAuthenticate : Command<CommandID::FIRST_AUTHENTICATE> { + public: +  struct CommandPayload { +    uint8_t card_password[25]; +    uint8_t temporary_password[25]; + +    bool isValid() const { return true; } + +    std::string dissect() const { +      std::stringstream ss; +      ss << "card_password:\t" << card_password << std::endl; +      ss << "temporary_password:\t" << temporary_password << std::endl; +      return ss.str(); +    } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class UserAuthenticate : Command<CommandID::USER_AUTHENTICATE> { + public: +  struct CommandPayload { +    uint8_t card_password[25]; +    uint8_t temporary_password[25]; + +    bool isValid() const { return true; } +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class Authorize : Command<CommandID::AUTHORIZE> { + public: +  struct CommandPayload { +    uint8_t crc[4]; +    uint8_t password[25]; +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class UserAuthorize : Command<CommandID::USER_AUTHORIZE> { + public: +  struct CommandPayload { +    uint8_t crc[4]; +    uint8_t password[25]; +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class UnlockUserPassword : Command<CommandID::UNLOCK_USER_PASSWORD> { + public: +  struct CommandPayload { +    uint8_t admin_password[20];  // TODO +  } __packed; + +  // TODO could we get the stick to return the retry count? + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class ChangeUserPin : Command<CommandID::CHANGE_USER_PIN> { + public: +  struct CommandPayload { +    uint8_t old_pin[25]; +    uint8_t new_pin[25]; +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +// TODO why is it needed? +class IsAESSupported : Command<CommandID::DETECT_SC_AES> { + public: +  struct CommandPayload { +    uint8_t password[20]; +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class ChangeAdminPin : Command<CommandID::CHANGE_ADMIN_PIN> { + public: +  struct CommandPayload { +    uint8_t old_pin[25]; +    uint8_t new_pin[25]; +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class LockDevice : Command<CommandID::LOCK_DEVICE> { + public: +  typedef Transaction<command_id(), struct EmptyPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class FactoryReset : Command<CommandID::FACTORY_RESET> { + public: +  struct CommandPayload { +    uint8_t password[20]; +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +}; + +class BuildAESKey : Command<CommandID::NEW_AES_KEY> { + public: +  struct CommandPayload { +    uint8_t password[20]; +  } __packed; + +  typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload> +      CommandTransaction; +};  } -  }  }  #endif diff --git a/include/stick20_commands.h b/include/stick20_commands.h index 22b7e9a..b84d436 100644 --- a/include/stick20_commands.h +++ b/include/stick20_commands.h @@ -10,238 +10,222 @@ namespace proto {  *	a superset of STICK10  */  namespace stick20 { -		class EnableEncryptedPartition : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t password[30]; // TODO check w/ firmware -			}; - -			typedef Transaction<CommandID::ENABLE_CRYPTED_PARI, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class DisableEncryptedPartition : semantics::non_constructible { -		public: -			typedef Transaction<CommandID::DISABLE_CRYPTED_PARI, -									struct EmptyPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class EnableHiddenEncryptedPartition : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t password[30]; // TODO check w/ firmware -			}; - -			typedef Transaction<CommandID::ENABLE_HIDDEN_CRYPTED_PARI, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class DisableHiddenEncryptedPartition : semantics::non_constructible { -		public: -			typedef Transaction<CommandID::DISABLE_CRYPTED_PARI, -									struct EmptyPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class EnableFirmwareUpdate : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t password[30]; // TODO check w/ firmware -			}; - -			typedef Transaction<CommandID::ENABLE_FIRMWARE_UPDATE, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class UpdatePassword : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t old_password[15]; -				uint8_t new_password[15]; -			}; - -			typedef Transaction<CommandID::CHANGE_UPDATE_PIN, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class ExportFirmware : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t password[30]; -			}; - -			typedef Transaction<CommandID::EXPORT_FIRMWARE_TO_FILE, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class CreateNewKeys : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t password[30]; -			}; - -			typedef Transaction<CommandID::GENERATE_NEW_KEYS, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class FillSDCardWithRandomChars : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t volume_flag; -				uint8_t password[30]; -			}; - -			typedef Transaction<CommandID::FILL_SD_CARD_WITH_RANDOM_CHARS, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class SetupHiddenVolume : semantics::non_constructible { -		public: -			typedef Transaction<CommandID::SEND_HIDDEN_VOLUME_SETUP, -									struct EmptyPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class SendPasswordMatrix : semantics::non_constructible { -		public: -			typedef Transaction<CommandID::SEND_PASSWORD_MATRIX, -									struct EmptyPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class SendPasswordMatrixPinData : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t pin_data[30]; // TODO how long actually can it be? -			}; - -			typedef Transaction<CommandID::SEND_PASSWORD_MATRIX_PINDATA, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class SendPasswordMatrixSetup : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t setup_data[30]; // TODO how long actually can it be? -			}; - -			typedef Transaction<CommandID::SEND_PASSWORD_MATRIX_SETUP, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class GetDeviceStatus : semantics::non_constructible { -		public: -			typedef Transaction<CommandID::GET_DEVICE_STATUS, -									struct EmptyPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class SendPassword : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t password[30]; -			}; - -			typedef Transaction<CommandID::SEND_PASSWORD, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class SendNewPassword : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t password[30]; -			}; - -			typedef Transaction<CommandID::SEND_NEW_PASSWORD, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		// TODO fix original nomenclature -		class SendSetReadonlyToUncryptedVolume : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t password[30]; -			}; - -			typedef Transaction<CommandID::ENABLE_READWRITE_UNCRYPTED_LUN, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class SendSetReadwriteToUncryptedVolume : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t password[30]; -			}; - -			typedef Transaction<CommandID::ENABLE_READWRITE_UNCRYPTED_LUN, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class SendClearNewSdCardFound : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t password[30]; -			}; - -			typedef Transaction<CommandID::CLEAR_NEW_SD_CARD_FOUND, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class SendStartup : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint64_t localtime; // POSIX -			}; - -			typedef Transaction<CommandID::SEND_STARTUP, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class SendHiddenVolumeSetup : semantics::non_constructible { -		public: -			struct CommandPayload { -				// TODO HiddenVolumeSetup_tst type -			}; - -			typedef Transaction<CommandID::SEND_HIDDEN_VOLUME_SETUP, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class LockFirmware : semantics::non_constructible { -		public: -			struct CommandPayload { -				uint8_t password[30]; -			}; - -			typedef Transaction<CommandID::SEND_LOCK_STICK_HARDWARE, -									struct CommandPayload, -									struct EmptyPayload> CommandTransaction; -		}; - -		class ProductionTest : semantics::non_constructible { -		public: -			typedef Transaction<CommandID::PRODUCTION_TEST, -									struct EmptyPayload, -									struct EmptyPayload> CommandTransaction; -		}; - +class EnableEncryptedPartition : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t password[30];  // TODO check w/ firmware +  }; + +  typedef Transaction<CommandID::ENABLE_CRYPTED_PARI, struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class DisableEncryptedPartition : semantics::non_constructible { + public: +  typedef Transaction<CommandID::DISABLE_CRYPTED_PARI, struct EmptyPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class EnableHiddenEncryptedPartition : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t password[30];  // TODO check w/ firmware +  }; + +  typedef Transaction<CommandID::ENABLE_HIDDEN_CRYPTED_PARI, +                      struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class DisableHiddenEncryptedPartition : semantics::non_constructible { + public: +  typedef Transaction<CommandID::DISABLE_CRYPTED_PARI, struct EmptyPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class EnableFirmwareUpdate : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t password[30];  // TODO check w/ firmware +  }; + +  typedef Transaction<CommandID::ENABLE_FIRMWARE_UPDATE, struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class UpdatePassword : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t old_password[15]; +    uint8_t new_password[15]; +  }; + +  typedef Transaction<CommandID::CHANGE_UPDATE_PIN, struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class ExportFirmware : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t password[30]; +  }; + +  typedef Transaction<CommandID::EXPORT_FIRMWARE_TO_FILE, struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class CreateNewKeys : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t password[30]; +  }; + +  typedef Transaction<CommandID::GENERATE_NEW_KEYS, struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class FillSDCardWithRandomChars : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t volume_flag; +    uint8_t password[30]; +  }; + +  typedef Transaction<CommandID::FILL_SD_CARD_WITH_RANDOM_CHARS, +                      struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class SetupHiddenVolume : semantics::non_constructible { + public: +  typedef Transaction<CommandID::SEND_HIDDEN_VOLUME_SETUP, struct EmptyPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class SendPasswordMatrix : semantics::non_constructible { + public: +  typedef Transaction<CommandID::SEND_PASSWORD_MATRIX, struct EmptyPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class SendPasswordMatrixPinData : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t pin_data[30];  // TODO how long actually can it be? +  }; + +  typedef Transaction<CommandID::SEND_PASSWORD_MATRIX_PINDATA, +                      struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class SendPasswordMatrixSetup : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t setup_data[30];  // TODO how long actually can it be? +  }; + +  typedef Transaction<CommandID::SEND_PASSWORD_MATRIX_SETUP, +                      struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class GetDeviceStatus : semantics::non_constructible { + public: +  typedef Transaction<CommandID::GET_DEVICE_STATUS, struct EmptyPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class SendPassword : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t password[30]; +  }; + +  typedef Transaction<CommandID::SEND_PASSWORD, struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class SendNewPassword : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t password[30]; +  }; + +  typedef Transaction<CommandID::SEND_NEW_PASSWORD, struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +// TODO fix original nomenclature +class SendSetReadonlyToUncryptedVolume : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t password[30]; +  }; + +  typedef Transaction<CommandID::ENABLE_READWRITE_UNCRYPTED_LUN, +                      struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class SendSetReadwriteToUncryptedVolume : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t password[30]; +  }; + +  typedef Transaction<CommandID::ENABLE_READWRITE_UNCRYPTED_LUN, +                      struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class SendClearNewSdCardFound : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t password[30]; +  }; + +  typedef Transaction<CommandID::CLEAR_NEW_SD_CARD_FOUND, struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class SendStartup : semantics::non_constructible { + public: +  struct CommandPayload { +    uint64_t localtime;  // POSIX +  }; + +  typedef Transaction<CommandID::SEND_STARTUP, struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class SendHiddenVolumeSetup : semantics::non_constructible { + public: +  struct CommandPayload { +    // TODO HiddenVolumeSetup_tst type +  }; + +  typedef Transaction<CommandID::SEND_HIDDEN_VOLUME_SETUP, +                      struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class LockFirmware : semantics::non_constructible { + public: +  struct CommandPayload { +    uint8_t password[30]; +  }; + +  typedef Transaction<CommandID::SEND_LOCK_STICK_HARDWARE, +                      struct CommandPayload, +                      struct EmptyPayload> CommandTransaction; +}; + +class ProductionTest : semantics::non_constructible { + public: +  typedef Transaction<CommandID::PRODUCTION_TEST, struct EmptyPayload, +                      struct EmptyPayload> CommandTransaction; +};  }  }  } @@ -11,34 +11,32 @@ Log *Log::mp_instance = NULL;  StdlogHandler stdlog_handler;  std::string LogHandler::loglevel_to_str(Loglevel lvl) { -	switch (lvl) { -		case Loglevel::DEBUG_L2: -			return std::string("DEBUG_L2"); -		case Loglevel::DEBUG: -			return std::string("DEBUG"); -		case Loglevel::INFO: -			return std::string("INFO"); -		case Loglevel::WARNING: -			return std::string("WARNING"); -		case Loglevel::ERROR: -			return std::string("ERROR"); -	} -	return std::string(""); +  switch (lvl) { +    case Loglevel::DEBUG_L2: +      return std::string("DEBUG_L2"); +    case Loglevel::DEBUG: +      return std::string("DEBUG"); +    case Loglevel::INFO: +      return std::string("INFO"); +    case Loglevel::WARNING: +      return std::string("WARNING"); +    case Loglevel::ERROR: +      return std::string("ERROR"); +  } +  return std::string("");  }  void Log::operator()(const std::string &logstr, Loglevel lvl) { -	if (mp_loghandler != NULL) -		if ((int)(lvl) >= (int)(m_loglevel)) -			mp_loghandler->print(logstr, lvl); +  if (mp_loghandler != NULL) +    if ((int)(lvl) >= (int)(m_loglevel)) mp_loghandler->print(logstr, lvl);  }  void StdlogHandler::print(const std::string &str, Loglevel lvl) { -    std::time_t t = std::time(nullptr); -    std::tm tm = *std::localtime(&t);  +  std::time_t t = std::time(nullptr); +  std::tm tm = *std::localtime(&t); -	std::clog << "[" << loglevel_to_str(lvl) << "] [" -			  << std::put_time(&tm, "%c %Z") <<  "]\t" << str << std::endl; +  std::clog << "[" << loglevel_to_str(lvl) << "] [" +            << std::put_time(&tm, "%c %Z") << "]\t" << str << std::endl;  } -  }  } @@ -6,46 +6,44 @@  namespace nitrokey {  namespace misc { -std::string hexdump(const char *p, size_t size) {  -	std::stringstream out; -	char formatbuf[128]; -	const char *pstart = p; - -	for (const char *pend = p + size; p < pend;) { -		snprintf(formatbuf, 128, "%04x\t", p - pstart); -		out << formatbuf; - -		for (const char *le = p + 16; p < le && p < pend; p++) { -			snprintf(formatbuf, 128, "%02x ", uint8_t(*p)); -			out << formatbuf; -		} -		out << std::endl; -	} -	return out.str(); +std::string hexdump(const char *p, size_t size) { +  std::stringstream out; +  char formatbuf[128]; +  const char *pstart = p; + +  for (const char *pend = p + size; p < pend;) { +    snprintf(formatbuf, 128, "%04x\t", p - pstart); +    out << formatbuf; + +    for (const char *le = p + 16; p < le && p < pend; p++) { +      snprintf(formatbuf, 128, "%02x ", uint8_t(*p)); +      out << formatbuf; +    } +    out << std::endl; +  } +  return out.str();  } -static uint32_t _crc32 (uint32_t crc, uint32_t data) -{ -	int i; -    crc = crc ^ data; +static uint32_t _crc32(uint32_t crc, uint32_t data) { +  int i; +  crc = crc ^ data; -    for (i = 0; i < 32; i++) { -        if (crc & 0x80000000) -            crc = (crc << 1) ^ 0x04C11DB7;  // polynomial used in STM32 -        else -            crc = (crc << 1); -	} +  for (i = 0; i < 32; i++) { +    if (crc & 0x80000000) +      crc = (crc << 1) ^ 0x04C11DB7;  // polynomial used in STM32 +    else +      crc = (crc << 1); +  } -    return crc; +  return crc;  }  uint32_t stm_crc32(const uint8_t *data, size_t size) { -	uint32_t crc = 0xffffffff; -	const uint32_t *pend = (const uint32_t *)(data + size); -	for (const uint32_t *p = (const uint32_t *)(data); p < pend; p++) -		crc = _crc32(crc, *p); -	return crc; +  uint32_t crc = 0xffffffff; +  const uint32_t *pend = (const uint32_t *)(data + size); +  for (const uint32_t *p = (const uint32_t *)(data); p < pend; p++) +    crc = _crc32(crc, *p); +  return crc;  } -  }  } diff --git a/unittest/test.cc b/unittest/test.cc index 8f6a27a..2c77b60 100644 --- a/unittest/test.cc +++ b/unittest/test.cc @@ -12,28 +12,27 @@ using namespace nitrokey::device;  using namespace nitrokey::proto::stick10;  using namespace nitrokey::log; - -std::string getSlotName(Stick10& stick, int slotNo){ -        ReadSlot::CommandTransaction::CommandPayload slot_req; -        slot_req.slot_number = slotNo; -        auto slot = ReadSlot::CommandTransaction::run(stick, slot_req); -        std::string sName(reinterpret_cast<char*>(slot.slot_name)); -        return sName; +std::string getSlotName(Stick10 &stick, int slotNo) { +  ReadSlot::CommandTransaction::CommandPayload slot_req; +  slot_req.slot_number = slotNo; +  auto slot = ReadSlot::CommandTransaction::run(stick, slot_req); +  std::string sName(reinterpret_cast<char *>(slot.slot_name)); +  return sName;  } -TEST_CASE( "Slot names are correct", "[slotNames]" ) { -	Stick10 stick; -        stick.connect(); +TEST_CASE("Slot names are correct", "[slotNames]") { +  Stick10 stick; +  stick.connect(); -	Log::instance().set_loglevel(Loglevel::DEBUG_L2); +  Log::instance().set_loglevel(Loglevel::DEBUG_L2); -		auto resp = GetStatus::CommandTransaction::run(stick); +  auto resp = GetStatus::CommandTransaction::run(stick); -		FirstAuthenticate::CommandTransaction::CommandPayload authreq; -		strcpy((char *)(authreq.card_password), "12345678"); -		FirstAuthenticate::CommandTransaction::run(stick, authreq); +  FirstAuthenticate::CommandTransaction::CommandPayload authreq; +  strcpy((char *)(authreq.card_password), "12345678"); +  FirstAuthenticate::CommandTransaction::run(stick, authreq); -            REQUIRE( getSlotName(stick, 0x20) == std::string("1")  );  -            REQUIRE( getSlotName(stick, 0x21) == std::string("slot2")  );  -        stick.disconnect(); +  REQUIRE(getSlotName(stick, 0x20) == std::string("1")); +  REQUIRE(getSlotName(stick, 0x21) == std::string("slot2")); +  stick.disconnect();  } | 
