From 4615f5ecf96ef4637d814a4dfeab9c404b4a3667 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Mon, 10 Dec 2018 12:42:48 +0000 Subject: Update to libnitrokey v3.4 Besides the changes listed in the changelog, this patch also changes the build system to be able to generate the version.cc file containing the library version. --- libnitrokey-v3.4/libnitrokey/stick10_commands.h | 889 ++++++++++++++++++++++++ 1 file changed, 889 insertions(+) create mode 100644 libnitrokey-v3.4/libnitrokey/stick10_commands.h (limited to 'libnitrokey-v3.4/libnitrokey/stick10_commands.h') diff --git a/libnitrokey-v3.4/libnitrokey/stick10_commands.h b/libnitrokey-v3.4/libnitrokey/stick10_commands.h new file mode 100644 index 0000000..f2ffba2 --- /dev/null +++ b/libnitrokey-v3.4/libnitrokey/stick10_commands.h @@ -0,0 +1,889 @@ +/* + * 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 STICK10_COMMANDS_H +#define STICK10_COMMANDS_H + +#include +#include +#include +#include +#include +#include "device_proto.h" +#include "command.h" + +#pragma pack (push,1) + +namespace nitrokey { +namespace proto { + + + +/* + * Stick10 protocol definition + */ +namespace stick10 { +class GetSlotName : public Command { + public: + // reachable as a typedef in Transaction + struct CommandPayload { + uint8_t slot_number; + + bool isValid() const { return slot_number<0x10+3; } + 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]; + + bool isValid() const { return true; } + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(slot_name); + return ss.str(); + } + } __packed; + + typedef Transaction CommandTransaction; +}; + +class EraseSlot : Command { + 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; + + typedef Transaction + CommandTransaction; +}; + +class SetTime : Command { + public: + struct CommandPayload { + uint8_t reset; // 0 - get time, 1 - set time + uint64_t time; // posix time + + bool isValid() const { return reset && reset != 1; } + std::string dissect() const { + std::stringstream ss; + ss << "reset:\t" << (int)(reset) << std::endl; + ss << "time:\t" << (time) << std::endl; + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + + +class WriteToHOTPSlot : Command { + public: + struct CommandPayload { + uint8_t slot_number; + uint8_t slot_name[15]; + uint8_t slot_secret[20]; + union{ + uint8_t _slot_config; + struct{ + bool use_8_digits : 1; + bool use_enter : 1; + bool use_tokenID : 1; + }; + }; + union{ + uint8_t slot_token_id[13]; /** OATH Token Identifier */ + struct{ /** @see https://openauthentication.org/token-specs/ */ + uint8_t omp[2]; + uint8_t tt[2]; + uint8_t mui[8]; + uint8_t keyboard_layout; //disabled feature in nitroapp as of 20160805 + } slot_token_fields; + }; + union{ + uint64_t slot_counter; + uint8_t slot_counter_s[8]; + } __packed; + + bool isValid() const { return !(slot_number & 0xF0); } + std::string dissect() const { + std::stringstream ss; + ss << "slot_number:\t" << (int)(slot_number) << std::endl; + print_to_ss_volatile(slot_name); + print_to_ss_volatile(slot_secret); + ss << "slot_config:\t" << std::bitset<8>((int)_slot_config) << std::endl; + ss << "\tuse_8_digits(0):\t" << use_8_digits << std::endl; + ss << "\tuse_enter(1):\t" << use_enter << std::endl; + ss << "\tuse_tokenID(2):\t" << use_tokenID << std::endl; + + ss << "slot_token_id:\t"; + for (auto i : slot_token_id) + ss << std::hex << std::setw(2) << std::setfill('0')<< (int) i << " " ; + ss << std::endl; + ss << "slot_counter:\t[" << (int)slot_counter << "]\t" + << ::nitrokey::misc::hexdump((const uint8_t *)(&slot_counter), sizeof slot_counter, false); + + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class WriteToTOTPSlot : Command { + public: + struct CommandPayload { + uint8_t slot_number; + uint8_t slot_name[15]; + uint8_t slot_secret[20]; + 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; + }; + uint16_t slot_interval; + + bool isValid() const { return !(slot_number & 0xF0); } //TODO check + std::string dissect() const { + std::stringstream ss; + ss << "slot_number:\t" << (int)(slot_number) << std::endl; + print_to_ss_volatile(slot_name); + print_to_ss_volatile(slot_secret); + ss << "slot_config:\t" << std::bitset<8>((int)_slot_config) << std::endl; + ss << "slot_token_id:\t"; + for (auto i : slot_token_id) + ss << std::hex << std::setw(2) << std::setfill('0')<< (int) i << " " ; + ss << std::endl; + ss << "slot_interval:\t" << (int)slot_interval << std::endl; + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class GetTOTP : Command { + 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); } + std::string dissect() const { + std::stringstream ss; + 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 GetHOTP : Command { + 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 { + 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 ReadSlot : Command { + 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]; + union{ + uint8_t _slot_config; + struct{ + bool use_8_digits : 1; + bool use_enter : 1; + bool use_tokenID : 1; + }; + }; + union{ + uint8_t slot_token_id[13]; /** OATH Token Identifier */ + struct{ /** @see https://openauthentication.org/token-specs/ */ + uint8_t omp[2]; + uint8_t tt[2]; + uint8_t mui[8]; + uint8_t keyboard_layout; //disabled feature in nitroapp as of 20160805 + } slot_token_fields; + }; + union{ + uint64_t slot_counter; + uint8_t slot_counter_s[8]; + } __packed; + + bool isValid() const { return true; } + + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(slot_name); + ss << "slot_config:\t" << std::bitset<8>((int)_slot_config) << std::endl; + ss << "\tuse_8_digits(0):\t" << use_8_digits << std::endl; + ss << "\tuse_enter(1):\t" << use_enter << std::endl; + ss << "\tuse_tokenID(2):\t" << use_tokenID << std::endl; + + ss << "slot_token_id:\t"; + for (auto i : slot_token_id) + ss << std::hex << std::setw(2) << std::setfill('0')<< (int) i << " " ; + ss << std::endl; + ss << "slot_counter:\t[" << (int)slot_counter << "]\t" + << ::nitrokey::misc::hexdump((const uint8_t *)(&slot_counter), sizeof slot_counter, false); + return ss.str(); + } + } __packed; + + typedef Transaction CommandTransaction; +}; + +class GetStatus : Command { + public: + struct ResponsePayload { + union { + uint16_t firmware_version; + struct { + uint8_t minor; + uint8_t major; + } firmware_version_st; + }; + union{ + uint8_t card_serial[4]; + uint32_t card_serial_u32; + } __packed; + union { + uint8_t general_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; /* unused */ + } __packed; + } __packed; + + static constexpr uint8_t special_HOTP_slots = 2; + bool isValid() const { return numlock < special_HOTP_slots && capslock < special_HOTP_slots + && scrolllock < special_HOTP_slots && enable_user_password < 2; } + + std::string get_card_serial_hex() const { + return nitrokey::misc::toHex(card_serial_u32); + } + + std::string dissect() const { + std::stringstream ss; + ss << "firmware_version:\t" + << "[" << firmware_version << "]" << "\t" + << ::nitrokey::misc::hexdump( + (const uint8_t *)(&firmware_version), sizeof firmware_version, false); + ss << "card_serial_u32:\t" << std::hex << card_serial_u32 << std::endl; + ss << "card_serial:\t" + << ::nitrokey::misc::hexdump((const uint8_t *)(card_serial), + sizeof card_serial, false); + ss << "general_config:\t" + << ::nitrokey::misc::hexdump((const uint8_t *)(general_config), + sizeof general_config, false); + 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; +}; + +class GetPasswordRetryCount : Command { + public: + struct ResponsePayload { + uint8_t password_retry_count; + + bool isValid() const { return true; } + std::string dissect() const { + std::stringstream ss; + ss << " password_retry_count\t" << (int)password_retry_count << std::endl; + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class GetUserPasswordRetryCount + : Command { + public: + struct ResponsePayload { + uint8_t password_retry_count; + + bool isValid() const { return true; } + std::string dissect() const { + std::stringstream ss; + ss << " password_retry_count\t" << (int)password_retry_count << std::endl; + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + + template + void write_array(T &ss, Q (&arr)[N]){ + for (int i=0; i { + public: + struct ResponsePayload { + uint8_t password_safe_status[PWS_SLOT_COUNT]; + + bool isValid() const { return true; } + std::string dissect() const { + std::stringstream ss; + ss << "password_safe_status\t"; + write_array(ss, password_safe_status); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class GetPasswordSafeSlotName : Command { + 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[PWS_SLOTNAME_LENGTH]; + + bool isValid() const { return true; } + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(slot_name); + return ss.str(); + } + } __packed; + + typedef Transaction CommandTransaction; +}; + +class GetPasswordSafeSlotPassword + : Command { + 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_password[PWS_PASSWORD_LENGTH]; + + bool isValid() const { return true; } + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(slot_password); + return ss.str(); + } + } __packed; + + typedef Transaction CommandTransaction; +}; + +class GetPasswordSafeSlotLogin + : Command { + 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_login[PWS_LOGINNAME_LENGTH]; + + bool isValid() const { return true; } + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(slot_login); + return ss.str(); + } + } __packed; + + typedef Transaction CommandTransaction; +}; + +class SetPasswordSafeSlotData : Command { + 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); } + std::string dissect() const { + std::stringstream ss; + ss << " slot_number\t" << (int)slot_number << std::endl; + print_to_ss_volatile(slot_name); + print_to_ss_volatile(slot_password); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class SetPasswordSafeSlotData2 : Command { + public: + struct CommandPayload { + uint8_t slot_number; + uint8_t slot_login_name[PWS_LOGINNAME_LENGTH]; + + bool isValid() const { return !(slot_number & 0xF0); } + std::string dissect() const { + std::stringstream ss; + ss << " slot_number\t" << (int)slot_number << std::endl; + print_to_ss_volatile(slot_login_name); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class ErasePasswordSafeSlot : Command { + 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; + + typedef Transaction + CommandTransaction; +}; + +class EnablePasswordSafe : Command { + public: + struct CommandPayload { + uint8_t user_password[30]; + + bool isValid() const { return true; } + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(user_password); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class PasswordSafeInitKey : Command { + /** + * never used in Nitrokey App + */ + public: + typedef Transaction + CommandTransaction; +}; + +class PasswordSafeSendSlotViaHID : Command { + /** + * never used in Nitrokey App + */ + public: + struct CommandPayload { + uint8_t slot_number; + uint8_t slot_kind; + + bool isValid() const { return !(slot_number & 0xF0); } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +// TODO "Device::passwordSafeSendSlotDataViaHID" + +class WriteGeneralConfig : Command { + 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; + }; + }; + bool isValid() const { return numlock < 2 && capslock < 2 && scrolllock < 2 && 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; +}; + +class FirstAuthenticate : Command { + 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; + print_to_ss_volatile(card_password); + hexdump_to_ss(temporary_password); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class UserAuthenticate : Command { + 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; + print_to_ss_volatile(card_password); + hexdump_to_ss(temporary_password); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class Authorize : Command { + public: + struct CommandPayload { + uint32_t crc_to_authorize; + uint8_t temporary_password[25]; + + std::string dissect() const { + std::stringstream ss; + ss << " crc_to_authorize:\t" << std::hex << std::setw(2) << std::setfill('0') << crc_to_authorize<< std::endl; + hexdump_to_ss(temporary_password); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class UserAuthorize : Command { + public: + struct CommandPayload { + uint32_t crc_to_authorize; + uint8_t temporary_password[25]; + std::string dissect() const { + std::stringstream ss; + ss << " crc_to_authorize:\t" << crc_to_authorize<< std::endl; + hexdump_to_ss(temporary_password); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class UnlockUserPassword : Command { + public: + struct CommandPayload { + uint8_t admin_password[25]; + uint8_t user_new_password[25]; + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(admin_password); + print_to_ss_volatile(user_new_password); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class ChangeUserPin : Command { + public: + struct CommandPayload { + uint8_t old_pin[25]; + uint8_t new_pin[25]; + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(old_pin); + print_to_ss_volatile(new_pin); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class IsAESSupported : Command { + public: + struct CommandPayload { + uint8_t user_password[20]; + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(user_password); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + + +class ChangeAdminPin : Command { + public: + struct CommandPayload { + uint8_t old_pin[25]; + uint8_t new_pin[25]; + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(old_pin); + print_to_ss_volatile(new_pin); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class LockDevice : Command { + public: + typedef Transaction + CommandTransaction; +}; + +class FactoryReset : Command { + public: + struct CommandPayload { + uint8_t admin_password[20]; + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(admin_password); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; +}; + +class BuildAESKey : Command { + public: + struct CommandPayload { + uint8_t admin_password[20]; + std::string dissect() const { + std::stringstream ss; + print_to_ss_volatile(admin_password); + return ss.str(); + } + } __packed; + + typedef Transaction + CommandTransaction; + +}; + +} +} +} +#pragma pack (pop) +#endif -- cgit v1.2.1