@@ -58,7 +58,7 @@ func getAttestationKey(tpm io.ReadWriter) (*tpmclient.Key, error) {
58
58
// getInstanceInfo generates an extended SNP report, i.e. the report and any loaded certificates.
59
59
// Report generation is triggered by sending ioctl syscalls to the SNP guest device, the AMD PSP generates the report.
60
60
// The returned bytes will be written into the attestation document.
61
- func getInstanceInfo (_ context.Context , tpm io.ReadWriteCloser , extraData []byte ) ([]byte , error ) {
61
+ func getInstanceInfo (_ context.Context , _ io.ReadWriteCloser , extraData []byte ) ([]byte , error ) {
62
62
if len (extraData ) > 64 {
63
63
return nil , fmt .Errorf ("extra data too long: %d, should be 64 bytes at most" , len (extraData ))
64
64
}
@@ -76,7 +76,7 @@ func getInstanceInfo(_ context.Context, tpm io.ReadWriteCloser, extraData []byte
76
76
return nil , fmt .Errorf ("getting extended report: %w" , err )
77
77
}
78
78
79
- vcek , err := pemEncodedVCEK (certs )
79
+ vcek , certChain , err := pemEncodedVCEK (certs )
80
80
if err != nil {
81
81
return nil , fmt .Errorf ("parsing vcek: %w" , err )
82
82
}
@@ -89,6 +89,7 @@ func getInstanceInfo(_ context.Context, tpm io.ReadWriteCloser, extraData []byte
89
89
raw , err := json .Marshal (snp.InstanceInfo {
90
90
AttestationReport : report ,
91
91
ReportSigner : vcek ,
92
+ CertChain : certChain ,
92
93
GCP : gceInstanceInfo ,
93
94
})
94
95
if err != nil {
@@ -124,30 +125,44 @@ func gceInstanceInfo() (*attest.GCEInstanceInfo, error) {
124
125
}, nil
125
126
}
126
127
127
- // pemEncodedVCEK takes a marshalled SNP certificate table and returns the PEM-encoded VCEK certificate.
128
+ // preFetchCerts takes a marshalled SNP certificate table and returns the PEM-encoded VCEK certificate and,
129
+ // if present, the ASK of the SNP certificate chain.
128
130
// AMD documentation on certificate tables can be found in section 4.1.8.1, revision 2.03 "SEV-ES Guest-Hypervisor Communication Block Standardization".
129
131
// https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/56421.pdf
130
- func pemEncodedVCEK (certs []byte ) ([]byte , error ) {
132
+ func pemEncodedVCEK (certs []byte ) (vcekPEM []byte , certChain [] byte , err error ) {
131
133
certTable := abi.CertTable {}
132
134
if err := certTable .Unmarshal (certs ); err != nil {
133
- return nil , fmt .Errorf ("unmarshalling SNP certificate table: %w" , err )
135
+ return nil , nil , fmt .Errorf ("unmarshalling SNP certificate table: %w" , err )
134
136
}
135
137
136
138
vcekRaw , err := certTable .GetByGUIDString (abi .VcekGUID )
137
139
if err != nil {
138
- return nil , fmt .Errorf ("getting VCEK certificate: %w" , err )
140
+ return nil , nil , fmt .Errorf ("getting VCEK certificate: %w" , err )
139
141
}
140
142
141
143
// An optional check for certificate well-formedness. vcekRaw == cert.Raw.
142
- cert , err := x509 .ParseCertificate (vcekRaw )
144
+ vcek , err := x509 .ParseCertificate (vcekRaw )
143
145
if err != nil {
144
- return nil , fmt .Errorf ("parsing certificate: %w" , err )
146
+ return nil , nil , fmt .Errorf ("parsing certificate: %w" , err )
145
147
}
146
148
147
- certPEM : = pem .EncodeToMemory (& pem.Block {
149
+ vcekPEM = pem .EncodeToMemory (& pem.Block {
148
150
Type : "CERTIFICATE" ,
149
- Bytes : cert .Raw ,
151
+ Bytes : vcek .Raw ,
150
152
})
151
153
152
- return certPEM , nil
154
+ var askPEM []byte
155
+ if askRaw , err := certTable .GetByGUIDString (abi .AskGUID ); err == nil {
156
+ ask , err := x509 .ParseCertificate (askRaw )
157
+ if err != nil {
158
+ return nil , nil , fmt .Errorf ("parsing ASK certificate: %w" , err )
159
+ }
160
+
161
+ askPEM = pem .EncodeToMemory (& pem.Block {
162
+ Type : "CERTIFICATE" ,
163
+ Bytes : ask .Raw ,
164
+ })
165
+ }
166
+
167
+ return vcekPEM , askPEM , nil
153
168
}
0 commit comments