diff --git a/src/main.cpp b/src/main.cpp index fa4c7c9..4181e27 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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(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(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( 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 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(buffer)}; diff --git a/src/scsiencrypt.cpp b/src/scsiencrypt.cpp index 03fec45..b0c1a85 100644 --- a/src/scsiencrypt.cpp +++ b/src/scsiencrypt.cpp @@ -238,7 +238,7 @@ inquiry_data get_inquiry(const std::string& device) std::unique_ptr make_sde(encrypt_mode enc_mode, decrypt_mode dec_mode, std::uint8_t algorithm_index, const std::vector& 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()); diff --git a/src/scsiencrypt.h b/src/scsiencrypt.h index d83c973..4f9b5c7 100644 --- a/src/scsiencrypt.h +++ b/src/scsiencrypt.h @@ -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 make_sde(encrypt_mode enc_mode, decrypt_mode dec_mode, std::uint8_t algorithm_index, const std::vector& 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); diff --git a/tests/scsi.cpp b/tests/scsi.cpp index 1b721d6..dd52f2d 100644 --- a/tests/scsi.cpp +++ b/tests/scsi.cpp @@ -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 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(*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(*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(*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(*page_buffer.get())}; REQUIRE(sizeof(scsi::page_header) + ntohs(page.length) == sizeof(expected)); REQUIRE(std::memcmp(&page, expected, sizeof(expected)) == 0);