Skip to content

Add teeattestation package for TEE attestation validation#1899

Open
nadahalli wants to merge 15 commits intomainfrom
tejaswi/tee-attestation
Open

Add teeattestation package for TEE attestation validation#1899
nadahalli wants to merge 15 commits intomainfrom
tejaswi/tee-attestation

Conversation

@nadahalli
Copy link
Copy Markdown
Contributor

@nadahalli nadahalli commented Mar 16, 2026

Summary

  • Adds pkg/teeattestation/ with platform-agnostic domain-separated hashing (DomainHash)
  • Adds pkg/teeattestation/nitro/ with AWS Nitro attestation validation (ValidateAttestation, PCR types, default CA roots)
  • Adds pkg/teeattestation/nitro/fake/ with FakeAttestor for testing without Nitro hardware
  • New dependency: github.com/hf/nitrite (Nitro attestation verifier)

Nitro-specific code is isolated in nitro/ so GCP Confidential Computing etc. can be added as sibling packages later.

Used by both confidential-compute (enclave-side) and chainlink (relay DON handler) for attestation validation and domain-separated hashing. It is an almost direct copy from https://github.com/smartcontractkit/confidential-compute/tree/main/enclave-client/attestation-validator

@nadahalli nadahalli requested a review from a team as a code owner March 16, 2026 17:24
Copilot AI review requested due to automatic review settings March 16, 2026 17:24
@github-actions
Copy link
Copy Markdown

👋 nadahalli, thanks for creating this pull request!

To help reviewers, please consider creating future PRs as drafts first. This allows you to self-review and make any final changes before notifying the team.

Once you're ready, you can mark it as "Ready for review" to request feedback. Thanks!

@nadahalli nadahalli force-pushed the tejaswi/tee-attestation branch from 0ea8118 to 2edce5f Compare March 16, 2026 17:26
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new teeattestation package providing platform-agnostic domain-separated hashing and AWS Nitro Enclave attestation validation, along with a fake attestor for testing.

Changes:

  • Introduces pkg/teeattestation/hash.go with DomainHash for domain-separated SHA-256 hashing
  • Adds pkg/teeattestation/nitro/validate.go with ValidateAttestation for verifying AWS Nitro attestation documents against expected PCRs and user data
  • Adds pkg/teeattestation/nitro/fake/ with a FakeAttestor that produces COSE Sign1 documents verifiable without real Nitro hardware

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pkg/teeattestation/hash.go Domain-separated SHA-256 hashing primitive
pkg/teeattestation/hash_test.go Tests for DomainHash
pkg/teeattestation/nitro/validate.go AWS Nitro attestation validation with PCR and user data checks
pkg/teeattestation/nitro/fake/fake.go Fake attestor producing valid COSE Sign1 docs for testing
pkg/teeattestation/nitro/fake/fake_test.go Tests for FakeAttestor
go.mod Adds github.com/hf/nitrite dependency
Comments suppressed due to low confidence (1)

pkg/teeattestation/nitro/validate.go:1

  • The cosePayload struct has an Unprotected field of type cbor.RawMessage, but it is not set when constructing outer in fake.go (line 147). CBOR nil/zero-value for RawMessage may serialize differently than the empty CBOR map ({}) that COSE Sign1 expects for the unprotected header. If nitrite.Verify is strict about this, it could fail. This comment applies to fake.go line 147, referencing the struct in the same file.
// Package nitro provides AWS Nitro Enclave attestation validation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


// ValidateAttestation verifies an AWS Nitro attestation document against
// expected user data and trusted PCR measurements.
func ValidateAttestation(attestation, expectedUserData, trustedMeasurements []byte, caRootsPEM string) error {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional. Empty string means 'use production default'. All existing callers pass empty string for production and a non-empty PEM for tests. Changing this would break the ergonomics for no practical gain.

"pcr1": hex.EncodeToString(f.pcrs[1]),
"pcr2": hex.EncodeToString(f.pcrs[2]),
}
b, _ := json.Marshal(m)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment. Changing the signature would break callers for an error that can't happen (json.Marshal on map[string]string).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, since it is simple and fixed, you could use fmt.Sprintf 🤷

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@nadahalli nadahalli force-pushed the tejaswi/tee-attestation branch 2 times, most recently from f9dede0 to 2c727f6 Compare March 16, 2026 17:29
@nadahalli nadahalli requested a review from a team March 16, 2026 17:32

