88 Commits

Author SHA1 Message Date
Jonas Stein
704b5dd7dd Version bump to 2.0.1 2025-07-24 01:32:28 +02:00
Jonas Stein
1bb64e6408 Fix typo in configure
Superflous ] dropped
2025-07-24 00:47:42 +02:00
Jonas Stein
9a68c885f8 add thanks 2023-05-14 16:27:07 +02:00
Jonas Stein
3ed40cb71d ChangeLog for 2.0.0 2023-05-14 16:19:47 +02:00
Jonas Stein
4b0b7e1575 convert CRLF to LF 2023-05-14 14:29:27 +02:00
Jonas Stein
b853fd604a add version 2.0.0 2023-05-14 14:28:08 +02:00
James Wilson
7943f1860e Update license headers (#112) 2023-05-14 09:02:36 +02:00
James Wilson
57591d01a9 clang-format and include-what-you-use run (#111) 2023-05-02 06:57:47 +02:00
James Wilson
daa541a654 Update status output format (#108)
* Update format of status output

* Add print_buffer and modernize SCSI debug output using std::for_each
2023-05-01 22:48:54 +02:00
James Wilson
7e449bff7b missing verb in man page (#107) 2023-05-01 20:30:19 +02:00
James Wilson
22e21715f2 Remove unneeded STDC header check, reference https://www.gnu.org/software/autoconf/manual/autoconf-2.70/html_node/Default-Includes.html (#106)
remove DEFAULT_ALGORITHM config parameter
2023-05-01 19:32:07 +02:00
Jonas Stein
0e53223fc5 Add .license for CPE xml file 2023-01-17 23:06:06 +01:00
Jonas Stein
9d7b1ed4b8 Drop LGTM Badge 2023-01-17 23:04:50 +01:00
Alvaro Muñoz
965bba59bf Add CodeQL workflow (#103) 2023-01-17 23:01:09 +01:00
Christian Reiss
bfb35cd968 Remove --detail and change repository to https
* Fix: Changed clone url to public, so everyone -not only developers- can
clone.
* Fix: Changed $ stenc -f /dev/nst0 --detail to $ stenc -f /dev/nst0.
"--detail" is an unknown option in the newer versions.
2022-10-21 17:00:58 +02:00
Jonas Stein
c979a3da74 add stenc.xml CPE file 2022-10-18 00:46:29 +02:00
Paweł Marciniak
eb012d9538 Pre-release 2.x.x spec file update (#99)
Co-authored-by: Paweł Marciniak <sunwire+git@gmail.com>
2022-08-27 21:05:15 +02:00
Jonas Stein
31d63481d5 Add remaining SPDX License information (#97)
* Add SPDX License information

Adding license information according to the SPDX stanard.
Used the reuse tool.
Bug: https://github.com/scsitape/stenc/issues/95

* Add SPDX license information to remaining files

- converted AUTHORS to markdown
- added FSFUL license INSTALL.license as it is named in the header of INSTALL

- added SPDX license information for some files such as insignificant-files
  and uncopyrightable files.
  used GPL-2-or-later where possible, because this was the former
  statement of the project and in order to minimize the number of licenses
  used.
  See also https://reuse.software/faq/#uncopyrightable
  and https://reuse.software/tutorial/#insignificant-files
2022-08-25 23:59:52 +02:00
Jonas Stein
8b1756eb89 Add SPDX License information (#96)
Adding license information according to the SPDX stanard.
Used the reuse tool.
Bug: https://github.com/scsitape/stenc/issues/95
2022-08-24 22:41:43 +02:00
Paweł Marciniak
89d354e927 Add #include <limits> (#93)
Co-authored-by: Paweł Marciniak <sunwire+git@gmail.com>
2022-06-26 17:16:45 +02:00
James Wilson
5366997e79 Minor housecleaning: (#91)
- Replace `HEX` macro with inline function
- Replace `atoi` with `strtoul` and validate range of algorithm index
- Add back debug logging of SCSI traffic that got deleted a while ago
    * Remove logging "additional sense bytes" since it was interpreting
      the sense data wrong. Still print out the whole sense result in
      debug mode.
- Fix some compiler warnings
    * replace switch statement with if-else blocks since we don't use
      all the enum values
2022-06-21 07:58:54 +02:00
James Wilson
13af87abaa Fix FreeBSD build issues (#89) 2022-06-18 21:48:53 +02:00
James Wilson
918afb35fb Rewrite man page (#88) 2022-06-16 21:49:36 +02:00
James Wilson
f800dc2f51 Check ENCRYPT_C and DECRYPT_C fields in data encryption capabilities page (#85) 2022-06-06 02:42:59 +02:00
James Wilson
a3d03e5211 Use KAD format field (#86) 2022-06-06 00:40:52 +02:00
Jonas Stein
f77e46eeb0 bash completion in changelog 2022-06-05 16:42:10 +02:00
Paweł Marciniak
e6f7f1b7b3 Add bash completion (#84)
Co-authored-by: Paweł Marciniak <sunwire+git@gmail.com>
2022-06-05 16:41:08 +02:00
James Wilson
b2082bf854 Do validation of options against device capabilities (#83)
* Validate options against device capabilities

* Use std::reference_wrapper instead of raw pointers

* Reword error message

* Also validate --(no-)allow-raw-read against device capabilities

* --ckod should do a media check
2022-06-04 18:37:52 +02:00
James Wilson
23f8d829bf Change command line option processing (#82)
* Changes command line option processing:
  - Use getopt_long in libc and support long options
  - GNU style option processing (don't try to enforce non-conflicting options)
  - GNU style usage message
  - Separate encrypt and decrypt settings
  - --unprotect -> --allow-raw-read, --protect -> --no-allow-raw-read for clarification
  - Change reading key file from stdin using --key-file=-
  - Always print detailed status, remove summary "Drive Encryption" line

* Other formatting and style cleanup

* Test output changes
2022-06-01 00:05:46 +02:00
James Wilson
1200fe92ee Use hardcoded CEEM value instead of configure script parameter (#81)
The default CEEM (check external encryption mode) parameter is undocumented, and default of 0 makes behavior vendor-specific. The standard allows for a drive to report an error when trying to read a block that was pre-encrypted before written to the drive, such as is done with a keyless copy of a tape. This sounds like a very rare scenario to need to support. For the widest compatibility with data sources, this should be set to 1 for general-purpose use.
2022-05-28 11:50:08 +02:00
James Wilson
c6bf88e25f Add James Wilson to AUTHORS (#80) 2022-05-24 17:21:53 +02:00
Jonas Stein
aeab6f03de add author and reformat 2022-05-23 22:29:04 +02:00
James Wilson
490251f101 Fix incorrect radix printing (#78) 2022-05-19 09:08:51 +02:00
James Wilson
d2b7363769 clang-format run (#77)
* pull updated template .clang-format with `clang-format-14 --style=llvm --dump-config`, move to base directory so it is shared between `src` and `tests`
* tweak to match existing style a little (e.g. K&R style for function braces)
* run on all sources
2022-05-18 23:48:31 +02:00
James Wilson
86cca0804c Print algorithm information in detail output (#75)
* Print algorithm information in detail output
* Update documentation with information about algorithm listing
2022-05-18 22:28:37 +02:00
James Wilson
a7a7c4750c Do media checks on getting next block encryption status (#74)
* Do media check before getting NBES and allow getting status without media
* Supress error from BLANK CHECK sense when querying next block encryption status
2022-05-18 22:27:11 +02:00
James Wilson
8caaf85fbb Cleanup & reorganization (#73)
scsi::get_des & others should take a non-const buffer since they modify it
Reorder functions in main.cpp to declare internal functions static
Fix compile error in newer GCC (Compilation error #72) with more explicit cast
Remove some unused constants
Add KAD type enum
Pass key vector by reference instead of copying

Closes: https://github.com/scsitape/stenc/issues/72
2022-05-16 02:05:14 +02:00
James Wilson
f5856d7591 Test for key_from_hex_chars (#70) 2022-05-13 23:17:53 +02:00
James Wilson
eeb7d72686 Introduce portable, endian-clean structures using shifts and masks instead of bitfields (#66)
* Introduce portable, endian-clean structures using shifts and masks instead of bitfields
* Modernize SCSIExecute with RAII and exceptions
* Convert SP-IN calls to use the new portable SCSI structures and functions
* Convert SP-OUT code to use the new portable SCSI structures and functions
* Delete bitfield-based code and remove runtime endian check
Closes: https://github.com/scsitape/stenc/issues/63
2022-05-13 22:43:58 +02:00
James Wilson
1508f432ad Remove getuid root check (#68)
Closes: https://github.com/scsitape/stenc/discussions/64
2022-05-12 06:25:29 +02:00
Jonas Stein
08bd10230f add SCSI-Programming-HOWTO 2022-05-12 00:50:15 +02:00
James Wilson
13cf62cf8b Add unit test coverage of stenc output (#67)
using stream in functions instead of directly writing to cout
2022-05-12 00:40:39 +02:00
James Wilson
8ebccddc50 Small cleanup: (#65)
- pass string arguments by reference
- replace macros with constexpr where possible
- move command strings out of global scope
- use standard library strerror instead of custom printer readIOError
2022-05-10 19:20:55 +02:00
Paweł Marciniak
ebabc39c3e Fix missing manpage header (#62)
Closes: https://github.com/scsitape/stenc/issues/58
Co-authored-by: Paweł Marciniak <sunwire+git@gmail.com>
2022-05-10 00:42:39 +02:00
James Wilson
88975cc9ed Use CAM and the pass(4) device instead of the optional sg(4) device on FreeBSD (#30) 2022-05-09 11:53:49 +02:00
Jonas Stein
8b7e99556a note on drop of AIX support 2022-05-09 11:48:57 +02:00
James Wilson
44603e4884 Remove key generation (#60)
Closes: https://github.com/scsitape/stenc/issues/3
Closes: https://github.com/scsitape/stenc/issues/32
2022-05-09 11:43:59 +02:00
Jonas Stein
859c1a0757 Update ChangeLog 2022-05-09 01:13:37 +02:00
James Wilson
e6ac5fa3f0 Remove AIX support (#59) 2022-05-09 01:11:07 +02:00
James Wilson
f893ee93cc Use standard syslog facilities for logging (#47)
Closes: https://github.com/scsitape/stenc/issues/31
Co-authored-by: Jonas Stein <news@jonasstein.de>
2022-05-09 01:00:18 +02:00
James Wilson
fbba173a1f Remove device renaming and select default device (#48) 2022-05-09 00:52:07 +02:00
Jonas Stein
8078a346d1 Update ChangeLog 2022-05-08 21:39:47 +02:00
James Wilson
13f09ea5aa Remove KeyInfo and use standard library to parse hex strings (#46)
* Remove KeyInfo and use standard library to parse hex strings

* One declaration per line, more useful name of key_from_hex_chars
2022-05-08 21:07:58 +02:00
Jonas Stein
030c674fbc Indent run: 2022-04-30 21:17:37 +02:00
Jonas Stein
1e26d47230 add spaces 2022-04-30 21:12:40 +02:00
Jonas Stein
fe4cf3c00d Remove duplicate line 2022-04-30 20:41:57 +02:00
Paweł Marciniak
c5f8c9e73e Add distclean rule to satisfy distcheck (#53)
* Update c-cpp.yml

* Add distclean rule to satisfy distcheck

* Revert "Update c-cpp.yml"

This reverts commit 6a9628d533.

Co-authored-by: Paweł Marciniak <sunwire+git@gmail.com>
2022-04-30 20:29:16 +02:00
Jonas Stein
41b8baec2a Try to fix CI
Bug: https://github.com/scsitape/stenc/issues/52
2022-04-30 19:41:14 +02:00
Jonas Stein
fb588dda64 Fix version number
Closes: https://github.com/scsitape/stenc/issues/50
2022-04-30 16:38:09 +02:00
Paweł Marciniak
1ece43b1cb Add pandoc to makefile (#51)
* Add check for pandoc
* Generate the man page from reStructuredText
* Install man page after generation by pandoc

Closes: https://github.com/scsitape/stenc/issues/44
Co-authored-by: Paweł Marciniak <sunwire+git@gmail.com>
2022-04-30 16:34:51 +02:00
Jonas Stein
20edbdcb3d Update man
Remove Authors from man. We use now the AUTHORS file as single source.
Bugs go to github.
Compiled now with pandoc.
Closes: https://github.com/scsitape/stenc/issues/45
2022-04-27 15:11:02 +02:00
Jonas Stein
6c7492046b .rst file as source for man page
Added a human readable .rst file to generate man pages with pandoc
Usage:
pandoc --from rst --to man --file stenc.rst -o stenc.1
2022-04-25 21:13:07 +02:00
Jonas Stein
88b0bccea1 Add usage example 2022-04-25 01:32:10 +02:00
Jonas Stein
708932b383 Version bump 1.1.1
Version 1.1.1
2022-04-25 01:14:02 +02:00
Jonas Stein
226c5bcef0 remove duplicate test
Closes: https://github.com/scsitape/stenc/issues/41
2022-04-24 22:00:05 +02:00
Jonas Stein
4a7b143d50 Add tests to README 2022-04-24 21:19:57 +02:00
James Wilson
ff413aac3e Add unit tests and add const 2022-04-24 20:09:08 +02:00
Paweł Marciniak
f1a36eba42 Reintroduce HEX macro as fix
Co-authored-by: Paweł Marciniak <sunwire+git@gmail.com>
2022-04-24 16:35:52 +02:00
Paweł Marciniak
844306dbe4 cast to proper type (#38)
Co-authored-by: Paweł Marciniak <sunwire+git@gmail.com>
2022-04-24 12:52:30 +02:00
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
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
36 changed files with 21188 additions and 2138 deletions

154
.clang-format Normal file
View File

@@ -0,0 +1,154 @@
# SPDX-FileCopyrightText: 2022 stenc authors
#
# SPDX-License-Identifier: CC0-1.0
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveBitFields: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
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
DeriveLineEnding: 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
SortPriority: 0
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
- Regex: '.*'
Priority: 1
SortPriority: 0
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentWidth: 2
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReferenceAlignment: Left
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: c++17
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false
UseTab: Never
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
...

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

@@ -0,0 +1,32 @@
# SPDX-FileCopyrightText: 2022 stenc authors
#
# SPDX-License-Identifier: CC0-1.0
name: C/C++ CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
#install pandoc
- name: Install pandoc package
run: |
sudo apt-get -y install pandoc
- 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

55
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,55 @@
# SPDX-FileCopyrightText: 2022 stenc authors
#
# SPDX-License-Identifier: CC0-1.0
name: "CodeQL"
on:
push:
branches: [ 'master' ]
pull_request:
branches: [ 'master' ]
schedule:
- cron: '4 11 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install pandoc package
run: |
sudo apt-get -y install pandoc
- name: autoconf
run: autoreconf -i
- name: configure
run: ./configure
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
queries: +security-and-quality
- name: make
run: make
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

61
.gitignore vendored
View File

@@ -1,3 +1,10 @@
# SPDX-FileCopyrightText: 2022 stenc authors
#
# SPDX-License-Identifier: CC0-1.0
# Tempfiles
*~
# Prerequisites # Prerequisites
*.d *.d
@@ -16,10 +23,6 @@
*.dylib *.dylib
*.dll *.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries # Compiled Static libraries
*.lai *.lai
*.la *.la
@@ -30,3 +33,53 @@
*.exe *.exe
*.out *.out
*.app *.app
src/stenc
tests/scsi
tests/output
# Other outputs
man/stenc.1
# dist outputs
*.tar.gz
# 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
/config.h.in
/config.log
/config.status
/config.sub
/configure
/configure.scan
/depcomp
/install-sh
/missing
/stamp-h1
/tests/*.log
/tests/*.trs

View File

@@ -1,9 +0,0 @@
stenc AUTHORS
===============================================================================
The authors of stenc are
John Coleman <ninthclowd@user.sourceforge.net>
Samuel Martinez Jr. <sam_martinez_82@hotmail.com>

15
AUTHORS.md Normal file
View File

@@ -0,0 +1,15 @@
<!--
SPDX-FileCopyrightText: 2022 stenc authors
SPDX-License-Identifier: CC0-1.0
-->
stenc AUTHORS
=============
The authors of stenc are
* John Coleman <ninthclowd@user.sourceforge.net>
* Samuel Martinez Jr. <sam_martinez_82@hotmail.com>
* Jonas Stein <news@jonasstein.de>
* James Wilson <jmw@jmw.name>

View File

@@ -1,3 +1,9 @@
<!--
SPDX-FileCopyrightText: 2022 stenc authors
SPDX-License-Identifier: CC0-1.0
-->
The Stenc team is looking forward to your contribution. The Stenc team is looking forward to your contribution.
Please prepare a pull request, or send us your `.patch` file Please prepare a pull request, or send us your `.patch` file
Leave also a note, how you have tested the code. Leave also a note, how you have tested the code.

340
COPYING
View File

@@ -1,340 +0,0 @@
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
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
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
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
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
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
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
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
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
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
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
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
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
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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; either version 2 of the License, or
(at your option) any later version.
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.
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
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
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
Public License instead of this License.

View File

@@ -1,3 +1,29 @@
2025-07-24 Jonas Stein <news@jonasstein.de>
* Version upgraded to 2.0.1
* Fix typo in configure. Superflous ]
2023-05-14 Jonas Stein <news@jonasstein.de>
* Version upgraded to 2.0.0
* define C++17 as minimal C++ version
* build manpage with pandoc
* Add license information according to the SPDX standard
* Dropped AIX support. If you can test and develop code for AIX, please contact us.
* Added bash completion
* New syntax
* Added missing includes
* Special thanks to James Wilson, Paweł Marciniak, Christian Reiss and Alvaro Muñoz
2022-04-25 Jonas Stein <news@jonasstein.de>
* Version upgraded to 1.1.1
* Testframework Catch added
* Fixed bug (mixed HEX macro and std::hex)
* More constants marked with const
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> 2020-06-16 Jonas Stein <news@jonasstein.de>
* Version upgraded to 1.0.8 * Version upgraded to 1.0.8
* Merged patches to fix make files and provide more error messages * Merged patches to fix make files and provide more error messages

3
ChangeLog.license Normal file
View File

@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: 2022 stenc authors
SPDX-License-Identifier: GPL-2.0-or-later

3
INSTALL.license Normal file
View File

@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: 1994 Free Software Foundation, Inc.
SPDX-License-Identifier: CC0-1.0

7
LICENSES/BSL-1.0.txt Normal file
View File

@@ -0,0 +1,7 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following:
The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

121
LICENSES/CC0-1.0.txt Normal file
View File

@@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

View File

@@ -0,0 +1,117 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
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.
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free 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 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 price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any 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.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this 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 themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering 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 void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot 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 may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 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 possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author
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; either version 2 of the License, or (at your option) any later version.
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.
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.
If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker.
signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice

View File

@@ -1,2 +1,6 @@
SUBDIRS = src man # SPDX-FileCopyrightText: 2022 stenc authors
EXTRA_DIST = buildconf #
# SPDX-License-Identifier: CC0-1.0
SUBDIRS = src man tests bash-completion
# EXTRA_DIST = buildconf

View File

@@ -1,17 +1,24 @@
<!--
SPDX-FileCopyrightText: 2022 stenc authors
SPDX-License-Identifier: GPL-2.0-or-later
-->
[![REUSE status](https://api.reuse.software/badge/github.com/scsitape/stenc/)](https://api.reuse.software/info/github.com/scsitape/stenc/)
Stenc Stenc
----- -----
SCSI Tape Encryption Manager - Manages encryption on LTO tape drives (starting with generation 4) with hardware-based encryption. SCSI Tape Encryption Manager - Manages hardware encryption on LTO tape drives (starting with generation 4).
Program should work on any other SCSI security protocol (SSP) capable tape drives. Built specifically for Linux and AIX. Program should work on any other SCSI security protocol (SSP) capable tape drives.
Supports key change auditing and key descriptors (uKAD). Supports key change auditing and key descriptors (uKAD).
Features Features
-------- --------
* SCSI hardware-based encryption management * SCSI hardware-based encryption management
* Supports AIX and Linux * Supports Linux and FreeBSD
* Supports most SSP compliant devices, such as LTO-4 tape drives * Supports most SSP compliant devices, such as LTO-4 tape drives
* Random key generation
* Key change audit logging * Key change audit logging
* AES Encryption * AES Encryption
* Key Descriptor Management * Key Descriptor Management
@@ -20,21 +27,43 @@ Get the source code and compile
------------------------------- -------------------------------
``` ```
git clone git@github.com:scsitape/stenc.git git clone https://github.com/scsitape/stenc.git
cd stenc/ cd stenc/
autoreconf --install autoreconf --install
./configure ./autogen.sh && ./configure
make check # optionally run the catch testing framework
make make
``` ```
Usage example
-------------
```
$ stenc -f /dev/nst0
Status for /dev/nst0 (TANDBERG LTO-6 HH 3579)
--------------------------------------------------
Reading: Decrypting (AES-256-GCM-128)
Writing: Encrypting (AES-256-GCM-128)
Protecting from raw read
Key instance counter: 1
Drive key desc. (U-KAD): mykey20170113
Supported algorithms:
1 AES-256-GCM-128
Key descriptors allowed, maximum 32 bytes
Raw decryption mode allowed, raw read enabled by default
```
Linux Packages Linux Packages
-------------- --------------
[![Packaging status](https://repology.org/badge/vertical-allrepos/stenc.svg)](https://repology.org/metapackage/stenc) [![Packaging status](https://repology.org/badge/vertical-allrepos/stenc.svg)](https://repology.org/metapackage/stenc)
Requirements
------------
AIX support was suspended on 2022-05-08 until we have contributors who can develop and test the code on AIX.
License License
------- -------
Program copyright 2012-2018 contributing authors. Program copyright 2012-2022 contributing authors.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@@ -45,3 +74,13 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. 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
SCSI-Programming-HOWTO
https://tldp.org/HOWTO/archived/SCSI-Programming-HOWTO/SCSI-Programming-HOWTO-9.html

View File

@@ -1,2 +1,7 @@
#/usr/bin/env sh #!/bin/sh
# SPDX-FileCopyrightText: 2022 stenc authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
autoreconf --install || exit 1 autoreconf --install || exit 1

View File

@@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: 2022 stenc authors
#
# SPDX-License-Identifier: CC0-1.0
if ENABLE_BASH_COMPLETION
bashcompletiondir = $(BASH_COMPLETION_DIR)
dist_bashcompletion_DATA = stenc
endif

49
bash-completion/stenc Normal file
View File

@@ -0,0 +1,49 @@
#/usr/bin/env bash
# SPDX-FileCopyrightText: 2022 stenc authors
# SPDX-License-Identifier: GPL-2.0-or-later
#stenc bash completion
_stenc () {
local cur prev words cword
_init_completion || return
COMPREPLY=()
case $prev in
--version )
return
;;
-f )
#list tape devices
if [[ $(uname) == Linux ]]; then
for tape in /sys/class/scsi_tape/*;
do devs+="/dev/${tape##*/} ";
done;
COMPREPLY=($(compgen -W "$devs" -- "$cur"))
else
_filedir
fi
return
;;
-e | --encrypt )
COMPREPLY=($(compgen -W 'off on' -- "$cur"))
return
;;
-d | --decrypt )
COMPREPLY=($(compgen -W 'off on mixed' -- "$cur"))
return
;;
-k | --key-file )
_filedir
return
;;
esac
if [[ $cur == -* ]]; then
COMPREPLY=($(compgen -W '-f --file -e --encrypt -d --decrypt -k --key-file -a --algorithm --allow-raw-read --no-allow-raw-read --ckod -h --help --version' -- "$cur"))
return
fi
}
complete -F _stenc stenc

View File

@@ -1,17 +1,16 @@
AC_INIT([stenc], [1.0.8]) # SPDX-FileCopyrightText: 2022 stenc authors
# SPDX-License-Identifier: GPL-2.0-or-later
AC_INIT([stenc],[2.0.1])
AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_SRCDIR([src/main.cpp])
AM_INIT_AUTOMAKE([foreign]) AM_INIT_AUTOMAKE([foreign subdir-objects])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CHECK_HEADER([sys/types.h]) AC_CHECK_HEADERS
AC_CHECK_HEADER([sys/machine.h]) AC_CHECK_HEADERS([arpa/inet.h netinet/in.h])
# Checks for programs # Checks for programs
AC_PROG_CXX AC_PROG_CXX
# Checks for header files.
AC_HEADER_STDC
AC_MSG_CHECKING(whether to output raw SCSI messages) AC_MSG_CHECKING(whether to output raw SCSI messages)
AC_ARG_WITH([scsi-debug], AC_ARG_WITH([scsi-debug],
[AS_HELP_STRING([--with-scsi-debug],[enable scsi communication debug])], [AS_HELP_STRING([--with-scsi-debug],[enable scsi communication debug])],
@@ -19,29 +18,6 @@ AC_ARG_WITH([scsi-debug],
AC_MSG_RESULT(yes)], AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)]) [AC_MSG_RESULT(no)])
AC_MSG_CHECKING(max tape read blocks for volume status)
AC_ARG_WITH([max-tape-read-blocks],
[AS_HELP_STRING([--with-max-tape-read-blocks=<number>],[how many blocks the tape drive will seek to determine the encryption status on the volume. Defaults to 100])],
[AC_DEFINE_UNQUOTED([MAX_TAPE_READ_BLOCKS],$withval,"") AC_MSG_RESULT($withval)],
[AC_DEFINE([MAX_TAPE_READ_BLOCKS],100,"") AC_MSG_RESULT(100)])
AC_MSG_CHECKING(default encryption algorithm index to use)
AC_ARG_WITH([default-algorithm],
[AS_HELP_STRING([--with-default-algorithm=<number>],[the default algorithm index to set for encryption. Defaults to 0])],
[AC_DEFINE_UNQUOTED([DEFAULT_ALGORITHM],$withval,"") AC_MSG_RESULT($withval)],
[AC_DEFINE([DEFAULT_ALGORITHM],0,"") AC_MSG_RESULT(0)])
AC_MSG_CHECKING(default CEEM flag to use)
AC_ARG_WITH([default-ceem],
[AS_HELP_STRING([--with-default-ceem=<number>],[the default CEEM flag when setting options. Defaults to 0])],
[AC_DEFINE_UNQUOTED([DEFAULT_CEEM],$withval,"") AC_MSG_RESULT($withval)],
[AC_DEFINE([DEFAULT_CEEM],0,"") AC_MSG_RESULT(0)])
AC_MSG_CHECKING(default key size to use)
AC_ARG_WITH([default-key-size],
[AS_HELP_STRING([--with-default-key-size=<bytes>],[the default key size for your drive. Only used when turning off encryption. Defaults to 32 (256 bit)])],
[AC_DEFINE_UNQUOTED([DEFAULT_KEYSIZE],$withval,"") AC_MSG_RESULT($withval)],
[AC_DEFINE([DEFAULT_KEYSIZE],32,"") AC_MSG_RESULT(32)])
AC_MSG_CHECKING(your OS) AC_MSG_CHECKING(your OS)
system=`uname` system=`uname`
case $system in case $system in
@@ -53,10 +29,6 @@ case $system in
AC_DEFINE(OS_FREEBSD,1,"") AC_DEFINE(OS_FREEBSD,1,"")
AC_MSG_RESULT(FreeBSD) AC_MSG_RESULT(FreeBSD)
;; ;;
AIX)
AC_DEFINE(OS_AIX,1,"")
AC_MSG_RESULT(AIX)
;;
*) *)
AC_MSG_ERROR(unknown OS type: $system) AC_MSG_ERROR(unknown OS type: $system)
;; ;;
@@ -67,31 +39,28 @@ AC_ARG_WITH([static-libgcc],
[AS_HELP_STRING([--with-static-libgcc],[build with static libgcc library])], [AS_HELP_STRING([--with-static-libgcc],[build with static libgcc library])],
[ [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
if test "${system}" = "AIX"; then LDFLAGS="${LDFLAGS} -static-libgcc -Wl,-static -lstdc++ -lsupc++"
LDFLAGS="${LDFLAGS} -static-libgcc -Wl,-bstatic -lstdc++ -Wl,-bdynamic -lsupc++"
else
LDFLAGS="${LDFLAGS} -static-libgcc -Wl,-static -lstdc++ -lsupc++"
fi
], ],
[AC_MSG_RESULT(no)]) [AC_MSG_RESULT(no)])
AC_CHECK_PROG(PANDOC, [pandoc], [yes])
AM_CONDITIONAL([FOUND_PANDOC], [test "x$PANDOC" = xyes])
AM_COND_IF([FOUND_PANDOC],,[AC_MSG_ERROR([required program 'pandoc' not found.])])
AC_MSG_CHECKING(whether to convert rewinding device names to non-rewinding device names) if test "${system}" = "FreeBSD"; then
AC_ARG_ENABLE([device-name-conversion], LIBS="${LIBS} -lcam"
[AS_HELP_STRING([--enable-device-name-conversion],[converts /dev/st* to /dev/st*.1 and /dev/rmt* to /dev/rmt*.1 to prevent rewinds. Enabled by default.])],
[enable_dnc=$enableval],
[enable_dnc="yes"]
)
if test "$enable_dnc" = "yes"; then
AC_MSG_RESULT(yes)
else
AC_DEFINE(DISABLE_DEVICE_NAME_CONVERSION,1,"")
AC_MSG_RESULT(no)
fi fi
# BASH completion
PKG_CHECK_VAR([BASH_COMPLETION_DIR], [bash-completion >= 2.0], [completionsdir],
[
with_bash_completion_dir=yes;
AC_MSG_NOTICE(BASH_COMPLETION_DIR is $BASH_COMPLETION_DIR);
AC_SUBST([BASH_COMPLETION_DIR])
],
[with_bash_completion_dir=no])
AC_OUTPUT(Makefile src/Makefile man/Makefile) AM_CONDITIONAL([ENABLE_BASH_COMPLETION],[test "x$with_bash_completion_dir" != "xno"])
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile tests/Makefile bash-completion/Makefile])
AC_OUTPUT

View File

@@ -1 +1,19 @@
dist_man_MANS = stenc.1 # SPDX-FileCopyrightText: 2022 stenc authors
#
# SPDX-License-Identifier: CC0-1.0
man1_MANS = stenc.1
EXTRA_DIST = stenc.rst
all: stenc.1
stenc.1: stenc.rst
pandoc --standalone --to man $? -o $@
clean:
rm -f stenc.1
distclean: clean
rm -f Makefile

View File

@@ -1,128 +0,0 @@
.TH STENC 1
.SH NAME
stenc - SCSI Tape Hardware Encryption Manager
.SH SYNOPSIS
\fBstenc\fR \fB\-g\fR \fIlength\fR \fB\-k\fR \fIfile\fR [\fB\-kd\fR \fIdescription\fR]
.br
\fBstenc\fR \fB\-f\fR \fIdevice\fR [\fB\-\-detail\fR]
.br
\fBstenc\fR \fB\-f\fR \fIdevice\fR \fB\-e\fR \fBon\fR|\fBmixed\fR|\fBrawread\fR [\fB\-a\fR \fIindex\fR] [\fB\-k\fR \fIfile\fR] [\fB\-\-ckod\fR] [\fB\-\-protect\fR | \fB\-\-unprotect\fR]
.br
\fBstenc\fR \fB\-f\fR \fIdevice\fR \fB\-e\fR \fBoff\fR [\fB\-a\fR \fIindex\fR] [\fB\-\-ckod\fR] [\fB\-\-protect\fR | \fB\-\-unprotect\fR]
.br
\fBstenc\fR \fB\-\-version\fR
.SH AVAILABILITY
Linux, AIX
.SH DESCRIPTION
Allows you to manage hardware encryption on SSP enabled tape devices (LTO4, LTO5, etc).
.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.
.TP
\fB\-f\fR \fIdevice\fR
Specifies the device to use (i.e. \fI/dev/nst0, /dev/rmt0.1, /dev/sg0\fR). Use the \fBlsscsi\fR command to determine the appropriate device to use. You should always use a device name that does not rewind (i.e. use /dev/nst0 instead of /dev/st0, /dev/rmt0.1 instead of /dev/rmt0). Use commands like 'cat /proc/scsi/scsi', 'lsscsi', and 'lsdev' to determine the proper device to use. On some distros, a /dev/sg device must be used instead of a /dev/st device.
If this is the only option specified, the status of the device will be displayed. To retrieve more detailed status information, add \fB\-\-detail\fR. If you are root and the status command fails, either the \fIdevice\fR is incorrect (try another link to the device: \fI/dev/rmt0.1\fR, \fI/dev/nst0\fR, \fI/dev/tape\fR, etc.), a tape may not be in the drive, you may be using the wrong algorithm for the tape drive (see the \fB\-a\fR option), or the device does not support SCSI Security Protocol. \fBstenc\fR may read up to 100 blocks of the tape, starting at the current position, in order to determine if the volume has been encrypted. For this reason, you should not run the status command while another process is accessing the drive. If the device returns \fIUnable to determine\fR for the volume encryption status, you may need to move to a section of the tape that contains data (i.e. \fBmt -f <device> fsr <count>\fR) or rewind the tape in order for \fBstenc\fR to output the volume status.
.TP
\fB\-e\fR \fBon\fR | \fBmixed\fR | \fBrawread\fR | \fBoff\fR
Sets the encryption mode for the device specified with \fB\-f\fR option. Successful operations of this type will create an audit entry in the \fI/var/log/stenc\fR file. If \fBoff\fR is not specified and the \fB\-k\fR option is not specified, the program will require the user to enter a hexadecimal key (see \fIKEY INPUT SYNTAX\fR) and an optional key description (see \fIKEY DESCRIPTORS\fR).
\fBon\fR - The drive will encrypt all data sent to it and will only output data it is able to decrypt, ignoring unencrypted data on the drive.
\fBmixed\fR - The drive will encrypt all data sent to it and will output both encrypted data and unencrypted data, providing the drive is able to do so.
\fBrawread\fR - The drive will encrypt all data sent to it and will output unencrypted data and raw encrypted data. You will probably need to have specified \fB\-\-unprotect\fR when the data was written in order to read it with this option. Some drives do not support this option. See the \fB\-\-protect\fR option.
\fBoff\fR - The drive will neither encrypt data sent to it, or decrypt encrypted data found on the drive. If this command fails you may have switch your algorithm or specify a different default key size when you configure the program
\fBWARNING:\fR The SCSI device will revert all encryption settings if the tape device is power cycled (if the tape drive is extenal, it may keep the settings even if the system is rebooted). You can modify you local startup script (/etc/rc.local, /etc/rc, etc.) to set encryption at reboot if need be. If you do this, you will need to use the \fB\-k\fR option to prevent the system from waiting on the local console user to enter the encryption key.
.TP
\fB\-a\fR \fIindex\fR
Only valid when setting encryption (see the \fB\-e\fR option). Specifies the algorithm index to use for the device (defaults to 0, which can be changed using the --with-default-algorithm configure option). Setting encryption on/off may fail on some devices if this is not the correct algorithm for the drive (i.e. HP drives use an algorithm index of 1).
.TP
\fB\-\-ckod\fR
Only valid when setting encryption (see the \fB\-e\fR option). Instructs the drive to clear its encryption keys when the volume is unmounted instead of keeping it until the drive is power cycled. Some devices may not support this option.
.TP
\fB\-\-protect\fR | \fB\-\-unprotect\fR
Only valid when setting encryption (see the \fB\-e\fR option). Instructs the drive to \fBprotect\fR or \fBunprotect\fR any encrypted data from being raw read. See the \fB\-e rawread\fR option. Some devices may not support these options.
.TP
\fB\-k\fR \fIfile\fR
Only valid when turning encryption on (see the \fB\-e\fR option) or generating a new key (see the \fB\-g\fR option). When turning encryption on, this specifies the location of a key file previously generated with the \fB\-g\fR option. When generating a new key with the \fB\-g\fR option, this specifies the key file that the new key will be saved into. Key files should be owned by root ('\fBchown root\fR') and only readable by root ('\fBchmod 600\fR'). \fBstenc\fR automatically chmods key files generated with the \fB\-g\fR option.
.SH KEY INPUT SYNTAX
.TP
All keys should be a maximum of 256 bits (32 bytes). \fBstenc\fR requires that all keys are entered using 2 digit hexadecimal bytes, with no delimiters in between bytes. Do not precede your key input with '0x'. If you try to use a key size that the drive does not support, the command will error. When using a key file, the second line in the file can contain an optional key description that will be displayed with the device status (see the \fB\-f\fR option).
.TP
\fBExample 128 bit Key:\fR
000102030405060708090a0b0c0d0e0f
.TP
\fBExample 256 bit Key:\fR
000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
.SH EXAMPLE
.TP
\fBstenc -g 256 -k /etc/tape.key -kd "September Tape Key"\fR
Generate a random 256 bit key file with the description "September Tape Key" and save it into /etc/tape.key
.TP
\fBstenc -f /dev/st0 -e on -k /etc/stenc.key\fR
Turns on encryption on /dev/st0 using the key contained in /etc/stenc.key
.TP
\fBstenc -f /dev/st0 -e on\fR
Asks user to input a key in hexadecimal format and then turns on encryption for /dev/st0 using that key
.TP
\fBstenc -f /dev/st0 -e off\fR
Turns off encryption for /dev/st0
.TP
\fBstenc -f /dev/st0 --detail\fR
Outputs the detailed encryption status of /dev/st0
.TP
\fBtail /var/log/stenc\fR
Lists the last few key change audit entries
.SH KEY CHANGE AUDITING
Each time a key is changed using this program, a corresponding entry will be entered into the \fI/var/log/stenc\fR file. These entries will have an \fIKey Instance Counter\fR corresponding to the counter listed in the device status (see the \fB\-f\fR option). Each time the key is set, a checksum of that key (or a key description) is also listed in this file. This allows you to know when keys were changed and if the key you are using is the same as a prior key. If an unauthorized party would compromise this log file, your key security would be decreased if checksums were present in the log. To prevent this, you should use key descriptors instead of checksums (see \fIKEY DESCRIPTORS\fR).
.SH KEY DESCRIPTORS
Key descriptors are set when using the \fB\-g\fR option or the \fB\-e\fR option. They will be displayed when retrieving the drive status (see the \fB\-f\fR option). These descriptors will be written to the volume, so they should NEVER contain information that would reduce the security of the key (i.e. a checksum, bitlength, algorithm, a portion of the key). If \fBstenc\fR detects that the volume is encrypted but it cannot decrypt the data, the key descriptor on the volume will be displayed as part of the device status. This can be useful for determining which key goes to which volume.
.SH AUTHOR
Written by \fBJohn Coleman\fR and \fBSamuel Martinez Jr.\fR of SunWest Educational Credit Union.
.SH REPORTING BUGS
Report \fBstenc\fR bugs to \fIjcoleman1981@live.com\fR.
.SH PROJECT UPDATES
Visit \fBhttp://sourceforge.net/projects/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.
.SH SEE ALSO
\fBmt\fR(1L)
.br
\fBlsscsi\fR(8)

207
man/stenc.rst Normal file
View File

@@ -0,0 +1,207 @@
.. SPDX-FileCopyrightText: 2022 stenc authors
..
.. SPDX-License-Identifier: GPL-2.0-or-later
=================================
STENC(1) |General Commands Manual
=================================
NAME
====
stenc - SCSI Tape Hardware Encryption Manager
SYNOPSIS
========
| **stenc** [**-f** *DEVICE*]
| **stenc** [**-f** *DEVICE*] [**-e** *ENC-MODE*] [**-d** *DEC-MODE*] [*OPTIONS*]
DESCRIPTION
===========
**stenc** manages hardware data encryption on tape devices that support
the SCSI security protocol.
Controlling device encryption
-----------------------------
The encryption mode (what happens to data written to the
device), and decryption mode (what happens to data read from the device)
can be controlled independently. If only one of the following options is
given, the other mode will be inferred to set the encryption and decryption
modes in tandem.
**-e, --encrypt**=\ *ENC-MODE*
Sets the encryption mode. *ENC-MODE* is either *off* or *on*.
**off**
Data written to the device will be not encrypted.
**on**
Data written to the device will be encrypted.
**-d, --decrypt**=\ *DEC-MODE*
Sets the decryption mode. *DEC-MODE* is either *off*, *on*, or *mixed*.
**off**
Data read from the device will not be decrypted and only unencrypted
tape blocks can be read.
**on**
Data read from the device will be decrypted and only encrypted tape blocks can
be read. The drive will only read data it is able to decrypt, and will not
read unencrypted data on the drive.
**mixed**
Data read from the device will be decrypted, if needed. Both encrypted and
unencrypted tape blocks can be read. The drive will read both encrypted
data and unencrypted data, provided the drive is able to do so.
Viewing device status
---------------------
When neither options to set encryption or decryption mode are given, **stenc**
prints the encryption settings, the encryption status of the current block,
and capabilities of the device, including a list of supported algorithm indexes.
The device may display current block encryption status as *Unable to determine*
if the tape is positioned at a filemark or end of tape, in which case it may be
necessary to move the tape position using **mt**\ (1).
OPTIONS
=======
**-f, --file**=\ *DEVICE*
Specifies the device to use (e.g. */dev/nst0*, */dev/nsa0*, */dev/rmt0.1*).
Use the **lsscsi**\ (8) command on Linux, or **camcontrol**\ (8) on FreeBSD
to determine the appropriate device to use. It is recommended to the use a
non-rewinding device (i.e. */dev/nst0* instead of */dev/st0*, */dev/rmt0.1*
instead of */dev/rmt0*). Typically, only the superuser can access tape
devices.
If this option is omitted, and the environment variable **TAPE** is
set, it is used. Otherwise, a default device defined in the system header
*mtio.h* is used.
**-a, --algorithm**=\ *index*
Selects the encryption algorithm to use for the device.
Changing encryption settings may fail on some devices if this is not a
supported algorithm for the drive (e.g. HP drives use an algorithm
index of 1). A list of supported algorithms can be obtained by requesting
device status. If the device only
supports one algorithm, this option may be omitted and **stenc** will use
the only choice. Otherwise **stenc** will print the list of supported algorithms
and exit if this option is omitted.
**-k, --key-file**=\ *FILE* \| *-*
Read the encryption key and optional key descriptor from *FILE*, or
standard input when *FILE* is *-*. If standard input is a terminal,
this will prompt for the key and optional key
descriptor. This option is required when *ENC-MODE* and *DEC-MODE*
are not both *off*. See *KEY INPUT SYNTAX* for the expected format of the
key file.
**--ckod**
Clear key on demount. Instructs the device to clear its encryption keys when
the tape is unloaded instead of keeping it until the drive is power cycled.
This option may only be given if tape media is presently loaded in the
device. Some devices may not support this option.
**--allow-raw-read** \| **--no-allow-raw-read**
Instructs the device to mark encrypted blocks written to the tape to allow
(or disallow) subsequent raw mode reads. If neither option is given, the
device default is used, which can be found by requesting the device status.
Some devices may not support these options.
**-h, --help**
Print a usage message and exit.
**--version**
Print version information and exit.
KEY INPUT SYNTAX
================
**stenc** requires that all keys are entered as text hexadecimal strings,
with no delimiters in between bytes. Do not precede your key input with *0x*.
When using a key file, the second line in the file can contain an optional
key descriptor that will be displayed with the device status (see
*KEY DESCRIPTORS*).
Keys can be generated using any cryptographically secure entropy source,
such as the **random**\ (4) device or the **openssl**\ (1SSL) suite of commands.
A 256-bit key file can be created with the following command:
openssl rand -hex 32
**Example 128 bit key:**
000102030405060708090a0b0c0d0e0f
**Example 256 bit key:**
000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
**Example 256 key file with key descriptor:**
| 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
| April backup key
KEY DESCRIPTORS
===============
A key file (see *KEY INPUT SYNTAX*) can optionally include a key descriptor.
The descriptor will be written with each tape block, and will be displayed
when retrieving the drive status, so it should *never* contain information
that would reduce the security of the key (i.e. a checksum or any portion of
the key). If **stenc** detects a tape block is encrypted but it cannot decrypt
the data, the key descriptor of the current block, if any, will be displayed
as part of the device status. This can be useful for determining which key
is used.
KEY CHANGE AUDITING
===================
Each time device encryption settings are changed, **stenc** will write an
entry to the system log. These entries will have a *Key Instance Counter*
corresponding to the counter listed in the device status. Each time the key
is set, the key descriptor, if any, is also written to the log. This allows
you to know when keys were changed and if the key you are using is the same
as a prior key.
EXAMPLE
=======
**stenc -f /dev/nst0 -e on -d on -k /etc/stenc.key**
Turns on encryption and decryption for */dev/nst0* using the key
in */etc/stenc.key*
**stenc -f /dev/nst0 -e on -d mixed -k -**
Asks user to input a key in hexadecimal format and then turns on
encryption, with mixed decryption mode, for */dev/nst0*
**stenc -f /dev/nst0 -e off -d off**
Turns off encryption and decryption for */dev/nst0*
**stenc -f /dev/nst0**
Prints the encryption status of */dev/nst0*
BUGS
====
Report bugs to **https://github.com/scsitape/stenc/issues**
COPYRIGHT
=========
Copyright 2012-2022 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.
SEE ALSO
========
| **openssl**\ (1SSL)
| **mt**\ (1)
| **lsscsi**\ (8)

View File

@@ -1,4 +1,8 @@
# SPDX-FileCopyrightText: 2022 stenc authors
#
# SPDX-License-Identifier: CC0-1.0
bin_PROGRAMS = stenc bin_PROGRAMS = stenc
AM_CXXFLAGS = $(INTI_CFLAGS) $(DEPS_CFLAGS) AM_CXXFLAGS = -std=c++17 $(INTI_CFLAGS) $(DEPS_CFLAGS)
stenc_SOURCES = main.cpp scsiencrypt.cpp scsiencrypt.h keyinfo.h keyinfo.cpp stenc_SOURCES = main.cpp scsiencrypt.cpp scsiencrypt.h
#stenc_LDADD = $(INTI_LIBS) #stenc_LDADD = $(INTI_LIBS)

View File

@@ -1,123 +0,0 @@
#include <config.h>
#include <iostream>
#include <string.h>
#include <string>
#include <sstream>
#include "keyinfo.h"
#include "scsiencrypt.h"
using namespace std;
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;
return;
}
//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':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
break;
default:
cout<<"Invalid character '"<<hexinput.at(i)<<"' found in key!"<<endl;
valid=false;
return;
}
}
// delete the key if its already allocated
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;
return;
}
//convert the hex input to a char*
loadKey(hexinput);
//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;
return;
}
cout<<"Provided key length is "<<(keySize*8)<<" bits."<<endl;
cout<<"Key checksum is "<<check<<"."<<endl;
}
void Keyinfo::loadCheck() {
int i;
int chk = 0;
for (i = 0; i<keySize;i++) {
chk += ((int)key[i]) * (i + 1);
}
stringstream retval;
retval<<hex<<chk;
check=retval.str();
}
Keyinfo::~Keyinfo(){
delete key;
}
void Keyinfo::loadKey(string str)
{
int length = str.size();
// make sure the input string has an even digit numbers
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;
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;
}
}

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,7 @@
// SPDX-FileCopyrightText: 2022 stenc authors
//
// SPDX-License-Identifier: GPL-2.0-or-later
/* /*
Header file to send and recieve SPIN/SPOUT commands to SCSI device Header file to send and recieve SPIN/SPOUT commands to SCSI device
@@ -15,350 +19,424 @@ GNU General Public License for more details.
#ifndef _SCSIENC_H #ifndef _SCSIENC_H
#define _SCSIENC_H #define _SCSIENC_H
#include <config.h>
#include <array>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <ostream>
#include <string> #include <string>
#include <bitset>
#include <vector> #include <vector>
#define SSP_KEY_LENGTH 0X20 #include <stdexcept>
#define SSP_DESCRIPTOR_LENGTH 1024 #include <utility>
#define SSP_PAGE_DES_LENGTH 24
#define SSP_PAGE_NBES_LENGTH 16
#define SSP_KAD_HEAD_LENGTH 4
#define SSP_PAGE_ALLOCATION 8192
#define SSP_UKAD_LENGTH 0x1e
#define KAD_TYPE_UKAD 0x00 #if HAVE_ARPA_INET_H
#define KAD_TYPE_AKAD 0x01 #include <arpa/inet.h>
#define KAD_TYPE_NONCE 0x02 #endif
#define KAD_TYPE_META 0x03 #if HAVE_NETINET_IN_H
#include <netinet/in.h>
#define RDMC_PROTECT 0x03
#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] ) ))
#ifdef HAVE_SYS_MACHINE_H
#include <sys/machine.h>
#endif #endif
#ifdef HAVE_SYS_TYPES_H namespace scsi {
#include <sys/types.h>
#endif
#ifdef BYTE_ORDER enum class encrypt_mode : std::uint8_t {
#define STENC_BYTE_ORDER BYTE_ORDER off = 0u,
#endif external = 1u,
#ifndef STENC_BYTE_ORDER on = 2u,
#ifdef __BYTE_ORDER
#define STENC_BYTE_ORDER __BYTE_ORDER
#endif
#endif
#ifdef 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
#endif
#if STENC_BYTE_ORDER == STENC_TYPE_BIG_ENDIAN
#define STENC_BIG_ENDIAN 1
#else
#define STENC_BIG_ENDIAN 0
#endif
typedef struct {
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;
#else
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];
#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;
#else
unsigned char RDMD :1;
unsigned char CEEMS :2;
unsigned char VCELB :1;
unsigned char parametersControl :3;
unsigned char res_bits_2 :1;
#endif
unsigned char res_bits_3;
unsigned char ASDKCount [2];
unsigned char res_bits_4 [8];
} SSP_PAGE_DES; //device encryption status page
typedef struct {
unsigned char type;
#if STENC_BIG_ENDIAN == 1
unsigned char res_bits_1 :5;
unsigned char authenticated :3;
#else
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
} 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 log_obj_num [8];
#if STENC_BIG_ENDIAN == 1
unsigned char compressionStatus :4;
unsigned char encryptionStatus :4;
#else
unsigned char encryptionStatus :4;
unsigned char compressionStatus :4;
#endif
unsigned char algorithmIndex;
#if STENC_BIG_ENDIAN == 1
unsigned char res_bits_1 :6;
unsigned char EMES :1;
unsigned char RDMDS :1;
#else
unsigned char RDMDS :1;
unsigned char EMES :1;
unsigned char res_bits_1 :6;
#endif
unsigned char res_bits_2;
} SSP_PAGE_NBES; //next block encryption status page
typedef struct{
#if STENC_BIG_ENDIAN == 0
unsigned char peripheralQualifier :3;
unsigned char periphrealDeviceType :5;
#else
unsigned char periphrealDeviceType :5;
unsigned char peripheralQualifier :3;
#endif
#if STENC_BIG_ENDIAN == 0
unsigned char RMB :1;
unsigned char res_bits_1 :7;
#else
unsigned char res_bits_1 :7;
unsigned char RMB :1;
#endif
unsigned char Version [1];
#if STENC_BIG_ENDIAN == 0
unsigned char obs_bits_1 :2;
unsigned char NORMACA :1;
unsigned char HISUP :1;
unsigned char responseDataFormat :4;
#else
unsigned char responseDataFormat :4;
unsigned char HISUP :1;
unsigned char NORMACA :1;
unsigned char obs_bits_1 :2;
#endif
unsigned char additionalLength [1];
#if STENC_BIG_ENDIAN == 0
unsigned char SCCS :1;
unsigned char ACC :1;
unsigned char TPGS :2;
unsigned char threePC :1;
unsigned char res_bits_2 :2;
unsigned char protect :1;
#else
unsigned char protect :1;
unsigned char res_bits_2 :2;
unsigned char threePC :1;
unsigned char TPGS :2;
unsigned char ACC :1;
unsigned char SCCS :1;
#endif
#if STENC_BIG_ENDIAN == 0
unsigned char obs_bits_2 :1;
unsigned char ENCSERV :1;
unsigned char VS :1;
unsigned char MULTIP :1;
unsigned char MCHNGR :1;
unsigned char obs_bits_3 :2;
unsigned char ADDR16 :1;
#else
unsigned char ADDR16 :1;
unsigned char obs_bits_3 :2;
unsigned char MCHNGR :1;
unsigned char MULTIP :1;
unsigned char VS :1;
unsigned char ENCSERV :1;
unsigned char obs_bits_2 :1;
#endif
#if STENC_BIG_ENDIAN == 0
unsigned char obs_bits_4 :2;
unsigned char WBUS16 :1;
unsigned char SYNC :1;
unsigned char obs_bits_5 :2;
unsigned char CMDQUE :1;
unsigned char VS2 :1;
#else
unsigned char VS2 :1;
unsigned char CMDQUE :1;
unsigned char obs_bits_5 :2;
unsigned char SYNC :1;
unsigned char WBUS16 :1;
unsigned char obs_bits_4 :2;
#endif
unsigned char vender [8];
unsigned char productID [16];
unsigned char productRev [4];
unsigned char SN [7];
unsigned char venderUnique [12];
#if STENC_BIG_ENDIAN == 0
unsigned char res_bits_3 :4;
unsigned char CLOCKING :2;
unsigned char QAS :1;
unsigned char IUS :1;
#else
unsigned char IUS :1;
unsigned char QAS :1;
unsigned char CLOCKING :2;
unsigned char res_bits_3 :4;
#endif
unsigned char res_bits_4 [1];
unsigned char versionDescriptor [16];
unsigned char res_bits_5 [22];
unsigned char copyright [1];
} SCSI_PAGE_INQ; //device inquiry response
typedef struct{
#if STENC_BIG_ENDIAN == 1
unsigned char valid :1;
unsigned char responseCode :7;
#else
unsigned char responseCode :7;
unsigned char valid :1;
#endif
unsigned char res_bits_1;
#if STENC_BIG_ENDIAN == 1
unsigned char filemark :1;
unsigned char EOM :1;
unsigned char ILI :1;
unsigned char res_bits_2 :1;
unsigned char senseKey :4;
#else
unsigned char senseKey :4;
unsigned char res_bits_2 :1;
unsigned char ILI :1;
unsigned char EOM :1;
unsigned char filemark :1;
#endif
unsigned char information [4];
unsigned char addSenseLen;
unsigned char cmdSpecificInfo [4];
unsigned char addSenseCode;
unsigned char addSenseCodeQual;
unsigned char fieldRepUnitCode;
#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;
#else
unsigned char SKSV :1;
unsigned char cd :1; // control/data
unsigned char resvd2 :2; // reserved
unsigned char bpv :1; // bit pointer valid
unsigned char sim :3; // system information message
#endif
unsigned char field [2]; // field pointer
unsigned char addSenseData [109];
} SCSI_PAGE_SENSE; //sense data response
class KAD_CLASS{
public:
std::vector<SSP_KAD> kads;
protected:
void loadKADs(SSP_PAGE_BUFFER* buffer, int start);
}; };
inline std::ostream& operator<<(std::ostream& os, encrypt_mode m)
{
if (m == encrypt_mode::off) {
os << "off";
} else if (m == encrypt_mode::external) {
os << "external";
} else {
os << "on";
}
return os;
}
//class used to parse next block encryption status page enum class decrypt_mode : std::uint8_t {
class SSP_NBES: public KAD_CLASS{ off = 0u,
public: raw = 1u,
SSP_PAGE_NBES nbes; on = 2u,
SSP_NBES(SSP_PAGE_BUFFER* buffer); mixed = 3u,
};
//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);
}; };
inline std::ostream& operator<<(std::ostream& os, decrypt_mode m)
{
if (m == decrypt_mode::off) {
os << "off";
} else if (m == decrypt_mode::raw) {
os << "raw";
} else if (m == decrypt_mode::on) {
os << "on";
} else {
os << "mixed";
}
return os;
}
//enum for SCSIEncryptOptions.cryptMode enum class kad_type : std::uint8_t {
enum { CRYPTMODE_OFF, CRYPTMODE_MIXED,CRYPTMODE_ON,CRYPTMODE_RAWREAD}; ukad = 0u, // unauthenticated key-associated data
akad = 1u, // authenticated key-associated data
//used to pass parameters to SCSIWriteEncryptOptions nonce = 2u, // nonce value
class SCSIEncryptOptions { mkad = 3u, // metadata key-associated data
public: wkkad = 4u, // wrapped key key-associated data
int rdmc;
bool CKOD;
int cryptMode;
unsigned int algorithmIndex;
std::string cryptoKey;
std::string keyName;
SCSIEncryptOptions();
}; };
//Gets encryption options on the tape drive enum class kadf : std::uint8_t {
SSP_DES* SSPGetDES(std::string tapeDevice); unspecified = 0u,
//Gets the encryption status from the tape volume binary_key_name = 1u,
SSP_NBES* SSPGetNBES(std::string tapeDevice,bool retry); ascii_key_name = 2u,
//Writes encryption options to the tape drive };
bool SCSIWriteEncryptOptions(std::string tapeDevice, SCSIEncryptOptions* eOptions);
//Gets device inquiry // key-associated data
SCSI_PAGE_INQ* SCSIGetInquiry(std::string tapeDevice); struct __attribute__((packed)) kad {
kad_type type;
std::byte flags;
static constexpr auto flags_authenticated_pos {0u};
static constexpr std::byte flags_authenticated_mask {
7u << flags_authenticated_pos};
std::uint16_t length;
std::uint8_t descriptor[];
};
static_assert(sizeof(kad) == 4u);
// common 4-byte header of all SP-IN and SP-OUT pages
struct __attribute__((packed)) page_header {
std::uint16_t page_code;
std::uint16_t length;
};
static_assert(sizeof(page_header) == 4u);
// device encryption status page
struct __attribute__((packed)) page_des {
std::uint16_t page_code;
std::uint16_t length;
std::byte scope;
static constexpr auto scope_it_nexus_pos {5u};
static constexpr std::byte scope_it_nexus_mask {7u << scope_it_nexus_pos};
static constexpr auto scope_encryption_pos {0u};
static constexpr std::byte scope_encryption_mask {7u << scope_encryption_pos};
encrypt_mode encryption_mode;
decrypt_mode decryption_mode;
std::uint8_t algorithm_index;
std::uint32_t key_instance_counter;
std::byte flags;
static constexpr auto flags_parameters_control_pos {4u};
static constexpr std::byte flags_parameters_control_mask {
7u << flags_parameters_control_pos};
// volume contains encrypted logical blocks
static constexpr auto flags_vcelb_pos {3u};
static constexpr std::byte flags_vcelb_mask {1u << flags_vcelb_pos};
// check external encryption mode status
static constexpr auto flags_ceems_pos {1u};
static constexpr std::byte flags_ceems_mask {3u << flags_ceems_pos};
// raw decryption mode disabled
static constexpr auto flags_rdmd_pos {0u};
static constexpr std::byte flags_rdmd_mask {1u << flags_rdmd_pos};
kadf kad_format;
std::uint16_t asdk_count;
std::byte reserved[8];
kad kads[];
};
static_assert(sizeof(page_des) == 24u);
constexpr std::size_t SSP_PAGE_ALLOCATION = 8192;
using page_buffer = std::uint8_t[SSP_PAGE_ALLOCATION];
// set data encryption page
struct __attribute__((packed)) page_sde {
std::uint16_t page_code;
std::uint16_t length;
std::byte control;
static constexpr auto control_scope_pos {5u};
static constexpr std::byte control_scope_mask {7u << control_scope_pos};
static constexpr auto control_lock_pos {0u};
static constexpr std::byte control_lock_mask {1u << control_lock_pos};
std::byte flags;
// check external encryption mode
static constexpr auto flags_ceem_pos {6u};
static constexpr std::byte flags_ceem_mask {3u << flags_ceem_pos};
// raw decryption mode control
static constexpr auto flags_rdmc_pos {4u};
static constexpr std::byte flags_rdmc_mask {3u << flags_rdmc_pos};
// supplemental decryption key
static constexpr auto flags_sdk_pos {3u};
static constexpr std::byte flags_sdk_mask {1u << flags_sdk_pos};
// clear key on demount
static constexpr auto flags_ckod_pos {2u};
static constexpr std::byte flags_ckod_mask {1u << flags_ckod_pos};
// clear key on reservation preempt
static constexpr auto flags_ckorp_pos {1u};
static constexpr std::byte flags_ckorp_mask {1u << flags_ckorp_pos};
// clear key on reservation loss
static constexpr auto flags_ckorl_pos {0u};
static constexpr std::byte flags_ckorl_mask {1u << flags_ckorl_pos};
encrypt_mode encryption_mode;
decrypt_mode decryption_mode;
std::uint8_t algorithm_index;
std::uint8_t key_format;
kadf kad_format;
std::byte reserved[7];
std::uint16_t key_length;
std::uint8_t key[];
};
static_assert(sizeof(page_sde) == 20u);
enum class sde_rdmc : std::uint8_t {
algorithm_default = 0u << page_sde::flags_rdmc_pos,
enabled = 2u << page_sde::flags_rdmc_pos, // corresponds to --allow-raw-read
// command line option
disabled =
3u << page_sde::flags_rdmc_pos, // corresponds to --no-allow-raw-read
// command line option
};
// next block encryption status page
struct __attribute__((packed)) page_nbes {
std::uint16_t page_code;
std::uint16_t length;
std::uint64_t logical_object_number;
std::byte status;
static constexpr auto status_compression_pos {4u};
static constexpr std::byte status_compression_mask {
15u << status_compression_pos};
static constexpr auto status_encryption_pos {0u};
static constexpr std::byte status_encryption_mask {15u
<< status_encryption_pos};
std::uint8_t algorithm_index;
std::byte flags;
// encryption mode external status
static constexpr auto flags_emes_pos {1u};
static constexpr std::byte flags_emes_mask {1u << flags_emes_pos};
// raw decryption mode disabled status
static constexpr auto flags_rdmds_pos {0u};
static constexpr std::byte flags_rdmds_mask {1u << flags_rdmds_pos};
kadf kad_format;
kad kads[];
};
static_assert(sizeof(page_nbes) == 16u);
struct __attribute__((packed)) algorithm_descriptor {
std::uint8_t algorithm_index;
std::byte reserved1;
std::uint16_t length;
std::byte flags1;
// algorithm valid for mounted volume
static constexpr auto flags1_avfmv_pos {7u};
static constexpr std::byte flags1_avfmv_mask {1u << flags1_avfmv_pos};
// supplemental decryption key capable
static constexpr auto flags1_sdk_c_pos {6u};
static constexpr std::byte flags1_sdk_c_mask {1u << flags1_sdk_c_pos};
// message authentication code capable
static constexpr auto flags1_mac_c_pos {5u};
static constexpr std::byte flags1_mac_c_mask {1u << flags1_mac_c_pos};
// distinguish encrypted logical block capable
static constexpr auto flags1_delb_c_pos {4u};
static constexpr std::byte flags1_delb_c_mask {1u << flags1_delb_c_pos};
// decryption capabilities
static constexpr auto flags1_decrypt_c_pos {2u};
static constexpr std::byte flags1_decrypt_c_mask {3u << flags1_decrypt_c_pos};
// encryption capabilities
static constexpr auto flags1_encrypt_c_pos {0u};
static constexpr std::byte flags1_encrypt_c_mask {3u << flags1_encrypt_c_pos};
std::byte flags2;
// algorithm valid for current logical position
static constexpr auto flags2_avfcp_pos {6u};
static constexpr std::byte flags2_avfcp_mask {3u << flags2_avfcp_pos};
// nonce capabilities
static constexpr auto flags2_nonce_pos {4u};
static constexpr std::byte flags2_nonce_mask {3u << flags2_nonce_pos};
// KAD format capable
static constexpr auto flags2_kadf_c_pos {3u};
static constexpr std::byte flags2_kadf_c_mask {1u << flags2_kadf_c_pos};
// volume contains encrypted logical blocks capable
static constexpr auto flags2_vcelb_c_pos {2u};
static constexpr std::byte flags2_vcelb_c_mask {1u << flags2_vcelb_c_pos};
// U-KAD fixed
static constexpr auto flags2_ukadf_pos {1u};
static constexpr std::byte flags2_ukadf_mask {1u << flags2_ukadf_pos};
// A-KAD fixed
static constexpr auto flags2_akadf_pos {0u};
static constexpr std::byte flags2_akadf_mask {1u << flags2_akadf_pos};
std::uint16_t maximum_ukad_length;
std::uint16_t maximum_akad_length;
std::uint16_t key_length;
std::byte flags3;
// decryption capabilities
static constexpr auto flags3_dkad_c_pos {6u};
static constexpr std::byte flags3_dkad_c_mask {3u << flags3_dkad_c_pos};
// external encryption mode control capabilities
static constexpr auto flags3_eemc_c_pos {4u};
static constexpr std::byte flags3_eemc_c_mask {3u << flags3_eemc_c_pos};
// raw decryption mode control capabilities
static constexpr auto flags3_rdmc_c_pos {1u};
static constexpr std::byte flags3_rdmc_c_mask {7u << flags3_rdmc_c_pos};
// encryption algorithm records encryption mode
static constexpr auto flags3_earem_pos {0u};
static constexpr std::byte flags3_earem_mask {1u << flags3_earem_pos};
std::uint8_t maximum_eedk_count;
static constexpr auto maximum_eedk_count_pos {0u};
static constexpr std::uint8_t maximum_eedk_count_mask {
15u << maximum_eedk_count_pos};
std::uint16_t msdk_count;
std::uint16_t maximum_eedk_size;
std::byte reserved2[2];
std::uint32_t security_algorithm_code;
static constexpr std::size_t header_size {4u};
};
static_assert(sizeof(algorithm_descriptor) == 24u);
// device encryption capabilities page
struct __attribute__((packed)) page_dec {
std::uint16_t page_code;
std::uint16_t length;
std::byte flags;
// external data encryption control capable
static constexpr auto flags_extdecc_pos {2u};
static constexpr std::byte flags_extdecc_mask {3u << flags_extdecc_pos};
// configuration prevented
static constexpr auto flags_cfg_p_pos {0u};
static constexpr std::byte flags_cfg_p_mask {3u << flags_cfg_p_pos};
std::byte reserved[15];
algorithm_descriptor ads[];
};
static_assert(sizeof(page_dec) == 20u);
struct __attribute__((packed)) inquiry_data {
// bitfield definitions omitted since stenc only uses vendor and product info
std::byte peripheral;
std::byte flags1;
std::uint8_t version;
std::byte flags2;
std::uint8_t additional_length;
std::byte flags3;
std::byte flags4;
std::byte flags5;
std::array<char, 8> vendor;
std::array<char, 16> product_id;
std::array<char, 4> product_rev;
std::uint8_t vendor_specific[20];
std::byte reserved1[2];
std::uint16_t version_descriptor[8];
std::byte reserved2[22];
static constexpr std::size_t header_size {5u};
};
static_assert(sizeof(inquiry_data) == 96u);
struct __attribute__((packed)) sense_data {
std::byte response;
static constexpr auto response_valid_pos {7u};
static constexpr std::byte response_valid_mask {1u << response_valid_pos};
static constexpr auto response_code_pos {0u};
static constexpr std::byte response_code_mask {127u << response_code_pos};
std::byte reserved;
std::byte flags;
static constexpr auto flags_filemark_pos {7u};
static constexpr std::byte flags_filemark_mask {1u << flags_filemark_pos};
static constexpr auto flags_eom_pos {6u}; // end of medium
static constexpr std::byte flags_eom_mask {1u << flags_eom_pos};
static constexpr auto flags_ili_pos {5u}; // incorrect length indicator
static constexpr std::byte flags_ili_mask {1u << flags_ili_pos};
static constexpr auto flags_sdat_ovfl_pos {4u}; // sense data overflow
static constexpr std::byte flags_sdat_ovfl_mask {1u << flags_sdat_ovfl_pos};
static constexpr auto flags_sense_key_pos {0u};
static constexpr std::byte flags_sense_key_mask {15u << flags_sense_key_pos};
std::uint8_t information[4];
std::uint8_t additional_sense_length;
std::uint8_t command_specific_information[4];
std::uint8_t additional_sense_code;
std::uint8_t additional_sense_qualifier;
std::uint8_t field_replaceable_unit_code;
std::uint8_t sense_key_specific[3];
std::uint8_t additional_sense_bytes[];
static constexpr std::byte no_sense {0u};
static constexpr std::byte recovered_error {1u};
static constexpr std::byte not_ready {2u};
static constexpr std::byte medium_error {3u};
static constexpr std::byte hardware_error {4u};
static constexpr std::byte illegal_request {5u};
static constexpr std::byte unit_attention {6u};
static constexpr std::byte data_protect {7u};
static constexpr std::byte blank_check {8u};
static constexpr std::size_t header_size {8u};
static constexpr std::size_t maximum_size {252u}; // per SPC-5
};
static_assert(sizeof(sense_data) == 18u);
// declared as std::array instead of std::uint8_t[] because
// std::unique_ptr does not allow construction of fixed-sized arrays
using sense_buffer = std::array<std::uint8_t, sense_data::maximum_size>;
class scsi_error : public std::runtime_error {
public:
explicit scsi_error(std::unique_ptr<sense_buffer>&& buf)
: std::runtime_error {"SCSI I/O error"}, sense_buf {std::move(buf)}
{}
const sense_data& get_sense() const
{
return reinterpret_cast<sense_data&>(*sense_buf->data());
}
private:
std::unique_ptr<sense_buffer> sense_buf;
};
// Extract pointers to kad structures within a variable-length page.
// Page must have a page_header layout
template <typename Page>
std::vector<std::reference_wrapper<const kad>> read_page_kads(const Page& page)
{
const auto start {reinterpret_cast<const std::uint8_t *>(&page)};
auto it {start + sizeof(Page)};
const auto end {start + ntohs(page.length) + sizeof(page_header)};
std::vector<std::reference_wrapper<const kad>> v {};
while (it < end) {
auto elem {reinterpret_cast<const kad *>(it)};
v.push_back(std::cref(*elem));
it += ntohs(elem->length) + sizeof(kad);
}
return v;
}
// Check if a tape is loaded
bool is_device_ready(const std::string& device);
// Get SCSI inquiry data from device
inquiry_data get_inquiry(const std::string& device);
// Get data encryption status page
const page_des& get_des(const std::string& device, std::uint8_t *buffer,
std::size_t length);
// Get next block encryption status page
const page_nbes& get_nbes(const std::string& device, std::uint8_t *buffer,
std::size_t length);
// Get device encryption capabilities
const page_dec& get_dec(const std::string& device, std::uint8_t *buffer,
std::size_t length);
// Fill out a set data encryption page with parameters.
// Result is allocated and returned as a std::unique_ptr and should
// be sent to the device using scsi::write_sde
std::unique_ptr<const std::uint8_t[]>
make_sde(encrypt_mode enc_mode, decrypt_mode dec_mode,
std::uint8_t algorithm_index, const std::vector<std::uint8_t>& key,
const std::string& key_name, kadf key_format, sde_rdmc rdmc,
bool ckod);
// Write set data encryption parameters to device
void write_sde(const std::string& device, const std::uint8_t *sde_buffer);
void print_sense_data(std::ostream& os, const sense_data& sd);
std::vector<std::reference_wrapper<const algorithm_descriptor>>
read_algorithms(const page_dec& page);
} // namespace scsi
#endif #endif

45
stenc.spec Normal file
View File

@@ -0,0 +1,45 @@
# SPDX-FileCopyrightText: 2022 stenc authors
#
# SPDX-License-Identifier: CC0-1.0
Name: stenc
Version: 2.x.x
Release: 1%{?dist}
Summary: SCSI Tape Encryption Manager
License: GPL-2.0-or-later
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
BuildRequires: bash-completion
%description
SCSI Tape Encryption Manager - Manages encryption on LTO 4 and newer tape
drives with hardware-based encryption
%prep
%autosetup
%build
./autogen.sh
%configure
make %{?_smp_mflags}
%install
make install DESTDIR=%{buildroot}
%files
%license LICENSES/GPL-2.0-or-later.txt
%doc README.md AUTHORS.md
%{_bindir}/stenc
%{_mandir}/man1/stenc.1*
%{_datadir}/bash-completion/completions/stenc
%changelog
* Sat Aug 27 2022 Paweł Marciniak <sunwire+repo@gmail.com> - 2.x.x-1
- Version 2.0.0 Pre-release

51
stenc.xml Normal file
View File

@@ -0,0 +1,51 @@
<?xml version='1.0' encoding='UTF-8'?>
<cpe-list xmlns:config="http://scap.nist.gov/schema/configuration/0.1" xmlns="http://cpe.mitre.org/dictionary/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlnsscap-core="http://scap.nist.gov/schema/scap-core/0.3" xmlns:cpe-23="http://scap.nist.gov/schema/cpe-extension/2.3" xmlns:ns6="http://scap.nist.gov/schema/scap-core/0.1" xmlns:meta="http://scap.nist.gov/schema/cpe-dictionary-metadata/0.2" xsi:schemaLocation="http://scap.nist.gov/schema/cpe-extension/2.3 https://scap.nist.gov/schema/cpe/2.3/cpe-dictionary-extension_2.3.xsd http://cpe.mitre.org/dictionary/2.0 https://scap.nist.gov/schema/cpe/2.3/cpe-dictionary_2.3.xsd http://scap.nist.gov/schema/cpe-dictionary-metadata/0.2 https://scap.nist.gov/schema/cpe/2.1/cpe-dictionary-metadata_0.2.xsd http://scap.nist.gov/schema/scap-core/0.3 https://scap.nist.gov/schema/nvd/scap-core_0.3.xsd http://scap.nist.gov/schema/configuration/0.1 https://scap.nist.gov/schema/nvd/configuration_0.1.xsd http://scap.nist.gov/schema/scap-core/0.1 https://scap.nist.gov/schema/nvd/scap-core_0.1.xsd">
<cpe-item name="cpe:/a:stencproject:stenc:1.0.7">
<title xml:lang="en-US">stenc 1.0.7</title>
<references>
<reference href="https://github.com/scsitape/stenc/releases">VERSION</reference>
<reference href="https://github.com/scsitape">VENDOR</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:stencproject:stenc:1.0.7:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:stencproject:stenc:1.0.8">
<title xml:lang="en-US">stenc 1.0.8</title>
<references>
<reference href="https://github.com/scsitape/stenc/releases">VERSION</reference>
<reference href="https://github.com/scsitape">VENDOR</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:stencproject:stenc:1.0.8:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:stencproject:stenc:1.1.0">
<title xml:lang="en-US">stenc 1.1.0</title>
<references>
<reference href="https://github.com/scsitape/stenc/releases">VERSION</reference>
<reference href="https://github.com/scsitape">VENDOR</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:stencproject:stenc:1.1.0:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:stencproject:stenc:1.1.1">
<title xml:lang="en-US">stenc 1.1.1</title>
<references>
<reference href="https://github.com/scsitape/stenc/releases">VERSION</reference>
<reference href="https://github.com/scsitape">VENDOR</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:stencproject:stenc:1.1.1:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:stencproject:stenc:2.0.0">
<title xml:lang="en-US">stenc 2.0.0</title>
<references>
<reference href="https://github.com/scsitape/stenc/releases">VERSION</reference>
<reference href="https://github.com/scsitape">VENDOR</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:stencproject:stenc:2.0.0:*:*:*:*:*:*:*"/>
</cpe-item>
<cpe-item name="cpe:/a:stencproject:stenc:2.0.1">
<title xml:lang="en-US">stenc 2.0.1</title>
<references>
<reference href="https://github.com/scsitape/stenc/releases">VERSION</reference>
<reference href="https://github.com/scsitape">VENDOR</reference>
</references>
<cpe-23:cpe23-item name="cpe:2.3:a:stencproject:stenc:2.0.1:*:*:*:*:*:*:*"/>
</cpe-item>
</cpe-list>

3
stenc.xml.license Normal file
View File

@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: 2022 stenc authors
SPDX-License-Identifier: CC0-1.0

9
tests/Makefile.am Normal file
View File

@@ -0,0 +1,9 @@
# SPDX-FileCopyrightText: 2022 stenc authors
#
# SPDX-License-Identifier: CC0-1.0
AM_CPPFLAGS=-std=c++17 -I${top_srcdir}/src
TESTS=scsi output
check_PROGRAMS=scsi output
scsi_SOURCES=catch.hpp scsi.cpp ${top_srcdir}/src/scsiencrypt.cpp
output_SOURCES=catch.hpp output.cpp ${top_srcdir}/src/scsiencrypt.cpp

17976
tests/catch.hpp Normal file

File diff suppressed because it is too large Load Diff

178
tests/output.cpp Normal file
View File

@@ -0,0 +1,178 @@
// SPDX-FileCopyrightText: 2022 stenc authors
//
// SPDX-License-Identifier: GPL-2.0-or-later
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include <cstdint>
#include <map>
#include <optional>
#include <sstream>
#include <string>
#include <vector>
#include "main.cpp"
using namespace std::literals::string_literals;
TEST_CASE("Test key_from_hex_chars", "[output]")
{
REQUIRE(key_from_hex_chars(""s) == std::vector<std::uint8_t> {});
REQUIRE(key_from_hex_chars("hello"s) == std::nullopt);
REQUIRE(key_from_hex_chars("12z"s) == std::nullopt);
REQUIRE(key_from_hex_chars("0xabcd"s) == std::nullopt);
REQUIRE(key_from_hex_chars("ab cd"s) == std::nullopt);
REQUIRE(key_from_hex_chars("a"s) == std::vector<std::uint8_t> {0x0a});
REQUIRE(key_from_hex_chars("0123456789abcdef"s) ==
std::vector<std::uint8_t> {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
0xef});
REQUIRE(key_from_hex_chars("0123456789ABCDEF"s) ==
std::vector<std::uint8_t> {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
0xef});
}
/**
* Compare the output of stenc given device responses
*
* These tests check the representation and interpretation of raw device data
* and that the program output accurately reports the meaning of the data.
*/
TEST_CASE("Test SCSI inquiry output", "[output]")
{
const std::uint8_t response[] {
0x01, 0x80, 0x00, 0x02, 0x5b, 0x00, 0x00, 0x02, 0x41, 0x43, 0x4d, 0x45,
0x20, 0x20, 0x20, 0x20, 0x55, 0x6c, 0x74, 0x72, 0x69, 0x75, 0x6d, 0x2d,
0x31, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x31, 0x32, 0x33, 0x34,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const std::string expected_output {"ACME Ultrium-1000 1234"s};
std::ostringstream oss;
print_device_inquiry(oss,
reinterpret_cast<const scsi::inquiry_data&>(response));
REQUIRE(oss.str() == expected_output);
}
TEST_CASE("SCSI get device encryption status output 1", "[output]")
{
std::map<std::uint8_t, std::string> algorithms {
{1, "AES-256-GCM-128"s},
};
const std::uint8_t page[] {
0x00, 0x20, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const std::string expected_output {"\
Reading: Not decrypting\n\
Writing: Not encrypting\n\
Key instance counter: 0\n"s};
std::ostringstream oss;
print_device_status(oss, reinterpret_cast<const scsi::page_des&>(page),
algorithms);
REQUIRE(oss.str() == expected_output);
}
TEST_CASE("SCSI get device encryption status output 2", "[output]")
{
std::map<std::uint8_t, std::string> algorithms {
{1, "AES-256-GCM-128"s},
};
const std::uint8_t page[] {
0x00, 0x20, 0x00, 0x24, 0x42, 0x02, 0x02, 0x01, 0x00, 0x00,
0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x48, 0x65,
0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
};
const std::string expected_output {"\
Reading: Decrypting (AES-256-GCM-128)\n\
Unencrypted blocks not readable\n\
Writing: Encrypting (AES-256-GCM-128)\n\
Key instance counter: 1\n\
Drive key desc. (U-KAD): Hello world!\n"s};
std::ostringstream oss;
print_device_status(oss, reinterpret_cast<const scsi::page_des&>(page),
algorithms);
REQUIRE(oss.str() == expected_output);
}
TEST_CASE("Test SCSI get next block encryption status output 1", "[output]")
{
std::map<std::uint8_t, std::string> algorithms {
{1, "AES-256-GCM-128"s},
};
const std::uint8_t page[] {
0x00, 0x21, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
};
const std::string expected_output {"\
Current block status: Not encrypted\n"s};
std::ostringstream oss;
print_block_status(oss, reinterpret_cast<const scsi::page_nbes&>(page),
algorithms);
REQUIRE(oss.str() == expected_output);
}
TEST_CASE("Test SCSI get next block encryption status output 2", "[output]")
{
std::map<std::uint8_t, std::string> algorithms {
{1, "AES-256-GCM-128"s},
};
const std::uint8_t page[] {
0x00, 0x21, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x48, 0x65,
0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
};
const std::string expected_output {"\
Current block status: Encrypted and able to decrypt (AES-256-GCM-128)\n"s};
std::ostringstream oss;
print_block_status(oss, reinterpret_cast<const scsi::page_nbes&>(page),
algorithms);
REQUIRE(oss.str() == expected_output);
}
TEST_CASE("Test SCSI get next block encryption status output 3", "[output]")
{
std::map<std::uint8_t, std::string> algorithms {
{1, "AES-256-GCM-128"s},
};
const std::uint8_t page[] {
0x00, 0x21, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x06, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x0c, 0x48, 0x65,
0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
};
const std::string expected_output {"\
Current block status: Encrypted, key missing or invalid (AES-256-GCM-128)\n\
Current block key desc. (U-KAD): Hello world!\n"s};
std::ostringstream oss;
print_block_status(oss, reinterpret_cast<const scsi::page_nbes&>(page),
algorithms);
REQUIRE(oss.str() == expected_output);
}
TEST_CASE("Test SCSI get data encryption capabilities output", "[output]")
{
const std::uint8_t page[] {
0x00, 0x10, 0x00, 0x3c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14,
0x8a, 0x8c, 0x00, 0x20, 0x00, 0x3c, 0x00, 0x20, 0xed, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, 0x02, 0x00, 0x00, 0x14,
0x8a, 0x8f, 0x00, 0x20, 0x00, 0x3c, 0x00, 0x20, 0xd9, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10,
};
const std::string expected_output {"\
Supported algorithms:\n\
1 AES-256-GCM-128\n\
Key descriptors allowed, maximum 32 bytes\n\
Raw decryption mode not allowed\n\
2 AES-256-CCM-128\n\
Key descriptors allowed, fixed 32 bytes\n\
Raw decryption mode allowed, raw read disabled by default\n"s};
std::ostringstream oss;
print_algorithms(oss, scsi::read_algorithms(
reinterpret_cast<const scsi::page_dec&>(page)));
REQUIRE(oss.str() == expected_output);
}

427
tests/scsi.cpp Normal file
View File

@@ -0,0 +1,427 @@
// SPDX-FileCopyrightText: 2022 stenc authors
//
// SPDX-License-Identifier: GPL-2.0-or-later
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <functional>
#include <memory>
#include <string>
#include <vector>
#if HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#if HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include "scsiencrypt.h"
using namespace std::literals::string_literals;
/**
* Compare the SPOUT Set Data Encryption pages generated by stenc to an
* expected output buffer based on the SCSI command spec.
*
* This checks that the program can correctly format command buffers that
* reflect available input and program options.
*/
TEST_CASE("Disable encryption command", "[scsi]")
{
const std::uint8_t expected[] {
// clang-format off
0x00, 0x10, // page code
0x00, 0x10, // page length
0x40, // scope
0x40, // CEEM, CKOD, RDMC, et al.
0x00, // encyption mode
0x00, // decryption mode
0x01, // algorithm index
0x00, // key format
0x00, // KAD format
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [7]
0x00, 0x00 // key length
// clang-format on
};
std::vector<std::uint8_t> key {};
std::string key_name {};
auto page_buffer {scsi::make_sde(
scsi::encrypt_mode::off, scsi::decrypt_mode::off, 1u, key, key_name,
scsi::kadf::unspecified, scsi::sde_rdmc::algorithm_default, false)};
auto& page {reinterpret_cast<const scsi::page_sde&>(*page_buffer.get())};
REQUIRE(sizeof(scsi::page_header) + ntohs(page.length) == sizeof(expected));
REQUIRE(std::memcmp(&page, expected, sizeof(expected)) == 0);
}
TEST_CASE("Enable encryption command", "[scsi]")
{
const std::uint8_t expected[] {
// clang-format off
0x00, 0x10, // page code
0x00, 0x30, // page length
0x40, // scope
0x40, // CEEM, CKOD, RDMC, et al.
0x02, // encyption mode
0x02, // decryption mode
0x01, // algorithm index
0x00, // key format
0x00, // KAD format
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [7]
0x00, 0x20, // key length
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
// clang-format on
};
std::vector<std::uint8_t> key {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
};
std::string key_name {};
auto page_buffer {scsi::make_sde(
scsi::encrypt_mode::on, scsi::decrypt_mode::on, 1u, key, key_name,
scsi::kadf::unspecified, scsi::sde_rdmc::algorithm_default, false)};
auto& page {reinterpret_cast<const scsi::page_sde&>(*page_buffer.get())};
REQUIRE(sizeof(scsi::page_header) + ntohs(page.length) == sizeof(expected));
REQUIRE(std::memcmp(&page, expected, sizeof(expected)) == 0);
}
TEST_CASE("Enable encryption command with options", "[scsi]")
{
const std::uint8_t expected[] {
// clang-format off
0x00, 0x10, // page code
0x00, 0x30, // page length
0x40, // scope
0x64, // CEEM, CKOD, RDMC, et al.
0x02, // encyption mode
0x02, // decryption mode
0x01, // algorithm index
0x00, // key format
0x01, // KAD format
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [7]
0x00, 0x20, // key length
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
// clang-format on
};
std::vector<std::uint8_t> key {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
};
std::string key_name {};
auto page_buffer {scsi::make_sde(
scsi::encrypt_mode::on, scsi::decrypt_mode::on, 1u, key, key_name,
scsi::kadf::binary_key_name, scsi::sde_rdmc::enabled, true)};
auto& page {reinterpret_cast<const scsi::page_sde&>(*page_buffer.get())};
REQUIRE(sizeof(scsi::page_header) + ntohs(page.length) == sizeof(expected));
REQUIRE(std::memcmp(&page, expected, sizeof(expected)) == 0);
}
TEST_CASE("Enable encryption command with key name", "[scsi]")
{
const std::uint8_t expected[] {
// clang-format off
0x00, 0x10, // page code
0x00, 0x40, // page length
0x40, // scope
0x40, // CEEM, CKOD, RDMC, et al.
0x02, // encyption mode
0x02, // decryption mode
0x01, // algorithm index
0x00, // key format
0x02, // KAD format
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved [7]
0x00, 0x20, // key length
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
// KAD
0x00, // type
0x00, // authenticated
0x00, 0x0c, // length
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
// clang-format on
};
std::vector<std::uint8_t> key {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA,
0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
};
std::string key_name {"Hello world!"s};
auto page_buffer {scsi::make_sde(
scsi::encrypt_mode::on, scsi::decrypt_mode::on, 1u, key, key_name,
scsi::kadf::ascii_key_name, scsi::sde_rdmc::algorithm_default, false)};
auto& page {reinterpret_cast<const scsi::page_sde&>(*page_buffer.get())};
REQUIRE(sizeof(scsi::page_header) + ntohs(page.length) == sizeof(expected));
REQUIRE(std::memcmp(&page, expected, sizeof(expected)) == 0);
}
/**
* Check the representation of the SPIN Device Encryption Status page
* matches the values from the raw buffer. Input buffers were observed
* from device traffic.
*
* This checks the SSP_DES structure layout matches the spec, especially
* with regard to byte ordering and bitfield positions.
*/
TEST_CASE("Interpret device encryption status page", "[scsi]")
{
const std::uint8_t buffer[] {
// clang-format off
0x00, 0x20, // page code
0x00, 0x24, // length
0x42, // nexus = 2h, key scope = 2h
0x02, // encryption mode
0x02, // decryption mode
0x01, // algorithm index
0x00, 0x00, 0x00, 0x01, // key instance counter
0x18, // parameters control = 1, VCELB = 1, CEEMS = 0, RDMD = 0
0x00, // KAD format
0x00, 0x00, // ADSK count
0x00, 0x00, 0x00, 0x00, // reserved[8]
0x00, 0x00, 0x00, 0x00,
// KAD descriptor
0x00, // descriptor type
0x01, // authenticated
0x00, 0x0c, // length
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
// clang-format on
};
auto& page_des {reinterpret_cast<const scsi::page_des&>(buffer)};
REQUIRE(ntohs(page_des.page_code) == 0x20u);
REQUIRE(ntohs(page_des.length) == 36u);
REQUIRE((page_des.scope & scsi::page_des::scope_it_nexus_mask) ==
std::byte {2u} << scsi::page_des::scope_it_nexus_pos);
REQUIRE((page_des.scope & scsi::page_des::scope_encryption_mask) ==
std::byte {2u} << scsi::page_des::scope_encryption_pos);
REQUIRE(page_des.encryption_mode == scsi::encrypt_mode::on);
REQUIRE(page_des.decryption_mode == scsi::decrypt_mode::on);
REQUIRE(page_des.algorithm_index == 1u);
REQUIRE(ntohl(page_des.key_instance_counter) == 1u);
REQUIRE((page_des.flags & scsi::page_des::flags_parameters_control_mask) ==
std::byte {1u} << scsi::page_des::flags_parameters_control_pos);
REQUIRE((page_des.flags & scsi::page_des::flags_vcelb_mask) ==
scsi::page_des::flags_vcelb_mask);
REQUIRE((page_des.flags & scsi::page_des::flags_ceems_mask) == std::byte {});
REQUIRE((page_des.flags & scsi::page_des::flags_rdmd_mask) == std::byte {});
auto kads = read_page_kads(page_des);
REQUIRE(kads.size() == 1u);
const scsi::kad& kd = kads[0];
REQUIRE((kd.flags & scsi::kad::flags_authenticated_mask) == std::byte {1u});
REQUIRE(ntohs(kd.length) == std::strlen("Hello world!"));
REQUIRE(std::memcmp(kd.descriptor, "Hello world!", ntohs(kd.length)) == 0);
}
TEST_CASE("Interpret next block encryption status page", "[scsi]")
{
const std::uint8_t buffer[] {
// clang-format off
0x00, 0x21, // page code
0x00, 0x1c, // length
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x05, // compression status = 0, encryption status = 5h
0x01, // algorithm index
0x00, // EMES = 0, RDMDS = 0
0x00, // KAD format
// KAD descriptor
0x00, // descriptor type
0x01, // authenticated
0x00, 0x0c, // length
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21,
// clang-format on
};
auto& page_nbes {reinterpret_cast<const scsi::page_nbes&>(buffer)};
REQUIRE(ntohs(page_nbes.page_code) == 0x21u);
REQUIRE(ntohs(page_nbes.length) == 28u);
REQUIRE((page_nbes.status & scsi::page_nbes::status_compression_mask) ==
std::byte {});
REQUIRE((page_nbes.status & scsi::page_nbes::status_encryption_mask) ==
std::byte {5u} << scsi::page_nbes::status_encryption_pos);
REQUIRE(page_nbes.algorithm_index == 1u);
REQUIRE((page_nbes.flags & scsi::page_nbes::flags_emes_mask) == std::byte {});
REQUIRE((page_nbes.flags & scsi::page_nbes::flags_rdmds_mask) ==
std::byte {});
auto kads = read_page_kads(page_nbes);
REQUIRE(kads.size() == 1u);
const scsi::kad& kd = kads[0];
REQUIRE((kd.flags & scsi::kad::flags_authenticated_mask) == std::byte {1u});
REQUIRE(ntohs(kd.length) == std::strlen("Hello world!"));
REQUIRE(std::memcmp(kd.descriptor, "Hello world!", ntohs(kd.length)) == 0);
}
TEST_CASE("Interpret data encryption capabilties page", "[scsi]")
{
const std::uint8_t buffer[] {
// clang-format off
0x00, 0x10, // page code
0x00, 0x3c, // length
0x09, // EXTDECC and CFG_P
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// algorithm 1
0x01,
0x00,
0x00, 0x14,
0x8a, // capabilties
0x8c,
0x00, 0x20,
0x00, 0x3c,
0x00, 0x20,
0xed,
0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x01, 0x00, 0x14,
// algorithm 2
0x02,
0x00,
0x00, 0x14,
0x8a, // capabilties
0x8f,
0x00, 0x20,
0x00, 0x3c,
0x00, 0x20,
0xd9,
0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x01, 0x00, 0x10,
// clang-format on
};
static_assert(sizeof(buffer) == sizeof(scsi::page_dec) +
2 * sizeof(scsi::algorithm_descriptor));
auto& page_dec {reinterpret_cast<const scsi::page_dec&>(buffer)};
REQUIRE(ntohs(page_dec.page_code) == 0x10u);
REQUIRE(ntohs(page_dec.length) == 60u);
REQUIRE((page_dec.flags & scsi::page_dec::flags_extdecc_mask) ==
std::byte {2u} << scsi::page_dec::flags_extdecc_pos);
REQUIRE((page_dec.flags & scsi::page_dec::flags_cfg_p_mask) ==
std::byte {1u} << scsi::page_dec::flags_cfg_p_pos);
auto algorithms {read_algorithms(page_dec)};
REQUIRE(algorithms.size() == 2u);
const scsi::algorithm_descriptor& algo1 = algorithms[0];
REQUIRE(algo1.algorithm_index == 1u);
REQUIRE(ntohs(algo1.length) == 20u);
REQUIRE((algo1.flags1 & scsi::algorithm_descriptor::flags1_avfmv_mask) ==
scsi::algorithm_descriptor::flags1_avfmv_mask);
REQUIRE((algo1.flags1 & scsi::algorithm_descriptor::flags1_sdk_c_mask) ==
std::byte {});
REQUIRE((algo1.flags1 & scsi::algorithm_descriptor::flags1_mac_c_mask) ==
std::byte {});
REQUIRE((algo1.flags1 & scsi::algorithm_descriptor::flags1_delb_c_mask) ==
std::byte {});
REQUIRE((algo1.flags1 & scsi::algorithm_descriptor::flags1_decrypt_c_mask) ==
std::byte {2u} << scsi::algorithm_descriptor::flags1_decrypt_c_pos);
REQUIRE((algo1.flags1 & scsi::algorithm_descriptor::flags1_encrypt_c_mask) ==
std::byte {2u} << scsi::algorithm_descriptor::flags1_encrypt_c_pos);
REQUIRE((algo1.flags2 & scsi::algorithm_descriptor::flags2_avfcp_mask) ==
std::byte {2u} << scsi::algorithm_descriptor::flags2_avfcp_pos);
REQUIRE((algo1.flags2 & scsi::algorithm_descriptor::flags2_nonce_mask) ==
std::byte {});
REQUIRE((algo1.flags2 & scsi::algorithm_descriptor::flags2_kadf_c_mask) ==
scsi::algorithm_descriptor::flags2_kadf_c_mask);
REQUIRE((algo1.flags2 & scsi::algorithm_descriptor::flags2_vcelb_c_mask) ==
scsi::algorithm_descriptor::flags2_vcelb_c_mask);
REQUIRE((algo1.flags2 & scsi::algorithm_descriptor::flags2_ukadf_mask) ==
std::byte {});
REQUIRE((algo1.flags2 & scsi::algorithm_descriptor::flags2_akadf_mask) ==
std::byte {});
REQUIRE(ntohs(algo1.maximum_ukad_length) == 32u);
REQUIRE(ntohs(algo1.maximum_akad_length) == 60u);
REQUIRE(ntohs(algo1.key_length) == 32u);
REQUIRE((algo1.flags3 & scsi::algorithm_descriptor::flags3_dkad_c_mask) ==
std::byte {3u} << scsi::algorithm_descriptor::flags3_dkad_c_pos);
REQUIRE((algo1.flags3 & scsi::algorithm_descriptor::flags3_eemc_c_mask) ==
std::byte {2u} << scsi::algorithm_descriptor::flags3_eemc_c_pos);
REQUIRE((algo1.flags3 & scsi::algorithm_descriptor::flags3_rdmc_c_mask) ==
std::byte {6u} << scsi::algorithm_descriptor::flags3_rdmc_c_pos);
REQUIRE((algo1.flags3 & scsi::algorithm_descriptor::flags3_earem_mask) ==
scsi::algorithm_descriptor::flags3_earem_mask);
REQUIRE((algo1.maximum_eedk_count &
scsi::algorithm_descriptor::maximum_eedk_count_mask) == 0u);
REQUIRE(ntohs(algo1.msdk_count) == 0u);
REQUIRE(ntohs(algo1.maximum_eedk_size) == 0u);
REQUIRE(ntohl(algo1.security_algorithm_code) == 0x00010014u);
const scsi::algorithm_descriptor& algo2 = algorithms[1];
REQUIRE(algo2.algorithm_index == 2u);
REQUIRE(ntohs(algo2.length) == 20u);
REQUIRE((algo2.flags1 & scsi::algorithm_descriptor::flags1_avfmv_mask) ==
scsi::algorithm_descriptor::flags1_avfmv_mask);
REQUIRE((algo2.flags1 & scsi::algorithm_descriptor::flags1_sdk_c_mask) ==
std::byte {});
REQUIRE((algo2.flags1 & scsi::algorithm_descriptor::flags1_mac_c_mask) ==
std::byte {});
REQUIRE((algo2.flags1 & scsi::algorithm_descriptor::flags1_delb_c_mask) ==
std::byte {});
REQUIRE((algo2.flags1 & scsi::algorithm_descriptor::flags1_decrypt_c_mask) ==
std::byte {2u} << scsi::algorithm_descriptor::flags1_decrypt_c_pos);
REQUIRE((algo2.flags1 & scsi::algorithm_descriptor::flags1_encrypt_c_mask) ==
std::byte {2u} << scsi::algorithm_descriptor::flags1_encrypt_c_pos);
REQUIRE((algo2.flags2 & scsi::algorithm_descriptor::flags2_avfcp_mask) ==
std::byte {2u} << scsi::algorithm_descriptor::flags2_avfcp_pos);
REQUIRE((algo2.flags2 & scsi::algorithm_descriptor::flags2_nonce_mask) ==
std::byte {});
REQUIRE((algo2.flags2 & scsi::algorithm_descriptor::flags2_kadf_c_mask) ==
scsi::algorithm_descriptor::flags2_kadf_c_mask);
REQUIRE((algo2.flags2 & scsi::algorithm_descriptor::flags2_vcelb_c_mask) ==
scsi::algorithm_descriptor::flags2_vcelb_c_mask);
REQUIRE((algo2.flags2 & scsi::algorithm_descriptor::flags2_ukadf_mask) ==
scsi::algorithm_descriptor::flags2_ukadf_mask);
REQUIRE((algo2.flags2 & scsi::algorithm_descriptor::flags2_akadf_mask) ==
scsi::algorithm_descriptor::flags2_akadf_mask);
REQUIRE(ntohs(algo2.maximum_ukad_length) == 32u);
REQUIRE(ntohs(algo2.maximum_akad_length) == 60u);
REQUIRE(ntohs(algo2.key_length) == 32u);
REQUIRE((algo2.flags3 & scsi::algorithm_descriptor::flags3_dkad_c_mask) ==
std::byte {3u} << scsi::algorithm_descriptor::flags3_dkad_c_pos);
REQUIRE((algo2.flags3 & scsi::algorithm_descriptor::flags3_eemc_c_mask) ==
std::byte {1u} << scsi::algorithm_descriptor::flags3_eemc_c_pos);
REQUIRE((algo2.flags3 & scsi::algorithm_descriptor::flags3_rdmc_c_mask) ==
std::byte {4u} << scsi::algorithm_descriptor::flags3_rdmc_c_pos);
REQUIRE((algo2.flags3 & scsi::algorithm_descriptor::flags3_earem_mask) ==
scsi::algorithm_descriptor::flags3_earem_mask);
REQUIRE((algo2.maximum_eedk_count &
scsi::algorithm_descriptor::maximum_eedk_count_mask) == 0u);
REQUIRE(ntohs(algo2.msdk_count) == 0u);
REQUIRE(ntohs(algo2.maximum_eedk_size) == 0u);
REQUIRE(ntohl(algo2.security_algorithm_code) == 0x00010010u);
}