/
acm.go
336 lines (302 loc) · 8.44 KB
/
acm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
package api
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"log"
)
const (
ACMChipsetTypeBios uint8 = 0x00
ACMChipsetTypeSinit uint8 = 0x01
ACMChipsetTypeBiosRevoc uint8 = 0x08
ACMChipsetTypeSinitRevoc uint8 = 0x09
ACMTypeChipset uint16 = 0x02
ACMSubTypeReset uint16 = 0x01
ACMVendorIntel uint32 = 0x8086
TPMExtPolicyIllegal uint8 = 0x00
TPMExtPolicyAlgAgile uint8 = 0x01
TPMExtPolicyEmbeddedAlgs uint8 = 0x10
TPMExtPolicyBoth uint8 = 0x11
TPMFamilyIllegal uint16 = 0x0000
TPMFamilyDTPM12 uint16 = 0x0001
TPMFamilyDTPM20 uint16 = 0x0010
TPMFamilyDTPMBoth uint16 = 0x0011
TPMFamilyPTT20 uint16 = 0x1000
ACMUUIDV3 string = "7fc03aaa-46a7-18db-ac2e-698f8d417f5a"
ACMSizeOffset int64 = 24
TPMAlgoSHA1 uint16 = 0x0004
TPMAlgoSHA256 uint16 = 0x000b
TPMAlgoSHA384 uint16 = 0x000c
TPMAlgoSHA512 uint16 = 0x000d
TPMAlgoNULL uint16 = 0x0010
TPMAlgoSM3_256 uint16 = 0x0012
TPMAlgoRSASSA uint16 = 0x0014
TPMAlgoECDSA uint16 = 0x0018
TPMAlgoSM2 uint16 = 0x001B
)
type UUID struct {
Field1 uint32
Field2 uint16
Field3 uint16
Field4 uint16
Field5 [6]uint8
}
type ACMInfo struct {
Uuid UUID
ChipsetACMType uint8
Version uint8
Length uint16
ChipsetIDList uint32
OSSinitDataVersion uint32
MinMleHeaderVersion uint32
TxtCaps uint32
ACMVersion uint8
Reserved [3]uint8
ProcessorIDList uint32
TPMInfoList uint32
}
type ChipsetID struct {
Flags uint32
VendorID uint16
DeviceID uint16
RevisionID uint16
Reserved uint16
ExtendedID uint16
}
type Chipsets struct {
Count uint32
IDList []ChipsetID
}
type ProcessorID struct {
FMS uint32
FMSMask uint32
PlatformID uint64
PlatformMask uint64
}
type Processors struct {
Count uint32
IDList []ProcessorID
}
type TPMs struct {
Capabilities uint32
Count uint16
AlgID []uint16
}
type ACM struct {
ModuleType uint16
ModuleSubType uint16
HeaderLen uint32
HeaderVersion uint32
ChipsetID uint16
Flags uint16
ModuleVendor uint32
Date uint32
Size uint32
TxtSVN uint16
SeSVN uint16
CodeControl uint32
ErrorEntryPoint uint32
GDTLimit uint32
GDTBase uint32
SegSel uint32
EntryPoint uint32
Reserved2 [64]uint8
KeySize uint32
ScratchSize uint32
PubKey [256]uint8
PubExp uint32
Signatur [256]uint8
Scratch [143]uint32
Info ACMInfo
}
// ParseACM
func ParseACM(data []byte) (*ACM, *Chipsets, *Processors, *TPMs, error) {
var acm ACM
var processors Processors
var chipsets Chipsets
var tpms TPMs
buf := bytes.NewReader(data)
err := binary.Read(buf, binary.LittleEndian, &acm)
if err != nil {
return nil, nil, nil, nil, err
}
buf.Seek(int64(acm.Info.ChipsetIDList), io.SeekStart)
err = binary.Read(buf, binary.LittleEndian, &chipsets.Count)
if err != nil {
return nil, nil, nil, nil, err
}
chipsets.IDList = make([]ChipsetID, chipsets.Count)
err = binary.Read(buf, binary.LittleEndian, &chipsets.IDList)
if err != nil {
return nil, nil, nil, nil, err
}
buf.Seek(int64(acm.Info.ProcessorIDList), io.SeekStart)
err = binary.Read(buf, binary.LittleEndian, &processors.Count)
if err != nil {
return nil, nil, nil, nil, err
}
processors.IDList = make([]ProcessorID, processors.Count)
err = binary.Read(buf, binary.LittleEndian, &processors.IDList)
if err != nil {
return nil, nil, nil, nil, err
}
buf.Seek(int64(acm.Info.TPMInfoList), io.SeekStart)
err = binary.Read(buf, binary.LittleEndian, &tpms.Capabilities)
if err != nil {
return nil, nil, nil, nil, err
}
err = binary.Read(buf, binary.LittleEndian, &tpms.Count)
if err != nil {
return nil, nil, nil, nil, err
}
tpms.AlgID = make([]uint16, tpms.Count)
for i := 0; i < int(tpms.Count); i++ {
err = binary.Read(buf, binary.LittleEndian, &tpms.AlgID[i])
if err != nil {
return nil, nil, nil, nil, err
}
}
return &acm, &chipsets, &processors, &tpms, nil
}
func LookupSize(header []byte) (int64, error) {
var acmSize uint32
buf := bytes.NewReader(header[:32])
buf.Seek(ACMSizeOffset, io.SeekStart)
err := binary.Read(buf, binary.LittleEndian, &acmSize)
if err != nil {
return 0, err
}
return int64(acmSize * 4), nil
}
func (a *ACM) PrettyPrint() {
log.Println("Authenticated Code Module")
if a.ModuleVendor == ACMVendorIntel {
log.Println("Module Vendor: Intel")
} else {
log.Println("Module Vendor: Unknown")
}
if a.ModuleType == ACMTypeChipset {
log.Println("Module Type: ACM_TYPE_CHIPSET")
} else {
log.Println("Module Type: UNKNOWN")
}
if a.ModuleSubType == ACMSubTypeReset {
log.Println("Module Subtype: Execute at Reset")
} else if a.ModuleSubType == 0 {
log.Println("Module Subtype: 0x0")
} else {
log.Println("Module Subtype: Unknown")
}
log.Printf("Module Date: 0x%02x\n", a.Date)
log.Printf("Module Size: %db\n", a.Size*4)
log.Printf("Header Length: %db\n", a.HeaderLen)
log.Printf("Header Version: %d\n", a.HeaderVersion)
log.Printf("Chipset ID: 0x%02x\n", a.ChipsetID)
log.Printf("Flags: 0x%02x\n", a.Flags)
log.Printf("TXT SVN: 0x%08x\n", a.TxtSVN)
log.Printf("SE SVN: 0x%08x\n", a.SeSVN)
log.Printf("Code Control: 0x%02x\n", a.CodeControl)
log.Printf("Entry Point: 0x%08x:%08x\n", a.SegSel, a.EntryPoint)
log.Printf("Scratch Size: %db\n", a.ScratchSize)
log.Println("Info Table:")
uuidStr := fmt.Sprintf("%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
a.Info.Uuid.Field1,
a.Info.Uuid.Field2,
a.Info.Uuid.Field3,
a.Info.Uuid.Field4,
a.Info.Uuid.Field5[0],
a.Info.Uuid.Field5[1],
a.Info.Uuid.Field5[2],
a.Info.Uuid.Field5[3],
a.Info.Uuid.Field5[4],
a.Info.Uuid.Field5[5])
if uuidStr == ACMUUIDV3 {
log.Println("\tUUID: ACM_UUID_V3")
}
switch a.Info.ChipsetACMType {
case ACMChipsetTypeBios:
log.Println("\tChipset ACM: BIOS")
break
case ACMChipsetTypeBiosRevoc:
log.Println("\tChipset ACM: BIOS Revocation")
break
case ACMChipsetTypeSinit:
log.Println("\tChipset ACM: SINIT")
break
case ACMChipsetTypeSinitRevoc:
log.Println("\tChipset ACM: SINIT Revocation")
break
default:
log.Println("\tChipset ACM: Unknown")
}
log.Printf("\tVersion: %d\n", a.Info.Version)
log.Printf("\tLength: %db\n", a.Info.Length)
log.Printf("\tChipset ID List: 0x%02x\n", a.Info.ChipsetIDList)
log.Printf("\tOS SINIT Data Version: 0x%02x\n", a.Info.OSSinitDataVersion)
log.Printf("\tMin. MLE Header Version: 0x%08x\n", a.Info.MinMleHeaderVersion)
log.Printf("\tCapabilities: 0x%08x\n", a.Info.TxtCaps)
log.Printf("\tACM Version: %d\n", a.Info.ACMVersion)
}
func (c *Chipsets) PrettyPrint() {
log.Println("Chipset List:")
log.Printf("\tEntries: %d\n", c.Count)
for idx, chipset := range c.IDList {
log.Printf("\tEntry %d:\n", idx)
log.Printf("\t\tFlags: 0x%02x\n", chipset.Flags)
log.Printf("\t\tVendor: 0x%02x\n", chipset.VendorID)
log.Printf("\t\tDevice: 0x%02x\n", chipset.DeviceID)
log.Printf("\t\tRevision: 0x%02x\n", chipset.RevisionID)
log.Printf("\t\tExtended: 0x%02x\n", chipset.ExtendedID)
}
}
func (p *Processors) PrettyPrint() {
log.Println("Processor List:")
log.Printf("\tEntries: %d\n", p.Count)
for idx, processor := range p.IDList {
log.Printf("\tEntry %d:\n", idx)
log.Printf("\t\tFMS: 0x%02x\n", processor.FMS)
log.Printf("\t\tFMS Maks: 0x%02x\n", processor.FMSMask)
log.Printf("\t\tPlatform ID: 0x%02x\n", processor.PlatformID)
log.Printf("\t\tPlatform Mask: 0x%02x\n", processor.PlatformMask)
}
}
func (t *TPMs) PrettyPrint() {
log.Println("TPM Info List:")
log.Println("\tCapabilities:")
log.Printf("\t\tExternal Policy: %02x\n", t.Capabilities)
log.Printf("\tAlgorithms: %d\n", t.Count)
for _, algo := range t.AlgID {
switch algo {
case TPMAlgoNULL:
log.Println("\t\tNULL")
break
case TPMAlgoSHA1:
log.Println("\t\tSHA-1")
break
case TPMAlgoSHA256:
log.Println("\t\tSHA-256")
break
case TPMAlgoSHA384:
log.Println("\t\tSHA-384")
break
case TPMAlgoSHA512:
log.Println("\t\tSHA-512")
break
case TPMAlgoSM3_256:
log.Println("\t\tSM3-256")
break
case TPMAlgoRSASSA:
log.Println("\t\tRSA-SSA")
break
case TPMAlgoECDSA:
log.Println("\t\tEC-DSA")
break
case TPMAlgoSM2:
log.Println("\t\tSM2")
break
default:
log.Println("\t\tUnknown")
}
}
}