@@ -8,7 +8,8 @@ use std::error::Error;
8
8
9
9
use igvm:: snp_defs:: SevVmsa ;
10
10
use igvm:: { IgvmDirectiveHeader , IgvmFile } ;
11
- use igvm_defs:: { IgvmPageDataFlags , IgvmPageDataType , PAGE_SIZE_4K } ;
11
+ use igvm_defs:: { IgvmPageDataFlags , IgvmPageDataType , IgvmPlatformType , PAGE_SIZE_4K } ;
12
+ use sha2:: { Digest , Sha256 } ;
12
13
use zerocopy:: AsBytes ;
13
14
14
15
use crate :: page_info:: PageInfo ;
@@ -123,19 +124,35 @@ impl std::fmt::Display for SnpPageType {
123
124
}
124
125
}
125
126
127
+ #[ derive( Debug ) ]
128
+ struct IgvmMeasureContext {
129
+ digest_snp : [ u8 ; 48 ] ,
130
+ digest_es : Sha256 ,
131
+ }
132
+
133
+ impl Default for IgvmMeasureContext {
134
+ fn default ( ) -> Self {
135
+ Self {
136
+ digest_snp : [ 0u8 ; 48 ] ,
137
+ digest_es : Sha256 :: default ( ) ,
138
+ }
139
+ }
140
+ }
141
+
126
142
#[ derive( Debug ) ]
127
143
pub struct IgvmMeasure {
128
144
show_progress : bool ,
129
145
check_kvm : bool ,
130
146
native_zero : bool ,
131
- digest : [ u8 ; 48 ] ,
147
+ digest : Vec < u8 > ,
132
148
last_page_type : SnpPageType ,
133
149
last_gpa : u64 ,
134
150
last_next_gpa : u64 ,
135
151
last_len : u64 ,
136
152
compatibility_mask : u32 ,
137
153
vmsa_count : u32 ,
138
154
id_block_ld : Option < [ u8 ; 48 ] > ,
155
+ platform : IgvmPlatformType ,
139
156
}
140
157
141
158
const PAGE_SIZE_2M : u64 = 2 * 1024 * 1024 ;
@@ -146,39 +163,45 @@ impl IgvmMeasure {
146
163
check_kvm : bool ,
147
164
native_zero : bool ,
148
165
compatibility_mask : u32 ,
166
+ platform : IgvmPlatformType ,
149
167
igvm : & IgvmFile ,
150
168
) -> Result < Self , Box < dyn Error > > {
151
169
let mut result = Self {
152
170
show_progress,
153
171
check_kvm,
154
172
native_zero,
155
- digest : [ 0u8 ; 48 ] ,
173
+ digest : vec ! [ ] ,
156
174
last_page_type : SnpPageType :: None ,
157
175
last_gpa : 0 ,
158
176
last_next_gpa : 0 ,
159
177
last_len : 0 ,
160
178
compatibility_mask,
161
179
vmsa_count : 0 ,
162
180
id_block_ld : None ,
181
+ platform,
163
182
} ;
164
183
result. do_measure ( igvm) ?;
165
184
Ok ( result)
166
185
}
167
186
168
187
pub fn check_id_block ( & self ) -> Result < ( ) , IgvmMeasureError > {
169
188
if let Some ( expected_ld) = self . id_block_ld {
170
- if expected_ld != self . digest {
189
+ let mut ld = [ 0u8 ; 48 ] ;
190
+ ld. copy_from_slice ( self . digest ( ) ) ;
191
+ if expected_ld != ld {
171
192
return Err ( IgvmMeasureError :: IDBlockMismatch ( expected_ld) ) ;
172
193
}
173
194
}
174
195
Ok ( ( ) )
175
196
}
176
197
177
- pub fn digest ( & self ) -> [ u8 ; 48 ] {
178
- self . digest
198
+ pub fn digest ( & self ) -> & Vec < u8 > {
199
+ & self . digest
179
200
}
180
201
181
202
fn do_measure ( & mut self , igvm : & IgvmFile ) -> Result < ( ) , Box < dyn Error > > {
203
+ let mut ctx = IgvmMeasureContext :: default ( ) ;
204
+
182
205
for directive in igvm. directives ( ) {
183
206
match directive {
184
207
IgvmDirectiveHeader :: PageData {
@@ -189,7 +212,7 @@ impl IgvmMeasure {
189
212
data,
190
213
} => {
191
214
if ( * compatibility_mask & self . compatibility_mask ) != 0 {
192
- self . measure_page ( * gpa, flags, * data_type, data) ?;
215
+ self . measure_page ( & mut ctx , * gpa, flags, * data_type, data) ?;
193
216
}
194
217
}
195
218
IgvmDirectiveHeader :: ParameterInsert ( param) => {
@@ -198,6 +221,7 @@ impl IgvmMeasure {
198
221
return Err ( IgvmMeasureError :: InvalidVmsaOrder . into ( ) ) ;
199
222
}
200
223
self . measure_page (
224
+ & mut ctx,
201
225
param. gpa ,
202
226
& IgvmPageDataFlags :: new ( ) . with_unmeasured ( true ) ,
203
227
IgvmPageDataType :: NORMAL ,
@@ -211,7 +235,7 @@ impl IgvmMeasure {
211
235
vp_index : _vp_index,
212
236
vmsa,
213
237
} => {
214
- self . measure_vmsa ( * gpa, * compatibility_mask, vmsa) ?;
238
+ self . measure_vmsa ( & mut ctx , * gpa, * compatibility_mask, vmsa) ?;
215
239
}
216
240
IgvmDirectiveHeader :: SnpIdBlock {
217
241
compatibility_mask,
@@ -226,6 +250,12 @@ impl IgvmMeasure {
226
250
}
227
251
}
228
252
self . log_page ( SnpPageType :: None , 0 , 0 ) ;
253
+
254
+ if ( self . platform == IgvmPlatformType :: SEV_ES ) || ( self . platform == IgvmPlatformType :: SEV ) {
255
+ self . digest = ctx. digest_es . finalize_reset ( ) . to_vec ( ) ;
256
+ } else {
257
+ self . digest = ctx. digest_snp . to_vec ( ) ;
258
+ }
229
259
Ok ( ( ) )
230
260
}
231
261
@@ -251,6 +281,7 @@ impl IgvmMeasure {
251
281
252
282
fn measure_page (
253
283
& mut self ,
284
+ ctx : & mut IgvmMeasureContext ,
254
285
gpa : u64 ,
255
286
flags : & IgvmPageDataFlags ,
256
287
data_type : IgvmPageDataType ,
@@ -265,11 +296,12 @@ impl IgvmMeasure {
265
296
266
297
if data. is_empty ( ) {
267
298
for page_offset in ( 0 ..page_len) . step_by ( PAGE_SIZE_4K as usize ) {
268
- self . measure_page_4k ( gpa + page_offset, flags, data_type, & vec ! [ ] ) ;
299
+ self . measure_page_4k ( ctx , gpa + page_offset, flags, data_type, & vec ! [ ] ) ;
269
300
}
270
301
} else {
271
302
for ( index, page_data) in data. chunks ( PAGE_SIZE_4K as usize ) . enumerate ( ) {
272
303
self . measure_page_4k (
304
+ ctx,
273
305
gpa + index as u64 * PAGE_SIZE_4K ,
274
306
flags,
275
307
data_type,
@@ -282,49 +314,55 @@ impl IgvmMeasure {
282
314
283
315
fn measure_page_4k (
284
316
& mut self ,
317
+ ctx : & mut IgvmMeasureContext ,
285
318
gpa : u64 ,
286
319
flags : & IgvmPageDataFlags ,
287
320
data_type : IgvmPageDataType ,
288
321
data : & Vec < u8 > ,
289
322
) {
290
- let page_info = match data_type {
291
- IgvmPageDataType :: NORMAL => {
292
- if flags. unmeasured ( ) {
293
- self . log_page ( SnpPageType :: Unmeasured , gpa, PAGE_SIZE_4K ) ;
294
- Some ( PageInfo :: new_unmeasured_page ( self . digest , gpa) )
295
- } else if data. is_empty ( ) {
296
- if self . native_zero {
297
- self . log_page ( SnpPageType :: Zero , gpa, PAGE_SIZE_4K ) ;
298
- Some ( PageInfo :: new_zero_page ( self . digest , gpa) )
323
+ if self . platform == IgvmPlatformType :: SEV_SNP {
324
+ let page_info = match data_type {
325
+ IgvmPageDataType :: NORMAL => {
326
+ if flags. unmeasured ( ) {
327
+ self . log_page ( SnpPageType :: Unmeasured , gpa, PAGE_SIZE_4K ) ;
328
+ Some ( PageInfo :: new_unmeasured_page ( ctx. digest_snp , gpa) )
329
+ } else if data. is_empty ( ) {
330
+ if self . native_zero {
331
+ self . log_page ( SnpPageType :: Zero , gpa, PAGE_SIZE_4K ) ;
332
+ Some ( PageInfo :: new_zero_page ( ctx. digest_snp , gpa) )
333
+ } else {
334
+ self . log_page ( SnpPageType :: Normal , gpa, PAGE_SIZE_4K ) ;
335
+ Some ( PageInfo :: new_normal_page (
336
+ ctx. digest_snp ,
337
+ gpa,
338
+ & vec ! [ 0u8 ; PAGE_SIZE_4K as usize ] ,
339
+ ) )
340
+ }
299
341
} else {
300
- self . log_page ( SnpPageType :: Normal , gpa, PAGE_SIZE_4K ) ;
301
- Some ( PageInfo :: new_normal_page (
302
- self . digest ,
303
- gpa,
304
- & vec ! [ 0u8 ; PAGE_SIZE_4K as usize ] ,
305
- ) )
342
+ self . log_page ( SnpPageType :: Normal , gpa, data. len ( ) as u64 ) ;
343
+ Some ( PageInfo :: new_normal_page ( ctx. digest_snp , gpa, data) )
306
344
}
307
- } else {
308
- self . log_page ( SnpPageType :: Normal , gpa, data. len ( ) as u64 ) ;
309
- Some ( PageInfo :: new_normal_page ( self . digest , gpa, data) )
310
345
}
346
+ IgvmPageDataType :: SECRETS => {
347
+ self . log_page ( SnpPageType :: Secrets , gpa, PAGE_SIZE_4K ) ;
348
+ Some ( PageInfo :: new_secrets_page ( ctx. digest_snp , gpa) )
349
+ }
350
+ IgvmPageDataType :: CPUID_DATA => {
351
+ self . log_page ( SnpPageType :: CpuId , gpa, PAGE_SIZE_4K ) ;
352
+ Some ( PageInfo :: new_cpuid_page ( ctx. digest_snp , gpa) )
353
+ }
354
+ IgvmPageDataType :: CPUID_XF => {
355
+ self . log_page ( SnpPageType :: CpuId , gpa, PAGE_SIZE_4K ) ;
356
+ Some ( PageInfo :: new_cpuid_page ( ctx. digest_snp , gpa) )
357
+ }
358
+ _ => None ,
359
+ } ;
360
+ if let Some ( page_info) = page_info {
361
+ ctx. digest_snp = page_info. update_hash ( ) ;
311
362
}
312
- IgvmPageDataType :: SECRETS => {
313
- self . log_page ( SnpPageType :: Secrets , gpa, PAGE_SIZE_4K ) ;
314
- Some ( PageInfo :: new_secrets_page ( self . digest , gpa) )
315
- }
316
- IgvmPageDataType :: CPUID_DATA => {
317
- self . log_page ( SnpPageType :: CpuId , gpa, PAGE_SIZE_4K ) ;
318
- Some ( PageInfo :: new_cpuid_page ( self . digest , gpa) )
319
- }
320
- IgvmPageDataType :: CPUID_XF => {
321
- self . log_page ( SnpPageType :: CpuId , gpa, PAGE_SIZE_4K ) ;
322
- Some ( PageInfo :: new_cpuid_page ( self . digest , gpa) )
323
- }
324
- _ => None ,
325
- } ;
326
- if let Some ( page_info) = page_info {
327
- self . digest = page_info. update_hash ( ) ;
363
+ } else {
364
+ self . log_page ( SnpPageType :: Normal , gpa, PAGE_SIZE_4K ) ;
365
+ ctx. digest_es . update ( data) ;
328
366
}
329
367
}
330
368
@@ -348,6 +386,7 @@ impl IgvmMeasure {
348
386
349
387
fn measure_vmsa (
350
388
& mut self ,
389
+ ctx : & mut IgvmMeasureContext ,
351
390
gpa : u64 ,
352
391
_compatibility_mask : u32 ,
353
392
vmsa : & SevVmsa ,
@@ -357,8 +396,12 @@ impl IgvmMeasure {
357
396
let mut vmsa_page = vmsa. as_bytes ( ) . to_vec ( ) ;
358
397
vmsa_page. resize ( PAGE_SIZE_4K as usize , 0 ) ;
359
398
self . log_page ( SnpPageType :: Vmsa , gpa, PAGE_SIZE_4K ) ;
360
- let page_info = PageInfo :: new_vmsa_page ( self . digest , gpa, & vmsa_page) ;
361
- self . digest = page_info. update_hash ( ) ;
399
+ if self . platform == IgvmPlatformType :: SEV_SNP {
400
+ let page_info = PageInfo :: new_vmsa_page ( ctx. digest_snp , gpa, & vmsa_page) ;
401
+ ctx. digest_snp = page_info. update_hash ( ) ;
402
+ } else {
403
+ ctx. digest_es . update ( vmsa_page. as_bytes ( ) ) ;
404
+ }
362
405
self . vmsa_count += 1 ;
363
406
364
407
Ok ( ( ) )
0 commit comments