Skip to content

Commit 1da4441

Browse files
committed
feat: add amd-suite
amd-suite runs AMD specific tests for: * AMD PSB * AMD SME * AMD SEV * AMD SEV-SNP Signed-off-by: Christian Walter <[email protected]>
1 parent 1ab9344 commit 1da4441

File tree

5 files changed

+878
-7
lines changed

5 files changed

+878
-7
lines changed

cmd/core/amd-suite/TESTPLAN.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ Id | Group | Test | Implemented | Reference | Notes
77
13 | PSB | Platform Model ID is not zero | :x: | - | Should be non-zero
88
14 | PSB | Read BIOS Key Revision is not zero | :x: | - | Should be non zero
99
15 | PSB | AMD Key is disabled | :x: | - | If the AMD key is not disabled, the system will still boot AMD signed firmware
10-
16 | PSB | Secure Debug is disabled | :x: | - | -
10+
16 | PSB | Secure Debug is disabled | :x: | - | Should be disabled
1111
17 | PSB | Keys are fused | :x: | - | Test checks if the customer keys have been fused by reading `Customer Key Lock` from the `PSB_STATUS` register.
12-
18 | PSB | PSB Policy Hash | :x: | - | Check the PSB Policy Hash
12+
18 | PSB | PSB Policy Hash | :x: | - | Check the PSB Policy Hash and print it.
1313
19 | PSB | Revocation Status | :x: | - | Check the Revokation Status
1414
20 | SME | SME Support | :x: | - | Test checks `0x8000001f`
1515
21 | SME | SME Enabled | :x: | - | Test checks `MSR_AMD64_SYSCFG`

cmd/core/amd-suite/cmd.go

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"sort"
6+
7+
"github.com/9elements/converged-security-suite/v2/pkg/test"
8+
"github.com/9elements/converged-security-suite/v2/pkg/tools"
9+
"github.com/9elements/go-linux-lowlevel-hw/pkg/hwapi"
10+
log "github.com/sirupsen/logrus"
11+
12+
a "github.com/logrusorgru/aurora"
13+
)
14+
15+
type context struct {
16+
logpath string
17+
}
18+
19+
var cli struct {
20+
ExecTests execTestsCmd `cmd:"" help:"Executes tests given by test set" short:"e"`
21+
22+
Version versionCmd `cmd:"" help:"Prints the version of the program"`
23+
Debug bool `help:"Enable debug mode."`
24+
}
25+
26+
type versionCmd struct{}
27+
28+
type execTestsCmd struct {
29+
Set string `required:"" short:"s" default:"all" help:"Select a subset, or all test that should be run"`
30+
}
31+
32+
func (v *versionCmd) Run(ctx *context) error {
33+
tools.ShowVersion(programName, gittag, gitcommit)
34+
return nil
35+
}
36+
37+
func (e *execTestsCmd) Run(ctx *context) error {
38+
preset := &test.PreSet{}
39+
switch e.Set {
40+
case "general":
41+
run("AMD General", getTests("general"), preset)
42+
case "psb":
43+
run("AMD PSB", getTests("psb"), preset)
44+
case "sme":
45+
run("AMD SME", getTests("sme"), preset)
46+
case "sev":
47+
run("AMD SEV", getTests("sev"), preset)
48+
case "sevsnp":
49+
run("AMD SEV-SNP", getTests("sevsnp"), preset)
50+
case "all":
51+
fmt.Println("Running all tests")
52+
run("AMD", getTests("all"), preset)
53+
default:
54+
return fmt.Errorf("Unknown test set: %s", e.Set)
55+
}
56+
57+
return nil
58+
}
59+
60+
func getTests(group string) []*test.Test {
61+
switch group {
62+
case "psb":
63+
return test.TestsAMDPSP
64+
case "sme":
65+
return test.TestsAMDSME
66+
case "sev":
67+
return test.TestsAMDSEV
68+
case "sevsnp":
69+
return test.TestsAMDSEVSNP
70+
case "all":
71+
return test.TestsAMD
72+
default:
73+
// For "general" or unknown groups, return just the family/model test
74+
return []*test.Test{}
75+
}
76+
}
77+
78+
func run(testGroup string, tests []*test.Test, preset *test.PreSet) bool {
79+
result := false
80+
81+
hwAPI := hwapi.GetAPI()
82+
83+
log.Infof("%s tests (%d tests)", a.Bold(a.Gray(20-1, testGroup).BgGray(4-1)), len(tests))
84+
log.Info("--------------------------------------------------")
85+
for idx := range tests {
86+
if len(testnos) > 0 {
87+
// SearchInt returns an index where to "insert" idx
88+
i := sort.SearchInts(testnos, idx)
89+
if i >= len(testnos) {
90+
continue
91+
}
92+
// still here? i must be within testnos.
93+
if testnos[i] != idx {
94+
continue
95+
}
96+
}
97+
98+
_ = tests[idx].Run(hwAPI, preset)
99+
}
100+
101+
for index := range tests {
102+
var s string
103+
104+
if tests[index].Status == test.NotImplemented {
105+
continue
106+
}
107+
if tests[index].Result == test.ResultNotRun {
108+
continue
109+
}
110+
s += fmt.Sprintf("%02d - ", index)
111+
s += fmt.Sprintf("%-40s: ", a.Bold(tests[index].Name))
112+
113+
if tests[index].Result == test.ResultPass {
114+
s += fmt.Sprintf("%-20s", a.Bold(a.Green(tests[index].Result)))
115+
} else {
116+
s += fmt.Sprintf("%-20s", a.Bold(a.Red(tests[index].Result)))
117+
result = false
118+
}
119+
if tests[index].ErrorText != "" {
120+
s += fmt.Sprintf(" (%s)", tests[index].ErrorText)
121+
} else if len(tests[index].ErrorText) == 0 && tests[index].Result == test.ResultFail {
122+
s += " (No error text given)"
123+
}
124+
log.Infof("%s", s)
125+
126+
}
127+
128+
return result
129+
}

