Skip to content

Commit

Permalink
common/node: Verify AVR quote status
Browse files Browse the repository at this point in the history
When verifying a TEECapabilities structure, additionally verify the
quote status against the new SGXConstraints.AllowedQuoteStatuses vector
so that nodes that have an invalid quote status can be omitted from
scheduling entirely.

Note: QuoteOK is ALWAYS allowed, as disallowing it is nonsensical.
  • Loading branch information
Yawning committed Dec 13, 2021
1 parent 7dbb3d9 commit ffa93cd
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 10 deletions.
8 changes: 8 additions & 0 deletions .changelog/4055.internal.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
common/node: Verify AVR quote status

When verifying a TEECapabilities structure, additionally verify the
quote status against the new SGXConstraints.AllowedQuoteStatuses vector
so that nodes that have an invalid quote status can be omitted from
scheduling entirely.

Note: QuoteOK is ALWAYS allowed, as disallowing it is nonsensical.
42 changes: 41 additions & 1 deletion go/common/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ var (
// identity doesn't match the required values.
ErrBadEnclaveIdentity = errors.New("node: bad TEE enclave identity")

// ErrConstraintViolation the error returned when the TEE attestation
// fails to conform to the optional additional constraints.
ErrConstraintViolation = errors.New("node: TEE constraint violation")

teeHashContext = []byte("oasis-core/node: TEE RAK binding")

_ prettyprint.PrettyPrinter = (*MultiSignedNode)(nil)
Expand Down Expand Up @@ -436,6 +440,37 @@ type CapabilityTEE struct {
Attestation []byte `json:"attestation"`
}

// SGXConstraints are the Intel SGX TEE constraints.
type SGXConstraints struct {
// Enclaves is the allowed MRENCLAVE/MRSIGNER pairs.
Enclaves []sgx.EnclaveIdentity `json:"enclaves,omitempty"`

// AllowedQuoteStatuses are the allowed quote statuses for the node
// to be scheduled as a compute worker.
//
// Note: QuoteOK is ALWAYS allowed, and does not need to be specified.
AllowedQuoteStatuses []ias.ISVEnclaveQuoteStatus `json:"allowed_quote_statuses,omitempty"`
}

func (constraints *SGXConstraints) quoteStatusAllowed(avr *ias.AttestationVerificationReport) bool {
status := avr.ISVEnclaveQuoteStatus

// Always allow "OK".
if status == ias.QuoteOK {
return true
}

// Search through the constraints to see if the AVR quote status is
// explicitly allowed.
for _, v := range constraints.AllowedQuoteStatuses {
if v == status {
return true
}
}

return false
}

// RAKHash computes the expected AVR report hash bound to a given public RAK.
func RAKHash(rak signature.PublicKey) hash.Hash {
hData := make([]byte, 0, len(teeHashContext)+signature.PublicKeySize)
Expand Down Expand Up @@ -468,7 +503,7 @@ func (c *CapabilityTEE) Verify(ts time.Time, constraints []byte) error {

// Ensure that the MRENCLAVE/MRSIGNER match what is specified
// in the TEE-specific constraints field.
var cs sgx.Constraints
var cs SGXConstraints
if err := cbor.Unmarshal(constraints, &cs); err != nil {
return fmt.Errorf("node: malformed SGX constraints: %w", err)
}
Expand All @@ -493,6 +528,11 @@ func (c *CapabilityTEE) Verify(ts time.Time, constraints []byte) error {
return ErrRAKHashMismatch
}

// Ensure that the quote status is acceptable.
if !cs.quoteStatusAllowed(avr) {
return ErrConstraintViolation
}

// The last 32 bytes of the quote ReportData are deliberately
// ignored.

Expand Down
2 changes: 2 additions & 0 deletions go/common/sgx/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,10 @@ func (id EnclaveIdentity) String() string {
return hex.EncodeToString(id.MrEnclave[:]) + hex.EncodeToString(id.MrSigner[:])
}

/*
// Constraints are the Intel SGX TEE constraints.
type Constraints struct {
// Enclaves is the allowed MRENCLAVE/MRSIGNER pairs.
Enclaves []EnclaveIdentity `json:"enclaves"`
}
*/
4 changes: 2 additions & 2 deletions go/genesis/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func TestGenesisSanityCheck(t *testing.T) {
Kind: registry.KindKeyManager,
TEEHardware: node.TEEHardwareIntelSGX,
Version: registry.VersionInfo{
TEE: cbor.Marshal(sgx.Constraints{
TEE: cbor.Marshal(node.SGXConstraints{
Enclaves: []sgx.EnclaveIdentity{{}},
}),
},
Expand Down Expand Up @@ -243,7 +243,7 @@ func TestGenesisSanityCheck(t *testing.T) {
},
TEEHardware: node.TEEHardwareIntelSGX,
Version: registry.VersionInfo{
TEE: cbor.Marshal(sgx.Constraints{
TEE: cbor.Marshal(node.SGXConstraints{
Enclaves: []sgx.EnclaveIdentity{{}},
}),
},
Expand Down
3 changes: 2 additions & 1 deletion go/oasis-node/cmd/debug/byzantine/steps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/oasisprotocol/oasis-core/go/common/cbor"
"github.com/oasisprotocol/oasis-core/go/common/node"
"github.com/oasisprotocol/oasis-core/go/common/sgx"
"github.com/oasisprotocol/oasis-core/go/common/sgx/ias"
)
Expand All @@ -15,7 +16,7 @@ func TestFakeCapabilitySGX(t *testing.T) {
_, fakeCapabilitiesSGX, err := initFakeCapabilitiesSGX()
require.NoError(t, err, "initFakeCapabilitiesSGX failed")

cs := cbor.Marshal(sgx.Constraints{
cs := cbor.Marshal(node.SGXConstraints{
Enclaves: []sgx.EnclaveIdentity{{}},
})

Expand Down
2 changes: 1 addition & 1 deletion go/oasis-node/cmd/ias/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (st *enclaveStore) addRuntime(runtime *registry.Runtime) (int, error) {
return len(st.enclaves), nil
}

var cs sgx.Constraints
var cs node.SGXConstraints
if err := cbor.Unmarshal(runtime.Version.TEE, &cs); err != nil {
return len(st.enclaves), err
}
Expand Down
2 changes: 1 addition & 1 deletion go/oasis-test-runner/oasis/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (rt *Runtime) RefreshEnclaveIdentity() error {
enclaveIdentities = append(enclaveIdentities, sgx.EnclaveIdentity{MrEnclave: *mrEnclave, MrSigner: *rt.mrSigner})
mrEnclaves = append(mrEnclaves, mrEnclave)
}
rt.descriptor.Version.TEE = cbor.Marshal(sgx.Constraints{
rt.descriptor.Version.TEE = cbor.Marshal(node.SGXConstraints{
Enclaves: enclaveIdentities,
})
rt.mrEnclaves = mrEnclaves
Expand Down
3 changes: 1 addition & 2 deletions go/registry/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"github.com/oasisprotocol/oasis-core/go/common/logging"
"github.com/oasisprotocol/oasis-core/go/common/node"
"github.com/oasisprotocol/oasis-core/go/common/pubsub"
"github.com/oasisprotocol/oasis-core/go/common/sgx"
"github.com/oasisprotocol/oasis-core/go/consensus/api/transaction"
staking "github.com/oasisprotocol/oasis-core/go/staking/api"
)
Expand Down Expand Up @@ -996,7 +995,7 @@ func VerifyRuntime( // nolint: gocyclo
if rt.TEEHardware != node.TEEHardwareInvalid {
switch rt.TEEHardware {
case node.TEEHardwareIntelSGX:
var cs sgx.Constraints
var cs node.SGXConstraints
if err := cbor.Unmarshal(rt.Version.TEE, &cs); err != nil {
logger.Error("RegisterRuntime: invalid SGX TEE constraints",
"err", err,
Expand Down
4 changes: 2 additions & 2 deletions go/registry/tests/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ func testRegistryRuntime(t *testing.T, backend api.Backend, consensus consensusA
rt.Kind = api.KindKeyManager
rt.TEEHardware = node.TEEHardwareIntelSGX

cs := sgx.Constraints{
cs := node.SGXConstraints{
Enclaves: []sgx.EnclaveIdentity{{}},
}
rt.Version.TEE = cbor.Marshal(cs)
Expand Down Expand Up @@ -812,7 +812,7 @@ func testRegistryRuntime(t *testing.T, backend api.Backend, consensus consensusA
rt.KeyManager = &rtMapByName["KeyManager"].ID
rt.TEEHardware = node.TEEHardwareIntelSGX

cs := sgx.Constraints{
cs := node.SGXConstraints{
Enclaves: []sgx.EnclaveIdentity{{}},
}
rt.Version.TEE = cbor.Marshal(cs)
Expand Down

0 comments on commit ffa93cd

Please sign in to comment.