Do validation of options against device capabilities (#83)
* Validate options against device capabilities * Use std::reference_wrapper instead of raw pointers * Reword error message * Also validate --(no-)allow-raw-read against device capabilities * --ckod should do a media check
This commit is contained in:
231
src/main.cpp
231
src/main.cpp
@@ -15,8 +15,10 @@ GNU General Public License for more details.
|
||||
*/
|
||||
#include <config.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <charconv>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
@@ -114,7 +116,7 @@ encryption status and capabilities of DEVICE, including a list of supported\n\
|
||||
algorithm indexes.\n";
|
||||
}
|
||||
|
||||
static void print_algorithm_name(std::ostream& os, const uint32_t code)
|
||||
static void print_algorithm_name(std::ostream& os, const std::uint32_t code)
|
||||
{
|
||||
// Reference: SFSC / INCITS 501-2016
|
||||
if (0x80010400 <= code && code <= 0x8001FFFF) {
|
||||
@@ -146,8 +148,7 @@ static void print_algorithms(std::ostream& os, const scsi::page_dec& page)
|
||||
|
||||
os << "Supported algorithms:\n";
|
||||
|
||||
for (auto ad_ptr: algorithms) {
|
||||
auto& ad {*ad_ptr};
|
||||
for (const scsi::algorithm_descriptor& ad: algorithms) {
|
||||
os << std::left << std::setw(5)
|
||||
<< static_cast<unsigned int>(ad.algorithm_index);
|
||||
print_algorithm_name(os, ntohl(ad.security_algorithm_code));
|
||||
@@ -156,7 +157,7 @@ static void print_algorithms(std::ostream& os, const scsi::page_dec& page)
|
||||
// Print KAD capabilities and size
|
||||
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) {
|
||||
if (dkad_c == 2u << scsi::algorithm_descriptor::flags3_dkad_c_pos) {
|
||||
os << std::left << std::setw(5) << ""
|
||||
<< "Key descriptors not allowed\n";
|
||||
} else if (dkad_c) {
|
||||
@@ -213,13 +214,6 @@ static void print_device_inquiry(std::ostream& os,
|
||||
os.put('\n');
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
os << std::left << std::setw(25) << "Drive Output:";
|
||||
@@ -275,33 +269,22 @@ static void print_device_status(std::ostream& os, const scsi::page_des& opt)
|
||||
<< static_cast<unsigned int>(opt.algorithm_index) << '\n';
|
||||
}
|
||||
auto kads {scsi::read_page_kads(opt)};
|
||||
for (auto kd: kads) {
|
||||
switch (kd->type) {
|
||||
for (const scsi::kad& kd: kads) {
|
||||
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)
|
||||
{
|
||||
alignas(4) scsi::page_buffer buffer;
|
||||
scsi::get_des(tapeDrive, buffer, sizeof(buffer));
|
||||
auto& opt {reinterpret_cast<const scsi::page_des&>(buffer)};
|
||||
|
||||
print_device_status(std::cout, opt);
|
||||
}
|
||||
|
||||
static void print_volume_status(std::ostream& os, const scsi::page_nbes& opt)
|
||||
{
|
||||
auto compression_status {static_cast<std::uint8_t>(
|
||||
@@ -343,18 +326,18 @@ static void print_volume_status(std::ostream& os, const scsi::page_nbes& opt)
|
||||
break;
|
||||
case 6u << scsi::page_nbes::status_encryption_pos:
|
||||
os << "Encrypted, but unable to decrypt due to invalid key.\n";
|
||||
for (auto kd: kads) {
|
||||
switch (kd->type) {
|
||||
for (const scsi::kad& kd: kads) {
|
||||
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;
|
||||
}
|
||||
@@ -376,15 +359,6 @@ static void print_volume_status(std::ostream& os, const scsi::page_nbes& opt)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct termios settings {};
|
||||
@@ -402,12 +376,14 @@ int main(int argc, char **argv)
|
||||
|
||||
std::optional<scsi::encrypt_mode> enc_mode;
|
||||
std::optional<scsi::decrypt_mode> dec_mode;
|
||||
std::uint8_t algorithm_index;
|
||||
std::optional<std::uint8_t> algorithm_index;
|
||||
std::vector<uint8_t> key;
|
||||
std::string key_name;
|
||||
scsi::sde_rdmc rdmc {};
|
||||
bool ckod {};
|
||||
|
||||
alignas(4) scsi::page_buffer buffer {};
|
||||
|
||||
enum opt_key : int {
|
||||
opt_version = 256,
|
||||
opt_ckod,
|
||||
@@ -446,7 +422,7 @@ int main(int argc, char **argv)
|
||||
dec_mode = scsi::decrypt_mode::mixed;
|
||||
} else {
|
||||
print_usage(std::cerr);
|
||||
exit(EXIT_FAILURE);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -458,7 +434,7 @@ int main(int argc, char **argv)
|
||||
enc_mode = scsi::encrypt_mode::off;
|
||||
} else {
|
||||
print_usage(std::cerr);
|
||||
exit(EXIT_FAILURE);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -477,21 +453,21 @@ int main(int argc, char **argv)
|
||||
case opt_rdmc_disable:
|
||||
rdmc = scsi::sde_rdmc::disabled;
|
||||
break;
|
||||
case static_cast<int>('h'):
|
||||
case 'h':
|
||||
print_usage(std::cout);
|
||||
exit(EXIT_SUCCESS);
|
||||
std::exit(EXIT_SUCCESS);
|
||||
case opt_version:
|
||||
std::cout << "stenc " VERSION " - SCSI Tape Encryption Manager\n"
|
||||
<< "https://github.com/scsitape/stenc\n";
|
||||
exit(EXIT_SUCCESS);
|
||||
std::exit(EXIT_SUCCESS);
|
||||
default:
|
||||
print_usage(std::cerr);
|
||||
exit(EXIT_FAILURE);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (optind != argc) { // left-over unparsed arguments or options
|
||||
print_usage(std::cerr);
|
||||
exit(EXIT_FAILURE);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// select device from env variable or system default if not given with -f
|
||||
@@ -511,11 +487,15 @@ int main(int argc, char **argv)
|
||||
<< "--------------------------------------------------\n";
|
||||
|
||||
try {
|
||||
inquiryDrive(tapeDrive);
|
||||
showDriveStatus(tapeDrive);
|
||||
print_device_inquiry(std::cout, scsi::get_inquiry(tapeDrive));
|
||||
scsi::get_des(tapeDrive, buffer, sizeof(buffer));
|
||||
print_device_status(std::cout,
|
||||
reinterpret_cast<const scsi::page_des&>(buffer));
|
||||
if (scsi::is_device_ready(tapeDrive)) {
|
||||
try {
|
||||
showVolumeStatus(tapeDrive);
|
||||
scsi::get_nbes(tapeDrive, buffer, sizeof(buffer));
|
||||
print_volume_status(std::cout,
|
||||
reinterpret_cast<const scsi::page_nbes&>(buffer));
|
||||
} catch (const scsi::scsi_error& err) {
|
||||
// #71: ignore BLANK CHECK sense key that some drives may return
|
||||
// during media access check in getting NBES
|
||||
@@ -526,19 +506,17 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
}
|
||||
alignas(4) scsi::page_buffer buffer {};
|
||||
scsi::get_dec(tapeDrive, buffer, sizeof(buffer));
|
||||
auto& page {reinterpret_cast<const scsi::page_dec&>(buffer)};
|
||||
|
||||
print_algorithms(std::cout, page);
|
||||
exit(EXIT_SUCCESS);
|
||||
print_algorithms(std::cout,
|
||||
reinterpret_cast<const scsi::page_dec&>(buffer));
|
||||
std::exit(EXIT_SUCCESS);
|
||||
} catch (const scsi::scsi_error& err) {
|
||||
std::cerr << "stenc: " << err.what() << '\n';
|
||||
scsi::print_sense_data(std::cerr, err.get_sense());
|
||||
exit(EXIT_FAILURE);
|
||||
std::exit(EXIT_FAILURE);
|
||||
} catch (const std::runtime_error& err) {
|
||||
std::cerr << "stenc: " << err.what() << '\n';
|
||||
exit(EXIT_FAILURE);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,7 +531,7 @@ int main(int argc, char **argv)
|
||||
} else {
|
||||
std::cerr << "stenc: Unexpected encrypt mode "
|
||||
<< static_cast<unsigned int>(*enc_mode) << '\n';
|
||||
exit(EXIT_FAILURE);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (!enc_mode && dec_mode) {
|
||||
if (dec_mode == scsi::decrypt_mode::off) {
|
||||
@@ -566,7 +544,7 @@ int main(int argc, char **argv)
|
||||
} else {
|
||||
std::cerr << "stenc: Unexpected decrypt mode "
|
||||
<< static_cast<unsigned int>(*dec_mode) << '\n';
|
||||
exit(EXIT_FAILURE);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,7 +552,7 @@ int main(int argc, char **argv)
|
||||
dec_mode != scsi::decrypt_mode::off) {
|
||||
if (keyFile.empty()) {
|
||||
std::cerr << "stenc: Encryption key required but no key file specified\n";
|
||||
exit(EXIT_FAILURE);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// set keyInput here
|
||||
@@ -582,7 +560,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (keyFile == "-"s) { // Read key file from standard input
|
||||
if (isatty(STDIN_FILENO)) {
|
||||
std::cout << "Enter key (input will be hidden): ";
|
||||
std::cout << "Enter key in hex format (input will be hidden): ";
|
||||
echo(false);
|
||||
}
|
||||
std::getline(std::cin, keyInput);
|
||||
@@ -596,7 +574,7 @@ int main(int argc, char **argv)
|
||||
if (!myfile.is_open()) {
|
||||
std::cerr << "stenc: Cannot open " << keyFile << ": " << strerror(errno)
|
||||
<< '\n';
|
||||
exit(EXIT_FAILURE);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
std::getline(myfile, keyInput);
|
||||
std::getline(myfile, key_name);
|
||||
@@ -606,53 +584,114 @@ int main(int argc, char **argv)
|
||||
key = *key_bytes;
|
||||
} else {
|
||||
std::cerr << "stenc: Invalid key in key file\n";
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
scsi::get_dec(tapeDrive, buffer, sizeof(buffer));
|
||||
auto& dec_page {reinterpret_cast<const scsi::page_dec&>(buffer)};
|
||||
auto algorithms {scsi::read_algorithms(dec_page)};
|
||||
|
||||
if (algorithm_index == std::nullopt) {
|
||||
if (algorithms.size() == 1) {
|
||||
// Pick the only available algorithm if not specified
|
||||
const scsi::algorithm_descriptor& ad = algorithms[0];
|
||||
std::cerr << "Algorithm index not specified, using " << std::dec
|
||||
<< static_cast<unsigned int>(ad.algorithm_index) << " (";
|
||||
print_algorithm_name(std::cerr, ntohl(ad.security_algorithm_code));
|
||||
std::cerr << ")\n";
|
||||
algorithm_index = ad.algorithm_index;
|
||||
} else {
|
||||
std::cerr << "stenc: Algorithm index not specified\n";
|
||||
print_algorithms(std::cerr, dec_page);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
auto algo_it {
|
||||
std::find_if(algorithms.begin(), algorithms.end(),
|
||||
[algorithm_index](const scsi::algorithm_descriptor& ad) {
|
||||
return ad.algorithm_index == algorithm_index;
|
||||
})};
|
||||
if (algo_it == algorithms.end()) {
|
||||
std::cerr << "stenc: Algorithm index " << std::dec
|
||||
<< static_cast<unsigned int>(*algorithm_index)
|
||||
<< " not supported by device\n";
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
const scsi::algorithm_descriptor& ad = *algo_it;
|
||||
|
||||
if ((enc_mode != scsi::encrypt_mode::off ||
|
||||
dec_mode != scsi::decrypt_mode::off) &&
|
||||
key.size() != ntohs(ad.key_length)) {
|
||||
std::cerr << "stenc: Incorrect key size, expected " << std::dec
|
||||
<< ntohs(ad.key_length) << " bytes, got " << key.size() << '\n';
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (key_name.size() > ntohs(ad.maximum_ukad_length)) {
|
||||
std::cerr << "stenc: Key descriptor exceeds maximum length of "
|
||||
<< std::dec << ntohs(ad.maximum_ukad_length) << " bytes\n";
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
bool ukad_fixed =
|
||||
(ad.flags2 & scsi::algorithm_descriptor::flags2_ukadf_mask) ==
|
||||
scsi::algorithm_descriptor::flags2_ukadf_mask;
|
||||
if (ukad_fixed && key_name.size() < ntohs(ad.maximum_ukad_length)) {
|
||||
// Pad key descriptor to required length
|
||||
key_name.resize(ntohs(ad.maximum_ukad_length), ' ');
|
||||
}
|
||||
|
||||
if (enc_mode != scsi::encrypt_mode::on) {
|
||||
// key descriptor only valid when key is used for writing
|
||||
key_name.erase();
|
||||
}
|
||||
|
||||
if (rdmc != scsi::sde_rdmc {}) {
|
||||
auto rdmc_c {static_cast<unsigned int>(
|
||||
ad.flags3 & scsi::algorithm_descriptor::flags3_rdmc_c_mask)};
|
||||
if (rdmc_c == 6u << scsi::algorithm_descriptor::flags3_rdmc_c_pos ||
|
||||
rdmc_c == 7u << scsi::algorithm_descriptor::flags3_rdmc_c_pos) {
|
||||
std::cerr << "stenc: Device does not allow control of raw reads\n";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ckod && !scsi::is_device_ready(tapeDrive)) {
|
||||
std::cerr << "stenc: Cannot use --ckod when no tape media is loaded\n";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (enc_mode != scsi::encrypt_mode::on) {
|
||||
key_name.erase(); // key descriptor only valid when key is used for writing
|
||||
}
|
||||
|
||||
// Write the options to the tape device
|
||||
std::cerr << "Changing encryption settings on device " << tapeDrive << '\n';
|
||||
try {
|
||||
// Write the options to the tape device
|
||||
std::cerr << "Changing encryption settings for device " << tapeDrive
|
||||
<< "...\n";
|
||||
auto sde_buffer {scsi::make_sde(enc_mode.value(), dec_mode.value(),
|
||||
algorithm_index, key, key_name, rdmc,
|
||||
ckod)};
|
||||
algorithm_index.value(), 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)};
|
||||
std::ostringstream oss;
|
||||
|
||||
if (enc_mode != scsi::encrypt_mode::off) {
|
||||
std::stringstream msg;
|
||||
msg << "Encryption turned on for device '" << tapeDrive << "'. ";
|
||||
if (!key_name.empty()) {
|
||||
msg << "Key Descriptor: '" << key_name << "'";
|
||||
}
|
||||
msg << " Key Instance: " << std::dec << ntohl(opt.key_instance_counter)
|
||||
<< '\n';
|
||||
|
||||
syslog(LOG_NOTICE, "%s", msg.str().c_str());
|
||||
} else {
|
||||
std::stringstream msg {};
|
||||
|
||||
msg << "Encryption turned off for device '" << tapeDrive << "'.";
|
||||
msg << " Key Instance: " << std::dec << ntohl(opt.key_instance_counter)
|
||||
<< '\n';
|
||||
|
||||
syslog(LOG_NOTICE, "%s", msg.str().c_str());
|
||||
oss << "Encryption settings changed for device " << tapeDrive
|
||||
<< ": mode: encrypt = " << enc_mode.value()
|
||||
<< ", decrypt = " << dec_mode.value() << '.';
|
||||
if (!key_name.empty()) {
|
||||
oss << " Key Descriptor: '" << key_name << "',";
|
||||
}
|
||||
oss << " Key Instance Counter: " << std::dec
|
||||
<< ntohl(opt.key_instance_counter) << '\n';
|
||||
syslog(LOG_NOTICE, "%s", oss.str().c_str());
|
||||
std::cerr << "Success! See system logs for a key change audit log.\n";
|
||||
} catch (const scsi::scsi_error& err) {
|
||||
std::cerr << "stenc: " << err.what() << '\n';
|
||||
scsi::print_sense_data(std::cerr, err.get_sense());
|
||||
exit(EXIT_FAILURE);
|
||||
std::exit(EXIT_FAILURE);
|
||||
} catch (const std::runtime_error& err) {
|
||||
std::cerr << "stenc: " << err.what() << '\n';
|
||||
exit(EXIT_FAILURE);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif // defined(CATCH_CONFIG_MAIN)
|
||||
|
||||
@@ -16,6 +16,7 @@ GNU General Public License for more details.
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@@ -358,16 +359,17 @@ 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<std::reference_wrapper<const algorithm_descriptor>>
|
||||
read_algorithms(const page_dec& page)
|
||||
{
|
||||
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 {};
|
||||
std::vector<std::reference_wrapper<const algorithm_descriptor>> v {};
|
||||
|
||||
while (it < end) {
|
||||
auto elem {reinterpret_cast<const algorithm_descriptor *>(it)};
|
||||
v.push_back(elem);
|
||||
v.push_back(std::cref(*elem));
|
||||
it += ntohs(elem->length) + 4u; // length field + preceding 4 byte header
|
||||
}
|
||||
return v;
|
||||
|
||||
@@ -20,7 +20,9 @@ GNU General Public License for more details.
|
||||
#include <bitset>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -35,7 +37,6 @@ GNU General Public License for more details.
|
||||
#endif
|
||||
|
||||
constexpr std::size_t SSP_PAGE_ALLOCATION = 8192;
|
||||
constexpr std::size_t SSP_UKAD_LENGTH = 0x1e;
|
||||
|
||||
// outputs hex in a 2 digit pair
|
||||
#define HEX(x) \
|
||||
@@ -50,6 +51,18 @@ enum class encrypt_mode : std::uint8_t {
|
||||
on = 2u,
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, encrypt_mode m)
|
||||
{
|
||||
if (m == encrypt_mode::off) {
|
||||
os << "off";
|
||||
} else if (m == encrypt_mode::external) {
|
||||
os << "external";
|
||||
} else {
|
||||
os << "on";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
enum class decrypt_mode : std::uint8_t {
|
||||
off = 0u,
|
||||
raw = 1u,
|
||||
@@ -57,6 +70,20 @@ enum class decrypt_mode : std::uint8_t {
|
||||
mixed = 3u,
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, decrypt_mode m)
|
||||
{
|
||||
if (m == decrypt_mode::off) {
|
||||
os << "off";
|
||||
} else if (m == decrypt_mode::raw) {
|
||||
os << "raw";
|
||||
} else if (m == decrypt_mode::on) {
|
||||
os << "on";
|
||||
} else {
|
||||
os << "mixed";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
enum class kad_type : std::uint8_t {
|
||||
ukad = 0u, // unauthenticated key-associated data
|
||||
akad = 1u, // authenticated key-associated data
|
||||
@@ -358,16 +385,16 @@ private:
|
||||
// Extract pointers to kad structures within a variable-length page.
|
||||
// Page must have a page_header layout
|
||||
template <typename Page>
|
||||
std::vector<const kad *> read_page_kads(const Page& page)
|
||||
std::vector<std::reference_wrapper<const kad>> read_page_kads(const Page& 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 {};
|
||||
std::vector<std::reference_wrapper<const kad>> v {};
|
||||
|
||||
while (it < end) {
|
||||
auto elem {reinterpret_cast<const kad *>(it)};
|
||||
v.push_back(elem);
|
||||
v.push_back(std::cref(*elem));
|
||||
it += ntohs(elem->length) + sizeof(kad);
|
||||
}
|
||||
return v;
|
||||
@@ -396,7 +423,8 @@ make_sde(encrypt_mode enc_mode, decrypt_mode dec_mode,
|
||||
// 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<std::reference_wrapper<const algorithm_descriptor>>
|
||||
read_algorithms(const page_dec& page);
|
||||
|
||||
} // namespace scsi
|
||||
|
||||
|
||||
@@ -208,11 +208,10 @@ 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(ntohs(kads[0]->length) == std::strlen("Hello world!"));
|
||||
REQUIRE(std::memcmp(kads[0]->descriptor, "Hello world!",
|
||||
ntohs(kads[0]->length)) == 0);
|
||||
const scsi::kad& kd = kads[0];
|
||||
REQUIRE((kd.flags & scsi::kad::flags_authenticated_mask) == std::byte {1u});
|
||||
REQUIRE(ntohs(kd.length) == std::strlen("Hello world!"));
|
||||
REQUIRE(std::memcmp(kd.descriptor, "Hello world!", ntohs(kd.length)) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("Interpret next block encryption status page", "[scsi]")
|
||||
@@ -248,11 +247,10 @@ TEST_CASE("Interpret next block encryption status page", "[scsi]")
|
||||
|
||||
auto kads = read_page_kads(page_nbes);
|
||||
REQUIRE(kads.size() == 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);
|
||||
const scsi::kad& kd = kads[0];
|
||||
REQUIRE((kd.flags & scsi::kad::flags_authenticated_mask) == std::byte {1u});
|
||||
REQUIRE(ntohs(kd.length) == std::strlen("Hello world!"));
|
||||
REQUIRE(std::memcmp(kd.descriptor, "Hello world!", ntohs(kd.length)) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("Interpret data encryption capabilties page", "[scsi]")
|
||||
@@ -311,7 +309,7 @@ TEST_CASE("Interpret data encryption capabilties page", "[scsi]")
|
||||
auto algorithms {read_algorithms(page_dec)};
|
||||
REQUIRE(algorithms.size() == 2u);
|
||||
|
||||
auto& algo1 {*algorithms[0]};
|
||||
const scsi::algorithm_descriptor& algo1 = algorithms[0];
|
||||
REQUIRE(algo1.algorithm_index == 1u);
|
||||
REQUIRE(ntohs(algo1.length) == 20u);
|
||||
REQUIRE((algo1.flags1 & scsi::algorithm_descriptor::flags1_avfmv_mask) ==
|
||||
@@ -359,7 +357,7 @@ TEST_CASE("Interpret data encryption capabilties page", "[scsi]")
|
||||
REQUIRE(ntohs(algo1.maximum_eedk_size) == 0u);
|
||||
REQUIRE(ntohl(algo1.security_algorithm_code) == 0x00010014u);
|
||||
|
||||
auto& algo2 {*algorithms[1]};
|
||||
const scsi::algorithm_descriptor& algo2 = algorithms[1];
|
||||
REQUIRE(algo2.algorithm_index == 2u);
|
||||
REQUIRE(ntohs(algo2.length) == 20u);
|
||||
REQUIRE((algo2.flags1 & scsi::algorithm_descriptor::flags1_avfmv_mask) ==
|
||||
|
||||
Reference in New Issue
Block a user