Skip to content

Commit 3ec63a9

Browse files
committed
send SPT attestation to GCA
1 parent c9fbf6f commit 3ec63a9

File tree

5 files changed

+229
-0
lines changed

5 files changed

+229
-0
lines changed

launcher/agent/agent.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,10 @@ func (a *agent) AttestWithClient(ctx context.Context, opts AttestAgentOpts, clie
268268
v.AkCert = a.fetchedAK.CertDERBytes()
269269

270270
req.TDCCELAttestation = v
271+
// Override the attached Nvidia GPU attestation as nil if the experiment flag is OFF.
272+
if !a.launchSpec.Experiments.EnableAttestationEvidence {
273+
req.TDCCELAttestation.NvidiaAttestation = nil
274+
}
271275
default:
272276
return nil, fmt.Errorf("received an unsupported attestation type! %v", v)
273277
}

launcher/internal/experiments/experiments.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type Experiments struct {
1919
EnableB200DriverInstallation bool
2020
EnableH100DriverInstallation bool
2121
EnableKeyManager bool
22+
EnableGpuGcaSupport bool
2223
}
2324

2425
// New takes a filepath, opens the file, and calls ReadJsonInput with the contents

launcher/internal/experiments/experiments_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ func TestExperiments(t *testing.T) {
1919
EnableB200DriverInstallation: true,
2020
EnableH100DriverInstallation: true,
2121
EnableKeyManager: false,
22+
EnableGpuGcaSupport: false,
2223
},
2324
},
2425
{
2526
input: "{\"EnableB200DriverInstallation\":true}",
2627
expectedExps: Experiments{
2728
EnableB200DriverInstallation: true,
2829
EnableKeyManager: false,
30+
EnableGpuGcaSupport: false,
2931
},
3032
},
3133
{
@@ -34,13 +36,26 @@ func TestExperiments(t *testing.T) {
3436
EnableTestFeatureForImage: true,
3537
EnableItaVerifier: true,
3638
EnableVerifyCS: true,
39+
EnableGpuGcaSupport: false,
3740
},
3841
},
3942
{
4043
input: "{\"EnableB200DriverInstallation\":true,\"EnableKeyManager\":true}",
4144
expectedExps: Experiments{
4245
EnableB200DriverInstallation: true,
4346
EnableKeyManager: true,
47+
EnableGpuGcaSupport: false,
48+
},
49+
},
50+
{
51+
input: "{\"EnableGpuGcaSupport\":true,\"EnableH100DriverInstallation\":true,\"EnableB200DriverInstallation\":false,\"EnableTestFeatureForImage\":true,\"EnableItaVerifier\":true,\"EnableKeyManager\":false}",
52+
expectedExps: Experiments{
53+
EnableTestFeatureForImage: true,
54+
EnableItaVerifier: true,
55+
EnableB200DriverInstallation: false,
56+
EnableH100DriverInstallation: true,
57+
EnableKeyManager: false,
58+
EnableGpuGcaSupport: true,
4459
},
4560
},
4661
}

verifier/rest/rest.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818

