Skip to content

Commit 71abc7e

Browse files
committed
add advisory list to attestation report
1 parent 6636737 commit 71abc7e

File tree

6 files changed

+145
-31
lines changed

6 files changed

+145
-31
lines changed

attestation/attestation.go

+10-15
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ import (
1515

1616
// Report is a parsed enclave report.
1717
type Report struct {
18-
Data []byte // The report data that has been included in the report.
19-
SecurityVersion uint // Security version of the enclave. For SGX enclaves, this is the ISVSVN value.
20-
Debug bool // If true, the report is for a debug enclave.
21-
UniqueID []byte // The unique ID for the enclave. For SGX enclaves, this is the MRENCLAVE value.
22-
SignerID []byte // The signer ID for the enclave. For SGX enclaves, this is the MRSIGNER value.
23-
ProductID []byte // The Product ID for the enclave. For SGX enclaves, this is the ISVPRODID value.
24-
TCBStatus tcbstatus.Status // The status of the enclave's TCB level.
18+
Data []byte // The report data that has been included in the report.
19+
SecurityVersion uint // Security version of the enclave. For SGX enclaves, this is the ISVSVN value.
20+
Debug bool // If true, the report is for a debug enclave.
21+
UniqueID []byte // The unique ID for the enclave. For SGX enclaves, this is the MRENCLAVE value.
22+
SignerID []byte // The signer ID for the enclave. For SGX enclaves, this is the MRSIGNER value.
23+
ProductID []byte // The Product ID for the enclave. For SGX enclaves, this is the ISVPRODID value.
24+
TCBStatus tcbstatus.Status // The status of the enclave's TCB level.
25+
TCBAdvisories []string // IDs of Intel security advisories that provide insight into the reasons when the TCB status is not UpToDate.
26+
TCBAdvisoriesErr error // Error that occurred while getting the advisory array (if any).
2527
}
2628

2729
var (
@@ -51,12 +53,5 @@ func VerifyAzureAttestationToken(token string, providerURL string) (Report, erro
5153
if err != nil {
5254
return Report{}, err
5355
}
54-
return Report{
55-
Data: report.Data,
56-
SecurityVersion: report.SecurityVersion,
57-
Debug: report.Debug,
58-
UniqueID: report.UniqueID,
59-
SignerID: report.SignerID,
60-
ProductID: report.ProductID,
61-
}, nil
56+
return Report(report), nil
6257
}

enclave/ert.go

+1-9
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,7 @@ func VerifyRemoteReport(reportBytes []byte) (attestation.Report, error) {
106106
if err != nil {
107107
return attestation.Report{}, err
108108
}
109-
return attestation.Report{
110-
Data: report.Data,
111-
SecurityVersion: report.SecurityVersion,
112-
Debug: report.Debug,
113-
UniqueID: report.UniqueID,
114-
SignerID: report.SignerID,
115-
ProductID: report.ProductID,
116-
TCBStatus: report.TCBStatus,
117-
}, verifyErr
109+
return attestation.Report(report), verifyErr
118110
}
119111

120112
// GetLocalReport gets a report signed by the enclave platform for use in local attestation.

internal/attestation/attestation.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ import (
2525

2626
// Report is a parsed enclave report.
2727
type Report struct {
28-
Data []byte // The report data that has been included in the report.
29-
SecurityVersion uint // Security version of the enclave. For SGX enclaves, this is the ISVSVN value.
30-
Debug bool // If true, the report is for a debug enclave.
31-
UniqueID []byte // The unique ID for the enclave. For SGX enclaves, this is the MRENCLAVE value.
32-
SignerID []byte // The signer ID for the enclave. For SGX enclaves, this is the MRSIGNER value.
33-
ProductID []byte // The Product ID for the enclave. For SGX enclaves, this is the ISVPRODID value.
34-
TCBStatus tcbstatus.Status // The status of the enclave's TCB level.
28+
Data []byte // The report data that has been included in the report.
29+
SecurityVersion uint // Security version of the enclave. For SGX enclaves, this is the ISVSVN value.
30+
Debug bool // If true, the report is for a debug enclave.
31+
UniqueID []byte // The unique ID for the enclave. For SGX enclaves, this is the MRENCLAVE value.
32+
SignerID []byte // The signer ID for the enclave. For SGX enclaves, this is the MRSIGNER value.
33+
ProductID []byte // The Product ID for the enclave. For SGX enclaves, this is the ISVPRODID value.
34+
TCBStatus tcbstatus.Status // The status of the enclave's TCB level.
35+
TCBAdvisories []string // IDs of Intel security advisories that provide insight into the reasons when the TCB status is not UpToDate.
36+
TCBAdvisoriesErr error // Error that occurred while getting the advisory array (if any).
3537
}
3638

3739
// https://github.com/openenclave/openenclave/blob/master/include/openenclave/internal/report.h

internal/attestation/claim.go

+29
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ package attestation
1010
import "C"
1111

1212
import (
13+
"bytes"
14+
"encoding/json"
1315
"errors"
16+
"math"
1417
"unsafe"
1518

1619
"github.com/edgelesssys/ego/attestation/tcbstatus"
@@ -24,6 +27,8 @@ func ParseClaims(claims uintptr, claimsLength uintptr) (Report, error) {
2427
func parseClaims(claims []C.oe_claim_t) (Report, error) {
2528
report := Report{TCBStatus: tcbstatus.Unknown}
2629
hasAttributes := false
30+
var tcbInfo []byte
31+
var tcbInfoIndex uint = math.MaxUint
2732

2833
for _, claim := range claims {
2934
switch C.GoString(claim.name) {
@@ -46,12 +51,17 @@ func parseClaims(claims []C.oe_claim_t) (Report, error) {
4651
report.TCBStatus = tcbstatus.Status(claimUint(claim))
4752
case C.OE_CLAIM_SGX_REPORT_DATA:
4853
report.Data = claimBytes(claim)
54+
case C.OE_CLAIM_SGX_TCB_INFO:
55+
tcbInfo = claimBytes(claim)
56+
case C.OE_CLAIM_SGX_TCB_INFO_INDEX:
57+
tcbInfoIndex = claimUint(claim)
4958
}
5059
}
5160

5261
if !hasAttributes {
5362
return Report{}, errors.New("missing attributes in report claims")
5463
}
64+
report.TCBAdvisories, report.TCBAdvisoriesErr = getAdvisoriesFromTCBInfo(tcbInfo, tcbInfoIndex)
5565
return report, nil
5666
}
5767

@@ -65,3 +75,22 @@ func claimUint(claim C.oe_claim_t) uint {
6575
func claimBytes(claim C.oe_claim_t) []byte {
6676
return C.GoBytes(unsafe.Pointer(claim.value), C.int(claim.value_size))
6777
}
78+
79+
func getAdvisoriesFromTCBInfo(tcbInfo []byte, tcbInfoIndex uint) ([]string, error) {
80+
tcbInfo = bytes.Trim(tcbInfo, "\x00") // claim from OE includes null terminator
81+
82+
var info struct {
83+
TCBInfo struct {
84+
TCBLevels []struct{ AdvisoryIDs []string }
85+
}
86+
}
87+
if err := json.Unmarshal(tcbInfo, &info); err != nil {
88+
return nil, err
89+
}
90+
91+
levels := info.TCBInfo.TCBLevels
92+
if uint(len(levels)) <= tcbInfoIndex {
93+
return nil, errors.New("invalid TCB info index")
94+
}
95+
return levels[tcbInfoIndex].AdvisoryIDs, nil
96+
}

internal/attestation/claim.h

+2
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ typedef struct _oe_claim
2222
#define OE_CLAIM_PRODUCT_ID "product_id"
2323
#define OE_CLAIM_TCB_STATUS "tcb_status"
2424
#define OE_CLAIM_SGX_REPORT_DATA "sgx_report_data"
25+
#define OE_CLAIM_SGX_TCB_INFO "sgx_tcb_info"
26+
#define OE_CLAIM_SGX_TCB_INFO_INDEX "sgx_tcb_info_index"

internal/attestation/claim_test.go

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package attestation
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
func TestGetAdvisoriesFromTCBInfo(t *testing.T) {
11+
const tcbInfo = `
12+
{
13+
"tcbInfo": {
14+
"tcbLevels": [
15+
{
16+
"tcbStatus": "UpToDate"
17+
},
18+
{
19+
"tcbStatus": "OutOfDate",
20+
"advisoryIDs": [
21+
"id 1"
22+
]
23+
},
24+
{
25+
"tcbStatus": "OutOfDate",
26+
"advisoryIDs": [
27+
"id 2",
28+
"id 3",
29+
"id 4"
30+
]
31+
}
32+
]
33+
}
34+
}
35+
`
36+
37+
testCases := map[string]struct {
38+
info string
39+
index uint
40+
wantErr bool
41+
wantAdvisories []string
42+
}{
43+
"0 advisories at index 0": {
44+
info: tcbInfo,
45+
index: 0,
46+
},
47+
"1 advisory at index 1": {
48+
info: tcbInfo,
49+
index: 1,
50+
wantAdvisories: []string{"id 1"},
51+
},
52+
"3 advisories at index 2": {
53+
info: tcbInfo,
54+
index: 2,
55+
wantAdvisories: []string{"id 2", "id 3", "id 4"},
56+
},
57+
"error at index 3": {
58+
info: tcbInfo,
59+
index: 3,
60+
wantErr: true,
61+
},
62+
"no TCB info": {
63+
info: "",
64+
index: 0,
65+
wantErr: true,
66+
},
67+
"null-terminated TCB info": {
68+
info: tcbInfo + "\x00",
69+
index: 1,
70+
wantAdvisories: []string{"id 1"},
71+
},
72+
"multiple null terminators": {
73+
info: tcbInfo + "\x00\x00\x00",
74+
index: 1,
75+
wantAdvisories: []string{"id 1"},
76+
},
77+
}
78+
79+
for name, tc := range testCases {
80+
t.Run(name, func(t *testing.T) {
81+
assert := assert.New(t)
82+
require := require.New(t)
83+
84+
advisories, err := getAdvisoriesFromTCBInfo([]byte(tc.info), tc.index)
85+
if tc.wantErr {
86+
assert.Error(err)
87+
return
88+
}
89+
require.NoError(err)
90+
91+
assert.Equal(tc.wantAdvisories, advisories)
92+
})
93+
}
94+
}

0 commit comments

Comments
 (0)