First version of Intel AMT RPE support in MeshCMD.
Ylian Saint-Hilaire committed
Jul 7, 2021 at 15:49 UTC
de80661037eccbfaafe0a1e5333faa201f796a57
4 files changed
+154
agents/MeshCmd-signed.exe
Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ
agents/MeshCmd64-signed.exe
Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ
agents/meshcmd.js
+153
@@ -198,6 +198,7 @@ function run(argv) {
198
console.log(' AmtScan - Search local network for Intel AMT devices.');
199
console.log(' AmtWifi - Intel AMT Wifi interface settings.');
200
console.log(' AmtWake - Intel AMT Wake Alarms.');
201
+ console.log(' AmtRPE - Intel AMT Remote Platform Erase.');
202
console.log('\r\nHelp on a specific action using:\r\n');
203
console.log(' meshcmd help [action]');
204
exit(1); return;
@@ -387,6 +388,21 @@ function run(argv) {
388
console.log(' --interval (dd-hh-mm) Optional alarm interval in days-hours-minutes format, default is alarm once.');
389
console.log(' --deletewhendone Indicates alarm is removed once triggered, default is to no remove.');
390
console.log(' --del [alarm-name] Remove a wake alarm');
391
+ } else if (action == 'amtrpe') {
392
+ console.log('AmtRPE is used to erase some elements of a remote Intel AMT platform. Example usage:\r\n\r\n meshcmd amtrpe --host 1.2.3.4 --user admin --pass mypassword');
393
+ console.log('\r\nRequired arguments:\r\n');
394
+ console.log(' --host [hostname] The IP address or DNS name of Intel AMT, 127.0.0.1 is default.');
395
+ console.log(' --pass [password] The Intel AMT login password.');
396
+ console.log('\r\nOptional arguments:\r\n');
397
+ console.log(' --user [username] The Intel AMT login username, admin is default.');
398
+ console.log(' --tls Specifies that TLS must be used.');
399
+ console.log(' --reset / --poweron Power action to perform on Intel AMT device.');
400
+ console.log(' --pyrite [PSID] Perform pyrite revert.');
401
+ console.log(' --ssd [Password] Perform secure erase all SSDs.');
402
+ console.log(' --tpm Perform TPM Clear.');
403
+ console.log(' --nvm Perform clear BIOS NVM variables.');
404
+ console.log(' --bios Perform BIOS reload of golden configuration.');
405
+ console.log(' --csme Perform CSME unconfigure.');
406
} else {
407
actions.shift();
408
console.log('Invalid action, usage:\r\n\r\n meshcmd help [action]\r\n\r\nValid actions are: ' + actions.join(', ') + '.');
@@ -718,6 +734,11 @@ function run(argv) {
734
if (((typeof args.date != 'string') || args.data == '')) { console.log("Wake alarm date is required (--date [yyyy-mm-dd])."); exit(1); return; }
735
}
736
performAmtWakeConfig(args);
737
+ } else if (settings.action == 'amtrpe') { // Perform Intel AMT remote platform erase operations
738
+ if (settings.hostname == null) { settings.hostname = '127.0.0.1'; }
739
+ if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; }
740
+ if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; }
741
+ performAmtPlatformErase(args);
742
} else if (settings.action == 'amtfeatures') { // Perform remote Intel AMT feature configuration operation
743
if (settings.hostname == null) { settings.hostname = '127.0.0.1'; }
744
if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; }
@@ -2534,6 +2555,138 @@ function performAmtWakeConfig1(stack, name, response, status, args) {
2555
}
2556
}
2557
2558
+
2559
+//
2560
+// Intel AMT Remote Platform Erase
2561
+//
2562
+
2563
+function performAmtPlatformErase(args) {
2564
+ var transport = require('amt-wsman-duk');
2565
+ var wsman = require('amt-wsman');
2566
+ var amt = require('amt');
2567
+ wsstack = new wsman(transport, settings.hostname, settings.tls ? 16993 : 16992, settings.username, settings.password, settings.tls);
2568
+ amtstack = new amt(wsstack);
2569
+ amtstack.BatchEnum(null, ['*CIM_BootService', '*AMT_BootCapabilities'], performAmtPlatformErase1, args);
2570
+}
2571
+
2572
+function performAmtPlatformErase1(stack, name, response, status, args) {
2573
+ debug(0, "performAmtPlatformErase1(" + status + "): " + JSON.stringify(response, null, 2));
2574
+ if (status == 200) {
2575
+ // See that RPE featues are supported
2576
+ var platfromEraseSupport = response['AMT_BootCapabilities'].response['PlatformErase'];
2577
+ if (platfromEraseSupport == null) { console.log("Remote Platfrom Erase (RPE) is not supported on this platform"); process.exit(1); return; }
2578
+ var supportedRpeFeatures = [];
2579
+ if (platfromEraseSupport & (1 << 1)) { supportedRpeFeatures.push("Pyrite Revert"); }
2580
+ if (platfromEraseSupport & (1 << 2)) { supportedRpeFeatures.push("Secure Erase All SSDs"); }
2581
+ if (platfromEraseSupport & (1 << 6)) { supportedRpeFeatures.push("TPM Clear"); }
2582
+ if (platfromEraseSupport & (1 << 25)) { supportedRpeFeatures.push("Clear BIOS NVM Variables"); }
2583
+ if (platfromEraseSupport & (1 << 26)) { supportedRpeFeatures.push("BIOS Reload of Golden Configuration"); }
2584
+ if (platfromEraseSupport & (1 << 31)) { supportedRpeFeatures.push("CSME Unconfigure"); }
2585
+ console.log("RPE Supported Features: " + supportedRpeFeatures.join(", "));
2586
+
2587
+ // Compute requested operations flags
2588
+ var rpeflags = 0;
2589
+ if (args.pyrite) { rpeflags += (1 << 1); }
2590
+ if (args.ssd) { rpeflags += (1 << 2); }
2591
+ if (args.tpm) { rpeflags += (1 << 6); }
2592
+ if (args.nvm) { rpeflags += (1 << 25); }
2593
+ if (args.bios) { rpeflags += (1 << 26); }
2594
+ if (args.csme) { rpeflags += (1 << 31); }
2595
+ if (rpeflags == 0) { process.exit(1); return; }
2596
+ if ((rpeflags | platfromEraseSupport) != platfromEraseSupport) { console.log("Unable to perform unsupported RPE operation."); process.exit(1); return; }
2597
+ settings.rpeflags = rpeflags;
2598
+ settings.powerAction = 0;
2599
+ if (args.reset) { settings.powerAction = 10; } else if (args.poweron) { settings.powerAction = 2; }
2600
+ if (settings.powerAction == 0) { console.log("--reset or --poweron is required to perform RPE action."); process.exit(1); return; }
2601
+
2602
+ // See if OCR and RPE are enabled
2603
+ var enabledState = response['CIM_BootService'].response['EnabledState'];
2604
+ var enabledBootStateStr = { 0: "Unknown", 1: "Other", 2: "Enabled", 3: "Disabled", 4: "Shutting Down", 5: "Not Applicable", 6: "Enabled but Offline", 7: "In Test", 8: "Deferred", 9: "Quiesce", 10: "Starting", 32768: "RPE Disabled", 32769: "All Enabled", 32770: "RPE & OCR Disabled" };
2605
+ var t = enabledBootStateStr[enabledState] ? enabledBootStateStr[enabledState] : ("Unknown, #" + enabledState);
2606
+ console.log("BootService Enabled State: " + t);
2607
+
2608
+ if (enabledState != 32769) {
2609
+ // Enabled OCR and RPE
2610
+ console.log("Enabling OCR and RPE features...");
2611
+ amtstack.CIM_BootService_RequestStateChange(32769, null, performAmtPlatformErase2);
2612
+ } else {
2613
+ performAmtPlatformErase3(args);
2614
+ }
2615
+ } else { console.log("Error, status " + status + "."); process.exit(1); }
2616
+}
2617
+
2618
+function performAmtPlatformErase2(stack, name, response, status, args) {
2619
+ debug(0, "performAmtPlatformErase2(" + status + "): " + JSON.stringify(response, null, 2));
2620
+ if (status == 200) {
2621
+ if (response.Body['ReturnValueStr'] != 'SUCCESS') { console.log("Error, " + response.Body['ReturnValueStr'] + "."); process.exit(1); }
2622
+ else { performAmtPlatformErase3(args); }
2623
+ process.exit(0);
2624
+ } else { console.log("Error, status " + status + "."); process.exit(1); }
2625
+}
2626
+
2627
+function performAmtPlatformErase3(args) {
2628
+ var tlv = makeUefiBootParam(1, settings.rpeflags, 4), tlvlen = 1;
2629
+ if ((settings.rpeflags & 2) && (typeof args.pyrite == 'string')) { tlv += makeUefiBootParam(10, args.pyrite); tlvlen++; }
2630
+ if ((settings.rpeflags & 4) && (typeof args.ssd == 'string')) { tlv += makeUefiBootParam(20, args.ssd); tlvlen++; }
2631
+ settings.platfromEraseTLV = { tlv: Buffer.from(tlv, 'binary').toString('base64'), tlvlen: tlvlen };
2632
+ debug(0, "platfromEraseTLV: " + JSON.stringify(r, null, 2));
2633
+ console.log("Fetching boot information...");
2634
+ amtstack.Get('AMT_BootSettingData', performAmtPlatformErase4, 0, 1);
2635
+}
2636
+
2637
+function performAmtPlatformErase4(stack, name, response, status, args) {
2638
+ debug(0, "performAmtPlatformErase4(" + status + "): " + JSON.stringify(response, null, 2));
2639
+ if (status == 200) {
2640
+ var r = response['Body'];
2641
+ r['PlatformErase'] = true;
2642
+ r['UefiBootParametersArray'] = settings.platfromEraseTLV.tlv;
2643
+ r['UefiBootNumberOfParams'] = settings.platfromEraseTLV.tlvlen;
2644
+ debug(0, "BootConfig: " + JSON.stringify(r, null, 2));
2645
+ console.log("Setting Boot Order...");
2646
+ amtstack.CIM_BootConfigSetting_ChangeBootOrder(null, function (stack, name, response, status) {
2647
+ if (status != 200) { console.log("PUT CIM_BootConfigSetting_ChangeBootOrder, Error #" + status + ((response.Header && response.Header.WsmanError) ? (', ' + response.Header.WsmanError) : '')); process.exit(1); return; }
2648
+ if (response.Body['ReturnValue'] != 0) { messagebox("Error, Change Boot Order returns " + response.Body.ReturnValueStr); process.exit(1); return; }
2649
+ amtstack.Put('AMT_BootSettingData', r, performAmtPlatformErase5, 0, 1);
2650
+ }, 0, 1);
2651
+ } else { console.log("Error, status " + status + "."); process.exit(1); }
2652
+}
2653
+
2654
+function performAmtPlatformErase5(stack, name, response, status, args) {
2655
+ debug(0, "performAmtPlatformErase5(" + status + "): " + JSON.stringify(response, null, 2));
2656
+ if (status == 200) {
2657
+ console.log("Setting Boot Configuration Role...");
2658
+ amtstack.SetBootConfigRole(1, performAmtPlatformErase6, 0, 1);
2659
+ } else { console.log("Error, status " + status + "."); process.exit(1); }
2660
+}
2661
+
2662
+function performAmtPlatformErase6(stack, name, response, status, args) {
2663
+ debug(0, "performAmtPlatformErase6(" + status + "): " + JSON.stringify(response, null, 2));
2664
+ if (status == 200) {
2665
+ if (response.Body['ReturnValueStr'] != 'SUCCESS') { console.log("Error, " + response.Body['ReturnValueStr'] + "."); process.exit(1); }
2666
+ else {
2667
+ console.log('Performing power state change...');
2668
+ amtstack.RequestPowerStateChange(settings.powerAction, performAmtPlatformErase7); // 2 = Power Up, 10 = Reset
2669
+ }
2670
+ } else { console.log("Error, status " + status + "."); process.exit(1); }
2671
+}
2672
+
2673
+function performAmtPlatformErase7(stack, name, response, status, args) {
2674
+ debug(0, "performAmtPlatformErase7(" + status + "): " + JSON.stringify(response, null, 2));
2675
+ if (status == 200) {
2676
+ if (response.Body['ReturnValueStr'] != 'SUCCESS') { console.log("Error, " + response.Body['ReturnValueStr'] + "."); process.exit(1); } else { console.log('Done.'); }
2677
+ process.exit(0);
2678
+ } else { console.log("Error, status " + status + "."); process.exit(1); }
2679
+}
2680
+
2681
+
2682
+// Returns a UEFI boot parameter in binary
2683
+function makeUefiBootParam(type, data, len) {
2684
+ if (typeof data == 'number') { if (len == 1) { data = String.fromCharCode(data & 0xFF); } if (len == 2) { data = ShortToStrX(data); } if (len == 4) { data = IntToStrX(data); } }
2685
+ return ShortToStrX(0x8086) + ShortToStrX(type) + IntToStrX(data.length) + data;
2686
+}
2687
+function IntToStrX(v) { return String.fromCharCode(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF, (v >> 24) & 0xFF); }
2688
+function ShortToStrX(v) { return String.fromCharCode(v & 0xFF, (v >> 8) & 0xFF); }
2689
+
2690
//
2691
// Intel AMT feature configuration action
2692
//
agents/modules_meshcmd/amt.js
+1
@@ -300,6 +300,7 @@ function AmtStackCreateService(wsmanStack) {
300
obj.CIM_AccountManagementService_CreateAccount = function (System, AccountTemplate, callback_func) { obj.Exec("CIM_AccountManagementService", "CreateAccount", { "System": System, "AccountTemplate": AccountTemplate }, callback_func); }
301
obj.CIM_BootConfigSetting_ChangeBootOrder = function (Source, callback_func) { obj.Exec("CIM_BootConfigSetting", "ChangeBootOrder", { "Source": Source }, callback_func); }
302
obj.CIM_BootService_SetBootConfigRole = function (BootConfigSetting, Role, callback_func) { obj.Exec("CIM_BootService", "SetBootConfigRole", { "BootConfigSetting": BootConfigSetting, "Role": Role }, callback_func, 0, 1); }
303
+ obj.CIM_BootService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec('CIM_BootService', 'RequestStateChange', { 'RequestedState': RequestedState, 'TimeoutPeriod': TimeoutPeriod }, callback_func, 0, 1); }
304
obj.CIM_Card_ConnectorPower = function (Connector, PoweredOn, callback_func) { obj.Exec("CIM_Card", "ConnectorPower", { "Connector": Connector, "PoweredOn": PoweredOn }, callback_func); }
305
obj.CIM_Card_IsCompatible = function (ElementToCheck, callback_func) { obj.Exec("CIM_Card", "IsCompatible", { "ElementToCheck": ElementToCheck }, callback_func); }
306
obj.CIM_Chassis_IsCompatible = function (ElementToCheck, callback_func) { obj.Exec("CIM_Chassis", "IsCompatible", { "ElementToCheck": ElementToCheck }, callback_func); }