1919
v1 "cloud.google.com/go/confidentialcomputing/apiv1"
2020
ccpb "cloud.google.com/go/confidentialcomputing/apiv1/confidentialcomputingpb"
21+
attestationpb "github.com/GoogleCloudPlatform/confidential-space/server/proto/gen/attestation"
2122
"google.golang.org/api/iterator"
2223
"google.golang.org/api/option"
2324
locationpb "google.golang.org/genproto/googleapis/cloud/location"
@@ -370,6 +371,8 @@ func convertCSRequestToREST(request verifier.VerifyAttestationRequest) *ccpb.Ver
370371
AkCert: verifyAttRequest.TpmAttestation.AkCert,
371372
AkCertChain: verifyAttRequest.TpmAttestation.CertChain,
372373
}
374+
375+
csReq.NvidiaAttestation = convertNvidiaAttestationToREST(request.TDCCELAttestation.NvidiaAttestation)
373376
} else { // TPM Attestation.
374377
csReq.TeeAttestation = &ccpb.VerifyConfidentialSpaceRequest_TpmAttestation{
375378
TpmAttestation: verifyAttRequest.TpmAttestation,
@@ -381,6 +384,38 @@ func convertCSRequestToREST(request verifier.VerifyAttestationRequest) *ccpb.Ver
381384
return csReq
382385
}
383386

387+
func convertNvidiaAttestationToREST(nvAtt *attestationpb.NvidiaAttestationReport) *ccpb.NvidiaAttestation {
388+
// GCA only supports SPT attestation.
389+
if nvAtt.GetSpt() != nil {
390+
return &ccpb.NvidiaAttestation{
391+
CcFeature: &ccpb.NvidiaAttestation_Spt{
392+
Spt: &ccpb.NvidiaAttestation_SinglePassthroughAttestation{
393+
GpuQuote: &ccpb.NvidiaAttestation_GpuInfo{
394+
Uuid: nvAtt.GetSpt().GetGpuQuote().GetUuid(),
395+
DriverVersion: nvAtt.GetSpt().GetGpuQuote().GetDriverVersion(),
396+
VbiosVersion: nvAtt.GetSpt().GetGpuQuote().GetVbiosVersion(),
397+
GpuArchitectureType: convertGPUArchToREST(nvAtt.GetSpt().GetGpuQuote().GetGpuArchitectureType()),
398+
AttestationCertificateChain: nvAtt.GetSpt().GetGpuQuote().GetAttestationCertificateChain(),
399+
AttestationReport: nvAtt.GetSpt().GetGpuQuote().GetAttestationReport(),
400+
},
401+
},
402+
},
403+
}
404+
}
405+
return nil
406+
}
407+
408+
func convertGPUArchToREST(arch attestationpb.GpuArchitectureType) ccpb.NvidiaAttestation_GpuArchitectureType {
409+
switch arch {
410+
case attestationpb.GpuArchitectureType_GPU_ARCHITECTURE_TYPE_HOPPER:
411+
return ccpb.NvidiaAttestation_GPU_ARCHITECTURE_TYPE_HOPPER
412+
case attestationpb.GpuArchitectureType_GPU_ARCHITECTURE_TYPE_BLACKWELL:
413+
return ccpb.NvidiaAttestation_GPU_ARCHITECTURE_TYPE_BLACKWELL
414+
default:
415+
return ccpb.NvidiaAttestation_GPU_ARCHITECTURE_TYPE_UNSPECIFIED
416+
}
417+
}
418+
384419
func convertToCSOpts(tokenOpts *ccpb.TokenOptions) *ccpb.VerifyConfidentialSpaceRequest_ConfidentialSpaceOptions {
385420
if tokenOpts == nil {
386421
return &ccpb.VerifyConfidentialSpaceRequest_ConfidentialSpaceOptions{

verifier/rest/rest_test.go

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ import (
1111
"github.com/google/uuid"
1212
"google.golang.org/genproto/googleapis/rpc/status"
1313
"google.golang.org/protobuf/encoding/prototext"
14+
"google.golang.org/protobuf/proto"
1415
"google.golang.org/protobuf/testing/protocmp"
1516

1617
ccpb "cloud.google.com/go/confidentialcomputing/apiv1/confidentialcomputingpb"
18+
attestationpb "github.com/GoogleCloudPlatform/confidential-space/server/proto/gen/attestation"
1719
sabi "github.com/google/go-sev-guest/abi"
1820
spb "github.com/google/go-sev-guest/proto/sevsnp"
1921
tabi "github.com/google/go-tdx-guest/abi"
@@ -382,6 +384,115 @@ func TestConvertTokenOptionsToREST(t *testing.T) {
382384
}
383385
}
384386

387+
func TestConvertNvidiaAttestationToREST(t *testing.T) {
388+
testcases := []struct {
389+
name string
390+
nvAtt *attestationpb.NvidiaAttestationReport
391+
want *ccpb.NvidiaAttestation
392+
}{
393+
{
394+
name: "nil attestation",
395+
nvAtt: nil,
396+
want: nil,
397+
},
398+
{
399+
name: "empty attestation",
400+
nvAtt: &attestationpb.NvidiaAttestationReport{},
401+
want: nil,
402+
},
403+
{
404+
name: "SPT attestation",
405+
nvAtt: &attestationpb.NvidiaAttestationReport{
406+
CcFeature: &attestationpb.NvidiaAttestationReport_Spt{
407+
Spt: &attestationpb.NvidiaAttestationReport_SinglePassthroughAttestation{
408+
GpuQuote: &attestationpb.GpuInfo{
409+
Uuid: "test-uuid",
410+
DriverVersion: "test-driver",
411+
VbiosVersion: "test-vbios",
412+
GpuArchitectureType: attestationpb.GpuArchitectureType_GPU_ARCHITECTURE_TYPE_HOPPER,
413+
AttestationCertificateChain: []byte("test-cert-chain"),
414+
AttestationReport: []byte("test-report"),
415+
},
416+
},
417+
},
418+
},
419+
want: &ccpb.NvidiaAttestation{
420+
CcFeature: &ccpb.NvidiaAttestation_Spt{
421+
Spt: &ccpb.NvidiaAttestation_SinglePassthroughAttestation{
422+
GpuQuote: &ccpb.NvidiaAttestation_GpuInfo{
423+
Uuid: "test-uuid",
424+
DriverVersion: "test-driver",
425+
VbiosVersion: "test-vbios",
426+
GpuArchitectureType: ccpb.NvidiaAttestation_GPU_ARCHITECTURE_TYPE_HOPPER,
427+
AttestationCertificateChain: []byte("test-cert-chain"),
428+
AttestationReport: []byte("test-report"),
429+
},
430+
},
431+
},
432+
},
433+
},
434+
{
435+
name: "MPT attestation",
436+
nvAtt: &attestationpb.NvidiaAttestationReport{
437+
CcFeature: &attestationpb.NvidiaAttestationReport_Mpt{
438+
Mpt: &attestationpb.NvidiaAttestationReport_MultiGpuSecurePassthroughAttestation{
439+
GpuQuotes: []*attestationpb.GpuInfo{
440+
{
441+
Uuid: "test-uuid",
442+
DriverVersion: "test-driver",
443+
VbiosVersion: "test-vbios",
444+
GpuArchitectureType: attestationpb.GpuArchitectureType_GPU_ARCHITECTURE_TYPE_HOPPER,
445+
AttestationCertificateChain: []byte("test-cert-chain"),
446+
AttestationReport: []byte("test-report"),
447+
},
448+
},
449+
},
450+
},
451+
},
452+
want: nil,
453+
},
454+
}
455+
456+
for _, tc := range testcases {
457+
t.Run(tc.name, func(t *testing.T) {
458+
got := convertNvidiaAttestationToREST(tc.nvAtt)
459+
if !proto.Equal(got, tc.want) {
460+
t.Errorf("convertNvidiaAttestationToREST(%v) = %v, want %v", tc.nvAtt, got, tc.want)
461+
}
462+
})
463+
}
464+
}
465+
466+
func TestConvertGPUArchToREST(t *testing.T) {
467+
testcases := []struct {
468+
name string
469+
arch attestationpb.GpuArchitectureType
470+
want ccpb.NvidiaAttestation_GpuArchitectureType
471+
}{
472+
{
473+
name: "Hopper",
474+
arch: attestationpb.GpuArchitectureType_GPU_ARCHITECTURE_TYPE_HOPPER,
475+
want: ccpb.NvidiaAttestation_GPU_ARCHITECTURE_TYPE_HOPPER,
476+
},
477+
{
478+
name: "Blackwell",
479+
arch: attestationpb.GpuArchitectureType_GPU_ARCHITECTURE_TYPE_BLACKWELL,
480+
want: ccpb.NvidiaAttestation_GPU_ARCHITECTURE_TYPE_BLACKWELL,
481+
},
482+
{
483+
name: "Unspecified",
484+
arch: attestationpb.GpuArchitectureType_GPU_ARCHITECTURE_TYPE_UNSPECIFIED,
485+
want: ccpb.NvidiaAttestation_GPU_ARCHITECTURE_TYPE_UNSPECIFIED,
486+
},
487+
}
488+
for _, tc := range testcases {
489+
t.Run(tc.name, func(t *testing.T) {
490+
if got := convertGPUArchToREST(tc.arch); got != tc.want {
491+
t.Errorf("convertGPUArchToREST() = %v, want %v", got, tc.want)
492+
}
493+
})
494+
}
495+
}
385496
func TestConvertTokenOptionsToCSOptions(t *testing.T) {
386497
testcases := []struct {
387498
name string
@@ -571,6 +682,66 @@ func TestConvertCSRequestToREST(t *testing.T) {
571682
SignedEntities: []*ccpb.SignedEntity{{ContainerImageSignatures: []*ccpb.ContainerImageSignature{}}},
572683
},
573684
},
685+
{
686+
name: "TDCCEL Attestation + Nvidia Attestation",
687+
verifierReq: verifier.VerifyAttestationRequest{
688+
TDCCELAttestation: &verifier.TDCCELAttestation{
689+
TdQuote: []byte("test td quote"),
690+
CcelAcpiTable: []byte("test CCEL table"),
691+
CcelData: []byte("test CCEL data"),
692+
CanonicalEventLog: []byte("test CEL"),
693+
AkCert: []byte("test-ak-cert"),
694+
IntermediateCerts: [][]byte{[]byte("chain-1"), []byte("chain-2")},
695+
NvidiaAttestation: &attestationpb.NvidiaAttestationReport{
696+
CcFeature: &attestationpb.NvidiaAttestationReport_Spt{
697+
Spt: &attestationpb.NvidiaAttestationReport_SinglePassthroughAttestation{
698+
GpuQuote: &attestationpb.GpuInfo{
699+
Uuid: "test-uuid",
700+
DriverVersion: "test-driver",
701+
VbiosVersion: "test-vbios",
702+
GpuArchitectureType: attestationpb.GpuArchitectureType_GPU_ARCHITECTURE_TYPE_HOPPER,
703+
AttestationCertificateChain: []byte("test-cert-chain"),
704+
AttestationReport: []byte("test-report"),
705+
},
706+
},
707+
},
708+
},
709+
},
710+
},
711+
expectedReq: &ccpb.VerifyConfidentialSpaceRequest{
712+
TeeAttestation: &ccpb.VerifyConfidentialSpaceRequest_TdCcel{
713+
TdCcel: &ccpb.TdxCcelAttestation{
714+
TdQuote: []byte("test td quote"),
715+
CcelAcpiTable: []byte("test CCEL table"),
716+
CcelData: []byte("test CCEL data"),
717+
CanonicalEventLog: []byte("test CEL"),
718+
},
719+
},
720+
NvidiaAttestation: &ccpb.NvidiaAttestation{
721+
CcFeature: &ccpb.NvidiaAttestation_Spt{
722+
Spt: &ccpb.NvidiaAttestation_SinglePassthroughAttestation{
723+
GpuQuote: &ccpb.NvidiaAttestation_GpuInfo{
724+
Uuid: "test-uuid",
725+
DriverVersion: "test-driver",
726+
VbiosVersion: "test-vbios",
727+
GpuArchitectureType: ccpb.NvidiaAttestation_GPU_ARCHITECTURE_TYPE_HOPPER,
728+
AttestationCertificateChain: []byte("test-cert-chain"),
729+
AttestationReport: []byte("test-report"),
730+
},
731+
},
732+
},
733+
},
734+
GceShieldedIdentity: &ccpb.GceShieldedIdentity{
735+
AkCert: []byte("test-ak-cert"),
736+
AkCertChain: [][]byte{[]byte("chain-1"), []byte("chain-2")},
737+
},
738+
Options: &ccpb.VerifyConfidentialSpaceRequest_ConfidentialSpaceOptions{
739+
TokenProfile: ccpb.TokenProfile_TOKEN_PROFILE_DEFAULT_EAT,
740+
},
741+
GcpCredentials: &ccpb.GcpCredentials{ServiceAccountIdTokens: []string{}},
742+
SignedEntities: []*ccpb.SignedEntity{{ContainerImageSignatures: []*ccpb.ContainerImageSignature{}}},
743+
},
744+
},
574745
}
575746

576747
cmpOpts := append(
@@ -584,6 +755,9 @@ func TestConvertCSRequestToREST(t *testing.T) {
584755
cmpopts.IgnoreUnexported(ccpb.VerifyConfidentialSpaceRequest_ConfidentialSpaceOptions{}),
585756
cmpopts.IgnoreUnexported(ccpb.ContainerImageSignature{}),
586757
cmpopts.IgnoreUnexported(ccpb.SignedEntity{}),
758+
cmpopts.IgnoreUnexported(ccpb.NvidiaAttestation{}),
759+
cmpopts.IgnoreUnexported(ccpb.NvidiaAttestation_SinglePassthroughAttestation{}),
760+
cmpopts.IgnoreUnexported(ccpb.NvidiaAttestation_GpuInfo{}),
587761
)
588762

589763
for _, tc := range testcases {

0 commit comments

Comments
 (0)