Skip to content

Commit 0e12934

Browse files
committed
Pad SHA-256 attestation report data
1 parent 6178b2e commit 0e12934

7 files changed

Lines changed: 27 additions & 13 deletions

File tree

consul-postgres-ha/ATTESTATION.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ current dstack guest agents: `quote`, `event_log`, and `vm_config`.
4040

4141
## Report Data
4242

43-
`report_data` is an unstructured SHA-256 digest. The structured
44-
admission data stays outside the quote in the binding statement:
43+
`report_data` is the 64-byte TDX REPORTDATA field. The structured
44+
admission data stays outside the quote in the binding statement.
45+
The first 32 bytes are a SHA-256 digest; the remaining 32 bytes are
46+
zero padding:
4547

4648
```text
47-
report_data = SHA-256(binding_statement_json || broker_nonce)
49+
report_data = SHA-256(binding_statement_json || broker_nonce) || 32 zero bytes
4850
```
4951

5052
The broker nonce is 32 random bytes encoded as hex. The binding

consul-postgres-ha/PROGRESS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ deployment model, trust model, or operational status.
6060

6161
- Workload identity is the Terraform-declared identity; compose hash
6262
is revision evidence, not the workload key.
63-
- `report_data` is `SHA-256(binding_statement_json || nonce)`.
63+
- `report_data` is the 64-byte TDX REPORTDATA field:
64+
`SHA-256(binding_statement_json || nonce) || 32 zero bytes`.
6465
- The broker relies on `dstack-verifier` for quote and event-log
6566
semantics. It does not parse raw RTMR event-log internals itself.
6667
- `peer_id` is the logical mesh/Consul node label, for example

consul-postgres-ha/admission-broker/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,10 @@ func reportDataHex(bindingHex, nonceHex string) (string, error) {
344344
h := sha256.New()
345345
h.Write(binding)
346346
h.Write(nonce)
347-
return hex.EncodeToString(h.Sum(nil)), nil
347+
digest := h.Sum(nil)
348+
reportData := make([]byte, 64)
349+
copy(reportData, digest)
350+
return hex.EncodeToString(reportData), nil
348351
}
349352

350353
func rawJSONAsString(raw json.RawMessage) string {

consul-postgres-ha/admission-broker/main_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ func TestReportDataHexBindsStatementAndNonce(t *testing.T) {
123123
h := sha256.New()
124124
h.Write(bindingBytes)
125125
h.Write(nonceBytes)
126-
want := hex.EncodeToString(h.Sum(nil))
126+
wantBytes := make([]byte, 64)
127+
copy(wantBytes, h.Sum(nil))
128+
want := hex.EncodeToString(wantBytes)
127129
if got != want {
128130
t.Fatalf("report_data mismatch\nwant %s\n got %s", want, got)
129131
}

consul-postgres-ha/admission-client/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,10 @@ func reportData(statementBytes []byte, nonceHex string) ([]byte, error) {
240240
h := sha256.New()
241241
h.Write(statementBytes)
242242
h.Write(nonce)
243-
return h.Sum(nil), nil
243+
digest := h.Sum(nil)
244+
reportData := make([]byte, 64)
245+
copy(reportData, digest)
246+
return reportData, nil
244247
}
245248

246249
func writeToken(path, token string) error {

consul-postgres-ha/admission-client/main_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ func TestReportDataBindsStatementAndNonce(t *testing.T) {
2626
h := sha256.New()
2727
h.Write(statement)
2828
h.Write(nonceBytes)
29-
if !bytes.Equal(got, h.Sum(nil)) {
29+
want := make([]byte, 64)
30+
copy(want, h.Sum(nil))
31+
if !bytes.Equal(got, want) {
3032
t.Fatalf("report data mismatch")
3133
}
3234
}

consul-postgres-ha/design/attestation-admission.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,11 @@ The broker validates:
141141
1. **Quote chain**: TDX → Intel PCS root, via a sibling
142142
`dstack-verifier` HTTP service.
143143
2. **`report_data` binding**: must equal
144-
`SHA-256(binding_statement || nonce)`. Anything else means the
145-
quote was generated for a different handshake; reject. The broker
146-
also verifies that the statement identity equals the claimed
147-
identity.
144+
`SHA-256(binding_statement || nonce)` placed in the first 32 bytes
145+
of the 64-byte TDX REPORTDATA field, with the remaining 32 bytes
146+
zero padded. Anything else means the quote was generated for a
147+
different handshake; reject. The broker also verifies that the
148+
statement identity equals the claimed identity.
148149
3. **Nonce freshness**: must be a nonce the broker issued
149150
recently and hasn't been consumed.
150151
4. **Verifier event-log result**: require `event_log_verified` from
@@ -328,7 +329,7 @@ client agent itself, then for each declared service identity.
328329
329330
3. POST /v1/admission/challenge to broker. Receive nonce.
330331
331-
4. report_data = SHA-256(binding_statement || nonce)
332+
4. report_data = SHA-256(binding_statement || nonce) || 32 zero bytes
332333
Call dstack GetQuote(report_data). Receive quote, event_log,
333334
vm_config, and report_data.
334335

0 commit comments

Comments
 (0)