/* * 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 STICK20_COMMANDS_H #define STICK20_COMMANDS_H #include #include "command.h" #include #include #include "device_proto.h" #pragma pack (push,1) namespace nitrokey { namespace proto { /* * STICK20 protocol command ids * a superset (almost) of STICK10 */ namespace stick20 { class ChangeAdminUserPin20Current : public PasswordCommand {}; class ChangeAdminUserPin20New : public PasswordCommand {}; class UnlockUserPin : public PasswordCommand {}; class EnableEncryptedPartition : public PasswordCommand {}; class EnableHiddenEncryptedPartition : public PasswordCommand {}; class SetUnencryptedVolumeReadOnlyAdmin : public PasswordCommand {}; class SetUnencryptedVolumeReadWriteAdmin : public PasswordCommand {}; class SetEncryptedVolumeReadOnly : public PasswordCommand {}; class SetEncryptedVolumeReadWrite : public PasswordCommand {}; //FIXME the volume disabling commands do not need password class DisableEncryptedPartition : public PasswordCommand {}; class DisableHiddenEncryptedPartition : public PasswordCommand {}; class EnableFirmwareUpdate : public PasswordCommand {}; class ChangeUpdatePassword : Command { public: struct CommandPayload { uint8_t __gap; uint8_t current_update_password[20]; uint8_t __gap2; uint8_t new_update_password[20]; std::string dissect() const { std::stringstream ss; print_to_ss_volatile( current_update_password ); print_to_ss_volatile( new_update_password ); return ss.str(); } }; typedef Transaction CommandTransaction; }; class ExportFirmware : public PasswordCommand {}; class CreateNewKeys : public PasswordCommand {}; class FillSDCardWithRandomChars : Command { public: enum class ChosenVolumes : uint8_t { all_volumes = 0, encrypted_volume = 1 }; struct CommandPayload { uint8_t volume_flag; uint8_t kind; uint8_t admin_pin[20]; std::string dissect() const { std::stringstream ss; print_to_ss( (int) volume_flag ); print_to_ss( kind ); print_to_ss_volatile(admin_pin); return ss.str(); } void set_kind_user() { kind = (uint8_t) 'P'; } void set_defaults(){ set_kind_user(); volume_flag = static_cast(ChosenVolumes::encrypted_volume); } } __packed; typedef Transaction::command_id(), struct CommandPayload, struct EmptyPayload> CommandTransaction; }; namespace StorageCommandResponsePayload{ using namespace DeviceResponseConstants; static constexpr auto padding_size = storage_data_absolute_address - header_size; struct TransmissionData{ uint8_t _padding[padding_size]; uint8_t SendCounter_u8; uint8_t SendDataType_u8; uint8_t FollowBytesFlag_u8; uint8_t SendSize_u8; std::string dissect() const { std::stringstream ss; ss << "_padding:" << std::endl << ::nitrokey::misc::hexdump((const uint8_t *) (_padding), sizeof _padding); print_to_ss((int) SendCounter_u8); print_to_ss((int) SendDataType_u8); print_to_ss((int) FollowBytesFlag_u8); print_to_ss((int) SendSize_u8); return ss.str(); } } __packed; } namespace DeviceConfigurationResponsePacket{ struct ResponsePayload { StorageCommandResponsePayload::TransmissionData transmission_data; uint16_t MagicNumber_StickConfig_u16; /** * READ_WRITE_ACTIVE = ReadWriteFlagUncryptedVolume_u8 == 0; */ uint8_t ReadWriteFlagUncryptedVolume_u8; uint8_t ReadWriteFlagCryptedVolume_u8; union{ uint8_t VersionInfo_au8[4]; struct { uint8_t major; uint8_t minor; uint8_t _reserved2; uint8_t build_iteration; } __packed versionInfo; } __packed; uint8_t ReadWriteFlagHiddenVolume_u8; uint8_t FirmwareLocked_u8; union{ uint8_t NewSDCardFound_u8; struct { bool NewCard :1; uint8_t Counter :7; } __packed NewSDCardFound_st; } __packed; /** * SD card FILLED with random chars */ uint8_t SDFillWithRandomChars_u8; uint32_t ActiveSD_CardID_u32; union{ uint8_t VolumeActiceFlag_u8; struct { bool unencrypted :1; bool encrypted :1; bool hidden :1; } __packed VolumeActiceFlag_st; } __packed; uint8_t NewSmartCardFound_u8; uint8_t UserPwRetryCount; uint8_t AdminPwRetryCount; uint32_t ActiveSmartCardID_u32; uint8_t StickKeysNotInitiated; bool isValid() const { return true; } std::string dissect() const { std::stringstream ss; print_to_ss(transmission_data.dissect()); print_to_ss( MagicNumber_StickConfig_u16 ); print_to_ss((int) ReadWriteFlagUncryptedVolume_u8 ); print_to_ss((int) ReadWriteFlagCryptedVolume_u8 ); print_to_ss((int) ReadWriteFlagHiddenVolume_u8 ); print_to_ss((int) versionInfo.major ); print_to_ss((int) versionInfo.minor ); print_to_ss((int) versionInfo.build_iteration ); print_to_ss((int) FirmwareLocked_u8 ); print_to_ss((int) NewSDCardFound_u8 ); print_to_ss((int) NewSDCardFound_st.NewCard ); print_to_ss((int) NewSDCardFound_st.Counter ); print_to_ss((int) SDFillWithRandomChars_u8 ); print_to_ss( ActiveSD_CardID_u32 ); print_to_ss((int) VolumeActiceFlag_u8 ); print_to_ss((int) VolumeActiceFlag_st.unencrypted ); print_to_ss((int) VolumeActiceFlag_st.encrypted ); print_to_ss((int) VolumeActiceFlag_st.hidden); print_to_ss((int) NewSmartCardFound_u8 ); print_to_ss((int) UserPwRetryCount ); print_to_ss((int) AdminPwRetryCount ); print_to_ss( ActiveSmartCardID_u32 ); print_to_ss((int) StickKeysNotInitiated ); return ss.str(); } } __packed; } class SendStartup : Command { public: struct CommandPayload { uint64_t localtime; // POSIX seconds from epoch start, supports until year 2106 std::string dissect() const { std::stringstream ss; print_to_ss( localtime ); return ss.str(); } void set_defaults(){ localtime = std::chrono::duration_cast ( std::chrono::system_clock::now().time_since_epoch()).count(); } }__packed; using ResponsePayload = DeviceConfigurationResponsePacket::ResponsePayload; typedef Transaction CommandTransaction; }; // TODO fix original nomenclature class SendSetReadonlyToUncryptedVolume : public PasswordCommand {}; class SendSetReadwriteToUncryptedVolume : public PasswordCommand {}; class SendClearNewSdCardFound : public PasswordCommand {}; class GetDeviceStatus : Command { public: using ResponsePayload = DeviceConfigurationResponsePacket::ResponsePayload; typedef Transaction CommandTransaction; }; class CheckSmartcardUsage : Command { public: typedef Transaction CommandTransaction; }; class GetSDCardOccupancy : Command { public: struct ResponsePayload { uint8_t WriteLevelMin; uint8_t WriteLevelMax; uint8_t ReadLevelMin; uint8_t ReadLevelMax; std::string dissect() const { std::stringstream ss; print_to_ss((int) WriteLevelMin); print_to_ss((int) WriteLevelMax); print_to_ss((int) ReadLevelMin); print_to_ss((int) ReadLevelMax); return ss.str(); } } __packed; typedef Transaction CommandTransaction; }; class SetupHiddenVolume : Command { public: constexpr static int MAX_HIDDEN_VOLUME_PASSWORD_SIZE = 20; struct CommandPayload { uint8_t SlotNr_u8; uint8_t StartBlockPercent_u8; uint8_t EndBlockPercent_u8; uint8_t HiddenVolumePassword_au8[MAX_HIDDEN_VOLUME_PASSWORD_SIZE]; std::string dissect() const { std::stringstream ss; print_to_ss((int) SlotNr_u8); print_to_ss((int) StartBlockPercent_u8); print_to_ss((int) EndBlockPercent_u8); print_to_ss_volatile(HiddenVolumePassword_au8); return ss.str(); } } __packed; typedef Transaction CommandTransaction; }; //disable this command for now // class LockFirmware : public PasswordCommand {}; class ProductionTest : Command { public: struct ResponsePayload { StorageCommandResponsePayload::TransmissionData transmission_data; uint8_t FirmwareVersion_au8[2]; // 2 byte // 2 uint8_t FirmwareVersionInternal_u8; // 1 byte // 3 uint8_t SD_Card_Size_u8; // 1 byte // 4 uint32_t CPU_CardID_u32; // 4 byte // 8 uint32_t SmartCardID_u32; // 4 byte // 12 uint32_t SD_CardID_u32; // 4 byte // 16 uint8_t SC_UserPwRetryCount; // User PIN retry count 1 byte // 17 uint8_t SC_AdminPwRetryCount; // Admin PIN retry count 1 byte // 18 uint8_t SD_Card_ManufacturingYear_u8; // 1 byte // 19 uint8_t SD_Card_ManufacturingMonth_u8; // 1 byte // 20 uint16_t SD_Card_OEM_u16; // 2 byte // 22 uint16_t SD_WriteSpeed_u16; // in kbyte / sec 2 byte // 24 uint8_t SD_Card_Manufacturer_u8; // 1 byte // 25 bool isValid() const { return true; } std::string dissect() const { std::stringstream ss; print_to_ss(transmission_data.dissect()); print_to_ss((int) FirmwareVersion_au8[0]); print_to_ss((int) FirmwareVersion_au8[1]); print_to_ss((int) FirmwareVersionInternal_u8); print_to_ss((int) SD_Card_Size_u8); print_to_ss( CPU_CardID_u32); print_to_ss( SmartCardID_u32); print_to_ss( SD_CardID_u32); print_to_ss((int) SC_UserPwRetryCount); print_to_ss((int) SC_AdminPwRetryCount); print_to_ss((int) SD_Card_ManufacturingYear_u8); print_to_ss((int) SD_Card_ManufacturingMonth_u8); print_to_ss( SD_Card_OEM_u16); print_to_ss( SD_WriteSpeed_u16); print_to_ss((int) SD_Card_Manufacturer_u8); return ss.str(); } } __packed; typedef Transaction CommandTransaction; }; } } } #undef print_to_ss #pragma pack (pop) #endif