From a88a02e36b93e6c1d1b9d123761a3c26d652086d Mon Sep 17 00:00:00 2001 From: itycodes 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 +#include #define __STDC_FORMAT_MACROS 1 // enable PRI* for C++ #include @@ -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 ""; 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