31 Commits

Author SHA1 Message Date
Jonas Stein
8ff2e4c4eb Codecleanup, Version bump 1.1.0 2022-04-22 00:47:33 +02:00
Jonas Stein
0ad0a208d5 Drop AC_CHECK_INCLUDES_DEFAULT
AC_CHECK_INCLUDES_DEFAULT requires autoconf at least version 2.70
Bug: https://github.com/scsitape/stenc/issues/33
2022-04-21 22:44:41 +02:00
Jonas Stein
59d5c6c0fa ignore temporary files 2022-04-21 22:24:51 +02:00
Jonas Stein
35b852cfeb add .clang-cormat
Add .clang-cormat config file to src folder for unified formatting.
2022-04-20 01:00:40 +02:00
Jonas Stein
88a507932e reformat and cleanup more
reformat the source in an unified way.
(improve later with clang-format config)
fix order of includes
use proper delete[] operator
2022-04-20 00:24:59 +02:00
Jonas Stein
aa2244308d cleaned code
removed std namespace
initialized variables
cleaned endl
added const for constants
tagged new version 1.0.8
2022-04-20 00:12:52 +02:00
Paweł Marciniak
e1e3676660 Use /dev/random to create a key (#22)
Co-authored-by: Paweł Marciniak <sunwire+git@gmail.com>
2022-04-19 22:16:37 +02:00
Jonas Stein
d4ffed77ab Create c-cpp.yml 2022-04-07 20:16:55 +02:00
Jonas Stein
82aca41962 do not make distbuilds anymore 2022-04-07 20:13:00 +02:00
Jonas Stein
b6b7cd90c0 Add LGTM Codeanalysis 2022-04-05 21:31:16 +02:00
John Coleman
e92ccb49ff Merge pull request #17 from fpiecka/patch-1
Remove duplicate zeroing
2020-11-13 20:11:27 -07:00
John Coleman
9feb3f8739 Merge pull request #23 from sunwire/spec
Add example spec file for Fedora/CentOS/RHEL
2020-11-13 20:10:40 -07:00
John Coleman
1dce245cce Merge pull request #25 from sunwire/license
Update GPL2 license
2020-11-13 20:10:18 -07:00
sunwire
b650fb67c0 Update URL from sf to github (#21)
* Correct url from sf to github

Co-authored-by: Paweł Marciniak <sunwire+git@gmail.com>
2020-11-13 00:25:23 +01:00
Paweł Marciniak
70859dfdaa Update GPL2 license 2020-11-11 14:29:13 +01:00
Paweł Marciniak
fc403b6267 Remove BuildRoot tag, add smp flags to make and license macro 2020-11-11 13:57:35 +01:00
Jonas Stein
aefb37e563 link IBM Tape Library Guide
Add link to documentation. 
IBM Tape Library Guide for Open Systems
2020-11-09 12:02:19 +01:00
Paweł Marciniak
90586aa018 Add example spec file for Fedora/CentOS/RHEL 2020-07-26 22:06:11 +02:00
Jonas Stein
dc99d2b3e6 Merge pull request #20 from jonasstein/master
Release 1.0.8
2020-06-17 01:13:03 +02:00
Jonas Stein
d9d8b158c5 Release 1.0.8 2020-06-17 01:11:56 +02:00
Jonas Stein
f175bf4c0b Merge pull request #19 from jonasstein/master
README .md syntax
2020-06-16 22:29:48 +02:00
Jonas Stein
41df2d0c0b README .md syntax 2020-06-16 22:28:45 +02:00
Jonas Stein
2f3d5d27a5 Merge pull request #18 from jonasstein/master
README compile
2020-06-16 22:25:25 +02:00
Jonas Stein
57727c43fe README compile 2020-06-16 22:22:43 +02:00
Jonas Stein
6fc15b72e7 Merge pull request #16 from JosefMeixner/errorreporting
Added output of strerror to undecoded error codes
2020-06-16 22:13:53 +02:00
Jonas Stein
65464950e0 Merge pull request #10 from scsitape/jonasstein-patch-1
Create CONTRIBUTING.md
2020-06-16 22:07:24 +02:00
Jonas Stein
1e89afd60e Merge pull request #14 from Malvineous/master
Fix errors in autogen.sh
2020-06-16 21:30:55 +02:00
Fedor Piecka
a4f407f361 Remove duplicate zeroing
memset zeroes whole &kad. No need to set it's parts to zero. Proposed in
2020-05-29 06:37:31 +02:00
Josef Meixner
e8d1f6b66b Added output of strerror to undecoded error codes 2020-04-13 12:11:26 +02:00
Adam Nielsen
a43678d209 Use Automake 'foreign' option
This avoids errors on missing files NEWS and README.
2018-12-21 00:02:34 +10:00
Adam Nielsen
9022262489 $VARS are not permitted in AC_INIT 2018-12-21 00:02:34 +10:00
15 changed files with 1762 additions and 1466 deletions

29
.github/workflows/c-cpp.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: C/C++ CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: autoconf
run: autoreconf -i
- name: configure
run: ./configure
- name: make
run: make
- name: make check
run: make check
- name: make distcheck
run: make distcheck
- name: make check
run: make check
- name: make distcheck
run: make distcheck

45
.gitignore vendored
View File

@@ -1,3 +1,6 @@
# Tempfiles
*~
# Prerequisites
*.d
@@ -16,10 +19,6 @@
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
@@ -30,3 +29,41 @@
*.exe
*.out
*.app
src/stenc
# Generated Makefile
# (meta build system like autotools,
# can automatically generate from config.status script
# (which is called by configure script))
Makefile
# http://www.gnu.org/software/automake
Makefile.in
/ar-lib
/mdate-sh
/py-compile
/test-driver
/ylwrap
.deps/
.dirstamp
# http://www.gnu.org/software/autoconf
autom4te.cache
/autoscan.log
/autoscan-*.log
/aclocal.m4
/compile
/config.cache
/config.guess
/config.h.in
/config.log
/config.status
/config.sub
/configure
/configure.scan
/depcomp
/install-sh
/missing
/stamp-h1

25
COPYING
View File

@@ -1,8 +1,8 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@@ -55,7 +55,7 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@@ -278,7 +278,7 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
@@ -303,10 +303,9 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
@@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@@ -1,3 +1,12 @@
2022-04-22 Jonas Stein <news@jonasstein.de>
* Version upgraded to 1.1.0
* Code cleanup
* Use /dev/random to create a key
2020-06-16 Jonas Stein <news@jonasstein.de>
* Version upgraded to 1.0.8
* Merged patches to fix make files and provide more error messages
2018-02-13 Jonas Stein <news@jonasstein.de>
* Merged patches from various sources
* move from SF to github in cooperation with John Coleman

View File

@@ -1,2 +1,2 @@
SUBDIRS = src man
EXTRA_DIST = buildconf
# EXTRA_DIST = buildconf

View File

@@ -1,3 +1,6 @@
[![Total alerts](https://img.shields.io/lgtm/alerts/g/scsitape/stenc.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/scsitape/stenc/alerts/)
[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/scsitape/stenc.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/scsitape/stenc/context:cpp)
Stenc
-----
@@ -16,6 +19,16 @@ Features
* AES Encryption
* Key Descriptor Management
Get the source code and compile
-------------------------------
```
git clone git@github.com:scsitape/stenc.git
cd stenc/
autoreconf --install
./configure
make
```
Linux Packages
--------------
@@ -35,3 +48,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.
Further reading
---------------
IBM Tape Library Guide for Open Systems
ISBN-13: 9780738458342
http://www.redbooks.ibm.com/abstracts/sg245946.html?Open

View File

@@ -1,9 +1,6 @@
PACKAGE=stenc
VERSION=1.0.7
AC_INIT($PACKAGE, $VERSION)
AC_INIT([stenc],[1.1.0])
AC_CONFIG_SRCDIR([src/main.cpp])
AM_INIT_AUTOMAKE
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_HEADERS([config.h])
AC_CHECK_HEADER([sys/types.h])
@@ -12,7 +9,19 @@ 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.
# Disable AC_CHECK_INCLUDES_DEFAULT, because this macro requires autoconf at
# least version 2.70 which is not default yet in many distributions.
# See: https://github.com/scsitape/stenc/issues/33
# AC_CHECK_INCLUDES_DEFAULT
AC_PROG_EGREP
AC_MSG_CHECKING(whether to output raw SCSI messages)
@@ -96,5 +105,6 @@ fi
AC_OUTPUT(Makefile src/Makefile man/Makefile)
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile])
AC_OUTPUT

View File

@@ -27,7 +27,7 @@ Allows you to manage hardware encryption on SSP enabled tape devices (LTO4, LTO5
.SH OPTIONS
.TP
\fB\-g \fIlength\fR \fB\-k\fR \fB<file to save as>\fR [\fB\-kd\fR \fI<key descriptor(uKAD)>\fR]
Generates a key file of \fIlength\fR (in bits) containing a random hexadecimal key. After entering this option, you will be required to press random keys followed by the enter key. This will seed the random number generator so that your key is more secure. Specify the file to save the key into with the -k option (you will need write permissions to that file location). Lastly you can enter an optional key description using the -kd flag (see \fIKEY DESCRIPTORS\fR). This key file can then be used with the \fB\-k\fR option. You should not generate a key file over an unsecured remote session. Typically, key files should be set to 256 bits (32 hexadecimal bytes), however your device may only support 128 bits.
Generates a key file of \fIlength\fR (in bits) containing a random hexadecimal key. After entering this option, you will be required to press random keys followed by the enter key. This will seed the random number generator so that your key is more secure. On systems with \fB/dev/random\fR, the key is automatically generated from the random content read from this file. Specify the file to save the key into with the -k option (you will need write permissions to that file location). Lastly you can enter an optional key description using the -kd flag (see \fIKEY DESCRIPTORS\fR). This key file can then be used with the \fB\-k\fR option. You should not generate a key file over an unsecured remote session. Typically, key files should be set to 256 bits (32 hexadecimal bytes), however your device may only support 128 bits.
.TP
\fB\-f\fR \fIdevice\fR
@@ -116,7 +116,7 @@ Written by \fBJohn Coleman\fR and \fBSamuel Martinez Jr.\fR of SunWest Education
Report \fBstenc\fR bugs to \fIjcoleman1981@live.com\fR.
.SH PROJECT UPDATES
Visit \fBhttp://sourceforge.net/projects/stenc/\fR for more information.
Visit \fBhttps://github.com/scsitape/stenc\fR for more information.
.SH COPYRIGHT
Copyright 2012 contributing authors. License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

118
src/.clang-format Normal file
View File

@@ -0,0 +1,118 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
...

View File

@@ -1,29 +1,27 @@
#include <config.h>
#include <iostream>
#include <string.h>
#include <string>
#include <sstream>
#include "keyinfo.h"
#include "scsiencrypt.h"
using namespace std;
#include <config.h>
#include <iostream>
#include <sstream>
#include <string.h>
#include <string>
Keyinfo::Keyinfo(){
valid=false;
check="";
key=NULL;
keySize=0;
Keyinfo::Keyinfo() {
valid = false;
check = "";
key = NULL;
keySize = 0;
}
void Keyinfo::load(string hexinput){
valid=true;
if(hexinput.size()<2){
valid=false;
cout<<"Key input too short!"<<endl;
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;i<hexinput.size();i++){
switch((unsigned char)hexinput.at(i)){
// parse for invalid characters
for (unsigned int i = 0; i < hexinput.size(); i++) {
switch ((unsigned char)hexinput.at(i)) {
case '0':
case '1':
case '2':
@@ -48,76 +46,77 @@ void Keyinfo::load(string hexinput){
case 'F':
break;
default:
cout<<"Invalid character '"<<hexinput.at(i)<<"' found in key!"<<endl;
valid=false;
std::cout << "Invalid character '" << hexinput.at(i)
<< "' found in key!\n";
valid = false;
return;
}
}
// delete the key if its already allocated
if(key!=NULL)
delete key;
if (key != NULL)
delete[] key;
// check that the input size is divisible by 2
if(hexinput.size()%2!=0){
valid=false;
cout<<"Each hexadecimal byte must consist of 2 digits!"<<endl;
if (hexinput.size() % 2 != 0) {
valid = false;
std::cout << "Each hexadecimal byte must consist of 2 digits!\n";
return;
}
//convert the hex input to a char*
// convert the hex input to a char*
loadKey(hexinput);
//load the check value
// load the check value
loadCheck();
//check for oversized key
if(keySize==0 || keySize>SSP_KEY_LENGTH){
cout<<"Key size cannot exceed "<<(SSP_KEY_LENGTH*8)<<" bits!"<<endl;
cout<<"Provided key is "<<(keySize*8)<<" bits in length."<<endl;
valid=false;
// check for oversized key
if (keySize == 0 || keySize > 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;
}
cout<<"Provided key length is "<<(keySize*8)<<" bits."<<endl;
cout<<"Key checksum is "<<check<<"."<<endl;
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<keySize;i++) {
for (i = 0; i < keySize; i++) {
chk += ((int)key[i]) * (i + 1);
}
stringstream retval;
retval<<hex<<chk;
check=retval.str();
std::stringstream retval;
retval << std::hex << chk;
check = retval.str();
}
Keyinfo::~Keyinfo(){
delete key;
}
void Keyinfo::loadKey(string str)
{
Keyinfo::~Keyinfo() { delete[] key; }
void Keyinfo::loadKey(std::string str) {
int length = str.size();
// make sure the input string has an even digit numbers
if(length%2 == 1)
{
if (length % 2 == 1) {
str = "0" + str;
length++;
}
// allocate memory for the output array
key = new char[length/2];
memset(key,0,(length/2)+1);
keySize = length/2;
key = new char[length / 2];
memset(key, 0, (length / 2) + 1);
keySize = length / 2;
stringstream sstr(str);
for(int i=0; i < keySize; i++)
{
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;
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;
}
}

View File

@@ -2,19 +2,19 @@
#define KEYINFO_H
#include <string>
class Keyinfo{
public:
char* key;
class Keyinfo {
public:
char *key;
int keySize;
bool valid;
std::string check;
void load(std::string hexinput);
Keyinfo();
~Keyinfo();
private:
private:
void loadKey(std::string str);
void loadCheck();
};
#endif

View File

@@ -13,558 +13,615 @@ 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 <config.h>
#include <termios.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <unistd.h>
#endif
#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <ios>
#include <iostream>
#include <sstream>
#include <string>
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#include <string.h>
#endif
#include "scsiencrypt.h"
#include "keyinfo.h"
#define LOGFILE "/var/log/stenc"
#include <ostream>
#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;
int main(int argc, char **argv) {
bitcheck bc;
memset(&bc,0,1);
bc.bit2=1;
bc.bit5=1;
memset(&bc, 0, 1);
bc.bit2 = 1;
bc.bit5 = 1;
unsigned char check;
memcpy(&check,&bc,1);
memcpy(&check, &bc, 1);
switch((int)check){
switch ((int)check) {
case 0x12:
//this is good
// 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 "<<HEX(check)<<endl;
std::cerr << "Unknown bit check result " << std::hex << check << "\n";
errorOut("Exiting program because it will not run properly");
break;
}
string tapeDrive="";
int action=0; // 0 = status, 1 =setting param, 2 = generating key
string keyFile,keyDesc;
int keyLength=0;
bool detail=false;
std::string tapeDrive = "";
int action = 0; // 0 = status, 1 =setting param, 2 = generating key
std::string keyFile, keyDesc;
int keyLength = 0;
bool detail = false;
SCSIEncryptOptions drvOptions;
//First load all of the options
for(int i=1;i<argc;i++){
string thisCmd=argv[i];
string nextCmd="";
if(i+1<argc){
if(strncmp(argv[i+1],"-",1)!=0)nextCmd=argv[i+1];
// First load all of the options
for (int i = 1; i < argc; i++) {
std::string thisCmd = argv[i];
std::string nextCmd = "";
if (i + 1 < argc) {
if (strncmp(argv[i + 1], "-", 1) != 0)
nextCmd = argv[i + 1];
}
if(thisCmd=="--version"){
cout<<"stenc v"<<VERSION<<" - SCSI Tape Encryption Manager"<<endl;
cout<<"http://sourceforge.net/projects/stenc/"<<endl;
if (thisCmd == "--version") {
std::cout << "stenc v" << VERSION << " - SCSI Tape Encryption Manager\n";
std::cout << "https://github.com/scsitape/stenc \n";
exit(EXIT_SUCCESS);
}
if(thisCmd=="-g"){ //Check if the help flag was passed. If it was, show usage and exit
if(nextCmd=="")errorOut("Key size must be specified when using -g");
i++; //skip the next argument
keyLength=atoi(nextCmd.c_str());
if (keyLength % 8 != 0)errorOut("Key size must be divisible by 8");
keyLength=keyLength/8;
if(keyLength>SSP_KEY_LENGTH){
cout<<"Warning: Keys over "<<(SSP_KEY_LENGTH*8)<<" bits cannot be used by this program!"<<endl;
if (thisCmd == "-g") { // Check if the help flag was passed. If it was,
// show usage and exit
if (nextCmd == "")
errorOut("Key size must be specified when using -g");
i++; // skip the next argument
keyLength = std::atoi(nextCmd.c_str());
if (keyLength % 8 != 0)
errorOut("Key size must be divisible by 8");
keyLength = keyLength / 8;
if (keyLength > SSP_KEY_LENGTH) {
std::cout << "Warning: Keys over " << (SSP_KEY_LENGTH * 8)
<< " bits cannot be used by this program! \n";
}
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){
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
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 + "'");
}
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==""){
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.");
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 << newkey << keyDesc;
kf.close();
cout<<"Random key saved into '"<<keyFile<<"'"<<endl;
chmod(keyFile.c_str(),0600);
cout<<"Permissions of keyfile set to 600"<<endl;
std::cout << "Random key saved into '" << keyFile << "'\n";
chmod(keyFile.c_str(), 0600);
std::cout << "Permissions of keyfile set to 600\n";
exit(EXIT_SUCCESS);
}
//validate the tape device
if(tapeDrive==""){
// 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'");
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(".")==string::npos){
if(tapeDrive.substr(0,7)=="/dev/st"){
tapeDrive="/dev/nst"+tapeDrive.substr(7,tapeDrive.size()-6);
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";
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){
if (getuid() != 0) {
errorOut("You must be root to read or set encryption options on a drive!");
}
logFile.open(LOGFILE,ios::app);
if(!logFile.is_open()){
cout<<"Warning: Could not open '"<<LOGFILE<<"' for key change auditing!"<<endl;
logFile.open(LOGFILE, std::ios::app);
if (!logFile.is_open()) {
std::cout << "Warning: Could not open '" << LOGFILE
<< "' for key change auditing!\n";
}
chmod(LOGFILE,0600);
chmod(LOGFILE, 0600);
if(action==0){
cout<<"Status for "<<tapeDrive<<endl;
cout<<"--------------------------------------------------"<<endl;
if(detail)
if (action == 0) {
std::cout << "Status for " << tapeDrive << "\n"
<< "--------------------------------------------------\n";
if (detail)
inquiryDrive(tapeDrive);
showDriveStatus(tapeDrive,detail);
if(detail)
showDriveStatus(tapeDrive, detail);
if (detail)
showVolumeStatus(tapeDrive);
exit(EXIT_SUCCESS);
}
Keyinfo ki;
if(drvOptions.cryptMode!=CRYPTMODE_OFF){
if(keyFile==""){
string p1="01";
string p2="02";
bool done=false;
while(!done){
cout<<"Enter key in hex format: ";
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(cin,p1);
getline(std::cin, p1);
echo(true);
cout<<endl;
cout<<"Re-enter key in hex format: ";
std::cout << "\nRe-enter key in hex format: ";
echo(false);
getline(cin,p2);
getline(std::cin, p2);
echo(true);
cout<<endl;
if(p1!=p2){
cout<<"Keys do not match!!"<<endl;
}else{
std::cout << "\n";
if (p1 != p2) {
std::cout << "Keys do not match!\n";
} else {
ki.load(p1);
if(ki.valid){
cout<<"Set encryption using this key? [y/n]: ";
string ans="";
getline(cin,ans);
if(ans=="y"){
done=true;
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 cout<<"Invalid key!"<<endl;
} else
std::cout << "Invalid key!\n";
}
}
drvOptions.keyName=keyDesc;
drvOptions.keyName = keyDesc;
}else{
//set keyInput here
string keyInput;
ifstream myfile(keyFile.c_str());
if (myfile.is_open())
{
getline (myfile,keyInput);
getline (myfile,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");
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);
drvOptions.cryptoKey.assign(ki.key, ki.keySize);
}
//Write the options to the tape device
cout<<"Turning "<<((drvOptions.cryptMode!=CRYPTMODE_OFF)?"on":"off")<<" encryption on device '"<<tapeDrive<<"'..."<<endl;
bool res=SCSIWriteEncryptOptions(tapeDrive,&drvOptions);
if(res){
// 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!");
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!");
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 '"<<tapeDrive<<"'. ";
if(drvOptions.keyName.size()==0)
msg<<"Key Checksum: "<<ki.check;
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: "<<dec<<BSLONG(opt->des.keyInstance)<<endl;
msg << "Key Descriptor: '" << drvOptions.keyName << "'";
msg << " Key Instance: " << std::dec << BSLONG(opt->des.keyInstance)
<< std::endl;
if(logFile.is_open()){
logFile<<timestamp()<<": "<<msg.str();
if (logFile.is_open()) {
logFile << timestamp() << ": " << msg.str();
}
}else{
stringstream msg;
} else {
std::stringstream msg{};
msg<< "Encryption turned off for device '"<<tapeDrive<<"'.";
msg<<" Key Instance: "<<dec<<BSLONG(opt->des.keyInstance)<<endl;
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();
if (logFile.is_open())
logFile << timestamp() << ": " << msg.str();
}
cout<< "Success! See '"<<LOGFILE<<"' for a key change audit log."<<endl;
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!");
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(string message){
cerr<<"Error: "<<message<<endl;
// exits to shell with an error message
void errorOut(std::string const message) {
std::cerr << "Error: " << message << "\n";
showUsage();
exit(EXIT_FAILURE);
}
//shows the command usage
void showUsage(){
cout<<"Usage: stenc --version | -g <length> -k <file> [-kd <description>] | -f <device> [--detail] [-e <on/mixed/rawread/off> [-k <file>] [-kd <description>] [-a <index>] [--protect | --unprotect] [--ckod] ]"<<endl;
cout<<"Type 'man stenc' for more information."<<endl;
// shows the command usage
void showUsage() {
std::cout
<< "Usage: stenc --version | -g <length> -k <file> [-kd <description>] | "
"-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(string tapeDevice){
SCSI_PAGE_INQ* iresult=SCSIGetInquiry(tapeDevice);
cout<<left<<setw(25)<<"Device Mfg:";
cout.write((const char*)iresult->vender,8);
cout<<endl;
cout<<left<<setw(25)<<"Product ID:";
cout.write((const char*)iresult->productID,16);
cout<<endl;
cout<<left<<setw(25)<<"Product Revision:";
cout.write((const char*)iresult->productRev,4);
cout<<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(string tapeDrive,bool detail){
SSP_DES* opt=SSPGetDES(tapeDrive);
if(opt==NULL)return;
string emode="unknown";
cout<<left<<setw(25)<<"Drive Encryption:";
if(
(int)opt->des.encryptionMode==0x2 && //encrypt
(int)opt->des.decryptionMode==0x2 //read only encrypted data
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 = "on";
if ((int)opt->des.encryptionMode == 0x2 && // encrypt
(int)opt->des.decryptionMode == 0x3 // read encrypted and unencrypted
)
emode="mixed";
emode = "mixed";
if(
(int)opt->des.encryptionMode==0x2 && //encrypt
(int)opt->des.decryptionMode==0x1 //read encrypted and unencrypted
if ((int)opt->des.encryptionMode == 0x2 && // encrypt
(int)opt->des.decryptionMode == 0x1 // read encrypted and unencrypted
)
emode="rawread";
emode = "rawread";
if(
(int)opt->des.encryptionMode==0x0 && //encrypt
(int)opt->des.decryptionMode==0x0 //read encrypted and unencrypted
if ((int)opt->des.encryptionMode == 0x0 && // encrypt
(int)opt->des.decryptionMode == 0x0 // read encrypted and unencrypted
)
emode="off";
emode = "off";
cout<<emode<<endl;
if(detail){
cout<<left<<setw(25)<<"Drive Output:";
switch ((int)opt->des.decryptionMode){
std::cout << emode << "\n";
if (detail) {
std::cout << std::left << std::setw(25) << "Drive Output:";
switch ((int)opt->des.decryptionMode) {
case 0x0:
cout<<"Not decrypting"<<endl;
cout<<setw(25)<<" "<<"Raw encrypted data not outputted"<<endl;
std::cout << "Not decrypting\n";
std::cout << std::setw(25) << " "
<< "Raw encrypted data not outputted\n";
break;
case 0x1:
cout<<"Not decrypting"<<endl;
cout<<setw(25)<<" "<<"Raw encrypted data outputted"<<endl;
std::cout << "Not decrypting\n";
std::cout << std::setw(25) << " "
<< "Raw encrypted data outputted\n";
break;
case 0x2:
cout<<"Decrypting"<<endl;
cout<<setw(25)<<" "<<"Unencrypted data not outputted"<<endl;
std::cout << "Decrypting\n";
std::cout << std::setw(25) << " "
<< "Unencrypted data not outputted\n";
break;
case 0x3:
cout<<"Decrypting"<<endl;
cout<<setw(25)<<" "<<"Unencrypted data outputted"<<endl;
std::cout << "Decrypting\n";
std::cout << std::setw(25) << " "
<< "Unencrypted data outputted\n";
break;
default:
cout<<"Unknown '0x"<<hex<<(int)opt->des.decryptionMode<<"' "<<endl;
std::cout << "Unknown '0x" << std::hex << (int)opt->des.decryptionMode
<< "' \n";
break;
}
cout<<setw(25)<<"Drive Input:";
switch((int)opt->des.encryptionMode){
std::cout << std::setw(25) << "Drive Input:";
switch ((int)opt->des.encryptionMode) {
case 0x0:
cout<<"Not encrypting"<<endl;
std::cout << "Not encrypting\n";
break;
case 0x2:
cout<<"Encrypting"<<endl;
std::cout << "Encrypting\n";
break;
default:
cout<<"Unknown result '0x"<<hex<<(int)opt->des.encryptionMode<<"'"<<endl;
std::cout << "Unknown result '0x" << std::hex
<< (int)opt->des.encryptionMode << "'\n";
break;
}
if(opt->des.RDMD==1){
cout<<setw(25)<<" "<<"Protecting from raw read"<<endl;
if (opt->des.RDMD == 1) {
std::cout << std::setw(25) << " "
<< "Protecting from raw read\n";
}
cout<<setw(25)<<"Key Instance Counter:"<<dec<<BSLONG(opt->des.keyInstance)<<endl;
if(opt->des.algorithmIndex!=0){
cout<<setw(25)<<"Encryption Algorithm:"<<hex<<(int)opt->des.algorithmIndex<<endl;
std::cout << std::setw(25) << "Key Instance Counter:" << std::dec
<< BSLONG(opt->des.keyInstance) << "\n";
if (opt->des.algorithmIndex != 0) {
std::cout << std::setw(25) << "Encryption Algorithm:" << std::hex
<< (int)opt->des.algorithmIndex << "\n";
}
}
if(opt->kads.size()>0){
for(unsigned int i=0;i<opt->kads.size();i++){
stringstream lbl;
lbl<<"Drive Key Desc.(";
switch(opt->kads[i].type){
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): ";
cout<<setw(25)<<lbl.str();
cout.write((const char*)&opt->kads[i].descriptor,BSSHORT(opt->kads[i].descriptorLength));
cout<<endl;
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): ";
cout<<setw(25)<<lbl.str();
cout.write((const char*)&opt->kads[i].descriptor,BSSHORT(opt->kads[i].descriptorLength));
cout<<endl;
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(string tapeDrive){
SSP_NBES* opt=SSPGetNBES(tapeDrive,true);
if(opt==NULL)return;
if(opt->nbes.compressionStatus!=0){
cout<<left<<setw(25)<<"Volume Compressed:";
switch(opt->nbes.compressionStatus){
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:
cout<<"Drive cannot determine"<<endl;
std::cout << "Drive cannot determine\n";
break;
default:
cout<<"Unknown result '"<<hex<<(int)opt->nbes.compressionStatus<<"'"<<endl;
std::cout << "Unknown result '" << std::hex
<< (int)opt->nbes.compressionStatus << "'\n";
break;
}
}
cout<<left<<setw(25)<<"Volume Encryption:";
switch((int)opt->nbes.encryptionStatus){
std::cout << std::left << std::setw(25) << "Volume Encryption:";
switch ((int)opt->nbes.encryptionStatus) {
case 0x01:
cout<<"Unable to determine"<<endl;
std::cout << "Unable to determine\n";
break;
case 0x02:
cout<<"Logical block is not a logical block"<<endl;
std::cout << "Logical block is not a logical block\n";
break;
case 0x03:
cout<<"Not encrypted"<<endl;
std::cout << "Not encrypted\n";
break;
case 0x05:
cout<<"Encrypted and able to decrypt"<<endl;
if(opt->nbes.RDMDS==1)
cout<<left<<setw(25)<<" "<<"Protected from raw read"<<endl;
std::cout << "Encrypted and able to decrypt\n";
if (opt->nbes.RDMDS == 1)
std::cout << std::left << std::setw(25)
<< " Protected from raw read\n";
break;
case 0x06:
cout<<"Encrypted, but unable to decrypt due to invalid key. "<<endl;
if(opt->kads.size()>0){
for(unsigned int i=0;i<opt->kads.size();i++){
stringstream lbl;
lbl<<"Volume Key Desc.(";
switch(opt->kads[i].type){
std::cout << "Encrypted, but unable to decrypt due to invalid key.\n";
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): ";
cout<<setw(25)<<lbl.str();
cout.write((const char*)&opt->kads[i].descriptor,BSSHORT(opt->kads[i].descriptorLength));
cout<<endl;
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): ";
cout<<setw(25)<<lbl.str();
cout.write((const char*)&opt->kads[i].descriptor,BSSHORT(opt->kads[i].descriptorLength));
cout<<endl;
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)
cout<<left<<setw(25)<<" "<<"Protected from raw read"<<endl;
if (opt->nbes.RDMDS == 1)
std::cout << std::left << std::setw(25) << " Protected from raw read\n";
break;
default:
cout<<"Unknown result '"<<hex<<(int)opt->nbes.encryptionStatus<<"'"<<endl;
std::cout << "Unknown result '" << std::hex
<< (int)opt->nbes.encryptionStatus << "'\n";
break;
}
if(opt->nbes.algorithmIndex!=0){
cout<<left<<setw(25)<<"Volume Algorithm:"<<(int)opt->nbes.algorithmIndex<<endl;
if (opt->nbes.algorithmIndex != 0) {
std::cout << std::left << std::setw(25)
<< "Volume Algorithm:" << (int)opt->nbes.algorithmIndex << "\n";
}
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 );
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;
std::string timestamp() {
time_t tm{};
time(&tm);
char buffer[80];
int len=strftime((char*)&buffer,80,"%Y-%m-%d",localtime(&tm));
string val;
val.assign(buffer,len);
return val;
int len = strftime((char *)&buffer, 80, "%Y-%m-%d", localtime(&tm));
std::string val;
val.assign(buffer, len);
return (val);
}
string randomKey(int length)
{
cout<<"Enter random keys on the keyboard to seed the generator."<<endl<<"End by pressing enter..."<<endl;
double check=0;
char c=0;
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<char *>(&rnd), 1);
retval << std::hex << rnd;
}
random.close();
} else {
std::cout << "Enter random keys on the keyboard to seed the generator.\n"
"End by pressing enter...\n";
double check = 0;
char c = 0;
echo(false);
while(c!=10){
check+=(int)c;
c=getchar();
while (c != 10) {
check += (int)c;
c = getchar();
}
echo(true);
srand(time(NULL)+(int)check);
stringstream retval;
for (int i=0; i<length; i++)
{
retval <<HEX(rand() % 256);
srand(time(NULL) + (int)check);
for (int i = 0; i < length; i++) {
retval << std::hex << (std::rand() % 256);
}
retval << endl;
return retval.str();
}
retval << std::endl;
return (retval.str());
}

View File

@@ -12,46 +12,46 @@ 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 <string>
#include <errno.h>
#include <fcntl.h>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <bitset>
#include <fcntl.h>
#include <errno.h>
#include <string>
#include <sys/ioctl.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <unistd.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#include <string.h>
#endif
#if defined(OS_LINUX)
#include <scsi/sg.h>
#include <scsi/scsi.h>
#define SCSI_TIMEOUT 5000
#include <scsi/scsi.h>
#include <scsi/sg.h>
#define SCSI_TIMEOUT 5000
#elif defined(OS_FREEBSD)
#include <cam/scsi/scsi_sg.h>
#define SCSI_TIMEOUT 5000
#include <cam/scsi/scsi_sg.h>
#define SCSI_TIMEOUT 5000
#elif defined(OS_AIX)
#define _LINUX_SOURCE_COMPAT
#include <sys/scsi.h>
#include <sys/scsi_buf.h>
#include <sys/tape.h>
#include <sys/Atape.h>
#define SCSI_TIMEOUT 5
#define _LINUX_SOURCE_COMPAT
#include <sys/Atape.h>
#include <sys/scsi.h>
#include <sys/scsi_buf.h>
#include <sys/tape.h>
#define SCSI_TIMEOUT 5
#else
#error "OS type is not set"
#error "OS type is not set"
#endif
#include <sys/mtio.h>
#include "scsiencrypt.h"
#include <sys/mtio.h>
#define SSP_SPIN_OPCODE 0XA2
#define SSP_SPOUT_OPCODE 0XB5
@@ -60,567 +60,540 @@ GNU General Public License for more details.
#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(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;
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 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,
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] = {
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,
0,
0,
BSINTTOCHAR(sizeof(SSP_PAGE_BUFFER)),
0,0
};
0,
0};
//Gets encryption options on the tape drive
SSP_DES* SSPGetDES(string tapeDevice){
// 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))
{
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);
SSP_DES *status = new SSP_DES(&buffer);
return status;
}
//Gets encryption options on the tape drive
SSP_NBES* SSPGetNBES(string tapeDevice,bool retry){
// 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))
{
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;
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;
status = NULL; // double free bug fix provided by Adam Nielsen
if (!moveTape(tapeDevice, 1, true))
break;
moves++;
status=SSPGetNBES(tapeDevice,false);
status = SSPGetNBES(tapeDevice, false);
}
moveTape(tapeDevice,moves,false);
moveTape(tapeDevice, moves, false);
}
return status;
}
//Sends and inquiry to the device
SCSI_PAGE_INQ* SCSIGetInquiry(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))
{
// 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(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);
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;
// 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;
case CRYPTMODE_MIXED: // encrypt, read all data
options.encryptionMode = 2;
options.decryptionMode = 3;
break;
case CRYPTMODE_RAWREAD:
options.encryptionMode=2;
options.decryptionMode=1;
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
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);
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!=""){
// create the key descriptor
if (eOptions->keyName != "") {
SSP_KAD kad;
memset(&kad,0,sizeof(kad));
kad.type=0x00;
kad.authenticated=0;
//set the descriptor length to the length of the keyName
byteswap((unsigned char*)&kad.descriptorLength,2,eOptions->keyName.size());
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);
// 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
// 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));
// 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,
unsigned char spout_sde_command[SSP_SP_CMD_LEN] = {SSP_SPOUT_OPCODE,
SSP_SP_PROTOCOL_TDE,
0,
0X10,
0,0,
0,
0,
BSINTTOCHAR(pagelen),
0,0
};
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
);
// 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(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;
errno = 0;
sg_fd = open(tapedevice, O_RDONLY);
if( sg_fd==-1){
cerr<<"Could not open device '"<<tapedevice<<"': ";
if (sg_fd == -1) {
std::cerr << "Could not open device '" << tapedevice << "': ";
readIOError(errno);
exit(EXIT_FAILURE);
}
sg_io_hdr cmdio;
memset(&cmdio,0,sizeof(sg_io_hdr));
memset(&cmdio, 0, sizeof(sg_io_hdr));
cmdio.cmd_len = cmd_len;
cmdio.dxfer_direction =(cmd_to_device)?SG_DXFER_TO_DEV:SG_DXFER_FROM_DEV;
cmdio.dxfer_direction = (cmd_to_device) ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
cmdio.dxfer_len = dxfer_len;
cmdio.dxferp = dxfer_p;
cmdio.cmdp = cmd_p;
cmdio.sbp = (unsigned char*)sd;
cmdio.mx_sb_len=sizeof(SCSI_PAGE_SENSE);
cmdio.sbp = (unsigned char *)sd;
cmdio.mx_sb_len = sizeof(SCSI_PAGE_SENSE);
cmdio.timeout = SCSI_TIMEOUT;
cmdio.interface_id = 'S';
retries=0;
do{
errno=0;
eresult=ioctl(sg_fd, SG_IO, &cmdio);
if(eresult!=0)
ioerr=errno;
retries = 0;
do {
errno = 0;
eresult = ioctl(sg_fd, SG_IO, &cmdio);
if (eresult != 0)
ioerr = errno;
retries++;
}while(errno!=0 && retries<=RETRYCOUNT);
} while (errno != 0 && retries <= RETRYCOUNT);
sresult=cmdio.status;
sresult = cmdio.status;
#elif defined(OS_AIX) // AIX System
errno=0;
sg_fd = openx((char*)tapedevice, O_RDONLY , NULL, SC_DIAGNOSTIC);
if(!sg_fd || sg_fd==-1){
cerr<<"Could not open device '"<<tapedevice<<"'"<<endl;
errno = 0;
sg_fd = openx((char *)tapedevice, O_RDONLY, NULL, SC_DIAGNOSTIC);
if (!sg_fd || sg_fd == -1) {
std::cerr << "Could not open device '" << tapedevice << "'" << std::endl;
exit(EXIT_FAILURE);
}
struct sc_iocmd cmdio;
memset(&cmdio,0,sizeof (struct sc_iocmd));
//copy the command bytes into the first part of the structure
memcpy(&cmdio.scsi_cdb,cmd_p,cmd_len);
cmdio.buffer=(char*)dxfer_p;
cmdio.timeout_value=SCSI_TIMEOUT;
cmdio.command_length=cmd_len;
cmdio.data_length=dxfer_len;
cmdio.status_validity=SC_SCSI_ERROR;
cmdio.flags=(cmd_to_device)?B_WRITE:B_READ;
memset(&cmdio, 0, sizeof(struct sc_iocmd));
// copy the command bytes into the first part of the structure
memcpy(&cmdio.scsi_cdb, cmd_p, cmd_len);
cmdio.buffer = (char *)dxfer_p;
cmdio.timeout_value = SCSI_TIMEOUT;
cmdio.command_length = cmd_len;
cmdio.data_length = dxfer_len;
cmdio.status_validity = SC_SCSI_ERROR;
cmdio.flags = (cmd_to_device) ? B_WRITE : B_READ;
retries=0;
do{
errno=0;
eresult=ioctl(sg_fd, STIOCMD, &cmdio);
sresult=(int)cmdio.scsi_bus_status;
if(eresult!=0)
ioerr=errno;
retries = 0;
do {
errno = 0;
eresult = ioctl(sg_fd, STIOCMD, &cmdio);
sresult = (int)cmdio.scsi_bus_status;
if (eresult != 0)
ioerr = errno;
retries++;
}while(errno!=0 && retries<=RETRYCOUNT);
} while (errno != 0 && retries <= RETRYCOUNT);
if(sresult==SC_CHECK_CONDITION){ //get the sense data
if (sresult == SC_CHECK_CONDITION) { // get the sense data
struct sc_iocmd scmdio;
memset(&scmdio,0,sizeof (struct sc_iocmd));
//copy the command bytes into the first part of the structure
memcpy(&scmdio.scsi_cdb,&scsi_sense_command,sizeof(scsi_sense_command));
scmdio.buffer=(char*)sd;
scmdio.timeout_value=SCSI_TIMEOUT;
scmdio.command_length=sizeof(scsi_sense_command);
scmdio.data_length=sizeof(SCSI_PAGE_SENSE);
scmdio.status_validity=SC_SCSI_ERROR;
scmdio.flags=B_READ;
memset(&scmdio, 0, sizeof(struct sc_iocmd));
// copy the command bytes into the first part of the structure
memcpy(&scmdio.scsi_cdb, &scsi_sense_command, sizeof(scsi_sense_command));
scmdio.buffer = (char *)sd;
scmdio.timeout_value = SCSI_TIMEOUT;
scmdio.command_length = sizeof(scsi_sense_command);
scmdio.data_length = sizeof(SCSI_PAGE_SENSE);
scmdio.status_validity = SC_SCSI_ERROR;
scmdio.flags = B_READ;
errno=0;
errno = 0;
ioctl(sg_fd, STIOCMD, &scmdio);
}
#else
#error "OS type is not set"
#error "OS type is not set"
#endif
#ifdef DEBUGSCSI
cout<<"SCSI Command: ";
for(int i=0;i<cmd_len;i++){
cout<<HEX(cmd_p[i]);
std::cout << "SCSI Command: ";
for (int i = 0; i < cmd_len; i++) {
std::cout << std::hex << cmd_p[i];
}
cout<<endl;
std::cout << "\n";
cout<<"SCSI Data: ";
for(int i=0;i<dxfer_len;i++){
cout<<HEX(dxfer_p[i]);
std::cout << "SCSI Data: ";
for (int i = 0; i < dxfer_len; i++) {
std::cout << std::hex << (dxfer_p[i]);
}
cout<<endl;
std::cout << std::endl;
#endif
close(sg_fd);
bool retval = true;
bool retval=true;
if(eresult!=0){
if(show_error)
if (eresult != 0) {
if (show_error)
readIOError(ioerr);
retval=false;
retval = false;
}
if(sresult!=0){
if(show_error)
if (sresult != 0) {
if (show_error)
outputSense(sd);
retval=false;
retval = false;
}
delete sd;
return retval;
}
void byteswap(unsigned char* array,int size,int value){
switch(size){
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);
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);
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:
cout<<"Unhandled byte swap length of "<<size<<endl;
std::cout << "Unhandled byte swap length of " << size << std::endl;
break;
}
}
SCSIEncryptOptions::SCSIEncryptOptions(){
cryptMode=CRYPTMODE_OFF;
algorithmIndex=DEFAULT_ALGORITHM;
cryptoKey="";
CKOD=false;
keyName="";
rdmc=RDMC_DEFAULT;
SCSIEncryptOptions::SCSIEncryptOptions() {
cryptMode = CRYPTMODE_OFF;
algorithmIndex = DEFAULT_ALGORITHM;
cryptoKey = "";
CKOD = false;
keyName = "";
rdmc = RDMC_DEFAULT;
}
SSP_NBES::SSP_NBES(SSP_PAGE_BUFFER* buffer){
memset(&nbes,0,sizeof(SSP_PAGE_NBES));
memcpy(&nbes,buffer,sizeof(SSP_PAGE_NBES));
loadKADs(buffer,sizeof(SSP_PAGE_NBES));
SSP_NBES::SSP_NBES(SSP_PAGE_BUFFER *buffer) {
memset(&nbes, 0, sizeof(SSP_PAGE_NBES));
memcpy(&nbes, buffer, sizeof(SSP_PAGE_NBES));
loadKADs(buffer, sizeof(SSP_PAGE_NBES));
}
SSP_DES::SSP_DES(SSP_PAGE_BUFFER* buffer){
memset(&des,0,sizeof(SSP_PAGE_DES));
memcpy(&des,buffer,sizeof(SSP_PAGE_DES));
loadKADs(buffer,sizeof(SSP_PAGE_DES));
SSP_DES::SSP_DES(SSP_PAGE_BUFFER *buffer) {
memset(&des, 0, sizeof(SSP_PAGE_DES));
memcpy(&des, buffer, sizeof(SSP_PAGE_DES));
loadKADs(buffer, sizeof(SSP_PAGE_DES));
}
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){
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++;
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){
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){
if (!sg_fd || sg_fd == -1) {
return false;
}
errno=0;
bool retval=true;
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_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_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;
if (errno != 0)
retval = false;
close(sg_fd);
errno=0;
errno = 0;
return retval;
}
void readIOError(int err){
if(err==0)return;
cerr<<"ERROR: ";
switch(err){
void readIOError(int err) {
if (err == 0)
return;
std::cerr << "ERROR: ";
switch (err) {
case EAGAIN:
cerr<<"Device already open"<<endl;
std::cerr << "Device already open.\n";
break;
case EBUSY:
cerr<<"Device Busy"<<endl;
std::cerr << "Device Busy.\n";
break;
case ETIMEDOUT:
cerr<<"Device operation timed out"<<endl;
std::cerr << "Device operation timed out\n";
break;
case EIO:
cerr<<"Device I/O Error."<<endl;
std::cerr << "Device I/O Error.\n";
break;
case EPERM:
cerr<<"You do not have privileges to do this. Are you root?"<<endl;
std::cerr << "You do not have privileges to do this. Are you root?\n";
break;
#ifdef OS_AIX
case EBADF:
cerr<<"EBADF"<<endl;
std::cerr << "EBADF\n";
break;
case EFAULT:
cerr<<"EFAULT"<<endl;
std::cerr << "EFAULT\n";
break;
case EINTR:
cerr<<"EINTR"<<endl;
std::cerr << "EINTR\n";
break;
case EINVAL:
cerr<<"Invalid device"<<endl;
std::cerr << "Invalid device.\n";
break;
case ENOTTY:
cerr<<"ENOTTY"<<endl;
std::cerr << "ENOTTY\n";
break;
case ENODEV:
cerr<<"Device is not responding"<<endl;
std::cerr << "Device is not responding.\n";
break;
case ENXIO:
cerr<<"ENXIO"<<endl;
std::cerr << "ENXIO\n";
break;
#endif
default:
if(errno!=0){
cerr<<"0x"<<hex<<errno<<endl;
if (errno != 0) {
std::cerr << "0x" << std::hex << errno << " " << strerror(errno) << "\n";
}
}
}
void outputSense(SCSI_PAGE_SENSE* sd){
cerr<<left<<setw(25)<<"Sense Code: ";
void outputSense(SCSI_PAGE_SENSE *sd) {
std::cerr << std::left << std::setw(25) << "Sense Code: ";
switch((int)sd->senseKey){
switch ((int)sd->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"<<HEX(sd->senseKey)<<")"<<endl;
cerr<<left<<setw(25)<<" ASC:"<<"0x"<<HEX(sd->addSenseCode)<<endl;
cerr<<left<<setw(25)<<" ASCQ:"<<"0x"<<HEX(sd->addSenseCodeQual)<<endl;
if(sd->addSenseLen>0){
cerr<<left<<setw(25)<<" Additional data:"<<"0x";
for(int i=0;i<sd->addSenseLen;i++){
cerr<<HEX(sd->addSenseData[i]);
std::cerr << " (0x" << std::hex << (sd->senseKey) << ")\n";
std::cerr << std::left << std::setw(25) << " ASC:"
<< "0x" << std::hex << (sd->addSenseCode) << "\n";
std::cerr << std::left << std::setw(25) << " ASCQ:"
<< "0x" << std::hex << (sd->addSenseCodeQual) << "\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]);
}
cerr<<endl;
std::cerr << "\n";
}
#ifdef DEBUGSCSI
cerr<<left<<setw(25)<<" Raw Sense:"<<"0x";
char* rawsense=(char*)sd;
std::cerr << std::left << std::setw(25) << " Raw Sense:"
<< "0x";
char *rawsense = (char *)sd;
for(int i=0;i<sizeof(SCSI_PAGE_SENSE);i++){
cerr<<HEX(rawsense[i]);
for (int i = 0; i < sizeof(SCSI_PAGE_SENSE); i++) {
std::cerr << std::hex << (rawsense[i]);
}
cerr<<endl;
std::cerr << "\n";
#endif
}

View File

@@ -15,8 +15,8 @@ GNU General Public License for more details.
#ifndef _SCSIENC_H
#define _SCSIENC_H
#include <string>
#include <bitset>
#include <string>
#include <vector>
#define SSP_KEY_LENGTH 0X20
#define SSP_DESCRIPTOR_LENGTH 1024
@@ -35,315 +35,310 @@ GNU General Public License for more details.
#define RDMC_UNPROTECT 0x02
#define RDMC_DEFAULT 0x00
//outputs hex in a 2 digit pair
#define HEX( x ) right<<setw(2)<< setfill('0') << hex << (int)( x )<<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] ) ))
// outputs hex in a 2 digit pair
#define HEX(x) \
right << setw(2) << setfill('0') << hex << (int)(x) << 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>
#include <sys/machine.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#include <sys/types.h>
#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 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;
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];
unsigned char ASDKCount[2];
unsigned char res_bits_4[8];
} SSP_PAGE_DES; //device encryption status page
} SSP_PAGE_DES; // device encryption status page
typedef struct {
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];
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;
unsigned char compressionStatus : 4;
unsigned char encryptionStatus : 4;
#else
unsigned char encryptionStatus :4;
unsigned char compressionStatus :4;
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;
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;
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
} SSP_PAGE_NBES; // next block encryption status page
typedef struct{
typedef struct {
#if STENC_BIG_ENDIAN == 0
unsigned char peripheralQualifier :3;
unsigned char periphrealDeviceType :5;
unsigned char peripheralQualifier : 3;
unsigned char periphrealDeviceType : 5;
#else
unsigned char periphrealDeviceType :5;
unsigned char peripheralQualifier :3;
unsigned char periphrealDeviceType : 5;
unsigned char peripheralQualifier : 3;
#endif
#if STENC_BIG_ENDIAN == 0
unsigned char RMB :1;
unsigned char res_bits_1 :7;
unsigned char RMB : 1;
unsigned char res_bits_1 : 7;
#else
unsigned char res_bits_1 :7;
unsigned char RMB :1;
unsigned char res_bits_1 : 7;
unsigned char RMB : 1;
#endif
unsigned char Version [1];
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;
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;
unsigned char responseDataFormat : 4;
unsigned char HISUP : 1;
unsigned char NORMACA : 1;
unsigned char obs_bits_1 : 2;
#endif
unsigned char additionalLength [1];
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;
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;
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;
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;
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;
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;
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];
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;
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;
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 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;
unsigned char valid : 1;
unsigned char responseCode : 7;
#else
unsigned char responseCode :7;
unsigned char valid :1;
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;
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;
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 information[4];
unsigned char addSenseLen;
unsigned char cmdSpecificInfo [4];
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
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:
unsigned char field[2]; // field pointer
unsigned char addSenseData[109];
} SCSI_PAGE_SENSE; // sense data response
class KAD_CLASS {
public:
std::vector<SSP_KAD> kads;
protected:
void loadKADs(SSP_PAGE_BUFFER* buffer, int start);
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:
// 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);
SSP_NBES(SSP_PAGE_BUFFER *buffer);
};
//class used to parse data encryption status page
class SSP_DES: public KAD_CLASS{
public:
// 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);
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:
public:
int rdmc;
bool CKOD;
int cryptMode;
@@ -353,12 +348,13 @@ class SCSIEncryptOptions {
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

50
stenc.spec Normal file
View File

@@ -0,0 +1,50 @@
Name: stenc
Version: 1.1.0
Release: 3%{?dist}
Summary: SCSI Tape Encryption Manager
License: GPLv2
URL: https://github.com/scsitape/stenc
Source0: https://github.com/scsitape/stenc/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz
BuildRequires: gcc-c++
BuildRequires: make
BuildRequires: autoconf
BuildRequires: automake
%description
SCSI Tape Encryption Manager - Manages encryption on LTO 4 and newer tape
drives with hardware-based encryption
%prep
%setup -q
%build
./autogen.sh
%configure
make %{?_smp_mflags}
%install
make install DESTDIR=%{buildroot}
%clean
rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
%license COPYING
%doc README.md AUTHORS
%{_bindir}/stenc
%{_mandir}/man1/stenc.1*
%changelog
* Wed Nov 11 2020 Paweł Marciniak <sunwire+repo@gmail.com> - 1.0.8-3
- Remove BuildRoot tag, add smp flags to make and license macro
* Sat Nov 07 2020 Paweł Marciniak <sunwire+repo@gmail.com> - 1.0.8-2
- Make will no longer be in BuildRoot by default
* Sat Jul 4 2020 Paweł Marciniak <sunwire+repo@gmail.com> 1.0.8-1
- Initial SPEC file