cmd/core/amd-suite/main.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package main
2+
3+
import (
4+
"github.com/9elements/converged-security-suite/v2/pkg/log"
5+
"github.com/alecthomas/kong"
6+
fianoLog "github.com/linuxboot/fiano/pkg/log"
7+
)
8+
9+
const (
10+
programName = "amd-suite"
11+
programDesc = "AMD PSB, SME, SEV and SEV-SNP Test Suite"
12+
)
13+
14+
var (
15+
gitcommit string
16+
gittag string
17+
testnos []int
18+
)
19+
20+
func main() {
21+
ctx := kong.Parse(&cli,
22+
kong.Name(programName),
23+
kong.Description(programDesc),
24+
kong.UsageOnError(),
25+
kong.ConfigureHelp(kong.HelpOptions{
26+
Compact: true,
27+
Summary: true,
28+
}))
29+
30+
fianoLog.DefaultLogger = log.FianoLogger{}
31+
err := ctx.Run(&context{})
32+
ctx.FatalIfErrorf(err)
33+
}

pkg/hwapi/mock_pc.go

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ import (
1212

1313
type pcmock struct {
1414
ReadMemoryFunc func(uint64) byte
15+
cpuidResponse map[uint32]struct {
16+
eax uint32
17+
ebx uint32
18+
ecx uint32
19+
edx uint32
20+
}
1521
}
1622

1723
func (n pcmock) CPUBlacklistTXTSupport() bool {
@@ -41,19 +47,30 @@ func (n pcmock) HasMTRR() bool {
4147
func (n pcmock) ProcessorBrandName() string {
4248
return ""
4349
}
50+
4451
func (n pcmock) CPUSignature() uint32 {
4552
return 0
4653
}
54+
4755
func (n pcmock) CPUSignatureFull() (uint32, uint32, uint32, uint32) {
4856
return 0, 0, 0, 0
4957
}
58+
5059
func (n pcmock) CPULogCount() uint32 {
5160
return 0
5261
}
5362

63+
func (n pcmock) CPUID(leaf uint32, subleaf uint32) (uint32, uint32, uint32, uint32) {
64+
if response, ok := n.cpuidResponse[leaf]; ok {
65+
return response.eax, response.ebx, response.ecx, response.edx
66+
}
67+
return 0, 0, 0, 0
68+
}
69+
5470
func (n pcmock) IsReservedInE820(start uint64, end uint64) (bool, error) {
5571
return false, fmt.Errorf("not implemented")
5672
}
73+
5774
func (n pcmock) UsableMemoryAbove4G() (size uint64, err error) {
5875
return 0, fmt.Errorf("not implemented")
5976
}
@@ -101,6 +118,7 @@ func (n pcmock) AllowsVMXInSMX() (bool, error) {
101118
func (n pcmock) TXTLeavesAreEnabled() (bool, error) {
102119
return false, fmt.Errorf("not implemented")
103120
}
121+
104122
func (n pcmock) IA32DebugInterfaceEnabledOrLocked() (*hwapi.IA32Debug, error) {
105123
return nil, fmt.Errorf("not implemented")
106124
}
@@ -153,10 +171,10 @@ func (n pcmock) ReadHostBridgeDPR() (hwapi.DMAProtectedRange, error) {
153171
return hwapi.DMAProtectedRange{}, fmt.Errorf("not implemented")
154172
}
155173

156-
//MockPCReadMemory emulates a x86_64 platform memory map
174+
// MockPCReadMemory emulates a x86_64 platform memory map
157175
func MockPCReadMemory(addr uint64) byte {
158176
mem := map[uint64][]byte{
159-
0xFED30000: []byte{
177+
0xFED30000: {
160178
0x01, 0xa7, 0x86, 0x80, 0x6b, 0xc8, 0x7b, 0x02, 0x00, 0x00, 0x00, 0x00,
161179
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162180
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -253,7 +271,6 @@ func MockPCReadMemory(addr uint64) byte {
253271
}
254272

255273
return 0xff
256-
257274
}
258275

259276
func (n pcmock) ReadPhys(addr int64, data hwapi.UintN) error {
@@ -299,9 +316,11 @@ func (n pcmock) NVLocked(tpmCon *hwapi.TPM) (bool, error) {
299316
func (n pcmock) ReadNVPublic(tpmCon *hwapi.TPM, index uint32) ([]byte, error) {
300317
return []byte{}, fmt.Errorf("not implemented")
301318
}
319+
302320
func (n pcmock) NVReadValue(tpmCon *hwapi.TPM, index uint32, password string, size, offhandle uint32) ([]byte, error) {
303321
return []byte{}, fmt.Errorf("not implemented")
304322
}
323+
305324
func (n pcmock) ReadPCR(tpmCon *hwapi.TPM, pcr uint32) ([]byte, error) {
306325
return []byte{}, fmt.Errorf("not implemented")
307326
}
@@ -342,9 +361,15 @@ func (n pcmock) PCIWriteConfigSpace(d hwapi.PCIDevice, off int, val interface{})
342361
return fmt.Errorf("not implemented")
343362
}
344363

345-
//GetPcMock returns APIInterfaces for mocking the hwapi used in unittests
364+
// GetPcMock returns APIInterfaces for mocking the hwapi used in unittests
346365
func GetPcMock(ReadMemoryFunc func(uint64) byte) hwapi.LowLevelHardwareInterfaces {
347366
return pcmock{
348-
ReadMemoryFunc,
367+
ReadMemoryFunc: ReadMemoryFunc,
368+
cpuidResponse: make(map[uint32]struct {
369+
eax uint32
370+
ebx uint32
371+
ecx uint32
372+
edx uint32
373+
}),
349374
}
350375
}

0 commit comments

Comments
 (0)