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); }