From 2cab8d2e60d0e8f07d91f931647fb7d58ab01733 Mon Sep 17 00:00:00 2001 From: Davide Cavalca Date: Aug 18 2022 15:22:06 +0000 Subject: Update to 1.20.0 and backport securemode, verifySIDPassword --- diff --git a/.gitignore b/.gitignore index af80f9f..cf76789 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /sedutil-1.12.tar.gz /sedutil-1.15.1.tar.gz +/sedutil-1.20.0.tar.gz diff --git a/408.patch b/408.patch new file mode 100644 index 0000000..b3d0a21 --- /dev/null +++ b/408.patch @@ -0,0 +1,1484 @@ +From b55cc396ce1a8e9e3961e8ad350a034ac5161348 Mon Sep 17 00:00:00 2001 +From: Howard McLauchlan +Date: Tue, 16 Aug 2022 21:48:38 -0700 +Subject: [PATCH 1/3] Shuffle GetPassPhrase{.h, .cpp} in makefile.am + +Moving GetPassPhrase.o down into SEDUTIL_LINUX_CODE, since we need it +for the securemode/password-setting work. + +This is fine since AFAICT linuxpba_SOURCES eventually gets consumed in +conjunction with SEDUTIL_LINUX_CODE, so that binary will get access to +the TU. + +Keeping this as seperate commit since it might be a little bit subtle / +weird, depending on what Make is doing behind the scenes. + +Signed-off-by: Howard McLauchlan +--- + Makefile.am | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 6656d593..82c51010 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -28,7 +28,8 @@ SEDUTIL_LINUX_CODE = \ + linux/Version.h linux/os.h linux/DtaDevLinuxDrive.h \ + linux/DtaDevLinuxNvme.cpp linux/DtaDevLinuxSata.cpp \ + linux/DtaDevLinuxNvme.h linux/DtaDevLinuxSata.h \ +- linux/DtaDevOS.cpp linux/DtaDevOS.h ++ linux/DtaDevOS.cpp linux/DtaDevOS.h \ ++ LinuxPBA/GetPassPhrase.cpp LinuxPBA/GetPassPhrase.h + sbin_PROGRAMS = sedutil-cli linuxpba + sedutil_cli_SOURCES = Common/sedutil.cpp Common/DtaOptions.cpp \ + Common/DtaOptions.h \ +@@ -37,8 +38,7 @@ sedutil_cli_SOURCES = Common/sedutil.cpp Common/DtaOptions.cpp \ + CLEANFILES = linux/Version.h + BUILT_SOURCES = linux/Version.h + # +-linuxpba_SOURCES = LinuxPBA/LinuxPBA.cpp LinuxPBA/GetPassPhrase.cpp LinuxPBA/UnlockSEDs.cpp \ +- LinuxPBA/GetPassPhrase.h LinuxPBA/UnlockSEDs.h \ ++linuxpba_SOURCES = LinuxPBA/LinuxPBA.cpp LinuxPBA/UnlockSEDs.cpp LinuxPBA/UnlockSEDs.h \ + $(SEDUTIL_LINUX_CODE) \ + $(SEDUTIL_COMMON_CODE) + EXTRA_DIST = linux/GitVersion.sh linux/PSIDRevert_LINUX.txt linux/TestSuite.sh README.md docs/sedutil-cli.8 + +From fc3c2d35a98de84b18b7d6a11f65070147b74024 Mon Sep 17 00:00:00 2001 +From: Howard McLauchlan +Date: Tue, 16 Aug 2022 22:11:04 -0700 +Subject: [PATCH 2/3] Add securemode/password-setting + +*BASICALLY CLEANED UP VERSION OF https://github.com/Drive-Trust-Alliance/sedutil/pull/271* + +This commit does what the linked PR says, and also fixes a few bugs in +that original PR. I'm not sure what the right way to give credit is and +it was very painful to resurrect CVE's original patches and roll my own +on top, so the disclaimer here is that it's like 95% his code :). + +A few notable things: +* We don't need to modify the makefiles, since we split that out in the + prior commit. +* We fixed his original makefile, which didn't quite work: that change + is folded naturally into prior commit. +* The generated makefiles don't need to change, because since CVE's + original patchset, GetPassPhrase.o was introduced organically to the + codebase, and ergo the makefiles. + +The most interesting thing here is we allow hashing to be forced off by +`-n` even during secure mode. + +The key issue we ran into was that if a drive is originally set with no +hashing, then hash'd invocations in the future will fail(obviously). As +implemented, CVE's original patches will silently debug output, and then +turn on hashing without telling the user. + +Not a domain expert in why hashing is necessary here, but in either +case, I think we should support the case where a password was originally +set without hashing, by allowing hashing to be turned off _if_ specified +explicitly. + +We also do some sneaky business by ensuring -n is evaluated after -s, so +-n will always override -s, if provided. + +Signed-off-by: Howard McLauchlan +--- + Common/DtaDev.h | 16 +++-- + Common/DtaDevEnterprise.cpp | 30 ++++++--- + Common/DtaDevEnterprise.h | 16 +++-- + Common/DtaDevGeneric.cpp | 12 ++-- + Common/DtaDevGeneric.h | 17 +++-- + Common/DtaDevOpal.cpp | 128 ++++++++++++++++++++++++++++-------- + Common/DtaDevOpal.h | 26 ++++++-- + Common/DtaOptions.cpp | 112 ++++++++++++++++++------------- + Common/DtaOptions.h | 36 +++++++--- + Common/sedutil.cpp | 81 ++++++++++++----------- + linux/os.h | 2 + + 11 files changed, 319 insertions(+), 157 deletions(-) + +diff --git a/Common/DtaDev.h b/Common/DtaDev.h +index 473f7bd0..c73c179e 100644 +--- a/Common/DtaDev.h ++++ b/Common/DtaDev.h +@@ -111,8 +111,9 @@ class DtaDev { + /** User command to prepare the device for management by sedutil. + * Specific to the SSC that the device supports + * @param password the password that is to be assigned to the SSC master entities ++ * @param securemode is the new password should be interactively asked + */ +- virtual uint8_t initialSetup(char * password) = 0; ++ virtual uint8_t initialSetup(char * password, bool securemode = false) = 0; + /** User command to prepare the drive for Single User Mode and rekey a SUM locking range. + * @param lockingrange locking range number to enable + * @param start LBA to start locking range +@@ -120,28 +121,30 @@ class DtaDev { + * @param Admin1Password admin1 password for TPer + * @param password User password to set for locking range + */ +- virtual uint8_t setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password) = 0; ++ virtual uint8_t setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password, bool securemode = false) = 0; + /** Set the SID password. + * Requires special handling because password is not always hashed. + * @param oldpassword current SID password + * @param newpassword value password is to be changed to + * @param hasholdpwd is the old password to be hashed before being added to the bytestream + * @param hashnewpwd is the new password to be hashed before being added to the bytestream ++ * @param securemode is the new password should be interactively asked + */ + virtual uint8_t setSIDPassword(char * oldpassword, char * newpassword, +- uint8_t hasholdpwd = 1, uint8_t hashnewpwd = 1) = 0; ++ uint8_t hasholdpwd = 1, uint8_t hashnewpwd = 1, bool securemode = false) = 0; + /** Set the password of a locking SP user. + * @param password current password + * @param userid the userid whose password is to be changed + * @param newpassword value password is to be changed to ++ * @param securemode is the new password shoulb be interactively asked + */ +- virtual uint8_t setPassword(char * password, char * userid, char * newpassword) = 0; ++ virtual uint8_t setPassword(char * password, char * userid, char * newpassword, bool securemode = false) = 0; + /** Set the password of a locking SP user in Single User Mode. + * @param password current user password + * @param userid the userid whose password is to be changed + * @param newpassword value password is to be changed to + */ +- virtual uint8_t setNewPassword_SUM(char * password, char * userid, char * newpassword) = 0; ++ virtual uint8_t setNewPassword_SUM(char * password, char * userid, char * newpassword, bool securemode = false) = 0; + /** Loads a disk image file to the shadow MBR table. + * @param password the password for the administrative authority with access to the table + * @param filename the filename of the disk image +@@ -230,8 +233,9 @@ class DtaDev { + virtual uint8_t eraseLockingRange_SUM(uint8_t lockingrange, char * password) = 0; + /** Change the SID password from it's MSID default + * @param newpassword new password for SID and locking SP admins ++ * @param securemode is the new password should be interactively asked + */ +- virtual uint8_t takeOwnership(char * newpassword) = 0; ++ virtual uint8_t takeOwnership(char * newpassword, bool securemode = false) = 0; + /** Reset the Locking SP to its factory default condition + * ERASES ALL DATA! + * @param password of Administrative user +diff --git a/Common/DtaDevEnterprise.cpp b/Common/DtaDevEnterprise.cpp +index ae649ec5..ba2e97a7 100644 +--- a/Common/DtaDevEnterprise.cpp ++++ b/Common/DtaDevEnterprise.cpp +@@ -171,12 +171,12 @@ DtaDevEnterprise::DtaDevEnterprise(const char * devref) + DtaDevEnterprise::~DtaDevEnterprise() + { + } +-uint8_t DtaDevEnterprise::initialSetup(char * password) ++uint8_t DtaDevEnterprise::initialSetup(char * password, bool securemode) + { + LOG(D1) << "Entering initialSetup()"; + uint8_t lastRC; + +- if ((lastRC = takeOwnership(password)) != 0) { ++ if ((lastRC = takeOwnership(password, securemode)) != 0) { + LOG(E) << "Initial setup failed - unable to take ownership"; + return lastRC; + } +@@ -196,7 +196,7 @@ uint8_t DtaDevEnterprise::initialSetup(char * password) + LOG(D1) << "Exiting initialSetup()"; + return 0; + } +-uint8_t DtaDevEnterprise::setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password) ++uint8_t DtaDevEnterprise::setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password, bool securemode) + { + LOG(D1) << "Entering DtaDevEnterprise::setup_SUM"; + LOG(I) << "setup_SUM not supported on DtaDevEnterprise"; +@@ -377,13 +377,18 @@ uint8_t DtaDevEnterprise::revertLockingSP(char * password, uint8_t keep) + LOG(D1) << "Exiting DtaDevEnterprise::revertLockingSP()"; + return 0; + } +-uint8_t DtaDevEnterprise::setPassword(char * password, char * userid, char * newpassword) ++uint8_t DtaDevEnterprise::setPassword(char * password, char * userid, char * newpassword, bool securemode) + { + LOG(D1) << "Entering DtaDevEnterprise::setPassword" ; +- uint8_t lastRC; ++ uint8_t lastRC = 0; + string defaultPassword; + char *pwd = password, *newpwd = newpassword; + ++ if (securemode) { ++ LOG(I) << "setSIDPassword in secure mode in the Enterprise SSC is not supported"; ++ return lastRC; ++ } ++ + if (11 > strnlen(userid, 15)) { + LOG(E) << "Invalid Userid " << userid; + return DTAERROR_INVALID_PARAMETER; +@@ -463,7 +468,7 @@ uint8_t DtaDevEnterprise::setPassword(char * password, char * userid, char * new + LOG(D1) << "Exiting DtaDevEnterprise::setPassword()"; + return 0; + } +-uint8_t DtaDevEnterprise::setNewPassword_SUM(char * password, char * userid, char * newpassword) ++uint8_t DtaDevEnterprise::setNewPassword_SUM(char * password, char * userid, char * newpassword, bool securemode) + { + LOG(D1) << "Entering DtaDevEnterprise::setNewPassword_SUM()"; + LOG(I) << "setNewPassword_SUM is not in the Enterprise SSC and not supported"; +@@ -1022,7 +1027,7 @@ uint8_t DtaDevEnterprise::eraseLockingRange_SUM(uint8_t lockingrange, char * pas + LOG(D1) << "Exiting DtaDevEnterprise::eraseLockingRange_SUM()"; + return DTAERROR_INVALID_PARAMETER; + } +-uint8_t DtaDevEnterprise::takeOwnership(char * newpassword) ++uint8_t DtaDevEnterprise::takeOwnership(char * newpassword, bool securemode) + { + string defaultPassword; + uint8_t lastRC; +@@ -1033,7 +1038,7 @@ uint8_t DtaDevEnterprise::takeOwnership(char * newpassword) + return lastRC; + } + defaultPassword = response.getString(5); +- if ((lastRC = setSIDPassword((char *)defaultPassword.c_str(), newpassword, 0)) != 0) { ++ if ((lastRC = setSIDPassword((char *)defaultPassword.c_str(), newpassword, 0, 1, securemode)) != 0) { + LOG(E) << "takeOwnership failed unable to set new SID password"; + return lastRC; + } +@@ -1270,10 +1275,15 @@ uint8_t DtaDevEnterprise::printDefaultPassword() + return 0; + } + uint8_t DtaDevEnterprise::setSIDPassword(char * oldpassword, char * newpassword, +- uint8_t hasholdpwd, uint8_t hashnewpwd) ++ uint8_t hasholdpwd, uint8_t hashnewpwd, bool securemode) + { + LOG(D1) << "Entering DtaDevEnterprise::setSIDPassword()"; +- uint8_t lastRC; ++ uint8_t lastRC = 0; ++ ++ if (securemode) { ++ LOG(I) << "setSIDPassword in the Enterprise SSC is not supported"; ++ return lastRC; ++ } + + vector user; + set8(user, OPALUID[OPAL_SID_UID]); +diff --git a/Common/DtaDevEnterprise.h b/Common/DtaDevEnterprise.h +index 5350da5c..4a6d2e2e 100644 +--- a/Common/DtaDevEnterprise.h ++++ b/Common/DtaDevEnterprise.h +@@ -57,8 +57,9 @@ class DtaDevEnterprise : public DtaDevOS { + uint16_t comID(); + /** Change the SID password from it's MSID default + * @param newpassword new password for SID ++ * @param securemode is the new password should be interactively asked + */ +- uint8_t takeOwnership(char * newpassword); ++ uint8_t takeOwnership(char * newpassword, bool securemode = false); + /** Change the passwords for the enabled Bandmasters and the Erasemaster + * from the MSID default. + * @param defaultPassword the MSID password +@@ -80,9 +81,10 @@ class DtaDevEnterprise : public DtaDevOS { + * @param newpassword value password is to be changed to + * @param hasholdpwd is the old password to be hashed before being added to the bytestream + * @param hashnewpwd is the new password to be hashed before being added to the bytestream ++ * @param securemode is the new password should be interactively asked + */ + uint8_t setSIDPassword(char * oldpassword, char * newpassword, +- uint8_t hasholdpwd = 1, uint8_t hashnewpwd = 1); ++ uint8_t hasholdpwd = 1, uint8_t hashnewpwd = 1, bool securemode = false); + /** set a single column in an object table + * @param table the UID of the table + * @param name the column name to be set +@@ -124,10 +126,11 @@ class DtaDevEnterprise : public DtaDevOS { + * @param password current password + * @param userid the userid whose password is to be changed + * @param newpassword value password is to be changed to ++ * @param securemode is the new password should be interactively asked + */ +- uint8_t setPassword(char * password, char * userid, char * newpassword); ++ uint8_t setPassword(char * password, char * userid, char * newpassword, bool securemode = false); + /** dummy code not implemented in the enterprise SSC*/ +- uint8_t setNewPassword_SUM(char * password, char * userid, char * newpassword); ++ uint8_t setNewPassword_SUM(char * password, char * userid, char * newpassword, bool securemode = false); + uint8_t setLockingRange(uint8_t lockingrange, uint8_t lockingstate, + char * password); + /** dummy code not implemented in the enterprise SSC*/ +@@ -180,10 +183,11 @@ class DtaDevEnterprise : public DtaDevOS { + /** User command to prepare the device for management by sedutil. + * Specific to the SSC that the device supports + * @param password the password that is to be assigned to the SSC master entities ++ * @param securemode is the new password should be interactively asked + */ +- uint8_t initialSetup(char * password); ++ uint8_t initialSetup(char * password, bool securemode = false); + /** dummy code not implemented in the enterprise SSC*/ +- uint8_t setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password); ++ uint8_t setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password, bool securemode = false); + /** Displays the identify and discovery 0 information */ + void puke(); + /** Dumps an object for diagnostic purposes +diff --git a/Common/DtaDevGeneric.cpp b/Common/DtaDevGeneric.cpp +index 6f5d57c6..8e1bdc91 100644 +--- a/Common/DtaDevGeneric.cpp ++++ b/Common/DtaDevGeneric.cpp +@@ -62,13 +62,13 @@ DtaDevGeneric::~DtaDevGeneric() + void DtaDevGeneric::init(const char * devref) + { + } +-uint8NOCODE(initialSetup, char *password) ++uint8NOCODE(initialSetup, char *password, bool securemode) + uint8NOCODE(configureLockingRange,uint8_t lockingrange, + uint8_t enabled, char * password) + uint8NOCODE(revertLockingSP,char * password, uint8_t keep) +-uint8NOCODE(setup_SUM, uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password) +-uint8NOCODE(setPassword,char * password, char * userid, char * newpassword) +-uint8NOCODE(setNewPassword_SUM,char * password, char * userid, char * newpassword) ++uint8NOCODE(setup_SUM, uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password, bool securemode) ++uint8NOCODE(setPassword,char * password, char * userid, char * newpassword, bool securemode) ++uint8NOCODE(setNewPassword_SUM,char * password, char * userid, char * newpassword, bool securemode) + uint8NOCODE(setMBREnable,uint8_t mbrstate, char * Admin1Password) + uint8NOCODE(setMBRDone,uint8_t mbrstate, char * Admin1Password) + uint8NOCODE(setLockingRange,uint8_t lockingrange, uint8_t lockingstate, +@@ -90,9 +90,9 @@ uint8NOCODE(loadPBA,char * password, char * filename) + uint8NOCODE(activateLockingSP,char * password) + uint8NOCODE(activateLockingSP_SUM,uint8_t lockingrange, char * password) + uint8NOCODE(eraseLockingRange_SUM, uint8_t lockingrange, char * password) +-uint8NOCODE(takeOwnership, char * newpassword) ++uint8NOCODE(takeOwnership, char * newpassword, bool securemode) + uint8NOCODE(setSIDPassword,char * oldpassword, char * newpassword, +- uint8_t hasholdpwd, uint8_t hashnewpwd) ++ uint8_t hasholdpwd, uint8_t hashnewpwd, bool securemode) + uint16_t DtaDevGeneric::comID() + { + LOG(E) << "Generic Device class does not support function " << "comID" << std::endl; +diff --git a/Common/DtaDevGeneric.h b/Common/DtaDevGeneric.h +index 9f5f9752..07728781 100644 +--- a/Common/DtaDevGeneric.h ++++ b/Common/DtaDevGeneric.h +@@ -56,36 +56,40 @@ class DtaDevGeneric : public DtaDevOS { + * Specific to the SSC that the device supports + * @param password the password that is to be assigned to the SSC master entities + */ +- uint8_t initialSetup(char * password) ; ++ uint8_t initialSetup(char * password, bool securemode) ; + /** User command to prepare the drive for Single User Mode and rekey a SUM locking range. + * @param lockingrange locking range number to enable + * @param start LBA to start locking range + * @param length length (in blocks) for locking range + * @param Admin1Password admin1 password for TPer + * @param password User password to set for locking range ++ * @param securemode is the new password shoulb be interactively asked + */ +- uint8_t setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password); ++ uint8_t setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password, bool securemode = false); + /** Set the SID password. + * Requires special handling because password is not always hashed. + * @param oldpassword current SID password + * @param newpassword value password is to be changed to + * @param hasholdpwd is the old password to be hashed before being added to the bytestream + * @param hashnewpwd is the new password to be hashed before being added to the bytestream ++ * @param securemode is the new password shoulb be interactively asked + */ + uint8_t setSIDPassword(char * oldpassword, char * newpassword, +- uint8_t hasholdpwd = 1, uint8_t hashnewpwd = 1) ; ++ uint8_t hasholdpwd = 1, uint8_t hashnewpwd = 1, bool securemode = false) ; + /** Set the password of a locking SP user. + * @param password current password + * @param userid the userid whose password is to be changed + * @param newpassword value password is to be changed to ++ * @param securemode is the new password should be interactively asked + */ +- uint8_t setPassword(char * password, char * userid, char * newpassword) ; ++ uint8_t setPassword(char * password, char * userid, char * newpassword, bool securemode = false) ; + /** Set the password of a locking SP user in Single User Mode. + * @param password current user password + * @param userid the userid whose password is to be changed + * @param newpassword value password is to be changed to ++ * @param securemode is the new password should be interactively asked + */ +- uint8_t setNewPassword_SUM(char * password, char * userid, char * newpassword) ; ++ uint8_t setNewPassword_SUM(char * password, char * userid, char * newpassword, bool securemode = false) ; + /** Loads a disk image file to the shadow MBR table. + * @param password the password for the administrative authority with access to the table + * @param filename the filename of the disk image +@@ -174,8 +178,9 @@ class DtaDevGeneric : public DtaDevOS { + uint8_t eraseLockingRange_SUM(uint8_t lockingrange, char * password); + /** Change the SID password from it's MSID default + * @param newpassword new password for SID and locking SP admins ++ * @param securemode is the new password should be interactively asked + */ +- uint8_t takeOwnership(char * newpassword) ; ++ uint8_t takeOwnership(char * newpassword, bool securemode = false) ; + /** Reset the Locking SP to its factory default condition + * ERASES ALL DATA! + * @param password of Administrative user +diff --git a/Common/DtaDevOpal.cpp b/Common/DtaDevOpal.cpp +index 1cb5701a..0f6ccc70 100644 +--- a/Common/DtaDevOpal.cpp ++++ b/Common/DtaDevOpal.cpp +@@ -50,31 +50,43 @@ void DtaDevOpal::init(const char * devref) + if((lastRC = properties()) != 0) { LOG(E) << "Properties exchange failed";} + } + +-uint8_t DtaDevOpal::initialSetup(char * password) ++uint8_t DtaDevOpal::initialSetup(char * password, bool securemode) + { + LOG(D1) << "Entering initialSetup()"; ++ std::string newpwd; + uint8_t lastRC; +- if ((lastRC = takeOwnership(password)) != 0) { ++ ++#ifdef __linux__ ++ if (securemode) { ++ if (askNewPassword(newpwd, true) != OPALSTATUSCODE::SUCCESS) { ++ LOG(E) << "Wrong password confirmation. Failure of password update."; ++ lastRC = OPALSTATUSCODE::FAIL; ++ return lastRC; ++ } ++ } ++#endif ++ ++ if ((lastRC = takeOwnership((securemode)?(char*)newpwd.c_str():password)) != 0) { + LOG(E) << "Initial setup failed - unable to take ownership"; + return lastRC; + } +- if ((lastRC = activateLockingSP(password)) != 0) { ++ if ((lastRC = activateLockingSP((securemode)?(char*)newpwd.c_str():password)) != 0) { + LOG(E) << "Initial setup failed - unable to activate LockingSP"; + return lastRC; + } +- if ((lastRC = configureLockingRange(0, DTA_DISABLELOCKING, password)) != 0) { ++ if ((lastRC = configureLockingRange(0, DTA_DISABLELOCKING, (securemode)?(char*)newpwd.c_str():password)) != 0) { + LOG(E) << "Initial setup failed - unable to configure global locking range"; + return lastRC; + } +- if ((lastRC = setLockingRange(0, OPAL_LOCKINGSTATE::READWRITE, password)) != 0) { ++ if ((lastRC = setLockingRange(0, OPAL_LOCKINGSTATE::READWRITE, (securemode)?(char*)newpwd.c_str():password)) != 0) { + LOG(E) << "Initial setup failed - unable to set global locking range RW"; + return lastRC; + } +- if ((lastRC = setMBRDone(1, password)) != 0){ ++ if ((lastRC = setMBRDone(1, (securemode)?(char*)newpwd.c_str():password)) != 0){ + LOG(E) << "Initial setup failed - unable to Enable MBR shadow"; + return lastRC; + } +- if ((lastRC = setMBREnable(1, password)) != 0){ ++ if ((lastRC = setMBREnable(1, (securemode)?(char*)newpwd.c_str():password)) != 0){ + LOG(E) << "Initial setup failed - unable to Enable MBR shadow"; + return lastRC; + } +@@ -84,7 +96,7 @@ uint8_t DtaDevOpal::initialSetup(char * password) + return 0; + } + +-uint8_t DtaDevOpal::setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password) ++uint8_t DtaDevOpal::setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password, bool securemode) + { + LOG(D1) << "Entering setup_SUM()"; + uint8_t lastRC; +@@ -108,7 +120,7 @@ uint8_t DtaDevOpal::setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t len + if (!disk_info.Locking_lockingEnabled) + { + LOG(D1) << "LockingSP not enabled. Beginning initial setup flow."; +- if ((lastRC = takeOwnership(Admin1Password)) != 0) { ++ if ((lastRC = takeOwnership(Admin1Password, securemode)) != 0) { + LOG(E) << "Setup_SUM failed - unable to take ownership"; + return lastRC; + } +@@ -147,7 +159,7 @@ uint8_t DtaDevOpal::setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t len + LOG(E) << "Setup_SUM failed - unable to enable locking range"; + return lastRC; + } +- if ((lastRC = setNewPassword_SUM(defaultPW, (char *)userId.c_str(), password)) != 0) { ++ if ((lastRC = setNewPassword_SUM(defaultPW, (char *)userId.c_str(), password, securemode)) != 0) { + LOG(E) << "Setup_SUM failed - unable to set new locking range password"; + return lastRC; + } +@@ -688,12 +700,13 @@ uint8_t DtaDevOpal::getAuth4User(char * userid, uint8_t uidorcpin, std::vector userCPIN, hash; + session = new DtaSession(this); ++ + if (NULL == session) { + LOG(E) << "Unable to create session object "; + return DTAERROR_OBJECT_CREATE_FAILED; +@@ -707,7 +720,28 @@ uint8_t DtaDevOpal::setPassword(char * password, char * userid, char * newpasswo + delete session; + return lastRC; + } +- DtaHashPwd(hash, newpassword, this); ++ ++ // Ask and confirm new password ++#ifdef __linux__ ++ if (securemode) { ++ std::string newpwd; ++ if (askNewPassword(newpwd, true) == OPALSTATUSCODE::SUCCESS) { ++ DtaHashPwd(hash, (char*)newpwd.c_str(), this); ++ } ++ else { ++ LOG(E) << "Wrong password confirmation. Failure of password update."; ++ delete session; ++ lastRC = OPALSTATUSCODE::FAIL; ++ return lastRC; ++ } ++ } ++ else { ++#endif //__linux__ ++ DtaHashPwd(hash, newpassword, this); ++#ifdef __linux__ ++ } ++#endif //__linux__ ++ + if ((lastRC = setTable(userCPIN, OPAL_TOKEN::PIN, hash)) != 0) { + LOG(E) << "Unable to set user " << userid << " new password "; + delete session; +@@ -718,7 +752,7 @@ uint8_t DtaDevOpal::setPassword(char * password, char * userid, char * newpasswo + LOG(D1) << "Exiting DtaDevOpal::setPassword()"; + return 0; + } +-uint8_t DtaDevOpal::setNewPassword_SUM(char * password, char * userid, char * newpassword) ++uint8_t DtaDevOpal::setNewPassword_SUM(char * password, char * userid, char * newpassword, bool securemode) + { + LOG(D1) << "Entering DtaDevOpal::setNewPassword_SUM"; + uint8_t lastRC; +@@ -1391,7 +1425,7 @@ uint8_t DtaDevOpal::eraseLockingRange_SUM(uint8_t lockingrange, char * password) + return 0; + } + +-uint8_t DtaDevOpal::takeOwnership(char * newpassword) ++uint8_t DtaDevOpal::takeOwnership(char * newpassword, bool securemode) + { + LOG(D1) << "Entering DtaDevOpal::takeOwnership()"; + uint8_t lastRC; +@@ -1399,7 +1433,7 @@ uint8_t DtaDevOpal::takeOwnership(char * newpassword) + LOG(E) << "Unable to read MSID password "; + return lastRC; + } +- if ((lastRC = setSIDPassword((char *)response.getString(4).c_str(), newpassword, 0)) != 0) { ++ if ((lastRC = setSIDPassword((char *)response.getString(4).c_str(), newpassword, 0, 1, securemode)) != 0) { + LOG(E) << "takeOwnership failed"; + return lastRC; + } +@@ -1447,7 +1481,7 @@ uint8_t DtaDevOpal::printDefaultPassword() + return 0; + } + uint8_t DtaDevOpal::setSIDPassword(char * oldpassword, char * newpassword, +- uint8_t hasholdpwd, uint8_t hashnewpwd) ++ uint8_t hasholdpwd, uint8_t hashnewpwd, bool securemode) + { + vector hash, table; + LOG(D1) << "Entering DtaDevOpal::setSIDPassword()"; +@@ -1468,17 +1502,39 @@ uint8_t DtaDevOpal::setSIDPassword(char * oldpassword, char * newpassword, + for (int i = 0; i < 8; i++) { + table.push_back(OPALUID[OPAL_UID::OPAL_C_PIN_SID][i]); + } ++ + hash.clear(); +- if (hashnewpwd) { +- DtaHashPwd(hash, newpassword, this); +- } +- else { +- hash.push_back(0xd0); +- hash.push_back((uint8_t)strnlen(newpassword, 255)); +- for (uint16_t i = 0; i < strnlen(newpassword, 255); i++) { +- hash.push_back(newpassword[i]); +- } +- } ++ ++#ifdef __linux__ ++ if (securemode) { ++ // In secure mode, the password hashing is mandatory ++ std::string newpwd; ++ if (askNewPassword(newpwd, true) == OPALSTATUSCODE::SUCCESS) { ++ DtaHashPwd(hash, (char*)newpwd.c_str(), this); ++ } ++ else { ++ LOG(E) << "Wrong password confirmation. Failure of password update."; ++ delete session; ++ lastRC = DTAERROR_INVALID_PARAMETER; ++ return lastRC; ++ } ++ } ++ else { ++#endif //__linux__ ++ if (hashnewpwd) { ++ DtaHashPwd(hash, newpassword, this); ++ } ++ else { ++ hash.push_back(0xd0); ++ hash.push_back((uint8_t)strnlen(newpassword, 255)); ++ for (uint16_t i = 0; i < strnlen(newpassword, 255); i++) { ++ hash.push_back(newpassword[i]); ++ } ++ } ++#ifdef __linux__ ++ } ++#endif //__linux__ ++ + if ((lastRC = setTable(table, OPAL_TOKEN::PIN, hash)) != 0) { + LOG(E) << "Unable to set new SID password "; + delete session; +@@ -1833,4 +1889,22 @@ uint8_t DtaDevOpal::rawCmd(char *sp, char * hexauth, char *pass, + delete session; + LOG(D1) << "Exiting DtaDevEnterprise::rawCmd"; + return 0; +-} +\ No newline at end of file ++} ++#ifdef __linux__ ++uint8_t DtaDevOpal::askNewPassword(std::string &password, bool confirm) { ++ uint8_t lastRC = OPALSTATUSCODE::SUCCESS; ++ password = GetPassPhrase("Please enter the new password "); ++ ++ if (confirm) { ++ std::string pwdcheck = GetPassPhrase("Please confirm the new password "); ++ ++ if (password != pwdcheck) { ++ password.clear(); ++ lastRC = OPALSTATUSCODE::FAIL; ++ } ++ } ++ ++ return lastRC; ++} ++#endif //__linux__ ++ +diff --git a/Common/DtaDevOpal.h b/Common/DtaDevOpal.h +index 60004db4..389b97f9 100644 +--- a/Common/DtaDevOpal.h ++++ b/Common/DtaDevOpal.h +@@ -61,8 +61,9 @@ class DtaDevOpal : public DtaDevOS { + virtual uint16_t comID() = 0; + /** Change the SID password from it's MSID default + * @param newpassword new password for SID ++ * @param securemode is the new password should be interactively asked + */ +- uint8_t takeOwnership(char * newpassword); ++ uint8_t takeOwnership(char * newpassword, bool securemode = false); + /** retrieve the MSID password */ + uint8_t printDefaultPassword(); + /** retrieve a single row from a table +@@ -78,9 +79,10 @@ class DtaDevOpal : public DtaDevOS { + * @param newpassword value password is to be changed to + * @param hasholdpwd is the old password to be hashed before being added to the bytestream + * @param hashnewpwd is the new password to be hashed before being added to the bytestream ++ * @param securemode is the new password should be interactively asked + */ + uint8_t setSIDPassword(char * oldpassword, char * newpassword, +- uint8_t hasholdpwd = 1, uint8_t hashnewpwd = 1); ++ uint8_t hasholdpwd = 1, uint8_t hashnewpwd = 1, bool securemode = false); + /** set a single column in an object table + * @param table the UID of the table + * @param name the column name to be set +@@ -143,14 +145,16 @@ class DtaDevOpal : public DtaDevOS { + * @param password current password + * @param userid the userid whose password is to be changed + * @param newpassword value password is to be changed to ++ * @param securemode is the new password should be interactively asked + */ +- uint8_t setPassword(char * password, char * userid, char * newpassword); ++ uint8_t setPassword(char * password, char * userid, char * newpassword, bool securemode = false); + /** Set the password of a locking SP user in Single User Mode. + * @param password current user password + * @param userid the userid whose password is to be changed + * @param newpassword value password is to be changed to ++ * @param securemode is the new password should be interactively asked + */ +- uint8_t setNewPassword_SUM(char * password, char * userid, char * newpassword); ++ uint8_t setNewPassword_SUM(char * password, char * userid, char * newpassword, bool securemode = false); + /** User command to manipulate the state of a locking range. + * RW|RO|LK are the supported states @see OPAL_LOCKINGSTATE + * @param lockingrange locking range number +@@ -229,16 +233,18 @@ class DtaDevOpal : public DtaDevOS { + /** User command to prepare the device for management by sedutil. + * Specific to the SSC that the device supports + * @param password the password that is to be assigned to the SSC master entities ++ * @param securemode is the new password should be interactively asked + */ +- uint8_t initialSetup(char * password); ++ uint8_t initialSetup(char * password, bool securemode); + /** User command to prepare the drive for Single User Mode and rekey a SUM locking range. + * @param lockingrange locking range number to enable + * @param start LBA to start locking range + * @param length length (in blocks) for locking range + * @param Admin1Password admin1 password for TPer + * @param password User password to set for locking range ++ * @param securemode is the new password should be interactively asked + */ +- uint8_t setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password); ++ uint8_t setup_SUM(uint8_t lockingrange, uint64_t start, uint64_t length, char *Admin1Password, char * password, bool securemode = false); + /** Displays the identify and discovery 0 information */ + void puke(); + /** Dumps an object for diagnostic purposes +@@ -289,4 +295,12 @@ class DtaDevOpal : public DtaDevOS { + */ + lrStatus_t getLockingRange_status(uint8_t lockingrange, char * password); + ++ /** Ask the user to input a new password. ++ * This function fails if the first password and it's confirmation differs ++ * @param password The new password entered by the user ++ * @param confirm Is a double check necessary ++ */ ++#ifdef __linux__ ++ uint8_t askNewPassword(std::string &password, bool confirm = false); ++#endif //__linux__ + }; +diff --git a/Common/DtaOptions.cpp b/Common/DtaOptions.cpp +index fdacc403..0d1752ee 100644 +--- a/Common/DtaOptions.cpp ++++ b/Common/DtaOptions.cpp +@@ -27,8 +27,10 @@ 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> <-s> \n"); + printf("-v (optional) increase verbosity, one to five v's\n"); ++ printf("-s (optional) secure mode. Passwords will be asked interactively to the user.\n"); ++ printf(" Available only on linux.\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("actions \n"); +@@ -130,11 +132,31 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + LOG(D) << "Log level set to " << CLog::ToString(CLog::FromInt(loggingLevel)); + LOG(D) << "sedutil version : " << GIT_VERSION; + } ++ else if (!(strcmp("-s", argv[i]))) { ++ baseOptions += 1; ++#ifdef __linux__ ++ opts->secure_mode = true; ++ opts->no_hash_passwords = false; ++#else ++ LOG(E) << "Secure mode not implemented"; ++#endif //__linux__ ++ } + else if (!(strcmp("-n", argv[i]))) { +- baseOptions += 1; +- opts->no_hash_passwords = true; +- LOG(D) << "Password hashing is disabled"; +- } ++ baseOptions += 1; ++#ifdef __linux__ ++ if (!opts->secure_mode) { ++#endif //__linux__ ++ opts->no_hash_passwords = true; ++ LOG(D) << "Password hashing is disabled"; ++#ifdef __linux__ ++ } ++ else { ++ LOG(D) << "No password hashing incompatible with secure mode"; ++ } ++ LOG(D) << "Disabling password hashing in secure mode (-s)"; ++ opts->no_hash_passwords = true; ++#endif //__linux__ ++ } + else if (!strcmp("-l", argv[i])) { + baseOptions += 1; + opts->output_format = sedutilNormal; +@@ -146,10 +168,10 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + LOG(E) << "Argument " << (uint16_t) i << " (" << argv[i] << ") should be a command"; + return DTAERROR_INVALID_COMMAND; + } +- BEGIN_OPTION(initialSetup, 2) OPTION_IS(password) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(setSIDPassword, 3) OPTION_IS(password) OPTION_IS(newpassword) ++ BEGIN_OPTION(initialSetup, 2, 1) OPTION_IS(password) OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(setSIDPassword, 3, 1) OPTION_IS(password) OPTION_IS(newpassword) + OPTION_IS(device) END_OPTION +- BEGIN_OPTION(setup_SUM, 6) ++ BEGIN_OPTION(setup_SUM, 6, 4) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -173,20 +195,20 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(newpassword) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(setAdmin1Pwd, 3) OPTION_IS(password) OPTION_IS(newpassword) ++ BEGIN_OPTION(setAdmin1Pwd, 3, 1) OPTION_IS(password) OPTION_IS(newpassword) + OPTION_IS(device) END_OPTION +- BEGIN_OPTION(loadPBAimage, 3) OPTION_IS(password) OPTION_IS(pbafile) ++ BEGIN_OPTION(loadPBAimage, 3, 2) OPTION_IS(password) OPTION_IS(pbafile) + OPTION_IS(device) END_OPTION +- BEGIN_OPTION(revertTPer, 2) OPTION_IS(password) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(revertNoErase, 2) OPTION_IS(password) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(PSIDrevert, 2) OPTION_IS(password) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(PSIDrevertAdminSP, 2) OPTION_IS(password) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(yesIreallywanttoERASEALLmydatausingthePSID, 2) OPTION_IS(password) ++ BEGIN_OPTION(revertTPer, 2, 1) OPTION_IS(password) OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(revertNoErase, 2, 1) OPTION_IS(password) OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(PSIDrevert, 2, 1) OPTION_IS(password) OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(PSIDrevertAdminSP, 2, 1) OPTION_IS(password) OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(yesIreallywanttoERASEALLmydatausingthePSID, 2, 1) OPTION_IS(password) + OPTION_IS(device) END_OPTION +- BEGIN_OPTION(enableuser, 2) OPTION_IS(password) OPTION_IS(userid) ++ BEGIN_OPTION(enableuser, 3, 2) OPTION_IS(password) OPTION_IS(userid) + OPTION_IS(device) END_OPTION +- BEGIN_OPTION(activateLockingSP, 2) OPTION_IS(password) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(activateLockingSP_SUM, 3) ++ BEGIN_OPTION(activateLockingSP, 2, 1) OPTION_IS(password) OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(activateLockingSP_SUM, 3, 2) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -205,7 +227,7 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + TESTARG(15, lockingrange, 15) + TESTFAIL("Invalid Locking Range (0-15)") + OPTION_IS(password) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(eraseLockingRange_SUM, 3) ++ BEGIN_OPTION(eraseLockingRange_SUM, 3, 2) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -224,10 +246,10 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + TESTARG(15, lockingrange, 15) + TESTFAIL("Invalid Locking Range (1-15)") + OPTION_IS(password) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(query, 1) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(scan, 0) END_OPTION +- BEGIN_OPTION(isValidSED, 1) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(eraseLockingRange, 3) ++ BEGIN_OPTION(query, 1, 1) OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(scan, 0, 0) END_OPTION ++ BEGIN_OPTION(isValidSED, 1, 1) OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(eraseLockingRange, 3, 2) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -248,14 +270,14 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(takeOwnership, 2) OPTION_IS(password) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(revertLockingSP, 2) OPTION_IS(password) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(setPassword, 4) OPTION_IS(password) OPTION_IS(userid) ++ BEGIN_OPTION(takeOwnership, 2, 1) OPTION_IS(password) OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(revertLockingSP, 2, 1) OPTION_IS(password) OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(setPassword, 4, 2) OPTION_IS(password) OPTION_IS(userid) + OPTION_IS(newpassword) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(setPassword_SUM, 4) OPTION_IS(password) OPTION_IS(userid) ++ BEGIN_OPTION(setPassword_SUM, 4, 2) OPTION_IS(password) OPTION_IS(userid) + OPTION_IS(newpassword) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(validatePBKDF2, 0) END_OPTION +- BEGIN_OPTION(setMBREnable, 3) ++ BEGIN_OPTION(validatePBKDF2, 0, 0) END_OPTION ++ BEGIN_OPTION(setMBREnable, 3, 2) + TESTARG(ON, mbrstate, 1) + TESTARG(on, mbrstate, 1) + TESTARG(off, mbrstate, 0) +@@ -264,7 +286,7 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(setMBRDone, 3) ++ BEGIN_OPTION(setMBRDone, 3, 2) + TESTARG(ON, mbrstate, 1) + TESTARG(on, mbrstate, 1) + TESTARG(off, mbrstate, 0) +@@ -273,7 +295,7 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(setLockingRange, 4) ++ BEGIN_OPTION(setLockingRange, 4, 3) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -301,7 +323,7 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(setLockingRange_SUM, 4) ++ BEGIN_OPTION(setLockingRange_SUM, 4, 3) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -329,7 +351,7 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(enableLockingRange, 3) ++ BEGIN_OPTION(enableLockingRange, 3, 2) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -350,7 +372,7 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(disableLockingRange, 3) ++ BEGIN_OPTION(disableLockingRange, 3, 2) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -371,7 +393,7 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(setupLockingRange, 5) ++ BEGIN_OPTION(setupLockingRange, 5, 4) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -394,7 +416,7 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(setupLockingRange_SUM, 5) ++ BEGIN_OPTION(setupLockingRange_SUM, 5, 4) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -417,7 +439,7 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(readonlyLockingRange, 3) ++ BEGIN_OPTION(readonlyLockingRange, 3, 2) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -438,11 +460,11 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(listLockingRanges, 2) ++ BEGIN_OPTION(listLockingRanges, 2, 1) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(listLockingRange, 3) ++ BEGIN_OPTION(listLockingRange, 3, 2) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -463,7 +485,7 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(rekeyLockingRange, 3) ++ BEGIN_OPTION(rekeyLockingRange, 3, 2) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -484,11 +506,11 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(setBandsEnabled, 2) ++ BEGIN_OPTION(setBandsEnabled, 2, 1) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(setBandEnabled, 3) ++ BEGIN_OPTION(setBandEnabled, 3, 2) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) + TESTARG(2, lockingrange, 2) +@@ -509,9 +531,9 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + OPTION_IS(password) + OPTION_IS(device) + END_OPTION +- BEGIN_OPTION(objDump, 5) i += 4; OPTION_IS(device) END_OPTION +- BEGIN_OPTION(printDefaultPassword, 1) OPTION_IS(device) END_OPTION +- BEGIN_OPTION(rawCmd, 7) i += 6; OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(objDump, 5, 5) i += 4; OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(printDefaultPassword, 1, 1) OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(rawCmd, 7, 7) i += 6; OPTION_IS(device) END_OPTION + else { + LOG(E) << "Invalid command line argument " << argv[i]; + return DTAERROR_INVALID_COMMAND; +diff --git a/Common/DtaOptions.h b/Common/DtaOptions.h +index c012af1d..4ae3bc29 100644 +--- a/Common/DtaOptions.h ++++ b/Common/DtaOptions.h +@@ -43,6 +43,8 @@ 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 secure_mode; /** global parameter, enable the secure mode */ ++ bool ask_password; /** global parameter, to know if the password needs to be interactively asked to the user */ + sedutiloutput output_format; + } DTA_OPTIONS; + /** Print a usage message */ +@@ -98,16 +100,18 @@ typedef enum _sedutiloption { + rawCmd, + + } sedutiloption; ++ + /** verify the number of arguments passed */ +-#define CHECKARGS(x) \ +-if((x+baseOptions) != argc) { \ +- LOG(E) << "Incorrect number of paramaters for " << argv[i] << " command"; \ +- return 100; \ +- } ++#define CHECKARGS(x1, x2) \ ++ int a = opts->secure_mode? x2: x1;\ ++ if((a+baseOptions) != argc) { \ ++ LOG(E) << "Incorrect number of paramaters for " << argv[i] << " command"; \ ++ return 100; \ ++ } + /** Test the command input for a recognized argument */ +-#define BEGIN_OPTION(cmdstring,args) \ ++#define BEGIN_OPTION(cmdstring,args,args_secure) \ + else if (!(strcasecmp(#cmdstring, &argv[i][2]))) { \ +- CHECKARGS(args) \ ++ CHECKARGS(args, args_secure) \ + opts->action = sedutiloption::cmdstring; \ + + /** end of an OPTION */ +@@ -126,6 +130,22 @@ i++; + + /** set the argc value for this parameter in the options structure */ + #define OPTION_IS(option_field) \ +- opts->option_field = ++i; ++ if (opts->secure_mode && \ ++ (!(strcasecmp(#option_field, "password")) || \ ++ !(strcasecmp(#option_field, "newpassword")))) { \ ++ opts->option_field = 255; \ ++ if (opts->action != sedutiloption::initialSetup)\ ++ opts->ask_password = true; \ ++ } \ ++ else { \ ++ opts->option_field = ++i; \ ++ }\ ++ ++/** Return the interactive password in secure mode or command line arg*/ ++#define GET_PASSWORD() \ ++ opts.secure_mode? (char*) interactive_password.c_str() : argv[opts.password]\ ++ ++#define GET_NEW_PASSWORD() \ ++ opts.secure_mode? (char*)"" : argv[opts.newpassword]\ + + #endif /* _DTAOPTIONS_H */ +diff --git a/Common/sedutil.cpp b/Common/sedutil.cpp +index fe6df19a..7053cd3c 100644 +--- a/Common/sedutil.cpp ++++ b/Common/sedutil.cpp +@@ -54,10 +54,17 @@ int main(int argc, char * argv[]) + { + DTA_OPTIONS opts; + DtaDev *tempDev = NULL, *d = NULL; ++ std::string interactive_password; + if (DtaOptions(argc, argv, &opts)) { + return DTAERROR_COMMAND_ERROR; + } + ++#ifdef __linux__ ++ if (opts.secure_mode && opts.ask_password) { ++ interactive_password = GetPassPhrase("Please enter password "); ++ } ++#endif //__linux__ ++ + if ((opts.action != sedutiloption::scan) && + (opts.action != sedutiloption::validatePBKDF2) && + (opts.action != sedutiloption::isValidSED)) { +@@ -99,101 +106,101 @@ int main(int argc, char * argv[]) + switch (opts.action) { + case sedutiloption::initialSetup: + LOG(D) << "Performing initial setup to use sedutil on drive " << argv[opts.device]; +- return (d->initialSetup(argv[opts.password])); ++ return (d->initialSetup(GET_PASSWORD(), opts.secure_mode)); + case sedutiloption::setup_SUM: + LOG(D) << "Performing SUM setup on drive " << argv[opts.device]; + return (d->setup_SUM(opts.lockingrange, atoll(argv[opts.lrstart]), +- atoll(argv[opts.lrlength]), argv[opts.password], argv[opts.newpassword])); ++ atoll(argv[opts.lrlength]), GET_PASSWORD(), GET_NEW_PASSWORD(), opts.secure_mode)); + break; + case sedutiloption::setSIDPassword: + LOG(D) << "Performing setSIDPassword "; +- return d->setSIDPassword(argv[opts.password], argv[opts.newpassword]); ++ return d->setSIDPassword(GET_PASSWORD(), GET_NEW_PASSWORD(), opts.no_hash_passwords? 0 : 1, opts.no_hash_passwords? 0 : 1, opts.secure_mode); + break; + case sedutiloption::setAdmin1Pwd: + LOG(D) << "Performing setPAdmin1Pwd "; +- return d->setPassword(argv[opts.password], (char *) "Admin1", +- argv[opts.newpassword]); ++ return d->setPassword(GET_PASSWORD(), (char *) "Admin1", ++ GET_NEW_PASSWORD(), opts.secure_mode); + break; + case sedutiloption::loadPBAimage: + LOG(D) << "Loading PBA image " << argv[opts.pbafile] << " to " << opts.device; +- return d->loadPBA(argv[opts.password], argv[opts.pbafile]); ++ return d->loadPBA(GET_PASSWORD(), argv[opts.pbafile]); + break; + case sedutiloption::setLockingRange: + LOG(D) << "Setting Locking Range " << (uint16_t) opts.lockingrange << " " << (uint16_t) opts.lockingstate; +- return d->setLockingRange(opts.lockingrange, opts.lockingstate, argv[opts.password]); ++ return d->setLockingRange(opts.lockingrange, opts.lockingstate, GET_PASSWORD()); + break; + case sedutiloption::setLockingRange_SUM: + LOG(D) << "Setting Locking Range " << (uint16_t)opts.lockingrange << " " << (uint16_t)opts.lockingstate << " in Single User Mode"; +- return d->setLockingRange_SUM(opts.lockingrange, opts.lockingstate, argv[opts.password]); ++ return d->setLockingRange_SUM(opts.lockingrange, opts.lockingstate, GET_PASSWORD()); + break; + case sedutiloption::enableLockingRange: + LOG(D) << "Enabling Locking Range " << (uint16_t) opts.lockingrange; + return (d->configureLockingRange(opts.lockingrange, +- (DTA_READLOCKINGENABLED | DTA_WRITELOCKINGENABLED), argv[opts.password])); ++ (DTA_READLOCKINGENABLED | DTA_WRITELOCKINGENABLED), GET_PASSWORD())); + break; + case sedutiloption::disableLockingRange: + LOG(D) << "Disabling Locking Range " << (uint16_t) opts.lockingrange; + return (d->configureLockingRange(opts.lockingrange, DTA_DISABLELOCKING, +- argv[opts.password])); ++ GET_PASSWORD())); + break; + case sedutiloption::readonlyLockingRange: + LOG(D) << "Enabling Locking Range " << (uint16_t)opts.lockingrange; + return (d->configureLockingRange(opts.lockingrange, +- DTA_WRITELOCKINGENABLED, argv[opts.password])); ++ DTA_WRITELOCKINGENABLED, GET_PASSWORD())); + break; + case sedutiloption::setupLockingRange: + LOG(D) << "Setup Locking Range " << (uint16_t)opts.lockingrange; + return (d->setupLockingRange(opts.lockingrange, atoll(argv[opts.lrstart]), +- atoll(argv[opts.lrlength]), argv[opts.password])); ++ atoll(argv[opts.lrlength]), GET_PASSWORD())); + break; + case sedutiloption::setupLockingRange_SUM: + LOG(D) << "Setup Locking Range " << (uint16_t)opts.lockingrange << " in Single User Mode"; + return (d->setupLockingRange_SUM(opts.lockingrange, atoll(argv[opts.lrstart]), +- atoll(argv[opts.lrlength]), argv[opts.password])); ++ atoll(argv[opts.lrlength]), GET_PASSWORD())); + break; + case sedutiloption::listLockingRanges: + LOG(D) << "List Locking Ranges "; +- return (d->listLockingRanges(argv[opts.password], -1)); ++ return (d->listLockingRanges(GET_PASSWORD(), -1)); + break; + case sedutiloption::listLockingRange: + LOG(D) << "List Locking Range[" << opts.lockingrange << "]"; +- return (d->listLockingRanges(argv[opts.password], opts.lockingrange)); ++ return (d->listLockingRanges(GET_PASSWORD(), opts.lockingrange)); + break; + case sedutiloption::rekeyLockingRange: + LOG(D) << "Rekey Locking Range[" << opts.lockingrange << "]"; +- return (d->rekeyLockingRange(opts.lockingrange, argv[opts.password])); ++ return (d->rekeyLockingRange(opts.lockingrange, GET_PASSWORD())); + break; + case sedutiloption::setBandsEnabled: + LOG(D) << "Set bands Enabled"; +- return (d->setBandsEnabled(-1, argv[opts.password])); ++ return (d->setBandsEnabled(-1, GET_PASSWORD())); + break; + case sedutiloption::setBandEnabled: + LOG(D) << "Set band[" << opts.lockingrange << "] enabled"; +- return (d->setBandsEnabled(opts.lockingrange, argv[opts.password])); ++ return (d->setBandsEnabled(opts.lockingrange, GET_PASSWORD())); + break; + case sedutiloption::setMBRDone: + LOG(D) << "Setting MBRDone " << (uint16_t)opts.mbrstate; +- return (d->setMBRDone(opts.mbrstate, argv[opts.password])); ++ return (d->setMBRDone(opts.mbrstate, GET_PASSWORD())); + break; + case sedutiloption::setMBREnable: + LOG(D) << "Setting MBREnable " << (uint16_t)opts.mbrstate; +- return (d->setMBREnable(opts.mbrstate, argv[opts.password])); ++ return (d->setMBREnable(opts.mbrstate, GET_PASSWORD())); + break; + case sedutiloption::enableuser: + LOG(D) << "Performing enable user for user " << argv[opts.userid]; +- return d->enableUser(argv[opts.password], argv[opts.userid]); ++ return d->enableUser(GET_PASSWORD(), argv[opts.userid]); + break; + case sedutiloption::activateLockingSP: + LOG(D) << "Activating the LockingSP on" << argv[opts.device]; +- return d->activateLockingSP(argv[opts.password]); ++ return d->activateLockingSP(GET_PASSWORD()); + break; + case sedutiloption::activateLockingSP_SUM: + LOG(D) << "Activating the LockingSP on" << argv[opts.device]; +- return d->activateLockingSP_SUM(opts.lockingrange, argv[opts.password]); ++ return d->activateLockingSP_SUM(opts.lockingrange, GET_PASSWORD()); + break; + case sedutiloption::eraseLockingRange_SUM: + LOG(D) << "Erasing LockingRange " << opts.lockingrange << " on" << argv[opts.device]; +- return d->eraseLockingRange_SUM(opts.lockingrange, argv[opts.password]); ++ return d->eraseLockingRange_SUM(opts.lockingrange, GET_PASSWORD()); + break; + case sedutiloption::query: + LOG(D) << "Performing diskquery() on " << argv[opts.device]; +@@ -210,29 +217,29 @@ int main(int argc, char * argv[]) + break; + case sedutiloption::takeOwnership: + LOG(D) << "Taking Ownership of the drive at" << argv[opts.device]; +- return d->takeOwnership(argv[opts.password]); ++ return d->takeOwnership(GET_PASSWORD(), opts.secure_mode); + break; + case sedutiloption::revertLockingSP: + LOG(D) << "Performing revertLockingSP on " << argv[opts.device]; +- return d->revertLockingSP(argv[opts.password], 0); ++ return d->revertLockingSP(GET_PASSWORD(), 0); + break; + case sedutiloption::setPassword: + LOG(D) << "Performing setPassword for user " << argv[opts.userid]; +- return d->setPassword(argv[opts.password], argv[opts.userid], +- argv[opts.newpassword]); ++ return d->setPassword(GET_PASSWORD(), argv[opts.userid], ++ GET_NEW_PASSWORD(), opts.secure_mode); + break; + case sedutiloption::setPassword_SUM: + LOG(D) << "Performing setPassword in SUM mode for user " << argv[opts.userid]; +- return d->setNewPassword_SUM(argv[opts.password], argv[opts.userid], +- argv[opts.newpassword]); ++ return d->setNewPassword_SUM(GET_PASSWORD(), argv[opts.userid], ++ GET_NEW_PASSWORD(), opts.secure_mode); + break; + case sedutiloption::revertTPer: + LOG(D) << "Performing revertTPer on " << argv[opts.device]; +- return d->revertTPer(argv[opts.password], 0, 0); ++ return d->revertTPer(GET_PASSWORD(), 0, 0); + break; + case sedutiloption::revertNoErase: + LOG(D) << "Performing revertLockingSP keep global locking range on " << argv[opts.device]; +- return d->revertLockingSP(argv[opts.password], 1); ++ return d->revertLockingSP(GET_PASSWORD(), 1); + break; + case sedutiloption::validatePBKDF2: + LOG(D) << "Performing PBKDF2 validation "; +@@ -240,16 +247,16 @@ int main(int argc, char * argv[]) + break; + case sedutiloption::yesIreallywanttoERASEALLmydatausingthePSID: + case sedutiloption::PSIDrevert: +- LOG(D) << "Performing a PSID Revert on " << argv[opts.device] << " with password " << argv[opts.password]; +- return d->revertTPer(argv[opts.password], 1, 0); ++ LOG(D) << "Performing a PSID Revert on " << argv[opts.device] << " with password " << GET_PASSWORD(); ++ return d->revertTPer(GET_PASSWORD(), 1, 0); + break; + case sedutiloption::PSIDrevertAdminSP: +- LOG(D) << "Performing a PSID RevertAdminSP on " << argv[opts.device] << " with password " << argv[opts.password]; +- return d->revertTPer(argv[opts.password], 1, 1); ++ LOG(D) << "Performing a PSID RevertAdminSP on " << argv[opts.device] << " with password " << GET_PASSWORD(); ++ return d->revertTPer(GET_PASSWORD(), 1, 1); + break; + case sedutiloption::eraseLockingRange: + LOG(D) << "Erase Locking Range " << (uint16_t)opts.lockingrange; +- return (d->eraseLockingRange(opts.lockingrange, argv[opts.password])); ++ return (d->eraseLockingRange(opts.lockingrange, GET_PASSWORD())); + break; + case sedutiloption::objDump: + LOG(D) << "Performing objDump " ; +diff --git a/linux/os.h b/linux/os.h +index 89a798ee..e65a0c4e 100644 +--- a/linux/os.h ++++ b/linux/os.h +@@ -33,3 +33,5 @@ along with sedutil. If not, see . + #define SNPRINTF snprintf + #define DEVICEMASK snprintf(devname,23,"/dev/sd%c",(char) 0x61+i) + #define DEVICEEXAMPLE "/dev/sdc" ++ ++#include "../LinuxPBA/GetPassPhrase.h" + +From e4452be67f3f5ae326ba6be4fe92048eddc2720b Mon Sep 17 00:00:00 2001 +From: Howard McLauchlan +Date: Tue, 16 Aug 2022 22:33:51 -0700 +Subject: [PATCH 3/3] Add verifySIDPassword + +This is a utility I added to aid debugging, but generally seems like a +good idea. Before adding this, the only way we had of checking "do i +have the right password" was to try to change it, which does seem a +little weird. The pattern of change_password -> verify_password seems a +little more sane to me. + +The implementation of this command is a little scuffed though. Under the +hood, we attempt to start a session with the passed in password. There +are many reasons for a session start to fail, and verifySIDPassword +faithfully returns them. On success, however, the password must be +correct. + +Signed-off-by: Howard McLauchlan +--- + Common/DtaDev.h | 7 +++++++ + Common/DtaDevEnterprise.cpp | 6 ++++++ + Common/DtaDevEnterprise.h | 7 +++++++ + Common/DtaDevGeneric.cpp | 1 + + Common/DtaDevGeneric.h | 7 +++++++ + Common/DtaDevOpal.cpp | 26 ++++++++++++++++++++++++++ + Common/DtaDevOpal.h | 8 ++++++++ + Common/DtaOptions.cpp | 3 +++ + Common/DtaOptions.h | 1 + + Common/sedutil.cpp | 4 ++++ + 10 files changed, 70 insertions(+) + +diff --git a/Common/DtaDev.h b/Common/DtaDev.h +index c73c179e..98777b09 100644 +--- a/Common/DtaDev.h ++++ b/Common/DtaDev.h +@@ -132,6 +132,13 @@ class DtaDev { + */ + virtual uint8_t setSIDPassword(char * oldpassword, char * newpassword, + uint8_t hasholdpwd = 1, uint8_t hashnewpwd = 1, bool securemode = false) = 0; ++ /** Verify the SID pasword. ++ * Requires special handling because password is not always hashed. ++ * @param password SID password to be tested ++ * @param hashpwd Should the password be hashed. See comments in function Impl. ++ * @param securemode Should the password be interactively obtained. ++ */ ++ virtual uint8_t verifySIDPassword(char const * const password, uint8_t hashpwd, bool securemode) = 0; + /** Set the password of a locking SP user. + * @param password current password + * @param userid the userid whose password is to be changed +diff --git a/Common/DtaDevEnterprise.cpp b/Common/DtaDevEnterprise.cpp +index ba2e97a7..f00c9ccd 100644 +--- a/Common/DtaDevEnterprise.cpp ++++ b/Common/DtaDevEnterprise.cpp +@@ -1346,6 +1346,12 @@ uint8_t DtaDevEnterprise::setSIDPassword(char * oldpassword, char * newpassword, + LOG(D1) << "Exiting DtaDevEnterprise::setSIDPassword()"; + return 0; + } ++uint8_t DtaDevEnterprise::verifySIDPassword(char const * const, uint8_t, bool) ++{ ++ LOG(E) << "DtaDevEnterprise does not support verifySIDPassword" << std::endl; ++ return DTAERROR_INVALID_COMMAND; ++} ++ + uint8_t DtaDevEnterprise::setTable(vector table, const char *name, + OPAL_TOKEN value) + { +diff --git a/Common/DtaDevEnterprise.h b/Common/DtaDevEnterprise.h +index 4a6d2e2e..b1950269 100644 +--- a/Common/DtaDevEnterprise.h ++++ b/Common/DtaDevEnterprise.h +@@ -85,6 +85,13 @@ class DtaDevEnterprise : public DtaDevOS { + */ + uint8_t setSIDPassword(char * oldpassword, char * newpassword, + uint8_t hasholdpwd = 1, uint8_t hashnewpwd = 1, bool securemode = false); ++ /** Verify the SID pasword. ++ * Requires special handling because password is not always hashed. ++ * @param password SID password to be tested ++ * @param hashpwdd Should the password be hashed. See comments in function Impl. ++ * @param securemode Should the password be interactively obtained. ++ */ ++ uint8_t verifySIDPassword(char const * const password, uint8_t hashpwd, bool securemode); + /** set a single column in an object table + * @param table the UID of the table + * @param name the column name to be set +diff --git a/Common/DtaDevGeneric.cpp b/Common/DtaDevGeneric.cpp +index 8e1bdc91..02b6ad98 100644 +--- a/Common/DtaDevGeneric.cpp ++++ b/Common/DtaDevGeneric.cpp +@@ -93,6 +93,7 @@ uint8NOCODE(eraseLockingRange_SUM, uint8_t lockingrange, char * password) + uint8NOCODE(takeOwnership, char * newpassword, bool securemode) + uint8NOCODE(setSIDPassword,char * oldpassword, char * newpassword, + uint8_t hasholdpwd, uint8_t hashnewpwd, bool securemode) ++uint8NOCODE(verifySIDPassword, char const * const password, uint8_t hashpwd, bool securemode) + uint16_t DtaDevGeneric::comID() + { + LOG(E) << "Generic Device class does not support function " << "comID" << std::endl; +diff --git a/Common/DtaDevGeneric.h b/Common/DtaDevGeneric.h +index 07728781..999209e4 100644 +--- a/Common/DtaDevGeneric.h ++++ b/Common/DtaDevGeneric.h +@@ -76,6 +76,13 @@ class DtaDevGeneric : public DtaDevOS { + */ + uint8_t setSIDPassword(char * oldpassword, char * newpassword, + uint8_t hasholdpwd = 1, uint8_t hashnewpwd = 1, bool securemode = false) ; ++ /** Verify the SID pasword. ++ * Requires special handling because password is not always hashed. ++ * @param password SID password to be tested ++ * @param hashpwdd Should the password be hashed. See comments in function Impl. ++ * @param securemode Should the password be interactively obtained. ++ */ ++ uint8_t verifySIDPassword(char const * const password, uint8_t hashpwd, bool securemode); + /** Set the password of a locking SP user. + * @param password current password + * @param userid the userid whose password is to be changed +diff --git a/Common/DtaDevOpal.cpp b/Common/DtaDevOpal.cpp +index 0f6ccc70..a5e7edaf 100644 +--- a/Common/DtaDevOpal.cpp ++++ b/Common/DtaDevOpal.cpp +@@ -1545,6 +1545,32 @@ uint8_t DtaDevOpal::setSIDPassword(char * oldpassword, char * newpassword, + return 0; + } + ++uint8_t DtaDevOpal::verifySIDPassword(char const * const password, uint8_t hashpwd, bool securemode) ++{ ++ LOG(D1) << "Entering DtaDevOpal::setSIDPassword()"; ++ uint8_t lastRC; ++ session = new DtaSession(this); ++ ++ if (!session) { ++ LOG(E) << "Unable to create session object "; ++ return DTAERROR_OBJECT_CREATE_FAILED; ++ } ++ if (!hashpwd) ++ session->dontHashPwd(); ++ if ((lastRC = session->start(OPAL_UID::OPAL_ADMINSP_UID, ++ const_cast(password), OPAL_UID::OPAL_SID_UID)) != 0) { ++ delete session; ++ return lastRC; ++ } ++ delete session; ++ LOG(D1) << "Exiting DtaDevOpal::VerifySIDPassword"; ++ ++ // Logging to ERROR on success is weird, but this is an easy way to force ++ // output to console without mucking around the internals of this codebase. ++ LOG(E) << "Successfully verified SIDPassword"; ++ return 0; ++} ++ + uint8_t DtaDevOpal::setTable(vector table, OPAL_TOKEN name, + OPAL_TOKEN value) + { +diff --git a/Common/DtaDevOpal.h b/Common/DtaDevOpal.h +index 389b97f9..50c9dd20 100644 +--- a/Common/DtaDevOpal.h ++++ b/Common/DtaDevOpal.h +@@ -83,6 +83,14 @@ class DtaDevOpal : public DtaDevOS { + */ + uint8_t setSIDPassword(char * oldpassword, char * newpassword, + uint8_t hasholdpwd = 1, uint8_t hashnewpwd = 1, bool securemode = false); ++ /** Verify the SID pasword. ++ * Requires special handling because password is not always hashed. ++ * @param password SID password to be tested ++ * @param hashpwdd Should the password be hashed. See comments in function Impl. ++ * @param securemode Should the password be interactively obtained. ++ */ ++ uint8_t verifySIDPassword(char const * const password, uint8_t hashpwd, bool securemode); ++ + /** set a single column in an object table + * @param table the UID of the table + * @param name the column name to be set +diff --git a/Common/DtaOptions.cpp b/Common/DtaOptions.cpp +index 0d1752ee..0e3eb9fb 100644 +--- a/Common/DtaOptions.cpp ++++ b/Common/DtaOptions.cpp +@@ -71,6 +71,8 @@ void usage() + printf("--setPassword \n"); + printf(" Change the Enterprise password for userid\n"); + printf(" \"EraseMaster\" or \"BandMaster\", 0 <= n <= 1023\n"); ++ printf("--verifySIDPassword \n"); ++ printf(" Verify the SID password for given device\n"); + printf("--setLockingRange <0...n> \n"); + printf(" Set the status of a Locking Range\n"); + printf(" 0 = GLobal 1..n = LRn \n"); +@@ -171,6 +173,7 @@ uint8_t DtaOptions(int argc, char * argv[], DTA_OPTIONS * opts) + BEGIN_OPTION(initialSetup, 2, 1) OPTION_IS(password) OPTION_IS(device) END_OPTION + BEGIN_OPTION(setSIDPassword, 3, 1) OPTION_IS(password) OPTION_IS(newpassword) + OPTION_IS(device) END_OPTION ++ BEGIN_OPTION(verifySIDPassword, 2 /*num_args_non_secure*/, 1/*num_args_secure*/) OPTION_IS(password) OPTION_IS(device) END_OPTION + BEGIN_OPTION(setup_SUM, 6, 4) + TESTARG(0, lockingrange, 0) + TESTARG(1, lockingrange, 1) +diff --git a/Common/DtaOptions.h b/Common/DtaOptions.h +index 4ae3bc29..990cd566 100644 +--- a/Common/DtaOptions.h ++++ b/Common/DtaOptions.h +@@ -60,6 +60,7 @@ typedef enum _sedutiloption { + deadbeef, // 0 should indicate no action specified + initialSetup, + setSIDPassword, ++ verifySIDPassword, + setup_SUM, + setAdmin1Pwd, + setPassword, +diff --git a/Common/sedutil.cpp b/Common/sedutil.cpp +index 7053cd3c..4c0e9ff5 100644 +--- a/Common/sedutil.cpp ++++ b/Common/sedutil.cpp +@@ -116,6 +116,10 @@ int main(int argc, char * argv[]) + LOG(D) << "Performing setSIDPassword "; + return d->setSIDPassword(GET_PASSWORD(), GET_NEW_PASSWORD(), opts.no_hash_passwords? 0 : 1, opts.no_hash_passwords? 0 : 1, opts.secure_mode); + break; ++ case sedutiloption::verifySIDPassword: ++ LOG(D) << "Performing verifySIDPassword "; ++ return d->verifySIDPassword(GET_PASSWORD(), !opts.no_hash_passwords, opts.secure_mode); ++ break; + case sedutiloption::setAdmin1Pwd: + LOG(D) << "Performing setPAdmin1Pwd "; + return d->setPassword(GET_PASSWORD(), (char *) "Admin1", diff --git a/sedutil.spec b/sedutil.spec index 99429e6..db4f2e2 100644 --- a/sedutil.spec +++ b/sedutil.spec @@ -1,10 +1,10 @@ -%global gittag0 1.15.1 +%global gittag0 1.20.0 %global _hardened_build 1 Name: sedutil Version: %{gittag0} -Release: 10%{?dist} +Release: 1%{?dist} Summary: Tools to manage the activation and use of self encrypting drives # Everything is GPLv3+ except: @@ -16,6 +16,8 @@ Source0: https://github.com/Drive-Trust-Alliance/%{name}/archive/%{gittag0}/%{na # Modified version of https://github.com/Drive-Trust-Alliance/sedutil/pull/56.patch # to use linux/nvme_ioctl.h regardless of kernel version number so we can compile on EL7. Patch0: sedutil-1.15.1-nvme_ioctl.patch +# PR#408: Add securemode, verifySIDPassword +Patch1: https://github.com/Drive-Trust-Alliance/sedutil/pull/408.patch # sedutil does not work on big-endian architectures ExcludeArch: ppc ppc64 s390 s390x @@ -23,6 +25,7 @@ ExcludeArch: ppc ppc64 s390 s390x BuildRequires: make BuildRequires: gcc-c++ BuildRequires: ncurses-devel +BuildRequires: autoconf automake # This package uses a bundled copy of Cifra: # https://github.com/ctz/cifra/commit/319fdb764cd12e12b8296358cfcd640346c4d0dd @@ -48,6 +51,7 @@ the PBA image itself. %prep %setup -q -n sedutil-%{gittag0} %{?el7:%patch0 -p1 -b .nvme_ioctl} +%patch1 -p1 -b .securemode # Adjust the GitVersion.sh script to just use the git tag from the # checkout so we don't need a full git tree or the git tool itself. cd linux @@ -58,35 +62,30 @@ find . -type f -name '*.cpp' -exec chmod -x {} \; %build -# Always use the x86_64 build configuration, because we override -# CFLAGS etc. for each arch build anyway and the upstream makefiles -# don't have build configs for every arch we support. -cd linux/CLI -make %{?_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" CONF=Release_x86_64 - -cd ../../LinuxPBA -make %{?_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" CONF=Release +autoreconf -iv +%configure +%make_build %install -mkdir -p $RPM_BUILD_ROOT%{_sbindir} -install -p -m755 linux/CLI/dist/Release_x86_64/GNU-Linux/sedutil-cli $RPM_BUILD_ROOT%{_sbindir}/sedutil-cli - -mkdir -p $RPM_BUILD_ROOT%{_mandir}/man8 -install -p -m644 docs/sedutil-cli.8 $RPM_BUILD_ROOT%{_mandir}/man8/sedutil-cli.8 - -mkdir -p $RPM_BUILD_ROOT%{_libexecdir} -install -p -m755 LinuxPBA/dist/Release/GNU-Linux/linuxpba $RPM_BUILD_ROOT%{_libexecdir}/linuxpba - +%make_install +mkdir -p %{buildroot}%{_libexecdir}/linuxpba +ln -s %{_sbindir}/linuxpba %{buildroot}%{_libexecdir}/linuxpba %files %doc README.md Common/Copyright.txt Common/ReadMe.txt linux/PSIDRevert_LINUX.txt %license Common/LICENSE.txt %{_sbindir}/sedutil-cli %{_mandir}/man8/sedutil-cli.8* +%{_sbindir}/linuxpba %{_libexecdir}/linuxpba %changelog +* Thu Aug 12 2022 Davide Cavalca - 1.20.0-1 +- Update to 1.20.0 +- Backport upstream PR for securemode and verifySIGPassword +- Use standard macros for building and installing + * Sat Jul 23 2022 Fedora Release Engineering - 1.15.1-10 - Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild diff --git a/sources b/sources index fad8bad..419b2f5 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (sedutil-1.15.1.tar.gz) = 9708ef307b457fad2f45735b044685ac6731c353af428c49ff0e312190f3bdc521bcfa71a9e1239d9ffe637d18293a99b09b7e001df96494cdce53f5442750f1 +SHA512 (sedutil-1.20.0.tar.gz) = b85891f1c519295bf9551ffc2488300611f519aec88c60d74555e0870e125efd6153a49a6ae5a9783102e0ad0fbb148a0c0a804a61984934c23020add85287d3