5
5
* Copyright (C) 2022 Intel Corporation
6
6
*/
7
7
8
+ #define pr_fmt (fmt ) KBUILD_MODNAME ": " fmt
9
+
8
10
#include <linux/kernel.h>
9
11
#include <linux/miscdevice.h>
10
12
#include <linux/mm.h>
15
17
#include <linux/set_memory.h>
16
18
#include <linux/io.h>
17
19
#include <linux/delay.h>
20
+ #include <linux/sockptr.h>
18
21
#include <linux/tsm.h>
19
- #include <linux/sizes .h>
22
+ #include <linux/tsm-mr .h>
20
23
21
24
#include <uapi/linux/tdx-guest.h>
22
25
23
26
#include <asm/cpu_device_id.h>
24
27
#include <asm/tdx.h>
25
28
29
+ /* TDREPORT buffer */
30
+ static u8 * tdx_report_buf ;
31
+
32
+ /* Lock to serialize TDG.MR.REPORT and TDG.MR.RTMR.EXTEND TDCALLs */
33
+ static DEFINE_MUTEX (mr_lock );
34
+
35
+ /* TDREPORT fields */
36
+ enum {
37
+ TDREPORT_reportdata = 128 ,
38
+ TDREPORT_tee_tcb_info = 256 ,
39
+ TDREPORT_tdinfo = TDREPORT_tee_tcb_info + 256 ,
40
+ TDREPORT_attributes = TDREPORT_tdinfo ,
41
+ TDREPORT_xfam = TDREPORT_attributes + sizeof (u64 ),
42
+ TDREPORT_mrtd = TDREPORT_xfam + sizeof (u64 ),
43
+ TDREPORT_mrconfigid = TDREPORT_mrtd + SHA384_DIGEST_SIZE ,
44
+ TDREPORT_mrowner = TDREPORT_mrconfigid + SHA384_DIGEST_SIZE ,
45
+ TDREPORT_mrownerconfig = TDREPORT_mrowner + SHA384_DIGEST_SIZE ,
46
+ TDREPORT_rtmr0 = TDREPORT_mrownerconfig + SHA384_DIGEST_SIZE ,
47
+ TDREPORT_rtmr1 = TDREPORT_rtmr0 + SHA384_DIGEST_SIZE ,
48
+ TDREPORT_rtmr2 = TDREPORT_rtmr1 + SHA384_DIGEST_SIZE ,
49
+ TDREPORT_rtmr3 = TDREPORT_rtmr2 + SHA384_DIGEST_SIZE ,
50
+ TDREPORT_servtd_hash = TDREPORT_rtmr3 + SHA384_DIGEST_SIZE ,
51
+ };
52
+
53
+ static int tdx_do_report (sockptr_t data , sockptr_t tdreport )
54
+ {
55
+ scoped_cond_guard (mutex_intr , return - EINTR , & mr_lock ) {
56
+ u8 * reportdata = tdx_report_buf + TDREPORT_reportdata ;
57
+ int ret ;
58
+
59
+ if (!sockptr_is_null (data ) &&
60
+ copy_from_sockptr (reportdata , data , TDX_REPORTDATA_LEN ))
61
+ return - EFAULT ;
62
+
63
+ ret = tdx_mcall_get_report0 (reportdata , tdx_report_buf );
64
+ if (WARN_ONCE (ret , "tdx_mcall_get_report0() failed: %d" , ret ))
65
+ return ret ;
66
+
67
+ if (!sockptr_is_null (tdreport ) &&
68
+ copy_to_sockptr (tdreport , tdx_report_buf , TDX_REPORT_LEN ))
69
+ return - EFAULT ;
70
+ }
71
+ return 0 ;
72
+ }
73
+
74
+ static int tdx_do_extend (u8 mr_ind , const u8 * data )
75
+ {
76
+ scoped_cond_guard (mutex_intr , return - EINTR , & mr_lock ) {
77
+ /*
78
+ * TDX requires @extend_buf to be 64-byte aligned.
79
+ * It's safe to use REPORTDATA buffer for that purpose because
80
+ * tdx_mr_report/extend_lock() are mutually exclusive.
81
+ */
82
+ u8 * extend_buf = tdx_report_buf + TDREPORT_reportdata ;
83
+ int ret ;
84
+
85
+ memcpy (extend_buf , data , SHA384_DIGEST_SIZE );
86
+
87
+ ret = tdx_mcall_extend_rtmr (mr_ind , extend_buf );
88
+ if (WARN_ONCE (ret , "tdx_mcall_extend_rtmr(%u) failed: %d" , mr_ind , ret ))
89
+ return ret ;
90
+ }
91
+ return 0 ;
92
+ }
93
+
94
+ #define TDX_MR_ (r ) .mr_value = (void *)TDREPORT_##r, TSM_MR_(r, SHA384)
95
+ static struct tsm_measurement_register tdx_mrs [] = {
96
+ { TDX_MR_ (rtmr0 ) | TSM_MR_F_RTMR },
97
+ { TDX_MR_ (rtmr1 ) | TSM_MR_F_RTMR },
98
+ { TDX_MR_ (rtmr2 ) | TSM_MR_F_RTMR },
99
+ { TDX_MR_ (rtmr3 ) | TSM_MR_F_RTMR },
100
+ { TDX_MR_ (mrtd ) },
101
+ { TDX_MR_ (mrconfigid ) | TSM_MR_F_NOHASH },
102
+ { TDX_MR_ (mrowner ) | TSM_MR_F_NOHASH },
103
+ { TDX_MR_ (mrownerconfig ) | TSM_MR_F_NOHASH },
104
+ };
105
+ #undef TDX_MR_
106
+
107
+ static int tdx_mr_refresh (const struct tsm_measurements * tm )
108
+ {
109
+ return tdx_do_report (KERNEL_SOCKPTR (NULL ), KERNEL_SOCKPTR (NULL ));
110
+ }
111
+
112
+ static int tdx_mr_extend (const struct tsm_measurements * tm ,
113
+ const struct tsm_measurement_register * mr ,
114
+ const u8 * data )
115
+ {
116
+ return tdx_do_extend (mr - tm -> mrs , data );
117
+ }
118
+
119
+ static struct tsm_measurements tdx_measurements = {
120
+ .mrs = tdx_mrs ,
121
+ .nr_mrs = ARRAY_SIZE (tdx_mrs ),
122
+ .refresh = tdx_mr_refresh ,
123
+ .write = tdx_mr_extend ,
124
+ };
125
+
126
+ static const struct attribute_group * tdx_mr_init (void )
127
+ {
128
+ const struct attribute_group * g ;
129
+ int rc ;
130
+
131
+ u8 * buf __free (kfree ) = kzalloc (TDX_REPORT_LEN , GFP_KERNEL );
132
+ if (!buf )
133
+ return ERR_PTR (- ENOMEM );
134
+
135
+ tdx_report_buf = buf ;
136
+ rc = tdx_mr_refresh (& tdx_measurements );
137
+ if (rc )
138
+ return ERR_PTR (rc );
139
+
140
+ /*
141
+ * @mr_value was initialized with the offset only, while the base
142
+ * address is being added here.
143
+ */
144
+ for (size_t i = 0 ; i < ARRAY_SIZE (tdx_mrs ); ++ i )
145
+ * (long * )& tdx_mrs [i ].mr_value += (long )buf ;
146
+
147
+ g = tsm_mr_create_attribute_group (& tdx_measurements );
148
+ if (!IS_ERR (g ))
149
+ tdx_report_buf = no_free_ptr (buf );
150
+
151
+ return g ;
152
+ }
153
+
154
+ static void tdx_mr_deinit (const struct attribute_group * mr_grp )
155
+ {
156
+ tsm_mr_free_attribute_group (mr_grp );
157
+ kfree (tdx_report_buf );
158
+ }
159
+
26
160
/*
27
161
* Intel's SGX QE implementation generally uses Quote size less
28
162
* than 8K (2K Quote data + ~5K of certificate blob).
@@ -285,10 +419,16 @@ static const struct file_operations tdx_guest_fops = {
285
419
.unlocked_ioctl = tdx_guest_ioctl ,
286
420
};
287
421
422
+ static const struct attribute_group * tdx_attr_groups [] = {
423
+ NULL , /* measurements */
424
+ NULL
425
+ };
426
+
288
427
static struct miscdevice tdx_misc_dev = {
289
428
.name = KBUILD_MODNAME ,
290
429
.minor = MISC_DYNAMIC_MINOR ,
291
430
.fops = & tdx_guest_fops ,
431
+ .groups = tdx_attr_groups ,
292
432
};
293
433
294
434
static const struct x86_cpu_id tdx_guest_ids [] = {
@@ -311,9 +451,13 @@ static int __init tdx_guest_init(void)
311
451
if (!x86_match_cpu (tdx_guest_ids ))
312
452
return - ENODEV ;
313
453
454
+ tdx_attr_groups [0 ] = tdx_mr_init ();
455
+ if (IS_ERR (tdx_attr_groups [0 ]))
456
+ return PTR_ERR (tdx_attr_groups [0 ]);
457
+
314
458
ret = misc_register (& tdx_misc_dev );
315
459
if (ret )
316
- return ret ;
460
+ goto deinit_mr ;
317
461
318
462
quote_data = alloc_quote_buf ();
319
463
if (!quote_data ) {
@@ -332,6 +476,8 @@ static int __init tdx_guest_init(void)
332
476
free_quote_buf (quote_data );
333
477
free_misc :
334
478
misc_deregister (& tdx_misc_dev );
479
+ deinit_mr :
480
+ tdx_mr_deinit (tdx_attr_groups [0 ]);
335
481
336
482
return ret ;
337
483
}
@@ -342,6 +488,7 @@ static void __exit tdx_guest_exit(void)
342
488
tsm_unregister (& tdx_tsm_ops );
343
489
free_quote_buf (quote_data );
344
490
misc_deregister (& tdx_misc_dev );
491
+ tdx_mr_deinit (tdx_attr_groups [0 ]);
345
492
}
346
493
module_exit (tdx_guest_exit );
347
494
0 commit comments