From 718637da43f95e2b01b2e8064220881d9f902626 Mon Sep 17 00:00:00 2001 From: Charlotte Hartmann Paludo Date: Tue, 18 Aug 2026 13:47:45 +0200 Subject: [PATCH] apitypes: depend on the standard library only --- apitypes/apitypes_test.go | 25 +++++++++++++++++++++++++ apitypes/attest.go | 9 ++++----- apitypes/reportdata_test.go | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 apitypes/apitypes_test.go create mode 100644 apitypes/reportdata_test.go diff --git a/apitypes/apitypes_test.go b/apitypes/apitypes_test.go new file mode 100644 index 0000000000..277a303b7e --- /dev/null +++ b/apitypes/apitypes_test.go @@ -0,0 +1,25 @@ +// Copyright 2026 Edgeless Systems GmbH +// SPDX-License-Identifier: BUSL-1.1 + +package apitypes + +import ( + "go/build" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +// TestNoExternalImports asserts that apitypes depends on the standard library only. +func TestNoExternalImports(t *testing.T) { + // Mode 0 only scans the directory for import statements, it does not resolve them. + pkg, err := build.ImportDir(".", 0) + require.NoError(t, err) + + for _, imp := range pkg.Imports { + // Standard library import paths have no dot in their first segment, because that segment cannot be a domain name. + first, _, _ := strings.Cut(imp, "/") + require.NotContains(t, first, ".", "apitypes must not import %q", imp) + } +} diff --git a/apitypes/attest.go b/apitypes/attest.go index aaab166f1a..2956bade9a 100644 --- a/apitypes/attest.go +++ b/apitypes/attest.go @@ -5,11 +5,10 @@ package apitypes import ( "bytes" + "crypto/sha256" "encoding/asn1" "encoding/json" "fmt" - - "github.com/edgelesssys/contrast/internal/history" ) // ReportDataSize is the size of the SNP/TDX REPORTDATA fields. @@ -98,14 +97,14 @@ type CoordinatorState struct { // intended for use with application-level verification. func ConstructReportData(nonce []byte, transitionDigest []byte, state *CoordinatorState) [ReportDataSize]byte { // reportdata = sha256(nonce || sha256(transition) || sha256(root-ca) || sha256(mesh-ca)) - rootCADigest := history.Digest(state.RootCA) - meshCADigest := history.Digest(state.MeshCA) + rootCADigest := sha256.Sum256(state.RootCA) + meshCADigest := sha256.Sum256(state.MeshCA) reportdata := append([]byte{}, nonce...) reportdata = append(reportdata, transitionDigest...) reportdata = append(reportdata, rootCADigest[:]...) reportdata = append(reportdata, meshCADigest[:]...) - hash32 := history.Digest(reportdata) + hash32 := sha256.Sum256(reportdata) var hash64 [64]byte copy(hash64[:], hash32[:]) diff --git a/apitypes/reportdata_test.go b/apitypes/reportdata_test.go new file mode 100644 index 0000000000..cd1a41f0db --- /dev/null +++ b/apitypes/reportdata_test.go @@ -0,0 +1,37 @@ +// Copyright 2026 Edgeless Systems GmbH +// SPDX-License-Identifier: BUSL-1.1 + +package apitypes + +import ( + "encoding/hex" + "testing" + + "github.com/stretchr/testify/assert" +) + +// TestConstructReportDataGolden pins the byte layout of the report data digest. +// +// The digest is baked into attestation reports and reproduced independently by every client, +// so any change here silently breaks verification against already-deployed Coordinators. +// If this test fails, the change needs a new API version, not a new test value. +func TestConstructReportDataGolden(t *testing.T) { + nonce := make([]byte, 32) + for i := range nonce { + nonce[i] = byte(i) + } + transitionDigest := make([]byte, 32) + for i := range transitionDigest { + transitionDigest[i] = byte(0xa0 + i) + } + state := &CoordinatorState{ + RootCA: []byte("root-ca"), + MeshCA: []byte("mesh-ca"), + } + + got := ConstructReportData(nonce, transitionDigest, state) + + want := "ec25193fbfa21fb46964de80adca8e7d70222ad41e67c77a696e2f188c02a0f2" + + "0000000000000000000000000000000000000000000000000000000000000000" + assert.Equal(t, want, hex.EncodeToString(got[:])) +}