diff --git a/configure.ac b/configure.ac index 93bb3a4..1a74c4c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([stenc], [1.0.8]) +AC_INIT([stenc],[1.0.8]) AC_CONFIG_SRCDIR([src/main.cpp]) AM_INIT_AUTOMAKE([foreign]) @@ -9,7 +9,15 @@ AC_CHECK_HEADER([sys/machine.h]) AC_PROG_CXX # Checks for header files. -AC_HEADER_STDC +m4_warn([obsolete], +[The preprocessor macro `STDC_HEADERS' is obsolete. + Except in unusual embedded environments, you can safely include all + ISO C90 headers unconditionally.])dnl +# Autoupdate added the next two lines to ensure that your configure +# script's behavior did not change. They are probably safe to remove. +AC_CHECK_INCLUDES_DEFAULT +AC_PROG_EGREP + AC_MSG_CHECKING(whether to output raw SCSI messages) @@ -93,5 +101,6 @@ fi -AC_OUTPUT(Makefile src/Makefile man/Makefile) +AC_CONFIG_FILES([Makefile src/Makefile man/Makefile]) +AC_OUTPUT diff --git a/src/keyinfo.cpp b/src/keyinfo.cpp index 6659525..2eb9e14 100644 --- a/src/keyinfo.cpp +++ b/src/keyinfo.cpp @@ -5,7 +5,7 @@ #include #include "keyinfo.h" #include "scsiencrypt.h" -using namespace std; +//using namespace std; Keyinfo::Keyinfo(){ valid=false; @@ -13,11 +13,11 @@ Keyinfo::Keyinfo(){ key=NULL; keySize=0; } -void Keyinfo::load(string hexinput){ +void Keyinfo::load(std::string hexinput){ valid=true; if(hexinput.size()<2){ valid=false; - cout<<"Key input too short!"<SSP_KEY_LENGTH){ - cout<<"Key size cannot exceed "<<(SSP_KEY_LENGTH*8)<<" bits!"< #include #ifdef HAVE_UNISTD_H - #include +#include #endif -#include -#include -#include #include +#include +#include +#include #include #include #include #ifdef HAVE_STDLIB_H - #include +#include #endif #ifdef HAVE_STRING_H - #include +#include #endif -#include "scsiencrypt.h" #include "keyinfo.h" -#define LOGFILE "/var/log/stenc" +#include "scsiencrypt.h" +#include + +#define LOGFILE "/var/log/stenc" typedef struct { #if STENC_BIG_ENDIAN == 0 - unsigned char bit1:1; - unsigned char bit2:1; - unsigned char bit3:1; - unsigned char bit4:1; - unsigned char bit5:1; - unsigned char bit6:1; - unsigned char bit7:1; - unsigned char bit8:1; + unsigned char bit1 : 1; + unsigned char bit2 : 1; + unsigned char bit3 : 1; + unsigned char bit4 : 1; + unsigned char bit5 : 1; + unsigned char bit6 : 1; + unsigned char bit7 : 1; + unsigned char bit8 : 1; #else - unsigned char bit8:1; - unsigned char bit7:1; - unsigned char bit6:1; - unsigned char bit5:1; - unsigned char bit4:1; - unsigned char bit3:1; - unsigned char bit2:1; - unsigned char bit1:1; + unsigned char bit8 : 1; + unsigned char bit7 : 1; + unsigned char bit6 : 1; + unsigned char bit5 : 1; + unsigned char bit4 : 1; + unsigned char bit3 : 1; + unsigned char bit2 : 1; + unsigned char bit1 : 1; #endif } bitcheck; + using namespace std; void showUsage(); -void errorOut(string message); -void inquiryDrive(string tapeDevice); -void showDriveStatus(string tapeDevice,bool detail); -void showVolumeStatus(string tapeDevice); -string randomKey(int length); -string timestamp(); +void errorOut(std::string const message); +void inquiryDrive(std::string tapeDevice); +void showDriveStatus(std::string tapeDevice, bool detail); +void showVolumeStatus(std::string tapeDevice); +std::string randomKey(int length); +std::string timestamp(); void echo(bool); -ofstream logFile; -//program entry point -int main(int argc, char **argv){ +std::ofstream logFile; - bitcheck bc; - memset(&bc,0,1); - bc.bit2=1; - bc.bit5=1; - unsigned char check; - memcpy(&check,&bc,1); +int main(int argc, char **argv) { - switch((int)check){ - case 0x12: - //this is good - break; - case 0x48: + bitcheck bc; + memset(&bc, 0, 1); + bc.bit2 = 1; + bc.bit5 = 1; + unsigned char check; + memcpy(&check, &bc, 1); + + switch ((int)check) { + case 0x12: + // this is good + break; + case 0x48: #if STENC_BIG_ENDIAN == 1 - errorOut("Swapped bit ordering detected(BI). Program needs to be configured without the --enable-swapendian option in order to function properly on your system"); + errorOut("Swapped bit ordering detected(BI). Program needs to be " + "configured without the --enable-swapendian option in order to " + "function properly on your system"); #else - errorOut("Swapped bit ordering detected(LI). Program needs to be configured with the --enable-swapendian option in order to function properly on your system"); + errorOut("Swapped bit ordering detected(LI). Program needs to be " + "configured with the --enable-swapendian option in order to " + "function properly on your system"); #endif - break; - default: - cerr<<"Unknown bit check result "<SSP_KEY_LENGTH){ - cout<<"Warning: Keys over "<<(SSP_KEY_LENGTH*8)<<" bits cannot be used by this program!"<SSP_UKAD_LENGTH){ - errorOut("Key description too long!"); - } - i++; //skip the next argument - } - else if(thisCmd=="--protect"){ - if(drvOptions.rdmc==RDMC_UNPROTECT)errorOut("'--protect' cannot be specified at the same time as '--unprotect'"); - drvOptions.rdmc=RDMC_PROTECT; - } - else if(thisCmd=="--unprotect"){ - if(drvOptions.rdmc==RDMC_PROTECT)errorOut("'--unprotect' cannot be specified at the same time as '--protect'"); - drvOptions.rdmc=RDMC_UNPROTECT; - } - else if(thisCmd=="--ckod"){ - drvOptions.CKOD=true; - } - else if(thisCmd=="--detail"){ - detail=true; - } - else if(thisCmd=="-a"){ - if(nextCmd=="")errorOut("You must specify a numeric algorithm index when using the -a flag"); - drvOptions.algorithmIndex=atoi(nextCmd.c_str()); - i++; //skip the next argument - } - else{ - errorOut("Unknown command '"+thisCmd+"'"); - } - + if (thisCmd == "--version") { + std::cout << "stenc v" << VERSION << " - SCSI Tape Encryption Manager\n"; + std::cout << "https://github.com/scsitape/stenc" << std::endl; + exit(EXIT_SUCCESS); } - - if(action==2){//generate key - if(keyFile==""){ - errorOut("Specify file to save into with the -k argument."); - } - - string newkey=randomKey(keyLength); - ofstream kf; - umask(077); //make sure that no one else can read the new key file we are creating - kf.open(keyFile.c_str(),ios::trunc); - if(!kf.is_open()){ - errorOut("Could not open '"+keyFile+"' for writing."); - - } - kf<des.encryptionMode!=2){ - errorOut("Turning encryption on for '"+tapeDrive+"' failed!"); - } - if(drvOptions.cryptMode==CRYPTMODE_OFF && opt->des.encryptionMode!=0){ - errorOut("Turning encryption off for '"+tapeDrive+"' failed!"); - } - delete opt; - - if(drvOptions.cryptMode!=CRYPTMODE_OFF){ - stringstream msg; - msg<<"Encryption turned on for device '"<des.keyInstance)<des.keyInstance)< -k [-kd ] | -f [--detail] [-e [-k ] [-kd ] [-a ] [--protect | --unprotect] [--ckod] ]"<vender,8); - cout<productID,16); - cout<productRev,4); - cout<des.encryptionMode==0x2 && //encrypt - (int)opt->des.decryptionMode==0x2 //read only encrypted data - ) - emode="on"; - if( - (int)opt->des.encryptionMode==0x2 && //encrypt - (int)opt->des.decryptionMode==0x3 //read encrypted and unencrypted - ) - emode="mixed"; - - if( - (int)opt->des.encryptionMode==0x2 && //encrypt - (int)opt->des.decryptionMode==0x1 //read encrypted and unencrypted - ) - emode="rawread"; - - if( - (int)opt->des.encryptionMode==0x0 && //encrypt - (int)opt->des.decryptionMode==0x0 //read encrypted and unencrypted - ) - emode="off"; - - cout<des.decryptionMode){ - case 0x0: - cout<<"Not decrypting"<des.decryptionMode<<"' "<des.encryptionMode){ - case 0x0: - cout<<"Not encrypting"<des.encryptionMode<<"'"<des.RDMD==1){ - cout<des.keyInstance)<des.algorithmIndex!=0){ - cout<des.algorithmIndex<kads.size()>0){ - for(unsigned int i=0;ikads.size();i++){ - stringstream lbl; - lbl<<"Drive Key Desc.("; - switch(opt->kads[i].type){ - case KAD_TYPE_UKAD: - lbl<<"uKAD): "; - cout<kads[i].descriptor,BSSHORT(opt->kads[i].descriptorLength)); - cout<kads[i].descriptor,BSSHORT(opt->kads[i].descriptorLength)); - cout<nbes.compressionStatus!=0){ - cout<nbes.compressionStatus){ - case 0x00: - cout<<"Drive cannot determine"<nbes.compressionStatus<<"'"<nbes.encryptionStatus){ - case 0x01: - cout<<"Unable to determine"<nbes.RDMDS==1) - cout<kads.size()>0){ - for(unsigned int i=0;ikads.size();i++){ - stringstream lbl; - lbl<<"Volume Key Desc.("; - switch(opt->kads[i].type){ - case KAD_TYPE_UKAD: - lbl<<"uKAD): "; - cout<kads[i].descriptor,BSSHORT(opt->kads[i].descriptorLength)); - cout<kads[i].descriptor,BSSHORT(opt->kads[i].descriptorLength)); - cout<nbes.RDMDS==1) - cout<nbes.encryptionStatus<<"'"<nbes.algorithmIndex!=0){ - cout<nbes.algorithmIndex<(&rnd), 1); - retval < SSP_KEY_LENGTH) { + std::cout << "Warning: Keys over " << (SSP_KEY_LENGTH * 8) + << " bits cannot be used by this program!" << std::endl; + } + action = 2; // generating key + } else if (thisCmd == "-e") { + if (nextCmd == "") + errorOut("Key file not specified after -k option"); + if (nextCmd == "on") + drvOptions.cryptMode = CRYPTMODE_ON; // encrypt, read only encrypted + // data + else if (nextCmd == "mixed") + drvOptions.cryptMode = + CRYPTMODE_MIXED; // encrypt, read encrypted and unencrypted data + else if (nextCmd == "rawread") + drvOptions.cryptMode = + CRYPTMODE_RAWREAD; // encrypt, read encrypted and unencrypted data + else if (nextCmd == "off") + drvOptions.cryptMode = + CRYPTMODE_OFF; // encrypt, read encrypted and unencrypted data + else + errorOut("Unknown encryption mode '" + nextCmd + + "'"); // encrypt, read encrypted and unencrypted data + i++; // skip the next argument + action = 1; + } else if (thisCmd == "-f") { + if (nextCmd == "") + errorOut("Device not specified after -f option."); + tapeDrive = nextCmd; // set the tape drive + i++; // skip the next argument + } else if (thisCmd == "-k") { + if (nextCmd == "") + errorOut("Key file not specified after -k option"); + keyFile = nextCmd; // set the key file + i++; // skip the next argument + } else if (thisCmd == "-kd") { + if (nextCmd == "") + errorOut("Key description not specified after the -kd option"); + keyDesc = nextCmd; // set the key file + if (keyDesc.size() > SSP_UKAD_LENGTH) { + errorOut("Key description too long!"); + } + i++; // skip the next argument + } else if (thisCmd == "--protect") { + if (drvOptions.rdmc == RDMC_UNPROTECT) + errorOut("'--protect' cannot be specified at the same time as " + "'--unprotect'"); + drvOptions.rdmc = RDMC_PROTECT; + } else if (thisCmd == "--unprotect") { + if (drvOptions.rdmc == RDMC_PROTECT) + errorOut("'--unprotect' cannot be specified at the same time as " + "'--protect'"); + drvOptions.rdmc = RDMC_UNPROTECT; + } else if (thisCmd == "--ckod") { + drvOptions.CKOD = true; + } else if (thisCmd == "--detail") { + detail = true; + } else if (thisCmd == "-a") { + if (nextCmd == "") + errorOut("You must specify a numeric algorithm index when using the -a " + "flag"); + drvOptions.algorithmIndex = std::atoi(nextCmd.c_str()); + i++; // skip the next argument + } else { + errorOut("Unknown command '" + thisCmd + "'"); } } - retval << endl; - return retval.str(); + + if (action == 2) { // generate key + if (keyFile == "") { + errorOut("Specify file to save into with the -k argument."); + } + + std::string const newkey = randomKey(keyLength); + std::ofstream kf { }; + umask(077); // make sure that no one else can read the new key file + kf.open(keyFile.c_str(), std::ios::trunc); + if (!kf.is_open()) { + errorOut("Could not open '" + keyFile + "' for writing."); + } + kf << newkey << keyDesc; + kf.close(); + std::cout << "Random key saved into '" << keyFile << "'" << std::endl; + chmod(keyFile.c_str(), 0600); + std::cout << "Permissions of keyfile set to 600" << std::endl; + exit(EXIT_SUCCESS); + } + // validate the tape device + if (tapeDrive == "") { + errorOut("Tape drive device must be specified with the -f option"); + } + if (drvOptions.cryptMode == CRYPTMODE_RAWREAD && + drvOptions.rdmc == RDMC_PROTECT) { + errorOut( + "'--protect' is not valid when setting encryption mode to 'rawread'"); + } + +#ifndef DISABLE_DEVICE_NAME_CONVERSION + if (tapeDrive.find(".") == std::string::npos) { + if (tapeDrive.substr(0, 7) == "/dev/st") { + tapeDrive = "/dev/nst" + tapeDrive.substr(7, tapeDrive.size() - 6); + } + + if (tapeDrive.substr(0, 8) == "/dev/rmt" && + tapeDrive.substr(tapeDrive.size() - 2, 2) != ".1") { + tapeDrive = "/dev/rmt" + tapeDrive.substr(8, tapeDrive.size() - 7) + ".1"; + } + } +#endif + if (getuid() != 0) { + errorOut("You must be root to read or set encryption options on a drive!"); + } + logFile.open(LOGFILE, std::ios::app); + if (!logFile.is_open()) { + std::cout << "Warning: Could not open '" << LOGFILE + << "' for key change auditing!" << std::endl; + } + chmod(LOGFILE, 0600); + + if (action == 0) { + std::cout << "Status for " << tapeDrive << std::endl; + std::cout << "--------------------------------------------------" + << std::endl; + if (detail) + inquiryDrive(tapeDrive); + showDriveStatus(tapeDrive, detail); + if (detail) + showVolumeStatus(tapeDrive); + exit(EXIT_SUCCESS); + } + + Keyinfo ki { }; + if (drvOptions.cryptMode != CRYPTMODE_OFF) { + if (keyFile == "") { + std::string p1 = "01"; + std::string p2 = "02"; + bool done = false; + while (!done) { + std::cout << "Enter key in hex format: "; + echo(false); + getline(std::cin, p1); + echo(true); + std::cout << std::endl; + std::cout << "Re-enter key in hex format: "; + echo(false); + getline(std::cin, p2); + echo(true); + std::cout << std::endl; + if (p1 != p2) { + std::cout << "Keys do not match!!" << std::endl; + } else { + ki.load(p1); + if (ki.valid) { + std::cout << "Set encryption using this key? [y/n]: "; + std::string ans = ""; + getline(std::cin, ans); + if (ans == "y") { + done = true; + } + } else + std::cout << "Invalid key!" << std::endl; + } + } + drvOptions.keyName = keyDesc; + + } else { + // set keyInput here + std::string keyInput; + std::ifstream myfile(keyFile.c_str()); + if (myfile.is_open()) { + getline(myfile, keyInput); + getline(myfile, keyDesc); + myfile.close(); + ki.load(keyInput); + if (!ki.valid) + errorOut("Invalid key found in '" + keyFile + "'"); + drvOptions.keyName = keyDesc; + } else + errorOut("Could not open '" + keyFile + "' for reading"); + } + drvOptions.cryptoKey.assign(ki.key, ki.keySize); + } + + // Write the options to the tape device + std::cout << "Turning " + << ((drvOptions.cryptMode != CRYPTMODE_OFF) ? "on" : "off") + << " encryption on device '" << tapeDrive << "'..." << std::endl; + bool res = SCSIWriteEncryptOptions(tapeDrive, &drvOptions); + if (res) { + + SSP_DES *opt = SSPGetDES(tapeDrive); + if (drvOptions.cryptMode != CRYPTMODE_OFF && opt->des.encryptionMode != 2) { + errorOut("Turning encryption on for '" + tapeDrive + "' failed!"); + } + if (drvOptions.cryptMode == CRYPTMODE_OFF && opt->des.encryptionMode != 0) { + errorOut("Turning encryption off for '" + tapeDrive + "' failed!"); + } + delete opt; + + if (drvOptions.cryptMode != CRYPTMODE_OFF) { + std::stringstream msg; + msg << "Encryption turned on for device '" << tapeDrive << "'. "; + if (drvOptions.keyName.size() == 0) + msg << "Key Checksum: " << ki.check; + else + msg << "Key Descriptor: '" << drvOptions.keyName << "'"; + msg << " Key Instance: " << std::dec << BSLONG(opt->des.keyInstance) + << std::endl; + + if (logFile.is_open()) { + logFile << timestamp() << ": " << msg.str(); + } + } else { + std::stringstream msg { }; + + msg << "Encryption turned off for device '" << tapeDrive << "'."; + msg << " Key Instance: " << std::dec << BSLONG(opt->des.keyInstance) + << std::endl; + + if (logFile.is_open()) + logFile << timestamp() << ": " << msg.str(); + } + std::cout << "Success! See '" << LOGFILE << "' for a key change audit log." + << std::endl; + exit(EXIT_SUCCESS); + } + if (drvOptions.cryptMode != CRYPTMODE_OFF) { + errorOut("Turning encryption on for '" + tapeDrive + "' failed!"); + } else { + errorOut("Turning encryption off for '" + tapeDrive + "' failed!"); + } +} +// exits to shell with an error message + +void errorOut(std::string const message) { + std::cerr << "Error: " << message << std::endl; + showUsage(); + exit(EXIT_FAILURE); +} + +// shows the command usage +void showUsage() { + std::cout + << "Usage: stenc --version | -g -k [-kd ] | " + "-f [--detail] [-e [-k ] [-kd " + "] [-a ] [--protect | --unprotect] [--ckod] ]" + << std::endl; + std::cout << "Type 'man stenc' for more information." << std::endl; +} +void inquiryDrive(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:"; + std::cout.write((const char *)iresult->vender, 8); + std::cout << std::endl; + std::cout << std::left << std::setw(25) << "Product ID:"; + std::cout.write((const char *)iresult->productID, 16); + std::cout << std::endl; + std::cout << std::left << std::setw(25) << "Product Revision:"; + std::cout.write((const char *)iresult->productRev, 4); + std::cout << std::endl; + + delete iresult; +} + +void showDriveStatus(std::string tapeDrive, bool detail) { + SSP_DES *opt = SSPGetDES(tapeDrive); + if (opt == NULL) + return; + std::string emode = "unknown"; + std::cout << std::left << std::setw(25) << "Drive Encryption:"; + if ((int)opt->des.encryptionMode == 0x2 && // encrypt + (int)opt->des.decryptionMode == 0x2 // read only encrypted data + ) + emode = "on"; + if ((int)opt->des.encryptionMode == 0x2 && // encrypt + (int)opt->des.decryptionMode == 0x3 // read encrypted and unencrypted + ) + emode = "mixed"; + + if ((int)opt->des.encryptionMode == 0x2 && // encrypt + (int)opt->des.decryptionMode == 0x1 // read encrypted and unencrypted + ) + emode = "rawread"; + + if ((int)opt->des.encryptionMode == 0x0 && // encrypt + (int)opt->des.decryptionMode == 0x0 // read encrypted and unencrypted + ) + emode = "off"; + + std::cout << emode << std::endl; + if (detail) { + std::cout << std::left << std::setw(25) << "Drive Output:"; + switch ((int)opt->des.decryptionMode) { + case 0x0: + std::cout << "Not decrypting" << std::endl; + std::cout << std::setw(25) << " " + << "Raw encrypted data not outputted" << std::endl; + break; + case 0x1: + std::cout << "Not decrypting" << std::endl; + std::cout << std::setw(25) << " " + << "Raw encrypted data outputted" << std::endl; + break; + case 0x2: + std::cout << "Decrypting" << std::endl; + std::cout << std::setw(25) << " " + << "Unencrypted data not outputted" << std::endl; + break; + case 0x3: + std::cout << "Decrypting" << std::endl; + std::cout << std::setw(25) << " " + << "Unencrypted data outputted" << std::endl; + break; + default: + std::cout << "Unknown '0x" << std::hex << (int)opt->des.decryptionMode + << "' " << std::endl; + break; + } + std::cout << std::setw(25) << "Drive Input:"; + switch ((int)opt->des.encryptionMode) { + case 0x0: + std::cout << "Not encrypting" << std::endl; + break; + case 0x2: + std::cout << "Encrypting" << std::endl; + break; + default: + std::cout << "Unknown result '0x" << std::hex + << (int)opt->des.encryptionMode << "'" << std::endl; + break; + } + if (opt->des.RDMD == 1) { + std::cout << std::setw(25) << " " + << "Protecting from raw read" << std::endl; + } + + std::cout << std::setw(25) << "Key Instance Counter:" << std::dec + << BSLONG(opt->des.keyInstance) << std::endl; + if (opt->des.algorithmIndex != 0) { + std::cout << std::setw(25) << "Encryption Algorithm:" << std::hex + << (int)opt->des.algorithmIndex << std::endl; + } + } + if (opt->kads.size() > 0) { + for (unsigned int i = 0; i < opt->kads.size(); i++) { + std::stringstream lbl { }; + lbl << "Drive Key Desc.("; + switch (opt->kads[i].type) { + case KAD_TYPE_UKAD: + lbl << "uKAD): "; + std::cout << std::setw(25) << lbl.str(); + std::cout.write((const char *)&opt->kads[i].descriptor, + BSSHORT(opt->kads[i].descriptorLength)); + std::cout << std::endl; + break; + case KAD_TYPE_AKAD: + lbl << "aKAD): "; + std::cout << std::setw(25) << lbl.str(); + std::cout.write((const char *)&opt->kads[i].descriptor, + BSSHORT(opt->kads[i].descriptorLength)); + std::cout << std::endl; + break; + } + } + } + + delete opt; +} + +void showVolumeStatus(std::string tapeDrive) { + SSP_NBES *opt = SSPGetNBES(tapeDrive, true); + if (opt == NULL) + return; + if (opt->nbes.compressionStatus != 0) { + std::cout << std::left << std::setw(25) << "Volume Compressed:"; + switch (opt->nbes.compressionStatus) { + case 0x00: + std::cout << "Drive cannot determine" << std::endl; + break; + default: + std::cout << "Unknown result '" << std::hex + << (int)opt->nbes.compressionStatus << "'" << std::endl; + break; + } + } + std::cout << std::left << std::setw(25) << "Volume Encryption:"; + switch ((int)opt->nbes.encryptionStatus) { + case 0x01: + std::cout << "Unable to determine" << std::endl; + break; + case 0x02: + std::cout << "Logical block is not a logical block" << std::endl; + break; + case 0x03: + std::cout << "Not encrypted" << std::endl; + break; + case 0x05: + std::cout << "Encrypted and able to decrypt" << std::endl; + if (opt->nbes.RDMDS == 1) + std::cout << std::left << std::setw(25) << " " + << "Protected from raw read" << std::endl; + break; + case 0x06: + std::cout << "Encrypted, but unable to decrypt due to invalid key. " + << std::endl; + if (opt->kads.size() > 0) { + for (unsigned int i = 0; i < opt->kads.size(); i++) { + std::stringstream lbl; + lbl << "Volume Key Desc.("; + switch (opt->kads[i].type) { + case KAD_TYPE_UKAD: + lbl << "uKAD): "; + std::cout << std::setw(25) << lbl.str(); + std::cout.write((const char *)&opt->kads[i].descriptor, + BSSHORT(opt->kads[i].descriptorLength)); + std::cout << std::endl; + break; + case KAD_TYPE_AKAD: + lbl << "aKAD): "; + std::cout << std::setw(25) << lbl.str(); + std::cout.write((const char *)&opt->kads[i].descriptor, + BSSHORT(opt->kads[i].descriptorLength)); + std::cout << std::endl; + break; + } + } + } + if (opt->nbes.RDMDS == 1) + std::cout << std::left << std::setw(25) << " " + << "Protected from raw read" << std::endl; + break; + + default: + std::cout << "Unknown result '" << std::hex + << (int)opt->nbes.encryptionStatus << "'" << std::endl; + break; + } + if (opt->nbes.algorithmIndex != 0) { + std::cout << std::left << std::setw(25) + << "Volume Algorithm:" << (int)opt->nbes.algorithmIndex + << std::endl; + } + + delete opt; +} + +void echo(bool on = true) { + struct termios settings { }; + tcgetattr(STDIN_FILENO, &settings); + settings.c_lflag = + on ? (settings.c_lflag | ECHO) : (settings.c_lflag & ~(ECHO)); + tcsetattr(STDIN_FILENO, TCSANOW, &settings); +} +std::string timestamp() { + time_t tm { }; + time(&tm); + char buffer[80]; + int len = strftime((char *)&buffer, 80, "%Y-%m-%d", localtime(&tm)); + std::string val; + val.assign(buffer, len); + return(val); +} + +std::string randomKey(int length) { + unsigned char rnd; + std::stringstream retval { }; + std::ifstream random { }; + + // Under Linux and AIX /dev/random provides much more cryptographically secure + // random output than rand() + random.open("/dev/random", std::ios::in | std::ios::binary); + if (random.is_open()) { + for (int i = 0; i < length; i++) { + random.read(reinterpret_cast(&rnd), 1); + retval << std::hex << rnd; + } + random.close(); + } else { + std::cout << "Enter random keys on the keyboard to seed the " + "generator.\nEnd by pressing enter..." + << std::endl; + double check = 0; + char c = 0; + echo(false); + while (c != 10) { + check += (int)c; + c = getchar(); + } + echo(true); + srand(time(NULL) + (int)check); + for (int i = 0; i < length; i++) { + retval << std::hex << (std::rand() % 256); + } + } + retval << std::endl; + return(retval.str()); } diff --git a/src/scsiencrypt.cpp b/src/scsiencrypt.cpp index d4d036d..c57ad47 100644 --- a/src/scsiencrypt.cpp +++ b/src/scsiencrypt.cpp @@ -63,7 +63,7 @@ GNU General Public License for more details. #define BSINTTOCHAR(x) (unsigned char)((x & 0xff000000)>>24), (unsigned char)((x & 0x00ff0000)>>16),(unsigned char)((x & 0x0000ff00)>>8),(unsigned char)(x & 0x000000ff) -using namespace std; +//using namespace std; void byteswap(unsigned char* array,int size,int value); @@ -71,7 +71,7 @@ bool moveTape(std::string tapeDevice,int count,bool dirForward); void outputSense(SCSI_PAGE_SENSE* sd); void readIOError(int err); -bool SCSIExecute(string tapedevice, unsigned char* cmd_p,int cmd_len,unsigned char* dxfer_p,int dxfer_len, bool cmd_to_device, bool show_error); +bool SCSIExecute(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]; @@ -144,7 +144,7 @@ unsigned char }; //Gets encryption options on the tape drive -SSP_DES* SSPGetDES(string tapeDevice){ +SSP_DES* SSPGetDES(std::string tapeDevice){ SSP_PAGE_BUFFER buffer; memset(&buffer,0,sizeof(SSP_PAGE_BUFFER)); if(!SCSIExecute(tapeDevice, @@ -162,7 +162,7 @@ SSP_DES* SSPGetDES(string tapeDevice){ } //Gets encryption options on the tape drive -SSP_NBES* SSPGetNBES(string tapeDevice,bool retry){ +SSP_NBES* SSPGetNBES(std::string tapeDevice,bool retry){ SSP_PAGE_BUFFER buffer; memset(&buffer,0,sizeof(SSP_PAGE_BUFFER)); @@ -198,7 +198,7 @@ SSP_NBES* SSPGetNBES(string tapeDevice,bool retry){ } //Sends and inquiry to the device -SCSI_PAGE_INQ* SCSIGetInquiry(string tapeDevice){ +SCSI_PAGE_INQ* SCSIGetInquiry(std::string tapeDevice){ SCSI_PAGE_INQ* status=new SCSI_PAGE_INQ; memset(status,0,sizeof(SCSI_PAGE_INQ)); if(!SCSIExecute(tapeDevice, @@ -216,7 +216,7 @@ SCSI_PAGE_INQ* SCSIGetInquiry(string tapeDevice){ //Writes encryption options to the tape drive -bool SCSIWriteEncryptOptions(string tapeDevice, SCSIEncryptOptions* eOptions){ +bool SCSIWriteEncryptOptions(std::string tapeDevice, SCSIEncryptOptions* eOptions){ char buffer[1024]; memset(&buffer,0,1024); @@ -302,7 +302,7 @@ bool SCSIWriteEncryptOptions(string tapeDevice, SCSIEncryptOptions* eOptions){ ); } -bool SCSIExecute(string tapedrive, unsigned char* cmd_p,int cmd_len,unsigned char* dxfer_p,int dxfer_len, bool cmd_to_device, bool show_error) +bool SCSIExecute(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(); int sg_fd,eresult,sresult,ioerr,retries; @@ -313,7 +313,7 @@ bool SCSIExecute(string tapedrive, unsigned char* cmd_p,int cmd_len,unsigned cha errno=0; sg_fd = open(tapedevice, O_RDONLY); if( sg_fd==-1){ - cerr<<"Could not open device '"<senseKey){ case 0: - cerr<<"No specific error"; + std::cerr<<"No specific error"; break; case 2: - cerr<<"Device not ready"; + std::cerr<<"Device not ready"; break; case 3: - cerr<<"Medium Error"; + std::cerr<<"Medium Error"; break; case 4: - cerr<<"Hardware Error"; + std::cerr<<"Hardware Error"; break; case 5: - cerr<<"Illegal Request"; + std::cerr<<"Illegal Request"; break; case 6: - cerr<<"Unit Attention"; + std::cerr<<"Unit Attention"; break; case 7: - cerr<<"Data protect"; + std::cerr<<"Data protect"; break; case 8: - cerr<<"Blank tape"; + std::cerr<<"Blank tape"; break; } - cerr<<" (0x"<senseKey)<<")"<addSenseCode)<addSenseCodeQual)<senseKey); + std::cerr<<")\n"; + + std::cerr<addSenseCode); + std::cerr<<"\n"; + + std::cerr<addSenseCodeQual); + std::cerr<<"\n"; + if(sd->addSenseLen>0){ - cerr<addSenseLen;i++){ - cerr<addSenseData[i]); + std::cerr<< std::hex << (sd->addSenseData[i]); } - cerr<