clang-format run (#77)
* pull updated template .clang-format with `clang-format-14 --style=llvm --dump-config`, move to base directory so it is shared between `src` and `tests` * tweak to match existing style a little (e.g. K&R style for function braces) * run on all sources
This commit is contained in:
@@ -3,16 +3,22 @@ Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveBitFields: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: true
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
@@ -21,10 +27,11 @@ AlwaysBreakTemplateDeclarations: MultiLine
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
@@ -32,12 +39,14 @@ BraceWrapping:
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
@@ -52,6 +61,7 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
@@ -64,15 +74,23 @@ IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: false
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertTrailingCommas: None
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
@@ -82,6 +100,7 @@ MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
@@ -93,26 +112,39 @@ PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
ReferenceAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeRangeBasedForLoopColon: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
SpaceBeforeSquareBrackets: false
|
||||
Standard: c++17
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
...
|
||||
|
||||
150
src/main.cpp
150
src/main.cpp
@@ -26,9 +26,9 @@ GNU General Public License for more details.
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <syslog.h>
|
||||
#include <sys/mtio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <syslog.h>
|
||||
#include <termios.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
@@ -43,14 +43,15 @@ GNU General Public License for more details.
|
||||
|
||||
#include "scsiencrypt.h"
|
||||
|
||||
static std::optional<std::vector<std::uint8_t>> key_from_hex_chars(const std::string& s)
|
||||
static std::optional<std::vector<std::uint8_t>>
|
||||
key_from_hex_chars(const std::string& s)
|
||||
{
|
||||
auto it = s.data();
|
||||
std::vector<std::uint8_t> bytes;
|
||||
|
||||
if (s.size() % 2) { // treated as if there is an implicit leading 0
|
||||
std::uint8_t result;
|
||||
auto [ptr, ec] { std::from_chars(it, it + 1, result, 16) };
|
||||
auto [ptr, ec] {std::from_chars(it, it + 1, result, 16)};
|
||||
if (ec != std::errc {}) {
|
||||
return {};
|
||||
}
|
||||
@@ -60,7 +61,7 @@ static std::optional<std::vector<std::uint8_t>> key_from_hex_chars(const std::st
|
||||
|
||||
while (*it) {
|
||||
std::uint8_t result;
|
||||
auto [ptr, ec] { std::from_chars(it, it + 2, result, 16) };
|
||||
auto [ptr, ec] {std::from_chars(it, it + 2, result, 16)};
|
||||
if (ec != std::errc {}) {
|
||||
return {};
|
||||
}
|
||||
@@ -71,16 +72,18 @@ static std::optional<std::vector<std::uint8_t>> key_from_hex_chars(const std::st
|
||||
}
|
||||
|
||||
// shows the command usage
|
||||
static void showUsage() {
|
||||
std::cerr
|
||||
<< "Usage: stenc --version | "
|
||||
static void showUsage()
|
||||
{
|
||||
std::cerr << "Usage: stenc --version | "
|
||||
"-f <device> [--detail] [-e <on/mixed/rawread/off> [-k <file>] "
|
||||
"[-kd <description>] [-a <index>] [--protect | --unprotect] [--ckod] ]\n\n"
|
||||
"[-kd <description>] [-a <index>] [--protect | --unprotect] "
|
||||
"[--ckod] ]\n\n"
|
||||
"Type 'man stenc' for more information.\n";
|
||||
}
|
||||
|
||||
// exits to shell with an error message
|
||||
static void errorOut(const std::string& message) {
|
||||
static void errorOut(const std::string& message)
|
||||
{
|
||||
std::cerr << "Error: " << message << "\n";
|
||||
showUsage();
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -90,8 +93,8 @@ static void print_algorithm_name(std::ostream& os, const uint32_t code)
|
||||
{
|
||||
// Reference: SFSC / INCITS 501-2016
|
||||
if (0x80010400 <= code && code <= 0x8001FFFF) {
|
||||
os << "Vendor specific 0x" << std::setw(8) << std::setfill('0')
|
||||
<< std::hex << code;
|
||||
os << "Vendor specific 0x" << std::setw(8) << std::setfill('0') << std::hex
|
||||
<< code;
|
||||
}
|
||||
switch (code) {
|
||||
case 0x0001000C:
|
||||
@@ -107,12 +110,11 @@ static void print_algorithm_name(std::ostream& os, const uint32_t code)
|
||||
os << "AES-256-XTS-HMAC-SHA-512";
|
||||
break;
|
||||
default:
|
||||
os << "Unknown 0x" << std::setw(8) << std::setfill('0')
|
||||
<< std::hex << code;
|
||||
os << "Unknown 0x" << std::setw(8) << std::setfill('0') << std::hex << code;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_algorithms(std::ostream& os, const scsi::page_dec &page)
|
||||
static void print_algorithms(std::ostream& os, const scsi::page_dec& page)
|
||||
{
|
||||
auto algorithms {scsi::read_algorithms(page)};
|
||||
|
||||
@@ -125,11 +127,11 @@ static void print_algorithms(std::ostream& os, const scsi::page_dec &page)
|
||||
os.put('\n');
|
||||
|
||||
// Print KAD capabilities and size
|
||||
auto dkad_c {
|
||||
static_cast<unsigned int>(ad.flags3 & scsi::algorithm_descriptor::flags3_dkad_c_mask)
|
||||
};
|
||||
auto dkad_c {static_cast<unsigned int>(
|
||||
ad.flags3 & scsi::algorithm_descriptor::flags3_dkad_c_mask)};
|
||||
if (dkad_c == 1u << scsi::algorithm_descriptor::flags3_dkad_c_pos) {
|
||||
os << std::left << std::setw(5) << "" << "Key descriptors not allowed\n";
|
||||
os << std::left << std::setw(5) << ""
|
||||
<< "Key descriptors not allowed\n";
|
||||
} else if (dkad_c) {
|
||||
os << std::left << std::setw(5) << "";
|
||||
if (dkad_c == 1u << scsi::algorithm_descriptor::flags3_dkad_c_pos) {
|
||||
@@ -147,9 +149,8 @@ static void print_algorithms(std::ostream& os, const scsi::page_dec &page)
|
||||
}
|
||||
|
||||
// Print raw decryption mode capability:
|
||||
auto rdmc_c {
|
||||
static_cast<unsigned int>(ad.flags3 & scsi::algorithm_descriptor::flags3_rdmc_c_mask)
|
||||
};
|
||||
auto rdmc_c {static_cast<unsigned int>(
|
||||
ad.flags3 & scsi::algorithm_descriptor::flags3_rdmc_c_mask)};
|
||||
switch (rdmc_c) {
|
||||
case 1u << scsi::algorithm_descriptor::flags3_rdmc_c_pos:
|
||||
case 6u << scsi::algorithm_descriptor::flags3_rdmc_c_pos:
|
||||
@@ -171,7 +172,8 @@ static void print_algorithms(std::ostream& os, const scsi::page_dec &page)
|
||||
}
|
||||
}
|
||||
|
||||
static void print_device_inquiry(std::ostream& os, const scsi::inquiry_data& iresult)
|
||||
static void print_device_inquiry(std::ostream& os,
|
||||
const scsi::inquiry_data& iresult)
|
||||
{
|
||||
os << std::left << std::setw(25) << "Vendor:";
|
||||
os.write(iresult.vendor, 8);
|
||||
@@ -184,34 +186,43 @@ static void print_device_inquiry(std::ostream& os, const scsi::inquiry_data& ire
|
||||
os.put('\n');
|
||||
}
|
||||
|
||||
static void inquiryDrive(const std::string& tapeDevice) {
|
||||
static void inquiryDrive(const std::string& tapeDevice)
|
||||
{
|
||||
// todo: std::cout should not be used outside main()
|
||||
auto iresult {scsi::get_inquiry(tapeDevice)};
|
||||
print_device_inquiry(std::cout, iresult);
|
||||
}
|
||||
|
||||
static void print_device_status(std::ostream& os, const scsi::page_des& opt, bool detail)
|
||||
static void print_device_status(std::ostream& os, const scsi::page_des& opt,
|
||||
bool detail)
|
||||
{
|
||||
std::string emode = "unknown";
|
||||
os << std::left << std::setw(25) << "Drive Encryption:";
|
||||
if (opt.encryption_mode == scsi::encrypt_mode::on && // encrypt
|
||||
opt.decryption_mode == scsi::decrypt_mode::on // read only encrypted data
|
||||
)
|
||||
) {
|
||||
emode = "on";
|
||||
}
|
||||
if (opt.encryption_mode == scsi::encrypt_mode::on && // encrypt
|
||||
opt.decryption_mode == scsi::decrypt_mode::mixed // read encrypted and unencrypted
|
||||
)
|
||||
opt.decryption_mode ==
|
||||
scsi::decrypt_mode::mixed // read encrypted and unencrypted
|
||||
) {
|
||||
emode = "mixed";
|
||||
}
|
||||
|
||||
if (opt.encryption_mode == scsi::encrypt_mode::on && // encrypt
|
||||
opt.decryption_mode == scsi::decrypt_mode::raw // read encrypted and unencrypted
|
||||
)
|
||||
opt.decryption_mode ==
|
||||
scsi::decrypt_mode::raw // read encrypted and unencrypted
|
||||
) {
|
||||
emode = "rawread";
|
||||
}
|
||||
|
||||
if (opt.encryption_mode == scsi::encrypt_mode::off && // encrypt
|
||||
opt.decryption_mode == scsi::decrypt_mode::off // read encrypted and unencrypted
|
||||
)
|
||||
opt.decryption_mode ==
|
||||
scsi::decrypt_mode::off // read encrypted and unencrypted
|
||||
) {
|
||||
emode = "off";
|
||||
}
|
||||
|
||||
os << emode << "\n";
|
||||
if (detail) {
|
||||
@@ -238,8 +249,8 @@ static void print_device_status(std::ostream& os, const scsi::page_des& opt, boo
|
||||
<< "Unencrypted data outputted\n";
|
||||
break;
|
||||
default:
|
||||
os << "Unknown '0x" << std::hex << static_cast<unsigned int>(opt.decryption_mode)
|
||||
<< "' \n";
|
||||
os << "Unknown '0x" << std::hex
|
||||
<< static_cast<unsigned int>(opt.decryption_mode) << "' \n";
|
||||
break;
|
||||
}
|
||||
os << std::setw(25) << "Drive Input:";
|
||||
@@ -255,7 +266,8 @@ static void print_device_status(std::ostream& os, const scsi::page_des& opt, boo
|
||||
<< static_cast<unsigned int>(opt.encryption_mode) << "'\n";
|
||||
break;
|
||||
}
|
||||
if ((opt.flags & scsi::page_des::flags_rdmd_mask) == scsi::page_des::flags_rdmd_mask) {
|
||||
if ((opt.flags & scsi::page_des::flags_rdmd_mask) ==
|
||||
scsi::page_des::flags_rdmd_mask) {
|
||||
os << std::setw(25) << " "
|
||||
<< "Protecting from raw read\n";
|
||||
}
|
||||
@@ -272,20 +284,23 @@ static void print_device_status(std::ostream& os, const scsi::page_des& opt, boo
|
||||
switch (kd->type) {
|
||||
case scsi::kad_type::ukad:
|
||||
os << std::setw(25) << "Drive Key Desc.(uKAD): ";
|
||||
os.write(reinterpret_cast<const char *>(kd->descriptor), ntohs(kd->length));
|
||||
os.write(reinterpret_cast<const char *>(kd->descriptor),
|
||||
ntohs(kd->length));
|
||||
os.put('\n');
|
||||
break;
|
||||
case scsi::kad_type::akad:
|
||||
os << std::setw(25) << "Drive Key Desc.(aKAD): ";
|
||||
os.write(reinterpret_cast<const char *>(kd->descriptor), ntohs(kd->length));
|
||||
os.write(reinterpret_cast<const char *>(kd->descriptor),
|
||||
ntohs(kd->length));
|
||||
os.put('\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void showDriveStatus(const std::string& tapeDrive, bool detail) {
|
||||
alignas(4) scsi::page_buffer buffer {};
|
||||
static void showDriveStatus(const std::string& tapeDrive, bool detail)
|
||||
{
|
||||
alignas(4) scsi::page_buffer buffer;
|
||||
scsi::get_des(tapeDrive, buffer, sizeof(buffer));
|
||||
auto& opt {reinterpret_cast<const scsi::page_des&>(buffer)};
|
||||
|
||||
@@ -294,10 +309,9 @@ static void showDriveStatus(const std::string& tapeDrive, bool detail) {
|
||||
|
||||
static void print_volume_status(std::ostream& os, const scsi::page_nbes& opt)
|
||||
{
|
||||
auto compression_status {
|
||||
static_cast<std::uint8_t>((opt.status & scsi::page_nbes::status_compression_mask)
|
||||
>> scsi::page_nbes::status_compression_pos)
|
||||
};
|
||||
auto compression_status {static_cast<std::uint8_t>(
|
||||
(opt.status & scsi::page_nbes::status_compression_mask) >>
|
||||
scsi::page_nbes::status_compression_pos)};
|
||||
// From vendor docs, no known drives actually report anything other than 0
|
||||
if (compression_status != 0u) {
|
||||
os << std::left << std::setw(25) << "Volume Compressed:";
|
||||
@@ -312,10 +326,9 @@ static void print_volume_status(std::ostream& os, const scsi::page_nbes& opt)
|
||||
}
|
||||
}
|
||||
os << std::left << std::setw(25) << "Volume Encryption:";
|
||||
auto encryption_status {
|
||||
static_cast<std::uint8_t>((opt.status & scsi::page_nbes::status_encryption_mask)
|
||||
>> scsi::page_nbes::status_encryption_pos)
|
||||
};
|
||||
auto encryption_status {static_cast<std::uint8_t>(
|
||||
(opt.status & scsi::page_nbes::status_encryption_mask) >>
|
||||
scsi::page_nbes::status_encryption_pos)};
|
||||
auto kads {read_page_kads(opt)};
|
||||
switch (encryption_status) {
|
||||
case 0u:
|
||||
@@ -330,7 +343,8 @@ static void print_volume_status(std::ostream& os, const scsi::page_nbes& opt)
|
||||
break;
|
||||
case 5u:
|
||||
os << "Encrypted and able to decrypt\n";
|
||||
if ((opt.flags & scsi::page_nbes::flags_rdmds_mask) == scsi::page_nbes::flags_rdmds_mask) {
|
||||
if ((opt.flags & scsi::page_nbes::flags_rdmds_mask) ==
|
||||
scsi::page_nbes::flags_rdmds_mask) {
|
||||
os << std::left << std::setw(25) << " Protected from raw read\n";
|
||||
}
|
||||
break;
|
||||
@@ -340,17 +354,20 @@ static void print_volume_status(std::ostream& os, const scsi::page_nbes& opt)
|
||||
switch (kd->type) {
|
||||
case scsi::kad_type::ukad:
|
||||
os << std::setw(25) << "Volume Key Desc.(uKAD): ";
|
||||
os.write(reinterpret_cast<const char *>(kd->descriptor), ntohs(kd->length));
|
||||
os.write(reinterpret_cast<const char *>(kd->descriptor),
|
||||
ntohs(kd->length));
|
||||
os.put('\n');
|
||||
break;
|
||||
case scsi::kad_type::akad:
|
||||
os << std::setw(25) << "Volume Key Desc.(aKAD): ";
|
||||
os.write(reinterpret_cast<const char *>(kd->descriptor), ntohs(kd->length));
|
||||
os.write(reinterpret_cast<const char *>(kd->descriptor),
|
||||
ntohs(kd->length));
|
||||
os.put('\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((opt.flags & scsi::page_nbes::flags_rdmds_mask) == scsi::page_nbes::flags_rdmds_mask) {
|
||||
if ((opt.flags & scsi::page_nbes::flags_rdmds_mask) ==
|
||||
scsi::page_nbes::flags_rdmds_mask) {
|
||||
os << std::left << std::setw(25) << " Protected from raw read\n";
|
||||
}
|
||||
break;
|
||||
@@ -361,19 +378,22 @@ static void print_volume_status(std::ostream& os, const scsi::page_nbes& opt)
|
||||
}
|
||||
if (opt.algorithm_index != 0) {
|
||||
os << std::left << std::setw(25)
|
||||
<< "Volume Algorithm:" << static_cast<unsigned int>(opt.algorithm_index) << "\n";
|
||||
<< "Volume Algorithm:" << static_cast<unsigned int>(opt.algorithm_index)
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
static void showVolumeStatus(const std::string& tapeDrive) {
|
||||
alignas(4) scsi::page_buffer buffer {};
|
||||
static void showVolumeStatus(const std::string& tapeDrive)
|
||||
{
|
||||
alignas(4) scsi::page_buffer buffer;
|
||||
scsi::get_nbes(tapeDrive, buffer, sizeof(buffer));
|
||||
auto& opt {reinterpret_cast<const scsi::page_nbes&>(buffer)};
|
||||
|
||||
print_volume_status(std::cout, opt);
|
||||
}
|
||||
|
||||
static void echo(bool on) {
|
||||
static void echo(bool on)
|
||||
{
|
||||
struct termios settings {};
|
||||
tcgetattr(STDIN_FILENO, &settings);
|
||||
settings.c_lflag =
|
||||
@@ -382,7 +402,8 @@ static void echo(bool on) {
|
||||
}
|
||||
|
||||
#if !defined(CATCH_CONFIG_MAIN)
|
||||
int main(int argc, const char **argv) {
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
std::string tapeDrive;
|
||||
int action = 0; // 0 = status, 1 =setting param, 2 = generating key
|
||||
std::string keyFile, keyDesc;
|
||||
@@ -429,7 +450,7 @@ int main(int argc, const char **argv) {
|
||||
// encrypt, read encrypted and unencrypted data
|
||||
enc_mode = scsi::encrypt_mode::off;
|
||||
dec_mode = scsi::decrypt_mode::off;
|
||||
} else{
|
||||
} else {
|
||||
errorOut("Unknown encryption mode '" + nextCmd +
|
||||
"'"); // encrypt, read encrypted and unencrypted data
|
||||
}
|
||||
@@ -511,9 +532,8 @@ int main(int argc, const char **argv) {
|
||||
} catch (const scsi::scsi_error& err) {
|
||||
// #71: ignore BLANK CHECK sense key that some drives may return
|
||||
// during media access check in getting NBES
|
||||
auto sense_key {
|
||||
err.get_sense().flags & scsi::sense_data::flags_sense_key_mask
|
||||
};
|
||||
auto sense_key {err.get_sense().flags &
|
||||
scsi::sense_data::flags_sense_key_mask};
|
||||
if (sense_key != scsi::sense_data::blank_check) {
|
||||
throw;
|
||||
}
|
||||
@@ -594,18 +614,20 @@ int main(int argc, const char **argv) {
|
||||
<< (enc_mode != scsi::encrypt_mode::off ? "on" : "off")
|
||||
<< " encryption on device '" << tapeDrive << "'..." << std::endl;
|
||||
try {
|
||||
auto sde_buffer {scsi::make_sde(enc_mode, dec_mode, algorithm_index,
|
||||
key, key_name, rdmc, ckod)};
|
||||
auto sde_buffer {scsi::make_sde(enc_mode, dec_mode, algorithm_index, key,
|
||||
key_name, rdmc, ckod)};
|
||||
scsi::write_sde(tapeDrive, sde_buffer.get());
|
||||
|
||||
alignas(4) scsi::page_buffer buffer {};
|
||||
scsi::get_des(tapeDrive, buffer, sizeof(buffer));
|
||||
auto& opt {reinterpret_cast<const scsi::page_des&>(buffer)};
|
||||
|
||||
if (enc_mode != scsi::encrypt_mode::off && opt.encryption_mode == scsi::encrypt_mode::off) {
|
||||
if (enc_mode != scsi::encrypt_mode::off &&
|
||||
opt.encryption_mode == scsi::encrypt_mode::off) {
|
||||
errorOut("Turning encryption on for '" + tapeDrive + "' failed!");
|
||||
}
|
||||
if (enc_mode == scsi::encrypt_mode::off && opt.encryption_mode != scsi::encrypt_mode::off) {
|
||||
if (enc_mode == scsi::encrypt_mode::off &&
|
||||
opt.encryption_mode != scsi::encrypt_mode::off) {
|
||||
errorOut("Turning encryption off for '" + tapeDrive + "' failed!");
|
||||
}
|
||||
|
||||
@@ -620,7 +642,7 @@ int main(int argc, const char **argv) {
|
||||
|
||||
syslog(LOG_NOTICE, "%s", msg.str().c_str());
|
||||
} else {
|
||||
std::stringstream msg{};
|
||||
std::stringstream msg {};
|
||||
|
||||
msg << "Encryption turned off for device '" << tapeDrive << "'.";
|
||||
msg << " Key Instance: " << std::dec << ntohl(opt.key_instance_counter)
|
||||
|
||||
@@ -34,8 +34,8 @@ GNU General Public License for more details.
|
||||
#include <scsi/sg.h>
|
||||
#define SCSI_TIMEOUT 5000
|
||||
#elif defined(OS_FREEBSD)
|
||||
#include <camlib.h>
|
||||
#include <cam/scsi/scsi_message.h>
|
||||
#include <camlib.h>
|
||||
#define SCSI_TIMEOUT 5000
|
||||
#else
|
||||
#error "OS type is not set"
|
||||
@@ -51,30 +51,36 @@ constexpr std::uint8_t SSP_SP_PROTOCOL_TDE = 0x20;
|
||||
constexpr int RETRYCOUNT = 1;
|
||||
|
||||
#define BSINTTOCHAR(x) \
|
||||
static_cast<std::uint8_t>((x) >> 24), \
|
||||
static_cast<std::uint8_t>((x) >> 16), \
|
||||
static_cast<std::uint8_t>((x) >> 8), \
|
||||
static_cast<std::uint8_t>((x))
|
||||
static_cast<std::uint8_t>((x) >> 24), static_cast<std::uint8_t>((x) >> 16), \
|
||||
static_cast<std::uint8_t>((x) >> 8), static_cast<std::uint8_t>((x))
|
||||
|
||||
// generic_deleter permits the use of std::unique_ptr for RAII on non-pointer
|
||||
// types like file descriptors.
|
||||
template<typename T, T null_value, typename Deleter, Deleter d>
|
||||
template <typename T, T null_value, typename Deleter, Deleter d>
|
||||
struct generic_deleter {
|
||||
class pointer {
|
||||
T t;
|
||||
|
||||
public:
|
||||
pointer() : t {null_value} {}
|
||||
pointer(T t) : t {t} {}
|
||||
pointer(std::nullptr_t) : t {null_value} {}
|
||||
explicit operator bool() const noexcept { return t != null_value; }
|
||||
friend bool operator ==(pointer lhs, pointer rhs) noexcept { return lhs.t == rhs.t; }
|
||||
friend bool operator !=(pointer lhs, pointer rhs) noexcept { return !(lhs == rhs); }
|
||||
friend bool operator==(pointer lhs, pointer rhs) noexcept
|
||||
{
|
||||
return lhs.t == rhs.t;
|
||||
}
|
||||
friend bool operator!=(pointer lhs, pointer rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
operator T() const noexcept { return t; }
|
||||
};
|
||||
|
||||
void operator()(pointer p) const noexcept { d(p); }
|
||||
};
|
||||
using unique_fd = std::unique_ptr<int, generic_deleter<int, -1, decltype(&close), &close>>;
|
||||
using unique_fd =
|
||||
std::unique_ptr<int, generic_deleter<int, -1, decltype(&close), &close>>;
|
||||
|
||||
enum class scsi_direction { to_device, from_device };
|
||||
|
||||
@@ -95,10 +101,11 @@ static void scsi_execute(const std::string& device, const std::uint8_t *cmd_p,
|
||||
|
||||
cmdio.cmd_len = cmd_len;
|
||||
cmdio.dxfer_direction = (direction == scsi_direction::to_device)
|
||||
? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
|
||||
? SG_DXFER_TO_DEV
|
||||
: SG_DXFER_FROM_DEV;
|
||||
cmdio.dxfer_len = dxfer_len;
|
||||
cmdio.dxferp = dxfer_p;
|
||||
cmdio.cmdp = const_cast<unsigned char*>(cmd_p);
|
||||
cmdio.cmdp = const_cast<unsigned char *>(cmd_p);
|
||||
cmdio.sbp = sense_buf->data();
|
||||
cmdio.mx_sb_len = sizeof(decltype(sense_buf)::element_type);
|
||||
cmdio.timeout = SCSI_TIMEOUT;
|
||||
@@ -111,32 +118,34 @@ static void scsi_execute(const std::string& device, const std::uint8_t *cmd_p,
|
||||
throw scsi::scsi_error {std::move(sense_buf)};
|
||||
}
|
||||
#elif defined(OS_FREEBSD)
|
||||
auto dev = std::unique_ptr<struct cam_device, decltype(&cam_close_device)>
|
||||
{cam_open_device(device.c_str(), O_RDWR), &cam_close_device};
|
||||
auto dev = std::unique_ptr<struct cam_device, decltype(&cam_close_device)> {
|
||||
cam_open_device(device.c_str(), O_RDWR), &cam_close_device};
|
||||
if (dev == nullptr) {
|
||||
std::ostringstream oss;
|
||||
oss << "Cannot open device " << device << ": " << cam_errbuf;
|
||||
throw std::runtime_error {oss.str()};
|
||||
}
|
||||
auto ccb = std::unique_ptr<union ccb, decltype(&cam_freeccb)>
|
||||
{cam_getccb(dev.get()), &cam_freeccb};
|
||||
auto ccb = std::unique_ptr<union ccb, decltype(&cam_freeccb)> {
|
||||
cam_getccb(dev.get()), &cam_freeccb};
|
||||
if (ccb == nullptr) {
|
||||
throw std::bad_alloc {};
|
||||
}
|
||||
CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
|
||||
|
||||
cam_fill_csio(&ccb->csio, RETRYCOUNT, nullptr,
|
||||
cam_fill_csio(
|
||||
&ccb->csio, RETRYCOUNT, nullptr,
|
||||
CAM_PASS_ERR_RECOVER | CAM_CDB_POINTER |
|
||||
(direction == scsi_direction::to_device ? CAM_DIR_OUT : CAM_DIR_IN),
|
||||
MSG_SIMPLE_Q_TAG, dxfer_p, dxfer_len, SSD_FULL_SIZE, cmd_len,
|
||||
SCSI_TIMEOUT);
|
||||
ccb->csio.cdb_io.cdb_ptr = const_cast<u_int8_t*>(cmd_p);
|
||||
ccb->csio.cdb_io.cdb_ptr = const_cast<u_int8_t *>(cmd_p);
|
||||
if (cam_send_ccb(dev.get(), ccb.get())) {
|
||||
throw std::system_error {errno, std::generic_category()};
|
||||
}
|
||||
if (ccb->csio.scsi_status) {
|
||||
auto sense_buf {std::make_unique<scsi::sense_buffer>()};
|
||||
std::memcpy(sense_buf->data(), &ccb->csio.sense_data, sizeof(scsi::sense_buffer));
|
||||
std::memcpy(sense_buf->data(), &ccb->csio.sense_data,
|
||||
sizeof(scsi::sense_buffer));
|
||||
throw scsi::scsi_error {std::move(sense_buf)};
|
||||
}
|
||||
#else
|
||||
@@ -159,7 +168,8 @@ bool is_device_ready(const std::string& device)
|
||||
}
|
||||
}
|
||||
|
||||
void get_des(const std::string& device, std::uint8_t *buffer, std::size_t length)
|
||||
void get_des(const std::string& device, std::uint8_t *buffer,
|
||||
std::size_t length)
|
||||
{
|
||||
const std::uint8_t spin_des_command[] {
|
||||
SSP_SPIN_OPCODE,
|
||||
@@ -172,11 +182,12 @@ void get_des(const std::string& device, std::uint8_t *buffer, std::size_t length
|
||||
0,
|
||||
0,
|
||||
};
|
||||
scsi_execute(device, spin_des_command, sizeof(spin_des_command),
|
||||
buffer, length, scsi_direction::from_device);
|
||||
scsi_execute(device, spin_des_command, sizeof(spin_des_command), buffer,
|
||||
length, scsi_direction::from_device);
|
||||
}
|
||||
|
||||
void get_nbes(const std::string& device, std::uint8_t *buffer, std::size_t length)
|
||||
void get_nbes(const std::string& device, std::uint8_t *buffer,
|
||||
std::size_t length)
|
||||
{
|
||||
const std::uint8_t spin_nbes_command[] {
|
||||
SSP_SPIN_OPCODE,
|
||||
@@ -189,42 +200,44 @@ void get_nbes(const std::string& device, std::uint8_t *buffer, std::size_t lengt
|
||||
0,
|
||||
0,
|
||||
};
|
||||
scsi_execute(device, spin_nbes_command, sizeof(spin_nbes_command),
|
||||
buffer, length, scsi_direction::from_device);
|
||||
scsi_execute(device, spin_nbes_command, sizeof(spin_nbes_command), buffer,
|
||||
length, scsi_direction::from_device);
|
||||
}
|
||||
|
||||
void get_dec(const std::string& device, std::uint8_t *buffer, std::size_t length)
|
||||
void get_dec(const std::string& device, std::uint8_t *buffer,
|
||||
std::size_t length)
|
||||
{
|
||||
const uint8_t spin_dec_command[] {
|
||||
const std::uint8_t spin_dec_command[] {
|
||||
SSP_SPIN_OPCODE,
|
||||
SSP_SP_PROTOCOL_TDE,
|
||||
0x00, 0x10,
|
||||
0x00,
|
||||
0x10,
|
||||
0,
|
||||
0,
|
||||
BSINTTOCHAR(length),
|
||||
0,
|
||||
0,
|
||||
};
|
||||
scsi_execute(device, spin_dec_command, sizeof(spin_dec_command),
|
||||
buffer, length, scsi_direction::from_device);
|
||||
scsi_execute(device, spin_dec_command, sizeof(spin_dec_command), buffer,
|
||||
length, scsi_direction::from_device);
|
||||
}
|
||||
|
||||
inquiry_data get_inquiry(const std::string& device)
|
||||
{
|
||||
const uint8_t scsi_inq_command[] {0x12, 0, 0, 0, sizeof(inquiry_data), 0};
|
||||
const std::uint8_t scsi_inq_command[] {
|
||||
0x12, 0, 0, 0, sizeof(inquiry_data), 0,
|
||||
};
|
||||
inquiry_data inq {};
|
||||
scsi_execute(device, scsi_inq_command, sizeof(scsi_inq_command),
|
||||
reinterpret_cast<std::uint8_t*>(&inq), sizeof(inq),
|
||||
reinterpret_cast<std::uint8_t *>(&inq), sizeof(inq),
|
||||
scsi_direction::from_device);
|
||||
return inq;
|
||||
}
|
||||
|
||||
std::unique_ptr<const std::uint8_t[]> make_sde(encrypt_mode enc_mode,
|
||||
decrypt_mode dec_mode,
|
||||
std::uint8_t algorithm_index,
|
||||
const std::vector<std::uint8_t>& key,
|
||||
const std::string& key_name,
|
||||
sde_rdmc rdmc, bool ckod)
|
||||
std::unique_ptr<const std::uint8_t[]>
|
||||
make_sde(encrypt_mode enc_mode, decrypt_mode dec_mode,
|
||||
std::uint8_t algorithm_index, const std::vector<std::uint8_t>& key,
|
||||
const std::string& key_name, sde_rdmc rdmc, bool ckod)
|
||||
{
|
||||
std::size_t length {sizeof(page_sde) + key.size()};
|
||||
if (!key_name.empty()) {
|
||||
@@ -235,7 +248,8 @@ std::unique_ptr<const std::uint8_t[]> make_sde(encrypt_mode enc_mode,
|
||||
|
||||
page.page_code = htons(0x10);
|
||||
page.length = htons(length - sizeof(page_header));
|
||||
page.control = std::byte {2u} << page_sde::control_scope_pos; // all IT nexus = 10b
|
||||
page.control = std::byte {2u}
|
||||
<< page_sde::control_scope_pos; // all IT nexus = 10b
|
||||
page.flags |= std::byte {DEFAULT_CEEM} << page_sde::flags_ceem_pos;
|
||||
page.flags |= std::byte {static_cast<std::underlying_type_t<sde_rdmc>>(rdmc)};
|
||||
if (ckod) {
|
||||
@@ -248,7 +262,8 @@ std::unique_ptr<const std::uint8_t[]> make_sde(encrypt_mode enc_mode,
|
||||
std::memcpy(page.key, key.data(), key.size());
|
||||
|
||||
if (!key_name.empty()) {
|
||||
auto &ukad {reinterpret_cast<kad&>(*(buffer.get() + sizeof(page_sde) + key.size()))};
|
||||
auto& ukad {reinterpret_cast<kad&>(
|
||||
*(buffer.get() + sizeof(page_sde) + key.size()))};
|
||||
ukad.length = htons(key_name.size());
|
||||
std::memcpy(ukad.descriptor, key_name.data(), key_name.size());
|
||||
}
|
||||
@@ -260,7 +275,7 @@ void write_sde(const std::string& device, const std::uint8_t *sde_buffer)
|
||||
{
|
||||
auto& page {reinterpret_cast<const page_sde&>(*sde_buffer)};
|
||||
std::size_t length {sizeof(page_header) + ntohs(page.length)};
|
||||
const uint8_t spout_sde_command[] {
|
||||
const std::uint8_t spout_sde_command[] {
|
||||
SSP_SPOUT_OPCODE,
|
||||
SSP_SP_PROTOCOL_TDE,
|
||||
0,
|
||||
@@ -269,14 +284,16 @@ void write_sde(const std::string& device, const std::uint8_t *sde_buffer)
|
||||
0,
|
||||
BSINTTOCHAR(length),
|
||||
0,
|
||||
0
|
||||
0,
|
||||
};
|
||||
|
||||
scsi_execute(device, spout_sde_command, sizeof(spout_sde_command),
|
||||
const_cast<std::uint8_t*>(sde_buffer), length, scsi_direction::to_device);
|
||||
const_cast<std::uint8_t *>(sde_buffer), length,
|
||||
scsi_direction::to_device);
|
||||
}
|
||||
|
||||
void print_sense_data(std::ostream& os, const sense_data& sd) {
|
||||
void print_sense_data(std::ostream& os, const sense_data& sd)
|
||||
{
|
||||
os << std::left << std::setw(25) << "Sense Code: ";
|
||||
|
||||
auto sense_key {sd.flags & sense_data::flags_sense_key_mask};
|
||||
@@ -317,7 +334,8 @@ void print_sense_data(std::ostream& os, const sense_data& sd) {
|
||||
<< "0x" << HEX(sd.additional_sense_qualifier) << "\n";
|
||||
|
||||
if (sd.additional_sense_length > 0) {
|
||||
os << std::left << std::setw(25) << " Additional data: " << "0x";
|
||||
os << std::left << std::setw(25) << " Additional data: "
|
||||
<< "0x";
|
||||
|
||||
for (int i = 0; i < sd.additional_sense_length; i++) {
|
||||
os << HEX(sd.additional_sense_bytes[i]);
|
||||
@@ -336,18 +354,19 @@ void print_sense_data(std::ostream& os, const sense_data& sd) {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<const algorithm_descriptor*> read_algorithms(const page_dec& page)
|
||||
std::vector<const algorithm_descriptor *> read_algorithms(const page_dec& page)
|
||||
{
|
||||
auto it {reinterpret_cast<const uint8_t*>(&page.ads[0])};
|
||||
const auto end {reinterpret_cast<const uint8_t*>(&page) + ntohs(page.length) + sizeof(page_header)};
|
||||
std::vector<const algorithm_descriptor*> v {};
|
||||
auto it {reinterpret_cast<const std::uint8_t *>(&page.ads[0])};
|
||||
const auto end {reinterpret_cast<const std::uint8_t *>(&page) +
|
||||
ntohs(page.length) + sizeof(page_header)};
|
||||
std::vector<const algorithm_descriptor *> v {};
|
||||
|
||||
while (it < end) {
|
||||
auto elem {reinterpret_cast<const algorithm_descriptor*>(it)};
|
||||
auto elem {reinterpret_cast<const algorithm_descriptor *>(it)};
|
||||
v.push_back(elem);
|
||||
it += ntohs(elem->length) + 4u; // length field + preceding 4 byte header
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace scsi
|
||||
|
||||
@@ -18,8 +18,8 @@ GNU General Public License for more details.
|
||||
|
||||
#include <array>
|
||||
#include <bitset>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -39,24 +39,25 @@ constexpr std::size_t SSP_UKAD_LENGTH = 0x1e;
|
||||
|
||||
// outputs hex in a 2 digit pair
|
||||
#define HEX(x) \
|
||||
std::right << std::setw(2) << std::setfill('0') << std::hex << (int)(x) << std::setfill(' ')
|
||||
std::right << std::setw(2) << std::setfill('0') << std::hex << (int)(x) \
|
||||
<< std::setfill(' ')
|
||||
|
||||
namespace scsi {
|
||||
|
||||
enum class encrypt_mode: std::uint8_t {
|
||||
enum class encrypt_mode : std::uint8_t {
|
||||
off = 0u,
|
||||
external = 1u,
|
||||
on = 2u,
|
||||
};
|
||||
|
||||
enum class decrypt_mode: std::uint8_t {
|
||||
enum class decrypt_mode : std::uint8_t {
|
||||
off = 0u,
|
||||
raw = 1u,
|
||||
on = 2u,
|
||||
mixed = 3u,
|
||||
};
|
||||
|
||||
enum class kad_type: std::uint8_t {
|
||||
enum class kad_type : std::uint8_t {
|
||||
ukad = 0u, // unauthenticated key-associated data
|
||||
akad = 1u, // authenticated key-associated data
|
||||
nonce = 2u, // nonce value
|
||||
@@ -69,7 +70,8 @@ struct __attribute__((packed)) kad {
|
||||
kad_type type;
|
||||
std::byte flags;
|
||||
static constexpr auto flags_authenticated_pos {0u};
|
||||
static constexpr std::byte flags_authenticated_mask {7u << flags_authenticated_pos};
|
||||
static constexpr std::byte flags_authenticated_mask {
|
||||
7u << flags_authenticated_pos};
|
||||
std::uint16_t length;
|
||||
std::uint8_t descriptor[];
|
||||
};
|
||||
@@ -97,12 +99,16 @@ struct __attribute__((packed)) page_des {
|
||||
std::uint32_t key_instance_counter;
|
||||
std::byte flags;
|
||||
static constexpr auto flags_parameters_control_pos {4u};
|
||||
static constexpr std::byte flags_parameters_control_mask {7u << flags_parameters_control_pos};
|
||||
static constexpr auto flags_vcelb_pos {3u}; // volume contains encrypted logical blocks
|
||||
static constexpr std::byte flags_parameters_control_mask {
|
||||
7u << flags_parameters_control_pos};
|
||||
// volume contains encrypted logical blocks
|
||||
static constexpr auto flags_vcelb_pos {3u};
|
||||
static constexpr std::byte flags_vcelb_mask {1u << flags_vcelb_pos};
|
||||
static constexpr auto flags_ceems_pos {1u}; // check external encryption mode status
|
||||
// check external encryption mode status
|
||||
static constexpr auto flags_ceems_pos {1u};
|
||||
static constexpr std::byte flags_ceems_mask {3u << flags_ceems_pos};
|
||||
static constexpr auto flags_rdmd_pos {0u}; // raw decryption mode disabled
|
||||
// raw decryption mode disabled
|
||||
static constexpr auto flags_rdmd_pos {0u};
|
||||
static constexpr std::byte flags_rdmd_mask {1u << flags_rdmd_pos};
|
||||
std::uint8_t kad_format;
|
||||
std::uint16_t asdk_count;
|
||||
@@ -123,17 +129,23 @@ struct __attribute__((packed)) page_sde {
|
||||
static constexpr auto control_lock_pos {0u};
|
||||
static constexpr std::byte control_lock_mask {1u << control_lock_pos};
|
||||
std::byte flags;
|
||||
static constexpr auto flags_ceem_pos {6u}; // check external encryption mode
|
||||
// check external encryption mode
|
||||
static constexpr auto flags_ceem_pos {6u};
|
||||
static constexpr std::byte flags_ceem_mask {3u << flags_ceem_pos};
|
||||
static constexpr auto flags_rdmc_pos {4u}; // raw decryption mode control
|
||||
// raw decryption mode control
|
||||
static constexpr auto flags_rdmc_pos {4u};
|
||||
static constexpr std::byte flags_rdmc_mask {3u << flags_rdmc_pos};
|
||||
static constexpr auto flags_sdk_pos {3u}; // supplemental decryption key
|
||||
// supplemental decryption key
|
||||
static constexpr auto flags_sdk_pos {3u};
|
||||
static constexpr std::byte flags_sdk_mask {1u << flags_sdk_pos};
|
||||
static constexpr auto flags_ckod_pos {2u}; // clear key on demount
|
||||
// clear key on demount
|
||||
static constexpr auto flags_ckod_pos {2u};
|
||||
static constexpr std::byte flags_ckod_mask {1u << flags_ckod_pos};
|
||||
static constexpr auto flags_ckorp_pos {1u}; // clear key on reservation preempt
|
||||
// clear key on reservation preempt
|
||||
static constexpr auto flags_ckorp_pos {1u};
|
||||
static constexpr std::byte flags_ckorp_mask {1u << flags_ckorp_pos};
|
||||
static constexpr auto flags_ckorl_pos {0u}; // clear key on reservation loss
|
||||
// clear key on reservation loss
|
||||
static constexpr auto flags_ckorl_pos {0u};
|
||||
static constexpr std::byte flags_ckorl_mask {1u << flags_ckorl_pos};
|
||||
encrypt_mode encryption_mode;
|
||||
decrypt_mode decryption_mode;
|
||||
@@ -146,10 +158,12 @@ struct __attribute__((packed)) page_sde {
|
||||
};
|
||||
static_assert(sizeof(page_sde) == 20u);
|
||||
|
||||
enum class sde_rdmc: std::uint8_t {
|
||||
enum class sde_rdmc : std::uint8_t {
|
||||
algorithm_default = 0u << page_sde::flags_rdmc_pos,
|
||||
enabled = 2u << page_sde::flags_rdmc_pos, // corresponds to --unprotect command line option
|
||||
disabled = 3u << page_sde::flags_rdmc_pos, // corresponds to --protect command line option
|
||||
enabled = 2u << page_sde::flags_rdmc_pos, // corresponds to --unprotect
|
||||
// command line option
|
||||
disabled = 3u << page_sde::flags_rdmc_pos, // corresponds to --protect command
|
||||
// line option
|
||||
};
|
||||
|
||||
// next block encryption status page
|
||||
@@ -159,14 +173,18 @@ struct __attribute__((packed)) page_nbes {
|
||||
std::uint64_t logical_object_number;
|
||||
std::byte status;
|
||||
static constexpr auto status_compression_pos {4u};
|
||||
static constexpr std::byte status_compression_mask {15u << status_compression_pos};
|
||||
static constexpr std::byte status_compression_mask {
|
||||
15u << status_compression_pos};
|
||||
static constexpr auto status_encryption_pos {0u};
|
||||
static constexpr std::byte status_encryption_mask {15u << status_encryption_pos};
|
||||
static constexpr std::byte status_encryption_mask {15u
|
||||
<< status_encryption_pos};
|
||||
std::uint8_t algorithm_index;
|
||||
std::byte flags;
|
||||
static constexpr auto flags_emes_pos {1u}; // encryption mode external status
|
||||
// encryption mode external status
|
||||
static constexpr auto flags_emes_pos {1u};
|
||||
static constexpr std::byte flags_emes_mask {1u << flags_emes_pos};
|
||||
static constexpr auto flags_rdmds_pos {0u}; // raw decryption mode disabled status
|
||||
// raw decryption mode disabled status
|
||||
static constexpr auto flags_rdmds_pos {0u};
|
||||
static constexpr std::byte flags_rdmds_mask {1u << flags_rdmds_pos};
|
||||
std::uint8_t kad_format;
|
||||
kad kads[];
|
||||
@@ -178,46 +196,63 @@ struct __attribute__((packed)) algorithm_descriptor {
|
||||
std::byte reserved1;
|
||||
std::uint16_t length;
|
||||
std::byte flags1;
|
||||
static constexpr auto flags1_avfmv_pos {7u}; // algorithm valid for mounted volume
|
||||
// algorithm valid for mounted volume
|
||||
static constexpr auto flags1_avfmv_pos {7u};
|
||||
static constexpr std::byte flags1_avfmv_mask {1u << flags1_avfmv_pos};
|
||||
static constexpr auto flags1_sdk_c_pos {6u}; // supplemental decryption key capable
|
||||
// supplemental decryption key capable
|
||||
static constexpr auto flags1_sdk_c_pos {6u};
|
||||
static constexpr std::byte flags1_sdk_c_mask {1u << flags1_sdk_c_pos};
|
||||
static constexpr auto flags1_mac_c_pos {5u}; // message authentication code capable
|
||||
// message authentication code capable
|
||||
static constexpr auto flags1_mac_c_pos {5u};
|
||||
static constexpr std::byte flags1_mac_c_mask {1u << flags1_mac_c_pos};
|
||||
static constexpr auto flags1_delb_c_pos {4u}; // distinguish encrypted logical block capable
|
||||
// distinguish encrypted logical block capable
|
||||
static constexpr auto flags1_delb_c_pos {4u};
|
||||
static constexpr std::byte flags1_delb_c_mask {1u << flags1_delb_c_pos};
|
||||
static constexpr auto flags1_decrypt_c_pos {2u}; // decryption capabilities
|
||||
// decryption capabilities
|
||||
static constexpr auto flags1_decrypt_c_pos {2u};
|
||||
static constexpr std::byte flags1_decrypt_c_mask {3u << flags1_decrypt_c_pos};
|
||||
static constexpr auto flags1_encrypt_c_pos {0u}; // encryption capabilities
|
||||
// encryption capabilities
|
||||
static constexpr auto flags1_encrypt_c_pos {0u};
|
||||
static constexpr std::byte flags1_encrypt_c_mask {3u << flags1_encrypt_c_pos};
|
||||
std::byte flags2;
|
||||
static constexpr auto flags2_avfcp_pos {6u}; // algorithm valid for current logical position
|
||||
// algorithm valid for current logical position
|
||||
static constexpr auto flags2_avfcp_pos {6u};
|
||||
static constexpr std::byte flags2_avfcp_mask {3u << flags2_avfcp_pos};
|
||||
static constexpr auto flags2_nonce_pos {4u}; // nonce capabilities
|
||||
// nonce capabilities
|
||||
static constexpr auto flags2_nonce_pos {4u};
|
||||
static constexpr std::byte flags2_nonce_mask {3u << flags2_nonce_pos};
|
||||
static constexpr auto flags2_kadf_c_pos {3u}; // KAD format capable
|
||||
// KAD format capable
|
||||
static constexpr auto flags2_kadf_c_pos {3u};
|
||||
static constexpr std::byte flags2_kadf_c_mask {1u << flags2_kadf_c_pos};
|
||||
static constexpr auto flags2_vcelb_c_pos {2u}; // volume contains encrypted logical blocks capable
|
||||
// volume contains encrypted logical blocks capable
|
||||
static constexpr auto flags2_vcelb_c_pos {2u};
|
||||
static constexpr std::byte flags2_vcelb_c_mask {1u << flags2_vcelb_c_pos};
|
||||
static constexpr auto flags2_ukadf_pos {1u}; // U-KAD fixed
|
||||
// U-KAD fixed
|
||||
static constexpr auto flags2_ukadf_pos {1u};
|
||||
static constexpr std::byte flags2_ukadf_mask {1u << flags2_ukadf_pos};
|
||||
static constexpr auto flags2_akadf_pos {0u}; // A-KAD fixed
|
||||
// A-KAD fixed
|
||||
static constexpr auto flags2_akadf_pos {0u};
|
||||
static constexpr std::byte flags2_akadf_mask {1u << flags2_akadf_pos};
|
||||
std::uint16_t maximum_ukad_length;
|
||||
std::uint16_t maximum_akad_length;
|
||||
std::uint16_t key_length;
|
||||
std::byte flags3;
|
||||
static constexpr auto flags3_dkad_c_pos {6u}; // decryption capabilities
|
||||
// decryption capabilities
|
||||
static constexpr auto flags3_dkad_c_pos {6u};
|
||||
static constexpr std::byte flags3_dkad_c_mask {3u << flags3_dkad_c_pos};
|
||||
static constexpr auto flags3_eemc_c_pos {4u}; // external encryption mode control capabilities
|
||||
// external encryption mode control capabilities
|
||||
static constexpr auto flags3_eemc_c_pos {4u};
|
||||
static constexpr std::byte flags3_eemc_c_mask {3u << flags3_eemc_c_pos};
|
||||
static constexpr auto flags3_rdmc_c_pos {1u}; // raw decryption mode control capabilities
|
||||
// raw decryption mode control capabilities
|
||||
static constexpr auto flags3_rdmc_c_pos {1u};
|
||||
static constexpr std::byte flags3_rdmc_c_mask {7u << flags3_rdmc_c_pos};
|
||||
static constexpr auto flags3_earem_pos {0u}; // encryption algorithm records encryption mode
|
||||
// encryption algorithm records encryption mode
|
||||
static constexpr auto flags3_earem_pos {0u};
|
||||
static constexpr std::byte flags3_earem_mask {1u << flags3_earem_pos};
|
||||
std::uint8_t maximum_eedk_count;
|
||||
static constexpr auto maximum_eedk_count_pos {0u};
|
||||
static constexpr std::uint8_t maximum_eedk_count_mask {15u << maximum_eedk_count_pos};
|
||||
static constexpr std::uint8_t maximum_eedk_count_mask {
|
||||
15u << maximum_eedk_count_pos};
|
||||
std::uint16_t msdk_count;
|
||||
std::uint16_t maximum_eedk_size;
|
||||
std::byte reserved2[2];
|
||||
@@ -230,9 +265,11 @@ struct __attribute__((packed)) page_dec {
|
||||
std::uint16_t page_code;
|
||||
std::uint16_t length;
|
||||
std::byte flags;
|
||||
static constexpr auto flags_extdecc_pos {2u}; // external data encryption control capable
|
||||
// external data encryption control capable
|
||||
static constexpr auto flags_extdecc_pos {2u};
|
||||
static constexpr std::byte flags_extdecc_mask {3u << flags_extdecc_pos};
|
||||
static constexpr auto flags_cfg_p_pos {0u}; // configuration prevented
|
||||
// configuration prevented
|
||||
static constexpr auto flags_cfg_p_pos {0u};
|
||||
static constexpr std::byte flags_cfg_p_mask {3u << flags_cfg_p_pos};
|
||||
std::byte reserved[15];
|
||||
algorithm_descriptor ads[];
|
||||
@@ -304,22 +341,26 @@ static_assert(sizeof(sense_data) == 18u);
|
||||
// std::unique_ptr does not allow construction of fixed-sized arrays
|
||||
using sense_buffer = std::array<std::uint8_t, sense_data::maximum_size>;
|
||||
|
||||
class scsi_error: public std::runtime_error {
|
||||
public:
|
||||
explicit scsi_error(std::unique_ptr<sense_buffer>&& buf) :
|
||||
sense_buf {std::move(buf)}, std::runtime_error {""} {}
|
||||
const sense_data& get_sense() const { return reinterpret_cast<sense_data&>(*sense_buf->data()); }
|
||||
class scsi_error : public std::runtime_error {
|
||||
public:
|
||||
explicit scsi_error(std::unique_ptr<sense_buffer>&& buf)
|
||||
: sense_buf {std::move(buf)}, std::runtime_error {""}
|
||||
{}
|
||||
const sense_data& get_sense() const
|
||||
{
|
||||
return reinterpret_cast<sense_data&>(*sense_buf->data());
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
std::unique_ptr<sense_buffer> sense_buf;
|
||||
};
|
||||
|
||||
// Extract pointers to kad structures within a variable-length page.
|
||||
// Page must have a page_header layout
|
||||
template<typename Page>
|
||||
template <typename Page>
|
||||
std::vector<const kad *> read_page_kads(const Page& page)
|
||||
{
|
||||
const auto start {reinterpret_cast<const uint8_t*>(&page)};
|
||||
const auto start {reinterpret_cast<const std::uint8_t *>(&page)};
|
||||
auto it {start + sizeof(Page)};
|
||||
const auto end {start + ntohs(page.length) + sizeof(page_header)};
|
||||
std::vector<const kad *> v {};
|
||||
@@ -337,25 +378,26 @@ bool is_device_ready(const std::string& device);
|
||||
// Get SCSI inquiry data from device
|
||||
inquiry_data get_inquiry(const std::string& device);
|
||||
// Get data encryption status page
|
||||
void get_des(const std::string& device, std::uint8_t *buffer, std::size_t length);
|
||||
void get_des(const std::string& device, std::uint8_t *buffer,
|
||||
std::size_t length);
|
||||
// Get next block encryption status page
|
||||
void get_nbes(const std::string& device, std::uint8_t *buffer, std::size_t length);
|
||||
void get_nbes(const std::string& device, std::uint8_t *buffer,
|
||||
std::size_t length);
|
||||
// Get device encryption capabilities
|
||||
void get_dec(const std::string& device, std::uint8_t *buffer, std::size_t length);
|
||||
void get_dec(const std::string& device, std::uint8_t *buffer,
|
||||
std::size_t length);
|
||||
// Fill out a set data encryption page with parameters.
|
||||
// Result is allocated and returned as a std::unique_ptr and should
|
||||
// be sent to the device using scsi::write_sde
|
||||
std::unique_ptr<const std::uint8_t[]> make_sde(encrypt_mode enc_mode,
|
||||
decrypt_mode dec_mode,
|
||||
std::uint8_t algorithm_index,
|
||||
const std::vector<std::uint8_t>& key,
|
||||
const std::string& key_name,
|
||||
sde_rdmc rdmc, bool ckod);
|
||||
std::unique_ptr<const std::uint8_t[]>
|
||||
make_sde(encrypt_mode enc_mode, decrypt_mode dec_mode,
|
||||
std::uint8_t algorithm_index, const std::vector<std::uint8_t>& key,
|
||||
const std::string& key_name, sde_rdmc rdmc, bool ckod);
|
||||
// Write set data encryption parameters to device
|
||||
void write_sde(const std::string& device, const std::uint8_t *sde_buffer);
|
||||
void print_sense_data(std::ostream& os, const sense_data& sd);
|
||||
std::vector<const algorithm_descriptor*> read_algorithms(const page_dec& page);
|
||||
std::vector<const algorithm_descriptor *> read_algorithms(const page_dec& page);
|
||||
|
||||
}
|
||||
} // namespace scsi
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
...
|
||||
|
||||
@@ -19,9 +19,11 @@ TEST_CASE("Test key_from_hex_chars", "[output]")
|
||||
REQUIRE(key_from_hex_chars("ab cd"s) == std::nullopt);
|
||||
REQUIRE(key_from_hex_chars("a"s) == std::vector<std::uint8_t> {0x0a});
|
||||
REQUIRE(key_from_hex_chars("0123456789abcdef"s) ==
|
||||
std::vector<std::uint8_t> {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef});
|
||||
std::vector<std::uint8_t> {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
|
||||
0xef});
|
||||
REQUIRE(key_from_hex_chars("0123456789ABCDEF"s) ==
|
||||
std::vector<std::uint8_t> {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef});
|
||||
std::vector<std::uint8_t> {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
|
||||
0xef});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,18 +35,14 @@ TEST_CASE("Test key_from_hex_chars", "[output]")
|
||||
TEST_CASE("Test SCSI inquiry output", "[output]")
|
||||
{
|
||||
const uint8_t response[] {
|
||||
0x01, 0x80, 0x00, 0x02, 0x5b, 0x00, 0x00, 0x02,
|
||||
0x41, 0x43, 0x4d, 0x45, 0x20, 0x20, 0x20, 0x20,
|
||||
0x55, 0x6c, 0x74, 0x72, 0x69, 0x75, 0x6d, 0x2d,
|
||||
0x31, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20,
|
||||
0x31, 0x32, 0x33, 0x34, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x80, 0x00, 0x02, 0x5b, 0x00, 0x00, 0x02, 0x41, 0x43, 0x4d, 0x45,
|
||||
0x20, 0x20, 0x20, 0x20, 0x55, 0x6c, 0x74, 0x72, 0x69, 0x75, 0x6d, 0x2d,
|
||||
0x31, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x31, 0x32, 0x33, 0x34,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
// note: fixed width strings in output
|
||||
const std::string expected_output {"\
|
||||
@@ -52,16 +50,16 @@ Vendor: ACME \n\
|
||||
Product ID: Ultrium-1000 \n\
|
||||
Product Revision: 1234\n"s};
|
||||
std::ostringstream oss;
|
||||
print_device_inquiry(oss, reinterpret_cast<const scsi::inquiry_data&>(response));
|
||||
print_device_inquiry(oss,
|
||||
reinterpret_cast<const scsi::inquiry_data&>(response));
|
||||
REQUIRE(oss.str() == expected_output);
|
||||
}
|
||||
|
||||
TEST_CASE("SCSI get device encryption status output 1", "[output]")
|
||||
{
|
||||
const uint8_t page[] {
|
||||
0x00, 0x20, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
const std::string expected_output {"\
|
||||
Drive Encryption: off\n\
|
||||
@@ -77,11 +75,10 @@ Key Instance Counter: 0\n"s};
|
||||
TEST_CASE("SCSI get device encryption status output 2", "[output]")
|
||||
{
|
||||
const uint8_t page[] {
|
||||
0x00, 0x20, 0x00, 0x24, 0x42, 0x02, 0x02, 0x01,
|
||||
0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0c, 0x48, 0x65, 0x6c, 0x6c,
|
||||
0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
|
||||
0x00, 0x20, 0x00, 0x24, 0x42, 0x02, 0x02, 0x01, 0x00, 0x00,
|
||||
0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x48, 0x65,
|
||||
0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
|
||||
};
|
||||
const std::string expected_output {"\
|
||||
Drive Encryption: on\n\
|
||||
@@ -112,10 +109,9 @@ Volume Encryption: Not encrypted\n"s};
|
||||
TEST_CASE("Test SCSI get next block encryption status output 2", "[output]")
|
||||
{
|
||||
const uint8_t page[] {
|
||||
0x00, 0x21, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x0c, 0x48, 0x65, 0x6c, 0x6c,
|
||||
0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
|
||||
0x00, 0x21, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x48, 0x65,
|
||||
0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
|
||||
};
|
||||
const std::string expected_output {"\
|
||||
Volume Encryption: Encrypted and able to decrypt\n\
|
||||
@@ -128,15 +124,12 @@ Volume Algorithm: 1\n"s};
|
||||
TEST_CASE("Test SCSI get data encryption capabilities output", "[output]")
|
||||
{
|
||||
const std::uint8_t page[] {
|
||||
0x00, 0x10, 0x00, 0x3c, 0x09, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14,
|
||||
0x8a, 0x8c, 0x00, 0x20, 0x00, 0x3c, 0x00, 0x20,
|
||||
0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x14, 0x02, 0x00, 0x00, 0x14,
|
||||
0x8a, 0x8f, 0x00, 0x20, 0x00, 0x3c, 0x00, 0x20,
|
||||
0xd9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x10,
|
||||
0x00, 0x10, 0x00, 0x3c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14,
|
||||
0x8a, 0x8c, 0x00, 0x20, 0x00, 0x3c, 0x00, 0x20, 0xed, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, 0x02, 0x00, 0x00, 0x14,
|
||||
0x8a, 0x8f, 0x00, 0x20, 0x00, 0x3c, 0x00, 0x20, 0xd9, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10,
|
||||
};
|
||||
const std::string expected_output {"\
|
||||
Supported algorithms:\n\
|
||||
|
||||
102
tests/scsi.cpp
102
tests/scsi.cpp
@@ -18,6 +18,7 @@ using namespace std::literals::string_literals;
|
||||
TEST_CASE("Disable encryption command", "[scsi]")
|
||||
{
|
||||
const std::uint8_t expected[] {
|
||||
// clang-format off
|
||||
0x00, 0x10, // page code
|
||||
0x00, 0x10, // page length
|
||||
0x40, // scope
|
||||
@@ -28,14 +29,15 @@ TEST_CASE("Disable encryption command", "[scsi]")
|
||||
0x00, // key format
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [8]
|
||||
0x00, 0x00 // key length
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
std::vector<std::uint8_t> key {};
|
||||
std::string key_name {};
|
||||
|
||||
auto page_buffer {scsi::make_sde(scsi::encrypt_mode::off, scsi::decrypt_mode::off,
|
||||
1u, key, key_name, scsi::sde_rdmc::algorithm_default,
|
||||
false)};
|
||||
auto page_buffer {scsi::make_sde(scsi::encrypt_mode::off,
|
||||
scsi::decrypt_mode::off, 1u, key, key_name,
|
||||
scsi::sde_rdmc::algorithm_default, false)};
|
||||
auto& page {reinterpret_cast<const scsi::page_sde&>(*page_buffer.get())};
|
||||
REQUIRE(sizeof(scsi::page_header) + ntohs(page.length) == sizeof(expected));
|
||||
REQUIRE(std::memcmp(&page, expected, sizeof(expected)) == 0);
|
||||
@@ -44,6 +46,7 @@ TEST_CASE("Disable encryption command", "[scsi]")
|
||||
TEST_CASE("Enable encryption command", "[scsi]")
|
||||
{
|
||||
const std::uint8_t expected[] {
|
||||
// clang-format off
|
||||
0x00, 0x10, // page code
|
||||
0x00, 0x30, // page length
|
||||
0x40, // scope
|
||||
@@ -58,19 +61,19 @@ TEST_CASE("Enable encryption command", "[scsi]")
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
std::vector<std::uint8_t> key {
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
|
||||
0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
|
||||
0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
};
|
||||
std::string key_name {};
|
||||
|
||||
auto page_buffer {scsi::make_sde(scsi::encrypt_mode::on, scsi::decrypt_mode::on,
|
||||
1u, key, key_name, scsi::sde_rdmc::algorithm_default,
|
||||
false)};
|
||||
auto page_buffer {scsi::make_sde(scsi::encrypt_mode::on,
|
||||
scsi::decrypt_mode::on, 1u, key, key_name,
|
||||
scsi::sde_rdmc::algorithm_default, false)};
|
||||
auto& page {reinterpret_cast<const scsi::page_sde&>(*page_buffer.get())};
|
||||
REQUIRE(sizeof(scsi::page_header) + ntohs(page.length) == sizeof(expected));
|
||||
REQUIRE(std::memcmp(&page, expected, sizeof(expected)) == 0);
|
||||
@@ -79,6 +82,7 @@ TEST_CASE("Enable encryption command", "[scsi]")
|
||||
TEST_CASE("Enable encryption command with options", "[scsi]")
|
||||
{
|
||||
const std::uint8_t expected[] {
|
||||
// clang-format off
|
||||
0x00, 0x10, // page code
|
||||
0x00, 0x30, // page length
|
||||
0x40, // scope
|
||||
@@ -93,19 +97,19 @@ TEST_CASE("Enable encryption command with options", "[scsi]")
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
std::vector<std::uint8_t> key {
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
|
||||
0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
|
||||
0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
};
|
||||
std::string key_name {};
|
||||
|
||||
auto page_buffer {scsi::make_sde(scsi::encrypt_mode::on, scsi::decrypt_mode::on,
|
||||
1u, key, key_name, scsi::sde_rdmc::enabled,
|
||||
true)};
|
||||
auto page_buffer {scsi::make_sde(scsi::encrypt_mode::on,
|
||||
scsi::decrypt_mode::on, 1u, key, key_name,
|
||||
scsi::sde_rdmc::enabled, true)};
|
||||
auto& page {reinterpret_cast<const scsi::page_sde&>(*page_buffer.get())};
|
||||
REQUIRE(sizeof(scsi::page_header) + ntohs(page.length) == sizeof(expected));
|
||||
REQUIRE(std::memcmp(&page, expected, sizeof(expected)) == 0);
|
||||
@@ -114,6 +118,7 @@ TEST_CASE("Enable encryption command with options", "[scsi]")
|
||||
TEST_CASE("Enable encryption command with key name", "[scsi]")
|
||||
{
|
||||
const std::uint8_t expected[] {
|
||||
// clang-format off
|
||||
0x00, 0x10, // page code
|
||||
0x00, 0x40, // page length
|
||||
0x40, // scope
|
||||
@@ -133,20 +138,19 @@ TEST_CASE("Enable encryption command with key name", "[scsi]")
|
||||
0x00, // authenticated
|
||||
0x00, 0x0c, // length
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
std::vector<std::uint8_t> key {
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
|
||||
0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
|
||||
0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
};
|
||||
std::string key_name {"Hello world!"s};
|
||||
|
||||
auto page_buffer {scsi::make_sde(scsi::encrypt_mode::on, scsi::decrypt_mode::on,
|
||||
1u, key, key_name,
|
||||
scsi::sde_rdmc::algorithm_default,
|
||||
false)};
|
||||
auto page_buffer {scsi::make_sde(scsi::encrypt_mode::on,
|
||||
scsi::decrypt_mode::on, 1u, key, key_name,
|
||||
scsi::sde_rdmc::algorithm_default, false)};
|
||||
auto& page {reinterpret_cast<const scsi::page_sde&>(*page_buffer.get())};
|
||||
REQUIRE(sizeof(scsi::page_header) + ntohs(page.length) == sizeof(expected));
|
||||
REQUIRE(std::memcmp(&page, expected, sizeof(expected)) == 0);
|
||||
@@ -163,6 +167,7 @@ TEST_CASE("Enable encryption command with key name", "[scsi]")
|
||||
TEST_CASE("Interpret device encryption status page", "[scsi]")
|
||||
{
|
||||
const std::uint8_t buffer[] {
|
||||
// clang-format off
|
||||
0x00, 0x20, // page code
|
||||
0x00, 0x24, // length
|
||||
0x42, // nexus = 2h, key scope = 2h
|
||||
@@ -180,21 +185,22 @@ TEST_CASE("Interpret device encryption status page", "[scsi]")
|
||||
0x01, // authenticated
|
||||
0x00, 0x0c, // length
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
auto& page_des {reinterpret_cast<const scsi::page_des&>(buffer)};
|
||||
REQUIRE(ntohs(page_des.page_code) == 0x20u);
|
||||
REQUIRE(ntohs(page_des.length) == 36u);
|
||||
REQUIRE((page_des.scope & scsi::page_des::scope_it_nexus_mask)
|
||||
>> scsi::page_des::scope_it_nexus_pos == std::byte {2u});
|
||||
REQUIRE((page_des.scope & scsi::page_des::scope_encryption_mask)
|
||||
>> scsi::page_des::scope_encryption_pos == std::byte {2u});
|
||||
REQUIRE((page_des.scope & scsi::page_des::scope_it_nexus_mask) ==
|
||||
std::byte {2u} << scsi::page_des::scope_it_nexus_pos);
|
||||
REQUIRE((page_des.scope & scsi::page_des::scope_encryption_mask) ==
|
||||
std::byte {2u} << scsi::page_des::scope_encryption_pos);
|
||||
REQUIRE(page_des.encryption_mode == scsi::encrypt_mode::on);
|
||||
REQUIRE(page_des.decryption_mode == scsi::decrypt_mode::on);
|
||||
REQUIRE(page_des.algorithm_index == 1u);
|
||||
REQUIRE(ntohl(page_des.key_instance_counter) == 1u);
|
||||
REQUIRE((page_des.flags & scsi::page_des::flags_parameters_control_mask)
|
||||
== std::byte {1u} << scsi::page_des::flags_parameters_control_pos);
|
||||
REQUIRE((page_des.flags & scsi::page_des::flags_parameters_control_mask) ==
|
||||
std::byte {1u} << scsi::page_des::flags_parameters_control_pos);
|
||||
REQUIRE((page_des.flags & scsi::page_des::flags_vcelb_mask) ==
|
||||
scsi::page_des::flags_vcelb_mask);
|
||||
REQUIRE((page_des.flags & scsi::page_des::flags_ceems_mask) == std::byte {});
|
||||
@@ -202,14 +208,17 @@ TEST_CASE("Interpret device encryption status page", "[scsi]")
|
||||
|
||||
auto kads = read_page_kads(page_des);
|
||||
REQUIRE(kads.size() == 1u);
|
||||
REQUIRE((kads[0]->flags & scsi::kad::flags_authenticated_mask) == std::byte {1u});
|
||||
REQUIRE((kads[0]->flags & scsi::kad::flags_authenticated_mask) ==
|
||||
std::byte {1u});
|
||||
REQUIRE(ntohs(kads[0]->length) == std::strlen("Hello world!"));
|
||||
REQUIRE(std::memcmp(kads[0]->descriptor, "Hello world!", ntohs(kads[0]->length)) == 0);
|
||||
REQUIRE(std::memcmp(kads[0]->descriptor, "Hello world!",
|
||||
ntohs(kads[0]->length)) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("Interpret next block encryption status page", "[scsi]")
|
||||
{
|
||||
const std::uint8_t buffer[] {
|
||||
// clang-format off
|
||||
0x00, 0x21, // page code
|
||||
0x00, 0x1c, // length
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
@@ -222,28 +231,34 @@ TEST_CASE("Interpret next block encryption status page", "[scsi]")
|
||||
0x01, // authenticated
|
||||
0x00, 0x0c, // length
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
auto& page_nbes {reinterpret_cast<const scsi::page_nbes&>(buffer)};
|
||||
REQUIRE(ntohs(page_nbes.page_code) == 0x21u);
|
||||
REQUIRE(ntohs(page_nbes.length) == 28u);
|
||||
REQUIRE((page_nbes.status & scsi::page_nbes::status_compression_mask) == std::byte {});
|
||||
REQUIRE((page_nbes.status & scsi::page_nbes::status_encryption_mask)
|
||||
== std::byte {5u} << scsi::page_nbes::status_encryption_pos);
|
||||
REQUIRE((page_nbes.status & scsi::page_nbes::status_compression_mask) ==
|
||||
std::byte {});
|
||||
REQUIRE((page_nbes.status & scsi::page_nbes::status_encryption_mask) ==
|
||||
std::byte {5u} << scsi::page_nbes::status_encryption_pos);
|
||||
REQUIRE(page_nbes.algorithm_index == 1u);
|
||||
REQUIRE((page_nbes.flags & scsi::page_nbes::flags_emes_mask) == std::byte {});
|
||||
REQUIRE((page_nbes.flags & scsi::page_nbes::flags_rdmds_mask) == std::byte {});
|
||||
REQUIRE((page_nbes.flags & scsi::page_nbes::flags_rdmds_mask) ==
|
||||
std::byte {});
|
||||
|
||||
auto kads = read_page_kads(page_nbes);
|
||||
REQUIRE(kads.size() == 1u);
|
||||
REQUIRE((kads[0]->flags & scsi::kad::flags_authenticated_mask) == std::byte {1u});
|
||||
REQUIRE((kads[0]->flags & scsi::kad::flags_authenticated_mask) ==
|
||||
std::byte {1u});
|
||||
REQUIRE(ntohs(kads[0]->length) == std::strlen("Hello world!"));
|
||||
REQUIRE(std::memcmp(kads[0]->descriptor, "Hello world!", ntohs(kads[0]->length)) == 0);
|
||||
REQUIRE(std::memcmp(kads[0]->descriptor, "Hello world!",
|
||||
ntohs(kads[0]->length)) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("Interpret data encryption capabilties page", "[scsi]")
|
||||
{
|
||||
const std::uint8_t buffer[] {
|
||||
// clang-format off
|
||||
0x00, 0x10, // page code
|
||||
0x00, 0x3c, // length
|
||||
0x09, // EXTDECC and CFG_P
|
||||
@@ -279,6 +294,7 @@ TEST_CASE("Interpret data encryption capabilties page", "[scsi]")
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x10,
|
||||
// clang-format on
|
||||
};
|
||||
static_assert(sizeof(buffer) == sizeof(scsi::page_dec) +
|
||||
2 * sizeof(scsi::algorithm_descriptor));
|
||||
@@ -337,8 +353,8 @@ TEST_CASE("Interpret data encryption capabilties page", "[scsi]")
|
||||
REQUIRE((algo1.flags3 & scsi::algorithm_descriptor::flags3_earem_mask) ==
|
||||
scsi::algorithm_descriptor::flags3_earem_mask);
|
||||
|
||||
REQUIRE((algo1.maximum_eedk_count & scsi::algorithm_descriptor::maximum_eedk_count_mask) ==
|
||||
0u);
|
||||
REQUIRE((algo1.maximum_eedk_count &
|
||||
scsi::algorithm_descriptor::maximum_eedk_count_mask) == 0u);
|
||||
REQUIRE(ntohs(algo1.msdk_count) == 0u);
|
||||
REQUIRE(ntohs(algo1.maximum_eedk_size) == 0u);
|
||||
REQUIRE(ntohl(algo1.security_algorithm_code) == 0x00010014u);
|
||||
@@ -385,8 +401,8 @@ TEST_CASE("Interpret data encryption capabilties page", "[scsi]")
|
||||
REQUIRE((algo2.flags3 & scsi::algorithm_descriptor::flags3_earem_mask) ==
|
||||
scsi::algorithm_descriptor::flags3_earem_mask);
|
||||
|
||||
REQUIRE((algo2.maximum_eedk_count & scsi::algorithm_descriptor::maximum_eedk_count_mask) ==
|
||||
0u);
|
||||
REQUIRE((algo2.maximum_eedk_count &
|
||||
scsi::algorithm_descriptor::maximum_eedk_count_mask) == 0u);
|
||||
REQUIRE(ntohs(algo2.msdk_count) == 0u);
|
||||
REQUIRE(ntohs(algo2.maximum_eedk_size) == 0u);
|
||||
REQUIRE(ntohl(algo2.security_algorithm_code) == 0x00010010u);
|
||||
|
||||
Reference in New Issue
Block a user