More work on Intel AMT provisioning server.
Ylian Saint-Hilaire committed
Mar 11, 2021 at 01:12 UTC
7dddb1a63a2b6a704c8562e98da41b89b2ca2ef6
1 file changed
+53
-62
amthelloserver.js
+53
-62
@@ -19,6 +19,7 @@
19
module.exports.CreateAmtHelloServer = function (parent, config) {
20
var obj = {};
21
22
+ // Start the Intel AMT hello server
23
var port = 9971;
24
if (typeof config.port == 'number') { port = config.port; }
25
const net = require('net');
@@ -26,8 +27,9 @@ module.exports.CreateAmtHelloServer = function (parent, config) {
27
socket.ra = socket.remoteAddress;
28
socket.data = null;
29
socket.on('error', function (err) { })
29
- socket.on('close', function () { if (this.data != null) { parseHelloData(this.data, this.ra); } delete this.ra; this.removeAllListeners(); })
30
+ socket.on('close', function () { if (this.data != null) { processHelloData(this.data, this.ra); } delete this.ra; this.removeAllListeners(); })
31
socket.on('data', function (data) {
32
+ console.log('indata', data.toString('hex'));
33
if (this.data == null) { this.data = data; } else { Buffer.concat([this.data, data]); }
34
var str = this.data.toString();
35
if (str.startsWith('GET ') && (str.indexOf('\r\n\r\n') >= 0)) {
@@ -40,75 +42,64 @@ module.exports.CreateAmtHelloServer = function (parent, config) {
42
})
43
});
44
obj.server.listen(port);
43
- console.log('MeshCentral Intel AMT hello server running on port ' + port + '.');
44
-
45
- function parseHelloData(data, addr) {
46
- if (addr.startsWith('::ffff:')) { addr = addr.substring(7); }
47
- console.log('parseHelloData', data.length);
48
- console.log('Address', addr);
49
- console.log('HEX', data.toString('hex'));
50
- }
51
-
52
- return obj;
53
-};
45
+ console.log('MeshCentral Intel(R) AMT provisioning server running on port ' + port + '.');
46
47
+ // Example hello data for testing
48
+ //processHelloData(Buffer.from('01000300000000004b529b93d413181de4871c697a6b7a2b170220c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4022045140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda0220d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef402201465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb65802202ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f502209acfab7e43c8d880d06b262a94deeee4b4659989c3d0caf19baf6405e41ab7df022016af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb0220960adf0063e96356750c2965dd0a0867da0b9cbd6e77714aeafb2349ab393da3022068ad50909b04363c605ef13581a939ff2c96372e3f12325b0a6861e1d59f660302206dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177022073c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c022043df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f33902202399561127a57125de8cefea610ddf2fa078b5c8067f4e828290bfb860e84b3c022070a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a02204348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c701610220cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f022031ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d00220552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988022067540a47aa5b9f34570a99723cfefa96a96ee3f0d9b8bf4def9440b8065d665d02207224395222cd588c4f2683716922addb41e39b581ac34fa87b39efa896fbb39e0220cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b0220179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c892402202cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69', 'hex'), '192.168.2.148');
49
50
+ // Parse Intel AMT hello data
51
+ function parseHelloData(data, addr) {
52
+ try {
53
+ if (addr.startsWith('::ffff:')) { addr = addr.substring(7); }
54
+ var amtHello = { time: Date.now(), addr: addr };
55
57
-/*
58
-[Serializable]
59
-public class AmtHello
60
-{
61
- public byte[] Data;
62
- public string Pid;
63
- public byte[][] CertHash;
64
- public DateTime ReceivedTime;
65
- public IPEndPoint RemoteEndPoint;
66
- public int Version;
56
+ // Decode header
57
+ if (data.length < 25) return; // Invalid data
58
+ const firstBytes = data.readInt16LE(0);
59
+ if (firstBytes > 1) return; // Invalid data
60
+ amtHello.adminCredentialsSet = (firstBytes != 0);
61
+ amtHello.version = data.readInt16LE(2);
62
+ if (amtHello.version != 3) return null; // One touch PID not supported, only version 3 supported.
63
+ amtHello.retryCount = data.readInt32LE(4);
64
+ amtHello.guidhex = data.slice(8, 24).toString('hex');
65
+ amtHello.guid = guidToStr(amtHello.guidhex);
66
68
- public AmtHello(byte[] buf, IPEndPoint ep)
69
- {
70
- Data = buf;
71
- ReceivedTime = DateTime.Now;
72
- RemoteEndPoint = ep;
73
- Version = buf[2];
74
- if (buf.Length == 32) // One Touch PID
75
- {
76
- byte[] b = new byte[8];
77
- Array.Copy(buf,24,b,0,8);
78
- Pid = UTF8Encoding.UTF8.GetString(b);
79
- if (Pid.Length == 8) Pid = Pid.Substring(0, 4) + "-" + Pid.Substring(4, 4);
80
- }
81
- if (Version == 3) // Zero-Touch Key Hash
82
- {
83
- int hashCount = buf[24];
84
- CertHash = new byte[hashCount][];
85
- int ptr = 26;
86
- for (int i = 0; i < hashCount; i++)
67
+ // Get the list of hashes
68
+ const hashCount = data[24];
69
+ amtHello.hashes = [];
70
+ var ptr = 25;
71
+ for (var i = 0; i < hashCount; i++)
72
{
88
- CertHash[i] = new byte[buf[ptr]];
89
- Array.Copy(buf, ptr + 1, CertHash[i], 0, buf[ptr]);
90
- ptr += (buf[ptr] + 2);
73
+ const hashType = data[ptr]; // 1=SHA1 (20 byte hash); 2 = SHA256 (32 byte hash); 3 = SHA384 (48 byte hash)
74
+ const hashSize = data[ptr + 1];
75
+ if ((hashType < 1) || (hashType > 3)) return null; // Unexpected hash type
76
+ if ((hashType == 1) && (hashSize != 20)) return null; // Unexpected SHA1 hash size
77
+ if ((hashType == 2) && (hashSize != 32)) return null; // Unexpected SHA256 hash size
78
+ if ((hashType == 3) && (hashSize != 48)) return null; // Unexpected SHA384 hash size
79
+ const hash = data.slice(ptr + 2, ptr + 2 + hashSize);
80
+ amtHello.hashes.push(hash.toString('hex'));
81
+ ptr += (hashSize + 2);
82
}
92
- }
83
+ if (amtHello.hashes.length != hashCount) return null; // Unexpected number of hashes
84
+ return amtHello; // Everything looks good.
85
+ } catch (ex) { return null; }
86
}
87
95
- public bool NetworkPasswordChanged
96
- {
97
- get {return BitConverter.ToInt16(Data, 0) != 0;}
98
- }
88
+ function guidToStr(g) { return g.substring(6, 8) + g.substring(4, 6) + g.substring(2, 4) + g.substring(0, 2) + "-" + g.substring(10, 12) + g.substring(8, 10) + "-" + g.substring(14, 16) + g.substring(12, 14) + "-" + g.substring(16, 20) + "-" + g.substring(20); }
89
+ function strToGuid(s) { s = s.replace(/-/g, ''); var ret = s.substring(6, 8) + s.substring(4, 6) + s.substring(2, 4) + s.substring(0, 2) + s.substring(10, 12) + s.substring(8, 10) + s.substring(14, 16) + s.substring(12, 14) + s.substring(16, 20) + s.substring(20); return ret; }
90
100
- public Guid GetGuid()
101
- {
102
- if (Data.Length < 24) return Guid.Empty;
103
- byte[] b = new byte[16];
104
- Array.Copy(Data, 8, b, 0, 16);
105
- return new Guid(b);
106
- }
91
+ // Process incoming Intel AMT hello data
92
+ function processHelloData(data, addr) {
93
+ // Check if we can parse the incoming data
94
+ const amtHello = parseHelloData(data, addr);
95
+ if (amtHello == null) return; // Invalid Intel AMT hello
96
108
- public float GetVersion()
109
- {
110
- if (Data.Length < 4) return 0;
111
- return (float)BitConverter.ToInt16(Data, 2);
97
+ console.log(JSON.stringify(amtHello, null, 2));
98
+ // TODO: Compute the nodeid for this device using the device GUID
99
+ // TODO: Get device group and assumed trusted FQDN
100
+ // TODO: Get an activation certificate chain
101
+ // TODO: Setup a connection to the Intel AMT device
102
}
113
-}
114
-*/
\ No newline at end of file
103
+
104
+ return obj;
105
+};