1
2
3
4
5
6 package amdsevsnp
7
8 import (
9 "bytes"
10 "encoding/binary"
11 "encoding/hex"
12 "fmt"
13 "os"
14 "unsafe"
15
16 "github.com/Microsoft/hcsshim/internal/guest/linux"
17 )
18
19 const (
20 msgTypeInvalid = iota
21 msgCPUIDRequest
22 msgCPUIDResponse
23 msgKeyRequest
24 msgKeyResponse
25 msgReportRequest
26 msgReportResponse
27 msgExportRequest
28 msgExportResponse
29 msgImportRequest
30 msgImportResponse
31 msgAbsorbRequest
32 msgAbsorbResponse
33 msgVMRKRequest
34 msgVMRKResponse
35 msgTypeMax
36 )
37
38 type guestRequest struct {
39 RequestMsgType byte
40 ResponseMsgType byte
41 MsgVersion byte
42 RequestLength uint16
43 RequestUAddr unsafe.Pointer
44 ResponseLength uint16
45 ResponseUAddr unsafe.Pointer
46 Error uint32
47 }
48
49
50 const (
51
52 guestType = 'S'
53
54 guestSize = 40
55 ioctlBase = linux.IocWRBase | guestType<<linux.IocTypeShift | guestSize<<linux.IocSizeShift
56
57
58 reportCode = 0x1
59 )
60
61
62
63
64 type reportRequest struct {
65 ReportData [64]byte
66 VMPL uint32
67 _ [28]byte
68 }
69
70
71
72
73 type report struct {
74 Version uint32
75 GuestSVN uint32
76 Policy uint64
77 FamilyID [16]byte
78 ImageID [16]byte
79 VMPL uint32
80 SignatureAlgo uint32
81 PlatformVersion uint64
82 PlatformInfo uint64
83 AuthorKeyEn uint32
84 Reserved1 uint32
85 ReportData [64]byte
86 Measurement [48]byte
87 HostData [32]byte
88 IDKeyDigest [48]byte
89 AuthorKeyDigest [48]byte
90 ReportID [32]byte
91 ReportIDMA [32]byte
92 ReportTCB uint64
93 Reserved2 [24]byte
94 ChipID [64]byte
95 CommittedSVN [8]byte
96 CommittedVersion [8]byte
97 LaunchSVN [8]byte
98 Reserved3 [168]byte
99 Signature [512]byte
100 }
101
102 func (sr *report) report() Report {
103 return Report{
104 Version: sr.Version,
105 GuestSVN: sr.GuestSVN,
106 Policy: sr.Policy,
107 FamilyID: hex.EncodeToString(mirrorBytes(sr.FamilyID[:])[:]),
108 ImageID: hex.EncodeToString(mirrorBytes(sr.ImageID[:])[:]),
109 VMPL: sr.VMPL,
110 SignatureAlgo: sr.SignatureAlgo,
111 PlatformVersion: sr.PlatformVersion,
112 PlatformInfo: sr.PlatformInfo,
113 AuthorKeyEn: sr.AuthorKeyEn,
114 ReportData: hex.EncodeToString(sr.ReportData[:]),
115 Measurement: hex.EncodeToString(sr.Measurement[:]),
116 HostData: sr.HostData[:],
117 IDKeyDigest: hex.EncodeToString(sr.IDKeyDigest[:]),
118 AuthorKeyDigest: hex.EncodeToString(sr.AuthorKeyDigest[:]),
119 ReportID: hex.EncodeToString(sr.ReportID[:]),
120 ReportIDMA: hex.EncodeToString(sr.ReportIDMA[:]),
121 ReportTCB: sr.ReportTCB,
122 ChipID: hex.EncodeToString(sr.ChipID[:]),
123 CommittedSVN: hex.EncodeToString(sr.CommittedSVN[:]),
124 CommittedVersion: hex.EncodeToString(sr.CommittedVersion[:]),
125 LaunchSVN: hex.EncodeToString(sr.LaunchSVN[:]),
126 Signature: hex.EncodeToString(sr.Signature[:]),
127 }
128 }
129
130
131
132
133
134
135
136
137
138 type reportResponse struct {
139 Status uint32
140 ReportSize uint32
141 reserved1 [24]byte
142 Report [1184]byte
143 reserved2 [64]byte
144 }
145
146
147 func FetchRawSNPReport(reportData []byte) ([]byte, error) {
148 f, err := os.OpenFile("/dev/sev", os.O_RDWR, 0)
149 if err != nil {
150 return nil, err
151 }
152 defer func() {
153 _ = f.Close()
154 }()
155
156 var (
157 msgReportIn reportRequest
158 msgReportOut reportResponse
159 )
160
161 if reportData != nil {
162 if len(reportData) > len(msgReportIn.ReportData) {
163 return nil, fmt.Errorf("reportData too large: %s", reportData)
164 }
165 copy(msgReportIn.ReportData[:], reportData)
166 }
167
168 payload := &guestRequest{
169 RequestMsgType: msgReportRequest,
170 ResponseMsgType: msgReportResponse,
171 MsgVersion: 1,
172 RequestLength: uint16(unsafe.Sizeof(msgReportIn)),
173 RequestUAddr: unsafe.Pointer(&msgReportIn),
174 ResponseLength: uint16(unsafe.Sizeof(msgReportOut)),
175 ResponseUAddr: unsafe.Pointer(&msgReportOut),
176 Error: 0,
177 }
178
179 if err := linux.Ioctl(f, reportCode|ioctlBase, unsafe.Pointer(payload)); err != nil {
180 return nil, err
181 }
182 return msgReportOut.Report[:], nil
183 }
184
185
186 type Report struct {
187 Version uint32
188 GuestSVN uint32
189 Policy uint64
190 FamilyID string
191 ImageID string
192 VMPL uint32
193 SignatureAlgo uint32
194 PlatformVersion uint64
195 PlatformInfo uint64
196 AuthorKeyEn uint32
197 ReportData string
198 Measurement string
199 HostData []byte
200 IDKeyDigest string
201 AuthorKeyDigest string
202 ReportID string
203 ReportIDMA string
204 ReportTCB uint64
205 ChipID string
206 CommittedSVN string
207 CommittedVersion string
208 LaunchSVN string
209 Signature string
210 }
211
212
213
214 func mirrorBytes(b []byte) []byte {
215 for i := 0; i < len(b)/2; i++ {
216 mirrorIndex := len(b) - i - 1
217 b[i], b[mirrorIndex] = b[mirrorIndex], b[i]
218 }
219 return b
220 }
221
222
223 func FetchParsedSNPReport(reportData []byte) (Report, error) {
224 rawBytes, err := FetchRawSNPReport(reportData)
225 if err != nil {
226 return Report{}, err
227 }
228
229 var r report
230 buf := bytes.NewBuffer(rawBytes)
231 if err := binary.Read(buf, binary.LittleEndian, &r); err != nil {
232 return Report{}, err
233 }
234 return r.report(), nil
235 }
236
View as plain text