Files
cocos/pkg/attestation/eat/eat.go
T
Jovan Djukic 27db9b29eb
CI / lint (push) Has been cancelled
CI / test (agent) (push) Has been cancelled
CI / test (cli) (push) Has been cancelled
CI / test (cmd) (push) Has been cancelled
CI / test (internal) (push) Has been cancelled
CI / test (manager, true) (push) Has been cancelled
CI / test (pkg) (push) Has been cancelled
CI / upload-coverage (push) Has been cancelled
COCOS-591: Add support for GPU CC attestation (#592)
* Added GPU evidence collection

* Added GPU evidence verification

* Added make command for nvattest helper

* Added command for installing all services

* changed attestion-service.service so it knows where the helper is

* Possible IGVM script bug

* Possible bug

* Bug

* bug

* Revert "bug"

This reverts commit d81d67e73d.

* Revert "Bug"

This reverts commit 5e566d53c1.

* Revert "Possible bug"

This reverts commit 47d13fe583.

* Revert "Possible IGVM script bug"

This reverts commit 3fb1b79537.

* Revert "changed attestion-service.service so it knows where the helper is"

This reverts commit f9f11ed183.

* Revert "Added command for installing all services"

This reverts commit 5dcf7a5c0a.

* NOISSUE - Enforce binding label check (#589)

* NOISSUE - Implement extensible resource downloader framework with support for S3, GCS, and OCI sources (#590)

* feat: implement extensible resource downloader framework with support for S3, GCS, and OCI sources

Signed-off-by: SammyOina <sammyoina@gmail.com>

* refactor: improve resource URL parsing and add support for bare OCI image references

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* fix: add empty string check and slash requirement for OCI image inference, and update python unit tests with event mock expectations

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* refactor: introduce OCIClient interface, add test coverage for decryption, and improve resource download error handling

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* chore: remove trailing whitespace in OCI downloader and HTTP tests

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

---------

Signed-off-by: SammyOina <sammyoina@gmail.com>
Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* Refactored baed on comments

* Added GPU evidence collection

* Added GPU evidence verification

* Added make command for nvattest helper

* Added command for installing all services

* changed attestion-service.service so it knows where the helper is

* Possible IGVM script bug

* Possible bug

* Bug

* bug

* Revert "bug"

This reverts commit d81d67e73d.

* Revert "Bug"

This reverts commit 5e566d53c1.

* Revert "Possible bug"

This reverts commit 47d13fe583.

* Revert "Possible IGVM script bug"

This reverts commit 3fb1b79537.

* Revert "changed attestion-service.service so it knows where the helper is"

This reverts commit f9f11ed183.

* Revert "Added command for installing all services"

This reverts commit 5dcf7a5c0a.

* Refactored baed on comments

* fixed lint error

* fixed tests

* Fixed according to comments

* COCOS-584 - Support multiple kbs (#587)

* feat: Implement per-resource KBS configuration, allowing algorithms and datasets to specify individual KBS URLs.

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* refactor: Encapsulate CLI error handling and CVM certificate paths within the CLI struct, and add algorithm type to agent's algorithm structure.

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* style: Remove blank lines and fix indentation in CLI commands.

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* refactor: Update downloadAndDecryptGenericResource to accept KBS URL as a parameter and adjust related tests

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* refactor: group CLI configuration into structured types and simplify skopeo decryption key handling

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

---------

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* Added GPU evidence collection

* Added GPU evidence verification

* Added make command for nvattest helper

* Added command for installing all services

* changed attestion-service.service so it knows where the helper is

* Possible IGVM script bug

* Possible bug

* Bug

* bug

* Revert "bug"

This reverts commit d81d67e73d.

* Revert "Bug"

This reverts commit 5e566d53c1.

* Revert "Possible bug"

This reverts commit 47d13fe583.

* Revert "Possible IGVM script bug"

This reverts commit 3fb1b79537.

* Revert "changed attestion-service.service so it knows where the helper is"

This reverts commit f9f11ed183.

* Revert "Added command for installing all services"

This reverts commit 5dcf7a5c0a.

* Refactored baed on comments

* Added GPU evidence collection

* Added GPU evidence verification

* Added make command for nvattest helper

* Added command for installing all services

* changed attestion-service.service so it knows where the helper is

* Possible IGVM script bug

* Possible bug

* Bug

* bug

* Revert "bug"

This reverts commit d81d67e73d.

* Revert "Bug"

This reverts commit 5e566d53c1.

* Revert "Possible bug"

This reverts commit 47d13fe583.

* Revert "Possible IGVM script bug"

This reverts commit 3fb1b79537.

* Revert "changed attestion-service.service so it knows where the helper is"

This reverts commit f9f11ed183.

* Revert "Added command for installing all services"

This reverts commit 5dcf7a5c0a.

* Refactored baed on comments

* fixed lint error

* fixed tests

* Fixed according to comments

---------

Signed-off-by: SammyOina <sammyoina@gmail.com>
Signed-off-by: Sammy Oina <sammyoina@gmail.com>
Co-authored-by: Danko Miladinovic <72250944+danko-miladinovic@users.noreply.github.com>
Co-authored-by: Sammy Kerata Oina <44265300+SammyOina@users.noreply.github.com>
2026-05-08 16:35:04 +02:00

227 lines
8.6 KiB
Go

// Copyright (c) Ultraviolet
// SPDX-License-Identifier: Apache-2.0
package eat
import (
"errors"
"github.com/ultravioletrs/cocos/pkg/attestation"
)
// EATClaims represents the Entity Attestation Token claims following RFC 9711.
type EATClaims struct {
// Standard JWT/CWT claims
Issuer string `json:"iss,omitempty" cbor:"1,keyasint,omitempty"`
Subject string `json:"sub,omitempty" cbor:"2,keyasint,omitempty"`
IssuedAt int64 `json:"iat,omitempty" cbor:"6,keyasint,omitempty"`
ExpiresAt int64 `json:"exp,omitempty" cbor:"4,keyasint,omitempty"`
// Core EAT claims (RFC 9711)
Nonce []byte `json:"eat_nonce" cbor:"10,keyasint"` // Freshness/replay protection
UEID []byte `json:"ueid" cbor:"256,keyasint"` // Universal Entity ID
OEMID int `json:"oemid,omitempty" cbor:"258,keyasint,omitempty"` // Hardware OEM ID
HWModel []byte `json:"hwmodel,omitempty" cbor:"259,keyasint,omitempty"` // Hardware model
HWVersion string `json:"hwversion,omitempty" cbor:"260,keyasint,omitempty"` // Hardware version
SWName string `json:"swname,omitempty" cbor:"270,keyasint,omitempty"` // Software name
SWVersion string `json:"swversion,omitempty" cbor:"271,keyasint,omitempty"` // Software version
DebugStatus int `json:"dbgstat" cbor:"263,keyasint"` // Debug status
IntUse int `json:"intuse,omitempty" cbor:"262,keyasint,omitempty"` // Intended use
Measurements []byte `json:"measurements" cbor:"265,keyasint"` // Software measurements
// Platform type indicator
PlatformType string `json:"platform_type"`
// Submodules for vTPM and other components
Submods map[string]interface{} `json:"submods,omitempty" cbor:"266,keyasint,omitempty"`
// Platform-specific extensions (custom claims)
SNPExtensions *SNPExtensions `json:"x-cocos-sevsnp,omitempty"`
TDXExtensions *TDXExtensions `json:"x-cocos-tdx,omitempty"`
VTPMExtensions *VTPMExtensions `json:"x-cocos-vtpm,omitempty"`
GPUExtensions *GPUExtensions `json:"x-cocos-gpu,omitempty"`
// Original binary report (for verification)
RawReport []byte `json:"raw_report,omitempty"`
}
// SNPExtensions contains AMD SEV-SNP specific claims.
type SNPExtensions struct {
Measurement []byte `json:"measurement"` // SNP MEASUREMENT field
TCB string `json:"tcb"` // TCB version info
PlatformInfo uint64 `json:"platform_info"` // PLATFORM_INFO
Policy uint64 `json:"policy"` // POLICY field
FamilyID []byte `json:"family_id,omitempty"` // Family ID
ImageID []byte `json:"image_id,omitempty"` // Image ID
VMPL int `json:"vmpl,omitempty"` // VM Privilege Level
SignatureAlgo int `json:"signature_algo,omitempty"` // Signature algorithm
CurrentTCB uint64 `json:"current_tcb,omitempty"` // Current TCB
ReportedTCB uint64 `json:"reported_tcb,omitempty"` // Reported TCB
ChipID []byte `json:"chip_id,omitempty"` // Chip ID
CommittedTCB uint64 `json:"committed_tcb,omitempty"` // Committed TCB
LaunchTCB uint64 `json:"launch_tcb,omitempty"` // Launch TCB
Signature []byte `json:"signature,omitempty"` // Signature
}
// TDXExtensions contains Intel TDX specific claims.
type TDXExtensions struct {
MRTD []byte `json:"tdx_mrtd"` // MRTD measurement
RTMR0 []byte `json:"tdx_rtmr0"` // Runtime measurement register 0
RTMR1 []byte `json:"tdx_rtmr1"` // Runtime measurement register 1
RTMR2 []byte `json:"tdx_rtmr2"` // Runtime measurement register 2
RTMR3 []byte `json:"tdx_rtmr3"` // Runtime measurement register 3
XFAM uint64 `json:"tdx_xfam"` // Extended features available mask
TDAttributes uint64 `json:"tdx_td_attributes"` // TD attributes
MRConfigID []byte `json:"tdx_mrconfigid,omitempty"` // MR Config ID
MROwner []byte `json:"tdx_mrowner,omitempty"` // MR Owner
MROwnerConfig []byte `json:"tdx_mrownerconfig,omitempty"` // MR Owner Config
MRSEAM []byte `json:"tdx_mrseam,omitempty"` // MR SEAM
TDXModule *TDXModuleInfo `json:"tdx_module,omitempty"` // TDX module info
Signature []byte `json:"tdx_signature,omitempty"` // Quote Signature
}
// TDXModuleInfo contains TDX module version information.
type TDXModuleInfo struct {
Major uint8 `json:"major"`
Minor uint8 `json:"minor"`
BuildNum uint16 `json:"build_num"`
BuildDate uint32 `json:"build_date"`
}
// VTPMExtensions contains vTPM specific claims.
type VTPMExtensions struct {
PCRs map[string]string `json:"pcrs"` // PCR values (SHA256/SHA384)
EventLog []byte `json:"event_log,omitempty"` // Event log
Quote []byte `json:"quote,omitempty"` // TPM quote
}
// GPUExtensions contains optional GPU attestation evidence that is bound to the
// same attestation session as the root TEE evidence.
type GPUExtensions struct {
Vendor string `json:"vendor,omitempty" cbor:"vendor,omitempty"`
EvidenceFormat string `json:"evidence_format,omitempty" cbor:"evidence_format,omitempty"`
Nonce []byte `json:"nonce,omitempty" cbor:"nonce,omitempty"`
EvidenceJSON []byte `json:"evidence_json,omitempty" cbor:"evidence_json,omitempty"`
}
// ClaimsOption customizes EAT claims after the root platform claims are
// extracted.
type ClaimsOption func(*EATClaims) error
// WithGPU attaches GPU evidence both as a typed extension and as an EAT submod.
func WithGPU(gpu *GPUExtensions) ClaimsOption {
return func(claims *EATClaims) error {
if gpu == nil {
return nil
}
claims.GPUExtensions = gpu
if claims.Submods == nil {
claims.Submods = map[string]interface{}{}
}
claims.Submods["gpu"] = gpu
return nil
}
}
// DebugStatus constants (RFC 9711 Section 4.2.6).
const (
DebugEnabled = 0 // Debug is enabled
DebugDisabled = 1 // Debug is disabled
DebugDisabledSinceBoot = 2 // Debug is disabled since boot
DebugPermanentDisable = 3 // Debug is permanently disabled
DebugFullPermanentDisable = 4 // Debug is fully and permanently disabled
)
// IntUse constants (RFC 9711 Section 4.2.5).
const (
IntUseGenericFresh = 1 // General purpose, fresh token
)
// MinNonceLength defines the minimum length for EAT nonce in bytes.
const MinNonceLength = 8
// NewEATClaims creates EAT claims from binary attestation report.
func NewEATClaims(report []byte, nonce []byte, platformType attestation.PlatformType, opts ...ClaimsOption) (*EATClaims, error) {
if len(nonce) < MinNonceLength {
return nil, errors.New("eat_nonce must be at least 8 bytes long")
}
claims := &EATClaims{
Nonce: nonce,
PlatformType: getPlatformTypeName(platformType),
RawReport: report,
DebugStatus: DebugDisabledSinceBoot, // Default to disabled since boot
IntUse: IntUseGenericFresh, // Default to general purpose, fresh token
}
// Extract platform-specific claims
if err := extractPlatformClaims(claims, report, platformType); err != nil {
return nil, err
}
for _, opt := range opts {
if opt == nil {
continue
}
if err := opt(claims); err != nil {
return nil, err
}
}
return claims, nil
}
// extractPlatformClaims extracts platform-specific claims from binary report.
func extractPlatformClaims(claims *EATClaims, report []byte, platformType attestation.PlatformType) error {
switch platformType {
case attestation.SNP, attestation.SNPvTPM:
return extractSNPClaims(claims, report)
case attestation.TDX:
return extractTDXClaims(claims, report)
case attestation.VTPM:
return extractVTPMClaims(claims, report)
case attestation.Azure:
return extractAzureClaims(claims, report)
default:
// For unknown platforms, just store the raw report
return nil
}
}
// getPlatformTypeName converts platform type to string name.
func getPlatformTypeName(platformType attestation.PlatformType) string {
switch platformType {
case attestation.SNP:
return "SNP"
case attestation.TDX:
return "TDX"
case attestation.VTPM:
return "vTPM"
case attestation.SNPvTPM:
return "SNP-vTPM"
case attestation.Azure:
return "Azure"
case attestation.NoCC:
return "NoCC"
default:
return "Unknown"
}
}
// Sanitize enforces dependency rules for claims.
// HWModel requires OEMID.
// HWVersion requires HWModel.
func (c *EATClaims) Sanitize() {
if c.OEMID == 0 {
c.HWModel = nil
c.HWVersion = ""
}
if len(c.HWModel) == 0 {
c.HWVersion = ""
}
if c.SWName == "" {
c.SWVersion = ""
}
}