/*
* Copyright (c) 2015-2018 Nitrokey UG
*
* This file is part of libnitrokey.
*
* libnitrokey is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* libnitrokey is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libnitrokey. If not, see .
*
* SPDX-License-Identifier: LGPL-3.0
*/
#ifndef LIBNITROKEY_STICK10_COMMANDS_0_8_H
#define LIBNITROKEY_STICK10_COMMANDS_0_8_H
#include
#include
#include
#include
#include
#include "command.h"
#include "device_proto.h"
#include "stick10_commands.h"
#pragma pack (push,1)
namespace nitrokey {
namespace proto {
/*
* Stick10 protocol definition
*/
namespace stick10_08 {
using stick10::FirstAuthenticate;
using stick10::UserAuthenticate;
using stick10::SetTime;
using stick10::GetStatus;
using stick10::BuildAESKey;
using stick10::ChangeAdminPin;
using stick10::ChangeUserPin;
using stick10::EnablePasswordSafe;
using stick10::ErasePasswordSafeSlot;
using stick10::FactoryReset;
using stick10::GetPasswordRetryCount;
using stick10::GetUserPasswordRetryCount;
using stick10::GetPasswordSafeSlotLogin;
using stick10::GetPasswordSafeSlotName;
using stick10::GetPasswordSafeSlotPassword;
using stick10::GetPasswordSafeSlotStatus;
using stick10::GetSlotName;
using stick10::IsAESSupported;
using stick10::LockDevice;
using stick10::PasswordSafeInitKey;
using stick10::PasswordSafeSendSlotViaHID;
using stick10::SetPasswordSafeSlotData;
using stick10::SetPasswordSafeSlotData2;
using stick10::UnlockUserPassword;
using stick10::ReadSlot;
class EraseSlot : Command {
public:
struct CommandPayload {
uint8_t slot_number;
uint8_t temporary_admin_password[25];
bool isValid() const { return !(slot_number & 0xF0); }
std::string dissect() const {
std::stringstream ss;
ss << "slot_number:\t" << (int)(slot_number) << std::endl;
hexdump_to_ss(temporary_admin_password);
return ss.str();
}
} __packed;
typedef Transaction
CommandTransaction;
};
class SendOTPData : Command {
//admin auth
public:
struct CommandPayload {
uint8_t temporary_admin_password[25];
uint8_t type; //S-secret, N-name
uint8_t id; //multiple reports for values longer than 30 bytes
uint8_t data[30]; //data, does not need null termination
bool isValid() const { return true; }
void setTypeName(){
type = 'N';
}
void setTypeSecret(){
type = 'S';
}
std::string dissect() const {
std::stringstream ss;
hexdump_to_ss(temporary_admin_password);
ss << "type:\t" << type << std::endl;
ss << "id:\t" << (int)id << std::endl;
#ifdef LOG_VOLATILE_DATA
ss << "data:" << std::endl
<< ::nitrokey::misc::hexdump((const uint8_t *) (&data), sizeof data);
#else
ss << " Volatile data not logged" << std::endl;
#endif
return ss.str();
}
} __packed;
struct ResponsePayload {
union {
uint8_t data[40];
} __packed;
bool isValid() const { return true; }
std::string dissect() const {
std::stringstream ss;
#ifdef LOG_VOLATILE_DATA
ss << "data:" << std::endl
<< ::nitrokey::misc::hexdump((const uint8_t *) (&data), sizeof data);
#else
ss << " Volatile data not logged" << std::endl;
#endif
return ss.str();
}
} __packed;
typedef Transaction
CommandTransaction;
};
class WriteToOTPSlot : Command {
//admin auth
public:
struct CommandPayload {
uint8_t temporary_admin_password[25];
uint8_t slot_number;
union {
uint64_t slot_counter_or_interval;
uint8_t slot_counter_s[8];
} __packed;
union {
uint8_t _slot_config;
struct {
bool use_8_digits : 1;
bool use_enter : 1;
bool use_tokenID : 1;
};
};
union {
uint8_t slot_token_id[13]; /** OATH Token Identifier */
struct { /** @see https://openauthentication.org/token-specs/ */
uint8_t omp[2];
uint8_t tt[2];
uint8_t mui[8];
uint8_t keyboard_layout; //disabled feature in nitroapp as of 20160805
} slot_token_fields;
};
bool isValid() const { return true; }
std::string dissect() const {
std::stringstream ss;
hexdump_to_ss(temporary_admin_password);
ss << "slot_config:\t" << std::bitset<8>((int) _slot_config) << std::endl;
ss << "\tuse_8_digits(0):\t" << use_8_digits << std::endl;
ss << "\tuse_enter(1):\t" << use_enter << std::endl;
ss << "\tuse_tokenID(2):\t" << use_tokenID << std::endl;
ss << "slot_number:\t" << (int) (slot_number) << std::endl;
ss << "slot_counter_or_interval:\t[" << (int) slot_counter_or_interval << "]\t"
<< ::nitrokey::misc::hexdump((const uint8_t *) (&slot_counter_or_interval), sizeof slot_counter_or_interval, false);
ss << "slot_token_id:\t";
for (auto i : slot_token_id)
ss << std::hex << std::setw(2) << std::setfill('0') << (int) i << " ";
ss << std::endl;
return ss.str();
}
} __packed;
typedef Transaction
CommandTransaction;
};
class GetHOTP : Command {
public:
struct CommandPayload {
uint8_t slot_number;
struct {
uint64_t challenge; //@unused
uint64_t last_totp_time; //@unused
uint8_t last_interval; //@unused
} __packed _unused;
uint8_t temporary_user_password[25];
bool isValid() const { return (slot_number & 0xF0); }
std::string dissect() const {
std::stringstream ss;
hexdump_to_ss(temporary_user_password);
ss << "slot_number:\t" << (int)(slot_number) << std::endl;
return ss.str();
}
} __packed;
struct ResponsePayload {
union {
uint8_t whole_response[18]; //14 bytes reserved for config, but used only 1
struct {
uint32_t code;
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 << "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;
typedef Transaction
CommandTransaction;
};
class GetTOTP : Command {
//user auth
public:
struct CommandPayload {
uint8_t slot_number;
uint64_t challenge; //@unused
uint64_t last_totp_time; //@unused
uint8_t last_interval; //@unused
uint8_t temporary_user_password[25];
bool isValid() const { return !(slot_number & 0xF0); }
std::string dissect() const {
std::stringstream ss;
hexdump_to_ss(temporary_user_password);
ss << "slot_number:\t" << (int)(slot_number) << std::endl;
ss << "challenge:\t" << (challenge) << std::endl;
ss << "last_totp_time:\t" << (last_totp_time) << std::endl;
ss << "last_interval:\t" << (int)(last_interval) << std::endl;
return ss.str();
}
} __packed;
struct ResponsePayload {
union {
uint8_t whole_response[18]; //14 bytes reserved for config, but used only 1
struct {
uint32_t code;
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 << "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;
typedef Transaction
CommandTransaction;
};
class WriteGeneralConfig : Command {
//admin auth
public:
struct CommandPayload {
union{
uint8_t config[5];
struct{
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;
};
};
uint8_t temporary_admin_password[25];
static constexpr uint8_t special_HOTP_slots = 3;
bool isValid() const { return numlock < special_HOTP_slots && capslock < special_HOTP_slots
&& scrolllock < special_HOTP_slots && enable_user_password < 2; }
std::string dissect() const {
std::stringstream ss;
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();
}
} __packed;
typedef Transaction
CommandTransaction;
};
}
}
}
#pragma pack (pop)
#endif //LIBNITROKEY_STICK10_COMMANDS_0_8_H