// ValidateAttestation verifies an AWS Nitro attestation document against
// expected user data and trusted PCR measurements.
func ValidateAttestation(attestation, expectedUserData, trustedMeasurements []byte, caRootsPEM string) error {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: rename to ValidateNitroAttestation

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's inside the nitro folder. That should be enough, no?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah. Forgot about that.

@vreff
Copy link
Copy Markdown
Contributor

vreff commented Mar 16, 2026

Would be nice to put this behind a /privacy/ or /confidential-compute/ root package and mark that thing as being Privacy codeowners. That way we can maintain better autonomy for approvals.

@nadahalli
Copy link
Copy Markdown
Contributor Author

Would be nice to put this behind a /privacy/ or /confidential-compute/ root package and mark that thing as being Privacy codeowners. That way we can maintain better autonomy for approvals.

Let's add privacy as the owner of this folder. I don't want to add a privacy specific top-level package.

@vreff
Copy link
Copy Markdown
Contributor

vreff commented Mar 16, 2026

Let's add privacy as the owner of this folder. I don't want to add a privacy specific top-level package.

sure

vreff
vreff previously approved these changes Mar 16, 2026
@vreff
Copy link
Copy Markdown
Contributor

vreff commented Mar 26, 2026

LGTM, will ship when the linting is fixed.

Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 2.

Benchmark suite Current: 767c996 Previous: c7b8c13 Ratio
BenchmarkKeystore_Sign/nop/in-process 753.4 ns/op 356.1 ns/op 2.12

This comment was automatically generated by workflow using github-action-benchmark.

@nadahalli nadahalli force-pushed the tejaswi/tee-attestation branch from eef5bc4 to af5248c Compare March 26, 2026 14:43

// DefaultCARoots is the AWS Nitro Enclaves root certificate.
// Downloaded from: https://aws-nitro-enclaves.amazonaws.com/AWS_NitroEnclaves_Root-G1.zip
const DefaultCARoots = "-----BEGIN CERTIFICATE-----\nMIICETCCAZagAwIBAgIRAPkxdWgbkK/hHUbMtOTn+FYwCgYIKoZIzj0EAwMwSTEL\nMAkGA1UEBhMCVVMxDzANBgNVBAoMBkFtYXpvbjEMMAoGA1UECwwDQVdTMRswGQYD\nVQQDDBJhd3Mubml0cm8tZW5jbGF2ZXMwHhcNMTkxMDI4MTMyODA1WhcNNDkxMDI4\nMTQyODA1WjBJMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGQW1hem9uMQwwCgYDVQQL\nDANBV1MxGzAZBgNVBAMMEmF3cy5uaXRyby1lbmNsYXZlczB2MBAGByqGSM49AgEG\nBSuBBAAiA2IABPwCVOumCMHzaHDimtqQvkY4MpJzbolL//Zy2YlES1BR5TSksfbb\n48C8WBoyt7F2Bw7eEtaaP+ohG2bnUs990d0JX28TcPQXCEPZ3BABIeTPYwEoCWZE\nh8l5YoQwTcU/9KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkCW1DdkF\nR+eWw5b6cp3PmanfS5YwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYC\nMQCjfy+Rocm9Xue4YnwWmNJVA44fA0P5W2OpYow9OYCVRaEevL8uO1XYru5xtMPW\nrfMCMQCi85sWBbJwKKXdS6BptQFuZbT73o/gBh1qUxl/nNr12UO8Yfwr6wPLb+6N\nIwLz3/Y=\n-----END CERTIFICATE-----\n"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according to the docs nitrite package already contains root CA cert

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as in the followup comment - when having root hard-coded it would be even better to avoid this import at all

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

"testing"
"time"

"github.com/hf/nitrite"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitrite package seems suspicious - it's like 400 lines of code in total made by two contributors; does not seems like a rocket science what it does. maybe it could be entirely avoided?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given all the recent supply chain attacks. I am inclined to agree. Let me see if I can rewrite the entire thing from scratch, or worst case, copy the whole thing locally.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thx. if you trust what they did you can fork it internally (that's on MIT), but imho such a short code that maybe not even worth it. also afaik it's mostly copy&pasta from aws page with attestation verification examples anyway ..

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They also rely on https://github.com/fxamacker/cbor - which is quite an active repo. So, we need to pin that to some known version. If we do that, we might as well just pin nitrite as well, no?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so.
cc: @michelemin

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Nitro attestation verification path now lives in-tree under pkg/teeattestation/nitro/, so we no longer depend on the nitrite package. We now do COSE Sign1 parsing, CBOR decoding, cert-chain verification against the configured roots, etc.

I kept github.com/fxamacker/cbor/v2 as the only external parsing dependency and pinned it explicitly in go.mod to v2.9.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants