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;
17 const struct config_item_type *type;
20 static DECLARE_RWSEM(tsm_rwsem);
23 * DOC: Trusted Security Module (TSM) Attestation Report Interface
25 * The TSM report interface is a common provider of blobs that facilitate
26 * attestation of a TVM (confidential computing guest) by an attestation
27 * service. A TSM report combines a user-defined blob (likely a public-key with
28 * a nonce for a key-exchange protocol) with a signed attestation report. That
29 * combined blob is then used to obtain secrets provided by an agent that can
30 * validate the attestation report. The expectation is that this interface is
31 * invoked infrequently, however configfs allows for multiple agents to
32 * own their own report generation instances to generate reports as
35 * The attestation report format is TSM provider specific, when / if a standard
36 * materializes that can be published instead of the vendor layout. Until then
37 * the 'provider' attribute indicates the format of 'outblob', and optionally
41 struct tsm_report_state {
42 struct tsm_report report;
43 unsigned long write_generation;
44 unsigned long read_generation;
45 struct config_item cfg;
48 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_inblob_write(struct config_item *cfg,
123 const void *buf, size_t count)
125 struct tsm_report *report = to_tsm_report(cfg);
128 guard(rwsem_write)(&tsm_rwsem);
129 rc = try_advance_write_generation(report);
133 report->desc.inblob_len = count;
134 memcpy(report->desc.inblob, buf, count);
137 CONFIGFS_BIN_ATTR_WO(tsm_report_, inblob, NULL, TSM_INBLOB_MAX);
139 static ssize_t tsm_report_generation_show(struct config_item *cfg, char *buf)
141 struct tsm_report *report = to_tsm_report(cfg);
142 struct tsm_report_state *state = to_state(report);
144 guard(rwsem_read)(&tsm_rwsem);
145 return sysfs_emit(buf, "%lu\n", state->write_generation);
147 CONFIGFS_ATTR_RO(tsm_report_, generation);
149 static ssize_t tsm_report_provider_show(struct config_item *cfg, char *buf)
151 guard(rwsem_read)(&tsm_rwsem);
152 return sysfs_emit(buf, "%s\n", provider.ops->name);
154 CONFIGFS_ATTR_RO(tsm_report_, provider);
156 static ssize_t __read_report(struct tsm_report *report, void *buf, size_t count,
157 enum tsm_data_select select)
163 if (select == TSM_REPORT) {
164 out = report->outblob;
165 len = report->outblob_len;
167 out = report->auxblob;
168 len = report->auxblob_len;
172 * Recall that a NULL @buf is configfs requesting the size of
177 return memory_read_from_buffer(buf, count, &offset, out, len);
180 static ssize_t read_cached_report(struct tsm_report *report, void *buf,
181 size_t count, enum tsm_data_select select)
183 struct tsm_report_state *state = to_state(report);
185 guard(rwsem_read)(&tsm_rwsem);
186 if (!report->desc.inblob_len)
190 * A given TSM backend always fills in ->outblob regardless of
191 * whether the report includes an auxblob or not.
193 if (!report->outblob ||
194 state->read_generation != state->write_generation)
197 return __read_report(report, buf, count, select);
200 static ssize_t tsm_report_read(struct tsm_report *report, void *buf,
201 size_t count, enum tsm_data_select select)
203 struct tsm_report_state *state = to_state(report);
204 const struct tsm_ops *ops;
207 /* try to read from the existing report if present and valid... */
208 rc = read_cached_report(report, buf, count, select);
209 if (rc >= 0 || rc != -EWOULDBLOCK)
212 /* slow path, report may need to be regenerated... */
213 guard(rwsem_write)(&tsm_rwsem);
217 if (!report->desc.inblob_len)
220 /* did another thread already generate this report? */
221 if (report->outblob &&
222 state->read_generation == state->write_generation)
225 kvfree(report->outblob);
226 kvfree(report->auxblob);
227 report->outblob = NULL;
228 report->auxblob = NULL;
229 rc = ops->report_new(report, provider.data);
232 state->read_generation = state->write_generation;
234 return __read_report(report, buf, count, select);
237 static ssize_t tsm_report_outblob_read(struct config_item *cfg, void *buf,
240 struct tsm_report *report = to_tsm_report(cfg);
242 return tsm_report_read(report, buf, count, TSM_REPORT);
244 CONFIGFS_BIN_ATTR_RO(tsm_report_, outblob, NULL, TSM_OUTBLOB_MAX);
246 static ssize_t tsm_report_auxblob_read(struct config_item *cfg, void *buf,
249 struct tsm_report *report = to_tsm_report(cfg);
251 return tsm_report_read(report, buf, count, TSM_CERTS);
253 CONFIGFS_BIN_ATTR_RO(tsm_report_, auxblob, NULL, TSM_OUTBLOB_MAX);
255 #define TSM_DEFAULT_ATTRS() \
256 &tsm_report_attr_generation, \
257 &tsm_report_attr_provider
259 static struct configfs_attribute *tsm_report_attrs[] = {
264 static struct configfs_attribute *tsm_report_extra_attrs[] = {
266 &tsm_report_attr_privlevel,
267 &tsm_report_attr_privlevel_floor,
271 #define TSM_DEFAULT_BIN_ATTRS() \
272 &tsm_report_attr_inblob, \
273 &tsm_report_attr_outblob
275 static struct configfs_bin_attribute *tsm_report_bin_attrs[] = {
276 TSM_DEFAULT_BIN_ATTRS(),
280 static struct configfs_bin_attribute *tsm_report_bin_extra_attrs[] = {
281 TSM_DEFAULT_BIN_ATTRS(),
282 &tsm_report_attr_auxblob,
286 static void tsm_report_item_release(struct config_item *cfg)
288 struct tsm_report *report = to_tsm_report(cfg);
289 struct tsm_report_state *state = to_state(report);
291 kvfree(report->auxblob);
292 kvfree(report->outblob);
296 static struct configfs_item_operations tsm_report_item_ops = {
297 .release = tsm_report_item_release,
300 const struct config_item_type tsm_report_default_type = {
301 .ct_owner = THIS_MODULE,
302 .ct_bin_attrs = tsm_report_bin_attrs,
303 .ct_attrs = tsm_report_attrs,
304 .ct_item_ops = &tsm_report_item_ops,
306 EXPORT_SYMBOL_GPL(tsm_report_default_type);
308 const struct config_item_type tsm_report_extra_type = {
309 .ct_owner = THIS_MODULE,
310 .ct_bin_attrs = tsm_report_bin_extra_attrs,
311 .ct_attrs = tsm_report_extra_attrs,
312 .ct_item_ops = &tsm_report_item_ops,
314 EXPORT_SYMBOL_GPL(tsm_report_extra_type);
316 static struct config_item *tsm_report_make_item(struct config_group *group,
319 struct tsm_report_state *state;
321 guard(rwsem_read)(&tsm_rwsem);
323 return ERR_PTR(-ENXIO);
325 state = kzalloc(sizeof(*state), GFP_KERNEL);
327 return ERR_PTR(-ENOMEM);
329 config_item_init_type_name(&state->cfg, name, provider.type);
333 static struct configfs_group_operations tsm_report_group_ops = {
334 .make_item = tsm_report_make_item,
337 static const struct config_item_type tsm_reports_type = {
338 .ct_owner = THIS_MODULE,
339 .ct_group_ops = &tsm_report_group_ops,
342 static const struct config_item_type tsm_root_group_type = {
343 .ct_owner = THIS_MODULE,
346 static struct configfs_subsystem tsm_configfs = {
350 .ci_type = &tsm_root_group_type,
353 .su_mutex = __MUTEX_INITIALIZER(tsm_configfs.su_mutex),
356 int tsm_register(const struct tsm_ops *ops, void *priv,
357 const struct config_item_type *type)
359 const struct tsm_ops *conflict;
362 type = &tsm_report_default_type;
363 if (!(type == &tsm_report_default_type || type == &tsm_report_extra_type))
366 guard(rwsem_write)(&tsm_rwsem);
367 conflict = provider.ops;
369 pr_err("\"%s\" ops already registered\n", conflict->name);
374 provider.data = priv;
375 provider.type = type;
378 EXPORT_SYMBOL_GPL(tsm_register);
380 int tsm_unregister(const struct tsm_ops *ops)
382 guard(rwsem_write)(&tsm_rwsem);
383 if (ops != provider.ops)
386 provider.data = NULL;
387 provider.type = NULL;
390 EXPORT_SYMBOL_GPL(tsm_unregister);
392 static struct config_group *tsm_report_group;
394 static int __init tsm_init(void)
396 struct config_group *root = &tsm_configfs.su_group;
397 struct config_group *tsm;
400 config_group_init(root);
401 rc = configfs_register_subsystem(&tsm_configfs);
405 tsm = configfs_register_default_group(root, "report",
408 configfs_unregister_subsystem(&tsm_configfs);
411 tsm_report_group = tsm;
415 module_init(tsm_init);
417 static void __exit tsm_exit(void)
419 configfs_unregister_default_group(tsm_report_group);
420 configfs_unregister_subsystem(&tsm_configfs);
422 module_exit(tsm_exit);
424 MODULE_LICENSE("GPL");
425 MODULE_DESCRIPTION("Provide Trusted Security Module attestation reports via configfs");