From d543dd4f32202e9211a936ff1dae16f334779c27 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 18 Nov 2017 22:51:21 +0100 Subject: [PATCH 1/4] Option to print the password hash Useful for users, who want to use different utilities with their SED drives, and also in combination with "-x -n", meaning "no hash", "hex", so no plaintext passwords are saved to scripts or shell history. --- Common/DtaDev.cpp | 19 +++++++++++++++++++ Common/DtaDev.h | 3 +++ Common/DtaOptions.cpp | 7 +++++++ Common/DtaOptions.h | 1 + Common/sedutil.cpp | 4 ++++ 5 files changed, 34 insertions(+) diff --git a/Common/DtaDev.cpp b/Common/DtaDev.cpp index 0dbc3b13..30e4930a 100644 --- a/Common/DtaDev.cpp +++ b/Common/DtaDev.cpp @@ -32,6 +32,7 @@ along with sedutil. If not, see . #include "DtaConstants.h" #include "DtaEndianFixup.h" #include "DtaHexDump.h" +#include "DtaHashPwd.h" using namespace std; @@ -211,6 +212,24 @@ void DtaDev::discovery0() while (cpos < epos); } + +uint8_t DtaDev::printPasswordHash(char * password) +{ + LOG(D1) << "Entering DtaDev::printPasswordHash()"; + vector 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()"; diff --git a/Common/DtaDev.h b/Common/DtaDev.h index 473f7bd0..03bc37a6 100644 --- a/Common/DtaDev.h +++ b/Common/DtaDev.h @@ -74,6 +74,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 diff --git a/Common/DtaOptions.cpp b/Common/DtaOptions.cpp index 9be2af17..f3ff4272 100644 --- a/Common/DtaOptions.cpp +++ b/Common/DtaOptions.cpp @@ -97,6 +97,9 @@ void usage() printf(" revert the device using the PSID *ERASING* *ALL* the data \n"); printf("--printDefaultPassword \n"); printf(" print MSID \n"); + printf("--printPasswordHash \n"); + printf(" print the hash of the password \n"); + printf(" as computed by sedutil. Hex-ecoded.\n"); printf("\n"); printf("Examples \n"); printf("sedutil-cli --scan \n"); @@ -512,6 +515,10 @@ 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(rawCmd, 7) i += 6; OPTION_IS(device) END_OPTION else { LOG(E) << "Invalid command line argument " << argv[i]; diff --git a/Common/DtaOptions.h b/Common/DtaOptions.h index c012af1d..48bffd15 100644 --- a/Common/DtaOptions.h +++ b/Common/DtaOptions.h @@ -95,6 +95,7 @@ typedef enum _sedutiloption { validatePBKDF2, objDump, printDefaultPassword, + printPasswordHash, rawCmd, } sedutiloption; diff --git a/Common/sedutil.cpp b/Common/sedutil.cpp index fe6df19a..4a5bbc5b 100644 --- a/Common/sedutil.cpp +++ b/Common/sedutil.cpp @@ -259,6 +259,10 @@ 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::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]); From e4c042a0bb1aa180bd794ab361610f37b81daf34 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 19 Nov 2017 00:44:28 +0100 Subject: [PATCH 2/4] Add S3 sleep support for Linux The new command is --prepareForS3Sleep, and it should be called every new boot, as it stores the drive key (password hash) in kernel memory. --- Common/DtaDev.cpp | 6 +++++ Common/DtaDev.h | 5 +++++ Common/DtaOptions.cpp | 24 ++++++++++++++++++++ Common/DtaOptions.h | 1 + Common/sedutil.cpp | 4 ++++ Makefile.am | 6 +++-- linux/DtaDevLinuxDrive.cpp | 46 ++++++++++++++++++++++++++++++++++++++ linux/DtaDevLinuxDrive.h | 5 +++++ linux/DtaDevLinuxNvme.h | 1 - linux/DtaDevLinuxSata.h | 1 - linux/DtaDevOS.cpp | 33 +++++++++++++++++++++++++++ linux/DtaDevOS.h | 2 ++ 12 files changed, 130 insertions(+), 4 deletions(-) create mode 100755 linux/DtaDevLinuxDrive.cpp diff --git a/Common/DtaDev.cpp b/Common/DtaDev.cpp index 30e4930a..7bd4493d 100644 --- a/Common/DtaDev.cpp +++ b/Common/DtaDev.cpp @@ -319,3 +319,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; +} diff --git a/Common/DtaDev.h b/Common/DtaDev.h index 03bc37a6..a8386cd8 100644 --- a/Common/DtaDev.h +++ b/Common/DtaDev.h @@ -252,6 +252,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 ti use for the dump diff --git a/Common/DtaOptions.cpp b/Common/DtaOptions.cpp index f3ff4272..86e595b5 100644 --- a/Common/DtaOptions.cpp +++ b/Common/DtaOptions.cpp @@ -100,6 +100,9 @@ void usage() printf("--printPasswordHash \n"); printf(" print the hash of the password \n"); printf(" as computed by sedutil. Hex-ecoded.\n"); + printf("--prepareForS3Sleep <0...n> \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"); @@ -519,6 +522,27 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) 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]; diff --git a/Common/DtaOptions.h b/Common/DtaOptions.h index 48bffd15..387d69b4 100644 --- a/Common/DtaOptions.h +++ b/Common/DtaOptions.h @@ -96,6 +96,7 @@ typedef enum _sedutiloption { objDump, printDefaultPassword, printPasswordHash, + prepareForS3Sleep, rawCmd, } sedutiloption; diff --git a/Common/sedutil.cpp b/Common/sedutil.cpp index 4a5bbc5b..f12d47cd 100644 --- a/Common/sedutil.cpp +++ b/Common/sedutil.cpp @@ -263,6 +263,10 @@ int main(int argc, char * argv[]) 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]); diff --git a/Makefile.am b/Makefile.am index 5d105b0d..11e71698 100644 --- a/Makefile.am +++ b/Makefile.am @@ -25,7 +25,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 @@ -36,7 +37,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 diff --git a/linux/DtaDevLinuxDrive.cpp b/linux/DtaDevLinuxDrive.cpp new file mode 100755 index 00000000..d04606a9 --- /dev/null +++ b/linux/DtaDevLinuxDrive.cpp @@ -0,0 +1,46 @@ +/* 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 . + + * C:E********************************************************************** */ +#include "os.h" +#include +#include +#include "DtaDevLinuxDrive.h" + +using namespace std; + +uint8_t DtaDevLinuxDrive::prepareForS3Sleep(uint8_t lockingrange, const vector &password_hash) +{ + LOG(D1) << "Entering DtaDevLinuxDrive::prepareForS3Sleep"; + + 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 = 0; + + 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; +} diff --git a/linux/DtaDevLinuxDrive.h b/linux/DtaDevLinuxDrive.h index d2022a16..39d1951f 100755 --- a/linux/DtaDevLinuxDrive.h +++ b/linux/DtaDevLinuxDrive.h @@ -18,8 +18,10 @@ along with sedutil. If not, see . * C:E********************************************************************** */ #pragma once +#include #include "DtaStructures.h" +using namespace std; /** virtual implementation for a disk interface-generic disk drive */ class DtaDevLinuxDrive { @@ -45,4 +47,7 @@ class DtaDevLinuxDrive { void * buffer, uint32_t bufferlen) = 0; /** Routine to send an identify to the device */ virtual void identify(OPAL_DiskInfo& disk_info) = 0; + /** Save the password hash to the kernel for S3 sleep wakeup */ + uint8_t prepareForS3Sleep(uint8_t lockingrange, const vector &password_hash); + int fd; /**< Linux handle for the device */ }; diff --git a/linux/DtaDevLinuxNvme.h b/linux/DtaDevLinuxNvme.h index 3ea6874d..b305a88f 100755 --- a/linux/DtaDevLinuxNvme.h +++ b/linux/DtaDevLinuxNvme.h @@ -59,5 +59,4 @@ class DtaDevLinuxNvme: public DtaDevLinuxDrive{ void * buffer, uint32_t bufferlen); /** NVMe specific routine to send an identify to the device */ void identify(OPAL_DiskInfo& disk_info); - int fd; /**< Linux handle for the device */ }; diff --git a/linux/DtaDevLinuxSata.h b/linux/DtaDevLinuxSata.h index 14b7e12a..6e19b44d 100755 --- a/linux/DtaDevLinuxSata.h +++ b/linux/DtaDevLinuxSata.h @@ -55,6 +55,5 @@ class DtaDevLinuxSata: public DtaDevLinuxDrive { void * buffer, uint32_t bufferlen); /** Linux specific routine to send an ATA identify to the device */ void identify_SAS(OPAL_DiskInfo *disk_info); - int fd; /**< Linux handle for the device */ int isSAS; /* The device is sas */ }; diff --git a/linux/DtaDevOS.cpp b/linux/DtaDevOS.cpp index 5261e736..342d63f3 100644 --- a/linux/DtaDevOS.cpp +++ b/linux/DtaDevOS.cpp @@ -38,6 +38,9 @@ along with sedutil. If not, see . #include "DtaDevLinuxSata.h" #include "DtaDevLinuxNvme.h" #include "DtaDevGeneric.h" +#include "DtaHashPwd.h" +#include "DtaSession.h" +#include "DtaDevOpal.h" using namespace std; @@ -165,6 +168,36 @@ int DtaDevOS::diskScan() return 0; } +uint8_t DtaDevOS::prepareForS3Sleep(uint8_t lockingrange, char* password) +{ + LOG(D1) << "Entering DtaDevOS::prepareForS3Sleep "; + LOG(D2) << "Starting testing of password "; + session = new DtaSession(this); + if (NULL == session) { + LOG(E) << "Unable to create session object "; + return DTAERROR_OBJECT_CREATE_FAILED; + } + int err; + if ((err = session->start(OPAL_UID::OPAL_LOCKINGSP_UID, password, OPAL_UID::OPAL_ADMIN1_UID)) != 0) { + delete session; + LOG(E) << "Unable to authenticate with the given password"; + return err; + } + delete session; + LOG(D2) << "Test successful, saving it to kernel "; + vector hash; + DtaHashPwd(hash, password, this); + hash.erase(hash.begin(), hash.begin()+2); + + err = drive->prepareForS3Sleep(0, hash); + if (err) + { + LOG(E) << "Error saving the password to the kernel errno = " << errno; + return errno; + } + return 0; +} + /** Close the device reference so this object can be delete. */ DtaDevOS::~DtaDevOS() { diff --git a/linux/DtaDevOS.h b/linux/DtaDevOS.h index beeacb38..fc3705fc 100644 --- a/linux/DtaDevOS.h +++ b/linux/DtaDevOS.h @@ -49,6 +49,8 @@ class DtaDevOS : public DtaDev { void * buffer, uint32_t bufferlen); /** A static class to scan for supported drives */ static int diskScan(); + /** Save device key to kernel for S3 sleep resume */ + uint8_t prepareForS3Sleep(uint8_t lockingrange, char* password); protected: /** OS specific command to Wait for specified number of milliseconds * @param ms number of milliseconds to wait From 40364297dc1687a96ab86937537093b4da461fb2 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 18 Nov 2017 22:25:22 +0100 Subject: [PATCH 3/4] Add option to use non-ascii passwords This is to allow proper '-h' (no password hashing) usage, where the user might have saved the hash itself, or used a different hashing mechanism altogether, and ends up with 0 bytes or control characters in the resulting string. --- Common/DtaDev.h | 1 + Common/DtaHashPwd.cpp | 48 +++++++++++++++++++++++++++++-------------- Common/DtaHashPwd.h | 2 +- Common/DtaOptions.cpp | 7 ++++++- Common/DtaOptions.h | 1 + Common/sedutil.cpp | 2 ++ 6 files changed, 44 insertions(+), 17 deletions(-) diff --git a/Common/DtaDev.h b/Common/DtaDev.h index a8386cd8..e103633c 100644 --- a/Common/DtaDev.h +++ b/Common/DtaDev.h @@ -292,6 +292,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 */ diff --git a/Common/DtaHashPwd.cpp b/Common/DtaHashPwd.cpp index e33d7585..909df393 100644 --- a/Common/DtaHashPwd.cpp +++ b/Common/DtaHashPwd.cpp @@ -32,8 +32,8 @@ extern "C" { } using namespace std; -void DtaHashPassword(vector &hash, char * password, vector salt, - unsigned int iter, uint8_t hashsize) +void DtaHashPassword(vector &hash, const vector &password, + const vector &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 @@ -42,7 +42,7 @@ void DtaHashPassword(vector &hash, char * password, vector 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 @@ -50,7 +50,7 @@ void DtaHashPassword(vector &hash, char * password, vector sal 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(), @@ -67,21 +67,38 @@ void DtaHashPwd(vector &hash, char * password, DtaDev * d) { LOG(D1) << " Entered DtaHashPwd"; char *serNum; + vector 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 salt(serNum, serNum + 20); // vector salt(DEFAULTSALT); - DtaHashPassword(hash, password, salt); + DtaHashPassword(hash, decoded_password, salt); LOG(D1) << " Exit DtaHashPwd"; // log for hash timing } @@ -109,7 +126,7 @@ int testresult(std::vector &result, const char * expected, size_t len) int Testsedutil(const PBKDF_TestTuple *testSet, unsigned int testSetSize) { int pass = 1; - std::vector hash, seaSalt; + std::vector hash, seaSalt, password; for (unsigned int i = 0; i < testSetSize; i++) { const PBKDF_TestTuple &tuple = testSet[i]; @@ -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; } diff --git a/Common/DtaHashPwd.h b/Common/DtaHashPwd.h index d17ae7c3..961c4ebc 100644 --- a/Common/DtaHashPwd.h +++ b/Common/DtaHashPwd.h @@ -41,7 +41,7 @@ void DtaHashPwd(vector &hash, char * password, DtaDev * device); * @param iter number of iterations to be preformed * @param hashsize size of hash to be returned */ -void DtaHashPassword(vector &hash, char * password, vector salt, +void DtaHashPassword(vector &hash, const vector &password, const vector &salt, unsigned int iter = 500000, uint8_t hashsize = 32); /** Test the hshing function using publicly available test cased and report */ int TestPBKDF2(); diff --git a/Common/DtaOptions.cpp b/Common/DtaOptions.cpp index 86e595b5..8e78637e 100644 --- a/Common/DtaOptions.cpp +++ b/Common/DtaOptions.cpp @@ -27,10 +27,11 @@ void usage() printf("a utility to manage self encrypting drives that conform\n"); printf("to the Trusted Computing Group OPAL 2.0 SSC specification\n"); printf("General Usage: (see readme for extended commandset)\n"); - printf("sedutil-cli <-v> <-n> \n"); + printf("sedutil-cli <-v> <-n> <-x> \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"); @@ -147,6 +148,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)) { diff --git a/Common/DtaOptions.h b/Common/DtaOptions.h index 387d69b4..669eef8c 100644 --- a/Common/DtaOptions.h +++ b/Common/DtaOptions.h @@ -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 */ diff --git a/Common/sedutil.cpp b/Common/sedutil.cpp index f12d47cd..4427e87c 100644 --- a/Common/sedutil.cpp +++ b/Common/sedutil.cpp @@ -93,6 +93,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; } From a93049d949eea59758c1fd1e2560126fc2b54027 Mon Sep 17 00:00:00 2001 From: ratcash Date: Wed, 27 May 2020 09:41:28 +0200 Subject: [PATCH 4/4] Readme to include S3 Sleep support setup / usage --- README.md | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3bb7d645..90158243 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ Unique to this repo are the following modifications: * SHA512 password hashing vs SHA1 on original SEDutil * Compatibile with AMD Ryzen and AMD Ryzen mobile systems +* Supports S3 sleep ## Build Process @@ -270,7 +271,48 @@ Expected Output: You now need to COMPLETELY POWER DOWN YOUR SYSTEM This will lock the drive so that when you restart your system it will boot the PBA. -#Recovery information: +## S3 sleep support + +To make the machine able to recover from sleep, the following is needed: +* Kernel 4.13 or later +* this patched sedutil-cli +* following the guide here: https://github.com/ladar/sedutil/issues/4#issue-482078217 , (which in turn was born from Drive-Trust-Alliance/sedutil#90). For completeness, mirrored below: + +1. (Optional for NVME drives, required for SATA) Edit /etc/default/grub to append `libata.allow_tpm=1` to the end the line GRUB_CMDLINE_LINUX_DEFAULT= + +2. (Optional for NVME drives, required for SATA) Update `grub.cfg` by running # `update-grub` + +3. Download (or build) the Linux binary from the release of this repo; extract and have it ready to run + +4. (Optional for NVME drives, required for SATA) Reboot + +5. Find your encryption key by +``` +# sedutil-cli --printPasswordHash /dev/nvme? +``` +(namespace needs to be included for NVMe, e.g. /dev/nvme0n1; same for the following) + +6. Add a systemd service that will execute the following command that will tell the kernel what password to use after wakeup. Note that the password needs to be in the hashed format already. + +``` +# sedutil-cli -n -x --prepareForS3Sleep 0 Admin1 /dev/nvme? +``` +Below is my /etc/systemd/system/seds3sleep.service + +``` +[Service] +Type=oneshot +ExecStart=/opt/sedutil-1.15.1-87/sedutil-cli -n -x --prepareForS3Sleep 0 Admin1 /dev/nvme? + +[Install] +WantedBy=multi-user.target +Enable this service. # systemctl enable seds3sleep.service && systemctl start seds3sleep.service +``` + +**NOTE:** if you have multiple disks, you may want to include multiple `ExecStart` commands, and ideally try all the disks for all passwords as their numbers may randomly change. So for 2 disks having different passwords you may want to include 4 ExecStart statements. + + +# Recovery information If there is an issue after enabling locking you can either disable locking or remove OPAL to continue using your drive without locking. @@ -351,5 +393,3 @@ Expected output: When this is finished the drive will be in a non-opal managed state. This would allow you to do anything that you could have done before starting OPAL management under OPAL. You can also reinitiate OPAL management if you wish. - -