diff --git a/src/keyinfo.cpp b/src/keyinfo.cpp index 2eb9e14..5be2fab 100644 --- a/src/keyinfo.cpp +++ b/src/keyinfo.cpp @@ -1,123 +1,122 @@ -#include -#include -#include -#include -#include #include "keyinfo.h" #include "scsiencrypt.h" -//using namespace std; +#include +#include +#include +#include +#include -Keyinfo::Keyinfo(){ - valid=false; - check=""; - key=NULL; - keySize=0; +Keyinfo::Keyinfo() { + valid = false; + check = ""; + key = NULL; + keySize = 0; } -void Keyinfo::load(std::string hexinput){ - valid=true; - if(hexinput.size()<2){ - valid=false; - std::cout<<"Key input too short!\n"; - return; - - } - //parse for invalid characters - for(unsigned int i=0;iSSP_KEY_LENGTH){ - std::cout<<"Key size cannot exceed "<<(SSP_KEY_LENGTH*8)<<" bits!\n"; - std::cout<<"Provided key is "<<(keySize*8)<<" bits in length.\n"; - valid=false; - return; - } - std::cout<<"Provided key length is "<<(keySize*8)<<" bits.\n"; - std::cout<<"Key checksum is "< SSP_KEY_LENGTH) { + std::cout << "Key size cannot exceed " << (SSP_KEY_LENGTH * 8) + << " bits!\n"; + std::cout << "Provided key is " << (keySize * 8) << " bits in length.\n"; + valid = false; + return; + } + std::cout << "Provided key length is " << (keySize * 8) << " bits.\n"; + std::cout << "Key checksum is " << check << ".\n"; } -void Keyinfo::loadCheck() { - int i; - int chk = 0; - for (i = 0; i> ch1 >> ch2; - int dig1=0, dig2=0; - if(isdigit(ch1)) dig1 = ch1 - '0'; - else if(ch1>='A' && ch1<='F') dig1 = ch1 - 'A' + 10; - else if(ch1>='a' && ch1<='f') dig1 = ch1 - 'a' + 10; - if(isdigit(ch2)) dig2 = ch2 - '0'; - else if(ch2>='A' && ch2<='F') dig2 = ch2 - 'A' + 10; - else if(ch2>='a' && ch2<='f') dig2 = ch2 - 'a' + 10; - key[i] = dig1*16 + dig2; - } + std::stringstream sstr(str); + for (int i = 0; i < keySize; i++) { + char ch1, ch2; + sstr >> ch1 >> ch2; + int dig1 = 0, dig2 = 0; + if (isdigit(ch1)) + dig1 = ch1 - '0'; + else if (ch1 >= 'A' && ch1 <= 'F') + dig1 = ch1 - 'A' + 10; + else if (ch1 >= 'a' && ch1 <= 'f') + dig1 = ch1 - 'a' + 10; + if (isdigit(ch2)) + dig2 = ch2 - '0'; + else if (ch2 >= 'A' && ch2 <= 'F') + dig2 = ch2 - 'A' + 10; + else if (ch2 >= 'a' && ch2 <= 'f') + dig2 = ch2 - 'a' + 10; + key[i] = dig1 * 16 + dig2; + } } diff --git a/src/keyinfo.h b/src/keyinfo.h index f773e8c..2099380 100644 --- a/src/keyinfo.h +++ b/src/keyinfo.h @@ -2,19 +2,19 @@ #define KEYINFO_H #include -class Keyinfo{ - public: - char* key; - int keySize; - bool valid; - std::string check; - void load(std::string hexinput); - Keyinfo(); - ~Keyinfo(); - private: - void loadKey(std::string str); - void loadCheck(); - +class Keyinfo { +public: + char *key; + int keySize; + bool valid; + std::string check; + void load(std::string hexinput); + Keyinfo(); + ~Keyinfo(); + +private: + void loadKey(std::string str); + void loadCheck(); }; #endif diff --git a/src/main.cpp b/src/main.cpp index d843287..0250e71 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,6 +13,9 @@ 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 "keyinfo.h" +#include "scsiencrypt.h" + #include #include #ifdef HAVE_UNISTD_H @@ -31,8 +34,6 @@ GNU General Public License for more details. #ifdef HAVE_STRING_H #include #endif -#include "keyinfo.h" -#include "scsiencrypt.h" #include diff --git a/src/scsiencrypt.cpp b/src/scsiencrypt.cpp index c57ad47..574a95f 100644 --- a/src/scsiencrypt.cpp +++ b/src/scsiencrypt.cpp @@ -12,620 +12,593 @@ 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 #include -#include +#include +#include +#include #include #include -#include -#include -#include -#include +#include #include #ifdef HAVE_UNISTD_H - #include +#include #endif #ifdef HAVE_STDLIB_H - #include +#include #endif #ifdef HAVE_STRING_H - #include +#include #endif #if defined(OS_LINUX) - #include - #include - #define SCSI_TIMEOUT 5000 +#include +#include +#define SCSI_TIMEOUT 5000 #elif defined(OS_FREEBSD) - #include - #define SCSI_TIMEOUT 5000 +#include +#define SCSI_TIMEOUT 5000 #elif defined(OS_AIX) - #define _LINUX_SOURCE_COMPAT - #include - #include - #include - #include - #define SCSI_TIMEOUT 5 +#define _LINUX_SOURCE_COMPAT +#include +#include +#include +#include +#define SCSI_TIMEOUT 5 #else - #error "OS type is not set" +#error "OS type is not set" #endif -#include #include "scsiencrypt.h" +#include -#define SSP_SPIN_OPCODE 0XA2 -#define SSP_SPOUT_OPCODE 0XB5 -#define SSP_SP_CMD_LEN 12 -#define SSP_SP_PROTOCOL_TDE 0X20 +#define SSP_SPIN_OPCODE 0XA2 +#define SSP_SPOUT_OPCODE 0XB5 +#define SSP_SP_CMD_LEN 12 +#define SSP_SP_PROTOCOL_TDE 0X20 #define 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) \ + (unsigned char)((x & 0xff000000) >> 24), \ + (unsigned char)((x & 0x00ff0000) >> 16), \ + (unsigned char)((x & 0x0000ff00) >> 8), (unsigned char)(x & 0x000000ff) - -//using namespace std; - - -void byteswap(unsigned char* array,int size,int value); -bool moveTape(std::string tapeDevice,int count,bool dirForward); -void outputSense(SCSI_PAGE_SENSE* sd); +void byteswap(unsigned char *array, int size, int value); +bool moveTape(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,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]; + unsigned char length[2]; -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; + 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; + 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; + 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]; + 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_PAGE_BUFFER buffer; - memset(&buffer,0,sizeof(SSP_PAGE_BUFFER)); - if(!SCSIExecute(tapeDevice, - (unsigned char*)&spin_des_command, - sizeof(spin_des_command), - (unsigned char*)&buffer, - sizeof(SSP_PAGE_BUFFER), - false,true)) - { - return NULL; - } - SSP_DES* status=new SSP_DES(&buffer); - return status; +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_PAGE_BUFFER buffer; + memset(&buffer, 0, sizeof(SSP_PAGE_BUFFER)); + if (!SCSIExecute(tapeDevice, (unsigned char *)&spin_des_command, + sizeof(spin_des_command), (unsigned char *)&buffer, + sizeof(SSP_PAGE_BUFFER), false, true)) { + return NULL; + } + SSP_DES *status = new SSP_DES(&buffer); + return status; } -//Gets encryption options on the tape drive -SSP_NBES* SSPGetNBES(std::string tapeDevice,bool retry){ - - SSP_PAGE_BUFFER buffer; - memset(&buffer,0,sizeof(SSP_PAGE_BUFFER)); - if(!SCSIExecute(tapeDevice, - (unsigned char*)&spin_nbes_command, - sizeof(spin_nbes_command), - (unsigned char*)&buffer, - sizeof(SSP_PAGE_BUFFER), - false,false)) - { - return NULL; - } - SSP_NBES* status=new SSP_NBES(&buffer); - if(status->nbes.encryptionStatus==0x01 && retry){ - //move to the start of the tape and try again - int moves=0; - while(true){ - if(status==NULL)break; - if(status->nbes.encryptionStatus!=0x01)break; - if(moves>=MAX_TAPE_READ_BLOCKS)break; - delete status; - status=NULL; //double free bug fix provided by Adam Nielsen - if(!moveTape(tapeDevice,1,true))break; - moves++; - status=SSPGetNBES(tapeDevice,false); - } - moveTape(tapeDevice,moves,false); - } - return status; - - +// Gets encryption options on the tape drive +SSP_NBES *SSPGetNBES(std::string tapeDevice, bool retry) { + SSP_PAGE_BUFFER buffer; + memset(&buffer, 0, sizeof(SSP_PAGE_BUFFER)); + if (!SCSIExecute(tapeDevice, (unsigned char *)&spin_nbes_command, + sizeof(spin_nbes_command), (unsigned char *)&buffer, + sizeof(SSP_PAGE_BUFFER), false, false)) { + return NULL; + } + SSP_NBES *status = new SSP_NBES(&buffer); + if (status->nbes.encryptionStatus == 0x01 && retry) { + // move to the start of the tape and try again + int moves = 0; + while (true) { + if (status == NULL) + break; + if (status->nbes.encryptionStatus != 0x01) + break; + if (moves >= MAX_TAPE_READ_BLOCKS) + break; + delete status; + status = NULL; // double free bug fix provided by Adam Nielsen + if (!moveTape(tapeDevice, 1, true)) + break; + moves++; + status = SSPGetNBES(tapeDevice, false); + } + moveTape(tapeDevice, moves, false); + } + return status; } -//Sends and inquiry to the device -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, - (unsigned char*)&scsi_inq_command, - sizeof(scsi_inq_command), - (unsigned char*)status, - sizeof(SCSI_PAGE_INQ), - false,true)) - { - exit(EXIT_FAILURE); - } - return status; - +// Sends and inquiry to the device +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, (unsigned char *)&scsi_inq_command, + sizeof(scsi_inq_command), (unsigned char *)status, + sizeof(SCSI_PAGE_INQ), false, true)) { + exit(EXIT_FAILURE); + } + return status; } +// Writes encryption options to the tape drive +bool SCSIWriteEncryptOptions(std::string tapeDevice, + SCSIEncryptOptions *eOptions) { -//Writes encryption options to the tape drive -bool SCSIWriteEncryptOptions(std::string tapeDevice, SCSIEncryptOptions* eOptions){ - - char buffer[1024]; - memset(&buffer,0,1024); + char buffer[1024]; + memset(&buffer, 0, 1024); - SSP_PAGE_SDE options; - //copy the template over the options - memset(&options,0, sizeof(SSP_PAGE_SDE)); - byteswap((unsigned char*)&options.pageCode,2,0x10); - int pagelen=sizeof(SSP_PAGE_SDE); - options.scope=2; //all IT nexus = 10b - options.RDMC=eOptions->rdmc; - options.ckod=(eOptions->CKOD)?1:0; - options.CEEM=DEFAULT_CEEM; - options.algorithmIndex=eOptions->algorithmIndex; - //set the specific options - switch(eOptions->cryptMode){ - case CRYPTMODE_ON: //encrypt, read only encrypted data - options.encryptionMode=2; - options.decryptionMode=2; - break; - case CRYPTMODE_MIXED: //encrypt, read all data - options.encryptionMode=2; - options.decryptionMode=3; - break; - case CRYPTMODE_RAWREAD: - options.encryptionMode=2; - options.decryptionMode=1; - break; - default: - byteswap((unsigned char*)options.keyLength,2,DEFAULT_KEYSIZE); - eOptions->cryptoKey=""; //blank the key - eOptions->keyName=""; //blank the key name, not supported when turned off - break; - } - - if(eOptions->cryptoKey!=""){ - //byte swap the keylength - byteswap((unsigned char*)&options.keyLength,2,eOptions->cryptoKey.size()); - //copy the crypto key into the options - eOptions->cryptoKey.copy((char*)&options.keyData, eOptions->cryptoKey.size(),0); - } - //create the key descriptor - if(eOptions->keyName!=""){ - SSP_KAD kad; - memset(&kad,0,sizeof(kad)); - //set the descriptor length to the length of the keyName - byteswap((unsigned char*)&kad.descriptorLength,2,eOptions->keyName.size()); - - //get the size of the kad object - int kadlen=eOptions->keyName.size()+SSP_KAD_HEAD_LENGTH; - //increment the SPOUT page len - pagelen+=kadlen; - //increase the page size - eOptions->keyName.copy((char*)&kad.descriptor,eOptions->keyName.size(),0); - //copy the kad after the SDE command - memcpy(&buffer[sizeof(SSP_PAGE_SDE)],&kad,kadlen); - } - //update the pagelen in options - byteswap((unsigned char*)&options.length,2,pagelen-4); //set the page length, minus the length and pageCode + SSP_PAGE_SDE options; + // copy the template over the options + memset(&options, 0, sizeof(SSP_PAGE_SDE)); + byteswap((unsigned char *)&options.pageCode, 2, 0x10); + int pagelen = sizeof(SSP_PAGE_SDE); + options.scope = 2; // all IT nexus = 10b + options.RDMC = eOptions->rdmc; + options.ckod = (eOptions->CKOD) ? 1 : 0; + options.CEEM = DEFAULT_CEEM; + options.algorithmIndex = eOptions->algorithmIndex; + // set the specific options + switch (eOptions->cryptMode) { + case CRYPTMODE_ON: // encrypt, read only encrypted data + options.encryptionMode = 2; + options.decryptionMode = 2; + break; + case CRYPTMODE_MIXED: // encrypt, read all data + options.encryptionMode = 2; + options.decryptionMode = 3; + break; + case CRYPTMODE_RAWREAD: + options.encryptionMode = 2; + options.decryptionMode = 1; + break; + default: + byteswap((unsigned char *)options.keyLength, 2, DEFAULT_KEYSIZE); + eOptions->cryptoKey = ""; // blank the key + eOptions->keyName = ""; // blank the key name, not supported when turned off + break; + } - //copy the options to the beginning of the buffer - memcpy(&buffer,&options,sizeof(SSP_PAGE_SDE)); - - unsigned char spout_sde_command [SSP_SP_CMD_LEN] = { - SSP_SPOUT_OPCODE, - SSP_SP_PROTOCOL_TDE, - 0, - 0X10, - 0,0, - BSINTTOCHAR(pagelen), - 0,0 - }; - + if (eOptions->cryptoKey != "") { + // byte swap the keylength + byteswap((unsigned char *)&options.keyLength, 2, + eOptions->cryptoKey.size()); + // copy the crypto key into the options + eOptions->cryptoKey.copy((char *)&options.keyData, + eOptions->cryptoKey.size(), 0); + } + // create the key descriptor + if (eOptions->keyName != "") { + SSP_KAD kad; + memset(&kad, 0, sizeof(kad)); + // set the descriptor length to the length of the keyName + byteswap((unsigned char *)&kad.descriptorLength, 2, + eOptions->keyName.size()); - //return whether or not the command executed - return SCSIExecute( - tapeDevice, - (unsigned char*)&spout_sde_command, - sizeof(spout_sde_command), - (unsigned char*)&buffer, - pagelen, - true,true - ); + // get the size of the kad object + int kadlen = eOptions->keyName.size() + SSP_KAD_HEAD_LENGTH; + // increment the SPOUT page len + pagelen += kadlen; + // increase the page size + eOptions->keyName.copy((char *)&kad.descriptor, eOptions->keyName.size(), + 0); + // copy the kad after the SDE command + memcpy(&buffer[sizeof(SSP_PAGE_SDE)], &kad, kadlen); + } + // update the pagelen in options + byteswap((unsigned char *)&options.length, 2, + pagelen - 4); // set the page length, minus the length and pageCode + + // copy the options to the beginning of the buffer + memcpy(&buffer, &options, sizeof(SSP_PAGE_SDE)); + + unsigned char spout_sde_command[SSP_SP_CMD_LEN] = {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, + sizeof(spout_sde_command), (unsigned char *)&buffer, + pagelen, true, true); } -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; - SCSI_PAGE_SENSE* sd=new SCSI_PAGE_SENSE; - memset(sd,0,sizeof(SCSI_PAGE_SENSE)); +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; + SCSI_PAGE_SENSE *sd = new SCSI_PAGE_SENSE; + memset(sd, 0, sizeof(SCSI_PAGE_SENSE)); -#if defined(OS_LINUX) || defined(OS_FREEBSD) // Linux or FreeBSD System - errno=0; - sg_fd = open(tapedevice, O_RDONLY); - if( sg_fd==-1){ - std::cerr<<"Could not open device '"<>8); - array[1]=(unsigned char)(value & 0x00ff); - break; - case 4: - array[0]=(unsigned char)((value & 0xff000000)>>24); - array[1]=(unsigned char)((value & 0x00ff0000)>>16); - array[2]=(unsigned char)((value & 0x0000ff00)>>8); - array[3]=(unsigned char)(value & 0x000000ff); +void byteswap(unsigned char *array, int size, int value) { + switch (size) { + case 2: + array[0] = (unsigned char)((value & 0xff00) >> 8); + array[1] = (unsigned char)(value & 0x00ff); + break; + case 4: + array[0] = (unsigned char)((value & 0xff000000) >> 24); + array[1] = (unsigned char)((value & 0x00ff0000) >> 16); + array[2] = (unsigned char)((value & 0x0000ff00) >> 8); + array[3] = (unsigned char)(value & 0x000000ff); - break; - default: - std::cout<<"Unhandled byte swap length of "<length)+4; - int pos=start; - while(pos=length)break; - unsigned short kadDesLen=BSSHORT(kad.descriptorLength); - if(kadDesLen>0){ - memcpy(&kad.descriptor,rawbuff+pos,kadDesLen); - pos+=kadDesLen; - }else pos++; - kads.push_back(kad); - } - - - +void KAD_CLASS::loadKADs(SSP_PAGE_BUFFER *buffer, int start) { + char *rawbuff = (char *)buffer; + int length = BSSHORT(buffer->length) + 4; + int pos = start; + while (pos < length) { + SSP_KAD kad; + memset(&kad, 0, sizeof(SSP_KAD)); + memcpy(&kad, rawbuff + pos, SSP_KAD_HEAD_LENGTH); + pos += SSP_KAD_HEAD_LENGTH; + if (pos >= length) + break; + unsigned short kadDesLen = BSSHORT(kad.descriptorLength); + if (kadDesLen > 0) { + memcpy(&kad.descriptor, rawbuff + pos, kadDesLen); + pos += kadDesLen; + } else + pos++; + kads.push_back(kad); + } } -bool moveTape(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){ - return false; - } - errno=0; - bool retval=true; -#if defined(OS_LINUX) || defined(OS_FREEBSD) // Linux or FreeBSD System - - mt_command.mt_op = (dirForward)?MTFSR:MTBSR; - mt_command.mt_count = count; - ioctl(sg_fd, MTIOCTOP, &mt_command); +bool moveTape(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) { + return false; + } + errno = 0; + bool retval = true; +#if defined(OS_LINUX) || defined(OS_FREEBSD) // Linux or FreeBSD System + + mt_command.mt_op = (dirForward) ? MTFSR : MTBSR; + mt_command.mt_count = count; + ioctl(sg_fd, MTIOCTOP, &mt_command); #elif defined(OS_AIX) - mt_command.st_op = (dirForward)?MTFSR:MTBSR; - mt_command.st_count = count; - ioctl(sg_fd, STIOCTOP, &mt_command); + mt_command.st_op = (dirForward) ? MTFSR : MTBSR; + mt_command.st_count = count; + ioctl(sg_fd, STIOCTOP, &mt_command); #else - #error "OS type is not set" +#error "OS type is not set" #endif - if(errno!=0)retval=false; - - close(sg_fd); - errno=0; - return retval; + if (errno != 0) + retval = false; + + close(sg_fd); + errno = 0; + return retval; } -void readIOError(int err){ - if(err==0)return; - std::cerr<<"ERROR: "; - switch(err){ - case EAGAIN: - std::cerr<<"Device already open"<senseKey){ - case 0: - std::cerr<<"No specific error"; - break; - case 2: - std::cerr<<"Device not ready"; - break; - case 3: - std::cerr<<"Medium Error"; - break; - case 4: - std::cerr<<"Hardware Error"; - break; - case 5: - std::cerr<<"Illegal Request"; - break; - case 6: - std::cerr<<"Unit Attention"; - break; - case 7: - std::cerr<<"Data protect"; - break; - case 8: - std::cerr<<"Blank tape"; - break; - - } + switch ((int)sd->senseKey) { + case 0: + std::cerr << "No specific error"; + break; + case 2: + std::cerr << "Device not ready"; + break; + case 3: + std::cerr << "Medium Error"; + break; + case 4: + std::cerr << "Hardware Error"; + break; + case 5: + std::cerr << "Illegal Request"; + break; + case 6: + std::cerr << "Unit Attention"; + break; + case 7: + std::cerr << "Data protect"; + break; + case 8: + std::cerr << "Blank tape"; + break; + } - std::cerr<<" (0x"<senseKey); - std::cerr<<")\n"; + std::cerr << " (0x" << std::hex << (sd->senseKey); + std::cerr << ")\n"; - std::cerr<addSenseCode); - std::cerr<<"\n"; + std::cerr << std::left << std::setw(25) << " ASC:" + << "0x" << std::hex << (sd->addSenseCode); + std::cerr << "\n"; - std::cerr<addSenseCodeQual); - std::cerr<<"\n"; + std::cerr << std::left << std::setw(25) << " ASCQ:" + << "0x" << std::hex << (sd->addSenseCodeQual); + std::cerr << "\n"; - if(sd->addSenseLen>0){ - std::cerr<addSenseLen;i++){ - std::cerr<< std::hex << (sd->addSenseData[i]); - } - std::cerr<<"\n"; - } + if (sd->addSenseLen > 0) { + std::cerr << std::left << std::setw(25) << " Additional data:" + << "0x"; + + for (int i = 0; i < sd->addSenseLen; i++) { + std::cerr << std::hex << (sd->addSenseData[i]); + } + std::cerr << "\n"; + } #ifdef DEBUGSCSI - std::cerr< #include +#include #include -#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 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 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 +#define RDMC_PROTECT 0x03 +#define RDMC_UNPROTECT 0x02 +#define RDMC_DEFAULT 0x00 -//outputs hex in a 2 digit pair -#define HEX( x ) right< +#include #endif -#ifdef HAVE_SYS_TYPES_H - #include +#ifdef HAVE_SYS_TYPES_H +#include #endif #ifdef BYTE_ORDER - #define STENC_BYTE_ORDER BYTE_ORDER +#define STENC_BYTE_ORDER BYTE_ORDER #endif #ifndef STENC_BYTE_ORDER - #ifdef __BYTE_ORDER - #define STENC_BYTE_ORDER __BYTE_ORDER - #endif +#ifdef __BYTE_ORDER +#define STENC_BYTE_ORDER __BYTE_ORDER +#endif #endif #ifdef BIG_ENDIAN - #define STENC_TYPE_BIG_ENDIAN BIG_ENDIAN +#define STENC_TYPE_BIG_ENDIAN BIG_ENDIAN #endif #ifndef STENC_TYPE_BIG_ENDIAN - #ifdef __BIG_ENDIAN - #define STENC_TYPE_BIG_ENDIAN __BIG_ENDIAN - #endif +#ifdef __BIG_ENDIAN +#define STENC_TYPE_BIG_ENDIAN __BIG_ENDIAN +#endif #endif #if STENC_BYTE_ORDER == STENC_TYPE_BIG_ENDIAN - #define STENC_BIG_ENDIAN 1 +#define STENC_BIG_ENDIAN 1 #else - #define STENC_BIG_ENDIAN 0 +#define STENC_BIG_ENDIAN 0 #endif - - - - typedef struct { - unsigned char pageCode [2]; - unsigned char length [2]; + unsigned char pageCode[2]; + unsigned char length[2]; #if STENC_BIG_ENDIAN == 1 - unsigned char nexusScope :3; - unsigned char res_bits_1 :2; - unsigned char keyScope :3; + unsigned char nexusScope : 3; + unsigned char res_bits_1 : 2; + unsigned char keyScope : 3; #else - unsigned char keyScope :3; - unsigned char res_bits_1 :2; - unsigned char nexusScope :3; + unsigned char keyScope : 3; + unsigned char res_bits_1 : 2; + unsigned char nexusScope : 3; #endif - unsigned char encryptionMode; - unsigned char decryptionMode; - unsigned char algorithmIndex; - unsigned char keyInstance [4]; + unsigned char encryptionMode; + unsigned char decryptionMode; + unsigned char algorithmIndex; + unsigned char keyInstance[4]; #if STENC_BIG_ENDIAN == 1 - unsigned char res_bits_2 :1; - unsigned char parametersControl :3; - unsigned char VCELB :1; - unsigned char CEEMS :2; - unsigned char RDMD :1; + unsigned char res_bits_2 : 1; + unsigned char parametersControl : 3; + unsigned char VCELB : 1; + unsigned char CEEMS : 2; + unsigned char RDMD : 1; #else - - unsigned char RDMD :1; - unsigned char CEEMS :2; - unsigned char VCELB :1; - unsigned char parametersControl :3; - unsigned char res_bits_2 :1; -#endif - unsigned char res_bits_3; - unsigned char ASDKCount [2]; - unsigned char res_bits_4 [8]; -} SSP_PAGE_DES; //device encryption status page + unsigned char RDMD : 1; + unsigned char CEEMS : 2; + unsigned char VCELB : 1; + unsigned char parametersControl : 3; + unsigned char res_bits_2 : 1; +#endif + unsigned char res_bits_3; + unsigned char ASDKCount[2]; + unsigned char res_bits_4[8]; + +} SSP_PAGE_DES; // device encryption status page typedef struct { - unsigned char type; + unsigned char type; #if STENC_BIG_ENDIAN == 1 - unsigned char res_bits_1 :5; - unsigned char authenticated :3; + unsigned char res_bits_1 : 5; + unsigned char authenticated : 3; #else - unsigned char authenticated :3; - unsigned char res_bits_1 :5; + unsigned char authenticated : 3; + unsigned char res_bits_1 : 5; #endif - unsigned char descriptorLength [2]; - unsigned char descriptor [SSP_DESCRIPTOR_LENGTH]; //will actually be the size of descriptorLength + unsigned char descriptorLength[2]; + unsigned char descriptor[SSP_DESCRIPTOR_LENGTH]; // will actually be the size + // of descriptorLength } SSP_KAD; -typedef struct{ - unsigned char pageCode [2]; - unsigned char length [2]; - unsigned char buffer [SSP_PAGE_ALLOCATION]; -} SSP_PAGE_BUFFER; //generic ssp page buffer - +typedef struct { + unsigned char pageCode[2]; + unsigned char length[2]; + unsigned char buffer[SSP_PAGE_ALLOCATION]; +} SSP_PAGE_BUFFER; // generic ssp page buffer typedef struct { - unsigned char pageCode [2]; - unsigned char length [2]; - unsigned char log_obj_num [8]; -#if STENC_BIG_ENDIAN == 1 - unsigned char compressionStatus :4; - unsigned char encryptionStatus :4; -#else - unsigned char encryptionStatus :4; - unsigned char compressionStatus :4; -#endif - - unsigned char algorithmIndex; -#if STENC_BIG_ENDIAN == 1 - unsigned char res_bits_1 :6; - unsigned char EMES :1; - unsigned char RDMDS :1; -#else - unsigned char RDMDS :1; - unsigned char EMES :1; - unsigned char res_bits_1 :6; -#endif - - unsigned char res_bits_2; -} SSP_PAGE_NBES; //next block encryption status page - - -typedef struct{ - -#if STENC_BIG_ENDIAN == 0 - unsigned char peripheralQualifier :3; - unsigned char periphrealDeviceType :5; -#else - unsigned char periphrealDeviceType :5; - unsigned char peripheralQualifier :3; -#endif - -#if STENC_BIG_ENDIAN == 0 - unsigned char RMB :1; - unsigned char res_bits_1 :7; -#else - unsigned char res_bits_1 :7; - unsigned char RMB :1; -#endif - unsigned char Version [1]; - -#if STENC_BIG_ENDIAN == 0 - unsigned char obs_bits_1 :2; - unsigned char NORMACA :1; - unsigned char HISUP :1; - unsigned char responseDataFormat :4; -#else - unsigned char responseDataFormat :4; - unsigned char HISUP :1; - unsigned char NORMACA :1; - unsigned char obs_bits_1 :2; -#endif - - unsigned char additionalLength [1]; - -#if STENC_BIG_ENDIAN == 0 - unsigned char SCCS :1; - unsigned char ACC :1; - unsigned char TPGS :2; - unsigned char threePC :1; - unsigned char res_bits_2 :2; - unsigned char protect :1; -#else - unsigned char protect :1; - unsigned char res_bits_2 :2; - unsigned char threePC :1; - unsigned char TPGS :2; - unsigned char ACC :1; - unsigned char SCCS :1; -#endif - - -#if STENC_BIG_ENDIAN == 0 - unsigned char obs_bits_2 :1; - unsigned char ENCSERV :1; - unsigned char VS :1; - unsigned char MULTIP :1; - unsigned char MCHNGR :1; - unsigned char obs_bits_3 :2; - unsigned char ADDR16 :1; -#else - unsigned char ADDR16 :1; - unsigned char obs_bits_3 :2; - unsigned char MCHNGR :1; - unsigned char MULTIP :1; - unsigned char VS :1; - unsigned char ENCSERV :1; - unsigned char obs_bits_2 :1; -#endif - - -#if STENC_BIG_ENDIAN == 0 - unsigned char obs_bits_4 :2; - unsigned char WBUS16 :1; - unsigned char SYNC :1; - unsigned char obs_bits_5 :2; - unsigned char CMDQUE :1; - unsigned char VS2 :1; -#else - unsigned char VS2 :1; - unsigned char CMDQUE :1; - unsigned char obs_bits_5 :2; - unsigned char SYNC :1; - unsigned char WBUS16 :1; - unsigned char obs_bits_4 :2; -#endif - - unsigned char vender [8]; - unsigned char productID [16]; - unsigned char productRev [4]; - unsigned char SN [7]; - unsigned char venderUnique [12]; - -#if STENC_BIG_ENDIAN == 0 - unsigned char res_bits_3 :4; - unsigned char CLOCKING :2; - unsigned char QAS :1; - unsigned char IUS :1; -#else - unsigned char IUS :1; - unsigned char QAS :1; - unsigned char CLOCKING :2; - unsigned char res_bits_3 :4; -#endif - - unsigned char res_bits_4 [1]; - unsigned char versionDescriptor [16]; - unsigned char res_bits_5 [22]; - unsigned char copyright [1]; -} SCSI_PAGE_INQ; //device inquiry response -typedef struct{ + unsigned char pageCode[2]; + unsigned char length[2]; + unsigned char log_obj_num[8]; #if STENC_BIG_ENDIAN == 1 - unsigned char valid :1; - unsigned char responseCode :7; + unsigned char compressionStatus : 4; + unsigned char encryptionStatus : 4; #else - unsigned char responseCode :7; - unsigned char valid :1; -#endif - unsigned char res_bits_1; + unsigned char encryptionStatus : 4; + unsigned char compressionStatus : 4; +#endif + + unsigned char algorithmIndex; +#if STENC_BIG_ENDIAN == 1 + unsigned char res_bits_1 : 6; + unsigned char EMES : 1; + unsigned char RDMDS : 1; +#else + unsigned char RDMDS : 1; + unsigned char EMES : 1; + unsigned char res_bits_1 : 6; +#endif + + unsigned char res_bits_2; +} SSP_PAGE_NBES; // next block encryption status page + +typedef struct { + +#if STENC_BIG_ENDIAN == 0 + unsigned char peripheralQualifier : 3; + unsigned char periphrealDeviceType : 5; +#else + unsigned char periphrealDeviceType : 5; + unsigned char peripheralQualifier : 3; +#endif + +#if STENC_BIG_ENDIAN == 0 + unsigned char RMB : 1; + unsigned char res_bits_1 : 7; +#else + unsigned char res_bits_1 : 7; + unsigned char RMB : 1; +#endif + unsigned char Version[1]; + +#if STENC_BIG_ENDIAN == 0 + unsigned char obs_bits_1 : 2; + unsigned char NORMACA : 1; + unsigned char HISUP : 1; + unsigned char responseDataFormat : 4; +#else + unsigned char responseDataFormat : 4; + unsigned char HISUP : 1; + unsigned char NORMACA : 1; + unsigned char obs_bits_1 : 2; +#endif + + unsigned char additionalLength[1]; + +#if STENC_BIG_ENDIAN == 0 + unsigned char SCCS : 1; + unsigned char ACC : 1; + unsigned char TPGS : 2; + unsigned char threePC : 1; + unsigned char res_bits_2 : 2; + unsigned char protect : 1; +#else + unsigned char protect : 1; + unsigned char res_bits_2 : 2; + unsigned char threePC : 1; + unsigned char TPGS : 2; + unsigned char ACC : 1; + unsigned char SCCS : 1; +#endif + +#if STENC_BIG_ENDIAN == 0 + unsigned char obs_bits_2 : 1; + unsigned char ENCSERV : 1; + unsigned char VS : 1; + unsigned char MULTIP : 1; + unsigned char MCHNGR : 1; + unsigned char obs_bits_3 : 2; + unsigned char ADDR16 : 1; +#else + unsigned char ADDR16 : 1; + unsigned char obs_bits_3 : 2; + unsigned char MCHNGR : 1; + unsigned char MULTIP : 1; + unsigned char VS : 1; + unsigned char ENCSERV : 1; + unsigned char obs_bits_2 : 1; +#endif + +#if STENC_BIG_ENDIAN == 0 + unsigned char obs_bits_4 : 2; + unsigned char WBUS16 : 1; + unsigned char SYNC : 1; + unsigned char obs_bits_5 : 2; + unsigned char CMDQUE : 1; + unsigned char VS2 : 1; +#else + unsigned char VS2 : 1; + unsigned char CMDQUE : 1; + unsigned char obs_bits_5 : 2; + unsigned char SYNC : 1; + unsigned char WBUS16 : 1; + unsigned char obs_bits_4 : 2; +#endif + + unsigned char vender[8]; + unsigned char productID[16]; + unsigned char productRev[4]; + unsigned char SN[7]; + unsigned char venderUnique[12]; + +#if STENC_BIG_ENDIAN == 0 + unsigned char res_bits_3 : 4; + unsigned char CLOCKING : 2; + unsigned char QAS : 1; + unsigned char IUS : 1; +#else + unsigned char IUS : 1; + unsigned char QAS : 1; + unsigned char CLOCKING : 2; + unsigned char res_bits_3 : 4; +#endif + + unsigned char res_bits_4[1]; + unsigned char versionDescriptor[16]; + unsigned char res_bits_5[22]; + unsigned char copyright[1]; +} SCSI_PAGE_INQ; // device inquiry response +typedef struct { +#if STENC_BIG_ENDIAN == 1 + unsigned char valid : 1; + unsigned char responseCode : 7; +#else + unsigned char responseCode : 7; + unsigned char valid : 1; +#endif + unsigned char res_bits_1; #if STENC_BIG_ENDIAN == 1 - unsigned char filemark :1; - unsigned char EOM :1; - unsigned char ILI :1; - unsigned char res_bits_2 :1; - unsigned char senseKey :4; -#else - unsigned char senseKey :4; - unsigned char res_bits_2 :1; - unsigned char ILI :1; - unsigned char EOM :1; - unsigned char filemark :1; -#endif - unsigned char information [4]; - unsigned char addSenseLen; - unsigned char cmdSpecificInfo [4]; - unsigned char addSenseCode; - unsigned char addSenseCodeQual; - unsigned char fieldRepUnitCode; + unsigned char filemark : 1; + unsigned char EOM : 1; + unsigned char ILI : 1; + unsigned char res_bits_2 : 1; + unsigned char senseKey : 4; +#else + unsigned char senseKey : 4; + unsigned char res_bits_2 : 1; + unsigned char ILI : 1; + unsigned char EOM : 1; + unsigned char filemark : 1; +#endif + unsigned char information[4]; + unsigned char addSenseLen; + unsigned char cmdSpecificInfo[4]; + unsigned char addSenseCode; + unsigned char addSenseCodeQual; + unsigned char fieldRepUnitCode; #if STENC_BIG_ENDIAN == 1 - unsigned char sim :3; // system information message - unsigned char bpv :1; // bit pointer valid - unsigned char resvd2 :2; // reserved - unsigned char cd :1; // control/data - unsigned char SKSV :1; + unsigned char sim : 3; // system information message + unsigned char bpv : 1; // bit pointer valid + unsigned char resvd2 : 2; // reserved + unsigned char cd : 1; // control/data + unsigned char SKSV : 1; -#else - unsigned char SKSV :1; - unsigned char cd :1; // control/data - unsigned char resvd2 :2; // reserved - unsigned char bpv :1; // bit pointer valid - unsigned char sim :3; // system information message -#endif - unsigned char field [2]; // field pointer - unsigned char addSenseData [109]; -} SCSI_PAGE_SENSE; //sense data response -class KAD_CLASS{ - public: - std::vector kads; - protected: - void loadKADs(SSP_PAGE_BUFFER* buffer, int start); +#else + unsigned char SKSV : 1; + unsigned char cd : 1; // control/data + unsigned char resvd2 : 2; // reserved + unsigned char bpv : 1; // bit pointer valid + unsigned char sim : 3; // system information message +#endif + unsigned char field[2]; // field pointer + unsigned char addSenseData[109]; +} SCSI_PAGE_SENSE; // sense data response +class KAD_CLASS { +public: + std::vector kads; + +protected: + void loadKADs(SSP_PAGE_BUFFER *buffer, int start); }; - -//class used to parse next block encryption status page -class SSP_NBES: public KAD_CLASS{ - public: - SSP_PAGE_NBES nbes; - SSP_NBES(SSP_PAGE_BUFFER* buffer); +// class used to parse next block encryption status page +class SSP_NBES : public KAD_CLASS { +public: + SSP_PAGE_NBES nbes; + SSP_NBES(SSP_PAGE_BUFFER *buffer); }; -//class used to parse data encryption status page -class SSP_DES: public KAD_CLASS{ - public: - SSP_PAGE_DES des; - SSP_DES(SSP_PAGE_BUFFER* buffer); +// class used to parse data encryption status page +class SSP_DES : public KAD_CLASS { +public: + SSP_PAGE_DES des; + SSP_DES(SSP_PAGE_BUFFER *buffer); }; +// enum for SCSIEncryptOptions.cryptMode +enum { CRYPTMODE_OFF, CRYPTMODE_MIXED, CRYPTMODE_ON, CRYPTMODE_RAWREAD }; -//enum for SCSIEncryptOptions.cryptMode -enum { CRYPTMODE_OFF, CRYPTMODE_MIXED,CRYPTMODE_ON,CRYPTMODE_RAWREAD}; - -//used to pass parameters to SCSIWriteEncryptOptions +// used to pass parameters to SCSIWriteEncryptOptions class SCSIEncryptOptions { - public: - int rdmc; - bool CKOD; - int cryptMode; - unsigned int algorithmIndex; - std::string cryptoKey; - std::string keyName; - SCSIEncryptOptions(); +public: + int rdmc; + bool CKOD; + int cryptMode; + unsigned int algorithmIndex; + std::string cryptoKey; + std::string keyName; + SCSIEncryptOptions(); }; -//Gets encryption options on the tape drive -SSP_DES* SSPGetDES(std::string tapeDevice); -//Gets the encryption status from the tape volume -SSP_NBES* SSPGetNBES(std::string tapeDevice,bool retry); -//Writes encryption options to the tape drive -bool SCSIWriteEncryptOptions(std::string tapeDevice, SCSIEncryptOptions* eOptions); -//Gets device inquiry -SCSI_PAGE_INQ* SCSIGetInquiry(std::string tapeDevice); +// Gets encryption options on the tape drive +SSP_DES *SSPGetDES(std::string tapeDevice); +// Gets the encryption status from the tape volume +SSP_NBES *SSPGetNBES(std::string tapeDevice, bool retry); +// Writes encryption options to the tape drive +bool SCSIWriteEncryptOptions(std::string tapeDevice, + SCSIEncryptOptions *eOptions); +// Gets device inquiry +SCSI_PAGE_INQ *SCSIGetInquiry(std::string tapeDevice); #endif