/* stenc - program to set and retrieve hardware based encryption options from certain SCSI devices (i.e. LTO4 Tape drives) Original program copyright 2010 John D. Coleman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, 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 #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #include "scsiencrypt.h" #include "keyinfo.h" #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; #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; #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 echo(bool); ofstream logFile; //program entry point int main(int argc, char **argv){ 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"); #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"); #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(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<