Use KAD format field (#86)

This commit is contained in:
James Wilson
2022-06-05 15:40:52 -07:00
committed by GitHub
parent f77e46eeb0
commit a3d03e5211
4 changed files with 47 additions and 33 deletions

View File

@@ -144,11 +144,9 @@ static void print_algorithm_name(std::ostream& os, const std::uint32_t code)
static void print_algorithms(std::ostream& os, const scsi::page_dec& page)
{
auto algorithms {scsi::read_algorithms(page)};
os << "Supported algorithms:\n";
for (const scsi::algorithm_descriptor& ad: algorithms) {
for (const scsi::algorithm_descriptor& ad: scsi::read_algorithms(page)) {
os << std::left << std::setw(5)
<< static_cast<unsigned int>(ad.algorithm_index);
print_algorithm_name(os, ntohl(ad.security_algorithm_code));
@@ -268,8 +266,7 @@ static void print_device_status(std::ostream& os, const scsi::page_des& opt)
os << std::setw(25) << "Encryption Algorithm:" << std::dec
<< static_cast<unsigned int>(opt.algorithm_index) << '\n';
}
auto kads {scsi::read_page_kads(opt)};
for (const scsi::kad& kd: kads) {
for (const scsi::kad& kd: scsi::read_page_kads(opt)) {
switch (kd.type) {
case scsi::kad_type::ukad:
os << std::setw(25) << "Drive Key Desc.(uKAD): ";
@@ -305,7 +302,6 @@ 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)};
auto kads {read_page_kads(opt)};
switch (encryption_status) {
case 0u << scsi::page_nbes::status_encryption_pos:
case 1u << scsi::page_nbes::status_encryption_pos:
@@ -326,7 +322,7 @@ 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 (const scsi::kad& kd: kads) {
for (const scsi::kad& kd: read_page_kads(opt)) {
switch (kd.type) {
case scsi::kad_type::ukad:
os << std::setw(25) << "Volume Key Desc.(uKAD): ";
@@ -380,6 +376,7 @@ int main(int argc, char **argv)
std::vector<uint8_t> key;
std::string key_name;
scsi::sde_rdmc rdmc {};
scsi::kadf kad_format {};
bool ckod {};
alignas(4) scsi::page_buffer buffer {};
@@ -644,6 +641,12 @@ int main(int argc, char **argv)
key_name.resize(ntohs(ad.maximum_ukad_length), ' ');
}
if ((ad.flags2 & scsi::algorithm_descriptor::flags2_kadf_c_mask) ==
scsi::algorithm_descriptor::flags2_kadf_c_mask) {
kad_format =
scsi::kadf::ascii_key_name; // set KAD format field if allowed
}
if (enc_mode != scsi::encrypt_mode::on) {
// key descriptor only valid when key is used for writing
key_name.erase();
@@ -655,13 +658,13 @@ int main(int argc, char **argv)
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);
std::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);
std::exit(EXIT_FAILURE);
}
// Write the options to the tape device
@@ -669,7 +672,7 @@ int main(int argc, char **argv)
<< "...\n";
auto sde_buffer {scsi::make_sde(enc_mode.value(), dec_mode.value(),
algorithm_index.value(), key, key_name,
rdmc, ckod)};
kad_format, rdmc, ckod)};
scsi::write_sde(tapeDrive, sde_buffer.get());
scsi::get_des(tapeDrive, buffer, sizeof(buffer));
auto& opt {reinterpret_cast<const scsi::page_des&>(buffer)};

View File

@@ -238,7 +238,7 @@ inquiry_data get_inquiry(const std::string& device)
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)
const std::string& key_name, kadf kad_format, sde_rdmc rdmc, bool ckod)
{
std::size_t length {sizeof(page_sde) + key.size()};
if (!key_name.empty()) {
@@ -260,6 +260,7 @@ make_sde(encrypt_mode enc_mode, decrypt_mode dec_mode,
page.encryption_mode = enc_mode;
page.decryption_mode = dec_mode;
page.algorithm_index = algorithm_index;
page.kad_format = kad_format;
page.key_length = htons(key.size());
std::memcpy(page.key, key.data(), key.size());

View File

@@ -92,6 +92,12 @@ enum class kad_type : std::uint8_t {
wkkad = 4u, // wrapped key key-associated data
};
enum class kadf : std::uint8_t {
unspecified = 0u,
binary_key_name = 1u,
ascii_key_name = 2u,
};
// key-associated data
struct __attribute__((packed)) kad {
kad_type type;
@@ -137,7 +143,7 @@ struct __attribute__((packed)) page_des {
// 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;
kadf kad_format;
std::uint16_t asdk_count;
std::byte reserved[8];
kad kads[];
@@ -178,7 +184,7 @@ struct __attribute__((packed)) page_sde {
decrypt_mode decryption_mode;
std::uint8_t algorithm_index;
std::uint8_t key_format;
std::uint8_t kad_format;
kadf kad_format;
std::byte reserved[7];
std::uint16_t key_length;
std::uint8_t key[];
@@ -187,9 +193,9 @@ static_assert(sizeof(page_sde) == 20u);
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
enabled = 2u << page_sde::flags_rdmc_pos, // corresponds to --allow-raw-read
// command line option
disabled = 3u << page_sde::flags_rdmc_pos, // corresponds to --protect command
disabled = 3u << page_sde::flags_rdmc_pos, // corresponds to --no-allow-raw-read command
// line option
};
@@ -213,7 +219,7 @@ struct __attribute__((packed)) page_nbes {
// 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;
kadf kad_format;
kad kads[];
};
static_assert(sizeof(page_nbes) == 16u);
@@ -419,7 +425,7 @@ void get_dec(const std::string& device, std::uint8_t *buffer,
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);
const std::string& key_name, kadf key_format, 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);

View File

@@ -27,7 +27,8 @@ TEST_CASE("Disable encryption command", "[scsi]")
0x00, // decryption mode
0x01, // algorithm index
0x00, // key format
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [8]
0x00, // KAD format
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [7]
0x00, 0x00 // key length
// clang-format on
};
@@ -35,9 +36,9 @@ TEST_CASE("Disable encryption command", "[scsi]")
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::kadf::unspecified, 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);
@@ -55,7 +56,8 @@ TEST_CASE("Enable encryption command", "[scsi]")
0x02, // decryption mode
0x01, // algorithm index
0x00, // key format
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [8]
0x00, // KAD format
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [7]
0x00, 0x20, // key length
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
@@ -71,9 +73,9 @@ TEST_CASE("Enable encryption command", "[scsi]")
};
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::kadf::unspecified, 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);
@@ -91,7 +93,8 @@ TEST_CASE("Enable encryption command with options", "[scsi]")
0x02, // decryption mode
0x01, // algorithm index
0x00, // key format
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [8]
0x01, // KAD format
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [7]
0x00, 0x20, // key length
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
@@ -107,9 +110,9 @@ TEST_CASE("Enable encryption command with options", "[scsi]")
};
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::kadf::binary_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);
@@ -127,7 +130,8 @@ TEST_CASE("Enable encryption command with key name", "[scsi]")
0x02, // decryption mode
0x01, // algorithm index
0x00, // key format
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [8]
0x02, // KAD format
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [7]
0x00, 0x20, // key length
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
@@ -148,9 +152,9 @@ TEST_CASE("Enable encryption command with key name", "[scsi]")
};
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::kadf::ascii_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);