From 36d9a0d261d019fe9b497fa9b5447904e74f79e5 Mon Sep 17 00:00:00 2001 From: Jernej Kos Date: Wed, 6 Nov 2024 09:37:27 +0100 Subject: [PATCH] go/runtime/bundle: Add expected enclave identity to manifest --- .changelog/5931.feature.md | 1 + go/runtime/bundle/bundle.go | 35 ++++++++++++++++++++++++++++---- go/runtime/bundle/bundle_test.go | 17 ++++++++++++++++ go/runtime/bundle/manifest.go | 17 ++++++++++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 .changelog/5931.feature.md diff --git a/.changelog/5931.feature.md b/.changelog/5931.feature.md new file mode 100644 index 00000000000..36eb4ffa927 --- /dev/null +++ b/.changelog/5931.feature.md @@ -0,0 +1 @@ +go/runtime/bundle: Add expected enclave identity to manifest diff --git a/go/runtime/bundle/bundle.go b/go/runtime/bundle/bundle.go index f0e4ee4fda6..137813db54b 100644 --- a/go/runtime/bundle/bundle.go +++ b/go/runtime/bundle/bundle.go @@ -219,8 +219,33 @@ func (bnd *Bundle) MrSigner(id component.ID) (*sgx.MrSigner, error) { return &mrSigner, nil } -// EnclaveIdentity returns the SGX enclave identity of the given component. +// EnclaveIdentity returns the enclave identity of the given component. +// +// Deprecated: Use EnclaveIdentities instead. func (bnd *Bundle) EnclaveIdentity(id component.ID) (*sgx.EnclaveIdentity, error) { + ids, err := bnd.EnclaveIdentities(id) + if err != nil { + return nil, err + } + return &ids[0], nil +} + +// EnclaveIdentities returns the enclave identities of the given component. +func (bnd *Bundle) EnclaveIdentities(id component.ID) ([]sgx.EnclaveIdentity, error) { + // If the component has a build-time known expected identity, use it. + comp := bnd.Manifest.GetComponentByID(id) + if comp == nil { + return nil, fmt.Errorf("runtime/bundle: component '%s' not available", id) + } + if len(comp.Identities) > 0 { + ids := make([]sgx.EnclaveIdentity, 0, len(comp.Identities)) + for _, id := range comp.Identities { + ids = append(ids, id.Enclave) + } + return ids, nil + } + + // When not available, recompute at runtime (only supported for SGX). mrEnclave, err := bnd.MrEnclave(id) if err != nil { return nil, err @@ -231,9 +256,11 @@ func (bnd *Bundle) EnclaveIdentity(id component.ID) (*sgx.EnclaveIdentity, error return nil, err } - return &sgx.EnclaveIdentity{ - MrEnclave: *mrEnclave, - MrSigner: *mrSigner, + return []sgx.EnclaveIdentity{ + { + MrEnclave: *mrEnclave, + MrSigner: *mrSigner, + }, }, nil } diff --git a/go/runtime/bundle/bundle_test.go b/go/runtime/bundle/bundle_test.go index 7ace6bdabd1..47c6ed34fda 100644 --- a/go/runtime/bundle/bundle_test.go +++ b/go/runtime/bundle/bundle_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/oasisprotocol/oasis-core/go/common" + "github.com/oasisprotocol/oasis-core/go/common/sgx" "github.com/oasisprotocol/oasis-core/go/runtime/bundle/component" ) @@ -40,6 +41,15 @@ func TestBundle(t *testing.T) { SGX: &SGXMetadata{ Executable: "runtime.sgx", }, + Identities: []Identity{ + { + Hypervisor: "test", + Enclave: sgx.EnclaveIdentity{ + MrSigner: sgx.MrSigner{0x01}, + MrEnclave: sgx.MrEnclave{0x02}, + }, + }, + }, }, }, } @@ -77,6 +87,13 @@ func TestBundle(t *testing.T) { delete(bundle2.Data, manifestName) ensureBundlesEqual(t, bundle, bundle2, "opened bundle mismatch") + + // Test enclave identity is correct. + eids, err := bundle2.EnclaveIdentities(component.ID_RONL) + require.NoError(t, err, "EnclaveIdentities") + require.Len(t, eids, 1) + require.Equal(t, "0100000000000000000000000000000000000000000000000000000000000000", eids[0].MrSigner.String()) + require.Equal(t, "0200000000000000000000000000000000000000000000000000000000000000", eids[0].MrEnclave.String()) }) t.Run("ResetManifest", func(t *testing.T) { diff --git a/go/runtime/bundle/manifest.go b/go/runtime/bundle/manifest.go index 63e5840dd63..73ca1540f18 100644 --- a/go/runtime/bundle/manifest.go +++ b/go/runtime/bundle/manifest.go @@ -5,6 +5,7 @@ import ( "github.com/oasisprotocol/oasis-core/go/common" "github.com/oasisprotocol/oasis-core/go/common/crypto/hash" + "github.com/oasisprotocol/oasis-core/go/common/sgx" "github.com/oasisprotocol/oasis-core/go/common/version" "github.com/oasisprotocol/oasis-core/go/runtime/bundle/component" ) @@ -214,6 +215,15 @@ func (r *TDXResources) Validate() error { return nil } +// Identity is the cryptographic identity of a component. +type Identity struct { + // Hypervisor is the optional hypervisor this identity is for. + Hypervisor string `json:"hypervisor,omitempty"` + + // Enclave is the enclave identity. + Enclave sgx.EnclaveIdentity `json:"enclave"` +} + // Component is a runtime component. type Component struct { // Kind is the component kind. @@ -232,6 +242,13 @@ type Component struct { // TDX is the TDX specific manifest metadata if any. TDX *TDXMetadata `json:"tdx,omitempty"` + // Identities are the (optional) expected enclave identities. When not provided, it must be + // computed at runtime. In the future, this field will become required. + // + // Multiple identities may be provided because they can differ across different deployment + // systems (e.g. hypervisors). + Identities []Identity `json:"identity,omitempty"` + // Disabled specifies whether the component is disabled by default and needs to be explicitly // enabled via node configuration to be used. Disabled bool `json:"disabled,omitempty"`