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 void *data; 18 } provider; 19 static DECLARE_RWSEM(tsm_rwsem); 20 21 /** 22 * DOC: Trusted Security Module (TSM) Attestation Report Interface 23 * 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 32 * often as needed. 33 * 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'. 38 */ 39 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; 45 }; 46 47 enum tsm_data_select { 48 TSM_REPORT, 49 TSM_CERTS, 50 TSM_MANIFEST, 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_service_provider_store(struct config_item *cfg, 123 const char *buf, size_t len) 124 { 125 struct tsm_report *report = to_tsm_report(cfg); 126 size_t sp_len; 127 char *sp; 128 int rc; 129 130 guard(rwsem_write)(&tsm_rwsem); 131 rc = try_advance_write_generation(report); 132 if (rc) 133 return rc; 134 135 sp_len = (buf[len - 1] != '\n') ? len : len - 1; 136 137 sp = kstrndup(buf, sp_len, GFP_KERNEL); 138 if (!sp) 139 return -ENOMEM; 140 kfree(report->desc.service_provider); 141 142 report->desc.service_provider = sp; 143 144 return len; 145 } 146 CONFIGFS_ATTR_WO(tsm_report_, service_provider); 147 148 static ssize_t tsm_report_service_guid_store(struct config_item *cfg, 149 const char *buf, size_t len) 150 { 151 struct tsm_report *report = to_tsm_report(cfg); 152 int rc; 153 154 guard(rwsem_write)(&tsm_rwsem); 155 rc = try_advance_write_generation(report); 156 if (rc) 157 return rc; 158 159 report->desc.service_guid = guid_null; 160 161 rc = guid_parse(buf, &report->desc.service_guid); 162 if (rc) 163 return rc; 164 165 return len; 166 } 167 CONFIGFS_ATTR_WO(tsm_report_, service_guid); 168 169 static ssize_t tsm_report_service_manifest_version_store(struct config_item *cfg, 170 const char *buf, size_t len) 171 { 172 struct tsm_report *report = to_tsm_report(cfg); 173 unsigned int val; 174 int rc; 175 176 rc = kstrtouint(buf, 0, &val); 177 if (rc) 178 return rc; 179 180 guard(rwsem_write)(&tsm_rwsem); 181 rc = try_advance_write_generation(report); 182 if (rc) 183 return rc; 184 report->desc.service_manifest_version = val; 185 186 return len; 187 } 188 CONFIGFS_ATTR_WO(tsm_report_, service_manifest_version); 189 190 static ssize_t tsm_report_inblob_write(struct config_item *cfg, 191 const void *buf, size_t count) 192 { 193 struct tsm_report *report = to_tsm_report(cfg); 194 int rc; 195 196 guard(rwsem_write)(&tsm_rwsem); 197 rc = try_advance_write_generation(report); 198 if (rc) 199 return rc; 200 201 report->desc.inblob_len = count; 202 memcpy(report->desc.inblob, buf, count); 203 return count; 204 } 205 CONFIGFS_BIN_ATTR_WO(tsm_report_, inblob, NULL, TSM_INBLOB_MAX); 206 207 static ssize_t tsm_report_generation_show(struct config_item *cfg, char *buf) 208 { 209 struct tsm_report *report = to_tsm_report(cfg); 210 struct tsm_report_state *state = to_state(report); 211 212 guard(rwsem_read)(&tsm_rwsem); 213 return sysfs_emit(buf, "%lu\n", state->write_generation); 214 } 215 CONFIGFS_ATTR_RO(tsm_report_, generation); 216 217 static ssize_t tsm_report_provider_show(struct config_item *cfg, char *buf) 218 { 219 guard(rwsem_read)(&tsm_rwsem); 220 return sysfs_emit(buf, "%s\n", provider.ops->name); 221 } 222 CONFIGFS_ATTR_RO(tsm_report_, provider); 223 224 static ssize_t __read_report(struct tsm_report *report, void *buf, size_t count, 225 enum tsm_data_select select) 226 { 227 loff_t offset = 0; 228 ssize_t len; 229 u8 *out; 230 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; 237 } else { 238 out = report->auxblob; 239 len = report->auxblob_len; 240 } 241 242 /* 243 * Recall that a NULL @buf is configfs requesting the size of 244 * the buffer. 245 */ 246 if (!buf) 247 return len; 248 return memory_read_from_buffer(buf, count, &offset, out, len); 249 } 250 251 static ssize_t read_cached_report(struct tsm_report *report, void *buf, 252 size_t count, enum tsm_data_select select) 253 { 254 struct tsm_report_state *state = to_state(report); 255 256 guard(rwsem_read)(&tsm_rwsem); 257 if (!report->desc.inblob_len) 258 return -EINVAL; 259 260 /* 261 * A given TSM backend always fills in ->outblob regardless of 262 * whether the report includes an auxblob/manifestblob or not. 263 */ 264 if (!report->outblob || 265 state->read_generation != state->write_generation) 266 return -EWOULDBLOCK; 267 268 return __read_report(report, buf, count, select); 269 } 270 271 static ssize_t tsm_report_read(struct tsm_report *report, void *buf, 272 size_t count, enum tsm_data_select select) 273 { 274 struct tsm_report_state *state = to_state(report); 275 const struct tsm_ops *ops; 276 ssize_t rc; 277 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) 281 return rc; 282 283 /* slow path, report may need to be regenerated... */ 284 guard(rwsem_write)(&tsm_rwsem); 285 ops = provider.ops; 286 if (!ops) 287 return -ENOTTY; 288 if (!report->desc.inblob_len) 289 return -EINVAL; 290 291 /* did another thread already generate this report? */ 292 if (report->outblob && 293 state->read_generation == state->write_generation) 294 goto out; 295 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); 303 if (rc < 0) 304 return rc; 305 state->read_generation = state->write_generation; 306 out: 307 return __read_report(report, buf, count, select); 308 } 309 310 static ssize_t tsm_report_outblob_read(struct config_item *cfg, void *buf, 311 size_t count) 312 { 313 struct tsm_report *report = to_tsm_report(cfg); 314 315 return tsm_report_read(report, buf, count, TSM_REPORT); 316 } 317 CONFIGFS_BIN_ATTR_RO(tsm_report_, outblob, NULL, TSM_OUTBLOB_MAX); 318 319 static ssize_t tsm_report_auxblob_read(struct config_item *cfg, void *buf, 320 size_t count) 321 { 322 struct tsm_report *report = to_tsm_report(cfg); 323 324 return tsm_report_read(report, buf, count, TSM_CERTS); 325 } 326 CONFIGFS_BIN_ATTR_RO(tsm_report_, auxblob, NULL, TSM_OUTBLOB_MAX); 327 328 static ssize_t tsm_report_manifestblob_read(struct config_item *cfg, void *buf, 329 size_t count) 330 { 331 struct tsm_report *report = to_tsm_report(cfg); 332 333 return tsm_report_read(report, buf, count, TSM_MANIFEST); 334 } 335 CONFIGFS_BIN_ATTR_RO(tsm_report_, manifestblob, NULL, TSM_OUTBLOB_MAX); 336 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, 345 NULL, 346 }; 347 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, 353 NULL, 354 }; 355 356 static void tsm_report_item_release(struct config_item *cfg) 357 { 358 struct tsm_report *report = to_tsm_report(cfg); 359 struct tsm_report_state *state = to_state(report); 360 361 kvfree(report->manifestblob); 362 kvfree(report->auxblob); 363 kvfree(report->outblob); 364 kfree(report->desc.service_provider); 365 kfree(state); 366 } 367 368 static struct configfs_item_operations tsm_report_item_ops = { 369 .release = tsm_report_item_release, 370 }; 371 372 static bool tsm_report_is_visible(struct config_item *item, 373 struct configfs_attribute *attr, int n) 374 { 375 guard(rwsem_read)(&tsm_rwsem); 376 if (!provider.ops) 377 return false; 378 379 if (!provider.ops->report_attr_visible) 380 return true; 381 382 return provider.ops->report_attr_visible(n); 383 } 384 385 static bool tsm_report_is_bin_visible(struct config_item *item, 386 struct configfs_bin_attribute *attr, int n) 387 { 388 guard(rwsem_read)(&tsm_rwsem); 389 if (!provider.ops) 390 return false; 391 392 if (!provider.ops->report_bin_attr_visible) 393 return true; 394 395 return provider.ops->report_bin_attr_visible(n); 396 } 397 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, 401 }; 402 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, 409 }; 410 411 static struct config_item *tsm_report_make_item(struct config_group *group, 412 const char *name) 413 { 414 struct tsm_report_state *state; 415 416 guard(rwsem_read)(&tsm_rwsem); 417 if (!provider.ops) 418 return ERR_PTR(-ENXIO); 419 420 state = kzalloc(sizeof(*state), GFP_KERNEL); 421 if (!state) 422 return ERR_PTR(-ENOMEM); 423 424 config_item_init_type_name(&state->cfg, name, &tsm_report_type); 425 return &state->cfg; 426 } 427 428 static struct configfs_group_operations tsm_report_group_ops = { 429 .make_item = tsm_report_make_item, 430 }; 431 432 static const struct config_item_type tsm_reports_type = { 433 .ct_owner = THIS_MODULE, 434 .ct_group_ops = &tsm_report_group_ops, 435 }; 436 437 static const struct config_item_type tsm_root_group_type = { 438 .ct_owner = THIS_MODULE, 439 }; 440 441 static struct configfs_subsystem tsm_configfs = { 442 .su_group = { 443 .cg_item = { 444 .ci_namebuf = "tsm", 445 .ci_type = &tsm_root_group_type, 446 }, 447 }, 448 .su_mutex = __MUTEX_INITIALIZER(tsm_configfs.su_mutex), 449 }; 450 451 int tsm_register(const struct tsm_ops *ops, void *priv) 452 { 453 const struct tsm_ops *conflict; 454 455 guard(rwsem_write)(&tsm_rwsem); 456 conflict = provider.ops; 457 if (conflict) { 458 pr_err("\"%s\" ops already registered\n", conflict->name); 459 return -EBUSY; 460 } 461 462 provider.ops = ops; 463 provider.data = priv; 464 return 0; 465 } 466 EXPORT_SYMBOL_GPL(tsm_register); 467 468 int tsm_unregister(const struct tsm_ops *ops) 469 { 470 guard(rwsem_write)(&tsm_rwsem); 471 if (ops != provider.ops) 472 return -EBUSY; 473 provider.ops = NULL; 474 provider.data = NULL; 475 return 0; 476 } 477 EXPORT_SYMBOL_GPL(tsm_unregister); 478 479 static struct config_group *tsm_report_group; 480 481 static int __init tsm_init(void) 482 { 483 struct config_group *root = &tsm_configfs.su_group; 484 struct config_group *tsm; 485 int rc; 486 487 config_group_init(root); 488 rc = configfs_register_subsystem(&tsm_configfs); 489 if (rc) 490 return rc; 491 492 tsm = configfs_register_default_group(root, "report", 493 &tsm_reports_type); 494 if (IS_ERR(tsm)) { 495 configfs_unregister_subsystem(&tsm_configfs); 496 return PTR_ERR(tsm); 497 } 498 tsm_report_group = tsm; 499 500 return 0; 501 } 502 module_init(tsm_init); 503 504 static void __exit tsm_exit(void) 505 { 506 configfs_unregister_default_group(tsm_report_group); 507 configfs_unregister_subsystem(&tsm_configfs); 508 } 509 module_exit(tsm_exit); 510 511 MODULE_LICENSE("GPL"); 512 MODULE_DESCRIPTION("Provide Trusted Security Module attestation reports via configfs"); 513