|
| 1 | +// Copyright 2025 Edgeless Systems GmbH |
| 2 | +// SPDX-License-Identifier: BUSL-1.1 |
| 3 | + |
| 4 | +// Package insecure provides a fake aTLS issuer and validator for development |
| 5 | +// platforms without confidential computing hardware. |
| 6 | +package insecure |
| 7 | + |
| 8 | +import ( |
| 9 | + "context" |
| 10 | + "encoding/asn1" |
| 11 | + "encoding/json" |
| 12 | + "fmt" |
| 13 | + "io" |
| 14 | + "net/http" |
| 15 | + |
| 16 | + "github.com/edgelesssys/contrast/internal/oid" |
| 17 | +) |
| 18 | + |
| 19 | +// HostdataAddr is the address where the initdata-processor serves the |
| 20 | +// hostdata digest on insecure platforms. |
| 21 | +const HostdataAddr = "127.0.0.1:19629" |
| 22 | + |
| 23 | +// HostdataURL is the full URL for fetching the hostdata digest. |
| 24 | +const HostdataURL = "http://" + HostdataAddr + "/hostdata" |
| 25 | + |
| 26 | +// Issuer issues fake attestation documents for insecure (non-CC) platforms. |
| 27 | +// |
| 28 | +// It fetches the initdata digest from the local initdata-processor HTTP server |
| 29 | +// and packages it with the report data into a JSON attestation document. |
| 30 | +type Issuer struct { |
| 31 | + hostdataURL string |
| 32 | + client *http.Client |
| 33 | +} |
| 34 | + |
| 35 | +// NewIssuer creates a new insecure issuer. |
| 36 | +func NewIssuer() *Issuer { |
| 37 | + return &Issuer{hostdataURL: HostdataURL, client: http.DefaultClient} |
| 38 | +} |
| 39 | + |
| 40 | +// OID returns the OID for the insecure attestation. |
| 41 | +func (i *Issuer) OID() asn1.ObjectIdentifier { |
| 42 | + return oid.RawInsecureReport |
| 43 | +} |
| 44 | + |
| 45 | +// Issue creates a fake attestation document containing the report data and |
| 46 | +// the initdata digest fetched from the local hostdata server. |
| 47 | +func (i *Issuer) Issue(ctx context.Context, reportData [64]byte) ([]byte, error) { |
| 48 | + req, err := http.NewRequestWithContext(ctx, http.MethodGet, i.hostdataURL, nil) |
| 49 | + if err != nil { |
| 50 | + return nil, fmt.Errorf("creating hostdata request: %w", err) |
| 51 | + } |
| 52 | + resp, err := i.client.Do(req) |
| 53 | + if err != nil { |
| 54 | + return nil, fmt.Errorf("fetching hostdata from %q: %w", i.hostdataURL, err) |
| 55 | + } |
| 56 | + defer resp.Body.Close() |
| 57 | + if resp.StatusCode != http.StatusOK { |
| 58 | + return nil, fmt.Errorf("fetching hostdata: status %s", resp.Status) |
| 59 | + } |
| 60 | + hostData, err := io.ReadAll(resp.Body) |
| 61 | + if err != nil { |
| 62 | + return nil, fmt.Errorf("reading hostdata response: %w", err) |
| 63 | + } |
| 64 | + return json.Marshal(attestationDoc{ |
| 65 | + ReportData: reportData[:], |
| 66 | + HostData: hostData, |
| 67 | + }) |
| 68 | +} |
| 69 | + |
| 70 | +// attestationDoc is the fake attestation document exchanged between issuer and validator. |
| 71 | +type attestationDoc struct { |
| 72 | + ReportData []byte `json:"reportData"` |
| 73 | + HostData []byte `json:"hostData"` |
| 74 | +} |
0 commit comments