Small cleanup: (#65)

- pass string arguments by reference
- replace macros with constexpr where possible
- move command strings out of global scope
- use standard library strerror instead of custom printer readIOError
This commit is contained in:
James Wilson
2022-05-10 10:20:55 -07:00
committed by GitHub
parent ebabc39c3e
commit 8ebccddc50
3 changed files with 180 additions and 196 deletions

View File

@@ -13,33 +13,35 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "scsiencrypt.h"
#include <config.h>
#include <charconv>
#include <config.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <cstdint>
#include <fstream>
#include <iomanip>
#include <ios>
#include <iostream>
#include <optional>
#include <stdint.h>
#include <sstream>
#include <string>
#include <vector>
#include <syslog.h>
#include <sys/mtio.h>
#include <sys/stat.h>
#include <termios.h>
#include <vector>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "scsiencrypt.h"
typedef struct {
#if STENC_BIG_ENDIAN == 0
@@ -63,12 +65,11 @@ typedef struct {
#endif
} bitcheck;
using namespace std;
void showUsage();
void errorOut(std::string const message);
void inquiryDrive(std::string tapeDevice);
void showDriveStatus(std::string tapeDevice, bool detail);
void showVolumeStatus(std::string tapeDevice);
void errorOut(const std::string& message);
void inquiryDrive(const std::string& tapeDevice);
void showDriveStatus(const std::string& tapeDevice, bool detail);
void showVolumeStatus(const std::string& tapeDevice);
void echo(bool);
static std::optional<std::vector<uint8_t>> key_from_hex_chars(const std::string& s)
@@ -79,7 +80,7 @@ static std::optional<std::vector<uint8_t>> key_from_hex_chars(const std::string&
if (s.size() % 2) { // treated as if there is an implicit leading 0
uint8_t result;
auto [ptr, ec] { std::from_chars(it, it + 1, result, 16) };
if (ec != errc {}) {
if (ec != std::errc {}) {
return {};
}
bytes.push_back(result);
@@ -89,7 +90,7 @@ static std::optional<std::vector<uint8_t>> key_from_hex_chars(const std::string&
while (*it) {
uint8_t result;
auto [ptr, ec] { std::from_chars(it, it + 2, result, 16) };
if (ec != errc {}) {
if (ec != std::errc {}) {
return {};
}
bytes.push_back(result);
@@ -98,7 +99,7 @@ static std::optional<std::vector<uint8_t>> key_from_hex_chars(const std::string&
return bytes;
}
int main(int argc, char **argv) {
int main(int argc, const char **argv) {
bitcheck bc;
memset(&bc, 0, 1);
bc.bit2 = 1;
@@ -340,9 +341,9 @@ int main(int argc, char **argv) {
errorOut("Turning encryption off for '" + tapeDrive + "' failed!");
}
}
// exits to shell with an error message
void errorOut(std::string const message) {
// exits to shell with an error message
void errorOut(const std::string& message) {
std::cerr << "Error: " << message << "\n";
showUsage();
exit(EXIT_FAILURE);
@@ -350,13 +351,14 @@ void errorOut(std::string const message) {
// shows the command usage
void showUsage() {
std::cout
std::cerr
<< "Usage: stenc --version | "
"-f <device> [--detail] [-e <on/mixed/rawread/off> [-k <file>] "
"[-kd <description>] [-a <index>] [--protect | --unprotect] [--ckod] ]\n\n"
"Type 'man stenc' for more information.\n";
}
void inquiryDrive(std::string tapeDevice) {
void inquiryDrive(const std::string& tapeDevice) {
// todo: std::cout should not be used outside main()
SCSI_PAGE_INQ *const iresult = SCSIGetInquiry(tapeDevice);
std::cout << std::left << std::setw(25) << "Device Mfg:";
@@ -372,7 +374,7 @@ void inquiryDrive(std::string tapeDevice) {
delete iresult;
}
void showDriveStatus(std::string tapeDrive, bool detail) {
void showDriveStatus(const std::string& tapeDrive, bool detail) {
SSP_DES *opt = SSPGetDES(tapeDrive);
if (opt == NULL)
return;
@@ -477,7 +479,7 @@ void showDriveStatus(std::string tapeDrive, bool detail) {
delete opt;
}
void showVolumeStatus(std::string tapeDrive) {
void showVolumeStatus(const std::string& tapeDrive) {
SSP_NBES *opt = SSPGetNBES(tapeDrive, true);
if (opt == NULL)
return;
@@ -551,7 +553,7 @@ void showVolumeStatus(std::string tapeDrive) {
delete opt;
}
void echo(bool on = true) {
void echo(bool on) {
struct termios settings {};
tcgetattr(STDIN_FILENO, &settings);
settings.c_lflag =

View File

@@ -12,15 +12,18 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include <bitset>
#include <config.h>
#include <errno.h>
#include <fcntl.h>
#include <bitset>
#include <cerrno>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mtio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -45,93 +48,40 @@ GNU General Public License for more details.
#endif
#include "scsiencrypt.h"
#include <sys/mtio.h>
#define SSP_SPIN_OPCODE 0XA2
#define SSP_SPOUT_OPCODE 0XB5
#define SSP_SP_CMD_LEN 12
#define SSP_SP_PROTOCOL_TDE 0X20
constexpr uint8_t SSP_SPIN_OPCODE = 0xa2;
constexpr uint8_t SSP_SPOUT_OPCODE = 0xb5;
constexpr uint8_t SSP_SP_CMD_LEN = 12;
constexpr uint8_t SSP_SP_PROTOCOL_TDE = 0x20;
#define RETRYCOUNT 1
constexpr int RETRYCOUNT = 1;
#define BSINTTOCHAR(x) \
(unsigned char)((x & 0xff000000) >> 24), \
(unsigned char)((x & 0x00ff0000) >> 16), \
(unsigned char)((x & 0x0000ff00) >> 8), (unsigned char)(x & 0x000000ff)
#define BSINTTOCHAR(x) \
static_cast<uint8_t>((x) >> 24), \
static_cast<uint8_t>((x) >> 16), \
static_cast<uint8_t>((x) >> 8), \
static_cast<uint8_t>((x))
void byteswap(unsigned char *array, int size, int value);
bool moveTape(std::string tapeDevice, int count, bool dirForward);
bool moveTape(const std::string& tapeDevice, int count, bool dirForward);
void outputSense(SCSI_PAGE_SENSE *sd);
void readIOError(int err);
bool SCSIExecute(std::string tapedevice, unsigned char *cmd_p, int cmd_len,
bool SCSIExecute(const std::string& tapedevice, unsigned char *cmd_p, int cmd_len,
unsigned char *dxfer_p, int dxfer_len, bool cmd_to_device,
bool show_error);
typedef struct { // structure for setting data encryption
unsigned char pageCode[2];
unsigned char length[2];
#if STENC_BIG_ENDIAN == 1
unsigned char scope : 3;
unsigned char res_bits_1 : 4;
unsigned char lock : 1;
#else
unsigned char lock : 1;
unsigned char res_bits_1 : 4;
unsigned char scope : 3;
#endif
#if STENC_BIG_ENDIAN == 1
unsigned char CEEM : 2;
unsigned char RDMC : 2;
unsigned char sdk : 1;
unsigned char ckod : 1;
unsigned char ckorp : 1;
unsigned char ckorl : 1;
#else
unsigned char ckorl : 1;
unsigned char ckorp : 1;
unsigned char ckod : 1;
unsigned char sdk : 1;
unsigned char RDMC : 2;
unsigned char CEEM : 2;
#endif
unsigned char encryptionMode;
unsigned char decryptionMode;
unsigned char algorithmIndex;
unsigned char keyFormat;
unsigned char res_bits_2[8];
unsigned char keyLength[2];
unsigned char keyData[SSP_KEY_LENGTH];
} SSP_PAGE_SDE;
unsigned char scsi_sense_command[6] = {0x03, 0, 0, 0, sizeof(SCSI_PAGE_SENSE),
0},
scsi_inq_command[6] = {0x12, 0, 0, 0, sizeof(SCSI_PAGE_INQ), 0},
spin_des_command[SSP_SP_CMD_LEN] = {SSP_SPIN_OPCODE,
SSP_SP_PROTOCOL_TDE,
0,
0X20,
0,
0,
BSINTTOCHAR(
sizeof(SSP_PAGE_BUFFER)),
0,
0},
spin_nbes_command[SSP_SP_CMD_LEN] = {
SSP_SPIN_OPCODE,
SSP_SP_PROTOCOL_TDE,
0,
0X21,
0,
0,
BSINTTOCHAR(sizeof(SSP_PAGE_BUFFER)),
0,
0};
// Gets encryption options on the tape drive
SSP_DES *SSPGetDES(std::string tapeDevice) {
SSP_DES *SSPGetDES(const std::string& tapeDevice) {
const uint8_t spin_des_command[] {
SSP_SPIN_OPCODE,
SSP_SP_PROTOCOL_TDE,
0,
0X20,
0,
0,
BSINTTOCHAR(sizeof(SSP_PAGE_BUFFER)),
0,
0,
};
SSP_PAGE_BUFFER buffer;
memset(&buffer, 0, sizeof(SSP_PAGE_BUFFER));
if (!SCSIExecute(tapeDevice, (unsigned char *)&spin_des_command,
@@ -144,8 +94,18 @@ SSP_DES *SSPGetDES(std::string tapeDevice) {
}
// Gets encryption options on the tape drive
SSP_NBES *SSPGetNBES(std::string tapeDevice, bool retry) {
SSP_NBES *SSPGetNBES(const std::string& tapeDevice, bool retry) {
const uint8_t spin_nbes_command[] {
SSP_SPIN_OPCODE,
SSP_SP_PROTOCOL_TDE,
0,
0X21,
0,
0,
BSINTTOCHAR(sizeof(SSP_PAGE_BUFFER)),
0,
0,
};
SSP_PAGE_BUFFER buffer;
memset(&buffer, 0, sizeof(SSP_PAGE_BUFFER));
if (!SCSIExecute(tapeDevice, (unsigned char *)&spin_nbes_command,
@@ -177,7 +137,8 @@ SSP_NBES *SSPGetNBES(std::string tapeDevice, bool retry) {
}
// Sends and inquiry to the device
SCSI_PAGE_INQ *SCSIGetInquiry(std::string tapeDevice) {
SCSI_PAGE_INQ *SCSIGetInquiry(const std::string& tapeDevice) {
const uint8_t scsi_inq_command[] {0x12, 0, 0, 0, sizeof(SCSI_PAGE_INQ), 0};
SCSI_PAGE_INQ *status = new SCSI_PAGE_INQ;
memset(status, 0, sizeof(SCSI_PAGE_INQ));
if (!SCSIExecute(tapeDevice, (unsigned char *)&scsi_inq_command,
@@ -256,21 +217,22 @@ int SCSIInitSDEPage(SCSIEncryptOptions *eOptions,
}
// Writes encryption options to the tape drive
bool SCSIWriteEncryptOptions(std::string tapeDevice,
bool SCSIWriteEncryptOptions(const std::string& tapeDevice,
SCSIEncryptOptions *eOptions) {
uint8_t buffer[1024];
memset(&buffer, 0, 1024);
uint8_t buffer[1024] {};
int pagelen = SCSIInitSDEPage(eOptions, buffer);
unsigned char spout_sde_command[SSP_SP_CMD_LEN] = {SSP_SPOUT_OPCODE,
SSP_SP_PROTOCOL_TDE,
0,
0X10,
0,
0,
BSINTTOCHAR(pagelen),
0,
0};
const uint8_t spout_sde_command[] {
SSP_SPOUT_OPCODE,
SSP_SP_PROTOCOL_TDE,
0,
0X10,
0,
0,
BSINTTOCHAR(pagelen),
0,
0,
};
// return whether or not the command executed
return SCSIExecute(tapeDevice, (unsigned char *)&spout_sde_command,
@@ -278,7 +240,7 @@ bool SCSIWriteEncryptOptions(std::string tapeDevice,
pagelen, true, true);
}
bool SCSIExecute(std::string tapedrive, unsigned char *cmd_p, int cmd_len,
bool SCSIExecute(const std::string& tapedrive, unsigned char *cmd_p, int cmd_len,
unsigned char *dxfer_p, int dxfer_len, bool cmd_to_device,
bool show_error) {
const char *tapedevice = tapedrive.c_str();
@@ -287,11 +249,10 @@ bool SCSIExecute(std::string tapedrive, unsigned char *cmd_p, int cmd_len,
memset(sd, 0, sizeof(SCSI_PAGE_SENSE));
#if defined(OS_LINUX)
errno = 0;
sg_fd = open(tapedevice, O_RDONLY);
if (sg_fd == -1) {
std::cerr << "Could not open device '" << tapedevice << "': ";
readIOError(errno);
std::cerr << "Could not open device '" << tapedevice << "': "
<< strerror(errno) << "\n";
exit(EXIT_FAILURE);
}
@@ -318,7 +279,6 @@ bool SCSIExecute(std::string tapedrive, unsigned char *cmd_p, int cmd_len,
sresult = cmdio.status;
close(sg_fd);
#elif defined(OS_FREEBSD)
errno = 0;
auto dev = cam_open_device(tapedevice, O_RDWR);
auto ccb = dev ? cam_getccb(dev) : nullptr;
@@ -363,8 +323,9 @@ bool SCSIExecute(std::string tapedrive, unsigned char *cmd_p, int cmd_len,
bool retval = true;
if (eresult != 0) {
if (show_error)
readIOError(ioerr);
if (show_error) {
std::cerr << "ERROR: " << strerror(ioerr) << "\n";
}
retval = false;
}
@@ -376,6 +337,7 @@ bool SCSIExecute(std::string tapedrive, unsigned char *cmd_p, int cmd_len,
delete sd;
return retval;
}
void byteswap(unsigned char *array, int size, int value) {
switch (size) {
case 2:
@@ -409,6 +371,7 @@ SSP_NBES::SSP_NBES(const SSP_PAGE_BUFFER *buffer) {
memcpy(&nbes, buffer, sizeof(SSP_PAGE_NBES));
loadKADs(buffer, sizeof(SSP_PAGE_NBES));
}
SSP_DES::SSP_DES(const SSP_PAGE_BUFFER *buffer) {
memset(&des, 0, sizeof(SSP_PAGE_DES));
memcpy(&des, buffer, sizeof(SSP_PAGE_DES));
@@ -435,7 +398,8 @@ void KAD_CLASS::loadKADs(const SSP_PAGE_BUFFER *buffer, int start) {
kads.push_back(kad);
}
}
bool moveTape(std::string tapeDevice, int count, bool dirForward) {
bool moveTape(const std::string& tapeDevice, int count, bool dirForward) {
struct mtop mt_command;
int sg_fd = open(tapeDevice.c_str(), O_RDONLY);
if (!sg_fd || sg_fd == -1) {
@@ -459,32 +423,6 @@ bool moveTape(std::string tapeDevice, int count, bool dirForward) {
return retval;
}
void readIOError(int err) {
if (err == 0)
return;
std::cerr << "ERROR: ";
switch (err) {
case EAGAIN:
std::cerr << "Device already open.\n";
break;
case EBUSY:
std::cerr << "Device Busy.\n";
break;
case ETIMEDOUT:
std::cerr << "Device operation timed out\n";
break;
case EIO:
std::cerr << "Device I/O Error.\n";
break;
case EPERM:
std::cerr << "You do not have privileges to do this. Are you root?\n";
break;
default:
if (errno != 0) {
std::cerr << "0x" << std::hex << errno << " " << strerror(errno) << "\n";
}
}
}
void outputSense(SCSI_PAGE_SENSE *sd) {
std::cerr << std::left << std::setw(25) << "Sense Code: ";
@@ -524,8 +462,7 @@ void outputSense(SCSI_PAGE_SENSE *sd) {
<< "0x" << HEX(sd->addSenseCodeQual) << "\n";
if (sd->addSenseLen > 0) {
std::cerr << std::left << std::setw(25) << " Additional data:"
<< "0x";
std::cerr << std::left << std::setw(25) << " Additional data: 0x";
for (int i = 0; i < sd->addSenseLen; i++) {
std::cerr << HEX(sd->addSenseData[i]);

View File

@@ -15,35 +15,10 @@ GNU General Public License for more details.
#ifndef _SCSIENC_H
#define _SCSIENC_H
#include <bitset>
#include <string>
#include <vector>
#define SSP_KEY_LENGTH 0X20
#define SSP_DESCRIPTOR_LENGTH 1024
#define SSP_PAGE_DES_LENGTH 24
#define SSP_PAGE_NBES_LENGTH 16
#define SSP_KAD_HEAD_LENGTH 4
#define SSP_PAGE_ALLOCATION 8192
#define SSP_UKAD_LENGTH 0x1e
#define KAD_TYPE_UKAD 0x00
#define KAD_TYPE_AKAD 0x01
#define KAD_TYPE_NONCE 0x02
#define KAD_TYPE_META 0x03
#define RDMC_PROTECT 0x03
#define RDMC_UNPROTECT 0x02
#define RDMC_DEFAULT 0x00
// outputs hex in a 2 digit pair
#define HEX(x) \
std::right << std::setw(2) << std::setfill('0') << std::hex << (int)(x) << std::setfill(' ')
// macro for a byte swapped short
#define BSSHORT(x) ((unsigned short)((x[0] << 8) + x[1]))
// macro for a byte swapped int
#define BSLONG(x) \
((unsigned int)((int)(x[0] << 24) + (int)(x[1] << 16) + (int)(x[2] << 8) + \
(int)(x[3])))
#ifdef HAVE_SYS_MACHINE_H
#include <sys/machine.h>
@@ -53,7 +28,37 @@ GNU General Public License for more details.
#include <sys/types.h>
#endif
#include <vector>
constexpr size_t SSP_KEY_LENGTH = 0X20;
constexpr size_t SSP_DESCRIPTOR_LENGTH = 1024;
constexpr size_t SSP_KAD_HEAD_LENGTH = 4;
constexpr size_t SSP_PAGE_ALLOCATION = 8192;
constexpr size_t SSP_UKAD_LENGTH = 0x1e;
constexpr uint8_t KAD_TYPE_UKAD = 0x00;
constexpr uint8_t KAD_TYPE_AKAD = 0x01;
constexpr uint8_t KAD_TYPE_NONCE = 0x02;
constexpr uint8_t KAD_TYPE_META = 0x03;
constexpr uint8_t RDMC_PROTECT = 0x03;
constexpr uint8_t RDMC_UNPROTECT = 0x02;
constexpr uint8_t RDMC_DEFAULT = 0x00;
// outputs hex in a 2 digit pair
#define HEX(x) \
std::right << std::setw(2) << std::setfill('0') << std::hex << (int)(x) << std::setfill(' ')
// macro for a byte swapped short
constexpr uint16_t BSSHORT(const uint8_t *p)
{
return static_cast<uint16_t>(p[0]) << 8 | p[1];
}
// macro for a byte swapped int
constexpr uint32_t BSLONG(const uint8_t *p)
{
return static_cast<uint32_t>(p[0]) << 24 |
static_cast<uint32_t>(p[1]) << 16 |
static_cast<uint32_t>(p[2]) << 8 |
static_cast<uint32_t>(p[3]);
}
#ifdef BYTE_ORDER
#define STENC_BYTE_ORDER BYTE_ORDER
@@ -79,7 +84,7 @@ GNU General Public License for more details.
#define STENC_BIG_ENDIAN 0
#endif
typedef struct {
struct SSP_PAGE_DES {
unsigned char pageCode[2];
unsigned char length[2];
@@ -114,9 +119,9 @@ typedef struct {
unsigned char ASDKCount[2];
unsigned char res_bits_4[8];
} SSP_PAGE_DES; // device encryption status page
}; // device encryption status page
typedef struct {
struct SSP_KAD{
unsigned char type;
#if STENC_BIG_ENDIAN == 1
unsigned char res_bits_1 : 5;
@@ -128,15 +133,53 @@ typedef struct {
unsigned char descriptorLength[2];
unsigned char descriptor[SSP_DESCRIPTOR_LENGTH]; // will actually be the size
// of descriptorLength
} SSP_KAD;
};
typedef struct {
struct SSP_PAGE_BUFFER {
unsigned char pageCode[2];
unsigned char length[2];
unsigned char buffer[SSP_PAGE_ALLOCATION];
} SSP_PAGE_BUFFER; // generic ssp page buffer
}; // generic ssp page buffer
typedef struct {
struct SSP_PAGE_SDE { // structure for setting data encryption
unsigned char pageCode[2];
unsigned char length[2];
#if STENC_BIG_ENDIAN == 1
unsigned char scope : 3;
unsigned char res_bits_1 : 4;
unsigned char lock : 1;
#else
unsigned char lock : 1;
unsigned char res_bits_1 : 4;
unsigned char scope : 3;
#endif
#if STENC_BIG_ENDIAN == 1
unsigned char CEEM : 2;
unsigned char RDMC : 2;
unsigned char sdk : 1;
unsigned char ckod : 1;
unsigned char ckorp : 1;
unsigned char ckorl : 1;
#else
unsigned char ckorl : 1;
unsigned char ckorp : 1;
unsigned char ckod : 1;
unsigned char sdk : 1;
unsigned char RDMC : 2;
unsigned char CEEM : 2;
#endif
unsigned char encryptionMode;
unsigned char decryptionMode;
unsigned char algorithmIndex;
unsigned char keyFormat;
unsigned char res_bits_2[8];
unsigned char keyLength[2];
unsigned char keyData[SSP_KEY_LENGTH];
};
struct SSP_PAGE_NBES {
unsigned char pageCode[2];
unsigned char length[2];
unsigned char log_obj_num[8];
@@ -160,9 +203,9 @@ typedef struct {
#endif
unsigned char res_bits_2;
} SSP_PAGE_NBES; // next block encryption status page
}; // next block encryption status page
typedef struct {
struct SCSI_PAGE_INQ {
#if STENC_BIG_ENDIAN == 0
unsigned char peripheralQualifier : 3;
@@ -267,8 +310,9 @@ typedef struct {
unsigned char versionDescriptor[16];
unsigned char res_bits_5[22];
unsigned char copyright[1];
} SCSI_PAGE_INQ; // device inquiry response
typedef struct {
}; // device inquiry response
struct SCSI_PAGE_SENSE {
#if STENC_BIG_ENDIAN == 1
unsigned char valid : 1;
unsigned char responseCode : 7;
@@ -313,7 +357,8 @@ typedef struct {
#endif
unsigned char field[2]; // field pointer
unsigned char addSenseData[109];
} SCSI_PAGE_SENSE; // sense data response
}; // sense data response
class KAD_CLASS {
public:
std::vector<SSP_KAD> kads;
@@ -351,14 +396,14 @@ public:
};
// Gets encryption options on the tape drive
SSP_DES *SSPGetDES(std::string tapeDevice);
SSP_DES *SSPGetDES(const std::string& tapeDevice);
// Gets the encryption status from the tape volume
SSP_NBES *SSPGetNBES(std::string tapeDevice, bool retry);
SSP_NBES *SSPGetNBES(const std::string& tapeDevice, bool retry);
// Writes encryption options to the tape drive
int SCSIInitSDEPage(SCSIEncryptOptions *eOptions,
uint8_t *buffer);
bool SCSIWriteEncryptOptions(std::string tapeDevice,
bool SCSIWriteEncryptOptions(const std::string& tapeDevice,
SCSIEncryptOptions *eOptions);
// Gets device inquiry
SCSI_PAGE_INQ *SCSIGetInquiry(std::string tapeDevice);
SCSI_PAGE_INQ *SCSIGetInquiry(const std::string& tapeDevice);
#endif