Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux S3 sleep support and two more useful additions #3

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Common/DtaDev.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ along with sedutil. If not, see <http://www.gnu.org/licenses/>.
#include "DtaConstants.h"
#include "DtaEndianFixup.h"
#include "DtaHexDump.h"
#include "DtaHashPwd.h"

using namespace std;

Expand Down Expand Up @@ -313,6 +314,24 @@ void DtaDev::discovery0()
while (cpos < epos);

}

uint8_t DtaDev::printPasswordHash(char * password)
{
LOG(D1) << "Entering DtaDev::printPasswordHash()";
vector<uint8_t> hash;
DtaHashPwd(hash, password, this);

/* std::hex overwrites flags; save them, so we do not alter other output later */
ios_base::fmtflags saved_flags = cout.flags();

/* First two bytes are actually the opal header */
for (size_t i = 2; i < hash.size(); ++i)
cout << hex << setfill('0') << setw(2) << (int)hash[i];
cout << endl;
cout.flags(saved_flags);
return 0;
}

void DtaDev::puke()
{
LOG(D1) << "Entering DtaDev::puke()";
Expand Down Expand Up @@ -487,3 +506,9 @@ void DtaDev::puke()
if (disk_info.Unknown)
cout << "**** " << (uint16_t)disk_info.Unknown << " **** Unknown function codes IGNORED " << std::endl;
}

