1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright(c) 2023 Intel Corporation. All rights reserved. */ 3 4 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 5 6 #include <linux/tsm.h> 7 #include <linux/err.h> 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> 14 15 static struct tsm_provider { 16 const struct tsm_ops *ops; 17 const struct config_item_type *type; 18 void *data; 19 } provider; 20 static DECLARE_RWSEM(tsm_rwsem); 21 22 /** 23 * DOC: Trusted Security Module (TSM) Attestation Report Interface 24 * 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 33 * often as needed. 34 * 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 38 * 'auxblob'. 39 */ 40 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; 46 }; 47 48 enum tsm_data_select { 49 TSM_REPORT, 50 TSM_CERTS, 51 }; 52 53 static struct tsm_report *to_tsm_report(struct config_item *cfg) 54 { 55 struct tsm_report_state *state = 56 container_of(cfg, struct tsm_report_state, cfg); 57 58 return &state->report; 59 } 60 61 static struct tsm_report_state *to_state(struct tsm_report *report) 62 { 63 return container_of(report, struct tsm_report_state, report); 64 } 65 66 static int try_advance_write_generation(struct tsm_report *report) 67 { 68 struct tsm_report_state *state = to_state(report); 69 70 lockdep_assert_held_write(&tsm_rwsem); 71 72 /* 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. 77 */ 78 if (state->write_generation == state->read_generation - 1) 79 return -EBUSY; 80 state->write_generation++; 81 return 0; 82 } 83 84 static ssize_t tsm_report_privlevel_store(struct config_item *cfg, 85 const char *buf, size_t len) 86 { 87 struct tsm_report *report = to_tsm_report(cfg); 88 unsigned int val; 89 int rc; 90 91 rc = kstrtouint(buf, 0, &val); 92 if (rc) 93 return rc; 94 95 /* 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 99 * than 0. 100 */ 101 if (provider.ops->privlevel_floor > val || val > TSM_PRIVLEVEL_MAX) 102 return -EINVAL; 103 104 guard(rwsem_write)(&tsm_rwsem); 105 rc = try_advance_write_generation(report); 106 if (rc) 107 return rc; 108 report->desc.privlevel = val; 109 110 return len; 111 } 112 CONFIGFS_ATTR_WO(tsm_report_, privlevel); 113 114 static ssize_t tsm_report_privlevel_floor_show(struct config_item *cfg, 115 char *buf) 116 { 117 guard(rwsem_read)(&tsm_rwsem); 118 return sysfs_emit(buf, "%u\n", provider.ops->privlevel_floor); 119 } 120 CONFIGFS_ATTR_RO(tsm_report_, privlevel_floor); 121 122 static ssize_t tsm_report_inblob_write(struct config_item *cfg, 123 const void *buf, size_t count) 124 { 125 struct tsm_report *report = to_tsm_report(cfg); 126 int rc; 127 128 guard(rwsem_write)(&tsm_rwsem); 129 rc = try_advance_write_generation(report); 130 if (rc) 131 return rc; 132 133 report->desc.inblob_len = count; 134 memcpy(report->desc.inblob, buf, count); 135 return count; 136 } 137 CONFIGFS_BIN_ATTR_WO(tsm_report_, inblob, NULL, TSM_INBLOB_MAX); 138 139 static ssize_t tsm_report_generation_show(struct config_item *cfg, char *buf) 140 { 141 struct tsm_report *report = to_tsm_report(cfg); 142 struct tsm_report_state *state = to_state(report); 143 144 guard(rwsem_read)(&tsm_rwsem); 145 return sysfs_emit(buf, "%lu\n", state->write_generation); 146 } 147 CONFIGFS_ATTR_RO(tsm_report_, generation); 148 149 static ssize_t tsm_report_provider_show(struct config_item *cfg, char *buf) 150 { 151 guard(rwsem_read)(&tsm_rwsem); 152 return sysfs_emit(buf, "%s\n", provider.ops->name); 153 } 154 CONFIGFS_ATTR_RO(tsm_report_, provider); 155 156 static ssize_t __read_report(struct tsm_report *report, void *buf, size_t count, 157 enum tsm_data_select select) 158 { 159 loff_t offset = 0; 160 ssize_t len; 161 u8 *out; 162 163 if (select == TSM_REPORT) { 164 out = report->outblob; 165 len = report->outblob_len; 166 } else { 167 out = report->auxblob; 168 len = report->auxblob_len; 169 } 170 171 /* 172 * Recall that a NULL @buf is configfs requesting the size of 173 * the buffer. 174 */ 175 if (!buf) 176 return len; 177 return memory_read_from_buffer(buf, count, &offset, out, len); 178 } 179 180 static ssize_t read_cached_report(struct tsm_report *report, void *buf, 181 size_t count, enum tsm_data_select select) 182 { 183 struct tsm_report_state *state = to_state(report); 184 185 guard(rwsem_read)(&tsm_rwsem); 186 if (!report->desc.inblob_len) 187 return -EINVAL; 188 189 /* 190 * A given TSM backend always fills in ->outblob regardless of 191 * whether the report includes an auxblob or not. 192 */ 193 if (!report->outblob || 194 state->read_generation != state->write_generation) 195 return -EWOULDBLOCK; 196 197 return __read_report(report, buf, count, select); 198 } 199 200 static ssize_t tsm_report_read(struct tsm_report *report, void *buf, 201 size_t count, enum tsm_data_select select) 202 { 203 struct tsm_report_state *state = to_state(report); 204 const struct tsm_ops *ops; 205 ssize_t rc; 206 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) 210 return rc; 211 212 /* slow path, report may need to be regenerated... */ 213 guard(rwsem_write)(&tsm_rwsem); 214 ops = provider.ops; 215 if (!ops) 216 return -ENOTTY; 217 if (!report->desc.inblob_len) 218 return -EINVAL; 219 220 /* did another thread already generate this report? */ 221 if (report->outblob && 222 state->read_generation == state->write_generation) 223 goto out; 224 225 kvfree(report->outblob); 226 kvfree(report->auxblob); 227 report->outblob = NULL; 228 report->auxblob = NULL; 229 rc = ops->report_new(report, provider.data); 230 if (rc < 0) 231 return rc; 232 state->read_generation = state->write_generation; 233 out: 234 return __read_report(report, buf, count, select); 235 } 236 237 static ssize_t tsm_report_outblob_read(struct config_item *cfg, void *buf, 238 size_t count) 239 { 240 struct tsm_report *report = to_tsm_report(cfg); 241 242 return tsm_report_read(report, buf, count, TSM_REPORT); 243 } 244 CONFIGFS_BIN_ATTR_RO(tsm_report_, outblob, NULL, TSM_OUTBLOB_MAX); 245 246 static ssize_t tsm_report_auxblob_read(struct config_item *cfg, void *buf, 247 size_t count) 248 { 249 struct tsm_report *report = to_tsm_report(cfg); 250 251 return tsm_report_read(report, buf, count, TSM_CERTS); 252 } 253 CONFIGFS_BIN_ATTR_RO(tsm_report_, auxblob, NULL, TSM_OUTBLOB_MAX); 254 255 #define TSM_DEFAULT_ATTRS() \ 256 &tsm_report_attr_generation, \ 257 &tsm_report_attr_provider 258 259 static struct configfs_attribute *tsm_report_attrs[] = { 260 TSM_DEFAULT_ATTRS(), 261 NULL, 262 }; 263 264 static struct configfs_attribute *tsm_report_extra_attrs[] = { 265 TSM_DEFAULT_ATTRS(), 266 &tsm_report_attr_privlevel, 267 &tsm_report_attr_privlevel_floor, 268 NULL, 269 }; 270 271 #define TSM_DEFAULT_BIN_ATTRS() \ 272 &tsm_report_attr_inblob, \ 273 &tsm_report_attr_outblob 274 275 static struct configfs_bin_attribute *tsm_report_bin_attrs[] = { 276 TSM_DEFAULT_BIN_ATTRS(), 277 NULL, 278 }; 279 280 static struct configfs_bin_attribute *tsm_report_bin_extra_attrs[] = { 281 TSM_DEFAULT_BIN_ATTRS(), 282 &tsm_report_attr_auxblob, 283 NULL, 284 }; 285 286 static void tsm_report_item_release(struct config_item *cfg) 287 { 288 struct tsm_report *report = to_tsm_report(cfg); 289 struct tsm_report_state *state = to_state(report); 290 291 kvfree(report->auxblob); 292 kvfree(report->outblob); 293 kfree(state); 294 } 295 296 static struct configfs_item_operations tsm_report_item_ops = { 297 .release = tsm_report_item_release, 298 }; 299 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, 305 }; 306 EXPORT_SYMBOL_GPL(tsm_report_default_type); 307 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, 313 }; 314 EXPORT_SYMBOL_GPL(tsm_report_extra_type); 315 316 static struct config_item *tsm_report_make_item(struct config_group *group, 317 const char *name) 318 { 319 struct tsm_report_state *state; 320 321 guard(rwsem_read)(&tsm_rwsem); 322 if (!provider.ops) 323 return ERR_PTR(-ENXIO); 324 325 state = kzalloc(sizeof(*state), GFP_KERNEL); 326 if (!state) 327 return ERR_PTR(-ENOMEM); 328 329 config_item_init_type_name(&state->cfg, name, provider.type); 330 return &state->cfg; 331 } 332 333 static struct configfs_group_operations tsm_report_group_ops = { 334 .make_item = tsm_report_make_item, 335 }; 336 337 static const struct config_item_type tsm_reports_type = { 338 .ct_owner = THIS_MODULE, 339 .ct_group_ops = &tsm_report_group_ops, 340 }; 341 342 static const struct config_item_type tsm_root_group_type = { 343 .ct_owner = THIS_MODULE, 344 }; 345 346 static struct configfs_subsystem tsm_configfs = { 347 .su_group = { 348 .cg_item = { 349 .ci_namebuf = "tsm", 350 .ci_type = &tsm_root_group_type, 351 }, 352 }, 353 .su_mutex = __MUTEX_INITIALIZER(tsm_configfs.su_mutex), 354 }; 355 356 int tsm_register(const struct tsm_ops *ops, void *priv, 357 const struct config_item_type *type) 358 { 359 const struct tsm_ops *conflict; 360 361 if (!type) 362 type = &tsm_report_default_type; 363 if (!(type == &tsm_report_default_type || type == &tsm_report_extra_type)) 364 return -EINVAL; 365 366 guard(rwsem_write)(&tsm_rwsem); 367 conflict = provider.ops; 368 if (conflict) { 369 pr_err("\"%s\" ops already registered\n", conflict->name); 370 return -EBUSY; 371 } 372 373 provider.ops = ops; 374 provider.data = priv; 375 provider.type = type; 376 return 0; 377 } 378 EXPORT_SYMBOL_GPL(tsm_register); 379 380 int tsm_unregister(const struct tsm_ops *ops) 381 { 382 guard(rwsem_write)(&tsm_rwsem); 383 if (ops != provider.ops) 384 return -EBUSY; 385 provider.ops = NULL; 386 provider.data = NULL; 387 provider.type = NULL; 388 return 0; 389 } 390 EXPORT_SYMBOL_GPL(tsm_unregister); 391 392 static struct config_group *tsm_report_group; 393 394 static int __init tsm_init(void) 395 { 396 struct config_group *root = &tsm_configfs.su_group; 397 struct config_group *tsm; 398 int rc; 399 400 config_group_init(root); 401 rc = configfs_register_subsystem(&tsm_configfs); 402 if (rc) 403 return rc; 404 405 tsm = configfs_register_default_group(root, "report", 406 &tsm_reports_type); 407 if (IS_ERR(tsm)) { 408 configfs_unregister_subsystem(&tsm_configfs); 409 return PTR_ERR(tsm); 410 } 411 tsm_report_group = tsm; 412 413 return 0; 414 } 415 module_init(tsm_init); 416 417 static void __exit tsm_exit(void) 418 { 419 configfs_unregister_default_group(tsm_report_group); 420 configfs_unregister_subsystem(&tsm_configfs); 421 } 422 module_exit(tsm_exit); 423 424 MODULE_LICENSE("GPL"); 425 MODULE_DESCRIPTION("Provide Trusted Security Module attestation reports via configfs"); 426