Blame 408.patch

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