Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions apitypes/apitypes_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
9 changes: 4 additions & 5 deletions apitypes/attest.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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[:])
Expand Down
37 changes: 37 additions & 0 deletions apitypes/reportdata_test.go
Original file line number Diff line number Diff line change
@@ -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[:]))
}
Loading