uint8_t DtaDev::prepareForS3Sleep(uint8_t lockingrange, char* password)
{
LOG(E) << "S3 sleep not supported on this platform";
return 1;
}
9 changes: 9 additions & 0 deletions Common/DtaDev.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ class DtaDev {
*/
void discovery0();

/** Print password hash, computed with this device's serial number
*/
uint8_t printPasswordHash(char * password);
/*
* virtual methods required in the OS specific
* device class
Expand Down Expand Up @@ -259,6 +262,11 @@ class DtaDev {
* @param password Password of administrative authority for locking range
*/
virtual uint8_t eraseLockingRange(uint8_t lockingrange, char * password) = 0;
/** Optionally implemented s3 sleep support.
* On Linux, it saves the password to the kernel to use on resume.
* @param password the password to save to the kernel
*/
virtual uint8_t prepareForS3Sleep(uint8_t lockingrange, char* password);
/** Dumps an object for diagnostic purposes
* @param sp index into the OPALUID table for the SP the object is in
* @param auth the authority to use for the dump
Expand Down Expand Up @@ -294,6 +302,7 @@ class DtaDev {
/** return the communications ID to be used for sessions to this device */
virtual uint16_t comID() = 0;
bool no_hash_passwords; /** disables hashing of passwords */
bool hex_passwords; /** converts passwords from hex before using them */
sedutiloutput output_format; /** standard, readable, JSON */
protected:
const char * dev; /**< character string representing the device in the OS lexicon */
Expand Down
48 changes: 33 additions & 15 deletions Common/DtaHashPwd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ extern "C" {
}
using namespace std;

void DtaHashPassword(vector<uint8_t> &hash, char * password, vector<uint8_t> salt,
unsigned int iter, uint8_t hashsize)
void DtaHashPassword(vector<uint8_t> &hash, const vector<uint8_t>& password,
const vector<uint8_t>& salt, unsigned int iter, uint8_t hashsize)
{
LOG(D1) << " Entered DtaHashPassword";
// if the hashsize can be > 255 the token overhead logic needs to be fixed
Expand All @@ -42,15 +42,15 @@ void DtaHashPassword(vector<uint8_t> &hash, char * password, vector<uint8_t> sal

hash.clear();
// don't hash the devault OPAL password ''
if (0 == strnlen(password, 32)) {
if (0 == password.size()) {
goto exit;
}
hash.reserve(hashsize + 2); // hope this will prevent reallocation
for (uint16_t i = 0; i < hashsize; i++) {
hash.push_back(' ');
}

cf_pbkdf2_hmac((uint8_t *)password, strnlen(password, 256),
cf_pbkdf2_hmac(&password[0], password.size(),
salt.data(), salt.size(),
iter,
hash.data(), hash.size(),
Expand All @@ -67,21 +67,38 @@ void DtaHashPwd(vector<uint8_t> &hash, char * password, DtaDev * d)
{
LOG(D1) << " Entered DtaHashPwd";
char *serNum;
vector<uint8_t> decoded_password;
if (d->hex_passwords)
{
for (char* p=password; *p; ++p)
{
uint8_t num1 = (uint8_t)(*p & 0x40 ? (*p & 0xf) + 9 : *p & 0xf);
++p;
if (*p == 0)
break;
uint8_t num2 = (uint8_t)(*p & 0x40 ? (*p & 0xf) + 9 : *p & 0xf);
decoded_password.push_back(num1 * 16 + num2);
}
}
else
{
decoded_password.assign(password, password + strlen(password));
}

if (d->no_hash_passwords) {
hash.clear();
for (uint16_t i = 0; i < strnlen(password, 32); i++)
hash.push_back(password[i]);
// add the token overhead
hash.insert(hash.begin(), (uint8_t)hash.size());
hash.insert(hash.begin(), 0xd0);
LOG(D1) << " Exit DtaHashPwd";
return;
if (decoded_password.size() > 32)
decoded_password.resize(32);
hash = decoded_password;
// add the token overhead
hash.insert(hash.begin(), (uint8_t)hash.size());
hash.insert(hash.begin(), 0xd0);
LOG(D1) << " Exit DtaHashPwd";
return;
}
serNum = d->getSerialNum();
vector<uint8_t> salt(serNum, serNum + 20);
// vector<uint8_t> salt(DEFAULTSALT);
DtaHashPassword(hash, password, salt);
DtaHashPassword(hash, decoded_password, salt);
LOG(D1) << " Exit DtaHashPwd"; // log for hash timing
}

Expand Down Expand Up @@ -109,7 +126,7 @@ int testresult(std::vector<uint8_t> &result, const char * expected, size_t len)
int Testsedutil(const PBKDF_TestTuple *testSet, unsigned int testSetSize)
{
int pass = 1;
std::vector<uint8_t> hash, seaSalt;
std::vector<uint8_t> hash, seaSalt, password;

for (unsigned int i = 0; i < testSetSize; i++) {
const PBKDF_TestTuple &tuple = testSet[i];
Expand All @@ -120,7 +137,8 @@ int Testsedutil(const PBKDF_TestTuple *testSet, unsigned int testSetSize)
}
printf("Password %s Salt %s Iterations %i Length %i\n", (char *)tuple.Password,
(char *) tuple.Salt, tuple.iterations, tuple.hashlen);
DtaHashPassword(hash, (char *) tuple.Password, seaSalt, tuple.iterations, tuple.hashlen);
password.assign(tuple.Password, tuple.Password+strlen(tuple.Password));
DtaHashPassword(hash, password, seaSalt, tuple.iterations, tuple.hashlen);
int fail = (testresult(hash, tuple.hexDerivedKey, tuple.hashlen) == 0);
pass = pass & fail;
}
Expand Down
4 changes: 2 additions & 2 deletions Common/DtaHashPwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void DtaHashPwd(vector<uint8_t> &hash, char * password, DtaDev * device);
* @param iter number of iterations to be preformed
* @param hashsize size of hash to be returned
*/
void DtaHashPassword(vector<uint8_t> &hash, char * password, vector<uint8_t> salt,
unsigned int iter = 75000, uint8_t hashsize = 32);
void DtaHashPassword(vector<uint8_t> &hash, const vector<uint8_t> &password,
const vector<uint8_t> &salt, unsigned int iter = 75000, uint8_t hashsize = 32);
/** Test the hshing function using publicly available test cased and report */
int TestPBKDF2();
38 changes: 37 additions & 1 deletion Common/DtaOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ void usage()
printf("a utility to manage self encrypting drives that conform\n");
printf("to the TCG Enterprise, Opal, Opalite and Pyrite SSC specs\n");
printf("General Usage: (see readme for extended commandset)\n");
printf("sedutil-cli <-v> <-n> <action> <options> <device>\n");
printf("sedutil-cli <-v> <-n> <-x> <action> <options> <device>\n");
printf("-v (optional) increase verbosity, one to five v's\n");
printf("-n (optional) no password hashing. Passwords will be sent in clear text!\n");
printf("-l (optional) log style output to stderr only\n");
printf("-x (optional) password inputs are in hex form\n");
printf("actions \n");
printf("--scan \n");
printf(" Scans the devices on the system \n");
Expand Down Expand Up @@ -99,6 +100,12 @@ void usage()
printf(" AdminSP->Revert instead of ThisSP->RevertSP\n");
printf("--printDefaultPassword <device>\n");
printf(" print MSID \n");
printf("--printPasswordHash <password> <device>\n");
printf(" print the hash of the password \n");
printf(" as computed by sedutil. Hex-ecoded.\n");
printf("--prepareForS3Sleep <0...n> <Admin1password> <device>\n");
printf(" Automatically unlock range after S3 resume\n");
printf(" This command will save the password to kernel memory\n");
printf("\n");
printf("Examples \n");
printf("sedutil-cli --scan \n");
Expand Down Expand Up @@ -144,6 +151,10 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts)
opts->output_format = sedutilNormal;
outputFormat = sedutilNormal;
}
else if (!strcmp("-x", argv[i])) {
baseOptions += 1;
opts->hex_passwords = true;
}
else if (!(('-' == argv[i][0]) && ('-' == argv[i][1])) &&
(0 == opts->action))
{
Expand Down Expand Up @@ -515,6 +526,31 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts)
END_OPTION
BEGIN_OPTION(objDump, 5) i += 4; OPTION_IS(device) END_OPTION
BEGIN_OPTION(printDefaultPassword, 1) OPTION_IS(device) END_OPTION
BEGIN_OPTION(printPasswordHash, 2)
OPTION_IS(password)
OPTION_IS(device)
END_OPTION
BEGIN_OPTION(prepareForS3Sleep, 3)
TESTARG(0, lockingrange, 0)
TESTARG(1, lockingrange, 1)
TESTARG(2, lockingrange, 2)
TESTARG(3, lockingrange, 3)
TESTARG(4, lockingrange, 4)
TESTARG(5, lockingrange, 5)
TESTARG(6, lockingrange, 6)
TESTARG(7, lockingrange, 7)
TESTARG(8, lockingrange, 8)
TESTARG(9, lockingrange, 9)
TESTARG(10, lockingrange, 10)
TESTARG(11, lockingrange, 11)
TESTARG(12, lockingrange, 12)
TESTARG(13, lockingrange, 13)
TESTARG(14, lockingrange, 14)
TESTARG(15, lockingrange, 15)
TESTFAIL("Invalid Locking Range (0-15)")
OPTION_IS(password)
OPTION_IS(device)
END_OPTION
BEGIN_OPTION(rawCmd, 7) i += 6; OPTION_IS(device) END_OPTION
else {
LOG(E) << "Invalid command line argument " << argv[i];
Expand Down
3 changes: 3 additions & 0 deletions Common/DtaOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ typedef struct _DTA_OPTIONS {
uint8_t lrlength; /** the length in blocks of a lockingrange */

bool no_hash_passwords; /** global parameter, disables hashing of passwords */
bool hex_passwords; /** global parameter, all incoming passwords are treated as hex-encoded */
sedutiloutput output_format;
} DTA_OPTIONS;
/** Print a usage message */
Expand Down Expand Up @@ -95,6 +96,8 @@ typedef enum _sedutiloption {
validatePBKDF2,
objDump,
printDefaultPassword,
printPasswordHash,
prepareForS3Sleep,
rawCmd,

} sedutiloption;
Expand Down
10 changes: 10 additions & 0 deletions Common/sedutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ int main(int argc, char * argv[])
// make sure DtaDev::no_hash_passwords is initialized
d->no_hash_passwords = opts.no_hash_passwords;

d->hex_passwords = opts.hex_passwords;

d->output_format = opts.output_format;
}

Expand Down Expand Up @@ -273,6 +275,14 @@ int main(int argc, char * argv[])
LOG(D) << "print default password";
return d->printDefaultPassword();
break;
case sedutiloption::printPasswordHash:
LOG(D) << "print password hash";
return d->printPasswordHash(argv[opts.password]);
break;
case sedutiloption::prepareForS3Sleep:
LOG(D) << "Preparing for S3 sleep " << (uint16_t) opts.lockingrange;
return d->prepareForS3Sleep(opts.lockingrange, argv[opts.password]);
break;
case sedutiloption::rawCmd:
LOG(D) << "Performing cmdDump ";
return d->rawCmd(argv[argc - 7], argv[argc - 6], argv[argc - 5], argv[argc - 4], argv[argc - 3], argv[argc - 2]);
Expand Down
1 change: 1 addition & 0 deletions LinuxPBA/UnlockSEDs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ uint8_t UnlockSEDs(char * password) {
d = new DtaDevOpal1(devref);
delete tempDev;
d->no_hash_passwords = false;
d->hex_passwords = false;
failed = 0;
if (d->Locked()) {
if (d->MBREnabled()) {
Expand Down
6 changes: 4 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ sedutil_cli_SOURCES = linux/Version.h Common/sedutil.cpp Common/DtaOptions.cpp C
linux/DtaDevLinuxNvme.cpp linux/DtaDevLinuxNvme.h \
linux/DtaDevLinuxSata.cpp linux/DtaDevLinuxSata.h \
linux/DtaDevOS.cpp linux/DtaDevOS.h \
linux/DtaDevLinuxDrive.h linux/os.h \
linux/DtaDevLinuxDrive.cpp linux/DtaDevLinuxDrive.h \
linux/os.h \
$(SEDUTIL_COMMON_CODE)
CLEANFILES = linux/Version.h
BUILT_SOURCES = linux/Version.h
Expand All @@ -40,7 +41,8 @@ linuxpba_SOURCES = LinuxPBA/LinuxPBA.cpp LinuxPBA/GetPassPhrase.cpp LinuxPBA/Unl
linux/DtaDevLinuxNvme.cpp linux/DtaDevLinuxNvme.h \
linux/DtaDevLinuxSata.cpp linux/DtaDevLinuxSata.h \
linux/DtaDevOS.cpp linux/DtaDevOS.h \
linux/DtaDevLinuxDrive.h linux/os.h \
linux/DtaDevLinuxDrive.cpp linux/DtaDevLinuxDrive.h \
linux/os.h \
\
$(SEDUTIL_COMMON_CODE)
EXTRA_DIST = linux/GitVersion.sh linux/PSIDRevert_LINUX.txt linux/TestSuite.sh README.md docs/sedutil-cli.8
Expand Down
4 changes: 3 additions & 1 deletion images/buildroot/packages/sedutil/sedutil.mk
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ define SEDUTIL_POST_EXTRACT_ACTIONS
sed -i '/^CLEANFILES/d' $(BUILD_DIR)/sedutil-$(SEDUTIL_VERSION)/Makefile.am
sed -i '/^BUILT_SOURCES/d' $(BUILD_DIR)/sedutil-$(SEDUTIL_VERSION)/Makefile.am
sed -i '/^linux\/Version/,3 d' $(BUILD_DIR)/sedutil-$(SEDUTIL_VERSION)/Makefile.am
sed -i 's/^AM_CXXFLAGS.*/\0 -DPBA_BUILD/' $(BUILD_DIR)/sedutil-$(SEDUTIL_VERSION)/Makefile.am
sed -i '/^BUILT_SOURCES/d' $(BUILD_DIR)/sedutil-$(SEDUTIL_VERSION)/Makefile.in
sed -i '/^CLEANFILES/d' $(BUILD_DIR)/sedutil-$(SEDUTIL_VERSION)/Makefile.in
sed -i '/^linux\/Version/,3 d' $(BUILD_DIR)/sedutil-$(SEDUTIL_VERSION)/Makefile.in
sed -i 's/^AM_CXXFLAGS.*/\0 -DPBA_BUILD/' $(BUILD_DIR)/sedutil-$(SEDUTIL_VERSION)/Makefile.in
endef
SEDUTIL_POST_EXTRACT_HOOKS += SEDUTIL_POST_EXTRACT_ACTIONS
$(eval $(autotools-package))
$(eval $(autotools-package))
53 changes: 53 additions & 0 deletions linux/DtaDevLinuxDrive.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* C:B**************************************************************************
Copyright 2017, Alex Badics

This file is part of sedutil.

sedutil 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 3 of the License, or
(at your option) any later version.

sedutil 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 sedutil. If not, see <http://www.gnu.org/licenses/>.

* C:E********************************************************************** */
#include "os.h"
#include <sys/ioctl.h>
#include "DtaDevLinuxDrive.h"
#ifndef PBA_BUILD
#include <linux/sed-opal.h>
#endif

using namespace std;

uint8_t DtaDevLinuxDrive::prepareForS3Sleep(uint8_t lockingrange, const vector<uint8_t> &password_hash)
{
LOG(D1) << "Entering DtaDevLinuxDrive::prepareForS3Sleep";

#ifdef PBA_BUILD
LOG(E) << "prepareForS3Sleep not supported in PBA build";
return -1;
#else
opal_lock_unlock opal_ioctl_data={};
opal_ioctl_data.l_state = OPAL_RW;
opal_ioctl_data.session.who = OPAL_ADMIN1;
opal_ioctl_data.session.opal_key.lr = lockingrange;

size_t hash_len=min(password_hash.size(), sizeof(opal_ioctl_data.session.opal_key.key));
LOG(D2) << "Setting a hash of length" << hash_len;

memcpy(opal_ioctl_data.session.opal_key.key, &password_hash[0], hash_len);
opal_ioctl_data.session.opal_key.key_len = hash_len;

int err = ioctl(fd, IOC_OPAL_SAVE, &opal_ioctl_data);
if (err < 0)
return errno;
return 0;
#endif
}
Loading