@@ -26,7 +26,7 @@ pub struct Evidence<'a> {
26
26
}
27
27
28
28
flags ! {
29
- pub enum Flags : u8 {
29
+ pub enum PolicyFlags : u8 {
30
30
/// Indicates if only one socket is permitted
31
31
SingleSocket = 1 << 4 ,
32
32
/// Indicates if debugging is permitted
@@ -38,6 +38,11 @@ flags! {
38
38
/// Indicates if SMT is permitted
39
39
SMT = 1 << 0 ,
40
40
}
41
+
42
+ pub enum PlatformInfoFlags : u8 {
43
+ TSME = 1 << 1 ,
44
+ SMT = 1 << 0 ,
45
+ }
41
46
}
42
47
43
48
#[ repr( C , packed) ]
@@ -48,17 +53,26 @@ pub struct Policy {
48
53
/// Minimum ABI major version required for the guest to run
49
54
pub abi_major : u8 ,
50
55
/// Bit fields indicating enabled features
51
- pub flags : FlagSet < Flags > ,
56
+ pub flags : FlagSet < PolicyFlags > ,
52
57
/// Reserved, must be zero
53
58
rsvd : [ u8 ; 5 ] ,
54
59
}
55
60
61
+ #[ repr( C , packed) ]
62
+ #[ derive( Copy , Clone , Debug ) ]
63
+ pub struct PlatformInfo {
64
+ /// Bit fields indicating enabled features
65
+ pub flags : FlagSet < PlatformInfoFlags > ,
66
+ /// Reserved
67
+ rsvd : [ u8 ; 7 ] ,
68
+ }
69
+
56
70
#[ repr( C , packed) ]
57
71
#[ derive( Copy , Clone , Debug ) ]
58
72
struct Body {
59
73
/// The version of the attestation report, currently 2
60
74
pub version : u32 ,
61
- /// Guest SVN
75
+ /// Guest Security Version Number ( SVN)
62
76
pub guest_svn : u32 ,
63
77
/// The guest policy
64
78
/// This indicates the required version of the firmware, and if debugging is enabled.
@@ -67,14 +81,14 @@ struct Body {
67
81
pub family_id : [ u8 ; 16 ] ,
68
82
/// The image ID provided at launch
69
83
pub image_id : [ u8 ; 16 ] ,
70
- /// The guest VMPL for the attestation report
84
+ /// The guest Virtual Machine Privilege Level ( VMPL) for the attestation report
71
85
pub vmpl : u32 ,
72
86
/// The signature algorithm used to sign this report
73
87
pub sig_algo : u32 ,
74
88
/// Current TCB
75
89
pub plat_version : u64 ,
76
90
/// Platform information
77
- pub plat_info : u64 ,
91
+ pub plat_info : PlatformInfo ,
78
92
/// Indicates (zero or one) that the digest of the author key is in `author_key_digest`
79
93
/// The other bits are reserved and must be zero.
80
94
pub author_key_en : u32 ,
@@ -100,8 +114,28 @@ struct Body {
100
114
rsvd2 : [ u8 ; 24 ] ,
101
115
/// The identifier unique to the chip, optionally masked and set to zero
102
116
pub chip_id : [ u8 ; 64 ] ,
117
+ /// Committed TCB
118
+ pub committed_tcb : u64 ,
119
+ /// The build number of the Current Version
120
+ pub current_build : u8 ,
121
+ /// The minor number of the Current Version
122
+ pub current_minor : u8 ,
123
+ /// The major number of the Current Version
124
+ pub current_major : u8 ,
125
+ /// Reserved, must be zero
126
+ rsvd3 : u8 ,
127
+ /// The build number of the Committed Version
128
+ pub committed_build : u8 ,
129
+ /// The minor number of the Committed Version
130
+ pub committed_minor : u8 ,
131
+ /// The major number of the Committed Version
132
+ pub committed_major : u8 ,
103
133
/// Reserved, must be zero
104
- rsvd3 : [ u8 ; 192 ] ,
134
+ rsvd4 : u8 ,
135
+ /// The Current TCB at the time the guest was launched or imported
136
+ pub launch_tcb : u64 ,
137
+ /// Reserved, must be zero
138
+ rsvd5 : [ u8 ; 168 ] ,
105
139
}
106
140
107
141
impl AsRef < [ u8 ; size_of :: < Self > ( ) ] > for Body {
@@ -254,22 +288,91 @@ impl ExtVerifier for Snp {
254
288
255
289
// TODO: additional field validations.
256
290
291
+ // Should only be version 2
257
292
if report. body . version != 2 {
258
293
return Err ( anyhow ! ( "snp report is an unknown version" ) ) ;
259
294
}
260
295
261
- if !report. body . policy . flags . contains ( Flags :: Reserved ) {
296
+ // Check policy
297
+ if !report. body . policy . flags . contains ( PolicyFlags :: Reserved ) {
262
298
return Err ( anyhow ! ( "snp guest policy mandatory reserved flag not set" ) ) ;
263
299
}
264
300
301
+ if report. body . policy . flags . contains ( PolicyFlags :: MigrateMA ) {
302
+ return Err ( anyhow ! ( "snp guest policy migration flag was set" ) ) ;
303
+ }
304
+
305
+ // Check reserved fields
306
+ if report. body . rsvd1 != 0 || report. body . rsvd3 != 0 || report. body . rsvd4 != 0 {
307
+ return Err ( anyhow ! ( "snp report reserved fields were set" ) ) ;
308
+ }
309
+
310
+ for value in report. body . rsvd2 {
311
+ if value != 0 {
312
+ return Err ( anyhow ! ( "snp report reserved fields were set" ) ) ;
313
+ }
314
+ }
315
+
316
+ for value in report. body . rsvd5 {
317
+ if value != 0 {
318
+ return Err ( anyhow ! ( "snp report reserved fields were set" ) ) ;
319
+ }
320
+ }
321
+
322
+ for value in report. body . policy . rsvd {
323
+ if value != 0 {
324
+ return Err ( anyhow ! ( "snp report policy reserved fields were set" ) ) ;
325
+ }
326
+ }
327
+
328
+ for value in report. body . plat_info . rsvd {
329
+ if value != 0 {
330
+ return Err ( anyhow ! ( "snp report platform_info reserved fields were set" ) ) ;
331
+ }
332
+ }
333
+
334
+ // Check fields not set by Enarx
335
+ for value in report. body . author_key_digest {
336
+ if value != 0 {
337
+ return Err ( anyhow ! ( "snp report author_key_digest field not set by Enarx" ) ) ;
338
+ }
339
+ }
340
+
341
+ for value in report. body . host_data {
342
+ if value != 0 {
343
+ return Err ( anyhow ! ( "snp report host_data field not set by Enarx" ) ) ;
344
+ }
345
+ }
346
+
347
+ for value in report. body . id_key_digest {
348
+ if value != 0 {
349
+ return Err ( anyhow ! ( "snp report id_key_digest field not set by Enarx" ) ) ;
350
+ }
351
+ }
352
+
353
+ if report. body . vmpl != 0 {
354
+ return Err ( anyhow ! ( "snp report vmpl field not set by Enarx" ) ) ;
355
+ }
356
+
357
+ if report. body . guest_svn != 0 {
358
+ return Err ( anyhow ! ( "snp report guest_svn field not set by Enarx" ) ) ;
359
+ }
360
+
361
+ // Check field set by Enarx
362
+ for value in report. body . report_id_ma {
363
+ if value != 255 {
364
+ return Err ( anyhow ! ( "snp report report_id_ma field not the value set by Enarx" ) ) ;
365
+ }
366
+ }
367
+
265
368
if !dbg {
266
369
// Validate that the certification request came from an SNP VM.
267
370
let hash = sha2:: Sha384 :: digest ( & cri. public_key . to_vec ( ) ?) ;
268
371
if hash. as_slice ( ) != & report. body . report_data [ ..hash. as_slice ( ) . len ( ) ] {
269
372
return Err ( anyhow ! ( "snp report.report_data is invalid" ) ) ;
270
373
}
271
374
272
- if report. body . policy . flags . contains ( Flags :: Debug ) {
375
+ if report. body . policy . flags . contains ( PolicyFlags :: Debug ) {
273
376
return Err ( anyhow ! ( "snp guest policy permits debugging" ) ) ;
274
377
}
275
378
}
0 commit comments