1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2023 Intel Corporation. All rights reserved. */
4 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8 #include <linux/slab.h>
9 #include <linux/rwsem.h>
10 #include <linux/string.h>
11 #include <linux/module.h>
12 #include <linux/cleanup.h>
13 #include <linux/configfs.h>
15 static struct tsm_provider
{
16 const struct tsm_ops
*ops
;
19 static DECLARE_RWSEM(tsm_rwsem
);
22 * DOC: Trusted Security Module (TSM) Attestation Report Interface
24 * The TSM report interface is a common provider of blobs that facilitate
25 * attestation of a TVM (confidential computing guest) by an attestation
26 * service. A TSM report combines a user-defined blob (likely a public-key with
27 * a nonce for a key-exchange protocol) with a signed attestation report. That
28 * combined blob is then used to obtain secrets provided by an agent that can
29 * validate the attestation report. The expectation is that this interface is
30 * invoked infrequently, however configfs allows for multiple agents to
31 * own their own report generation instances to generate reports as
34 * The attestation report format is TSM provider specific, when / if a standard
35 * materializes that can be published instead of the vendor layout. Until then
36 * the 'provider' attribute indicates the format of 'outblob', and optionally
37 * 'auxblob' and 'manifestblob'.
40 struct tsm_report_state
{
41 struct tsm_report report
;
42 unsigned long write_generation
;
43 unsigned long read_generation
;
44 struct config_item cfg
;
47 enum tsm_data_select
{
53 static struct tsm_report
*to_tsm_report(struct config_item
*cfg
)
55 struct tsm_report_state
*state
=
56 container_of(cfg
, struct tsm_report_state
, cfg
);
58 return &state
->report
;
61 static struct tsm_report_state
*to_state(struct tsm_report
*report
)
63 return container_of(report
, struct tsm_report_state
, report
);
66 static int try_advance_write_generation(struct tsm_report
*report
)
68 struct tsm_report_state
*state
= to_state(report
);
70 lockdep_assert_held_write(&tsm_rwsem
);
73 * Malicious or broken userspace has written enough times for
74 * read_generation == write_generation by modular arithmetic without an
75 * interim read. Stop accepting updates until the current report
76 * configuration is read.
78 if (state
->write_generation
== state
->read_generation
- 1)
80 state
->write_generation
++;
84 static ssize_t
tsm_report_privlevel_store(struct config_item
*cfg
,
85 const char *buf
, size_t len
)
87 struct tsm_report
*report
= to_tsm_report(cfg
);
91 rc
= kstrtouint(buf
, 0, &val
);
96 * The valid privilege levels that a TSM might accept, if it accepts a
97 * privilege level setting at all, are a max of TSM_PRIVLEVEL_MAX (see
98 * SEV-SNP GHCB) and a minimum of a TSM selected floor value no less
101 if (provider
.ops
->privlevel_floor
> val
|| val
> TSM_PRIVLEVEL_MAX
)
104 guard(rwsem_write
)(&tsm_rwsem
);
105 rc
= try_advance_write_generation(report
);
108 report
->desc
.privlevel
= val
;
112 CONFIGFS_ATTR_WO(tsm_report_
, privlevel
);
114 static ssize_t
tsm_report_privlevel_floor_show(struct config_item
*cfg
,
117 guard(rwsem_read
)(&tsm_rwsem
);
118 return sysfs_emit(buf
, "%u\n", provider
.ops
->privlevel_floor
);
120 CONFIGFS_ATTR_RO(tsm_report_
, privlevel_floor
);
122 static ssize_t
tsm_report_service_provider_store(struct config_item
*cfg
,
123 const char *buf
, size_t len
)
125 struct tsm_report
*report
= to_tsm_report(cfg
);
130 guard(rwsem_write
)(&tsm_rwsem
);
131 rc
= try_advance_write_generation(report
);
135 sp_len
= (buf
[len
- 1] != '\n') ? len
: len
- 1;
137 sp
= kstrndup(buf
, sp_len
, GFP_KERNEL
);
140 kfree(report
->desc
.service_provider
);
142 report
->desc
.service_provider
= sp
;
146 CONFIGFS_ATTR_WO(tsm_report_
, service_provider
);
148 static ssize_t
tsm_report_service_guid_store(struct config_item
*cfg
,
149 const char *buf
, size_t len
)
151 struct tsm_report
*report
= to_tsm_report(cfg
);
154 guard(rwsem_write
)(&tsm_rwsem
);
155 rc
= try_advance_write_generation(report
);
159 report
->desc
.service_guid
= guid_null
;
161 rc
= guid_parse(buf
, &report
->desc
.service_guid
);
167 CONFIGFS_ATTR_WO(tsm_report_
, service_guid
);
169 static ssize_t
tsm_report_service_manifest_version_store(struct config_item
*cfg
,
170 const char *buf
, size_t len
)
172 struct tsm_report
*report
= to_tsm_report(cfg
);
176 rc
= kstrtouint(buf
, 0, &val
);
180 guard(rwsem_write
)(&tsm_rwsem
);
181 rc
= try_advance_write_generation(report
);
184 report
->desc
.service_manifest_version
= val
;
188 CONFIGFS_ATTR_WO(tsm_report_
, service_manifest_version
);
190 static ssize_t
tsm_report_inblob_write(struct config_item
*cfg
,
191 const void *buf
, size_t count
)
193 struct tsm_report
*report
= to_tsm_report(cfg
);
196 guard(rwsem_write
)(&tsm_rwsem
);
197 rc
= try_advance_write_generation(report
);
201 report
->desc
.inblob_len
= count
;
202 memcpy(report
->desc
.inblob
, buf
, count
);
205 CONFIGFS_BIN_ATTR_WO(tsm_report_
, inblob
, NULL
, TSM_INBLOB_MAX
);
207 static ssize_t
tsm_report_generation_show(struct config_item
*cfg
, char *buf
)
209 struct tsm_report
*report
= to_tsm_report(cfg
);
210 struct tsm_report_state
*state
= to_state(report
);
212 guard(rwsem_read
)(&tsm_rwsem
);
213 return sysfs_emit(buf
, "%lu\n", state
->write_generation
);
215 CONFIGFS_ATTR_RO(tsm_report_
, generation
);
217 static ssize_t
tsm_report_provider_show(struct config_item
*cfg
, char *buf
)
219 guard(rwsem_read
)(&tsm_rwsem
);
220 return sysfs_emit(buf
, "%s\n", provider
.ops
->name
);
222 CONFIGFS_ATTR_RO(tsm_report_
, provider
);
224 static ssize_t
__read_report(struct tsm_report
*report
, void *buf
, size_t count
,
225 enum tsm_data_select select
)
231 if (select
== TSM_REPORT
) {
232 out
= report
->outblob
;
233 len
= report
->outblob_len
;
234 } else if (select
== TSM_MANIFEST
) {
235 out
= report
->manifestblob
;
236 len
= report
->manifestblob_len
;
238 out
= report
->auxblob
;
239 len
= report
->auxblob_len
;
243 * Recall that a NULL @buf is configfs requesting the size of
248 return memory_read_from_buffer(buf
, count
, &offset
, out
, len
);
251 static ssize_t
read_cached_report(struct tsm_report
*report
, void *buf
,
252 size_t count
, enum tsm_data_select select
)
254 struct tsm_report_state
*state
= to_state(report
);
256 guard(rwsem_read
)(&tsm_rwsem
);
257 if (!report
->desc
.inblob_len
)
261 * A given TSM backend always fills in ->outblob regardless of
262 * whether the report includes an auxblob/manifestblob or not.
264 if (!report
->outblob
||
265 state
->read_generation
!= state
->write_generation
)
268 return __read_report(report
, buf
, count
, select
);
271 static ssize_t
tsm_report_read(struct tsm_report
*report
, void *buf
,
272 size_t count
, enum tsm_data_select select
)
274 struct tsm_report_state
*state
= to_state(report
);
275 const struct tsm_ops
*ops
;
278 /* try to read from the existing report if present and valid... */
279 rc
= read_cached_report(report
, buf
, count
, select
);
280 if (rc
>= 0 || rc
!= -EWOULDBLOCK
)
283 /* slow path, report may need to be regenerated... */
284 guard(rwsem_write
)(&tsm_rwsem
);
288 if (!report
->desc
.inblob_len
)
291 /* did another thread already generate this report? */
292 if (report
->outblob
&&
293 state
->read_generation
== state
->write_generation
)
296 kvfree(report
->outblob
);
297 kvfree(report
->auxblob
);
298 kvfree(report
->manifestblob
);
299 report
->outblob
= NULL
;
300 report
->auxblob
= NULL
;
301 report
->manifestblob
= NULL
;
302 rc
= ops
->report_new(report
, provider
.data
);
305 state
->read_generation
= state
->write_generation
;
307 return __read_report(report
, buf
, count
, select
);
310 static ssize_t
tsm_report_outblob_read(struct config_item
*cfg
, void *buf
,
313 struct tsm_report
*report
= to_tsm_report(cfg
);
315 return tsm_report_read(report
, buf
, count
, TSM_REPORT
);
317 CONFIGFS_BIN_ATTR_RO(tsm_report_
, outblob
, NULL
, TSM_OUTBLOB_MAX
);
319 static ssize_t
tsm_report_auxblob_read(struct config_item
*cfg
, void *buf
,
322 struct tsm_report
*report
= to_tsm_report(cfg
);
324 return tsm_report_read(report
, buf
, count
, TSM_CERTS
);
326 CONFIGFS_BIN_ATTR_RO(tsm_report_
, auxblob
, NULL
, TSM_OUTBLOB_MAX
);
328 static ssize_t
tsm_report_manifestblob_read(struct config_item
*cfg
, void *buf
,
331 struct tsm_report
*report
= to_tsm_report(cfg
);
333 return tsm_report_read(report
, buf
, count
, TSM_MANIFEST
);
335 CONFIGFS_BIN_ATTR_RO(tsm_report_
, manifestblob
, NULL
, TSM_OUTBLOB_MAX
);
337 static struct configfs_attribute
*tsm_report_attrs
[] = {
338 [TSM_REPORT_GENERATION
] = &tsm_report_attr_generation
,
339 [TSM_REPORT_PROVIDER
] = &tsm_report_attr_provider
,
340 [TSM_REPORT_PRIVLEVEL
] = &tsm_report_attr_privlevel
,
341 [TSM_REPORT_PRIVLEVEL_FLOOR
] = &tsm_report_attr_privlevel_floor
,
342 [TSM_REPORT_SERVICE_PROVIDER
] = &tsm_report_attr_service_provider
,
343 [TSM_REPORT_SERVICE_GUID
] = &tsm_report_attr_service_guid
,
344 [TSM_REPORT_SERVICE_MANIFEST_VER
] = &tsm_report_attr_service_manifest_version
,
348 static struct configfs_bin_attribute
*tsm_report_bin_attrs
[] = {
349 [TSM_REPORT_INBLOB
] = &tsm_report_attr_inblob
,
350 [TSM_REPORT_OUTBLOB
] = &tsm_report_attr_outblob
,
351 [TSM_REPORT_AUXBLOB
] = &tsm_report_attr_auxblob
,
352 [TSM_REPORT_MANIFESTBLOB
] = &tsm_report_attr_manifestblob
,
356 static void tsm_report_item_release(struct config_item
*cfg
)
358 struct tsm_report
*report
= to_tsm_report(cfg
);
359 struct tsm_report_state
*state
= to_state(report
);
361 kvfree(report
->manifestblob
);
362 kvfree(report
->auxblob
);
363 kvfree(report
->outblob
);
364 kfree(report
->desc
.service_provider
);
368 static struct configfs_item_operations tsm_report_item_ops
= {
369 .release
= tsm_report_item_release
,
372 static bool tsm_report_is_visible(struct config_item
*item
,
373 struct configfs_attribute
*attr
, int n
)
375 guard(rwsem_read
)(&tsm_rwsem
);
379 if (!provider
.ops
->report_attr_visible
)
382 return provider
.ops
->report_attr_visible(n
);
385 static bool tsm_report_is_bin_visible(struct config_item
*item
,
386 struct configfs_bin_attribute
*attr
, int n
)
388 guard(rwsem_read
)(&tsm_rwsem
);
392 if (!provider
.ops
->report_bin_attr_visible
)
395 return provider
.ops
->report_bin_attr_visible(n
);
398 static struct configfs_group_operations tsm_report_attr_group_ops
= {
399 .is_visible
= tsm_report_is_visible
,
400 .is_bin_visible
= tsm_report_is_bin_visible
,
403 static const struct config_item_type tsm_report_type
= {
404 .ct_owner
= THIS_MODULE
,
405 .ct_bin_attrs
= tsm_report_bin_attrs
,
406 .ct_attrs
= tsm_report_attrs
,
407 .ct_item_ops
= &tsm_report_item_ops
,
408 .ct_group_ops
= &tsm_report_attr_group_ops
,
411 static struct config_item
*tsm_report_make_item(struct config_group
*group
,
414 struct tsm_report_state
*state
;
416 guard(rwsem_read
)(&tsm_rwsem
);
418 return ERR_PTR(-ENXIO
);
420 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
422 return ERR_PTR(-ENOMEM
);
424 config_item_init_type_name(&state
->cfg
, name
, &tsm_report_type
);
428 static struct configfs_group_operations tsm_report_group_ops
= {
429 .make_item
= tsm_report_make_item
,
432 static const struct config_item_type tsm_reports_type
= {
433 .ct_owner
= THIS_MODULE
,
434 .ct_group_ops
= &tsm_report_group_ops
,
437 static const struct config_item_type tsm_root_group_type
= {
438 .ct_owner
= THIS_MODULE
,
441 static struct configfs_subsystem tsm_configfs
= {
445 .ci_type
= &tsm_root_group_type
,
448 .su_mutex
= __MUTEX_INITIALIZER(tsm_configfs
.su_mutex
),
451 int tsm_register(const struct tsm_ops
*ops
, void *priv
)
453 const struct tsm_ops
*conflict
;
455 guard(rwsem_write
)(&tsm_rwsem
);
456 conflict
= provider
.ops
;
458 pr_err("\"%s\" ops already registered\n", conflict
->name
);
463 provider
.data
= priv
;
466 EXPORT_SYMBOL_GPL(tsm_register
);
468 int tsm_unregister(const struct tsm_ops
*ops
)
470 guard(rwsem_write
)(&tsm_rwsem
);
471 if (ops
!= provider
.ops
)
474 provider
.data
= NULL
;
477 EXPORT_SYMBOL_GPL(tsm_unregister
);
479 static struct config_group
*tsm_report_group
;
481 static int __init
tsm_init(void)
483 struct config_group
*root
= &tsm_configfs
.su_group
;
484 struct config_group
*tsm
;
487 config_group_init(root
);
488 rc
= configfs_register_subsystem(&tsm_configfs
);
492 tsm
= configfs_register_default_group(root
, "report",
495 configfs_unregister_subsystem(&tsm_configfs
);
498 tsm_report_group
= tsm
;
502 module_init(tsm_init
);
504 static void __exit
tsm_exit(void)
506 configfs_unregister_default_group(tsm_report_group
);
507 configfs_unregister_subsystem(&tsm_configfs
);
509 module_exit(tsm_exit
);
511 MODULE_LICENSE("GPL");
512 MODULE_DESCRIPTION("Provide Trusted Security Module attestation reports via configfs");