aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/NitrokeyManager.h16
-rw-r--r--include/device.h2
-rw-r--r--include/device_proto.h5
-rw-r--r--include/stick10_commands.h126
4 files changed, 89 insertions, 60 deletions
diff --git a/include/NitrokeyManager.h b/include/NitrokeyManager.h
index 4f1dcfa..7bc2673 100644
--- a/include/NitrokeyManager.h
+++ b/include/NitrokeyManager.h
@@ -21,10 +21,12 @@ namespace nitrokey {
static NitrokeyManager *instance();
bool first_authenticate(const char *pin, const char *temporary_password);
- bool write_HOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint64_t hotp_counter,
- bool use_8_digits, const char *temporary_password);
- bool write_TOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret,
- uint16_t time_window, bool use_8_digits, const char *temporary_password);
+ bool write_HOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint8_t hotp_counter,
+ bool use_8_digits, bool use_enter, bool use_tokenID, const char *token_ID,
+ const char *temporary_password);
+ bool write_TOTP_slot(uint8_t slot_number, const char *slot_name, const char *secret, uint16_t time_window,
+ bool use_8_digits, bool use_enter, bool use_tokenID, const char *token_ID,
+ const char *temporary_password);
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);
@@ -68,13 +70,15 @@ namespace nitrokey {
void build_aes_key(const char *admin_password);
- void unlock_user_password(const char *admin_password);
+ void unlock_user_password(const char *admin_password, const char *new_user_password);
- void write_config(bool numlock, bool capslock, bool scrolllock, bool enable_user_password,
+ void write_config(uint8_t numlock, uint8_t capslock, uint8_t scrolllock, bool enable_user_password,
bool delete_user_password, const char *admin_temporary_password);
vector<uint8_t> read_config();
+ bool is_AES_supported(const char *user_password);
+
private:
NitrokeyManager();
~NitrokeyManager();
diff --git a/include/device.h b/include/device.h
index ffc38e5..0553d2e 100644
--- a/include/device.h
+++ b/include/device.h
@@ -50,7 +50,7 @@ public:
std::chrono::milliseconds get_retry_timeout() const { return m_retry_timeout; };
std::chrono::milliseconds get_send_receive_delay() const {return m_send_receive_delay;}
- int get_last_command_status() const;
+ 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;}
diff --git a/include/device_proto.h b/include/device_proto.h
index 6e21f9f..78abe38 100644
--- a/include/device_proto.h
+++ b/include/device_proto.h
@@ -215,11 +215,14 @@ class Transaction : semantics::non_constructible {
Log::instance()("Incoming HID packet:", Loglevel::DEBUG);
Log::instance()((std::string)(resp), Loglevel::DEBUG);
+ Log::instance()(std::string("Retry count: ") + std::to_string(retry), Loglevel::DEBUG);
if (!resp.isValid()) throw std::runtime_error("Invalid incoming packet");
+ if (retry <= 0) throw std::runtime_error("Maximum retry count reached for receiving response from the device!");
if (resp.last_command_status!=0) throw CommandFailedException(resp.command_id, resp.last_command_status);
- // See: DeviceResponse
+
+ // See: DeviceResponse
return resp.payload;
}
diff --git a/include/stick10_commands.h b/include/stick10_commands.h
index 6df8727..ef83747 100644
--- a/include/stick10_commands.h
+++ b/include/stick10_commands.h
@@ -81,7 +81,6 @@ class SetTime : Command<CommandID::SET_TIME> {
};
-// TODO duplicate TOTP
class WriteToHOTPSlot : Command<CommandID::WRITE_TO_SLOT> {
public:
struct CommandPayload {
@@ -96,7 +95,15 @@ class WriteToHOTPSlot : Command<CommandID::WRITE_TO_SLOT> {
bool use_tokenID : 1;
};
};
- uint8_t slot_token_id[13];
+ 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;
+ };
uint64_t slot_counter;
bool isValid() const { return !(slot_number & 0xF0); }
@@ -137,7 +144,15 @@ class WriteToTOTPSlot : Command<CommandID::WRITE_TO_SLOT> {
bool use_tokenID : 1;
};
};
- uint8_t slot_token_id[13];
+ 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;
+ };
uint16_t slot_interval;
bool isValid() const { return !(slot_number & 0xF0); } //TODO check
@@ -160,27 +175,6 @@ class WriteToTOTPSlot : Command<CommandID::WRITE_TO_SLOT> {
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 GetTOTP : Command<CommandID::GET_CODE> {
public:
struct CommandPayload {
@@ -202,18 +196,28 @@ class GetTOTP : Command<CommandID::GET_CODE> {
struct ResponsePayload {
union {
- uint8_t whole_response[18]; //TODO remove if not needed
+ uint8_t whole_response[18]; //14 bytes reserved for config, but used only 1
struct {
uint32_t code;
- uint8_t config;
- } __packed;
- } __packed;
+ union{
+ uint8_t _slot_config;
+ struct{
+ bool use_8_digits : 1;
+ bool use_enter : 1;
+ bool use_tokenID : 1;
+ };
+ };
+ } __packed ;
+ } __packed ;
bool isValid() const { return true; }
std::string dissect() const {
std::stringstream ss;
ss << "code:\t" << (code) << std::endl;
- ss << "config:\t" << "TODO" /*(config) */<< std::endl; //TODO show byte field options
+ 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;
return ss.str();
}
} __packed;
@@ -237,10 +241,17 @@ class GetHOTP : Command<CommandID::GET_CODE> {
struct ResponsePayload {
union {
- uint8_t whole_response[18]; //TODO remove if not needed
+ uint8_t whole_response[18]; //14 bytes reserved for config, but used only 1
struct {
uint32_t code;
- uint8_t config;
+ union{
+ uint8_t _slot_config;
+ struct{
+ bool use_8_digits : 1;
+ bool use_enter : 1;
+ bool use_tokenID : 1;
+ };
+ };
} __packed;
} __packed;
@@ -248,7 +259,10 @@ class GetHOTP : Command<CommandID::GET_CODE> {
std::string dissect() const {
std::stringstream ss;
ss << "code:\t" << (code) << std::endl;
- ss << "config:\t" << "TODO" /*(config) */<< std::endl; //TODO show byte field options
+ 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;
return ss.str();
}
} __packed;
@@ -301,14 +315,14 @@ class GetStatus : Command<CommandID::GET_STATUS> {
union {
uint8_t general_config[5];
struct{
- uint8_t numlock;
- uint8_t capslock;
- uint8_t scrolllock;
+ uint8_t numlock; /** 0-1: HOTP slot number from which the code will be get on double press, other value - function disabled */
+ uint8_t capslock; /** same as numlock */
+ uint8_t scrolllock; /** same as numlock */
uint8_t enable_user_password;
uint8_t delete_user_password;
};
};
- bool isValid() const { return true; }
+ bool isValid() const { return enable_user_password!=delete_user_password; }
std::string dissect() const {
std::stringstream ss;
@@ -319,9 +333,9 @@ class GetStatus : Command<CommandID::GET_STATUS> {
ss << "general_config:\t"
<< ::nitrokey::misc::hexdump((const char *)(general_config),
sizeof general_config);
- ss << "numlock:\t" << (bool)numlock << std::endl;
- ss << "capslock:\t" << (bool)capslock << std::endl;
- ss << "scrolllock:\t" << (bool)scrolllock << std::endl;
+ ss << "numlock:\t" << (int)numlock << std::endl;
+ ss << "capslock:\t" << (int)capslock << std::endl;
+ ss << "scrolllock:\t" << (int)scrolllock << std::endl;
ss << "enable_user_password:\t" << (bool) enable_user_password << std::endl;
ss << "delete_user_password:\t" << (bool) delete_user_password << std::endl;
@@ -557,13 +571,18 @@ class EnablePasswordSafe : Command<CommandID::PW_SAFE_ENABLE> {
};
class PasswordSafeInitKey : Command<CommandID::PW_SAFE_INIT_KEY> {
+ /**
+ * never used in Nitrokey App
+ */
public:
typedef Transaction<command_id(), struct EmptyPayload, struct EmptyPayload>
CommandTransaction;
};
-// TODO naming screwed up, see above
class PasswordSafeSendSlotViaHID : Command<CommandID::PW_SAFE_SEND_DATA> {
+ /**
+ * never used in Nitrokey App
+ */
public:
struct CommandPayload {
uint8_t slot_number;
@@ -584,18 +603,18 @@ class WriteGeneralConfig : Command<CommandID::WRITE_CONFIG> {
union{
uint8_t config[5];
struct{
- uint8_t numlock;
- uint8_t capslock;
- uint8_t scrolllock;
+ uint8_t numlock; /** 0-1: HOTP slot number from which the code will be get on double press, other value - function disabled */
+ uint8_t capslock; /** same as numlock */
+ uint8_t scrolllock; /** same as numlock */
uint8_t enable_user_password;
uint8_t delete_user_password;
};
};
std::string dissect() const {
std::stringstream ss;
- ss << "numlock:\t" << (bool)numlock << std::endl;
- ss << "capslock:\t" << (bool)capslock << std::endl;
- ss << "scrolllock:\t" << (bool)scrolllock << std::endl;
+ ss << "numlock:\t" << (int)numlock << std::endl;
+ ss << "capslock:\t" << (int)capslock << std::endl;
+ ss << "scrolllock:\t" << (int)scrolllock << std::endl;
ss << "enable_user_password:\t" << (bool) enable_user_password << std::endl;
ss << "delete_user_password:\t" << (bool) delete_user_password << std::endl;
return ss.str();
@@ -666,7 +685,7 @@ class Authorize : Command<CommandID::AUTHORIZE> {
class UserAuthorize : Command<CommandID::USER_AUTHORIZE> {
public:
struct CommandPayload {
- uint64_t crc_to_authorize;
+ uint32_t crc_to_authorize;
uint8_t temporary_password[25];
std::string dissect() const {
std::stringstream ss;
@@ -683,7 +702,8 @@ class UserAuthorize : Command<CommandID::USER_AUTHORIZE> {
class UnlockUserPassword : Command<CommandID::UNLOCK_USER_PASSWORD> {
public:
struct CommandPayload {
- uint8_t admin_password[20];
+ uint8_t admin_password[25];
+ uint8_t user_new_password[25];
std::string dissect() const {
std::stringstream ss;
ss << " admin_password:\t" << admin_password<< std::endl;
@@ -691,8 +711,6 @@ class UnlockUserPassword : Command<CommandID::UNLOCK_USER_PASSWORD> {
}
} __packed;
- // TODO could we get the stick to return the retry count?
-
typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload>
CommandTransaction;
};
@@ -714,11 +732,15 @@ class ChangeUserPin : Command<CommandID::CHANGE_USER_PIN> {
CommandTransaction;
};
-// TODO why is it needed?
class IsAESSupported : Command<CommandID::DETECT_SC_AES> {
public:
struct CommandPayload {
- uint8_t password[20];
+ uint8_t user_password[20];
+ std::string dissect() const {
+ std::stringstream ss;
+ ss << " user_password:\t" << user_password<< std::endl;
+ return ss.str();
+ }
} __packed;
typedef Transaction<command_id(), struct CommandPayload, struct EmptyPayload>