Skip to content

Commit

Permalink
add advisory list to attestation report
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasten committed Sep 18, 2024
1 parent 6636737 commit 71abc7e
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 31 deletions.
25 changes: 10 additions & 15 deletions attestation/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ import (

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

var (
Expand Down Expand Up @@ -51,12 +53,5 @@ func VerifyAzureAttestationToken(token string, providerURL string) (Report, erro
if err != nil {
return Report{}, err
}
return Report{
Data: report.Data,
SecurityVersion: report.SecurityVersion,
Debug: report.Debug,
UniqueID: report.UniqueID,
SignerID: report.SignerID,
ProductID: report.ProductID,
}, nil
return Report(report), nil
}
10 changes: 1 addition & 9 deletions enclave/ert.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,7 @@ func VerifyRemoteReport(reportBytes []byte) (attestation.Report, error) {
if err != nil {
return attestation.Report{}, err
}
return attestation.Report{
Data: report.Data,
SecurityVersion: report.SecurityVersion,
Debug: report.Debug,
UniqueID: report.UniqueID,
SignerID: report.SignerID,
ProductID: report.ProductID,
TCBStatus: report.TCBStatus,
}, verifyErr
return attestation.Report(report), verifyErr
}

// GetLocalReport gets a report signed by the enclave platform for use in local attestation.
Expand Down
16 changes: 9 additions & 7 deletions internal/attestation/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ import (

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

// https://github.com/openenclave/openenclave/blob/master/include/openenclave/internal/report.h
Expand Down
29 changes: 29 additions & 0 deletions internal/attestation/claim.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ package attestation
import "C"

import (
"bytes"
"encoding/json"
"errors"
"math"
"unsafe"

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

for _, claim := range claims {
switch C.GoString(claim.name) {
Expand All @@ -46,12 +51,17 @@ func parseClaims(claims []C.oe_claim_t) (Report, error) {
report.TCBStatus = tcbstatus.Status(claimUint(claim))
case C.OE_CLAIM_SGX_REPORT_DATA:
report.Data = claimBytes(claim)
case C.OE_CLAIM_SGX_TCB_INFO:
tcbInfo = claimBytes(claim)
case C.OE_CLAIM_SGX_TCB_INFO_INDEX:
tcbInfoIndex = claimUint(claim)
}
}

if !hasAttributes {
return Report{}, errors.New("missing attributes in report claims")
}
report.TCBAdvisories, report.TCBAdvisoriesErr = getAdvisoriesFromTCBInfo(tcbInfo, tcbInfoIndex)
return report, nil
}

Expand All @@ -65,3 +75,22 @@ func claimUint(claim C.oe_claim_t) uint {
func claimBytes(claim C.oe_claim_t) []byte {
return C.GoBytes(unsafe.Pointer(claim.value), C.int(claim.value_size))
}

func getAdvisoriesFromTCBInfo(tcbInfo []byte, tcbInfoIndex uint) ([]string, error) {
tcbInfo = bytes.Trim(tcbInfo, "\x00") // claim from OE includes null terminator

var info struct {
TCBInfo struct {
TCBLevels []struct{ AdvisoryIDs []string }
}
}
if err := json.Unmarshal(tcbInfo, &info); err != nil {
return nil, err
}

levels := info.TCBInfo.TCBLevels
if uint(len(levels)) <= tcbInfoIndex {
return nil, errors.New("invalid TCB info index")
}
return levels[tcbInfoIndex].AdvisoryIDs, nil
}
2 changes: 2 additions & 0 deletions internal/attestation/claim.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ typedef struct _oe_claim
#define OE_CLAIM_PRODUCT_ID "product_id"
#define OE_CLAIM_TCB_STATUS "tcb_status"
#define OE_CLAIM_SGX_REPORT_DATA "sgx_report_data"
#define OE_CLAIM_SGX_TCB_INFO "sgx_tcb_info"
#define OE_CLAIM_SGX_TCB_INFO_INDEX "sgx_tcb_info_index"
94 changes: 94 additions & 0 deletions internal/attestation/claim_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package attestation

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestGetAdvisoriesFromTCBInfo(t *testing.T) {
const tcbInfo = `
{
"tcbInfo": {
"tcbLevels": [
{
"tcbStatus": "UpToDate"
},
{
"tcbStatus": "OutOfDate",
"advisoryIDs": [
"id 1"
]
},
{
"tcbStatus": "OutOfDate",
"advisoryIDs": [
"id 2",
"id 3",
"id 4"
]
}
]
}
}
`

testCases := map[string]struct {
info string
index uint
wantErr bool
wantAdvisories []string
}{
"0 advisories at index 0": {
info: tcbInfo,
index: 0,
},
"1 advisory at index 1": {
info: tcbInfo,
index: 1,
wantAdvisories: []string{"id 1"},
},
"3 advisories at index 2": {
info: tcbInfo,
index: 2,
wantAdvisories: []string{"id 2", "id 3", "id 4"},
},
"error at index 3": {
info: tcbInfo,
index: 3,
wantErr: true,
},
"no TCB info": {
info: "",
index: 0,
wantErr: true,
},
"null-terminated TCB info": {
info: tcbInfo + "\x00",
index: 1,
wantAdvisories: []string{"id 1"},
},
"multiple null terminators": {
info: tcbInfo + "\x00\x00\x00",
index: 1,
wantAdvisories: []string{"id 1"},
},
}

for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
require := require.New(t)

advisories, err := getAdvisoriesFromTCBInfo([]byte(tc.info), tc.index)
if tc.wantErr {
assert.Error(err)
return
}
require.NoError(err)

assert.Equal(tc.wantAdvisories, advisories)
})
}
}

0 comments on commit 71abc7e

Please sign in to comment.