You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
raid-unlock-tool/0002-Add-a-password-flag-fo...

171 lines
7.1 KiB

From a88a02e36b93e6c1d1b9d123761a3c26d652086d Mon Sep 17 00:00:00 2001
From: itycodes <tranquillitycodes@proton.me>
Date: Wed, 29 May 2024 23:01:48 +0200
Subject: [PATCH 2/4] Add a password flag for ATA Security
---
smartmontools/atacmds.cpp | 19 +++++++++++++++++++
smartmontools/atacmds.h | 15 +++++++++++++++
smartmontools/ataprint.cpp | 2 +-
smartmontools/ataprint.h | 1 +
smartmontools/smartctl.cpp | 14 ++++++++++++++
smartmontools/smartd.cpp | 1 +
6 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/smartmontools/atacmds.cpp b/smartmontools/atacmds.cpp
index 3f88c299..0c465c8b 100644
--- a/smartmontools/atacmds.cpp
+++ b/smartmontools/atacmds.cpp
@@ -12,6 +12,8 @@
*/
#include "config.h"
+#include <cstdlib>
+#include <new>
#define __STDC_FORMAT_MACROS 1 // enable PRI* for C++
#include <inttypes.h>
@@ -795,6 +797,23 @@ bool ata_nodata_command(ata_device * device, unsigned char command,
return device->ata_pass_through(in);
}
+// Issue a no-data ATA command with optional sector count register value
+bool ata_password_command(ata_device * device, unsigned char command, unsigned char flags,
+ unsigned short password[16])
+{
+ ata_cmd_in in;
+ in.in_regs.command = command;
+ in.in_regs.sector_count = 1;
+ ata_security_unlock_data_content* unlock = new ata_security_unlock_data_content();
+ memset(unlock, 0, sizeof(ata_security_unlock_data_content));
+ memcpy(&unlock->flags, &flags, sizeof(unlock->flags));
+ memcpy(&unlock->password, password, sizeof(unlock->password));
+ printf("The password is: %s\n", (char*)&unlock->password);
+ in.set_data_out(unlock, 1);
+
+ return device->ata_pass_through(in);
+}
+
// Issue SET FEATURES command with optional sector count register value
bool ata_set_features(ata_device * device, unsigned char features,
int sector_count /* = -1 */)
diff --git a/smartmontools/atacmds.h b/smartmontools/atacmds.h
index b914cc64..77a1522d 100644
--- a/smartmontools/atacmds.h
+++ b/smartmontools/atacmds.h
@@ -193,6 +193,17 @@ STATIC_ASSERT(sizeof(ata_smart_attribute) == 12);
#define ATTRIBUTE_FLAGS_OTHER(x) ((x) & 0xffc0)
+// ATA Security Unlock data structure
+#pragma pack(1)
+struct ata_security_unlock_data_content
+{
+ unsigned short flags; // 3 = Error Recovery Control
+ unsigned short password[16]; // 1 = Set Current, 2 = Return Current, 3 = Set Power-on, 4 = Return Power-on, 5 = Restore Default
+ unsigned short words017_255[239]; // reserved
+} ATTR_PACKED;
+#pragma pack()
+STATIC_ASSERT(sizeof(ata_security_unlock_data_content) == 512);
+
// Format of data returned by SMART READ DATA
// Table 62 of T13/1699-D (ATA8-ACS) Revision 6a, September 2008
#pragma pack(1)
@@ -754,6 +765,10 @@ int ataCheckPowerMode(ata_device * device);
// Issue a no-data ATA command with optional sector count register value
bool ata_nodata_command(ata_device * device, unsigned char command, int sector_count = -1);
+// Issue an ATA command that needs a password
+bool ata_password_command(ata_device * device, unsigned char command, unsigned char flags,
+ unsigned short password[16]);
+
// Issue SET FEATURES command with optional sector count register value
bool ata_set_features(ata_device * device, unsigned char features, int sector_count = -1);
diff --git a/smartmontools/ataprint.cpp b/smartmontools/ataprint.cpp
index 40edd33f..00ff8878 100644
--- a/smartmontools/ataprint.cpp
+++ b/smartmontools/ataprint.cpp
@@ -3880,7 +3880,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
// Unlock ATA security
if (options.set_security_unlock) {
- if (!ata_nodata_command(device, ATA_SECURITY_UNLOCK)) {
+ if (!ata_password_command(device, ATA_SECURITY_UNLOCK, 0, options.security_password)) {
pout("ATA SECURITY UNLOCK failed: %s\n", device->get_errmsg());
returnval |= FAILSMART;
}
diff --git a/smartmontools/ataprint.h b/smartmontools/ataprint.h
index ff35dead..dcf96dfb 100644
--- a/smartmontools/ataprint.h
+++ b/smartmontools/ataprint.h
@@ -94,6 +94,7 @@ struct ata_print_options
bool get_security = false; // print ATA security status
bool set_security_freeze = false; // Freeze ATA security
bool set_security_unlock = false; // Unlock ATA security
+ unsigned short* security_password; // ATA security password
bool get_wcache = false; // print write cache status
int set_wcache = 0; // disable(-1), enable(1) write cache
bool sct_wcache_reorder_get = false; // print write cache reordering status
diff --git a/smartmontools/smartctl.cpp b/smartmontools/smartctl.cpp
index 4fd5915e..25b3d09e 100644
--- a/smartmontools/smartctl.cpp
+++ b/smartmontools/smartctl.cpp
@@ -191,6 +191,8 @@ static void Usage()
" %s, swapid\n\n"
" -P TYPE, --presets=TYPE (ATA)\n"
" Drive-specific presets: use, ignore, show, showall\n\n"
+" -p PASSWORD, --password=PASSWORD (ATA)\n"
+" ATA Security User Password\n\n"
" -B [+]FILE, --drivedb=[+]FILE (ATA)\n"
" Read and replace [add] drive database from FILE\n"
" [default is +%s",
@@ -254,6 +256,8 @@ static std::string getvalidarglist(int opt)
"nvmelog,N,SIZE, tapedevstat, zdevstat, envrep, farm";
case 'P':
return "use, ignore, show, showall";
+ case 'p':
+ return "<PASSWORD>";
case 't':
return "offline, short, long, conveyance, force, vendor,N, select,M-N, "
"pending,N, afterselect,[on|off]";
@@ -331,6 +335,7 @@ static int parse_options(int argc, char** argv, const char * & type,
{ "badsum", required_argument, 0, 'b' },
{ "report", required_argument, 0, 'r' },
{ "smart", required_argument, 0, opt_smart },
+ { "password", required_argument, 0, 'p' },
{ "offlineauto", required_argument, 0, 'o' },
{ "saveauto", required_argument, 0, 'S' },
{ "health", no_argument, 0, 'H' },
@@ -801,6 +806,15 @@ static int parse_options(int argc, char** argv, const char * & type,
badarg = true;
}
break;
+ // Password, has to be 32 characters
+ case 'p':
+ if(strlen(optarg) != 32) {
+ badarg = true;
+ } else {
+ ataopts.security_password = (unsigned short*)malloc(32);
+ memcpy(ataopts.security_password, optarg, 32);
+ }
+ break;
case 't':
if (!strcmp(optarg,"offline")) {
testcnt++;
diff --git a/smartmontools/smartd.cpp b/smartmontools/smartd.cpp
index 9e4ae2eb..c218434d 100644
--- a/smartmontools/smartd.cpp
+++ b/smartmontools/smartd.cpp
@@ -436,6 +436,7 @@ struct dev_config
int set_standby{}; // set(1..255->0..254) standby timer
bool set_security_freeze{}; // Freeze ATA security
bool set_security_unlock{}; // Unlock ATA security
+ unsigned short security_password[16]{}; // ATA security password
int set_wcache{}; // disable(-1), enable(1) write cache
int set_dsn{}; // disable(0x2), enable(0x1) DSN
--
2.45.1