mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-06-23 04:10:25 +00:00
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
* 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 commitd81d67e73d. * Revert "Bug" This reverts commit5e566d53c1. * Revert "Possible bug" This reverts commit47d13fe583. * Revert "Possible IGVM script bug" This reverts commit3fb1b79537. * Revert "changed attestion-service.service so it knows where the helper is" This reverts commitf9f11ed183. * Revert "Added command for installing all services" This reverts commit5dcf7a5c0a. * 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 commitd81d67e73d. * Revert "Bug" This reverts commit5e566d53c1. * Revert "Possible bug" This reverts commit47d13fe583. * Revert "Possible IGVM script bug" This reverts commit3fb1b79537. * Revert "changed attestion-service.service so it knows where the helper is" This reverts commitf9f11ed183. * Revert "Added command for installing all services" This reverts commit5dcf7a5c0a. * 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 commitd81d67e73d. * Revert "Bug" This reverts commit5e566d53c1. * Revert "Possible bug" This reverts commit47d13fe583. * Revert "Possible IGVM script bug" This reverts commit3fb1b79537. * Revert "changed attestion-service.service so it knows where the helper is" This reverts commitf9f11ed183. * Revert "Added command for installing all services" This reverts commit5dcf7a5c0a. * 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 commitd81d67e73d. * Revert "Bug" This reverts commit5e566d53c1. * Revert "Possible bug" This reverts commit47d13fe583. * Revert "Possible IGVM script bug" This reverts commit3fb1b79537. * Revert "changed attestion-service.service so it knows where the helper is" This reverts commitf9f11ed183. * Revert "Added command for installing all services" This reverts commit5dcf7a5c0a. * 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>
169 lines
4.8 KiB
Go
169 lines
4.8 KiB
Go
// Copyright (c) Ultraviolet
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package atls
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
eaattestation "github.com/ultravioletrs/cocos/pkg/atls/eaattestation"
|
|
cocosattestation "github.com/ultravioletrs/cocos/pkg/attestation"
|
|
"github.com/ultravioletrs/cocos/pkg/attestation/azure"
|
|
"github.com/ultravioletrs/cocos/pkg/attestation/eat"
|
|
"github.com/ultravioletrs/cocos/pkg/attestation/gpu"
|
|
"github.com/ultravioletrs/cocos/pkg/attestation/tdx"
|
|
"github.com/ultravioletrs/cocos/pkg/attestation/vtpm"
|
|
"github.com/veraison/corim/corim"
|
|
)
|
|
|
|
type policyEvidenceVerifier struct {
|
|
policyPath string
|
|
loadManifest func(string) (*corim.UnsignedCorim, error)
|
|
rootVerifier func(cocosattestation.PlatformType) (cocosattestation.Verifier, error)
|
|
newGPUVerifier func() (cocosattestation.Verifier, error)
|
|
}
|
|
|
|
func NewEvidenceVerifier(policyPath string) eaattestation.EvidenceVerifier {
|
|
return &policyEvidenceVerifier{
|
|
policyPath: policyPath,
|
|
loadManifest: loadCoRIM,
|
|
rootVerifier: platformVerifier,
|
|
newGPUVerifier: defaultGPUVerifier,
|
|
}
|
|
}
|
|
|
|
func (v *policyEvidenceVerifier) VerifyEvidence(evidence []byte) error {
|
|
if v.policyPath == "" {
|
|
return fmt.Errorf("atls: attestation policy path is not set")
|
|
}
|
|
claims, err := eat.DecodeCBOR(evidence, nil)
|
|
if err != nil {
|
|
return fmt.Errorf("atls: failed to decode EAT evidence: %w", err)
|
|
}
|
|
manifest, err := v.loadManifest(v.policyPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
verifier, err := v.rootVerifier(platformTypeFromClaims(claims.PlatformType))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := verifier.VerifyWithCoRIM(claims.RawReport, manifest); err != nil {
|
|
return err
|
|
}
|
|
|
|
if claims.GPUExtensions != nil {
|
|
if err := v.verifyGPUEvidence(claims, manifest); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func loadCoRIM(path string) (*corim.UnsignedCorim, error) {
|
|
corimBytes, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("atls: failed to read CoRIM file: %w", err)
|
|
}
|
|
|
|
var sc corim.SignedCorim
|
|
if err := sc.FromCOSE(corimBytes); err == nil {
|
|
return &sc.UnsignedCorim, nil
|
|
}
|
|
|
|
var uc corim.UnsignedCorim
|
|
if err := uc.FromCBOR(corimBytes); err != nil {
|
|
return nil, fmt.Errorf("atls: failed to parse CoRIM: %w", err)
|
|
}
|
|
return &uc, nil
|
|
}
|
|
|
|
func platformTypeFromClaims(name string) cocosattestation.PlatformType {
|
|
switch name {
|
|
case "SNP":
|
|
return cocosattestation.SNP
|
|
case "TDX":
|
|
return cocosattestation.TDX
|
|
case "vTPM":
|
|
return cocosattestation.VTPM
|
|
case "SNP-vTPM":
|
|
return cocosattestation.SNPvTPM
|
|
case "Azure":
|
|
return cocosattestation.Azure
|
|
default:
|
|
return cocosattestation.NoCC
|
|
}
|
|
}
|
|
|
|
func platformVerifier(platformType cocosattestation.PlatformType) (cocosattestation.Verifier, error) {
|
|
switch platformType {
|
|
case cocosattestation.SNP, cocosattestation.SNPvTPM, cocosattestation.VTPM:
|
|
return vtpm.NewVerifier(nil), nil
|
|
case cocosattestation.Azure:
|
|
return azure.NewVerifier(nil), nil
|
|
case cocosattestation.TDX:
|
|
return tdx.NewVerifier(), nil
|
|
default:
|
|
return nil, fmt.Errorf("atls: unsupported platform type: %d", platformType)
|
|
}
|
|
}
|
|
|
|
func defaultGPUVerifier() (cocosattestation.Verifier, error) {
|
|
timeout := 30 * time.Second
|
|
if rawTimeout := os.Getenv("ATLS_GPU_VERIFIER_TIMEOUT"); rawTimeout != "" {
|
|
parsed, err := time.ParseDuration(rawTimeout)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("atls: invalid ATLS_GPU_VERIFIER_TIMEOUT: %w", err)
|
|
}
|
|
timeout = parsed
|
|
}
|
|
|
|
binaryPath := os.Getenv("ATLS_GPU_VERIFIER_PATH")
|
|
if binaryPath == "" {
|
|
binaryPath = os.Getenv("ATTESTATION_GPU_HELPER_PATH")
|
|
}
|
|
|
|
return gpu.NewVerifier(binaryPath, timeout)
|
|
}
|
|
|
|
func (v *policyEvidenceVerifier) verifyGPUEvidence(claims *eat.EATClaims, manifest *corim.UnsignedCorim) error {
|
|
if len(claims.GPUExtensions.EvidenceJSON) == 0 {
|
|
return fmt.Errorf("atls: gpu evidence is empty")
|
|
}
|
|
|
|
expectedNonce := sha256.Sum256(append(append([]byte(nil), claims.Nonce...), []byte(":gpu")...))
|
|
if !bytes.Equal(claims.GPUExtensions.Nonce, expectedNonce[:]) {
|
|
return fmt.Errorf("atls: gpu nonce binding mismatch")
|
|
}
|
|
|
|
// Guard against replay: a stale self-consistent EvidenceJSON blob can be
|
|
// paired with a rewritten outer Nonce unless the inner nonce is also checked.
|
|
var envelopes []struct {
|
|
Nonce string `json:"nonce"`
|
|
}
|
|
if err := json.Unmarshal(claims.GPUExtensions.EvidenceJSON, &envelopes); err != nil {
|
|
return fmt.Errorf("atls: failed to parse GPU evidence JSON: %w", err)
|
|
}
|
|
if len(envelopes) == 0 || strings.TrimSpace(envelopes[0].Nonce) == "" {
|
|
return fmt.Errorf("atls: GPU evidence JSON missing nonce")
|
|
}
|
|
if envelopes[0].Nonce != hex.EncodeToString(expectedNonce[:]) {
|
|
return fmt.Errorf("atls: gpu evidence nonce mismatch")
|
|
}
|
|
|
|
verifier, err := v.newGPUVerifier()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return verifier.VerifyWithCoRIM(claims.GPUExtensions.EvidenceJSON, manifest)
|
|
}
|